Skip to main content

ab_riscv_primitives/instructions/
zifencei.rs

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