|
|
|
@ -945,11 +945,7 @@ template <> constexpr bool isPosZero<uint64_t>(uint64_t x) { return x == 0x00000
|
|
|
|
|
template <typename dest_elem_t, typename src_elem_t> dest_elem_t widen_float(src_elem_t val) {
|
|
|
|
|
throw new std::runtime_error("Trying to widen a weird 'float'");
|
|
|
|
|
};
|
|
|
|
|
template <> inline uint64_t widen_float<uint64_t, uint32_t>(uint32_t val) {
|
|
|
|
|
float32_t v1{val};
|
|
|
|
|
float64_t v2 = f32_to_f64(v1);
|
|
|
|
|
return v2.v;
|
|
|
|
|
}
|
|
|
|
|
template <> inline uint64_t widen_float<uint64_t, uint32_t>(uint32_t val) { return f32_to_f64(float32_t{val}).v; }
|
|
|
|
|
|
|
|
|
|
template <typename elem_size_t> elem_size_t fp_add(uint8_t, elem_size_t, elem_size_t);
|
|
|
|
|
template <> inline uint32_t fp_add<uint32_t>(uint8_t mode, uint32_t v2, uint32_t v1) { return fadd_s(v1, v2, mode); }
|
|
|
|
@ -1047,175 +1043,173 @@ template <> inline uint64_t fp_max<uint64_t>(uint64_t v2, uint64_t v1) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename dest_elem_t, typename src2_elem_t = dest_elem_t, typename src1_elem_t = dest_elem_t>
|
|
|
|
|
std::function<dest_elem_t(uint8_t, uint_fast8_t&, dest_elem_t, src2_elem_t, src1_elem_t)> get_fp_funct(unsigned funct6, unsigned funct3) {
|
|
|
|
|
std::function<dest_elem_t(uint8_t, uint8_t&, dest_elem_t, src2_elem_t, src1_elem_t)> get_fp_funct(unsigned funct6, unsigned funct3) {
|
|
|
|
|
if(funct3 == OPFVV || funct3 == OPFVF)
|
|
|
|
|
switch(funct6) {
|
|
|
|
|
case 0b000000: // VFADD
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
dest_elem_t val = fp_add<dest_elem_t>(rm, vs2, vs1);
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
case 0b000010: // VFSUB
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
dest_elem_t val = fp_sub<dest_elem_t>(rm, vs2, vs1);
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
case 0b000100: // VFMIN
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
return fp_min<dest_elem_t>(vs2, vs1);
|
|
|
|
|
};
|
|
|
|
|
case 0b000110: // VFMAX
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
return fp_max<dest_elem_t>(vs2, vs1);
|
|
|
|
|
};
|
|
|
|
|
case 0b100000: // VFDIV
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
dest_elem_t val = fp_div<src2_elem_t>(rm, vs2, vs1);
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
case 0b100001: // VFRDIV
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
dest_elem_t val = fp_div<src2_elem_t>(rm, vs1, vs2);
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
case 0b100100: // VFMUL
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
dest_elem_t val = fp_mul<dest_elem_t>(rm, vs2, vs1);
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
case 0b100111: // VFRSUB
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
dest_elem_t val = fp_sub<src2_elem_t>(rm, vs1, vs2);
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
case 0b101000: // VFMADD
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
dest_elem_t val = fp_madd<src2_elem_t>(rm, vs1, vd, vs2);
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
case 0b101001: // VFNMADD
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
dest_elem_t val = fp_nmadd<src2_elem_t>(rm, vs1, vd, vs2);
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
case 0b101010: // VFMSUB
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
dest_elem_t val = fp_msub<src2_elem_t>(rm, vs1, vd, vs2);
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
case 0b101011: // VFNMSUB
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
dest_elem_t val = fp_nmsub<src2_elem_t>(rm, vs1, vd, vs2);
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
case 0b101100: // VFMACC
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
dest_elem_t val = fp_madd<src2_elem_t>(rm, vs1, vs2, vd);
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
case 0b101101: // VFNMAC
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
dest_elem_t val = fp_nmadd<src2_elem_t>(rm, vs1, vs2, vd);
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
case 0b101110: // VFMSAC
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
dest_elem_t val = fp_msub<src2_elem_t>(rm, vs1, vs2, vd);
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
case 0b101111: // VFNMSAC
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
dest_elem_t val = fp_nmsub<src2_elem_t>(rm, vs1, vs2, vd);
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
case 0b110000: // VFWADD
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
dest_elem_t val = fp_add<dest_elem_t>(rm, widen_float<dest_elem_t>(vs2), widen_float<dest_elem_t>(vs1));
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
case 0b110010: // VFWSUB
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
dest_elem_t val = fp_sub<dest_elem_t>(rm, widen_float<dest_elem_t>(vs2), widen_float<dest_elem_t>(vs1));
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
case 0b110100: // VFWADD.W
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
dest_elem_t val = fp_add<dest_elem_t>(rm, vs2, widen_float<dest_elem_t>(vs1));
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
case 0b110110: // VFWSUB.W
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
dest_elem_t val = fp_sub<dest_elem_t>(rm, vs2, widen_float<dest_elem_t>(vs1));
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
case 0b111000: // VFWMUL
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
dest_elem_t val = fp_mul<dest_elem_t>(rm, widen_float<dest_elem_t>(vs2), vs1);
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
case 0b111100: // VFWMACC
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
dest_elem_t val = fp_madd<dest_elem_t>(rm, widen_float<dest_elem_t>(vs1), widen_float<dest_elem_t>(vs2), vd);
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
case 0b111101: // VFWNMACC
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
dest_elem_t val = fp_nmadd<dest_elem_t>(rm, widen_float<dest_elem_t>(vs1), widen_float<dest_elem_t>(vs2), vd);
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
case 0b111110: // VFWMSAC
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
dest_elem_t val = fp_msub<dest_elem_t>(rm, widen_float<dest_elem_t>(vs1), widen_float<dest_elem_t>(vs2), vd);
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
case 0b111111: // VFWNMSAC
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
dest_elem_t val = fp_nmsub<dest_elem_t>(rm, widen_float<dest_elem_t>(vs1), widen_float<dest_elem_t>(vs2), vd);
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
case 0b001000: // VFSGNJ
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
dest_elem_t mask = std::numeric_limits<dest_elem_t>::max() >> 1;
|
|
|
|
|
dest_elem_t sign_mask = std::numeric_limits<std::make_signed_t<dest_elem_t>>::min();
|
|
|
|
|
return (vs2 & mask) | (vs1 & sign_mask);
|
|
|
|
|
};
|
|
|
|
|
case 0b001001: // VFSGNJN
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
dest_elem_t mask = std::numeric_limits<dest_elem_t>::max() >> 1;
|
|
|
|
|
dest_elem_t sign_mask = std::numeric_limits<std::make_signed_t<dest_elem_t>>::min();
|
|
|
|
|
return (vs2 & mask) | (~vs1 & sign_mask);
|
|
|
|
|
};
|
|
|
|
|
case 0b001010: // VFSGNJX
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
|
|
|
|
dest_elem_t mask = std::numeric_limits<dest_elem_t>::max() >> 1;
|
|
|
|
|
dest_elem_t sign_mask = std::numeric_limits<std::make_signed_t<dest_elem_t>>::min();
|
|
|
|
|
return vs2 ^ (vs1 & sign_mask);
|
|
|
|
|
};
|
|
|
|
|
case 0b010111: // VFMERGE/VFMV
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
throw new std::runtime_error("Unknown funct6 in get_fp_funct");
|
|
|
|
|
}
|
|
|
|
@ -1231,7 +1225,7 @@ void fp_vector_vector_op(uint8_t* V, unsigned funct6, unsigned funct3, uint64_t
|
|
|
|
|
auto vs2_view = get_vreg<VLEN, src2_elem_t>(V, vs2, elem_count);
|
|
|
|
|
auto vd_view = get_vreg<VLEN, dest_elem_t>(V, vd, elem_count);
|
|
|
|
|
auto fn = get_fp_funct<dest_elem_t, src2_elem_t, src1_elem_t>(funct6, funct3);
|
|
|
|
|
uint_fast8_t accrued_flags = 0;
|
|
|
|
|
uint8_t accrued_flags = 0;
|
|
|
|
|
// elements w/ index smaller than vstart are in the prestart and get skipped
|
|
|
|
|
// body is from vstart to min(elem_count, vl)
|
|
|
|
|
for(unsigned idx = vstart; idx < std::min(elem_count, vl); idx++) {
|
|
|
|
@ -1259,7 +1253,7 @@ void fp_vector_imm_op(uint8_t* V, unsigned funct6, unsigned funct3, uint64_t vl,
|
|
|
|
|
auto vs2_view = get_vreg<VLEN, src2_elem_t>(V, vs2, elem_count);
|
|
|
|
|
auto vd_view = get_vreg<VLEN, dest_elem_t>(V, vd, elem_count);
|
|
|
|
|
auto fn = get_fp_funct<dest_elem_t, src2_elem_t, src1_elem_t>(funct6, funct3);
|
|
|
|
|
uint_fast8_t accrued_flags = 0;
|
|
|
|
|
uint8_t accrued_flags = 0;
|
|
|
|
|
// elements w/ index smaller than vstart are in the prestart and get skipped
|
|
|
|
|
// body is from vstart to min(elem_count, vl)
|
|
|
|
|
for(unsigned idx = vstart; idx < std::min(elem_count, vl); idx++) {
|
|
|
|
@ -1280,34 +1274,34 @@ void fp_vector_imm_op(uint8_t* V, unsigned funct6, unsigned funct3, uint64_t vl,
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
template <typename dest_elem_t, typename src_elem_t>
|
|
|
|
|
std::function<void(uint8_t, uint_fast8_t&, dest_elem_t&, src_elem_t)> get_fp_red_funct(unsigned funct6, unsigned funct3) {
|
|
|
|
|
std::function<void(uint8_t, uint8_t&, dest_elem_t&, src_elem_t)> get_fp_red_funct(unsigned funct6, unsigned funct3) {
|
|
|
|
|
if(funct3 == OPFVV || funct3 == OPFVF)
|
|
|
|
|
switch(funct6) {
|
|
|
|
|
case 0b000001: // VFREDUSUM
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, dest_elem_t& running_total, src_elem_t vs2) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, dest_elem_t& running_total, src_elem_t vs2) {
|
|
|
|
|
running_total = fp_add<dest_elem_t>(rm, running_total, vs2);
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
};
|
|
|
|
|
case 0b000011: // VFREDOSUM
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, dest_elem_t& running_total, src_elem_t vs2) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, dest_elem_t& running_total, src_elem_t vs2) {
|
|
|
|
|
running_total = fp_add<dest_elem_t>(rm, running_total, vs2);
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
};
|
|
|
|
|
case 0b000101: // VFREDMIN
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, dest_elem_t& running_total, src_elem_t vs2) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, dest_elem_t& running_total, src_elem_t vs2) {
|
|
|
|
|
running_total = fp_min<dest_elem_t>(running_total, vs2);
|
|
|
|
|
};
|
|
|
|
|
case 0b000111: // VFREDMAX
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, dest_elem_t& running_total, src_elem_t vs2) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, dest_elem_t& running_total, src_elem_t vs2) {
|
|
|
|
|
running_total = fp_max<dest_elem_t>(running_total, vs2);
|
|
|
|
|
};
|
|
|
|
|
case 0b110001: // VFWREDUSUM
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, dest_elem_t& running_total, src_elem_t vs2) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, dest_elem_t& running_total, src_elem_t vs2) {
|
|
|
|
|
running_total = fp_add<dest_elem_t>(rm, running_total, widen_float<dest_elem_t>(vs2));
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
};
|
|
|
|
|
case 0b110011: // VFWREDOSUM
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, dest_elem_t& running_total, src_elem_t vs2) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, dest_elem_t& running_total, src_elem_t vs2) {
|
|
|
|
|
running_total = fp_add<dest_elem_t>(rm, running_total, widen_float<dest_elem_t>(vs2));
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
};
|
|
|
|
@ -1329,7 +1323,7 @@ void fp_vector_red_op(uint8_t* V, unsigned funct6, unsigned funct3, uint64_t vl,
|
|
|
|
|
auto vd_view = get_vreg<VLEN, dest_elem_t>(V, vd, elem_count);
|
|
|
|
|
auto fn = get_fp_red_funct<dest_elem_t, src_elem_t>(funct6, funct3);
|
|
|
|
|
dest_elem_t& running_total = {vs1_elem};
|
|
|
|
|
uint_fast8_t accrued_flags = 0;
|
|
|
|
|
uint8_t accrued_flags = 0;
|
|
|
|
|
for(unsigned idx = vstart; idx < std::min(elem_count, vl); idx++) {
|
|
|
|
|
bool mask_active = vm ? 1 : mask_reg[idx];
|
|
|
|
|
if(mask_active) {
|
|
|
|
@ -1356,46 +1350,173 @@ template <> inline uint64_t fp_rec7<uint64_t>(uint8_t mode, uint64_t v2) { retur
|
|
|
|
|
template <typename elem_size_t> elem_size_t fp_fclass(elem_size_t);
|
|
|
|
|
template <> inline uint32_t fp_fclass<uint32_t>(uint32_t v2) { return fclass_s(v2); }
|
|
|
|
|
template <> inline uint64_t fp_fclass<uint64_t>(uint64_t v2) { return fclass_d(v2); }
|
|
|
|
|
template <typename dest_elem_size_t, typename src_elem_size_t> dest_elem_size_t fp_f_to_ui(uint8_t, src_elem_size_t);
|
|
|
|
|
template <> inline uint32_t fp_f_to_ui<uint32_t, uint32_t>(uint8_t rm, uint32_t v2) {
|
|
|
|
|
softfloat_exceptionFlags = 0;
|
|
|
|
|
return f32_to_ui32(float32_t{v2}, rm, true);
|
|
|
|
|
}
|
|
|
|
|
template <> inline uint64_t fp_f_to_ui<uint64_t, uint64_t>(uint8_t rm, uint64_t v2) {
|
|
|
|
|
softfloat_exceptionFlags = 0;
|
|
|
|
|
return f64_to_ui64(float64_t{v2}, rm, true);
|
|
|
|
|
}
|
|
|
|
|
template <> inline uint64_t fp_f_to_ui<uint64_t, uint32_t>(uint8_t rm, uint32_t v2) {
|
|
|
|
|
softfloat_exceptionFlags = 0;
|
|
|
|
|
return f32_to_ui64(float32_t{v2}, rm, true);
|
|
|
|
|
}
|
|
|
|
|
template <> inline uint32_t fp_f_to_ui<uint32_t, uint64_t>(uint8_t rm, uint64_t v2) {
|
|
|
|
|
softfloat_exceptionFlags = 0;
|
|
|
|
|
return f64_to_ui32(float64_t{v2}, rm, true);
|
|
|
|
|
}
|
|
|
|
|
template <typename dest_elem_size_t, typename src_elem_size_t> dest_elem_size_t fp_f_to_i(uint8_t, src_elem_size_t);
|
|
|
|
|
template <> inline uint32_t fp_f_to_i<uint32_t, uint32_t>(uint8_t rm, uint32_t v2) {
|
|
|
|
|
softfloat_exceptionFlags = 0;
|
|
|
|
|
return f32_to_i32(float32_t{v2}, rm, true);
|
|
|
|
|
}
|
|
|
|
|
template <> inline uint64_t fp_f_to_i<uint64_t, uint64_t>(uint8_t rm, uint64_t v2) {
|
|
|
|
|
softfloat_exceptionFlags = 0;
|
|
|
|
|
return f64_to_i64(float64_t{v2}, rm, true);
|
|
|
|
|
}
|
|
|
|
|
template <> inline uint64_t fp_f_to_i<uint64_t, uint32_t>(uint8_t rm, uint32_t v2) {
|
|
|
|
|
softfloat_exceptionFlags = 0;
|
|
|
|
|
return f32_to_i64(float32_t{v2}, rm, true);
|
|
|
|
|
}
|
|
|
|
|
template <> inline uint32_t fp_f_to_i<uint32_t, uint64_t>(uint8_t rm, uint64_t v2) {
|
|
|
|
|
softfloat_exceptionFlags = 0;
|
|
|
|
|
return f64_to_i32(float64_t{v2}, rm, true);
|
|
|
|
|
}
|
|
|
|
|
template <typename dest_elem_size_t, typename src_elem_size_t> dest_elem_size_t fp_ui_to_f(src_elem_size_t);
|
|
|
|
|
template <> inline uint32_t fp_ui_to_f<uint32_t, uint32_t>(uint32_t v2) {
|
|
|
|
|
softfloat_exceptionFlags = 0;
|
|
|
|
|
return ui32_to_f32(v2).v;
|
|
|
|
|
}
|
|
|
|
|
template <> inline uint64_t fp_ui_to_f<uint64_t, uint64_t>(uint64_t v2) {
|
|
|
|
|
softfloat_exceptionFlags = 0;
|
|
|
|
|
return ui64_to_f64(v2).v;
|
|
|
|
|
}
|
|
|
|
|
template <> inline uint64_t fp_ui_to_f<uint64_t, uint32_t>(uint32_t v2) {
|
|
|
|
|
softfloat_exceptionFlags = 0;
|
|
|
|
|
return ui32_to_f64(v2).v;
|
|
|
|
|
}
|
|
|
|
|
template <> inline uint32_t fp_ui_to_f<uint32_t, uint64_t>(uint64_t v2) {
|
|
|
|
|
softfloat_exceptionFlags = 0;
|
|
|
|
|
return ui64_to_f32(v2).v;
|
|
|
|
|
}
|
|
|
|
|
template <typename dest_elem_size_t, typename src_elem_size_t> dest_elem_size_t fp_i_to_f(src_elem_size_t);
|
|
|
|
|
template <> inline uint32_t fp_i_to_f<uint32_t, uint32_t>(uint32_t v2) {
|
|
|
|
|
softfloat_exceptionFlags = 0;
|
|
|
|
|
return i32_to_f32(v2).v;
|
|
|
|
|
}
|
|
|
|
|
template <> inline uint64_t fp_i_to_f<uint64_t, uint64_t>(uint64_t v2) {
|
|
|
|
|
softfloat_exceptionFlags = 0;
|
|
|
|
|
return i64_to_f64(v2).v;
|
|
|
|
|
}
|
|
|
|
|
template <> inline uint64_t fp_i_to_f<uint64_t, uint32_t>(uint32_t v2) {
|
|
|
|
|
softfloat_exceptionFlags = 0;
|
|
|
|
|
return i32_to_f64(v2).v;
|
|
|
|
|
}
|
|
|
|
|
template <> inline uint32_t fp_i_to_f<uint32_t, uint64_t>(uint64_t v2) {
|
|
|
|
|
softfloat_exceptionFlags = 0;
|
|
|
|
|
return i64_to_f32(v2).v;
|
|
|
|
|
}
|
|
|
|
|
template <typename dest_elem_t, typename src_elem_t> dest_elem_t fp_f_to_f(uint8_t mode, src_elem_t val) {
|
|
|
|
|
throw new std::runtime_error("Conversion not explicitly specialized");
|
|
|
|
|
}
|
|
|
|
|
template <> inline uint64_t fp_f_to_f<uint64_t, uint32_t>(uint8_t mode, uint32_t val) { return fconv_f2d(val, mode); }
|
|
|
|
|
template <> inline uint32_t fp_f_to_f<uint32_t, uint64_t>(uint8_t mode, uint64_t val) { return fconv_d2f(val, mode); }
|
|
|
|
|
|
|
|
|
|
template <typename dest_elem_t, typename src_elem_t = dest_elem_t>
|
|
|
|
|
std::function<dest_elem_t(uint8_t, uint_fast8_t&, src_elem_t)> get_fp_unary_fn(unsigned unary_op) {
|
|
|
|
|
switch(unary_op) {
|
|
|
|
|
case 0b00000: // VFSQRT
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, src_elem_t vs2) {
|
|
|
|
|
dest_elem_t val = fp_sqrt(rm, vs2);
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
case 0b00100: // VFRSQRT7
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, src_elem_t vs2) {
|
|
|
|
|
dest_elem_t val = fp_rsqrt7(vs2);
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
case 0b00101: // VFREC7
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, src_elem_t vs2) {
|
|
|
|
|
dest_elem_t val = fp_rec7(rm, vs2);
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
case 0b10000: // VFCLASS
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, src_elem_t vs2) {
|
|
|
|
|
dest_elem_t val = fp_fclass(vs2);
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
default:
|
|
|
|
|
std::function<dest_elem_t(uint8_t, uint8_t&, src_elem_t)> get_fp_unary_fn(unsigned encoding_space, unsigned unary_op) {
|
|
|
|
|
if(encoding_space == 0b010011) // VFUNARY1
|
|
|
|
|
switch(unary_op) {
|
|
|
|
|
case 0b00000: // VFSQRT
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, src_elem_t vs2) {
|
|
|
|
|
dest_elem_t val = fp_sqrt(rm, vs2);
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
case 0b00100: // VFRSQRT7
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, src_elem_t vs2) {
|
|
|
|
|
dest_elem_t val = fp_rsqrt7(vs2);
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
case 0b00101: // VFREC7
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, src_elem_t vs2) {
|
|
|
|
|
dest_elem_t val = fp_rec7(rm, vs2);
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
case 0b10000: // VFCLASS
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, src_elem_t vs2) {
|
|
|
|
|
dest_elem_t val = fp_fclass(vs2);
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
default:
|
|
|
|
|
throw new std::runtime_error("Unknown funct in get_fp_unary_fn");
|
|
|
|
|
}
|
|
|
|
|
else if(encoding_space == 0b010010) // VFUNARY0
|
|
|
|
|
switch(unary_op) {
|
|
|
|
|
case 0b00000: // VFCVT.XU.F.V
|
|
|
|
|
case 0b01000: // VFWCVT.XU.F.V
|
|
|
|
|
case 0b10000: // VFNCVT.XU.F.W
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, src_elem_t vs2) {
|
|
|
|
|
dest_elem_t val = fp_f_to_ui<dest_elem_t, src_elem_t>(rm, vs2);
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
case 0b00001: // VFCVT.X.F.V
|
|
|
|
|
case 0b01001: // VFWCVT.X.F.V
|
|
|
|
|
case 0b10001: // VFNCVT.X.F.W
|
|
|
|
|
case 0b00111: // VFCVT.RTZ.X.F.V
|
|
|
|
|
case 0b01111: // VFWCVT.RTZ.X.F.V
|
|
|
|
|
case 0b10111: // VFNCVT.RTZ.X.F.W
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, src_elem_t vs2) {
|
|
|
|
|
dest_elem_t val = fp_f_to_i<dest_elem_t, src_elem_t>(rm, vs2);
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
case 0b00010: // VFCVT.F.XU.V
|
|
|
|
|
case 0b00110: // VFCVT.RTZ.XU.F.V
|
|
|
|
|
case 0b01010: // VFWCVT.F.XU.V
|
|
|
|
|
case 0b01110: // VFWCVT.RTZ.XU.F.V
|
|
|
|
|
case 0b10010: // VFNCVT.F.XU.W
|
|
|
|
|
case 0b10110: // VFNCVT.RTZ.XU.F.W
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, src_elem_t vs2) {
|
|
|
|
|
dest_elem_t val = fp_ui_to_f<dest_elem_t, src_elem_t>(vs2);
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
case 0b00011: // VFCVT.F.X.V
|
|
|
|
|
case 0b01011: // VFWCVT.F.X.V
|
|
|
|
|
case 0b10011: // VFNCVT.F.X.W
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, src_elem_t vs2) {
|
|
|
|
|
dest_elem_t val = fp_i_to_f<dest_elem_t, src_elem_t>(vs2);
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
case 0b01100: // VFWCVT.F.F.V
|
|
|
|
|
case 0b10100: // VFNCVT.F.F.W
|
|
|
|
|
case 0b10101: // VFNCVT.ROD.F.F.W
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, src_elem_t vs2) {
|
|
|
|
|
dest_elem_t val = fp_f_to_f<dest_elem_t, src_elem_t>(rm, vs2);
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
default:
|
|
|
|
|
throw new std::runtime_error("Unknown funct in get_fp_unary_fn");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
throw new std::runtime_error("Unknown funct in get_fp_unary_fn");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
template <unsigned VLEN, typename dest_elem_t, typename src_elem_t>
|
|
|
|
|
void fp_vector_unary_op(uint8_t* V, unsigned unary_op, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vd, unsigned vs2,
|
|
|
|
|
uint8_t rm) {
|
|
|
|
|
void fp_vector_unary_op(uint8_t* V, unsigned encoding_space, unsigned unary_op, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm,
|
|
|
|
|
unsigned vd, unsigned vs2, uint8_t rm) {
|
|
|
|
|
uint64_t elem_count = VLEN * vtype.lmul() / vtype.sew();
|
|
|
|
|
vmask_view mask_reg = read_vmask<VLEN>(V, elem_count);
|
|
|
|
|
auto vs2_view = get_vreg<VLEN, src_elem_t>(V, vs2, elem_count);
|
|
|
|
|
auto vd_view = get_vreg<VLEN, dest_elem_t>(V, vd, elem_count);
|
|
|
|
|
auto fn = get_fp_unary_fn<dest_elem_t, src_elem_t>(unary_op);
|
|
|
|
|
uint_fast8_t accrued_flags = 0;
|
|
|
|
|
auto fn = get_fp_unary_fn<dest_elem_t, src_elem_t>(encoding_space, unary_op);
|
|
|
|
|
uint8_t accrued_flags = 0;
|
|
|
|
|
for(unsigned idx = vstart; idx < std::min(elem_count, vl); idx++) {
|
|
|
|
|
bool mask_active = vm ? 1 : mask_reg[idx];
|
|
|
|
|
if(mask_active) {
|
|
|
|
@ -1420,40 +1541,40 @@ template <> inline bool fp_le<uint64_t>(uint64_t v2, uint64_t v1) { return fcmp_
|
|
|
|
|
template <typename elem_size_t> bool fp_lt(elem_size_t, elem_size_t);
|
|
|
|
|
template <> inline bool fp_lt<uint32_t>(uint32_t v2, uint32_t v1) { return fcmp_s(v2, v1, 2); }
|
|
|
|
|
template <> inline bool fp_lt<uint64_t>(uint64_t v2, uint64_t v1) { return fcmp_d(v2, v1, 2); }
|
|
|
|
|
template <typename elem_t> std::function<bool(uint8_t, uint_fast8_t&, elem_t, elem_t)> get_fp_mask_funct(unsigned funct6) {
|
|
|
|
|
template <typename elem_t> std::function<bool(uint8_t, uint8_t&, elem_t, elem_t)> get_fp_mask_funct(unsigned funct6) {
|
|
|
|
|
switch(funct6) {
|
|
|
|
|
case 0b011000: // VMFEQ
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, elem_t vs2, elem_t vs1) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, elem_t vs2, elem_t vs1) {
|
|
|
|
|
elem_t val = fp_eq(vs2, vs1);
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
case 0b011001: // VMFLE
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, elem_t vs2, elem_t vs1) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, elem_t vs2, elem_t vs1) {
|
|
|
|
|
elem_t val = fp_le(vs2, vs1);
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
case 0b011011: // VMFLT
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, elem_t vs2, elem_t vs1) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, elem_t vs2, elem_t vs1) {
|
|
|
|
|
elem_t val = fp_lt(vs2, vs1);
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
case 0b011100: // VMFNE
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, elem_t vs2, elem_t vs1) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, elem_t vs2, elem_t vs1) {
|
|
|
|
|
elem_t val = !fp_eq(vs2, vs1);
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
case 0b011101: // VMFGT
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, elem_t vs2, elem_t vs1) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, elem_t vs2, elem_t vs1) {
|
|
|
|
|
elem_t val = fp_lt(vs1, vs2);
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
|
};
|
|
|
|
|
case 0b011111: // VMFGE
|
|
|
|
|
return [](uint8_t rm, uint_fast8_t& accrued_flags, elem_t vs2, elem_t vs1) {
|
|
|
|
|
return [](uint8_t rm, uint8_t& accrued_flags, elem_t vs2, elem_t vs1) {
|
|
|
|
|
elem_t val = fp_le(vs1, vs2);
|
|
|
|
|
accrued_flags |= softfloat_exceptionFlags;
|
|
|
|
|
return val;
|
|
|
|
@ -1471,7 +1592,7 @@ void mask_fp_vector_vector_op(uint8_t* V, unsigned funct6, uint64_t vl, uint64_t
|
|
|
|
|
auto vs2_view = get_vreg<VLEN, elem_t>(V, vs2, elem_count);
|
|
|
|
|
vmask_view vd_mask_view = read_vmask<VLEN>(V, VLEN, vd);
|
|
|
|
|
auto fn = get_fp_mask_funct<elem_t>(funct6);
|
|
|
|
|
uint_fast8_t accrued_flags = 0;
|
|
|
|
|
uint8_t accrued_flags = 0;
|
|
|
|
|
for(unsigned idx = vstart; idx < vl; idx++) {
|
|
|
|
|
bool mask_active = vm ? 1 : mask_reg[idx];
|
|
|
|
|
if(mask_active) {
|
|
|
|
@ -1494,7 +1615,7 @@ void mask_fp_vector_imm_op(uint8_t* V, unsigned funct6, uint64_t vl, uint64_t vs
|
|
|
|
|
auto vs2_view = get_vreg<VLEN, elem_t>(V, vs2, elem_count);
|
|
|
|
|
vmask_view vd_mask_view = read_vmask<VLEN>(V, VLEN, vd);
|
|
|
|
|
auto fn = get_fp_mask_funct<elem_t>(funct6);
|
|
|
|
|
uint_fast8_t accrued_flags = 0;
|
|
|
|
|
uint8_t accrued_flags = 0;
|
|
|
|
|
for(unsigned idx = vstart; idx < vl; idx++) {
|
|
|
|
|
bool mask_active = vm ? 1 : mask_reg[idx];
|
|
|
|
|
if(mask_active) {
|
|
|
|
|