use paste::paste;
use strum_macros::EnumString;
use crate::layout;
use crate::rv32i::instr_masks::*;
macro_rules! define_parse_single_instruction {
( $source:ident, $m_sym:ident, $m_layout:ty ) => {
{
paste!{
if ($source & [<MASK_ $m_sym>]) == [<MATCH_ $m_sym>] {
return Some(Instruction::$m_sym($m_layout::from($source)));
}
}
}
};
}
macro_rules! define_instruction_set_enum {
($(($name:ident, $layout:ty)),*) => {
#[derive(Debug, PartialEq, EnumString)]
pub enum Instruction {
$(
$name($layout),
)*
}
}
}
macro_rules! define_instruction_set_parser {
($(($name:ident, $layout:ty)),*) => {
impl Instruction {
pub fn get_name(&self) -> String {
match self {
$(
Self::$name(_) => String::from(stringify!($name)),
)*
}
}
pub fn parse_from_word(word: u32) -> Option<Instruction>{
$(
define_parse_single_instruction!(word, $name, $layout);
)*
None
}
}
}
}
macro_rules! define_instruction_set {
{$($x:tt)*} => {
define_instruction_set_enum!($($x)*);
define_instruction_set_parser!($($x)*);
}
}
define_instruction_set!{
(ADD, layout::R),
(SUB, layout::R),
(ADDI, layout::I),
(SLT, layout::R),
(SLTI, layout::I),
(SLTU, layout::R),
(SLTIU, layout::I),
(LUI, layout::U),
(AUIPC, layout::U),
(AND, layout::R),
(OR, layout::R),
(XOR, layout::R),
(ANDI, layout::I),
(ORI, layout::I),
(XORI, layout::I),
(SLL, layout::R),
(SRL, layout::R),
(SRA, layout::R),
(SLLI, layout::I),
(SRLI, layout::I),
(SRAI, layout::I),
(LW, layout::I),
(LH, layout::I),
(LB, layout::I),
(LHU, layout::I),
(LBU, layout::S),
(SW, layout::S),
(SH, layout::S),
(SB, layout::S),
(BEQ, layout::B),
(BNE, layout::B),
(BGE, layout::B),
(BGEU, layout::B),
(BLT, layout::B),
(BLTU, layout::B),
(JAL, layout::I),
(JALR, layout::I),
(ECALL, layout::Raw),
(EBREAK, layout::Raw),
(FENCE, layout::Raw)
}