ab_riscv_interpreter/v/zvexx/config/
zvexx_config_helpers.rs1use crate::v::vector_registers::VectorRegistersExt;
4use crate::v::zvexx::zvexx_helpers::INSTRUCTION_SIZE;
5use crate::{ExecutionError, ProgramCounter};
6use ab_riscv_primitives::prelude::*;
7use core::fmt;
8use core::hint::cold_path;
9
10#[inline(always)]
17#[doc(hidden)]
18pub fn apply_vsetvl<Reg, ExtState, Memory, PC, CustomError>(
20 ext_state: &mut ExtState,
21 program_counter: &PC,
22 rd: Reg,
23 rs1: Reg,
24 rs1_value: Reg::Type,
25 vtype_raw: Reg::Type,
26) -> Result<Reg::Type, ExecutionError<Reg::Type, CustomError>>
27where
28 Reg: Register,
29 ExtState: VectorRegistersExt<Reg, CustomError>,
30 [(); SUPPORTED_ELEN_VLEN::<{ ExtState::ELEN }, { ExtState::VLEN }>]:,
31 PC: ProgramCounter<Reg::Type, Memory, CustomError>,
32 CustomError: fmt::Debug,
33{
34 if !ext_state.vector_instructions_allowed() {
36 cold_path();
37 return Err(ExecutionError::IllegalInstruction {
38 address: program_counter.old_pc(INSTRUCTION_SIZE),
39 });
40 }
41
42 let Some(new_vtype) = Vtype::from_raw::<Reg>(vtype_raw) else {
43 cold_path();
44 ext_state.set_vtype(None);
45 ext_state.set_vl(Vl::ZERO);
46 ext_state.mark_vs_dirty();
47 ext_state.reset_vstart();
48
49 return Ok(Reg::Type::from(0u8));
50 };
51
52 let vlmax = ext_state.vlmax_for_vtype(new_vtype);
53
54 let rs1_is_zero = rs1 == Reg::ZERO;
55 let rd_is_zero = rd == Reg::ZERO;
56
57 let new_vl = if !rs1_is_zero {
58 let avl = rs1_value.as_u64() as u32;
60 ext_state.compute_vl(Vl::new_saturating(avl), vlmax)
61 } else if !rd_is_zero {
62 vlmax
64 } else {
65 let current_vl = ext_state.vl();
69 let old_vtype = ext_state.vtype();
70 let old_vlmax = old_vtype.map_or_default(|old_vtype| ext_state.vlmax_for_vtype(old_vtype));
71
72 if vlmax != old_vlmax {
73 cold_path();
74 ext_state.set_vtype(None);
75 ext_state.set_vl(Vl::ZERO);
76 ext_state.mark_vs_dirty();
77 ext_state.reset_vstart();
78
79 return Ok(Reg::Type::from(0u8));
80 }
81
82 ext_state.compute_vl(current_vl, vlmax)
83 };
84
85 ext_state.set_vtype(Some(new_vtype));
86 ext_state.set_vl(new_vl);
87 ext_state.mark_vs_dirty();
88 ext_state.reset_vstart();
89
90 Ok(Reg::Type::from(u32::from(new_vl)))
91}
92
93#[inline(always)]
100#[doc(hidden)]
101pub fn apply_vsetivli<Reg, ExtState, Memory, PC, CustomError>(
103 ext_state: &mut ExtState,
104 program_counter: &PC,
105 uimm: u8,
106 vtypei: u16,
107) -> Result<Reg::Type, ExecutionError<Reg::Type, CustomError>>
108where
109 Reg: Register,
110 ExtState: VectorRegistersExt<Reg, CustomError>,
111 [(); SUPPORTED_ELEN_VLEN::<{ ExtState::ELEN }, { ExtState::VLEN }>]:,
112 PC: ProgramCounter<Reg::Type, Memory, CustomError>,
113 CustomError: fmt::Debug,
114{
115 if !ext_state.vector_instructions_allowed() {
117 cold_path();
118 return Err(ExecutionError::IllegalInstruction {
119 address: program_counter.old_pc(INSTRUCTION_SIZE),
120 });
121 }
122
123 let vtype_raw = Reg::Type::from(vtypei);
124
125 let rd_value = if let Some(new_vtype) = Vtype::from_raw::<Reg>(vtype_raw) {
126 let vlmax = ext_state.vlmax_for_vtype(new_vtype);
127 let avl = Vl::from(uimm);
128 let new_vl = ext_state.compute_vl(avl, vlmax);
129
130 ext_state.set_vtype(Some(new_vtype));
131 ext_state.set_vl(new_vl);
132 Reg::Type::from(u32::from(new_vl))
133 } else {
134 cold_path();
135 ext_state.set_vtype(None);
136 ext_state.set_vl(Vl::ZERO);
137 Reg::Type::from(0u8)
138 };
139 ext_state.mark_vs_dirty();
140 ext_state.reset_vstart();
141
142 Ok(rd_value)
143}