1use core::fmt::{self, Write};
2
3use super::{
4 decode::{Decoder, Instruction},
5 opcodes::Encoding,
6 opcodes::OPCODE_STR,
7 Opcode,
8};
9
10pub struct Formatter {
11 abi_names: bool,
12}
13
14impl Formatter {
15 pub const fn new() -> Self {
16 Self { abi_names: !true }
17 }
18
19 fn write_reg<W: Write>(&self, out: &mut W, f: bool, vec: bool, reg: u32) -> fmt::Result {
20 if vec && self.abi_names {
21 match reg {
22 0..=7 => write!(out, "v{}", reg),
23 8..=15 => write!(out, "vs{}", reg - 8),
24 16..=31 => write!(out, "v{}", reg),
25 _ => write!(out, "<invalid>"),
26 }?;
27 } else if vec {
28 write!(out, "v{}", reg)?;
29 }
30
31 if f && self.abi_names {
32 match reg {
33 0 => write!(out, "ft0"),
34 1 => write!(out, "ft1"),
35 2 => write!(out, "ft2"),
36 3 => write!(out, "ft3"),
37 4 => write!(out, "ft4"),
38 5 => write!(out, "ft5"),
39 6 => write!(out, "ft6"),
40 7 => write!(out, "ft7"),
41 8 => write!(out, "fs0"),
42 9 => write!(out, "fs1"),
43 10 => write!(out, "fa0"),
44 11 => write!(out, "fa1"),
45 12 => write!(out, "fa2"),
46 13 => write!(out, "fa3"),
47 14 => write!(out, "fa4"),
48 15 => write!(out, "fa5"),
49 16 => write!(out, "fa6"),
50 17 => write!(out, "fa7"),
51 18 => write!(out, "fs2"),
52 19 => write!(out, "fs3"),
53 20 => write!(out, "fs4"),
54 21 => write!(out, "fs5"),
55 22 => write!(out, "fs6"),
56 23 => write!(out, "fs7"),
57 24 => write!(out, "fs8"),
58 25 => write!(out, "fs9"),
59 26 => write!(out, "fs10"),
60 27 => write!(out, "fs11"),
61 28 => write!(out, "ft8"),
62 29 => write!(out, "ft9"),
63 30 => write!(out, "ft10"),
64 31 => write!(out, "ft11"),
65 _ => write!(out, "<invalid>"),
66 }
67 } else if f {
68 write!(out, "f{}", reg)
69 } else {
70 if self.abi_names {
71 match reg {
72 0 => write!(out, "zero"),
73 1 => write!(out, "ra"),
74 2 => write!(out, "sp"),
75 3 => write!(out, "gp"),
76 4 => write!(out, "tp"),
77 5 => write!(out, "t0"),
78 6 => write!(out, "t1"),
79 7 => write!(out, "t2"),
80 8 => write!(out, "s0"),
81 9 => write!(out, "s1"),
82 10 => write!(out, "a0"),
83 11 => write!(out, "a1"),
84 12 => write!(out, "a2"),
85 13 => write!(out, "a3"),
86 14 => write!(out, "a4"),
87 15 => write!(out, "a5"),
88 16 => write!(out, "a6"),
89 17 => write!(out, "a7"),
90 18 => write!(out, "s2"),
91 19 => write!(out, "s3"),
92 20 => write!(out, "s4"),
93 21 => write!(out, "s5"),
94 22 => write!(out, "s6"),
95 23 => write!(out, "s7"),
96 24 => write!(out, "s8"),
97 25 => write!(out, "s9"),
98 26 => write!(out, "s10"),
99 27 => write!(out, "s11"),
100 28 => write!(out, "t3"),
101 29 => write!(out, "t4"),
102 30 => write!(out, "t5"),
103 31 => write!(out, "t6"),
104 _ => write!(out, "<invalid>"),
105 }
106 } else {
107 write!(out, "x{}", reg)
108 }
109 }
110 }
111
112 fn write_rlist<W: Write>(&self, out: &mut W, rlist: u32) -> fmt::Result {
113 for i in [27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 9, 8, 1] {
114 if rlist & (1 << i) != 0 {
115 self.write_reg(out, false, false, i)?;
116 write!(out, " ")?;
117 }
118 }
119
120 Ok(())
121 }
122
123 pub fn format<W: Write>(&self, out: &mut W, inst: &Instruction) -> fmt::Result {
124 let encoding = inst.code.encoding();
125 let mnem = OPCODE_STR[inst.code as usize];
126
127 write!(out, "{}", mnem)?;
128
129 match encoding {
130 Encoding::Bimm12HiRs1Bimm12lo => {
131 write!(out, " ")?;
132 self.write_reg(out, false, false, inst.value.rs1())?;
133 let addr = inst.address as isize as isize + inst.value.bimm12lohi() as isize;
134 write!(out, ", {:x}", addr)?;
135 }
136
137 Encoding::Bimm12HiRs1Rs2Bimm12lo => {
138 write!(out, " ")?;
139 self.write_reg(out, false, false, inst.value.rs1())?;
140 write!(out, ", ")?;
141 self.write_reg(out, false, false, inst.value.rs2())?;
142 let addr = inst.address as isize + inst.value.bimm12lohi() as isize;
143 write!(out, ", {:x}", addr)?;
144 }
145
146 Encoding::Bimm12HiRs2Bimm12lo => {
147 write!(out, " ")?;
148 self.write_reg(out, false, false, inst.value.rs2())?;
149 let addr =
150 inst.address as isize + inst.len as isize + inst.value.bimm12lohi() as isize;
151 write!(out, ", {:x}", addr)?;
152 }
153
154 Encoding::Bimm12HiRs2Rs1Bimm12lo => {
155 write!(out, " ")?;
156 self.write_reg(out, false, false, inst.value.rs2())?;
157 write!(out, ", ")?;
158 self.write_reg(out, false, false, inst.value.rs1())?;
159 let addr =
160 inst.address as isize + inst.len as isize + inst.value.bimm12lohi() as isize;
161 write!(out, ", {:x}", addr)?;
162 }
163
164 Encoding::CImm12 => {
165 write!(out, " ")?;
166 let addr = inst.address as i64 + inst.value.c_imm12() as i64;
167 write!(out, "{:x}", addr)?;
168 }
169
170 Encoding::CIndex => {
171 write!(out, " ")?;
172 write!(out, "{}", inst.value.c_index())?;
173 }
174
175 Encoding::CMopT => {
176 write!(out, " ")?;
177 write!(out, "{}", inst.value.c_mop_t())?;
178 }
179
180 Encoding::CNzimm10hiCNzimm10lo => {
181 write!(out, " ")?;
182 write!(out, "{}", inst.value.c_nzimm10lohi())?;
183 }
184
185 Encoding::CNzimm6hiCNzimm6lo => {
186 write!(out, " ")?;
187 write!(out, "{}", inst.value.c_nzimm6lohi())?;
188 }
189
190 Encoding::CRlistCSpimm => {
191 write!(out, " ")?;
192 let rlist = inst.value.c_rlist();
193 self.write_rlist(out, rlist)?;
194 write!(out, " {}", inst.value.c_spimm())?;
195 }
196
197 Encoding::CRs1N0 => {
198 write!(out, " ")?;
199 self.write_reg(out, false, false, inst.value.c_rs1_n0())?;
200 }
201
202 Encoding::CRs2CUimm8spS => {
203 write!(out, " ")?;
204 self.write_reg(out, false, false, inst.value.c_rs2())?;
205 write!(out, ", ")?;
206 write!(out, "{}", inst.value.c_uimm8sp_s())?;
207 }
208
209 Encoding::CRs2CUimm9spS => {
210 write!(out, " ")?;
211 self.write_reg(out, false, false, inst.value.c_rs2())?;
212 write!(out, ", ")?;
213 write!(out, "{}", inst.value.c_uimm9sp_s())?;
214 }
215
216 Encoding::CSreg1CSreg2 => {
217 write!(out, " ")?;
219 self.write_reg(out, false, false, inst.value.c_sreg1())?;
220 write!(out, ", ")?;
221 self.write_reg(out, false, false, inst.value.c_sreg2())?;
222 }
223
224 Encoding::CsrZimm => {
225 let zimm = inst.value.zimm();
226 write!(out, " ")?;
227 write!(out, "csr{}, {}", inst.value.csr(), zimm)?;
228 }
229
230 Encoding::Empty => {}
231 Encoding::FmPredSuccRs1Rd => {
232 write!(out, " ")?;
233 self.write_reg(out, false, false, inst.value.rd())?;
234 write!(out, ", ")?;
235 self.write_reg(out, false, false, inst.value.rs1())?;
236 write!(out, ", ")?;
237 write!(out, "{}", inst.value.pred())?;
238 write!(out, ", ")?;
239 write!(out, "{}", inst.value.succ())?;
240 }
241
242 Encoding::Imm12HiRs1Rs2Imm12lo => {
244 write!(out, " ")?;
245 let f = matches!(
246 inst.code,
247 Opcode::FSD | Opcode::FSH | Opcode::FSQ | Opcode::FSW
248 );
249 self.write_reg(out, f, false, inst.value.rs2())?;
250
251 write!(out, ", {}(", inst.value.imm12lohi())?;
252 self.write_reg(out, false, false, inst.value.rs1())?;
253 write!(out, ")")?;
254 }
255
256 Encoding::Imm12Rs1Rd => {
257 write!(out, " ")?;
258 self.write_reg(out, false, false, inst.value.rd())?;
259 write!(out, ", ")?;
260 self.write_reg(out, false, false, inst.value.rs1())?;
261 write!(out, ", ")?;
262 write!(out, "{}", inst.value.imm12())?;
263 }
264
265 Encoding::Jimm20 => {
266 write!(out, " ")?;
267 let addr = inst.address as i64 + inst.value.jimm20() as i64;
268 write!(out, "{:x}", addr)?;
269 }
270 Encoding::RdJimm20 => {
271 write!(out, " ")?;
272 self.write_reg(out, false, false, inst.value.rd())?;
273 write!(out, ", ")?;
274 let addr = inst.address as i64 + inst.value.jimm20() as i64;
275 write!(out, "{:x}", addr)?;
276 }
277 Encoding::MopRT30MopRT2726MopRT2120RdRs1 => {
278 write!(out, " ")?;
279 self.write_reg(out, false, false, inst.value.rd())?;
280 write!(out, ", ")?;
281 self.write_reg(out, false, false, inst.value.rs1())?;
282 }
283
284 Encoding::MopRrT30MopRrT2726RdRs1Rs2 => {
285 todo!()
286 }
287
288 Encoding::NfVmRs1Vd => {
289 let vd = inst.value.vd();
290 let vm = inst.value.vm();
291 let rs1 = inst.value.rs1();
292
293 write!(out, " ")?;
294 self.write_reg(out, false, true, vd)?;
295 write!(out, ", (")?;
296 self.write_reg(out, false, false, rs1)?;
297 write!(out, ")")?;
298 if vm == 0 {
299 write!(out, ", ")?;
300 write!(out, "v{}.t", vm)?;
301 }
302 }
303
304 Encoding::NfVmRs1Vs3 => {
305 let vs3 = inst.value.vs3();
306 let vm = inst.value.vm();
307 let rs1 = inst.value.rs1();
308
309 write!(out, " ")?;
310 self.write_reg(out, false, true, vs3)?;
311 write!(out, ", (")?;
312 self.write_reg(out, false, false, rs1)?;
313 write!(out, ")")?;
314 if vm == 0 {
315 write!(out, ", ")?;
316 write!(out, "v{}.t", vm)?;
317 }
318 }
319
320 Encoding::NfVmRs2Rs1Vd => {
322 let vd = inst.value.vd();
323 let vm = inst.value.vm();
324 let rs1 = inst.value.rs1();
325 let rs2 = inst.value.rs2();
326
327 write!(out, " ")?;
328 self.write_reg(out, false, true, vd)?;
329 write!(out, ", (")?;
330 self.write_reg(out, false, false, rs1)?;
331 write!(out, "), ")?;
332 self.write_reg(out, false, false, rs2)?;
333 if vm == 0 {
334 write!(out, ", ")?;
335 write!(out, "v{}.t", vm)?;
336 }
337 }
338
339 Encoding::NfVmRs2Rs1Vs3 => {
341 let vs3 = inst.value.vs3();
342 let vm = inst.value.vm();
343 let rs1 = inst.value.rs1();
344 let rs2 = inst.value.rs2();
345
346 write!(out, " ")?;
347 self.write_reg(out, false, true, vs3)?;
348 write!(out, ", (")?;
349 self.write_reg(out, false, false, rs1)?;
350 write!(out, "), ")?;
351 self.write_reg(out, false, false, rs2)?;
352 if vm == 0 {
353 write!(out, ", ")?;
354 write!(out, "v{}.t", vm)?;
355 }
356 }
357
358 Encoding::NfVmVs2Rs1Vd => {
360 let vd = inst.value.vd();
361 let vm = inst.value.vm();
362 let rs1 = inst.value.rs1();
363 let vs2 = inst.value.vs2();
364
365 write!(out, " ")?;
366 self.write_reg(out, false, true, vd)?;
367 write!(out, ", (")?;
368 self.write_reg(out, false, false, rs1)?;
369 write!(out, "), ")?;
370 self.write_reg(out, false, true, vs2)?;
371 if vm == 0 {
372 write!(out, ", ")?;
373 write!(out, "v{}.t", vm)?;
374 }
375 }
376
377 Encoding::NfVmVs2Rs1Vs3 => {
378 let vs3 = inst.value.vs3();
379 let vm = inst.value.vm();
380 let rs1 = inst.value.rs1();
381 let vs2 = inst.value.vs2();
382
383 write!(out, " ")?;
384 self.write_reg(out, false, true, vs3)?;
385 write!(out, ", (")?;
386 self.write_reg(out, false, false, rs1)?;
387 write!(out, "), ")?;
388 self.write_reg(out, false, true, vs2)?;
389 if vm == 0 {
390 write!(out, ", ")?;
391 write!(out, "v{}.t", vm)?;
392 }
393 }
394
395 Encoding::Rd => {
396 write!(out, " ")?;
397 self.write_reg(out, false, false, inst.value.rd())?;
398 }
399
400 Encoding::RdCUimm9sphiCUimm9splo => {
401 write!(out, " ")?;
402 self.write_reg(out, false, false, inst.value.rd())?;
403 write!(out, ", ")?;
404 write!(out, "{}", inst.value.c_uimm9splohi())?;
405 }
406
407 Encoding::RdCsrZimm => {
408 write!(out, " ")?;
409 self.write_reg(out, false, false, inst.value.rd())?;
410 write!(out, ", ")?;
411 write!(out, "csr{}, {}", inst.value.csr(), inst.value.zimm())?;
412 }
413
414 Encoding::RdImm20 => {
415 write!(out, " ")?;
416 self.write_reg(out, false, false, inst.value.rd())?;
417 write!(out, ", ")?;
418 write!(out, "{}", inst.value.imm20())?;
419 }
420
421 Encoding::RdN0CImm6loCImm6hi => {
422 write!(out, " ")?;
423 self.write_reg(out, false, false, inst.value.rd())?;
424 write!(out, ", ")?;
425 write!(out, "{}", inst.value.c_imm6lohi())?;
426 }
427
428 Encoding::RdN0CRs2N0 => {
429 write!(out, " ")?;
430 self.write_reg(out, false, false, inst.value.rd())?;
431 write!(out, ", ")?;
432 self.write_reg(out, false, false, inst.value.rs2())?;
433 }
434
435 Encoding::RdN0CUimm8sphiCUimm8splo => {
436 write!(out, " ")?;
437 self.write_reg(out, false, false, inst.value.rd())?;
438 write!(out, ", ")?;
439 write!(out, "{}", inst.value.c_uimm8splohi())?;
440 }
441
442 Encoding::RdN0CUimm9sphiCUimm9splo => {
443 write!(out, " ")?;
444 self.write_reg(out, false, false, inst.value.rd())?;
445 write!(out, ", ")?;
446 write!(out, "{}", inst.value.c_uimm9splohi())?;
447 }
448
449 Encoding::RdN2CNzimm18hiCNzimm18lo => {
450 write!(out, " ")?;
451 self.write_reg(out, false, false, inst.value.rd())?;
452 write!(out, ", ")?;
453 write!(out, "{}", inst.value.c_nzimm18lohi())?;
454 }
455
456 Encoding::RdPCNzuimm10 => {
457 write!(out, " ")?;
458 self.write_reg(out, false, false, inst.value.rd())?;
459 write!(out, ", ")?;
460 write!(out, "{}", inst.value.c_nzuimm10())?;
461 }
462
463 Encoding::RdPRs1PCUimm1 => {
464 write!(out, " ")?;
465 self.write_reg(out, false, false, inst.value.rd())?;
466 write!(out, ", ")?;
467 self.write_reg(out, false, false, inst.value.rs1())?;
468 write!(out, ", ")?;
469 write!(out, "{}", inst.value.c_uimm1())?;
470 }
471
472 Encoding::RdPRs1PCUimm2 => {
473 write!(out, " ")?;
474 self.write_reg(out, false, false, inst.value.rd())?;
475 write!(out, ", ")?;
476 self.write_reg(out, false, false, inst.value.rs1())?;
477 write!(out, ", ")?;
478 write!(out, "{}", inst.value.c_uimm2())?;
479 }
480
481 Encoding::RdPRs1PCUimm7loCUimm7hi => {
482 write!(out, " ")?;
483 self.write_reg(out, false, false, inst.value.rd())?;
484 write!(out, ", ")?;
485 self.write_reg(out, false, false, inst.value.rs1())?;
486 write!(out, ", {}", inst.value.c_uimm7lohi())?;
487 }
488
489 Encoding::RdPRs1PCUimm8loCUimm8hi => {
490 write!(out, " ")?;
491 self.write_reg(out, false, false, inst.value.rd_p() + 8)?;
492 write!(out, ", ")?;
493
494 self.write_reg(
495 out,
496 matches!(inst.code, Opcode::CFLD),
497 false,
498 inst.value.rs1_p() + 8,
499 )?;
500 write!(out, ", {}", inst.value.c_uimm8lohi())?;
501 }
502
503 Encoding::RdRs1 => match inst.code {
504 Opcode::FLID | Opcode::FLIQ | Opcode::FLIH | Opcode::FLIS => {
505 self.format_fli(out, inst)?;
506 }
507
508 Opcode::FMVDX | Opcode::FMVHX | Opcode::FMVPQX | Opcode::FMVSX => {
509 write!(out, " ")?;
510 self.write_reg(out, true, false, inst.value.rd())?;
511 write!(out, ", ")?;
512 self.write_reg(out, false, false, inst.value.rs1())?;
513 }
514
515 Opcode::FMVXD | Opcode::FMVXS | Opcode::FMVXH | Opcode::FMVXW => {
516 write!(out, " ")?;
517 self.write_reg(out, false, false, inst.value.rd())?;
518 write!(out, ", ")?;
519 self.write_reg(out, true, false, inst.value.rs1())?;
520 }
521
522 Opcode::FCLASSD | Opcode::FCLASSH | Opcode::FCLASSQ | Opcode::FCLASSS => {
523 write!(out, " ")?;
524 self.write_reg(out, false, false, inst.value.rd())?;
525 write!(out, ", ")?;
526 self.write_reg(out, true, false, inst.value.rs1())?;
527 }
528
529 _ => {
530 write!(out, " ")?;
531 self.write_reg(out, false, false, inst.value.rd())?;
532 write!(out, ", ")?;
533 self.write_reg(out, false, false, inst.value.rs1())?;
534 }
535 },
536
537 Encoding::RdRs1AqRl => {
538 write!(out, " ")?;
539 self.write_reg(out, false, false, inst.value.rd())?;
540 write!(out, ", ")?;
541 self.write_reg(out, false, false, inst.value.rs1())?;
542 }
543 Encoding::RdRs1Csr => {
545 write!(out, " ")?;
546 self.write_reg(out, false, false, inst.value.rd())?;
547 write!(out, ", ")?;
548 write!(out, "csr{}, ", inst.value.csr())?;
549 self.write_reg(out, false, false, inst.value.rs1())?;
550 }
551
552 Encoding::RdRs1Imm12 => {
554 let is_float = matches!(
555 inst.code,
556 Opcode::FLD | Opcode::FLH | Opcode::FLQ | Opcode::FLW
557 );
558
559 write!(out, " ")?;
560 self.write_reg(out, is_float, false, inst.value.rd())?;
561 write!(out, ", ")?;
562 match inst.code {
566 Opcode::FLD
567 | Opcode::FLH
568 | Opcode::FLQ
569 | Opcode::FLW
570 | Opcode::LB
571 | Opcode::LBU
572 | Opcode::LD
573 | Opcode::LH
574 | Opcode::LHU
575 | Opcode::LW
576 | Opcode::LWU => {
577 write!(out, "{}(", inst.value.imm12())?;
578 self.write_reg(out, false, false, inst.value.rs1())?;
579 write!(out, ")")?;
580 }
581
582 _ => {
583 self.write_reg(out, false, false, inst.value.rs1())?;
584 write!(out, ", {}", inst.value.imm12())?;
585 }
586 }
587 }
588
589 Encoding::RdRs1N0CImm6loCImm6hi => {
591 write!(out, " ")?;
592 self.write_reg(out, false, false, inst.value.rd())?;
593 write!(out, ", ")?;
594 self.write_reg(out, false, false, inst.value.rs1())?;
595 write!(out, ", ")?;
596 write!(out, "{}", inst.value.c_imm6lohi())?;
597 }
598
599 Encoding::RdRs1N0CNzimm6loCNzimm6hi => {
601 write!(out, " ")?;
602 self.write_reg(out, false, false, inst.value.rd())?;
603 write!(out, ", ")?;
604 self.write_reg(out, false, false, inst.value.rs1())?;
605 write!(out, ", ")?;
606 write!(out, "{}", inst.value.c_nzimm6lohi())?;
607 }
608
609 Encoding::RdRs1N0CNzuimm6hiCNzuimm6lo => {
611 write!(out, " ")?;
612 self.write_reg(out, false, false, inst.value.rd())?;
613 write!(out, ", ")?;
614 self.write_reg(out, false, false, inst.value.rs1())?;
615 write!(out, ", ")?;
616 write!(out, "{}", inst.value.c_nzuimm6lohi())?;
617 }
618
619 Encoding::RdRs1N0CRs2N0 => {
620 write!(out, " ")?;
621 self.write_reg(out, false, false, inst.value.rd())?;
622 write!(out, ", ")?;
623 self.write_reg(out, false, false, inst.value.rs1())?;
624 write!(out, ", ")?;
625 self.write_reg(out, false, false, inst.value.c_rs2())?;
626 }
627
628 Encoding::RdRs1P => {
629 write!(out, " ")?;
630 self.write_reg(out, false, false, inst.value.rd())?;
631 write!(out, ", ")?;
632 self.write_reg(out, false, false, inst.value.rs1_p())?;
633 }
634
635 Encoding::RdRs1PCImm6hiCImm6lo => {
636 write!(out, " ")?;
637 self.write_reg(out, false, false, inst.value.rd())?;
638 write!(out, ", ")?;
639 self.write_reg(out, false, false, inst.value.rs1())?;
640 write!(out, ", ")?;
641 write!(out, "{}", inst.value.c_imm6lohi())?;
642 }
643
644 Encoding::RdRs1PRs2P => {
645 write!(out, " ")?;
646 self.write_reg(out, false, false, inst.value.rd())?;
647 write!(out, ", ")?;
648 self.write_reg(out, false, false, inst.value.rs1_p())?;
649 write!(out, ", ")?;
650 self.write_reg(out, false, false, inst.value.rs2_p())?;
651 }
652
653 Encoding::RdRs1Rm => {
654 let (rd_is_f, rs1_is_f) = match inst.code {
655 Opcode::FCVTDH => (true, true),
656 Opcode::FCVTDL => (true, false),
657 Opcode::FCVTDLU => (true, false),
658 Opcode::FCVTDQ => (true, true),
659 Opcode::FCVTDS => (true, true),
660 Opcode::FCVTDW => (true, false),
661 Opcode::FCVTDWU => (true, false),
662 Opcode::FCVTHD => (true, true),
663 Opcode::FCVTHL => (true, false),
664 Opcode::FCVTHLU => (true, false),
665 Opcode::FCVTHQ => (true, true),
666 Opcode::FCVTHS => (true, true),
667 Opcode::FCVTHW => (true, false),
668 Opcode::FCVTHWU => (true, false),
669 Opcode::FCVTLD => (false, true),
670 Opcode::FCVTLUD => (false, true),
671 Opcode::FCVTLUH => (false, true),
672
673 Opcode::FCVTLH => (false, true),
674 Opcode::FCVTLQ => (false, true),
675 Opcode::FCVTLS => (false, true),
676 Opcode::FCVTLUQ => (false, true),
677 Opcode::FCVTLUS => (false, true),
678 Opcode::FCVTQD => (true, true),
679 Opcode::FCVTQH => (true, true),
680 Opcode::FCVTQL => (true, false),
681 Opcode::FCVTQLU => (true, false),
682 Opcode::FCVTQS => (true, true),
683 Opcode::FCVTQW => (true, false),
684 Opcode::FCVTQWU => (true, false),
685 Opcode::FCVTSD => (true, true),
686 Opcode::FCVTSH => (true, true),
687 Opcode::FCVTSL => (true, false),
688 Opcode::FCVTSLU => (true, false),
689 Opcode::FCVTSQ => (true, true),
690 Opcode::FCVTSW => (true, false),
691 Opcode::FCVTSWU => (true, false),
692 Opcode::FCVTWD => (false, true),
693 Opcode::FCVTWH => (false, true),
694 Opcode::FCVTWQ => (false, true),
695 Opcode::FCVTWS => (false, true),
696 Opcode::FCVTWUD => (false, true),
697 Opcode::FCVTWUH => (false, true),
698 Opcode::FCVTWUQ => (false, true),
699 Opcode::FCVTWUS => (false, true),
700 _ => (true, true),
701 };
702
703 write!(out, " ")?;
704 self.write_reg(out, rd_is_f, false, inst.value.rd())?;
705 write!(out, ", ")?;
706 self.write_reg(out, rs1_is_f, false, inst.value.rs1())?;
707 }
708 Encoding::RdRs1Rs2 => {
709 write!(out, " ")?;
710 let is_f = mnem.starts_with("f");
711
712 self.write_reg(out, is_f, false, inst.value.rd())?;
713 write!(out, ", ")?;
714 self.write_reg(out, is_f, false, inst.value.rs1())?;
715 write!(out, ", ")?;
716 self.write_reg(out, is_f, false, inst.value.rs2())?;
717 }
718 Encoding::RdRs1Shamtd => {
719 write!(out, " ")?;
720 self.write_reg(out, false, false, inst.value.rd())?;
721 write!(out, ", ")?;
722 self.write_reg(out, false, false, inst.value.rs1())?;
723 write!(out, ", {}", inst.value.shamtd())?;
724 }
725
726 Encoding::Rs1PRs2PCUimm8loCUimm8hi => {
727 write!(out, " ")?;
728 self.write_reg(out, false, false, inst.value.rs1_p())?;
729 write!(out, ", ")?;
730 self.write_reg(out, false, false, inst.value.rs2_p())?;
731 write!(out, ", {}", inst.value.c_uimm8lohi())?;
732 }
733
734 Encoding::RdRs1Rs2Rs3Rm => {
735 write!(out, " ")?;
736 self.write_reg(out, false, false, inst.value.rd())?;
737 write!(out, ", ")?;
738 self.write_reg(out, false, false, inst.value.rs1())?;
739 write!(out, ", ")?;
740 self.write_reg(out, false, false, inst.value.rs2())?;
741 write!(out, ", ")?;
742 self.write_reg(out, false, false, inst.value.rs3())?;
743 }
744
745 Encoding::Rs1PRs2PCUimm7loCUimm7hi => {
746 write!(out, " ")?;
747 self.write_reg(out, false, false, inst.value.rs1_p())?;
748 write!(out, ", ")?;
749 self.write_reg(out, false, false, inst.value.rs2_p())?;
750 write!(out, ", {}", inst.value.c_uimm7lohi())?;
751 }
752
753 Encoding::Rs1PRs2PCUimm8hiCUimm8lo => {
754 write!(out, " ")?;
755 self.write_reg(out, false, false, inst.value.rs1_p())?;
756 write!(out, ", ")?;
757 self.write_reg(out, false, false, inst.value.rs2_p())?;
758 write!(out, ", {}", inst.value.c_uimm8lohi())?;
759 }
760 _ => todo!("{:?}", encoding),
761 }
762
763 Ok(())
764 }
765
766 fn format_fli<W: Write>(&self, out: &mut W, inst: &Instruction) -> fmt::Result {
767 let rs1 = inst.value.rs1();
768 let c = match rs1 {
769 0 => "-1.0",
770 1 => "0.0",
771 2 => "1.0*2^-16",
772 3 => "1.0*2^-15",
773 4 => "1.0*2^-8",
774 5 => "1.0*2^-7",
775 6 => "0.0625",
776 7 => "0.125",
777 8 => "0.25",
778 9 => "0.3125",
779 10 => "0.375",
780 11 => "0.4375",
781 12 => "0.5",
782 13 => "0.625",
783 14 => "0.75",
784 15 => "0.875",
785 16 => "1.0",
786 17 => "1.25",
787 18 => "1.5",
788 19 => "1.75",
789 20 => "2.0",
790 21 => "2.5",
791 22 => "3",
792 23 => "4",
793 24 => "8",
794 25 => "16",
795 26 => "128",
796 27 => "256",
797 28 => "2^15",
798 29 => "2^16",
799 30 => "+inf",
800 31 => "NaN",
801 _ => "<invalid>",
802 };
803
804 write!(out, " ")?;
805 self.write_reg(out, true, false, inst.value.rd())?;
806 write!(out, ", {}", c)
807 }
808}
809
810pub fn pretty_disassembler<W: Write>(
811 out: &mut W,
812 bitness: usize,
813 data: &[u8],
814 address: u64,
815) -> fmt::Result {
816 let mut decoder = Decoder::new(bitness, data, address);
817 let mut fmt = Formatter::new();
818 fmt.abi_names = true;
819
820 let mut inst = Instruction::default();
821
822 while decoder.can_decode() {
823 decoder.decode_out(&mut inst);
824
825 write!(out, "{:016x}: {:08x} ", inst.address, inst.value.value)?;
826
827 fmt.format(out, &inst)?;
828 write!(out, "\n")?;
829 }
830 Ok(())
831}