1use super::instruction_formats;
22use super::InstructionProcessor;
23use paste::paste;
24
25pub struct InstructionStringOutputter {
26 pub insn_pc: u32,
29}
30
31macro_rules! string_out_for_alu_reg_op {
33 ($name:ident) => {
34 paste! {
35 fn [<process_ $name>](
36 &mut self,
37 dec_insn: instruction_formats::RType
38 ) -> Self::InstructionResult {
39 format!("{} x{}, x{}, x{}", stringify!($name), dec_insn.rd, dec_insn.rs1,
40 dec_insn.rs2)
41 }
42 }
43 };
44}
45
46macro_rules! string_out_for_alu_reg_ops {
47 ($($name:ident),*) => {
48 $(
49 string_out_for_alu_reg_op! {$name}
50 )*
51 };
52}
53
54macro_rules! string_out_for_alu_imm_op {
55 ($name:ident) => {
56 paste! {
57 fn [<process_ $name i>](
58 &mut self,
59 dec_insn: instruction_formats::IType
60 ) -> Self::InstructionResult {
61 format!("{}i x{}, x{}, {}", stringify!($name), dec_insn.rd, dec_insn.rs1,
62 dec_insn.imm)
63 }
64 }
65 };
66}
67
68macro_rules! string_out_for_alu_imm_shamt_op {
69 ($name:ident) => {
70 paste! {
71 fn [<process_ $name i>](
72 &mut self,
73 dec_insn: instruction_formats::ITypeShamt
74 ) -> Self::InstructionResult {
75 format!("{}i x{}, x{}, {}", stringify!($name), dec_insn.rd, dec_insn.rs1,
76 dec_insn.shamt)
77 }
78 }
79 };
80}
81
82macro_rules! string_out_for_alu_ops {
83 ($($name:ident),*) => {
84 $(
85 string_out_for_alu_reg_op! {$name}
86 string_out_for_alu_imm_op! {$name}
87 )*
88 }
89}
90
91macro_rules! string_out_for_shift_ops {
92 ($($name:ident),*) => {
93 $(
94 string_out_for_alu_reg_op! {$name}
95 string_out_for_alu_imm_shamt_op! {$name}
96 )*
97 }
98}
99
100macro_rules! string_out_for_branch_ops {
101 ($($name:ident),*) => {
102 $(
103 paste! {
104 fn [<process_ $name>](
105 &mut self,
106 dec_insn: instruction_formats::BType
107 ) -> Self::InstructionResult {
108 let branch_pc = self.insn_pc.wrapping_add(dec_insn.imm as u32);
109
110 format!("{} x{}, x{}, 0x{:08x}", stringify!($name), dec_insn.rs1, dec_insn.rs2,
111 branch_pc)
112 }
113 }
114 )*
115 }
116}
117
118macro_rules! string_out_for_load_ops {
119 ($($name:ident),*) => {
120 $(
121 paste! {
122 fn [<process_ $name>](
123 &mut self,
124 dec_insn: instruction_formats::IType
125 ) -> Self::InstructionResult {
126 format!("{} x{}, {}(x{})", stringify!($name), dec_insn.rd, dec_insn.imm,
127 dec_insn.rs1)
128 }
129 }
130 )*
131 }
132}
133
134macro_rules! string_out_for_store_ops {
135 ($($name:ident),*) => {
136 $(
137 paste! {
138 fn [<process_ $name>](
139 &mut self,
140 dec_insn: instruction_formats::SType
141 ) -> Self::InstructionResult {
142 format!("{} x{}, {}(x{})", stringify!($name), dec_insn.rs2, dec_insn.imm,
143 dec_insn.rs1)
144 }
145 }
146 )*
147 }
148}
149
150impl InstructionProcessor for InstructionStringOutputter {
151 type InstructionResult = String;
152
153 string_out_for_alu_ops! {add, slt, xor, or, and}
156 string_out_for_alu_reg_op! {sltu}
157 string_out_for_alu_reg_op! {sub}
158 string_out_for_shift_ops! {sll, srl, sra}
159
160 fn process_sltui(&mut self, dec_insn: instruction_formats::IType) -> Self::InstructionResult {
164 format!(
165 "sltiu x{}, x{}, {}",
166 dec_insn.rd, dec_insn.rs1, dec_insn.imm
167 )
168 }
169
170 fn process_lui(&mut self, dec_insn: instruction_formats::UType) -> Self::InstructionResult {
171 format!("lui x{}, 0x{:08x}", dec_insn.rd, dec_insn.imm)
172 }
173
174 fn process_auipc(&mut self, dec_insn: instruction_formats::UType) -> Self::InstructionResult {
175 let final_imm = self.insn_pc.wrapping_add(dec_insn.imm as u32);
176 format!("auipc x{}, 0x{:08x}", dec_insn.rd, final_imm)
177 }
178
179 string_out_for_branch_ops! {beq, bne, bge, bgeu, blt, bltu}
180 string_out_for_load_ops! {lb, lbu, lh, lhu, lw}
181 string_out_for_store_ops! {sb, sh, sw}
182
183 fn process_jal(&mut self, dec_insn: instruction_formats::JType) -> Self::InstructionResult {
184 let target_pc = self.insn_pc.wrapping_add(dec_insn.imm as u32);
185 format!("jal x{}, 0x{:08x}", dec_insn.rd, target_pc)
186 }
187
188 fn process_jalr(&mut self, dec_insn: instruction_formats::IType) -> Self::InstructionResult {
189 format!(
190 "jalr x{}, 0x{:03x}(x{})",
191 dec_insn.rd, dec_insn.imm, dec_insn.rs1
192 )
193 }
194
195 string_out_for_alu_reg_ops! {mul, mulh, mulhu, mulhsu, div, divu, rem, remu}
196
197 fn process_fence(&mut self, _dec_insn: instruction_formats::IType) -> Self::InstructionResult {
198 String::from("fence")
199 }
200}
201
202#[cfg(test)]
203mod tests {
204 use super::*;
205 use crate::process_instruction;
206
207 #[test]
208 fn test_insn_string_output() {
209 let mut outputter = InstructionStringOutputter { insn_pc: 0 };
210
211 let test_insns = vec![
212 0x07b60893, 0x24dba193, 0x06f63813, 0x14044f13, 0x7804e893, 0x1ea6fa13, 0x00511693,
213 0x00f45713, 0x417dd213, 0x01798733, 0x40e18ab3, 0x009e1533, 0x00c02fb3, 0x014ab933,
214 0x0175cd33, 0x014350b3, 0x41a753b3, 0x00566fb3, 0x01de7db3, 0xdeadb637, 0x00064897,
215 0x04c004ef, 0x100183e7, 0x04d38263, 0x05349063, 0x03774e63, 0x03dbdc63, 0x035e6a63,
216 0x0398f863, 0x04c18983, 0x07841b83, 0x1883a403, 0x03af4b03, 0x15acd883, 0x0d320923,
217 0x18061323, 0x0b382523, 0x034684b3, 0x03679f33, 0x0324bbb3, 0x03d9a233, 0x03f549b3,
218 0x02ee5133, 0x02a6e9b3, 0x02c976b3, 0xabc0000f,
219 ];
220
221 assert_eq!(
222 process_instruction(&mut outputter, test_insns[0]),
223 Some(String::from("addi x17, x12, 123"))
224 );
225
226 assert_eq!(
227 process_instruction(&mut outputter, test_insns[1]),
228 Some(String::from("slti x3, x23, 589"))
229 );
230
231 assert_eq!(
232 process_instruction(&mut outputter, test_insns[2]),
233 Some(String::from("sltiu x16, x12, 111"))
234 );
235
236 assert_eq!(
237 process_instruction(&mut outputter, test_insns[3]),
238 Some(String::from("xori x30, x8, 320"))
239 );
240
241 assert_eq!(
242 process_instruction(&mut outputter, test_insns[4]),
243 Some(String::from("ori x17, x9, 1920"))
244 );
245
246 assert_eq!(
247 process_instruction(&mut outputter, test_insns[5]),
248 Some(String::from("andi x20, x13, 490"))
249 );
250
251 assert_eq!(
252 process_instruction(&mut outputter, test_insns[6]),
253 Some(String::from("slli x13, x2, 5"))
254 );
255
256 assert_eq!(
257 process_instruction(&mut outputter, test_insns[7]),
258 Some(String::from("srli x14, x8, 15"))
259 );
260
261 assert_eq!(
262 process_instruction(&mut outputter, test_insns[8]),
263 Some(String::from("srai x4, x27, 23"))
264 );
265
266 assert_eq!(
267 process_instruction(&mut outputter, test_insns[9]),
268 Some(String::from("add x14, x19, x23"))
269 );
270
271 assert_eq!(
272 process_instruction(&mut outputter, test_insns[10]),
273 Some(String::from("sub x21, x3, x14"))
274 );
275
276 assert_eq!(
277 process_instruction(&mut outputter, test_insns[11]),
278 Some(String::from("sll x10, x28, x9"))
279 );
280
281 assert_eq!(
282 process_instruction(&mut outputter, test_insns[12]),
283 Some(String::from("slt x31, x0, x12"))
284 );
285
286 assert_eq!(
287 process_instruction(&mut outputter, test_insns[13]),
288 Some(String::from("sltu x18, x21, x20"))
289 );
290
291 assert_eq!(
292 process_instruction(&mut outputter, test_insns[14]),
293 Some(String::from("xor x26, x11, x23"))
294 );
295
296 assert_eq!(
297 process_instruction(&mut outputter, test_insns[15]),
298 Some(String::from("srl x1, x6, x20"))
299 );
300
301 assert_eq!(
302 process_instruction(&mut outputter, test_insns[16]),
303 Some(String::from("sra x7, x14, x26"))
304 );
305
306 assert_eq!(
307 process_instruction(&mut outputter, test_insns[17]),
308 Some(String::from("or x31, x12, x5"))
309 );
310
311 assert_eq!(
312 process_instruction(&mut outputter, test_insns[18]),
313 Some(String::from("and x27, x28, x29"))
314 );
315
316 assert_eq!(
317 process_instruction(&mut outputter, test_insns[19]),
318 Some(String::from("lui x12, 0xdeadb000"))
319 );
320
321 outputter.insn_pc = 0x50;
322 assert_eq!(
323 process_instruction(&mut outputter, test_insns[20]),
324 Some(String::from("auipc x17, 0x00064050"))
325 );
326
327 outputter.insn_pc = 0x54;
328 assert_eq!(
329 process_instruction(&mut outputter, test_insns[21]),
330 Some(String::from("jal x9, 0x000000a0"))
331 );
332
333 assert_eq!(
334 process_instruction(&mut outputter, test_insns[22]),
335 Some(String::from("jalr x7, 0x100(x3)"))
336 );
337
338 outputter.insn_pc = 0x5c;
339 assert_eq!(
340 process_instruction(&mut outputter, test_insns[23]),
341 Some(String::from("beq x7, x13, 0x000000a0"))
342 );
343
344 outputter.insn_pc = 0x60;
345 assert_eq!(
346 process_instruction(&mut outputter, test_insns[24]),
347 Some(String::from("bne x9, x19, 0x000000a0"))
348 );
349
350 outputter.insn_pc = 0x64;
351 assert_eq!(
352 process_instruction(&mut outputter, test_insns[25]),
353 Some(String::from("blt x14, x23, 0x000000a0"))
354 );
355
356 outputter.insn_pc = 0x68;
357 assert_eq!(
358 process_instruction(&mut outputter, test_insns[26]),
359 Some(String::from("bge x23, x29, 0x000000a0"))
360 );
361
362 outputter.insn_pc = 0x6c;
363 assert_eq!(
364 process_instruction(&mut outputter, test_insns[27]),
365 Some(String::from("bltu x28, x21, 0x000000a0"))
366 );
367
368 outputter.insn_pc = 0x70;
369 assert_eq!(
370 process_instruction(&mut outputter, test_insns[28]),
371 Some(String::from("bgeu x17, x25, 0x000000a0"))
372 );
373
374 assert_eq!(
375 process_instruction(&mut outputter, test_insns[29]),
376 Some(String::from("lb x19, 76(x3)"))
377 );
378
379 assert_eq!(
380 process_instruction(&mut outputter, test_insns[30]),
381 Some(String::from("lh x23, 120(x8)"))
382 );
383
384 assert_eq!(
385 process_instruction(&mut outputter, test_insns[31]),
386 Some(String::from("lw x8, 392(x7)"))
387 );
388
389 assert_eq!(
390 process_instruction(&mut outputter, test_insns[32]),
391 Some(String::from("lbu x22, 58(x30)"))
392 );
393
394 assert_eq!(
395 process_instruction(&mut outputter, test_insns[33]),
396 Some(String::from("lhu x17, 346(x25)"))
397 );
398
399 assert_eq!(
400 process_instruction(&mut outputter, test_insns[34]),
401 Some(String::from("sb x19, 210(x4)"))
402 );
403
404 assert_eq!(
405 process_instruction(&mut outputter, test_insns[35]),
406 Some(String::from("sh x0, 390(x12)"))
407 );
408
409 assert_eq!(
410 process_instruction(&mut outputter, test_insns[36]),
411 Some(String::from("sw x19, 170(x16)"))
412 );
413
414 assert_eq!(
415 process_instruction(&mut outputter, test_insns[37]),
416 Some(String::from("mul x9, x13, x20"))
417 );
418
419 assert_eq!(
420 process_instruction(&mut outputter, test_insns[38]),
421 Some(String::from("mulh x30, x15, x22"))
422 );
423
424 assert_eq!(
425 process_instruction(&mut outputter, test_insns[39]),
426 Some(String::from("mulhu x23, x9, x18"))
427 );
428
429 assert_eq!(
430 process_instruction(&mut outputter, test_insns[40]),
431 Some(String::from("mulhsu x4, x19, x29"))
432 );
433
434 assert_eq!(
435 process_instruction(&mut outputter, test_insns[41]),
436 Some(String::from("div x19, x10, x31"))
437 );
438
439 assert_eq!(
440 process_instruction(&mut outputter, test_insns[42]),
441 Some(String::from("divu x2, x28, x14"))
442 );
443
444 assert_eq!(
445 process_instruction(&mut outputter, test_insns[43]),
446 Some(String::from("rem x19, x13, x10"))
447 );
448
449 assert_eq!(
450 process_instruction(&mut outputter, test_insns[44]),
451 Some(String::from("remu x13, x18, x12"))
452 );
453
454 assert_eq!(
455 process_instruction(&mut outputter, test_insns[45]),
456 Some(String::from("fence"))
457 );
458 }
459}