ab_riscv_primitives/instructions/
zicsr.rs1#[cfg(test)]
4mod tests;
5
6use crate::hart::HartConfig;
7use crate::instructions::{ImplementedExtension, Instruction, IsaExtension};
8use crate::registers::general_purpose::Register;
9use ab_riscv_macros::instruction;
10use core::fmt;
11
12#[instruction]
14#[derive(Debug, Clone, Copy)]
15#[derive_const(PartialEq, Eq)]
16#[rustfmt::skip]
17pub enum ZicsrInstruction<Hart>
18where
19 Hart: HartConfig,
20{
21 Csrrw { rd: Hart::Reg, rs1: Hart::Reg, csr_index: u16 },
22 Csrrs { rd: Hart::Reg, rs1: Hart::Reg, csr_index: u16 },
23 Csrrc { rd: Hart::Reg, rs1: Hart::Reg, csr_index: u16 },
24 Csrrwi { rd: Hart::Reg, zimm: u8, csr_index: u16 },
25 Csrrsi { rd: Hart::Reg, zimm: u8, csr_index: u16 },
26 Csrrci { rd: Hart::Reg, zimm: u8, csr_index: u16 },
27}
28
29#[instruction]
30const impl<Reg, Hart> Instruction for ZicsrInstruction<Hart>
31where
32 Reg: [const] Register,
33 Hart: [const] HartConfig<Reg = Reg>,
34{
35 const OWN_ISA_EXTENSIONS: &'static [IsaExtension] = &[IsaExtension::new("zicsr", 2, 0)];
36
37 const ALIGNMENT: u8 = align_of::<u32>() as u8;
38
39 type Hart = Hart;
40
41 #[inline(always)]
42 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
43 fn try_decode(instruction: u32) -> Option<Self> {
44 let opcode = (instruction & 0b111_1111) as u8;
45 let rd_bits = ((instruction >> 7) & 0x1f) as u8;
46 let funct3 = ((instruction >> 12) & 0b111) as u8;
47 let rs1_bits = ((instruction >> 15) & 0x1f) as u8;
48 let csr_bits = ((instruction >> 20) & 0x0fff) as u16;
49
50 match opcode {
51 0b111_0011 => {
52 let rd = Reg::from_bits(rd_bits)?;
53 match funct3 {
54 0b001 => {
55 let rs1 = Reg::from_bits(rs1_bits)?;
56 Some(Self::Csrrw {
57 rd,
58 rs1,
59 csr_index: csr_bits,
60 })
61 }
62 0b010 => {
63 let rs1 = Reg::from_bits(rs1_bits)?;
64 Some(Self::Csrrs {
65 rd,
66 rs1,
67 csr_index: csr_bits,
68 })
69 }
70 0b011 => {
71 let rs1 = Reg::from_bits(rs1_bits)?;
72 Some(Self::Csrrc {
73 rd,
74 rs1,
75 csr_index: csr_bits,
76 })
77 }
78 0b101 => Some(Self::Csrrwi {
79 rd,
80 zimm: rs1_bits,
81 csr_index: csr_bits,
82 }),
83 0b110 => Some(Self::Csrrsi {
84 rd,
85 zimm: rs1_bits,
86 csr_index: csr_bits,
87 }),
88 0b111 => Some(Self::Csrrci {
89 rd,
90 zimm: rs1_bits,
91 csr_index: csr_bits,
92 }),
93 _ => None,
94 }
95 }
96 _ => None,
97 }
98 }
99
100 #[inline(always)]
101 fn size(&self) -> u8 {
102 size_of::<u32>() as u8
103 }
104}
105
106#[instruction]
107impl<Reg, Hart> fmt::Display for ZicsrInstruction<Hart>
108where
109 Reg: fmt::Display,
110 Hart: HartConfig<Reg = Reg>,
111{
112 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
113 match self {
114 Self::Csrrw { rd, rs1, csr_index } => write!(f, "csrrw {rd}, {csr_index}, {rs1}"),
115 Self::Csrrs { rd, rs1, csr_index } => write!(f, "csrrs {rd}, {csr_index}, {rs1}"),
116 Self::Csrrc { rd, rs1, csr_index } => write!(f, "csrrc {rd}, {csr_index}, {rs1}"),
117 Self::Csrrwi {
118 rd,
119 zimm,
120 csr_index,
121 } => write!(f, "csrrwi {rd}, {csr_index}, {zimm}"),
122 Self::Csrrsi {
123 rd,
124 zimm,
125 csr_index,
126 } => write!(f, "csrrsi {rd}, {csr_index}, {zimm}"),
127 Self::Csrrci {
128 rd,
129 zimm,
130 csr_index,
131 } => write!(f, "csrrci {rd}, {csr_index}, {zimm}"),
132 }
133 }
134}