five32_instruction_set/rv32i/
instr.rs

1use paste::paste;
2use strum_macros::EnumString;
3
4use crate::layout;
5use crate::rv32i::instr_masks::*;
6
7/// This macro is used to parse an Instruction if its corresponding bitmask matches the input word.
8macro_rules! define_parse_single_instruction {
9    ( $source:ident, $m_sym:ident, $m_layout:ty ) => {
10        {
11            paste!{
12                if ($source & [<MASK_ $m_sym>]) == [<MATCH_ $m_sym>] {
13                    return Some(Instruction::$m_sym($m_layout::from($source)));
14                }
15            }
16        }
17    };
18}
19
20/// This macro is used to define an enum which organizes instructions and byte layouts.
21macro_rules! define_instruction_set_enum {
22    ($(($name:ident, $layout:ty)),*) => {
23        #[derive(Debug, PartialEq, EnumString)]
24        pub enum Instruction {
25            $(
26                $name($layout),
27            )*
28        }
29    }
30}
31
32/// This macro is used to define a function which parses (decodes) an Instruction from a given word.
33macro_rules! define_instruction_set_parser {
34    ($(($name:ident, $layout:ty)),*) => {
35        // This will generate a function 'parse_from_word' for the given set of instructions.
36        impl Instruction {
37            /// Returns the Instruction name (ex: "ADD")
38            pub fn get_name(&self) -> String {
39                match self {
40                    $(
41                        Self::$name(_) => String::from(stringify!($name)),
42                    )*
43                }
44            }
45
46            /// Parses (decodes) the Instruction from a 32-bit word.
47            pub fn parse_from_word(word: u32) -> Option<Instruction>{
48                $(
49                    define_parse_single_instruction!(word, $name, $layout);
50                )*
51                None
52            }
53        }
54    }
55}
56
57/// This macro is used to define an instruction set. It takes a collection of instruction names and
58/// corresponding binary layouts. It then defines an enum to encapsulate these instructions and
59/// writes associated helper functions.
60///
61/// note:   The binary layout type must be fully-specified. This shortcoming is documented in
62///         https://rust-lang.github.io/api-guidelines/macros.html#type-fragments-are-flexible-c-macro-ty
63///
64/// ```rust
65///define_instruction_set!((ADD, layout::R));
66///
67/// // produces...
68/// pub enum Instruction {
69///     ADD(five32_instruction_set::layout::R)
70/// }
71///
72///impl Instruction {
73///   pub fn parse_from_word(word: u32) -> Option<Instruction> {
74///       if (word & MASK_AND) == MATCH_AND {
75///           return Some(Instruction::ADD(five32_instruction_set::R::from(word)));
76///       }
77///       None
78///   }
79///
80///   pub fn get_name(&self) -> String {
81///       match self {
82///           Instruction::ADD(_) => String::from("ADD")
83///       }
84///   }
85///}
86///
87/// ```
88macro_rules! define_instruction_set {
89    {$($x:tt)*} => {
90        define_instruction_set_enum!($($x)*);
91        define_instruction_set_parser!($($x)*);
92    }
93}
94
95define_instruction_set!{
96    // Arithmetic
97    (ADD,   layout::R),
98    (SUB,   layout::R),
99    (ADDI,  layout::I),
100    (SLT,   layout::R),
101    (SLTI,  layout::I),
102    (SLTU,  layout::R),
103    (SLTIU, layout::I),
104    (LUI,   layout::U),
105    (AUIPC, layout::U),
106    // Logical
107    (AND,   layout::R),
108    (OR,    layout::R),
109    (XOR,   layout::R),
110    (ANDI,  layout::I),
111    (ORI,   layout::I),
112    (XORI,  layout::I),
113    (SLL,   layout::R),
114    (SRL,   layout::R),
115    (SRA,   layout::R),
116    (SLLI,  layout::I),
117    (SRLI,  layout::I),
118    (SRAI,  layout::I),
119    // IO
120    (LW,    layout::I),
121    (LH,    layout::I),
122    (LB,    layout::I),
123    (LHU,   layout::I),
124    (LBU,   layout::S),
125    (SW,    layout::S),
126    (SH,    layout::S),
127    (SB,    layout::S),
128    // Branching
129    (BEQ,   layout::B),
130    (BNE,   layout::B),
131    (BGE,   layout::B),
132    (BGEU,  layout::B),
133    (BLT,   layout::B),
134    (BLTU,  layout::B),
135    (JAL,   layout::I),
136    (JALR,  layout::I),
137    // Special Flags
138    (ECALL,     layout::Raw),
139    (EBREAK,    layout::Raw),
140    (FENCE,     layout::Raw)
141}