Skip to main content

ab_riscv_primitives/
instructions.rs

1//! This module defines the RISC-V instruction set instructions
2
3pub mod rv32;
4pub mod rv64;
5#[cfg(test)]
6mod test_utils;
7pub mod utils;
8pub mod v;
9pub mod zawrs;
10pub mod zicond;
11pub mod zicsr;
12pub mod zifencei;
13pub mod zkr;
14pub mod zvbb;
15pub mod zvbc;
16
17use crate::registers::general_purpose::Register;
18use core::any::TypeId;
19use core::fmt;
20use core::marker::Destruct;
21
22/// Generic instruction
23pub const trait Instruction:
24    fmt::Display + fmt::Debug + [const] Destruct + Copy + Send + Sync + Sized + 'static
25{
26    /// Types of all fully implemented extensions.
27    ///
28    /// Note that this constant is auto-generated by the macro and usually doesn't need to be
29    /// specified explicitly (and if done, will cause conflicts at compile time).
30    const IMPLEMENTED_EXTENSIONS: &'static [TypeId];
31
32    /// Instruction alignment in bytes, also known as `IALIGN`
33    const ALIGNMENT: u8;
34
35    /// A register type used by the instruction
36    type Reg: [const] Register;
37
38    /// Try to decode a single valid instruction
39    fn try_decode(instruction: u32) -> Option<Self>;
40
41    /// Instruction size in bytes
42    fn size(&self) -> u8;
43
44    /// Checks whether this instruction implements the given extension
45    #[inline(always)]
46    fn implements_extension<E>() -> bool
47    where
48        E: Instruction<Reg = Self::Reg>,
49    {
50        const {
51            let mut result = false;
52            // TODO: Simple `.contains()` doesn't work in `const fn` yet:
53            //  https://github.com/rust-lang/rust/issues/92476
54            let mut index = 0;
55            while index < Self::IMPLEMENTED_EXTENSIONS.len() {
56                if Self::IMPLEMENTED_EXTENSIONS[index] == TypeId::of::<E>() {
57                    result = true;
58                }
59                index += 1;
60            }
61
62            result
63        }
64    }
65}