1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
use once_cell::sync::Lazy;
use strum::{Display, EnumString, IntoStaticStr, VariantArray};

use crate::utility::enum_map::EnumMap;

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, VariantArray, EnumString, Display)]
pub enum RV32IRegister {
    #[strum(to_string = "zero", serialize = "zero", serialize = "x0")]
    Zero,
    #[strum(to_string = "ra", serialize = "ra", serialize = "x1")]
    Ra,
    #[strum(to_string = "sp", serialize = "sp", serialize = "x2")]
    Sp,
    #[strum(to_string = "gp", serialize = "gp", serialize = "x3")]
    Gp,
    #[strum(to_string = "tp", serialize = "tp", serialize = "x4")]
    Tp,
    #[strum(to_string = "t0", serialize = "t0", serialize = "x5")]
    T0,
    #[strum(to_string = "t1", serialize = "t1", serialize = "x6")]
    T1,
    #[strum(to_string = "t2", serialize = "t2", serialize = "x7")]
    T2,
    #[strum(to_string = "s0", serialize = "s0", serialize = "fp", serialize = "x8")]
    S0,
    #[strum(to_string = "s1", serialize = "s1", serialize = "x9")]
    S1,
    #[strum(to_string = "a0", serialize = "a0", serialize = "x10")]
    A0,
    #[strum(to_string = "a1", serialize = "a1", serialize = "x11")]
    A1,
    #[strum(to_string = "a2", serialize = "a2", serialize = "x12")]
    A2,
    #[strum(to_string = "a3", serialize = "a3", serialize = "x13")]
    A3,
    #[strum(to_string = "a4", serialize = "a4", serialize = "x14")]
    A4,
    #[strum(to_string = "a5", serialize = "a5", serialize = "x15")]
    A5,
    #[strum(to_string = "a6", serialize = "a6", serialize = "x16")]
    A6,
    #[strum(to_string = "a7", serialize = "a7", serialize = "x17")]
    A7,
    #[strum(to_string = "s2", serialize = "s2", serialize = "x18")]
    S2,
    #[strum(to_string = "s3", serialize = "s3", serialize = "x19")]
    S3,
    #[strum(to_string = "s4", serialize = "s4", serialize = "x20")]
    S4,
    #[strum(to_string = "s5", serialize = "s5", serialize = "x21")]
    S5,
    #[strum(to_string = "s6", serialize = "s6", serialize = "x22")]
    S6,
    #[strum(to_string = "s7", serialize = "s7", serialize = "x23")]
    S7,
    #[strum(to_string = "s8", serialize = "s8", serialize = "x24")]
    S8,
    #[strum(to_string = "s9", serialize = "s9", serialize = "x25")]
    S9,
    #[strum(to_string = "s10", serialize = "s10", serialize = "x26")]
    S10,
    #[strum(to_string = "s11", serialize = "s11", serialize = "x27")]
    S11,
    #[strum(to_string = "t3", serialize = "t3", serialize = "x28")]
    T3,
    #[strum(to_string = "t4", serialize = "t4", serialize = "x29")]
    T4,
    #[strum(to_string = "t5", serialize = "t5", serialize = "x30")]
    T5,
    #[strum(to_string = "t6", serialize = "t6", serialize = "x31")]
    T6,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, VariantArray, EnumString, IntoStaticStr)]
#[strum(serialize_all = "snake_case")]
pub enum RV32IInstruction {
    Add,
    Addi,
    And,
    Andi,
    Auipc,
    Beq,
    Bge,
    Bgeu,
    Blt,
    Bltu,
    Bne,
    Csrrc,
    Csrrci,
    Csrrs,
    Csrrsi,
    Csrrw,
    Csrrwi,
    Ebreak,
    Ecall,
    Fence,
    FenceI,
    Jal,
    Jalr,
    Lb,
    Lbu,
    Lh,
    Lhu,
    Lui,
    Lw,
    Or,
    Ori,
    Sb,
    Sh,
    Sll,
    Slli,
    Slt,
    Slti,
    Sltiu,
    Sltu,
    Sra,
    Srai,
    Srl,
    Srli,
    Sub,
    Sw,
    Xor,
    Xori,
}

pub type RISCVImmediate = i32;

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, VariantArray, EnumString, IntoStaticStr)]
pub enum RV32ICsr {}

pub static RV32I_REGISTER_VALID_NAME: [&'static str; 65] = [
    "zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4",
    "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4",
    "t5", "t6", "fp", "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11",
    "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", "x24",
    "x25", "x26", "x27", "x28", "x29", "x30", "x31",
];

pub static RV32I_REGISTER_DEFAULT_NAME: Lazy<EnumMap<RV32IRegister, String>> =
    Lazy::new(|| EnumMap::new(RV32IRegister::VARIANTS, |&reg| (reg, reg.to_string())));

impl From<RV32IRegister> for &'static str {
    fn from(value: RV32IRegister) -> Self {
        RV32I_REGISTER_DEFAULT_NAME.get(value)
    }
}

pub fn get_32u_low(i: u32) -> RISCVImmediate {
    ((i & 0x7ff) | -(i as i32 & 0x800) as u32) as RISCVImmediate
}
pub fn get_32u_high(i: u32) -> RISCVImmediate {
    ((i >> 12) + ((i & 0x800) >> 11)) as RISCVImmediate
}