Skip to main content

ab_riscv_primitives/instructions/
zicsr.rs

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