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 =
134 inst.address as isize as isize + inst.value.bimm12lohi() as isize;
135 write!(out, ", {:x}", addr)?;
136 }
137
138 Encoding::Bimm12HiRs1Rs2Bimm12lo => {
139 write!(out, " ")?;
140 self.write_reg(out, false, false, inst.value.rs1())?;
141 write!(out, ", ")?;
142 self.write_reg(out, false, false, inst.value.rs2())?;
143 let addr =
144 inst.address as isize + inst.value.bimm12lohi() as isize;
145 write!(out, ", {:x}", addr)?;
146 }
147
148 Encoding::Bimm12HiRs2Bimm12lo => {
149 write!(out, " ")?;
150 self.write_reg(out, false, false, inst.value.rs2())?;
151 let addr =
152 inst.address as isize + inst.len as isize + inst.value.bimm12lohi() as isize;
153 write!(out, ", {:x}", addr)?;
154 }
155
156 Encoding::Bimm12HiRs2Rs1Bimm12lo => {
157 write!(out, " ")?;
158 self.write_reg(out, false, false, inst.value.rs2())?;
159 write!(out, ", ")?;
160 self.write_reg(out, false, false, inst.value.rs1())?;
161 let addr =
162 inst.address as isize + inst.len as isize + inst.value.bimm12lohi() as isize;
163 write!(out, ", {:x}", addr)?;
164 }
165
166 Encoding::CImm12 => {
167 write!(out, " ")?;
168 let addr = inst.address as i64 + inst.value.c_imm12() as i64;
169 write!(out, "{:x}", addr)?;
170 }
171
172 Encoding::CIndex => {
173 write!(out, " ")?;
174 write!(out, "{}", inst.value.c_index())?;
175 }
176
177 Encoding::CMopT => {
178 write!(out, " ")?;
179 write!(out, "{}", inst.value.c_mop_t())?;
180 }
181
182 Encoding::CNzimm10hiCNzimm10lo => {
183 write!(out, " ")?;
184 write!(out, "{}", inst.value.c_nzimm10lohi())?;
185 }
186
187 Encoding::CNzimm6hiCNzimm6lo => {
188 write!(out, " ")?;
189 write!(out, "{}", inst.value.c_nzimm6lohi())?;
190 }
191
192 Encoding::CRlistCSpimm => {
193 write!(out, " ")?;
194 let rlist = inst.value.c_rlist();
195 self.write_rlist(out, rlist)?;
196 write!(out, " {}", inst.value.c_spimm())?;
197 }
198
199 Encoding::CRs1N0 => {
200 write!(out, " ")?;
201 self.write_reg(out, false, false, inst.value.c_rs1_n0())?;
202 }
203
204 Encoding::CRs2CUimm8spS => {
205 write!(out, " ")?;
206 self.write_reg(out, false, false, inst.value.c_rs2())?;
207 write!(out, ", ")?;
208 write!(out, "{}", inst.value.c_uimm8sp_s())?;
209 }
210
211 Encoding::CRs2CUimm9spS => {
212 write!(out, " ")?;
213 self.write_reg(out, false, false, inst.value.c_rs2())?;
214 write!(out, ", ")?;
215 write!(out, "{}", inst.value.c_uimm9sp_s())?;
216 }
217
218 Encoding::CSreg1CSreg2 => {
219 write!(out, " ")?;
221 self.write_reg(out, false, false, inst.value.c_sreg1())?;
222 write!(out, ", ")?;
223 self.write_reg(out, false, false, inst.value.c_sreg2())?;
224 }
225
226 Encoding::CsrZimm => {
227 let zimm = inst.value.zimm();
228 write!(out, " ")?;
229 write!(out, "csr{}, {}", inst.value.csr(), zimm)?;
230 }
231
232 Encoding::Empty => {}
233 Encoding::FmPredSuccRs1Rd => {
234 write!(out, " ")?;
235 self.write_reg(out, false, false, inst.value.rd())?;
236 write!(out, ", ")?;
237 self.write_reg(out, false, false, inst.value.rs1())?;
238 write!(out, ", ")?;
239 write!(out, "{}", inst.value.pred())?;
240 write!(out, ", ")?;
241 write!(out, "{}", inst.value.succ())?;
242 }
243
244 Encoding::Imm12HiRs1Rs2Imm12lo => {
246 write!(out, " ")?;
247 let f = matches!(
248 inst.code,
249 Opcode::FSD | Opcode::FSH | Opcode::FSQ | Opcode::FSW
250 );
251 self.write_reg(out, f, false, inst.value.rs2())?;
252
253 write!(out, ", {}(", inst.value.imm12lohi())?;
254 self.write_reg(out, false, false, inst.value.rs1())?;
255 write!(out, ")")?;
256 }
257
258 Encoding::Imm12Rs1Rd => {
259 write!(out, " ")?;
260 self.write_reg(out, false, false, inst.value.rd())?;
261 write!(out, ", ")?;
262 self.write_reg(out, false, false, inst.value.rs1())?;
263 write!(out, ", ")?;
264 write!(out, "{}", inst.value.imm12())?;
265 }
266
267 Encoding::Jimm20 => {
268 write!(out, " ")?;
269 let addr = inst.address as i64 + inst.value.jimm20() as i64;
270 write!(out, "{:x}", addr)?;
271 }
272 Encoding::RdJimm20 => {
273 write!(out, " ")?;
274 self.write_reg(out, false, false, inst.value.rd())?;
275 write!(out, ", ")?;
276 let addr = inst.address as i64 + inst.value.jimm20() as i64;
277 write!(out, "{:x}", addr)?;
278 }
279 Encoding::MopRT30MopRT2726MopRT2120RdRs1 => {
280 write!(out, " ")?;
281 self.write_reg(out, false, false, inst.value.rd())?;
282 write!(out, ", ")?;
283 self.write_reg(out, false, false, inst.value.rs1())?;
284 }
285
286 Encoding::MopRrT30MopRrT2726RdRs1Rs2 => {
287 todo!()
288 }
289
290 Encoding::NfVmRs1Vd => {
291 let vd = inst.value.vd();
292 let vm = inst.value.vm();
293 let rs1 = inst.value.rs1();
294
295 write!(out, " ")?;
296 self.write_reg(out, false, true, vd)?;
297 write!(out, ", (")?;
298 self.write_reg(out, false, false, rs1)?;
299 write!(out, ")")?;
300 if vm == 0 {
301 write!(out, ", ")?;
302 write!(out, "v{}.t", vm)?;
303 }
304 }
305
306 Encoding::NfVmRs1Vs3 => {
307 let vs3 = inst.value.vs3();
308 let vm = inst.value.vm();
309 let rs1 = inst.value.rs1();
310
311 write!(out, " ")?;
312 self.write_reg(out, false, true, vs3)?;
313 write!(out, ", (")?;
314 self.write_reg(out, false, false, rs1)?;
315 write!(out, ")")?;
316 if vm == 0 {
317 write!(out, ", ")?;
318 write!(out, "v{}.t", vm)?;
319 }
320 }
321
322 Encoding::NfVmRs2Rs1Vd => {
324 let vd = inst.value.vd();
325 let vm = inst.value.vm();
326 let rs1 = inst.value.rs1();
327 let rs2 = inst.value.rs2();
328
329 write!(out, " ")?;
330 self.write_reg(out, false, true, vd)?;
331 write!(out, ", (")?;
332 self.write_reg(out, false, false, rs1)?;
333 write!(out, "), ")?;
334 self.write_reg(out, false, false, rs2)?;
335 if vm == 0 {
336 write!(out, ", ")?;
337 write!(out, "v{}.t", vm)?;
338 }
339 }
340
341 Encoding::NfVmRs2Rs1Vs3 => {
343 let vs3 = inst.value.vs3();
344 let vm = inst.value.vm();
345 let rs1 = inst.value.rs1();
346 let rs2 = inst.value.rs2();
347
348 write!(out, " ")?;
349 self.write_reg(out, false, true, vs3)?;
350 write!(out, ", (")?;
351 self.write_reg(out, false, false, rs1)?;
352 write!(out, "), ")?;
353 self.write_reg(out, false, false, rs2)?;
354 if vm == 0 {
355 write!(out, ", ")?;
356 write!(out, "v{}.t", vm)?;
357 }
358 }
359
360 Encoding::NfVmVs2Rs1Vd => {
362 let vd = inst.value.vd();
363 let vm = inst.value.vm();
364 let rs1 = inst.value.rs1();
365 let vs2 = inst.value.vs2();
366
367 write!(out, " ")?;
368 self.write_reg(out, false, true, vd)?;
369 write!(out, ", (")?;
370 self.write_reg(out, false, false, rs1)?;
371 write!(out, "), ")?;
372 self.write_reg(out, false, true, vs2)?;
373 if vm == 0 {
374 write!(out, ", ")?;
375 write!(out, "v{}.t", vm)?;
376 }
377 }
378
379 Encoding::NfVmVs2Rs1Vs3 => {
380 let vs3 = inst.value.vs3();
381 let vm = inst.value.vm();
382 let rs1 = inst.value.rs1();
383 let vs2 = inst.value.vs2();
384
385 write!(out, " ")?;
386 self.write_reg(out, false, true, vs3)?;
387 write!(out, ", (")?;
388 self.write_reg(out, false, false, rs1)?;
389 write!(out, "), ")?;
390 self.write_reg(out, false, true, vs2)?;
391 if vm == 0 {
392 write!(out, ", ")?;
393 write!(out, "v{}.t", vm)?;
394 }
395 }
396
397 Encoding::Rd => {
398 write!(out, " ")?;
399 self.write_reg(out, false, false, inst.value.rd())?;
400 }
401
402 Encoding::RdCUimm9sphiCUimm9splo => {
403 write!(out, " ")?;
404 self.write_reg(out, false, false, inst.value.rd())?;
405 write!(out, ", ")?;
406 write!(out, "{}", inst.value.c_uimm9splohi())?;
407 }
408
409 Encoding::RdCsrZimm => {
410 write!(out, " ")?;
411 self.write_reg(out, false, false, inst.value.rd())?;
412 write!(out, ", ")?;
413 write!(out, "csr{}, {}", inst.value.csr(), inst.value.zimm())?;
414 }
415
416 Encoding::RdImm20 => {
417 write!(out, " ")?;
418 self.write_reg(out, false, false, inst.value.rd())?;
419 write!(out, ", ")?;
420 write!(out, "{}", inst.value.imm20())?;
421 }
422
423 Encoding::RdN0CImm6loCImm6hi => {
424 write!(out, " ")?;
425 self.write_reg(out, false, false, inst.value.rd())?;
426 write!(out, ", ")?;
427 write!(out, "{}", inst.value.c_imm6lohi())?;
428 }
429
430 Encoding::RdN0CRs2N0 => {
431 write!(out, " ")?;
432 self.write_reg(out, false, false, inst.value.rd())?;
433 write!(out, ", ")?;
434 self.write_reg(out, false, false, inst.value.rs2())?;
435 }
436
437 Encoding::RdN0CUimm8sphiCUimm8splo => {
438 write!(out, " ")?;
439 self.write_reg(out, false, false, inst.value.rd())?;
440 write!(out, ", ")?;
441 write!(out, "{}", inst.value.c_uimm8splohi())?;
442 }
443
444 Encoding::RdN0CUimm9sphiCUimm9splo => {
445 write!(out, " ")?;
446 self.write_reg(out, false, false, inst.value.rd())?;
447 write!(out, ", ")?;
448 write!(out, "{}", inst.value.c_uimm9splohi())?;
449 }
450
451 Encoding::RdN2CNzimm18hiCNzimm18lo => {
452 write!(out, " ")?;
453 self.write_reg(out, false, false, inst.value.rd())?;
454 write!(out, ", ")?;
455 write!(out, "{}", inst.value.c_nzimm18lohi())?;
456 }
457
458 Encoding::RdPCNzuimm10 => {
459 write!(out, " ")?;
460 self.write_reg(out, false, false, inst.value.rd())?;
461 write!(out, ", ")?;
462 write!(out, "{}", inst.value.c_nzuimm10())?;
463 }
464
465 Encoding::RdPRs1PCUimm1 => {
466 write!(out, " ")?;
467 self.write_reg(out, false, false, inst.value.rd())?;
468 write!(out, ", ")?;
469 self.write_reg(out, false, false, inst.value.rs1())?;
470 write!(out, ", ")?;
471 write!(out, "{}", inst.value.c_uimm1())?;
472 }
473
474 Encoding::RdPRs1PCUimm2 => {
475 write!(out, " ")?;
476 self.write_reg(out, false, false, inst.value.rd())?;
477 write!(out, ", ")?;
478 self.write_reg(out, false, false, inst.value.rs1())?;
479 write!(out, ", ")?;
480 write!(out, "{}", inst.value.c_uimm2())?;
481 }
482
483 Encoding::RdPRs1PCUimm7loCUimm7hi => {
484 write!(out, " ")?;
485 self.write_reg(out, false, false, inst.value.rd())?;
486 write!(out, ", ")?;
487 self.write_reg(out, false, false, inst.value.rs1())?;
488 write!(out, ", {}", inst.value.c_uimm7lohi())?;
489 }
490
491 Encoding::RdPRs1PCUimm8loCUimm8hi => {
492 write!(out, " ")?;
493 self.write_reg(out, false, false, inst.value.rd_p() + 8)?;
494 write!(out, ", ")?;
495
496 self.write_reg(
497 out,
498 matches!(inst.code, Opcode::CFLD),
499 false,
500 inst.value.rs1_p() + 8,
501 )?;
502 write!(out, ", {}", inst.value.c_uimm8lohi())?;
503 }
504
505 Encoding::RdRs1 => match inst.code {
506 Opcode::FLID | Opcode::FLIQ | Opcode::FLIH | Opcode::FLIS => {
507 self.format_fli(out, inst)?;
508 }
509
510 Opcode::FMVDX | Opcode::FMVHX | Opcode::FMVPQX | Opcode::FMVSX => {
511 write!(out, " ")?;
512 self.write_reg(out, true, false, inst.value.rd())?;
513 write!(out, ", ")?;
514 self.write_reg(out, false, false, inst.value.rs1())?;
515 }
516
517 Opcode::FMVXD | Opcode::FMVXS | Opcode::FMVXH | Opcode::FMVXW => {
518 write!(out, " ")?;
519 self.write_reg(out, false, false, inst.value.rd())?;
520 write!(out, ", ")?;
521 self.write_reg(out, true, false, inst.value.rs1())?;
522 }
523
524 Opcode::FCLASSD | Opcode::FCLASSH | Opcode::FCLASSQ | Opcode::FCLASSS => {
525 write!(out, " ")?;
526 self.write_reg(out, false, false, inst.value.rd())?;
527 write!(out, ", ")?;
528 self.write_reg(out, true, false, inst.value.rs1())?;
529 }
530
531 _ => {
532 write!(out, " ")?;
533 self.write_reg(out, false, false, inst.value.rd())?;
534 write!(out, ", ")?;
535 self.write_reg(out, false, false, inst.value.rs1())?;
536 }
537 },
538
539 Encoding::RdRs1AqRl => {
540 write!(out, " ")?;
541 self.write_reg(out, false, false, inst.value.rd())?;
542 write!(out, ", ")?;
543 self.write_reg(out, false, false, inst.value.rs1())?;
544 }
545 Encoding::RdRs1Csr => {
547 write!(out, " ")?;
548 self.write_reg(out, false, false, inst.value.rd())?;
549 write!(out, ", ")?;
550 write!(out, "csr{}, ", inst.value.csr())?;
551 self.write_reg(out, false, false, inst.value.rs1())?;
552 }
553
554 Encoding::RdRs1Imm12 => {
556 let is_float = matches!(
557 inst.code,
558 Opcode::FLD | Opcode::FLH | Opcode::FLQ | Opcode::FLW
559 );
560
561 write!(out, " ")?;
562 self.write_reg(out, is_float, false, inst.value.rd())?;
563 write!(out, ", ")?;
564 match inst.code {
568 Opcode::FLD
569 | Opcode::FLH
570 | Opcode::FLQ
571 | Opcode::FLW
572 | Opcode::LB
573 | Opcode::LBU
574 | Opcode::LD
575 | Opcode::LH
576 | Opcode::LHU
577 | Opcode::LW
578 | Opcode::LWU => {
579 write!(out, "{}(", inst.value.imm12())?;
580 self.write_reg(out, false, false, inst.value.rs1())?;
581 write!(out, ")")?;
582 }
583
584 _ => {
585 self.write_reg(out, false, false, inst.value.rs1())?;
586 write!(out, ", {}", inst.value.imm12())?;
587 }
588 }
589 }
590
591 Encoding::RdRs1N0CImm6loCImm6hi => {
593 write!(out, " ")?;
594 self.write_reg(out, false, false, inst.value.rd())?;
595 write!(out, ", ")?;
596 self.write_reg(out, false, false, inst.value.rs1())?;
597 write!(out, ", ")?;
598 write!(out, "{}", inst.value.c_imm6lohi())?;
599 }
600
601 Encoding::RdRs1N0CNzimm6loCNzimm6hi => {
603 write!(out, " ")?;
604 self.write_reg(out, false, false, inst.value.rd())?;
605 write!(out, ", ")?;
606 self.write_reg(out, false, false, inst.value.rs1())?;
607 write!(out, ", ")?;
608 write!(out, "{}", inst.value.c_nzimm6lohi())?;
609 }
610
611 Encoding::RdRs1N0CNzuimm6hiCNzuimm6lo => {
613 write!(out, " ")?;
614 self.write_reg(out, false, false, inst.value.rd())?;
615 write!(out, ", ")?;
616 self.write_reg(out, false, false, inst.value.rs1())?;
617 write!(out, ", ")?;
618 write!(out, "{}", inst.value.c_nzuimm6lohi())?;
619 }
620
621 Encoding::RdRs1N0CRs2N0 => {
622 write!(out, " ")?;
623 self.write_reg(out, false, false, inst.value.rd())?;
624 write!(out, ", ")?;
625 self.write_reg(out, false, false, inst.value.rs1())?;
626 write!(out, ", ")?;
627 self.write_reg(out, false, false, inst.value.c_rs2())?;
628 }
629
630 Encoding::RdRs1P => {
631 write!(out, " ")?;
632 self.write_reg(out, false, false, inst.value.rd())?;
633 write!(out, ", ")?;
634 self.write_reg(out, false, false, inst.value.rs1_p())?;
635 }
636
637 Encoding::RdRs1PCImm6hiCImm6lo => {
638 write!(out, " ")?;
639 self.write_reg(out, false, false, inst.value.rd())?;
640 write!(out, ", ")?;
641 self.write_reg(out, false, false, inst.value.rs1())?;
642 write!(out, ", ")?;
643 write!(out, "{}", inst.value.c_imm6lohi())?;
644 }
645
646 Encoding::RdRs1PRs2P => {
647 write!(out, " ")?;
648 self.write_reg(out, false, false, inst.value.rd())?;
649 write!(out, ", ")?;
650 self.write_reg(out, false, false, inst.value.rs1_p())?;
651 write!(out, ", ")?;
652 self.write_reg(out, false, false, inst.value.rs2_p())?;
653 }
654
655 Encoding::RdRs1Rm => {
656 let (rd_is_f, rs1_is_f) = match inst.code {
657 Opcode::FCVTDH => (true, true),
658 Opcode::FCVTDL => (true, false),
659 Opcode::FCVTDLU => (true, false),
660 Opcode::FCVTDQ => (true, true),
661 Opcode::FCVTDS => (true, true),
662 Opcode::FCVTDW => (true, false),
663 Opcode::FCVTDWU => (true, false),
664 Opcode::FCVTHD => (true, true),
665 Opcode::FCVTHL => (true, false),
666 Opcode::FCVTHLU => (true, false),
667 Opcode::FCVTHQ => (true, true),
668 Opcode::FCVTHS => (true, true),
669 Opcode::FCVTHW => (true, false),
670 Opcode::FCVTHWU => (true, false),
671 Opcode::FCVTLD => (false, true),
672 Opcode::FCVTLUD => (false, true),
673 Opcode::FCVTLUH => (false, true),
674
675 Opcode::FCVTLH => (false, true),
676 Opcode::FCVTLQ => (false, true),
677 Opcode::FCVTLS => (false, true),
678 Opcode::FCVTLUQ => (false, true),
679 Opcode::FCVTLUS => (false, true),
680 Opcode::FCVTQD => (true, true),
681 Opcode::FCVTQH => (true, true),
682 Opcode::FCVTQL => (true, false),
683 Opcode::FCVTQLU => (true, false),
684 Opcode::FCVTQS => (true, true),
685 Opcode::FCVTQW => (true, false),
686 Opcode::FCVTQWU => (true, false),
687 Opcode::FCVTSD => (true, true),
688 Opcode::FCVTSH => (true, true),
689 Opcode::FCVTSL => (true, false),
690 Opcode::FCVTSLU => (true, false),
691 Opcode::FCVTSQ => (true, true),
692 Opcode::FCVTSW => (true, false),
693 Opcode::FCVTSWU => (true, false),
694 Opcode::FCVTWD => (false, true),
695 Opcode::FCVTWH => (false, true),
696 Opcode::FCVTWQ => (false, true),
697 Opcode::FCVTWS => (false, true),
698 Opcode::FCVTWUD => (false, true),
699 Opcode::FCVTWUH => (false, true),
700 Opcode::FCVTWUQ => (false, true),
701 Opcode::FCVTWUS => (false, true),
702 _ => (true, true),
703 };
704
705 write!(out, " ")?;
706 self.write_reg(out, rd_is_f, false, inst.value.rd())?;
707 write!(out, ", ")?;
708 self.write_reg(out, rs1_is_f, false, inst.value.rs1())?;
709 }
710 Encoding::RdRs1Rs2 => {
711 write!(out, " ")?;
712 let is_f = mnem.starts_with("f");
713
714 self.write_reg(out, is_f, false, inst.value.rd())?;
715 write!(out, ", ")?;
716 self.write_reg(out, is_f, false, inst.value.rs1())?;
717 write!(out, ", ")?;
718 self.write_reg(out, is_f, false, inst.value.rs2())?;
719 }
720 Encoding::RdRs1Shamtd => {
721 write!(out, " ")?;
722 self.write_reg(out, false, false, inst.value.rd())?;
723 write!(out, ", ")?;
724 self.write_reg(out, false, false, inst.value.rs1())?;
725 write!(out, ", {}", inst.value.shamtd())?;
726 }
727 _ => todo!("{:?}", encoding),
728 }
729
730 Ok(())
731 }
732
733 fn format_fli<W: Write>(&self, out: &mut W, inst: &Instruction) -> fmt::Result {
734 let rs1 = inst.value.rs1();
735 let c = match rs1 {
736 0 => "-1.0",
737 1 => "0.0",
738 2 => "1.0*2^-16",
739 3 => "1.0*2^-15",
740 4 => "1.0*2^-8",
741 5 => "1.0*2^-7",
742 6 => "0.0625",
743 7 => "0.125",
744 8 => "0.25",
745 9 => "0.3125",
746 10 => "0.375",
747 11 => "0.4375",
748 12 => "0.5",
749 13 => "0.625",
750 14 => "0.75",
751 15 => "0.875",
752 16 => "1.0",
753 17 => "1.25",
754 18 => "1.5",
755 19 => "1.75",
756 20 => "2.0",
757 21 => "2.5",
758 22 => "3",
759 23 => "4",
760 24 => "8",
761 25 => "16",
762 26 => "128",
763 27 => "256",
764 28 => "2^15",
765 29 => "2^16",
766 30 => "+inf",
767 31 => "NaN",
768 _ => "<invalid>",
769 };
770
771 write!(out, " ")?;
772 self.write_reg(out, true, false, inst.value.rd())?;
773 write!(out, ", {}", c)
774 }
775}
776
777pub fn pretty_disassembler<W: Write>(
778 out: &mut W,
779 bitness: usize,
780 data: &[u8],
781 address: u64,
782) -> fmt::Result {
783 let mut decoder = Decoder::new(bitness, data, address);
784 let mut fmt = Formatter::new();
785 fmt.abi_names = true;
786
787 let mut inst = Instruction::default();
788
789 while decoder.can_decode() {
790 decoder.decode_out(&mut inst);
791
792 write!(out, "{:016x}: {:08x} ", inst.address, inst.value.value)?;
793
794 fmt.format(out, &inst)?;
795 write!(out, "\n")?;
796 }
797 Ok(())
798}