Skip to main content

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 = 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                // TODO: Broken, implement sreg decoding/encoding
218                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            // <op> rs2, offset(rs1)
243            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            // <op> vd, (rs1), rs2, vm
321            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            // <op> v3, (rs1), rs2, vm
340            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            // vd, (rs1), vs2
359            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            // rd, csr, rs1
544            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            // rd, offset(rs1)
553            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                /*self.write_reg(out, is_float, false, inst.value.rs1())?;
563                write!(out, ", {}", inst.value.imm12())?;
564                */
565                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            // rd, rs1, imm6lohi
590            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            // rd, rs1, nzimm6lohi
600            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            // rd, rs1, nzuimm6lohi
610            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}