risc_v_disassembler/instructions/
mod.rs

1pub mod parsed_instructions;
2
3use crate::{DisassemblerError, Register};
4use parsed_instructions::*;
5use std::fmt;
6
7pub type Instruction32 = u32;
8pub(crate) enum DecodedInstruction32 {
9    RType {
10        opcode: u8,
11        rd: u8,
12        funct3: u8,
13        rs1: u8,
14        rs2: u8,
15        funct7: u8,
16    },
17    IType {
18        opcode: u8,
19        rd: u8,
20        funct3: u8,
21        rs1: u8,
22        imm: i32,
23    },
24    SType {
25        opcode: u8,
26        imm: i32,
27        funct3: u8,
28        rs1: u8,
29        rs2: u8,
30    },
31    BType {
32        opcode: u8,
33        imm: i32,
34        funct3: u8,
35        rs1: u8,
36        rs2: u8,
37    },
38    UType {
39        opcode: u8,
40        rd: u8,
41        imm: i32,
42    },
43    JType {
44        opcode: u8,
45        rd: u8,
46        imm: i32,
47    },
48}
49
50#[derive(Debug, PartialEq)]
51#[allow(non_camel_case_types)]
52pub enum ParsedInstruction32 {
53    add(add),
54    sub(sub),
55    xor(xor),
56    or(or),
57    and(and),
58    sll(sll),
59    srl(srl),
60    sra(sra),
61    slt(slt),
62    sltu(sltu),
63    addi(addi),
64    xori(xori),
65    ori(ori),
66    andi(andi),
67    slli(slli),
68    srli(srli),
69    srai(srai),
70    slti(slti),
71    sltiu(sltiu),
72    lb(lb),
73    lh(lh),
74    lw(lw),
75    lbu(lbu),
76    lhu(lhu),
77    sb(sb),
78    sh(sh),
79    sw(sw),
80    beq(beq),
81    bne(bne),
82    blt(blt),
83    bge(bge),
84    bltu(bltu),
85    bgeu(bgeu),
86    jal(jal),
87    jalr(jalr),
88    lui(lui),
89    auipc(auipc),
90    ecall(ecall),
91    ebreak(ebreak),
92}
93
94pub(crate) trait DecodeInstruction32 {
95    fn decode_instruction32(&self) -> Result<DecodedInstruction32, DisassemblerError>;
96}
97
98pub(crate) trait ParseInstruction32 {
99    fn parse_instruction32<T: Register>(&self) -> Result<ParsedInstruction32, DisassemblerError>;
100}
101
102impl fmt::Display for ParsedInstruction32 {
103    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104        match self {
105            ParsedInstruction32::add(inner) => inner.fmt(f),
106            ParsedInstruction32::sub(inner) => inner.fmt(f),
107            ParsedInstruction32::xor(inner) => inner.fmt(f),
108            ParsedInstruction32::or(inner) => inner.fmt(f),
109            ParsedInstruction32::and(inner) => inner.fmt(f),
110            ParsedInstruction32::sll(inner) => inner.fmt(f),
111            ParsedInstruction32::srl(inner) => inner.fmt(f),
112            ParsedInstruction32::sra(inner) => inner.fmt(f),
113            ParsedInstruction32::slt(inner) => inner.fmt(f),
114            ParsedInstruction32::sltu(inner) => inner.fmt(f),
115            ParsedInstruction32::addi(inner) => inner.fmt(f),
116            ParsedInstruction32::xori(inner) => inner.fmt(f),
117            ParsedInstruction32::ori(inner) => inner.fmt(f),
118            ParsedInstruction32::andi(inner) => inner.fmt(f),
119            ParsedInstruction32::slli(inner) => inner.fmt(f),
120            ParsedInstruction32::srli(inner) => inner.fmt(f),
121            ParsedInstruction32::srai(inner) => inner.fmt(f),
122            ParsedInstruction32::slti(inner) => inner.fmt(f),
123            ParsedInstruction32::sltiu(inner) => inner.fmt(f),
124            ParsedInstruction32::lb(inner) => inner.fmt(f),
125            ParsedInstruction32::lh(inner) => inner.fmt(f),
126            ParsedInstruction32::lw(inner) => inner.fmt(f),
127            ParsedInstruction32::lbu(inner) => inner.fmt(f),
128            ParsedInstruction32::lhu(inner) => inner.fmt(f),
129            ParsedInstruction32::sb(inner) => inner.fmt(f),
130            ParsedInstruction32::sh(inner) => inner.fmt(f),
131            ParsedInstruction32::sw(inner) => inner.fmt(f),
132            ParsedInstruction32::beq(inner) => inner.fmt(f),
133            ParsedInstruction32::bne(inner) => inner.fmt(f),
134            ParsedInstruction32::blt(inner) => inner.fmt(f),
135            ParsedInstruction32::bge(inner) => inner.fmt(f),
136            ParsedInstruction32::bltu(inner) => inner.fmt(f),
137            ParsedInstruction32::bgeu(inner) => inner.fmt(f),
138            ParsedInstruction32::jal(inner) => inner.fmt(f),
139            ParsedInstruction32::jalr(inner) => inner.fmt(f),
140            ParsedInstruction32::lui(inner) => inner.fmt(f),
141            ParsedInstruction32::auipc(inner) => inner.fmt(f),
142            ParsedInstruction32::ecall(inner) => inner.fmt(f),
143            ParsedInstruction32::ebreak(inner) => inner.fmt(f),
144        }
145    }
146}
147
148#[cfg(test)]
149mod test {
150    use crate::instructions::parsed_instructions::*;
151    use crate::ParsedInstruction32;
152
153    #[test]
154    fn test_instruction_printing() {
155        let parsed_add: ParsedInstruction32 = ParsedInstruction32::add(add {
156            rd: "x1",
157            rs1: "x2",
158            rs2: "x3",
159        });
160        assert_eq!(format!("{}", parsed_add), "add x1, x2, x3");
161
162        let parsed_addi: ParsedInstruction32 = ParsedInstruction32::addi(addi {
163            rd: "x1",
164            rs1: "x31",
165            imm: -5,
166        });
167        assert_eq!(format!("{}", parsed_addi), "addi x1, x31, -5");
168
169        let parsed_jal: ParsedInstruction32 = ParsedInstruction32::jal(jal { rd: "x1", imm: 5 });
170        assert_eq!(format!("{}", parsed_jal), "jal x1, 5");
171
172        let parsed_ecall: ParsedInstruction32 = ParsedInstruction32::ecall(ecall {});
173        assert_eq!(format!("{}", parsed_ecall), "ecall");
174    }
175}