Skip to main content

ab_riscv_primitives/instructions/
zifencei.rs

1//! Zifencei 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 Zifencei instruction
12#[instruction]
13#[derive(Debug, Clone, Copy)]
14#[derive_const(PartialEq, Eq)]
15pub enum ZifenceiInstruction<Reg> {
16    /// Instruction-fetch fence
17    FenceI,
18}
19
20#[instruction]
21const impl<Reg> Instruction for ZifenceiInstruction<Reg>
22where
23    Reg: [const] Register,
24{
25    const ALIGNMENT: u8 = align_of::<u32>() as u8;
26
27    type Reg = Reg;
28
29    #[inline(always)]
30    #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
31    fn try_decode(instruction: u32) -> Option<Self> {
32        let opcode = (instruction & 0b111_1111) as u8;
33        let funct3 = ((instruction >> 12) & 0b111) as u8;
34
35        // MISC-MEM major opcode, funct3=001
36        if opcode != 0b000_1111 || funct3 != 0b001 {
37            None?;
38        }
39
40        // `rd`, `rs1` and the immediate are all reserved and must be ignored by implementations
41        // rather than checked, so any encoding with funct3=001 in this opcode is a valid `fence.i`
42        Some(Self::FenceI)
43    }
44
45    #[inline(always)]
46    fn size(&self) -> u8 {
47        size_of::<u32>() as u8
48    }
49}
50
51#[instruction]
52impl<Reg> fmt::Display for ZifenceiInstruction<Reg>
53where
54    Reg: fmt::Display,
55{
56    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57        match self {
58            Self::FenceI => write!(f, "fence.i"),
59        }
60    }
61}