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