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>(
19 ext_state: &mut ExtState,
20 program_counter: &PC,
21 rd: Reg,
22 rs1: Reg,
23 rs1_value: Reg::Type,
24 vtype_raw: Reg::Type,
25) -> Result<Reg::Type, ExecutionError<Reg::Type, CustomError>>
26where
27 Reg: Register,
28 ExtState: VectorRegistersExt<Reg, CustomError>,
29 [(); ExtState::ELEN as usize]:,
30 [(); ExtState::VLEN as usize]:,
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(0);
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(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(0);
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(new_vl))
91}
92
93#[inline(always)]
100#[doc(hidden)]
101pub fn apply_vsetivli<Reg, ExtState, Memory, PC, CustomError>(
102 ext_state: &mut ExtState,
103 program_counter: &PC,
104 uimm: u8,
105 vtypei: u16,
106) -> Result<Reg::Type, ExecutionError<Reg::Type, CustomError>>
107where
108 Reg: Register,
109 ExtState: VectorRegistersExt<Reg, CustomError>,
110 [(); ExtState::ELEN as usize]:,
111 [(); ExtState::VLEN as usize]:,
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 = u32::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(new_vl)
133 } else {
134 cold_path();
135 ext_state.set_vtype(None);
136 ext_state.set_vl(0);
137 Reg::Type::from(0u8)
138 };
139 ext_state.mark_vs_dirty();
140 ext_state.reset_vstart();
141
142 Ok(rd_value)
143}