1use core::fmt::{self, Display, Write};
10
11use crate::csr::csr_name;
12use crate::instruction::Instruction;
13use crate::reg::{FP_NAMES, INT_NAMES};
14
15impl Display for Instruction {
16 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
19 f.write_str(self.op.name)?;
20 match (self.aq, self.rl) {
21 (true, true) => f.write_str(".aqrl")?,
22 (true, false) => f.write_str(".aq")?,
23 (false, true) => f.write_str(".rl")?,
24 (false, false) => {}
25 }
26 if !self.op.format.is_empty() {
27 write!(f, " {}", self.operands())?;
28 }
29 Ok(())
30 }
31}
32
33#[derive(Clone, Copy, Debug)]
37pub struct Operands<'a>(pub(crate) &'a Instruction);
38
39impl Display for Operands<'_> {
40 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41 let ins = self.0;
42 for c in ins.op.format.chars() {
43 write_part(f, ins, c)?;
44 }
45 Ok(())
46 }
47}
48
49fn write_part(out: &mut fmt::Formatter<'_>, ins: &Instruction, c: char) -> fmt::Result {
52 match c {
53 '(' | ',' | ' ' | ')' => out.write_char(c),
54 '0' => out.write_str(INT_NAMES[ins.rd as usize]),
55 '1' => out.write_str(INT_NAMES[ins.rs1 as usize]),
56 '2' => out.write_str(INT_NAMES[ins.rs2 as usize]),
57 '3' => out.write_str(FP_NAMES[ins.rd as usize]),
58 '4' => out.write_str(FP_NAMES[ins.rs1 as usize]),
59 '5' => out.write_str(FP_NAMES[ins.rs2 as usize]),
60 '6' => out.write_str(FP_NAMES[ins.rs3 as usize]),
61 '7' => write!(out, "{}", ins.rs1),
62 'i' => write!(out, "{}", ins.imm),
63 '>' => write!(out, "{:#x}", ins.imm),
64 'u' => write!(out, "{:#x}", (ins.imm as u32 >> 12) & 0xfffff),
65 'o' => write!(out, "{:#x}", ins.target()),
66 'c' => match csr_name(ins.imm as u16 & 0xfff) {
67 Some(name) => out.write_str(name),
68 None => write!(out, "{:#x}", ins.imm & 0xfff),
69 },
70 'r' if ins.rm == 7 => Ok(()),
71 'R' if ins.rm == 0 => Ok(()),
72 'r' | 'R' => {
73 let names = [
74 "rne", "rtz", "rdn", "rup", "rmm", "unknown", "unknown", "dyn",
75 ];
76 write!(out, ",{}", names[ins.rm as usize])
77 }
78 'l' => write!(out, "{}", ins.len),
79 'x' => {
80 let parcels = (64 - ins.inst.leading_zeros()).div_ceil(16).max(1) as usize;
82 write!(out, "0x{:01$x}", ins.inst, parcels * 4)
83 }
84 'p' => write_fence_set(out, ins.pred),
85 's' => write_fence_set(out, ins.succ),
86 _ => unreachable!("unknown format character {c:?}"),
87 }
88}
89
90fn write_fence_set(out: &mut fmt::Formatter<'_>, set: u8) -> fmt::Result {
93 if set == 0 {
94 return out.write_str("unknown");
95 }
96 for (bit, name) in [(8, 'i'), (4, 'o'), (2, 'r'), (1, 'w')] {
97 if set & bit != 0 {
98 out.write_char(name)?;
99 }
100 }
101 Ok(())
102}