Skip to main content

ab_riscv_primitives/instructions/
zicsr.rs

1//! Zicsr extension
2
3#[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/// RISC-V Zicsr instruction (Control and Status Register)
13#[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}