asmkit/riscv/
formatter.rs

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                // TODO: Broken, implement sreg decoding/encoding
220                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            // <op> rs2, offset(rs1)
245            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            // <op> vd, (rs1), rs2, vm
323            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            // <op> v3, (rs1), rs2, vm
342            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            // vd, (rs1), vs2
361            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            // rd, csr, rs1
546            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            // rd, offset(rs1)
555            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                /*self.write_reg(out, is_float, false, inst.value.rs1())?;
565                write!(out, ", {}", inst.value.imm12())?;
566                */
567                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            // rd, rs1, imm6lohi
592            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            // rd, rs1, nzimm6lohi
602            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            // rd, rs1, nzuimm6lohi
612            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}