adds vsmul, widens functions parameters for sat_vector operations

This commit is contained in:
Eyck-Alexander Jentzsch 2025-02-18 21:45:16 +01:00
parent 75d96bf18d
commit e1911bc450

View File

@ -596,24 +596,20 @@ template <typename T> bool get_rounding_increment(T v, uint64_t d, int64_t vxrm)
case 0b10: // rdn: round-down (truncate)
return false;
case 0b11: // rod: round-to-odd (jam)
return (!(v & (1 << d)) && ((v & ((1 << d) - 1)) != 0));
return (!(v & (static_cast<T>(1) << d)) && ((v & ((static_cast<T>(1) << d) - 1)) != 0));
}
return false;
}
template <typename T> T roundoff_unsigned(T v, uint64_t d, int64_t vxrm) {
unsigned r = get_rounding_increment(v, d, vxrm);
return (v >> d) + r;
}
template <typename T> T roundoff_signed(T v, uint64_t d, int64_t vxrm) {
template <typename T> T roundoff(T v, uint64_t d, int64_t vxrm) {
unsigned r = get_rounding_increment(v, d, vxrm);
return (v >> d) + r;
}
template <typename dest_elem_t, typename src_elem_t = dest_elem_t>
std::function<bool(uint64_t, dest_elem_t&, src_elem_t, src_elem_t)> get_sat_funct(unsigned funct6, unsigned funct3) {
std::function<bool(uint64_t, vtype_t, dest_elem_t&, src_elem_t, src_elem_t)> get_sat_funct(unsigned funct6, unsigned funct3) {
if(funct3 == OPIVV || funct3 == OPIVX || funct3 == OPIVI)
switch(funct6) {
case 0b100000: // VSADDU
return [](uint64_t vxrm, dest_elem_t& vd, src_elem_t vs2, src_elem_t vs1) {
return [](uint64_t vxrm, vtype_t vtype, dest_elem_t& vd, src_elem_t vs2, src_elem_t vs1) {
auto res = static_cast<twice_t<src_elem_t>>(vs2) + static_cast<twice_t<src_elem_t>>(vs1);
if(res > std::numeric_limits<src_elem_t>::max()) {
vd = std::numeric_limits<src_elem_t>::max();
@ -624,7 +620,7 @@ std::function<bool(uint64_t, dest_elem_t&, src_elem_t, src_elem_t)> get_sat_func
}
};
case 0b100001: // VSADD
return [](uint64_t vxrm, dest_elem_t& vd, src_elem_t vs2, src_elem_t vs1) {
return [](uint64_t vxrm, vtype_t vtype, dest_elem_t& vd, src_elem_t vs2, src_elem_t vs1) {
auto res = static_cast<twice_t<std::make_signed_t<src_elem_t>>>(static_cast<std::make_signed_t<src_elem_t>>(vs2)) +
static_cast<twice_t<std::make_signed_t<src_elem_t>>>(static_cast<std::make_signed_t<src_elem_t>>(vs1));
if(res < std::numeric_limits<std::make_signed_t<src_elem_t>>::min()) {
@ -639,7 +635,7 @@ std::function<bool(uint64_t, dest_elem_t&, src_elem_t, src_elem_t)> get_sat_func
}
};
case 0b100010: // VSSUBU
return [](uint64_t vxrm, dest_elem_t& vd, src_elem_t vs2, src_elem_t vs1) {
return [](uint64_t vxrm, vtype_t vtype, dest_elem_t& vd, src_elem_t vs2, src_elem_t vs1) {
if(vs2 < vs1) {
vd = 0;
return 1;
@ -649,7 +645,7 @@ std::function<bool(uint64_t, dest_elem_t&, src_elem_t, src_elem_t)> get_sat_func
}
};
case 0b100011: // VSSUB
return [](uint64_t vxrm, dest_elem_t& vd, src_elem_t vs2, src_elem_t vs1) {
return [](uint64_t vxrm, vtype_t vtype, dest_elem_t& vd, src_elem_t vs2, src_elem_t vs1) {
auto res = static_cast<twice_t<std::make_signed_t<src_elem_t>>>(static_cast<std::make_signed_t<src_elem_t>>(vs2)) -
static_cast<twice_t<std::make_signed_t<src_elem_t>>>(static_cast<std::make_signed_t<src_elem_t>>(vs1));
if(res < std::numeric_limits<std::make_signed_t<src_elem_t>>::min()) {
@ -663,7 +659,22 @@ std::function<bool(uint64_t, dest_elem_t&, src_elem_t, src_elem_t)> get_sat_func
return 0;
}
};
// case 0b100111: // VSMUL
case 0b100111: // VSMUL
return [](uint64_t vxrm, vtype_t vtype, dest_elem_t& vd, src_elem_t vs2, src_elem_t vs1) {
auto big_val = static_cast<twice_t<std::make_signed_t<src_elem_t>>>(static_cast<std::make_signed_t<src_elem_t>>(vs2)) *
static_cast<twice_t<std::make_signed_t<src_elem_t>>>(static_cast<std::make_signed_t<src_elem_t>>(vs1));
auto res = roundoff(big_val, vtype.sew() - 1, vxrm);
if(res < std::numeric_limits<std::make_signed_t<src_elem_t>>::min()) {
vd = std::numeric_limits<std::make_signed_t<src_elem_t>>::min();
return 1;
} else if(res > std::numeric_limits<std::make_signed_t<src_elem_t>>::max()) {
vd = std::numeric_limits<std::make_signed_t<src_elem_t>>::max();
return 1;
} else {
vd = res;
return 0;
}
};
// case 0b101010: // VSSRL
// case 0b101011: // VSSRA
// case 0b101110: // VNCLIPU
@ -674,29 +685,29 @@ std::function<bool(uint64_t, dest_elem_t&, src_elem_t, src_elem_t)> get_sat_func
else if(funct3 == OPMVV || funct3 == OPMVX)
switch(funct6) {
case 0b001000: // VAADDU
return [](uint64_t vxrm, dest_elem_t& vd, src_elem_t vs2, src_elem_t vs1) {
return [](uint64_t vxrm, vtype_t vtype, dest_elem_t& vd, src_elem_t vs2, src_elem_t vs1) {
auto res = static_cast<twice_t<src_elem_t>>(vs2) + static_cast<twice_t<src_elem_t>>(vs1);
vd = roundoff_unsigned(res, 1, vxrm);
vd = roundoff(res, 1, vxrm);
return 0;
};
case 0b001001: // VAADD
return [](uint64_t vxrm, dest_elem_t& vd, src_elem_t vs2, src_elem_t vs1) {
return [](uint64_t vxrm, vtype_t vtype, dest_elem_t& vd, src_elem_t vs2, src_elem_t vs1) {
auto res = static_cast<twice_t<std::make_signed_t<src_elem_t>>>(static_cast<std::make_signed_t<src_elem_t>>(vs2)) +
static_cast<twice_t<std::make_signed_t<src_elem_t>>>(static_cast<std::make_signed_t<src_elem_t>>(vs1));
vd = roundoff_signed(res, 1, vxrm);
vd = roundoff(res, 1, vxrm);
return 0;
};
case 0b001010: // VASUBU
return [](uint64_t vxrm, dest_elem_t& vd, src_elem_t vs2, src_elem_t vs1) {
return [](uint64_t vxrm, vtype_t vtype, dest_elem_t& vd, src_elem_t vs2, src_elem_t vs1) {
auto res = static_cast<twice_t<src_elem_t>>(vs2) - static_cast<twice_t<src_elem_t>>(vs1);
vd = roundoff_unsigned(res, 1, vxrm);
vd = roundoff(res, 1, vxrm);
return 0;
};
case 0b001011: // VASUB
return [](uint64_t vxrm, dest_elem_t& vd, src_elem_t vs2, src_elem_t vs1) {
return [](uint64_t vxrm, vtype_t vtype, dest_elem_t& vd, src_elem_t vs2, src_elem_t vs1) {
auto res = static_cast<twice_t<std::make_signed_t<src_elem_t>>>(static_cast<std::make_signed_t<src_elem_t>>(vs2)) -
static_cast<twice_t<std::make_signed_t<src_elem_t>>>(static_cast<std::make_signed_t<src_elem_t>>(vs1));
vd = roundoff_signed(res, 1, vxrm);
vd = roundoff(res, 1, vxrm);
return 0;
};
default:
@ -720,7 +731,7 @@ bool sat_vector_vector_op(uint8_t* V, unsigned funct6, unsigned funct3, uint64_t
for(unsigned idx = vstart; idx < std::min(elem_count, vl); idx++) {
bool mask_active = vm ? 1 : mask_reg[idx];
if(mask_active) {
saturated |= fn(vxrm, vd_view[idx], vs2_view[idx], vs1_view[idx]);
saturated |= fn(vxrm, vtype, vd_view[idx], vs2_view[idx], vs1_view[idx]);
} else {
vd_view[idx] = vtype.vma() ? vd_view[idx] : vd_view[idx];
}
@ -747,7 +758,7 @@ bool sat_vector_imm_op(uint8_t* V, unsigned funct6, unsigned funct3, uint64_t vl
for(unsigned idx = vstart; idx < std::min(elem_count, vl); idx++) {
bool mask_active = vm ? 1 : mask_reg[idx];
if(mask_active) {
saturated |= fn(vxrm, vd_view[idx], vs2_view[idx], imm);
saturated |= fn(vxrm, vtype, vd_view[idx], vs2_view[idx], imm);
} else {
vd_view[idx] = vtype.vma() ? vd_view[idx] : vd_view[idx];
}