risc_v_disassembler/instructions/
mod.rs1pub 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}