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    type Reg = Reg;
30
31    #[inline(always)]
32    #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
33    fn try_decode(instruction: u32) -> Option<Self> {
34        let opcode = (instruction & 0b111_1111) as u8;
35        let rd_bits = ((instruction >> 7) & 0x1f) as u8;
36        let funct3 = ((instruction >> 12) & 0b111) as u8;
37        let rs1_bits = ((instruction >> 15) & 0x1f) as u8;
38        let csr_bits = ((instruction >> 20) & 0x0fff) as u16;
39
40        match opcode {
41            0b111_0011 => {
42                let rd = Reg::from_bits(rd_bits)?;
43                match funct3 {
44                    0b001 => {
45                        let rs1 = Reg::from_bits(rs1_bits)?;
46                        Some(Self::Csrrw {
47                            rd,
48                            rs1,
49                            csr_index: csr_bits,
50                        })
51                    }
52                    0b010 => {
53                        let rs1 = Reg::from_bits(rs1_bits)?;
54                        Some(Self::Csrrs {
55                            rd,
56                            rs1,
57                            csr_index: csr_bits,
58                        })
59                    }
60                    0b011 => {
61                        let rs1 = Reg::from_bits(rs1_bits)?;
62                        Some(Self::Csrrc {
63                            rd,
64                            rs1,
65                            csr_index: csr_bits,
66                        })
67                    }
68                    0b101 => Some(Self::Csrrwi {
69                        rd,
70                        zimm: rs1_bits,
71                        csr_index: csr_bits,
72                    }),
73                    0b110 => Some(Self::Csrrsi {
74                        rd,
75                        zimm: rs1_bits,
76                        csr_index: csr_bits,
77                    }),
78                    0b111 => Some(Self::Csrrci {
79                        rd,
80                        zimm: rs1_bits,
81                        csr_index: csr_bits,
82                    }),
83                    _ => None,
84                }
85            }
86            _ => None,
87        }
88    }
89
90    #[inline(always)]
91    fn alignment() -> u8 {
92        align_of::<u32>() as u8
93    }
94
95    #[inline(always)]
96    fn size(&self) -> u8 {
97        size_of::<u32>() as u8
98    }
99}
100
101#[instruction]
102impl<Reg> fmt::Display for ZicsrInstruction<Reg>
103where
104    Reg: fmt::Display,
105{
106    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
107        match self {
108            Self::Csrrw { rd, rs1, csr_index } => write!(f, "csrrw {rd}, {csr_index}, {rs1}"),
109            Self::Csrrs { rd, rs1, csr_index } => write!(f, "csrrs {rd}, {csr_index}, {rs1}"),
110            Self::Csrrc { rd, rs1, csr_index } => write!(f, "csrrc {rd}, {csr_index}, {rs1}"),
111            Self::Csrrwi {
112                rd,
113                zimm,
114                csr_index,
115            } => write!(f, "csrrwi {rd}, {csr_index}, {zimm}"),
116            Self::Csrrsi {
117                rd,
118                zimm,
119                csr_index,
120            } => write!(f, "csrrsi {rd}, {csr_index}, {zimm}"),
121            Self::Csrrci {
122                rd,
123                zimm,
124                csr_index,
125            } => write!(f, "csrrci {rd}, {csr_index}, {zimm}"),
126        }
127    }
128}