eeric/rv_core/instruction/executor/v/
vsmul.rs

1use crate::rv_core::instruction::executor::prelude::*;
2
3use super::utils::rounding::Roundoff;
4
5pub fn vv(Opivv { vd, vs1, vs2, vm }: Opivv, v: &mut VectorContext<'_>) {
6    let roundoff_signed = Roundoff::new_signed(v.csr);
7
8    let int_max = i64::MAX >> (64 - v.vec_engine.sew.bit_length());
9    let int_min = i64::MIN >> (64 - v.vec_engine.sew.bit_length());
10
11    let vec_engine = *v.vec_engine;
12
13    let vreg = izip!(v.get(vs2).iter_eew(), v.get(vs1).iter_eew())
14        .masked_map(v.default_mask(vm), v.get(vd).iter_eew(), |(vs2, vs1)| {
15            let is_overflow = vs2 == vs1 && vs1 == int_min as u64;
16
17            if is_overflow {
18                v.csr[VXSAT].write(1);
19                int_max as u64
20            } else {
21                roundoff_signed(
22                    vs2 as u128 * vs1 as u128,
23                    v.vec_engine.sew.bit_length() as u8 - 1,
24                )
25            }
26        })
27        .collect_with_eew(vec_engine.sew);
28
29    v.apply(vd, vreg);
30}
31
32pub fn vx(Opivx { vd, rs1, vs2, vm }: Opivx, v: &mut VectorContext<'_>, x: &IntegerRegisters) {
33    let roundoff_signed = Roundoff::new_signed(v.csr);
34
35    let int_max = i64::MAX >> (64 - v.vec_engine.sew.bit_length());
36    let int_min = i64::MIN >> (64 - v.vec_engine.sew.bit_length());
37
38    let vec_engine = *v.vec_engine;
39
40    let vreg = v
41        .get(vs2)
42        .iter_eew()
43        .masked_map(v.default_mask(vm), v.get(vd).iter_eew(), |vs2| {
44            let is_overflow = vs2 == x[rs1] && x[rs1] == int_min as u64;
45
46            if is_overflow {
47                v.csr[VXSAT].write(1);
48                int_max as u64
49            } else {
50                roundoff_signed(
51                    vs2 as u128 * x[rs1] as u128,
52                    v.vec_engine.sew.bit_length() as u8 - 1,
53                )
54            }
55        })
56        .collect_with_eew(vec_engine.sew);
57
58    v.apply(vd, vreg);
59}