eeric/rv_core/instruction/executor/v/
vsmul.rs1use 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}