1use core::fmt::{self, Display, Write};
10
11use crate::csr::csr_name;
12use crate::instruction::Instruction;
13use crate::opcodes::zfa::FLI_CONSTANTS;
14use crate::reg::{FP_NAMES, INT_NAMES};
15
16impl Display for Instruction {
17 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
20 let name = self.op.name;
23 let name = match (self.aq || self.rl)
24 .then(|| name.strip_suffix(".aq").or(name.strip_suffix(".rl")))
25 {
26 Some(Some(base)) => base,
27 _ => name,
28 };
29 f.write_str(name)?;
30 match (self.aq, self.rl) {
31 (true, true) => f.write_str(".aqrl")?,
32 (true, false) => f.write_str(".aq")?,
33 (false, true) => f.write_str(".rl")?,
34 (false, false) => {}
35 }
36 if !self.op.format.is_empty() {
37 write!(f, " {}", self.operands())?;
38 }
39 Ok(())
40 }
41}
42
43#[derive(Clone, Copy, Debug)]
47pub struct Operands<'a>(pub(crate) &'a Instruction);
48
49impl Display for Operands<'_> {
50 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51 let ins = self.0;
52 for c in ins.op.format.chars() {
53 write_part(f, ins, c)?;
54 }
55 Ok(())
56 }
57}
58
59fn write_part(out: &mut fmt::Formatter<'_>, ins: &Instruction, c: char) -> fmt::Result {
62 let fp_names = if ins.fp_in_x { &INT_NAMES } else { &FP_NAMES };
64 match c {
65 '(' | ',' | ' ' | ')' | '-' => out.write_char(c),
66 'L' => match ins.rs1 {
67 4 => out.write_str("{ra}"),
68 5 => out.write_str("{ra,s0}"),
69 15 => out.write_str("{ra,s0-s11}"),
70 rlist => write!(out, "{{ra,s0-s{}}}", rlist - 5),
71 },
72 '0' => out.write_str(reg(&INT_NAMES, ins.rd)),
73 '1' => out.write_str(reg(&INT_NAMES, ins.rs1)),
74 '2' => out.write_str(reg(&INT_NAMES, ins.rs2)),
75 '3' => out.write_str(reg(fp_names, ins.rd)),
76 '4' => out.write_str(reg(fp_names, ins.rs1)),
77 '5' => out.write_str(reg(fp_names, ins.rs2)),
78 '6' => out.write_str(reg(fp_names, ins.rs3)),
79 '7' => write!(out, "{}", ins.rs1),
80 'i' => write!(out, "{}", ins.imm),
81 'j' => write!(out, "{}", ins.imm2),
82 '>' => write!(out, "{:#x}", ins.imm),
83 'u' => write!(out, "{:#x}", (ins.imm as u32 >> 12) & 0xfffff),
84 'o' => write!(out, "{:#x}", ins.target()),
85 'c' => match csr_name(ins.imm as u16 & 0xfff) {
86 Some(name) => out.write_str(name),
87 None => write!(out, "{:#x}", ins.imm & 0xfff),
88 },
89 'r' if ins.rm == 7 => Ok(()),
90 'R' if ins.rm == 0 => Ok(()),
91 'r' | 'R' => {
92 let names = [
93 "rne", "rtz", "rdn", "rup", "rmm", "unknown", "unknown", "dyn",
94 ];
95 write!(out, ",{}", names[ins.rm as usize & 7])
96 }
97 'P' => write!(out, "{}", ins.imm & !0x1f),
98 'D' => write!(out, "v{}", ins.rd),
99 'A' => write!(out, "v{}", ins.rs1),
100 'B' => write!(out, "v{}", ins.rs2),
101 'M' if ins.masked => out.write_str(",v0.t"),
102 'M' => Ok(()),
103 'Z' => out.write_str("v0"),
104 'T' => write_vtype(out, ins.imm as u32),
105 'F' => out.write_str(FLI_CONSTANTS[ins.rs1 as usize & 31]),
106 'l' => write!(out, "{}", ins.len),
107 'x' => {
108 let parcels = (64 - ins.inst.leading_zeros()).div_ceil(16).max(1) as usize;
110 write!(out, "0x{:01$x}", ins.inst, parcels * 4)
111 }
112 'p' => write_fence_set(out, ins.pred),
113 's' => write_fence_set(out, ins.succ),
114 _ => {
117 debug_assert!(false, "unknown format character {c:?}");
118 Ok(())
119 }
120 }
121}
122
123fn reg(names: &'static [&'static str; 32], r: u8) -> &'static str {
125 names[r as usize & 31]
126}
127
128fn write_vtype(out: &mut fmt::Formatter<'_>, vtype: u32) -> fmt::Result {
131 let (sew, lmul) = ((vtype >> 3) & 7, vtype & 7);
132 let lmul = ["m1", "m2", "m4", "m8", "", "mf8", "mf4", "mf2"][lmul as usize];
134 if vtype >> 8 != 0 || sew > 3 || lmul.is_empty() {
135 return write!(out, "{vtype}");
136 }
137 let tail = if vtype & 0x40 != 0 { "ta" } else { "tu" };
138 let mask = if vtype & 0x80 != 0 { "ma" } else { "mu" };
139 write!(out, "e{},{lmul},{tail},{mask}", 8 << sew)
140}
141
142fn write_fence_set(out: &mut fmt::Formatter<'_>, set: u8) -> fmt::Result {
145 if set == 0 {
146 return out.write_str("unknown");
147 }
148 for (bit, name) in [(8, 'i'), (4, 'o'), (2, 'r'), (1, 'w')] {
149 if set & bit != 0 {
150 out.write_char(name)?;
151 }
152 }
153 Ok(())
154}