1use crate::immediates::{
2 BImmediate, CSR, CSRImmediate, JImmediate, SImmediate, Shamt, ShamtW, UImmediate,
3};
4use crate::register::{FRegister, IRegister};
5use crate::{immediates::IImmediate, opcode::Opcode};
6use std::fmt::{Display, Formatter};
7
8#[derive(Debug, PartialEq, Clone, Copy)]
9pub enum RoundingMode {
10 RNE = 0b000,
12 RTZ = 0b001,
14 RDN = 0b010,
16 RUP = 0b011,
18 RMM = 0b100,
20 DYN = 0b111,
22}
23
24impl Display for RoundingMode {
25 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
26 match self {
27 RoundingMode::RNE => write!(f, "rne"),
28 RoundingMode::RTZ => write!(f, "rtz"),
29 RoundingMode::RDN => write!(f, "rdn"),
30 RoundingMode::RUP => write!(f, "rup"),
31 RoundingMode::RMM => write!(f, "rmm"),
32 RoundingMode::DYN => write!(f, "dyn"),
33 }
34 }
35}
36
37impl RoundingMode {
38 pub fn from_int(x: u32) -> Result<RoundingMode, String> {
39 match x {
40 0b000 => Ok(RoundingMode::RNE),
41 0b001 => Ok(RoundingMode::RTZ),
42 0b010 => Ok(RoundingMode::RDN),
43 0b011 => Ok(RoundingMode::RUP),
44 0b100 => Ok(RoundingMode::RMM),
45 0b111 => Ok(RoundingMode::DYN),
46 _ => Err("attempted to create invalid rounding mode".to_owned()),
47 }
48 }
49 pub fn from_str(x: &str) -> Result<RoundingMode, String> {
50 match x {
51 "rne" => Ok(RoundingMode::RNE),
52 "rtz" => Ok(RoundingMode::RTZ),
53 "rdn" => Ok(RoundingMode::RDN),
54 "rup" => Ok(RoundingMode::RUP),
55 "rmm" => Ok(RoundingMode::RMM),
56 "dyn" => Ok(RoundingMode::DYN),
57 _ => Err("attempted to create invalid rounding mode".to_owned()),
58 }
59 }
60
61 pub fn to_u32(self) -> u32 {
62 return (self as u32) << 12;
63 }
64}
65
66#[derive(Debug, PartialEq)]
67pub enum Instruction {
68 LUI {
73 dest: IRegister,
74 imm: UImmediate,
75 },
76 AUIPC {
78 dest: IRegister,
79 imm: UImmediate,
80 },
81 JAL {
83 dest: IRegister,
84 offset: JImmediate,
85 },
86 JALR {
88 dest: IRegister,
89 base: IRegister,
90 offset: IImmediate,
91 },
92 BEQ {
93 src1: IRegister,
94 src2: IRegister,
95 offset: BImmediate,
96 },
97 BNE {
98 src1: IRegister,
99 src2: IRegister,
100 offset: BImmediate,
101 },
102 BLT {
103 src1: IRegister,
104 src2: IRegister,
105 offset: BImmediate,
106 },
107 BGE {
108 src1: IRegister,
109 src2: IRegister,
110 offset: BImmediate,
111 },
112 BLTU {
113 src1: IRegister,
114 src2: IRegister,
115 offset: BImmediate,
116 },
117 BGEU {
118 src1: IRegister,
119 src2: IRegister,
120 offset: BImmediate,
121 },
122 LB {
124 dest: IRegister,
125 base: IRegister,
126 offset: IImmediate,
127 },
128 LH {
130 dest: IRegister,
131 base: IRegister,
132 offset: IImmediate,
133 },
134 LW {
136 dest: IRegister,
137 base: IRegister,
138 offset: IImmediate,
139 },
140 LBU {
142 dest: IRegister,
143 base: IRegister,
144 offset: IImmediate,
145 },
146 LHU {
148 dest: IRegister,
149 base: IRegister,
150 offset: IImmediate,
151 },
152 SB {
154 src: IRegister,
155 base: IRegister,
156 offset: SImmediate,
157 },
158 SH {
160 src: IRegister,
161 base: IRegister,
162 offset: SImmediate,
163 },
164 SW {
166 src: IRegister,
167 base: IRegister,
168 offset: SImmediate,
169 },
170 ADDI {
171 dest: IRegister,
172 src: IRegister,
173 imm: IImmediate,
174 },
175 SLTI {
176 dest: IRegister,
177 src: IRegister,
178 imm: IImmediate,
179 },
180 SLTIU {
181 dest: IRegister,
182 src: IRegister,
183 imm: IImmediate,
184 },
185 XORI {
186 dest: IRegister,
187 src: IRegister,
188 imm: IImmediate,
189 },
190 ORI {
191 dest: IRegister,
192 src: IRegister,
193 imm: IImmediate,
194 },
195 ANDI {
196 dest: IRegister,
197 src: IRegister,
198 imm: IImmediate,
199 },
200 SLLI {
202 dest: IRegister,
203 src: IRegister,
204 shamt: Shamt,
205 },
206 SRLI {
208 dest: IRegister,
209 src: IRegister,
210 shamt: Shamt,
211 },
212 SRAI {
214 dest: IRegister,
215 src: IRegister,
216 shamt: Shamt,
217 },
218 ADD {
219 dest: IRegister,
220 src1: IRegister,
221 src2: IRegister,
222 },
223 SUB {
224 dest: IRegister,
225 src1: IRegister,
226 src2: IRegister,
227 },
228 SLL {
230 dest: IRegister,
231 src1: IRegister,
232 src2: IRegister,
233 },
234 SLT {
236 dest: IRegister,
237 src1: IRegister,
238 src2: IRegister,
239 },
240 SLTU {
241 dest: IRegister,
242 src1: IRegister,
243 src2: IRegister,
244 },
245 XOR {
246 dest: IRegister,
247 src1: IRegister,
248 src2: IRegister,
249 },
250 SRL {
252 dest: IRegister,
253 src1: IRegister,
254 src2: IRegister,
255 },
256 SRA {
258 dest: IRegister,
259 src1: IRegister,
260 src2: IRegister,
261 },
262 OR {
263 dest: IRegister,
264 src1: IRegister,
265 src2: IRegister,
266 },
267 AND {
268 dest: IRegister,
269 src1: IRegister,
270 src2: IRegister,
271 },
272 FENCE {
273 rd: IRegister,
274 rs1: IRegister,
275 ops: u8,
276 fm: u8,
277 },
278 ECALL,
279 EBREAK,
280 LWU {
285 dest: IRegister,
286 base: IRegister,
287 offset: IImmediate,
288 },
289 LD {
291 dest: IRegister,
292 base: IRegister,
293 offset: IImmediate,
294 },
295 SD {
297 src: IRegister,
298 base: IRegister,
299 offset: SImmediate,
300 },
301 ADDIW {
303 dest: IRegister,
304 src: IRegister,
305 imm: IImmediate,
306 },
307 SLLIW {
309 dest: IRegister,
310 src: IRegister,
311 shamt: ShamtW,
312 },
313 SRLIW {
315 dest: IRegister,
316 src: IRegister,
317 shamt: ShamtW,
318 },
319 SRAIW {
321 dest: IRegister,
322 src: IRegister,
323 shamt: ShamtW,
324 },
325 ADDW {
327 dest: IRegister,
328 src1: IRegister,
329 src2: IRegister,
330 },
331 SUBW {
333 dest: IRegister,
334 src1: IRegister,
335 src2: IRegister,
336 },
337 SLLW {
339 dest: IRegister,
340 src1: IRegister,
341 src2: IRegister,
342 },
343 SRLW {
345 dest: IRegister,
346 src1: IRegister,
347 src2: IRegister,
348 },
349 SRAW {
351 dest: IRegister,
352 src1: IRegister,
353 src2: IRegister,
354 },
355 MUL {
360 dest: IRegister,
361 src1: IRegister,
362 src2: IRegister,
363 },
364 MULH {
366 dest: IRegister,
367 src1: IRegister,
368 src2: IRegister,
369 },
370 MULHSU {
372 dest: IRegister,
373 src1: IRegister,
374 src2: IRegister,
375 },
376 MULHU {
378 dest: IRegister,
379 src1: IRegister,
380 src2: IRegister,
381 },
382 DIV {
384 dest: IRegister,
385 src1: IRegister,
386 src2: IRegister,
387 },
388 DIVU {
390 dest: IRegister,
391 src1: IRegister,
392 src2: IRegister,
393 },
394 REM {
396 dest: IRegister,
397 src1: IRegister,
398 src2: IRegister,
399 },
400 REMU {
402 dest: IRegister,
403 src1: IRegister,
404 src2: IRegister,
405 },
406 MULW {
408 dest: IRegister,
409 src1: IRegister,
410 src2: IRegister,
411 },
412 DIVW {
414 dest: IRegister,
415 src1: IRegister,
416 src2: IRegister,
417 },
418 DIVUW {
420 dest: IRegister,
421 src1: IRegister,
422 src2: IRegister,
423 },
424 REMW {
426 dest: IRegister,
427 src1: IRegister,
428 src2: IRegister,
429 },
430 REMUW {
432 dest: IRegister,
433 src1: IRegister,
434 src2: IRegister,
435 },
436 LRW {
442 dest: IRegister,
443 addr: IRegister,
444 aq: bool,
445 rl: bool,
446 },
447 SCW {
448 dest: IRegister,
449 addr: IRegister,
450 src: IRegister,
451 aq: bool,
452 rl: bool,
453 },
454 AMOSWAPW {
455 dest: IRegister,
456 addr: IRegister,
457 src: IRegister,
458 aq: bool,
459 rl: bool,
460 },
461 AMOADDW {
462 dest: IRegister,
463 addr: IRegister,
464 src: IRegister,
465 aq: bool,
466 rl: bool,
467 },
468 AMOXORW {
469 dest: IRegister,
470 addr: IRegister,
471 src: IRegister,
472 aq: bool,
473 rl: bool,
474 },
475 AMOANDW {
476 dest: IRegister,
477 addr: IRegister,
478 src: IRegister,
479 aq: bool,
480 rl: bool,
481 },
482 AMOORW {
483 dest: IRegister,
484 addr: IRegister,
485 src: IRegister,
486 aq: bool,
487 rl: bool,
488 },
489 AMOMINW {
490 dest: IRegister,
491 addr: IRegister,
492 src: IRegister,
493 aq: bool,
494 rl: bool,
495 },
496 AMOMAXW {
497 dest: IRegister,
498 addr: IRegister,
499 src: IRegister,
500 aq: bool,
501 rl: bool,
502 },
503 AMOMINUW {
504 dest: IRegister,
505 addr: IRegister,
506 src: IRegister,
507 aq: bool,
508 rl: bool,
509 },
510 AMOMAXUW {
511 dest: IRegister,
512 addr: IRegister,
513 src: IRegister,
514 aq: bool,
515 rl: bool,
516 },
517 LRD {
519 dest: IRegister,
520 addr: IRegister,
521 aq: bool,
522 rl: bool,
523 },
524 SCD {
525 dest: IRegister,
526 addr: IRegister,
527 src: IRegister,
528 aq: bool,
529 rl: bool,
530 },
531 AMOSWAPD {
532 dest: IRegister,
533 addr: IRegister,
534 src: IRegister,
535 aq: bool,
536 rl: bool,
537 },
538 AMOADDD {
539 dest: IRegister,
540 addr: IRegister,
541 src: IRegister,
542 aq: bool,
543 rl: bool,
544 },
545 AMOXORD {
546 dest: IRegister,
547 addr: IRegister,
548 src: IRegister,
549 aq: bool,
550 rl: bool,
551 },
552 AMOANDD {
553 dest: IRegister,
554 addr: IRegister,
555 src: IRegister,
556 aq: bool,
557 rl: bool,
558 },
559 AMOORD {
560 dest: IRegister,
561 addr: IRegister,
562 src: IRegister,
563 aq: bool,
564 rl: bool,
565 },
566 AMOMIND {
567 dest: IRegister,
568 addr: IRegister,
569 src: IRegister,
570 aq: bool,
571 rl: bool,
572 },
573 AMOMAXD {
574 dest: IRegister,
575 addr: IRegister,
576 src: IRegister,
577 aq: bool,
578 rl: bool,
579 },
580 AMOMINUD {
581 dest: IRegister,
582 addr: IRegister,
583 src: IRegister,
584 aq: bool,
585 rl: bool,
586 },
587 AMOMAXUD {
588 dest: IRegister,
589 addr: IRegister,
590 src: IRegister,
591 aq: bool,
592 rl: bool,
593 },
594 FLW {
598 dest: FRegister,
599 base: IRegister,
600 offset: IImmediate,
601 },
602 FSW {
603 base: IRegister,
604 src: FRegister,
605 offset: SImmediate,
606 },
607 FMADDS {
608 dest: FRegister,
609 src1: FRegister,
610 src2: FRegister,
611 src3: FRegister,
612 rm: RoundingMode,
613 },
614 FMSUBS {
615 dest: FRegister,
616 src1: FRegister,
617 src2: FRegister,
618 src3: FRegister,
619 rm: RoundingMode,
620 },
621 FNMSUBS {
622 dest: FRegister,
623 src1: FRegister,
624 src2: FRegister,
625 src3: FRegister,
626 rm: RoundingMode,
627 },
628 FNMADDS {
629 dest: FRegister,
630 src1: FRegister,
631 src2: FRegister,
632 src3: FRegister,
633 rm: RoundingMode,
634 },
635 FADDS {
636 dest: FRegister,
637 src1: FRegister,
638 src2: FRegister,
639 rm: RoundingMode,
640 },
641 FSUBS {
642 dest: FRegister,
643 src1: FRegister,
644 src2: FRegister,
645 rm: RoundingMode,
646 },
647 FMULS {
648 dest: FRegister,
649 src1: FRegister,
650 src2: FRegister,
651 rm: RoundingMode,
652 },
653 FDIVS {
654 dest: FRegister,
655 src1: FRegister,
656 src2: FRegister,
657 rm: RoundingMode,
658 },
659 FSQRTS {
660 dest: FRegister,
661 src: FRegister,
662 rm: RoundingMode,
663 },
664 FSGNJS {
665 dest: FRegister,
666 src1: FRegister,
667 src2: FRegister,
668 },
669 FSGNJNS {
670 dest: FRegister,
671 src1: FRegister,
672 src2: FRegister,
673 },
674 FSGNJXS {
675 dest: FRegister,
676 src1: FRegister,
677 src2: FRegister,
678 },
679 FMINS {
680 dest: FRegister,
681 src1: FRegister,
682 src2: FRegister,
683 },
684 FMAXS {
685 dest: FRegister,
686 src1: FRegister,
687 src2: FRegister,
688 },
689 FCVTWS {
690 dest: IRegister,
691 src: FRegister,
692 rm: RoundingMode,
693 },
694 FCVTWUS {
695 dest: IRegister,
696 src: FRegister,
697 rm: RoundingMode,
698 },
699 FMVXW {
700 dest: IRegister,
701 src: FRegister,
702 },
703 FEQS {
704 dest: IRegister,
705 src1: FRegister,
706 src2: FRegister,
707 },
708 FLTS {
709 dest: IRegister,
710 src1: FRegister,
711 src2: FRegister,
712 },
713 FLES {
714 dest: IRegister,
715 src1: FRegister,
716 src2: FRegister,
717 },
718 FCLASSS {
719 dest: IRegister,
720 src: FRegister,
721 },
722 FCVTSW {
723 dest: FRegister,
724 src: IRegister,
725 rm: RoundingMode,
726 },
727 FCVTSWU {
728 dest: FRegister,
729 src: IRegister,
730 rm: RoundingMode,
731 },
732 FMVWX {
733 dest: FRegister,
734 src: IRegister,
735 },
736 FCVTLS {
740 dest: IRegister,
741 src: FRegister,
742 rm: RoundingMode,
743 },
744 FCVTLUS {
745 dest: IRegister,
746 src: FRegister,
747 rm: RoundingMode,
748 },
749 FCVTSL {
750 dest: FRegister,
751 src: IRegister,
752 rm: RoundingMode,
753 },
754 FCVTSLU {
755 dest: FRegister,
756 src: IRegister,
757 rm: RoundingMode,
758 },
759 CSRRW {
763 dest: IRegister,
764 src: IRegister,
765 csr: CSR,
766 },
767 CSRRS {
768 dest: IRegister,
769 src: IRegister,
770 csr: CSR,
771 },
772 CSRRC {
773 dest: IRegister,
774 src: IRegister,
775 csr: CSR,
776 },
777 CSRRWI {
778 dest: IRegister,
779 imm: CSRImmediate,
780 csr: CSR,
781 },
782 CSRRSI {
783 dest: IRegister,
784 imm: CSRImmediate,
785 csr: CSR,
786 },
787 CSRRCI {
788 dest: IRegister,
789 imm: CSRImmediate,
790 csr: CSR,
791 },
792 FENCEI,
796}
797
798fn aq_rl_suffix(aq: &bool, rl: &bool) -> &'static str {
799 match (aq, rl) {
800 (true, true) => ".aqrl",
801 (true, false) => ".aq",
802 (false, true) => ".rl",
803 (false, false) => "",
804 }
805}
806
807fn aqb(aq: bool) -> u32 {
809 if aq { 1 << 26 } else { 0 }
810}
811
812fn rlb(rl: bool) -> u32 {
814 if rl { 1 << 25 } else { 0 }
815}
816
817impl Display for Instruction {
818 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
819 match self {
820 Instruction::LUI { dest, imm } => write!(f, "lui {dest},{imm}"),
821 Instruction::AUIPC { dest, imm } => write!(f, "auipc {dest},{imm}"),
822 Instruction::JAL { dest, offset } => write!(f, "jal {dest},{offset}"),
823 Instruction::JALR { dest, base, offset } => write!(f, "jalr {dest},{offset}({base})"),
824 Instruction::BEQ { src1, src2, offset } => write!(f, "beq {src1},{src2},{offset}"),
825 Instruction::BNE { src1, src2, offset } => write!(f, "bne {src1},{src2},{offset}"),
826 Instruction::BLT { src1, src2, offset } => write!(f, "blt {src1},{src2},{offset}"),
827 Instruction::BGE { src1, src2, offset } => write!(f, "bge {src1},{src2},{offset}"),
828 Instruction::BLTU { src1, src2, offset } => write!(f, "bltu {src1},{src2},{offset}"),
829 Instruction::BGEU { src1, src2, offset } => write!(f, "bgeu {src1},{src2},{offset}"),
830 Instruction::LB { dest, base, offset } => write!(f, "lb {dest},{offset}({base})"),
831 Instruction::LH { dest, base, offset } => write!(f, "lh {dest},{offset}({base})"),
832 Instruction::LW { dest, base, offset } => write!(f, "lw {dest},{offset}({base})"),
833 Instruction::LBU { dest, base, offset } => write!(f, "lbu {dest},{offset}({base})"),
834 Instruction::LHU { dest, base, offset } => write!(f, "lhu {dest},{offset}({base})"),
835 Instruction::SB { src, base, offset } => write!(f, "sb {src},{offset}({base})"),
836 Instruction::SH { src, base, offset } => write!(f, "sh {src},{offset}({base})"),
837 Instruction::SW { src, base, offset } => write!(f, "sw {src},{offset}({base})"),
838 Instruction::ADDI { dest, src, imm } => write!(f, "addi {dest},{src},{imm}"),
839 Instruction::SLTI { dest, src, imm } => write!(f, "slti {dest},{src},{imm}"),
840 Instruction::SLTIU { dest, src, imm } => write!(f, "sltiu {dest},{src},{imm}"),
841 Instruction::XORI { dest, src, imm } => write!(f, "xori {dest},{src},{imm}"),
842 Instruction::ORI { dest, src, imm } => write!(f, "ori {dest},{src},{imm}"),
843 Instruction::ANDI { dest, src, imm } => write!(f, "andi {dest},{src},{imm}"),
844 Instruction::SLLI { dest, src, shamt } => write!(f, "slli {dest},{src},{shamt}"),
845 Instruction::SRLI { dest, src, shamt } => write!(f, "srli {dest},{src},{shamt}"),
846 Instruction::SRAI { dest, src, shamt } => write!(f, "srai {dest},{src},{shamt}"),
847 Instruction::ADD { dest, src1, src2 } => write!(f, "add {dest},{src1},{src2}"),
848 Instruction::SUB { dest, src1, src2 } => write!(f, "sub {dest},{src1},{src2}"),
849 Instruction::SLL { dest, src1, src2 } => write!(f, "sll {dest},{src1},{src2}"),
850 Instruction::SLT { dest, src1, src2 } => write!(f, "slt {dest},{src1},{src2}"),
851 Instruction::SLTU { dest, src1, src2 } => write!(f, "sltu {dest},{src1},{src2}"),
852 Instruction::XOR { dest, src1, src2 } => write!(f, "xor {dest},{src1},{src2}"),
853 Instruction::SRL { dest, src1, src2 } => write!(f, "srl {dest},{src1},{src2}"),
854 Instruction::SRA { dest, src1, src2 } => write!(f, "sra {dest},{src1},{src2}"),
855 Instruction::OR { dest, src1, src2 } => write!(f, "or {dest},{src1},{src2}"),
856 Instruction::AND { dest, src1, src2 } => write!(f, "and {dest},{src1},{src2}"),
857 Instruction::FENCE { .. } => write!(f, "{}", self.fmt_fence()),
858 Instruction::ECALL => write!(f, "ecall"),
859 Instruction::EBREAK => write!(f, "ebreak"),
860 Instruction::LWU { dest, base, offset } => write!(f, "lwu {dest},{offset}({base})"),
861 Instruction::LD { dest, base, offset } => write!(f, "ld {dest},{offset}({base})"),
862 Instruction::SD { src, base, offset } => write!(f, "sd {src},{offset}({base})"),
863 Instruction::ADDIW { dest, src, imm } => write!(f, "addiw {dest},{src},{imm}"),
864 Instruction::SLLIW { dest, src, shamt } => write!(f, "slliw {dest},{src},{shamt}"),
865 Instruction::SRLIW { dest, src, shamt } => write!(f, "srliw {dest},{src},{shamt}"),
866 Instruction::SRAIW { dest, src, shamt } => write!(f, "sraiw {dest},{src},{shamt}"),
867 Instruction::ADDW { dest, src1, src2 } => write!(f, "addw {dest},{src1},{src2}"),
868 Instruction::SUBW { dest, src1, src2 } => write!(f, "subw {dest},{src1},{src2}"),
869 Instruction::SLLW { dest, src1, src2 } => write!(f, "sllw {dest},{src1},{src2}"),
870 Instruction::SRLW { dest, src1, src2 } => write!(f, "srlw {dest},{src1},{src2}"),
871 Instruction::SRAW { dest, src1, src2 } => write!(f, "sraw {dest},{src1},{src2}"),
872 Instruction::MUL { dest, src1, src2 } => write!(f, "mul {dest},{src1},{src2}"),
873 Instruction::MULH { dest, src1, src2 } => write!(f, "mulh {dest},{src1},{src2}"),
874 Instruction::MULHSU { dest, src1, src2 } => write!(f, "mulhsu {dest},{src1},{src2}"),
875 Instruction::MULHU { dest, src1, src2 } => write!(f, "mulhu {dest},{src1},{src2}"),
876 Instruction::DIV { dest, src1, src2 } => write!(f, "div {dest},{src1},{src2}"),
877 Instruction::DIVU { dest, src1, src2 } => write!(f, "divu {dest},{src1},{src2}"),
878 Instruction::REM { dest, src1, src2 } => write!(f, "rem {dest},{src1},{src2}"),
879 Instruction::REMU { dest, src1, src2 } => write!(f, "remu {dest},{src1},{src2}"),
880 Instruction::MULW { dest, src1, src2 } => write!(f, "mulw {dest},{src1},{src2}"),
881 Instruction::DIVW { dest, src1, src2 } => write!(f, "divw {dest},{src1},{src2}"),
882 Instruction::DIVUW { dest, src1, src2 } => write!(f, "divuw {dest},{src1},{src2}"),
883 Instruction::REMW { dest, src1, src2 } => write!(f, "remw {dest},{src1},{src2}"),
884 Instruction::REMUW { dest, src1, src2 } => write!(f, "remuw {dest},{src1},{src2}"),
885 Instruction::LRW { dest, addr, aq, rl } => {
886 write!(f, "lr.w{} {dest},{addr}", aq_rl_suffix(aq, rl))
887 }
888 Instruction::SCW {
889 dest,
890 addr,
891 src,
892 aq,
893 rl,
894 } => {
895 write!(f, "sc.w{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
896 }
897 Instruction::AMOSWAPW {
898 dest,
899 addr,
900 src,
901 aq,
902 rl,
903 } => {
904 write!(f, "amoswap.w{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
905 }
906 Instruction::AMOADDW {
907 dest,
908 addr,
909 src,
910 aq,
911 rl,
912 } => {
913 write!(f, "amoadd.w{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
914 }
915 Instruction::AMOXORW {
916 dest,
917 addr,
918 src,
919 aq,
920 rl,
921 } => {
922 write!(f, "amoxor.w{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
923 }
924 Instruction::AMOANDW {
925 dest,
926 addr,
927 src,
928 aq,
929 rl,
930 } => {
931 write!(f, "amoand.w{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
932 }
933 Instruction::AMOORW {
934 dest,
935 addr,
936 src,
937 aq,
938 rl,
939 } => {
940 write!(f, "amoor.w{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
941 }
942
943 Instruction::AMOMINW {
944 dest,
945 addr,
946 src,
947 aq,
948 rl,
949 } => {
950 write!(f, "amomin.w{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
951 }
952 Instruction::AMOMAXW {
953 dest,
954 addr,
955 src,
956 aq,
957 rl,
958 } => {
959 write!(f, "amomax.w{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
960 }
961 Instruction::AMOMINUW {
962 dest,
963 addr,
964 src,
965 aq,
966 rl,
967 } => {
968 write!(f, "amominu.w{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
969 }
970 Instruction::AMOMAXUW {
971 dest,
972 addr,
973 src,
974 aq,
975 rl,
976 } => {
977 write!(f, "amomaxu.w{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
978 }
979 Instruction::LRD { dest, addr, aq, rl } => {
980 write!(f, "lr.d{} {dest},{addr}", aq_rl_suffix(aq, rl))
981 }
982 Instruction::SCD {
983 dest,
984 addr,
985 src,
986 aq,
987 rl,
988 } => {
989 write!(f, "sc.d{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
990 }
991 Instruction::AMOSWAPD {
992 dest,
993 addr,
994 src,
995 aq,
996 rl,
997 } => {
998 write!(f, "amoswap.d{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
999 }
1000 Instruction::AMOADDD {
1001 dest,
1002 addr,
1003 src,
1004 aq,
1005 rl,
1006 } => {
1007 write!(f, "amoadd.d{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
1008 }
1009 Instruction::AMOXORD {
1010 dest,
1011 addr,
1012 src,
1013 aq,
1014 rl,
1015 } => {
1016 write!(f, "amoxor.d{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
1017 }
1018 Instruction::AMOANDD {
1019 dest,
1020 addr,
1021 src,
1022 aq,
1023 rl,
1024 } => {
1025 write!(f, "amoand.d{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
1026 }
1027 Instruction::AMOORD {
1028 dest,
1029 addr,
1030 src,
1031 aq,
1032 rl,
1033 } => {
1034 write!(f, "amoor.d{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
1035 }
1036 Instruction::AMOMIND {
1037 dest,
1038 addr,
1039 src,
1040 aq,
1041 rl,
1042 } => {
1043 write!(f, "amomin.d{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
1044 }
1045 Instruction::AMOMAXD {
1046 dest,
1047 addr,
1048 src,
1049 aq,
1050 rl,
1051 } => {
1052 write!(f, "amomax.d{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
1053 }
1054 Instruction::AMOMINUD {
1055 dest,
1056 addr,
1057 src,
1058 aq,
1059 rl,
1060 } => {
1061 write!(f, "amominu.d{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
1062 }
1063 Instruction::AMOMAXUD {
1064 dest,
1065 addr,
1066 src,
1067 aq,
1068 rl,
1069 } => {
1070 write!(f, "amomaxu.d{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
1071 }
1072 Instruction::FLW { dest, base, offset } => write!(f, "flw {dest},{offset}({base})"),
1073 Instruction::FSW { base, src, offset } => write!(f, "fsw {src},{offset}({base})"),
1074 Instruction::FMADDS {
1075 dest,
1076 src1,
1077 src2,
1078 src3,
1079 rm,
1080 } => {
1081 write!(f, "fmadd.s.{rm} {dest},{src1},{src2},{src3}")
1082 }
1083 Instruction::FMSUBS {
1084 dest,
1085 src1,
1086 src2,
1087 src3,
1088 rm,
1089 } => {
1090 write!(f, "fmsub.s.{rm} {dest},{src1},{src2},{src3}")
1091 }
1092 Instruction::FNMSUBS {
1093 dest,
1094 src1,
1095 src2,
1096 src3,
1097 rm,
1098 } => {
1099 write!(f, "fnmsub.s.{rm} {dest},{src1},{src2},{src3}")
1100 }
1101 Instruction::FNMADDS {
1102 dest,
1103 src1,
1104 src2,
1105 src3,
1106 rm,
1107 } => {
1108 write!(f, "fnmadd.s.{rm} {dest},{src1},{src2},{src3}")
1109 }
1110 Instruction::FADDS {
1111 dest,
1112 src1,
1113 src2,
1114 rm,
1115 } => write!(f, "fadd.s.{rm} {dest},{src1},{src2}"),
1116 Instruction::FSUBS {
1117 dest,
1118 src1,
1119 src2,
1120 rm,
1121 } => write!(f, "fsub.s.{rm} {dest},{src1},{src2}"),
1122 Instruction::FMULS {
1123 dest,
1124 src1,
1125 src2,
1126 rm,
1127 } => write!(f, "fmul.s.{rm} {dest},{src1},{src2}"),
1128 Instruction::FDIVS {
1129 dest,
1130 src1,
1131 src2,
1132 rm,
1133 } => write!(f, "fdiv.s.{rm} {dest},{src1},{src2}"),
1134 Instruction::FSQRTS { dest, src, rm } => write!(f, "fsqrt.s.{rm} {dest},{src}"),
1135 Instruction::FSGNJS { dest, src1, src2 } => write!(f, "fsgnj.s {dest},{src1},{src2}"),
1136 Instruction::FSGNJNS { dest, src1, src2 } => write!(f, "fsgnjn.s {dest},{src1},{src2}"),
1137 Instruction::FSGNJXS { dest, src1, src2 } => write!(f, "fsgnjx.s {dest},{src1},{src2}"),
1138 Instruction::FMINS { dest, src1, src2 } => write!(f, "fmin.s {dest},{src1},{src2}"),
1139 Instruction::FMAXS { dest, src1, src2 } => write!(f, "fmax.s {dest},{src1},{src2}"),
1140 Instruction::FCVTWS { dest, src, rm } => write!(f, "fcvt.w.s.{rm} {dest},{src}"),
1141 Instruction::FCVTWUS { dest, src, rm } => write!(f, "fcvt.wu.s.{rm} {dest},{src}"),
1142 Instruction::FMVXW { dest, src } => write!(f, "fmv.x.w {dest},{src}"),
1143 Instruction::FEQS { dest, src1, src2 } => write!(f, "feq.s {dest},{src1},{src2}"),
1144 Instruction::FLTS { dest, src1, src2 } => write!(f, "flt.s {dest},{src1},{src2}"),
1145 Instruction::FLES { dest, src1, src2 } => write!(f, "fle.s {dest},{src1},{src2}"),
1146 Instruction::FCLASSS { dest, src } => write!(f, "fclass.s {dest},{src}"),
1147 Instruction::FCVTSW { dest, src, rm } => write!(f, "fcvt.s.w.{rm} {dest},{src}"),
1148 Instruction::FCVTSWU { dest, src, rm } => write!(f, "fcvt.s.wu.{rm} {dest},{src}"),
1149 Instruction::FMVWX { dest, src } => write!(f, "fmv.w.x {dest},{src}"),
1150 Instruction::FCVTLS { dest, src, rm } => write!(f, "fcvt.l.s.{rm} {dest},{src}"),
1151 Instruction::FCVTLUS { dest, src, rm } => write!(f, "fcvt.lu.s.{rm} {dest},{src}"),
1152 Instruction::FCVTSL { dest, src, rm } => write!(f, "fcvt.s.l.{rm} {dest},{src}"),
1153 Instruction::FCVTSLU { dest, src, rm } => write!(f, "fcvt.s.lu.{rm} {dest},{src}"),
1154 Instruction::CSRRW { dest, src, csr } => write!(f, "csrrw {dest},{csr},{src}"),
1155 Instruction::CSRRS { dest, src, csr } => write!(f, "csrrs {dest},{csr},{src}"),
1156 Instruction::CSRRC { dest, src, csr } => write!(f, "csrrc {dest},{csr},{src}"),
1157 Instruction::CSRRWI { dest, imm, csr } => write!(f, "csrrwi {dest},{csr},{imm}"),
1158 Instruction::CSRRSI { dest, imm, csr } => write!(f, "csrrsi {dest},{csr},{imm}"),
1159 Instruction::CSRRCI { dest, imm, csr } => write!(f, "csrrci {dest},{csr},{imm}"),
1160 Instruction::FENCEI => write!(f, "fence.i"),
1161 }
1162 }
1163}
1164
1165impl Instruction {
1166 fn fmt_fence(&self) -> String {
1167 if let Instruction::FENCE {
1168 rd: _,
1169 rs1: _,
1170 ops,
1171 fm,
1172 } = *self
1173 {
1174 let sw = if ops & 0b0000_0001 != 0 { "w" } else { "" };
1175 let sr = if ops & 0b0000_0010 != 0 { "r" } else { "" };
1176 let so = if ops & 0b0000_0100 != 0 { "o" } else { "" };
1177 let si = if ops & 0b0000_1000 != 0 { "i" } else { "" };
1178 let pw = if ops & 0b0001_0000 != 0 { "w" } else { "" };
1179 let pr = if ops & 0b0010_0000 != 0 { "r" } else { "" };
1180 let po = if ops & 0b0100_0000 != 0 { "o" } else { "" };
1181 let pi = if ops & 0b1000_0000 != 0 { "i" } else { "" };
1182 if fm == 0b1000 {
1183 format!("fence.tso {pi}{po}{pr}{pw},{si}{so}{sr}{sw}")
1184 } else {
1185 format!("fence {pi}{po}{pr}{pw},{si}{so}{sr}{sw}")
1186 }
1187 } else {
1188 unreachable!();
1189 }
1190 }
1191
1192 pub fn decode(instruction: u32) -> Result<Instruction, String> {
1194 let opcode = Opcode::from_int(instruction & 0b111_1111);
1195
1196 let func3 = (instruction >> 12) & 0b111;
1197 let func7 = (instruction >> 25) & 0b111_1111;
1198
1199 let rd = IRegister::from_int((instruction >> 7) & 0b1_1111);
1200 let rs1 = IRegister::from_int((instruction >> 15) & 0b1_1111);
1201 let rs2 = IRegister::from_int((instruction >> 20) & 0b1_1111);
1202
1203 let frd = FRegister::try_from((instruction >> 7) & 0b1_1111).unwrap();
1204 let frs1 = FRegister::try_from((instruction >> 15) & 0b1_1111).unwrap();
1205 let frs2 = FRegister::try_from((instruction >> 20) & 0b1_1111).unwrap();
1206 let frs3 = FRegister::try_from((instruction >> 27) & 0b1_1111).unwrap();
1207
1208 let i_immediate: IImmediate = IImmediate::from_u32(instruction);
1209
1210 let s_immediate: SImmediate = SImmediate::from_u32(instruction);
1211
1212 let u_immediate = UImmediate::from_u32(instruction);
1213
1214 let b_immediate = BImmediate::from_u32(instruction);
1215
1216 let shamt: Shamt = Shamt::from_u32(instruction);
1217
1218 let shamtw: ShamtW = ShamtW::from_u32(instruction);
1219
1220 let aq: bool = ((instruction >> 26) & 0b1) == 0b1;
1222 let rl: bool = ((instruction >> 25) & 0b1) == 0b1;
1223
1224 match opcode {
1225 Opcode::Load => match func3 {
1226 0b000 => Ok(Instruction::LB {
1227 dest: rd,
1228 base: rs1,
1229 offset: i_immediate,
1230 }),
1231 0b001 => Ok(Instruction::LH {
1232 dest: rd,
1233 base: rs1,
1234 offset: i_immediate,
1235 }),
1236 0b010 => Ok(Instruction::LW {
1237 dest: rd,
1238 base: rs1,
1239 offset: i_immediate,
1240 }),
1241 0b011 => Ok(Instruction::LD {
1242 dest: rd,
1243 base: rs1,
1244 offset: i_immediate,
1245 }),
1246 0b100 => Ok(Instruction::LBU {
1247 dest: rd,
1248 base: rs1,
1249 offset: i_immediate,
1250 }),
1251 0b101 => Ok(Instruction::LHU {
1252 dest: rd,
1253 base: rs1,
1254 offset: i_immediate,
1255 }),
1256 0b110 => Ok(Instruction::LWU {
1257 dest: rd,
1258 base: rs1,
1259 offset: i_immediate,
1260 }),
1261 0b111 => Err("Invalid load func3".to_owned()),
1262 _ => unreachable!(),
1263 },
1264 Opcode::Auipc => Ok(Instruction::AUIPC {
1265 dest: rd,
1266 imm: u_immediate,
1267 }),
1268 Opcode::Store => match func3 {
1269 0b000 => Ok(Instruction::SB {
1270 src: rs2,
1271 base: rs1,
1272 offset: s_immediate,
1273 }),
1274 0b001 => Ok(Instruction::SH {
1275 src: rs2,
1276 base: rs1,
1277 offset: s_immediate,
1278 }),
1279 0b010 => Ok(Instruction::SW {
1280 src: rs2,
1281 base: rs1,
1282 offset: s_immediate,
1283 }),
1284 0b011 => Ok(Instruction::SD {
1285 src: rs2,
1286 base: rs1,
1287 offset: s_immediate,
1288 }),
1289 x => Err(format!("invalid store func3: {}", x)),
1290 },
1291 Opcode::Lui => Ok(Instruction::LUI {
1292 dest: rd,
1293 imm: u_immediate,
1294 }),
1295 Opcode::Op => match (func7, func3) {
1296 (0b000_0000, 0b000) => Ok(Instruction::ADD {
1297 dest: rd,
1298 src1: rs1,
1299 src2: rs2,
1300 }),
1301 (0b000_0000, 0b001) => Ok(Instruction::SLL {
1302 dest: rd,
1303 src1: rs1,
1304 src2: rs2,
1305 }),
1306 (0b000_0000, 0b010) => Ok(Instruction::SLT {
1307 dest: rd,
1308 src1: rs1,
1309 src2: rs2,
1310 }),
1311 (0b000_0000, 0b011) => Ok(Instruction::SLTU {
1312 dest: rd,
1313 src1: rs1,
1314 src2: rs2,
1315 }),
1316 (0b000_0000, 0b100) => Ok(Instruction::XOR {
1317 dest: rd,
1318 src1: rs1,
1319 src2: rs2,
1320 }),
1321 (0b000_0000, 0b101) => Ok(Instruction::SRL {
1322 dest: rd,
1323 src1: rs1,
1324 src2: rs2,
1325 }),
1326 (0b000_0000, 0b110) => Ok(Instruction::OR {
1327 dest: rd,
1328 src1: rs1,
1329 src2: rs2,
1330 }),
1331 (0b000_0000, 0b111) => Ok(Instruction::AND {
1332 dest: rd,
1333 src1: rs1,
1334 src2: rs2,
1335 }),
1336 (0b010_0000, 0b000) => Ok(Instruction::SUB {
1337 dest: rd,
1338 src1: rs1,
1339 src2: rs2,
1340 }),
1341 (0b010_0000, 0b101) => Ok(Instruction::SRA {
1342 dest: rd,
1343 src1: rs1,
1344 src2: rs2,
1345 }),
1346 (0b000_0001, 0b000) => Ok(Instruction::MUL {
1347 dest: rd,
1348 src1: rs1,
1349 src2: rs2,
1350 }),
1351 (0b000_0001, 0b001) => Ok(Instruction::MULH {
1352 dest: rd,
1353 src1: rs1,
1354 src2: rs2,
1355 }),
1356 (0b000_0001, 0b010) => Ok(Instruction::MULHSU {
1357 dest: rd,
1358 src1: rs1,
1359 src2: rs2,
1360 }),
1361 (0b000_0001, 0b011) => Ok(Instruction::MULHU {
1362 dest: rd,
1363 src1: rs1,
1364 src2: rs2,
1365 }),
1366 (0b000_0001, 0b100) => Ok(Instruction::DIV {
1367 dest: rd,
1368 src1: rs1,
1369 src2: rs2,
1370 }),
1371 (0b000_0001, 0b101) => Ok(Instruction::DIVU {
1372 dest: rd,
1373 src1: rs1,
1374 src2: rs2,
1375 }),
1376 (0b000_0001, 0b110) => Ok(Instruction::REM {
1377 dest: rd,
1378 src1: rs1,
1379 src2: rs2,
1380 }),
1381 (0b000_0001, 0b111) => Ok(Instruction::REMU {
1382 dest: rd,
1383 src1: rs1,
1384 src2: rs2,
1385 }),
1386 _ => Err(format!("unknown Op. func3: {}, func7: {}", func3, func7)),
1387 },
1388 Opcode::Op32 => match (func3, func7) {
1389 (0b000, 0b000_0000) => Ok(Instruction::ADDW {
1390 dest: rd,
1391 src1: rs1,
1392 src2: rs2,
1393 }),
1394 (0b000, 0b000_0001) => Ok(Instruction::MULW {
1395 dest: rd,
1396 src1: rs1,
1397 src2: rs2,
1398 }),
1399 (0b000, 0b010_0000) => Ok(Instruction::SUBW {
1400 dest: rd,
1401 src1: rs1,
1402 src2: rs2,
1403 }),
1404 (0b001, 0b000_0000) => Ok(Instruction::SLLW {
1405 dest: rd,
1406 src1: rs1,
1407 src2: rs2,
1408 }),
1409 (0b100, 0b0000_001) => Ok(Instruction::DIVW {
1410 dest: rd,
1411 src1: rs1,
1412 src2: rs2,
1413 }),
1414 (0b101, 0b000_0000) => Ok(Instruction::SRLW {
1415 dest: rd,
1416 src1: rs1,
1417 src2: rs2,
1418 }),
1419 (0b101, 0b000_0001) => Ok(Instruction::DIVUW {
1420 dest: rd,
1421 src1: rs1,
1422 src2: rs2,
1423 }),
1424 (0b101, 0b010_0000) => Ok(Instruction::SRAW {
1425 dest: rd,
1426 src1: rs1,
1427 src2: rs2,
1428 }),
1429 (0b110, 0b000_0001) => Ok(Instruction::REMW {
1430 dest: rd,
1431 src1: rs1,
1432 src2: rs2,
1433 }),
1434 (0b111, 0b000_0001) => Ok(Instruction::REMUW {
1435 dest: rd,
1436 src1: rs1,
1437 src2: rs2,
1438 }),
1439 _ => Err(format!("unknown Op32. func3: {}, func7: {}", func3, func7)),
1440 },
1441 Opcode::OpImm => match func3 {
1442 0b000 => Ok(Instruction::ADDI {
1443 dest: rd,
1444 src: rs1,
1445 imm: i_immediate,
1446 }),
1447 0b001 => match func7 | 0b1 {
1449 0b000000_1 => Ok(Instruction::SLLI {
1450 dest: rd,
1451 src: rs1,
1452 shamt,
1453 }),
1454 _ => Err(format!("unknown OpImm. func3: {}, func7: {}", func3, func7)),
1455 },
1456 0b010 => Ok(Instruction::SLTI {
1457 dest: rd,
1458 src: rs1,
1459 imm: i_immediate,
1460 }),
1461 0b011 => Ok(Instruction::SLTIU {
1462 dest: rd,
1463 src: rs1,
1464 imm: i_immediate,
1465 }),
1466 0b100 => Ok(Instruction::XORI {
1467 dest: rd,
1468 src: rs1,
1469 imm: i_immediate,
1470 }),
1471 0b101 => match func7 | 0b1 {
1473 0b000000_1 => Ok(Instruction::SRLI {
1474 dest: rd,
1475 src: rs1,
1476 shamt,
1477 }),
1478 0b010000_1 => Ok(Instruction::SRAI {
1479 dest: rd,
1480 src: rs1,
1481 shamt,
1482 }),
1483 _ => Err(format!("unknown OpImm. func3: {}, func7: {}", func3, func7)),
1484 },
1485 0b110 => Ok(Instruction::ORI {
1486 dest: rd,
1487 src: rs1,
1488 imm: i_immediate,
1489 }),
1490 0b111 => Ok(Instruction::ANDI {
1491 dest: rd,
1492 src: rs1,
1493 imm: i_immediate,
1494 }),
1495 _ => Err(format!("unknown OpImm. func3: {}, func7: {}", func3, func7)),
1496 },
1497 Opcode::OpImm32 => match func3 {
1498 0b000 => Ok(Instruction::ADDIW {
1499 dest: rd,
1500 src: rs1,
1501 imm: i_immediate,
1502 }),
1503 0b001 => Ok(Instruction::SLLIW {
1504 dest: rd,
1505 src: rs1,
1506 shamt: shamtw,
1507 }),
1508 0b101 => match func7 {
1509 0b000_0000 => Ok(Instruction::SRLIW {
1510 dest: rd,
1511 src: rs1,
1512 shamt: shamtw,
1513 }),
1514 0b010_0000 => Ok(Instruction::SRAIW {
1515 dest: rd,
1516 src: rs1,
1517 shamt: shamtw,
1518 }),
1519 x => Err(format!("unknown OpImm32(101) func7: {}", x).to_owned()),
1520 },
1521 x => Err(format!("unkown OpImm32 func3: {}", x).to_owned()),
1522 },
1523 Opcode::Jalr => Ok(Instruction::JALR {
1524 dest: rd,
1525 base: rs1,
1526 offset: i_immediate,
1527 }),
1528 Opcode::Jal => Ok(Instruction::JAL {
1529 dest: rd,
1530 offset: JImmediate::from_u32(instruction),
1531 }),
1532 Opcode::Branch => match func3 {
1533 0b000 => Ok(Instruction::BEQ {
1534 src1: rs1,
1535 src2: rs2,
1536 offset: b_immediate,
1537 }),
1538 0b001 => Ok(Instruction::BNE {
1539 src1: rs1,
1540 src2: rs2,
1541 offset: b_immediate,
1542 }),
1543 0b100 => Ok(Instruction::BLT {
1544 src1: rs1,
1545 src2: rs2,
1546 offset: b_immediate,
1547 }),
1548 0b101 => Ok(Instruction::BGE {
1549 src1: rs1,
1550 src2: rs2,
1551 offset: b_immediate,
1552 }),
1553 0b110 => Ok(Instruction::BLTU {
1554 src1: rs1,
1555 src2: rs2,
1556 offset: b_immediate,
1557 }),
1558 0b111 => Ok(Instruction::BGEU {
1559 src1: rs1,
1560 src2: rs2,
1561 offset: b_immediate,
1562 }),
1563 x => Err(format!("invalid branch func3: {x}").to_owned()),
1564 },
1565 Opcode::MiscMem => match func3 {
1566 0b000 => {
1567 if rd != IRegister::Zero || rs1 != IRegister::Zero {
1568 Err("reserved register fields not set to zero".to_owned())
1570 } else {
1571 let fm = ((instruction >> 28) & 0b1111) as u8;
1572 if fm != 0 && fm != 0b1000 {
1573 Err(format!("reserved fence FM: {fm}").to_owned())
1574 } else if fm == 0b1000 && ((instruction >> 20) & 0xFF) != 0b0011_0011 {
1575 Err("fence.tso must be rw,rw".to_owned())
1576 } else {
1577 Ok(Instruction::FENCE {
1578 rd,
1579 rs1,
1580 ops: ((instruction >> 20) & 0xFF) as u8,
1581 fm: ((instruction >> 28) & 0b1111) as u8,
1582 })
1583 }
1584 }
1585 }
1586 0b001 => {
1587 if rd != IRegister::Zero || rs1 != IRegister::Zero {
1588 Err("reserved register fields not set to zero".to_owned())
1590 } else {
1591 let func12 = instruction >> 20;
1592 if func12 != 0 {
1593 Err("reserved register fields not set to zero".to_owned())
1594 } else {
1595 Ok(Instruction::FENCEI)
1596 }
1597 }
1598 }
1599 x => Err(format!("unknown fence func3: {x}")),
1600 },
1601 Opcode::AMO => match (func3, func7 >> 2) {
1602 (0b010, 0b00010) => {
1603 if rs2 != IRegister::Zero {
1604 Err("LR.W expects rs2 to be 0".to_owned())
1605 } else {
1606 Ok(Instruction::LRW {
1607 dest: rd,
1608 addr: rs1,
1609 aq,
1610 rl,
1611 })
1612 }
1613 }
1614 (0b011, 0b00010) => {
1615 if rs2 != IRegister::Zero {
1616 Err("LR.D expects rs2 to be 0".to_owned())
1617 } else {
1618 Ok(Instruction::LRD {
1619 dest: rd,
1620 addr: rs1,
1621 aq,
1622 rl,
1623 })
1624 }
1625 }
1626 (0b010, 0b00011) => Ok(Instruction::SCW {
1627 dest: rd,
1628 addr: rs1,
1629 src: rs2,
1630 aq,
1631 rl,
1632 }),
1633 (0b011, 0b00011) => Ok(Instruction::SCD {
1634 dest: rd,
1635 addr: rs1,
1636 src: rs2,
1637 aq,
1638 rl,
1639 }),
1640 (0b010, 0b00001) => Ok(Instruction::AMOSWAPW {
1641 dest: rd,
1642 addr: rs1,
1643 src: rs2,
1644 aq,
1645 rl,
1646 }),
1647 (0b011, 0b00001) => Ok(Instruction::AMOSWAPD {
1648 dest: rd,
1649 addr: rs1,
1650 src: rs2,
1651 aq,
1652 rl,
1653 }),
1654 (0b010, 0b00000) => Ok(Instruction::AMOADDW {
1655 dest: rd,
1656 addr: rs1,
1657 src: rs2,
1658 aq,
1659 rl,
1660 }),
1661 (0b011, 0b00000) => Ok(Instruction::AMOADDD {
1662 dest: rd,
1663 addr: rs1,
1664 src: rs2,
1665 aq,
1666 rl,
1667 }),
1668 (0b010, 0b00100) => Ok(Instruction::AMOXORW {
1669 dest: rd,
1670 addr: rs1,
1671 src: rs2,
1672 aq,
1673 rl,
1674 }),
1675 (0b011, 0b00100) => Ok(Instruction::AMOXORD {
1676 dest: rd,
1677 addr: rs1,
1678 src: rs2,
1679 aq,
1680 rl,
1681 }),
1682 (0b010, 0b01100) => Ok(Instruction::AMOANDW {
1683 dest: rd,
1684 addr: rs1,
1685 src: rs2,
1686 aq,
1687 rl,
1688 }),
1689 (0b011, 0b01100) => Ok(Instruction::AMOANDD {
1690 dest: rd,
1691 addr: rs1,
1692 src: rs2,
1693 aq,
1694 rl,
1695 }),
1696 (0b010, 0b01000) => Ok(Instruction::AMOORW {
1697 dest: rd,
1698 addr: rs1,
1699 src: rs2,
1700 aq,
1701 rl,
1702 }),
1703 (0b011, 0b01000) => Ok(Instruction::AMOORD {
1704 dest: rd,
1705 addr: rs1,
1706 src: rs2,
1707 aq,
1708 rl,
1709 }),
1710 (0b010, 0b10000) => Ok(Instruction::AMOMINW {
1711 dest: rd,
1712 addr: rs1,
1713 src: rs2,
1714 aq,
1715 rl,
1716 }),
1717 (0b011, 0b10000) => Ok(Instruction::AMOMIND {
1718 dest: rd,
1719 addr: rs1,
1720 src: rs2,
1721 aq,
1722 rl,
1723 }),
1724 (0b010, 0b10100) => Ok(Instruction::AMOMAXW {
1725 dest: rd,
1726 addr: rs1,
1727 src: rs2,
1728 aq,
1729 rl,
1730 }),
1731 (0b011, 0b10100) => Ok(Instruction::AMOMAXD {
1732 dest: rd,
1733 addr: rs1,
1734 src: rs2,
1735 aq,
1736 rl,
1737 }),
1738 (0b010, 0b11000) => Ok(Instruction::AMOMINUW {
1739 dest: rd,
1740 addr: rs1,
1741 src: rs2,
1742 aq,
1743 rl,
1744 }),
1745 (0b011, 0b11000) => Ok(Instruction::AMOMINUD {
1746 dest: rd,
1747 addr: rs1,
1748 src: rs2,
1749 aq,
1750 rl,
1751 }),
1752 (0b010, 0b11100) => Ok(Instruction::AMOMAXUW {
1753 dest: rd,
1754 addr: rs1,
1755 src: rs2,
1756 aq,
1757 rl,
1758 }),
1759 (0b011, 0b11100) => Ok(Instruction::AMOMAXUD {
1760 dest: rd,
1761 addr: rs1,
1762 src: rs2,
1763 aq,
1764 rl,
1765 }),
1766 _ => Err(format!("unknown AMO. func3: {func3}, func7: {func7}")),
1767 },
1768 Opcode::LoadFp => {
1769 println!("{i_immediate}, {:b}", instruction);
1770 if func3 == 0b010 {
1771 Ok(Instruction::FLW {
1772 dest: frd,
1773 base: rs1,
1774 offset: i_immediate,
1775 })
1776 } else {
1777 Err(format!("unknown func3: {func3} in opcode LoadFp"))
1778 }
1779 }
1780 Opcode::StoreFp => {
1781 if func3 == 0b010 {
1782 Ok(Instruction::FSW {
1783 base: rs1,
1784 src: frs2,
1785 offset: s_immediate,
1786 })
1787 } else {
1788 Err(format!("unknown func3: {func3} in opcode LoadFp"))
1789 }
1790 }
1791 Opcode::OpFp => match func7 {
1792 0b000_0000 => Ok(Instruction::FADDS {
1793 dest: frd,
1794 src1: frs1,
1795 src2: frs2,
1796 rm: RoundingMode::from_int(func3)?,
1797 }),
1798 0b000_0100 => Ok(Instruction::FSUBS {
1799 dest: frd,
1800 src1: frs1,
1801 src2: frs2,
1802 rm: RoundingMode::from_int(func3)?,
1803 }),
1804 0b000_1000 => Ok(Instruction::FMULS {
1805 dest: frd,
1806 src1: frs1,
1807 src2: frs2,
1808 rm: RoundingMode::from_int(func3)?,
1809 }),
1810 0b000_1100 => Ok(Instruction::FDIVS {
1811 dest: frd,
1812 src1: frs1,
1813 src2: frs2,
1814 rm: RoundingMode::from_int(func3)?,
1815 }),
1816 0b010_1100 => Ok(Instruction::FSQRTS {
1817 dest: frd,
1818 src: frs1,
1819 rm: RoundingMode::from_int(func3)?,
1820 }),
1821 0b001_0000 => match func3 {
1822 0b000 => Ok(Instruction::FSGNJS {
1823 dest: frd,
1824 src1: frs1,
1825 src2: frs2,
1826 }),
1827 0b001 => Ok(Instruction::FSGNJNS {
1828 dest: frd,
1829 src1: frs1,
1830 src2: frs2,
1831 }),
1832 0b010 => Ok(Instruction::FSGNJXS {
1833 dest: frd,
1834 src1: frs1,
1835 src2: frs2,
1836 }),
1837 x => Err(format!("unknown OpFp func7=0b001_0000 func3: {}", x)),
1838 },
1839 0b001_0100 => match func3 {
1840 0b000 => Ok(Instruction::FMINS {
1841 dest: frd,
1842 src1: frs1,
1843 src2: frs2,
1844 }),
1845 0b001 => Ok(Instruction::FMAXS {
1846 dest: frd,
1847 src1: frs1,
1848 src2: frs2,
1849 }),
1850 x => Err(format!("unknown OpFp func7=0b001_0100 func3: {}", x)),
1851 },
1852 0b101_0000 => match func3 {
1853 0b000 => Ok(Instruction::FLES {
1854 dest: rd,
1855 src1: frs1,
1856 src2: frs2,
1857 }),
1858 0b001 => Ok(Instruction::FLTS {
1859 dest: rd,
1860 src1: frs1,
1861 src2: frs2,
1862 }),
1863 0b010 => Ok(Instruction::FEQS {
1864 dest: rd,
1865 src1: frs1,
1866 src2: frs2,
1867 }),
1868 x => Err(format!("unknown OpFp func7=0b101_0000 func3: {}", x)),
1869 },
1870 0b110_0000 => match (instruction >> 20) & 0b1_1111 {
1871 0b0_0000 => Ok(Instruction::FCVTWS {
1872 dest: rd,
1873 src: frs1,
1874 rm: RoundingMode::from_int(func3)?,
1875 }),
1876 0b0_0001 => Ok(Instruction::FCVTWUS {
1877 dest: rd,
1878 src: frs1,
1879 rm: RoundingMode::from_int(func3)?,
1880 }),
1881 0b0_0010 => Ok(Instruction::FCVTLS {
1882 dest: rd,
1883 src: frs1,
1884 rm: RoundingMode::from_int(func3)?,
1885 }),
1886 0b0_0011 => Ok(Instruction::FCVTLUS {
1887 dest: rd,
1888 src: frs1,
1889 rm: RoundingMode::from_int(func3)?,
1890 }),
1891 x => Err(format!("unknown OpFp func7=0b001_0100 rs2: {}", x)),
1892 },
1893 0b110_1000 => match (instruction >> 20) & 0b1_1111 {
1894 0b0_0000 => Ok(Instruction::FCVTSW {
1895 dest: frd,
1896 src: rs1,
1897 rm: RoundingMode::from_int(func3)?,
1898 }),
1899 0b0_0001 => Ok(Instruction::FCVTSWU {
1900 dest: frd,
1901 src: rs1,
1902 rm: RoundingMode::from_int(func3)?,
1903 }),
1904 0b0_0010 => Ok(Instruction::FCVTSL {
1905 dest: frd,
1906 src: rs1,
1907 rm: RoundingMode::from_int(func3)?,
1908 }),
1909 0b0_0011 => Ok(Instruction::FCVTSLU {
1910 dest: frd,
1911 src: rs1,
1912 rm: RoundingMode::from_int(func3)?,
1913 }),
1914 x => Err(format!("unknown OpFp func7=0b001_0100 rs2: {}", x)),
1915 },
1916 0b111_0000 => {
1917 if (instruction >> 20) & 0b1_1111 == 0 {
1918 if func3 == 0 {
1919 Ok(Instruction::FMVXW {
1920 dest: rd,
1921 src: frs1,
1922 })
1923 } else if func3 == 1 {
1924 Ok(Instruction::FCLASSS {
1925 dest: rd,
1926 src: frs1,
1927 })
1928 } else {
1929 Err(format!(
1930 "unknown OpFp func7=0b111_0000 rs2=0 func3: {}",
1931 func3
1932 ))
1933 }
1934 } else {
1935 Err(format!(
1936 "unknown OpFp func7=0b111_0000 unknown rs2: {} and func3: {}",
1937 (instruction >> 20) & 0b1_1111,
1938 func3
1939 ))
1940 }
1941 }
1942 0b111_1000 => {
1943 if (instruction >> 20) & 0b1_1111 == 0 {
1944 if func3 == 0 {
1945 Ok(Instruction::FMVWX {
1946 dest: frd,
1947 src: rs1,
1948 })
1949 } else {
1950 Err(format!(
1951 "unknown OpFp func7=0b111_1000 rs2=0 func3: {}",
1952 func3
1953 ))
1954 }
1955 } else {
1956 Err(format!(
1957 "unknown OpFp func7=0b111_0000 unknown rs2: {} and func3: {}",
1958 (instruction >> 20) & 0b1_1111,
1959 func3
1960 ))
1961 }
1962 }
1963 x => Err(format!("Unknown OpFp func7: {x}")),
1964 },
1965 Opcode::Reserved => Err("instruction uses reserved opcode".to_owned()),
1966 Opcode::Madd => {
1967 if func7 & 0b11 == 0 {
1968 Ok(Instruction::FMADDS {
1969 dest: frd,
1970 src1: frs1,
1971 src2: frs2,
1972 src3: frs3,
1973 rm: RoundingMode::from_int(func3)?,
1974 })
1975 } else {
1976 Err(format!(
1977 "FMADD unknown lower 2 bits of func7: {}",
1978 func7 & 0b11
1979 ))
1980 }
1981 }
1982 Opcode::Msub => {
1983 if func7 & 0b11 == 0 {
1984 Ok(Instruction::FMSUBS {
1985 dest: frd,
1986 src1: frs1,
1987 src2: frs2,
1988 src3: frs3,
1989 rm: RoundingMode::from_int(func3)?,
1990 })
1991 } else {
1992 Err(format!(
1993 "FMSUB unknown lower 2 bits of func7: {}",
1994 func7 & 0b11
1995 ))
1996 }
1997 }
1998 Opcode::Nmsub => {
1999 if func7 & 0b11 == 0 {
2000 Ok(Instruction::FNMSUBS {
2001 dest: frd,
2002 src1: frs1,
2003 src2: frs2,
2004 src3: frs3,
2005 rm: RoundingMode::from_int(func3)?,
2006 })
2007 } else {
2008 Err(format!(
2009 "FMNSUB unknown lower 2 bits of func7: {}",
2010 func7 & 0b11
2011 ))
2012 }
2013 }
2014 Opcode::Nmadd => {
2015 if func7 & 0b11 == 0 {
2016 Ok(Instruction::FNMADDS {
2017 dest: frd,
2018 src1: frs1,
2019 src2: frs2,
2020 src3: frs3,
2021 rm: RoundingMode::from_int(func3)?,
2022 })
2023 } else {
2024 Err(format!(
2025 "FNMADD unknown lower 2 bits of func7: {}",
2026 func7 & 0b11
2027 ))
2028 }
2029 }
2030 Opcode::System => match func3 {
2031 0b000 => Err("Reserved func3 in Opcode SYSTEM".to_owned()),
2032 0b001 => Ok(Instruction::CSRRW {
2033 dest: rd,
2034 src: rs1,
2035 csr: CSR::from_u32(instruction),
2036 }),
2037 0b010 => Ok(Instruction::CSRRS {
2038 dest: rd,
2039 src: rs1,
2040 csr: CSR::from_u32(instruction),
2041 }),
2042 0b011 => Ok(Instruction::CSRRC {
2043 dest: rd,
2044 src: rs1,
2045 csr: CSR::from_u32(instruction),
2046 }),
2047 0b100 => Err("Reserved func3 in Opcode SYSTEM".to_owned()),
2048 0b101 => Ok(Instruction::CSRRWI {
2049 dest: rd,
2050 imm: CSRImmediate::from_u32(instruction),
2051 csr: CSR::from_u32(instruction),
2052 }),
2053 0b110 => Ok(Instruction::CSRRSI {
2054 dest: rd,
2055 imm: CSRImmediate::from_u32(instruction),
2056 csr: CSR::from_u32(instruction),
2057 }),
2058 0b111 => Ok(Instruction::CSRRCI {
2059 dest: rd,
2060 imm: CSRImmediate::from_u32(instruction),
2061 csr: CSR::from_u32(instruction),
2062 }),
2063 _ => unreachable!(),
2064 },
2065 }
2066 }
2067
2068 pub fn encode(instruction: &Instruction) -> u32 {
2069 match instruction {
2070 Instruction::LUI { dest, imm } => imm.to_u32() | dest.rd() | 0b0110111,
2071 Instruction::AUIPC { dest, imm } => imm.to_u32() | dest.rd() | 0b0010111,
2072 Instruction::JAL { dest, offset } => offset.to_u32() | dest.rd() | 0b1101111,
2073 Instruction::JALR { dest, base, offset } => {
2074 offset.to_u32() | base.rs1() | dest.rd() | 0b1100111
2075 }
2076 Instruction::BEQ { src1, src2, offset } => {
2077 offset.to_u32() | src2.rs2() | src1.rs1() | 0b000 << 12 | 0b1100011
2078 }
2079 Instruction::BNE { src1, src2, offset } => {
2080 offset.to_u32() | src2.rs2() | src1.rs1() | 0b001 << 12 | 0b1100011
2081 }
2082 Instruction::BLT { src1, src2, offset } => {
2083 offset.to_u32() | src2.rs2() | src1.rs1() | 0b100 << 12 | 0b1100011
2084 }
2085 Instruction::BGE { src1, src2, offset } => {
2086 offset.to_u32() | src2.rs2() | src1.rs1() | 0b101 << 12 | 0b1100011
2087 }
2088 Instruction::BLTU { src1, src2, offset } => {
2089 offset.to_u32() | src2.rs2() | src1.rs1() | 0b110 << 12 | 0b1100011
2090 }
2091 Instruction::BGEU { src1, src2, offset } => {
2092 offset.to_u32() | src2.rs2() | src1.rs1() | 0b111 << 12 | 0b1100011
2093 }
2094 Instruction::LB { dest, base, offset } => {
2095 offset.to_u32() | base.rs1() | 0b000 << 12 | dest.rd() | 0b0000011
2096 }
2097 Instruction::LH { dest, base, offset } => {
2098 offset.to_u32() | base.rs1() | 0b001 << 12 | dest.rd() | 0b0000011
2099 }
2100 Instruction::LW { dest, base, offset } => {
2101 offset.to_u32() | base.rs1() | 0b010 << 12 | dest.rd() | 0b0000011
2102 }
2103 Instruction::LBU { dest, base, offset } => {
2104 offset.to_u32() | base.rs1() | 0b100 << 12 | dest.rd() | 0b0000011
2105 }
2106 Instruction::LHU { dest, base, offset } => {
2107 offset.to_u32() | base.rs1() | 0b101 << 12 | dest.rd() | 0b0000011
2108 }
2109 Instruction::SB { src, base, offset } => {
2110 offset.to_u32() | src.rs2() | base.rs1() | 0b000 << 12 | 0b0100011
2111 }
2112 Instruction::SH { src, base, offset } => {
2113 offset.to_u32() | src.rs2() | base.rs1() | 0b001 << 12 | 0b0100011
2114 }
2115 Instruction::SW { src, base, offset } => {
2116 offset.to_u32() | src.rs2() | base.rs1() | 0b010 << 12 | 0b0100011
2117 }
2118 Instruction::ADDI { dest, src, imm } => {
2119 imm.to_u32() | src.rs1() | 0b000 << 12 | dest.rd() | 0b0010011
2120 }
2121 Instruction::SLTI { dest, src, imm } => {
2122 imm.to_u32() | src.rs1() | 0b010 << 12 | dest.rd() | 0b0010011
2123 }
2124 Instruction::SLTIU { dest, src, imm } => {
2125 imm.to_u32() | src.rs1() | 0b011 << 12 | dest.rd() | 0b0010011
2126 }
2127 Instruction::XORI { dest, src, imm } => {
2128 imm.to_u32() | src.rs1() | 0b100 << 12 | dest.rd() | 0b0010011
2129 }
2130 Instruction::ORI { dest, src, imm } => {
2131 imm.to_u32() | src.rs1() | 0b110 << 12 | dest.rd() | 0b0010011
2132 }
2133 Instruction::ANDI { dest, src, imm } => {
2134 imm.to_u32() | src.rs1() | 0b111 << 12 | dest.rd() | 0b0010011
2135 }
2136 Instruction::SLLI { dest, src, shamt } => {
2137 shamt.to_u32() | src.rs1() | 0b001 << 12 | dest.rd() | 0b0010011
2138 }
2139 Instruction::SRLI { dest, src, shamt } => {
2140 shamt.to_u32() | src.rs1() | 0b101 << 12 | dest.rd() | 0b0010011
2141 }
2142 Instruction::SRAI { dest, src, shamt } => {
2143 0b0100000 << 25 | shamt.to_u32() | src.rs1() | 0b101 << 12 | dest.rd() | 0b0010011
2144 }
2145 Instruction::ADD { dest, src1, src2 } => {
2146 src2.rs2() | src1.rs1() | 0b000 << 12 | dest.rd() | 0b0110011
2147 }
2148 Instruction::SUB { dest, src1, src2 } => {
2149 0b0100000 << 25 | src2.rs2() | src1.rs1() | 0b000 << 12 | dest.rd() | 0b0110011
2150 }
2151 Instruction::SLL { dest, src1, src2 } => {
2152 src2.rs2() | src1.rs1() | 0b001 << 12 | dest.rd() | 0b0110011
2153 }
2154 Instruction::SLT { dest, src1, src2 } => {
2155 src2.rs2() | src1.rs1() | 0b010 << 12 | dest.rd() | 0b0110011
2156 }
2157 Instruction::SLTU { dest, src1, src2 } => {
2158 src2.rs2() | src1.rs1() | 0b011 << 12 | dest.rd() | 0b0110011
2159 }
2160 Instruction::XOR { dest, src1, src2 } => {
2161 src2.rs2() | src1.rs1() | 0b100 << 12 | dest.rd() | 0b0110011
2162 }
2163 Instruction::SRL { dest, src1, src2 } => {
2164 src2.rs2() | src1.rs1() | 0b101 << 12 | dest.rd() | 0b0110011
2165 }
2166 Instruction::SRA { dest, src1, src2 } => {
2167 0b0100000 << 25 | src2.rs2() | src1.rs1() | 0b0101 << 12 | dest.rd() | 0b0110011
2168 }
2169 Instruction::OR { dest, src1, src2 } => {
2170 src2.rs2() | src1.rs1() | 0b110 << 12 | dest.rd() | 0b0110011
2171 }
2172 Instruction::AND { dest, src1, src2 } => {
2173 src2.rs2() | src1.rs1() | 0b111 << 12 | dest.rd() | 0b0110011
2174 }
2175 Instruction::FENCE { rd, rs1, ops, fm } => {
2176 (*fm as u32) << 28 | (*ops as u32) << 20 | rs1.rs1() | rd.rd() | 0b0001111
2177 }
2178 Instruction::ECALL => 0b1110011,
2179 Instruction::EBREAK => 0b1 << 20 | 0b1110011,
2180 Instruction::LWU { dest, base, offset } => {
2181 offset.to_u32() | base.rs1() | 0b110 << 12 | dest.rd() | 0b0000011
2182 }
2183 Instruction::LD { dest, base, offset } => {
2184 offset.to_u32() | base.rs1() | 0b011 << 12 | dest.rd() | 0b0000011
2185 }
2186 Instruction::SD { src, base, offset } => {
2187 offset.to_u32() | src.rs2() | base.rs1() | 0b011 << 12 | 0b0100011
2188 }
2189 Instruction::ADDIW { dest, src, imm } => {
2190 imm.to_u32() | src.rs1() | 0b000 << 12 | dest.rd() | 0b0011011
2191 }
2192 Instruction::SLLIW { dest, src, shamt } => {
2193 shamt.to_u32() | src.rs1() | 0b001 << 12 | dest.rd() | 0b0011011
2194 }
2195 Instruction::SRLIW { dest, src, shamt } => {
2196 shamt.to_u32() | src.rs1() | 0b101 << 12 | dest.rd() | 0b0011011
2197 }
2198 Instruction::SRAIW { dest, src, shamt } => {
2199 0b0100000 << 25 | shamt.to_u32() | src.rs1() | 0b101 << 12 | dest.rd() | 0b0011011
2200 }
2201 Instruction::ADDW { dest, src1, src2 } => {
2202 src2.rs2() | src1.rs1() | 0b000 << 12 | dest.rd() | 0b0111011
2203 }
2204 Instruction::SUBW { dest, src1, src2 } => {
2205 0b0100000 << 25 | src2.rs2() | src1.rs1() | 0b000 << 12 | dest.rd() | 0b0111011
2206 }
2207 Instruction::SLLW { dest, src1, src2 } => {
2208 src2.rs2() | src1.rs1() | 0b001 << 12 | dest.rd() | 0b0111011
2209 }
2210 Instruction::SRLW { dest, src1, src2 } => {
2211 src2.rs2() | src1.rs1() | 0b101 << 12 | dest.rd() | 0b0111011
2212 }
2213 Instruction::SRAW { dest, src1, src2 } => {
2214 0b0100000 << 25 | src2.rs2() | src1.rs1() | 0b101 << 12 | dest.rd() | 0b0111011
2215 }
2216 Instruction::MUL { dest, src1, src2 } => {
2217 0b0000001 << 25 | src2.rs2() | src1.rs1() | 0b000 << 12 | dest.rd() | 0b0110011
2218 }
2219 Instruction::MULH { dest, src1, src2 } => {
2220 0b0000001 << 25 | src2.rs2() | src1.rs1() | 0b001 << 12 | dest.rd() | 0b0110011
2221 }
2222 Instruction::MULHSU { dest, src1, src2 } => {
2223 0b0000001 << 25 | src2.rs2() | src1.rs1() | 0b010 << 12 | dest.rd() | 0b0110011
2224 }
2225 Instruction::MULHU { dest, src1, src2 } => {
2226 0b0000001 << 25 | src2.rs2() | src1.rs1() | 0b011 << 12 | dest.rd() | 0b0110011
2227 }
2228 Instruction::DIV { dest, src1, src2 } => {
2229 0b0000001 << 25 | src2.rs2() | src1.rs1() | 0b100 << 12 | dest.rd() | 0b0110011
2230 }
2231 Instruction::DIVU { dest, src1, src2 } => {
2232 0b0000001 << 25 | src2.rs2() | src1.rs1() | 0b101 << 12 | dest.rd() | 0b0110011
2233 }
2234 Instruction::REM { dest, src1, src2 } => {
2235 0b0000001 << 25 | src2.rs2() | src1.rs1() | 0b110 << 12 | dest.rd() | 0b0110011
2236 }
2237 Instruction::REMU { dest, src1, src2 } => {
2238 0b0000001 << 25 | src2.rs2() | src1.rs1() | 0b111 << 12 | dest.rd() | 0b0110011
2239 }
2240 Instruction::MULW { dest, src1, src2 } => {
2241 0b0000001 << 25 | src2.rs2() | src1.rs1() | 0b000 << 12 | dest.rd() | 0b0111011
2242 }
2243 Instruction::DIVW { dest, src1, src2 } => {
2244 0b0000001 << 25 | src2.rs2() | src1.rs1() | 0b100 << 12 | dest.rd() | 0b0111011
2245 }
2246 Instruction::DIVUW { dest, src1, src2 } => {
2247 0b0000001 << 25 | src2.rs2() | src1.rs1() | 0b101 << 12 | dest.rd() | 0b0111011
2248 }
2249 Instruction::REMW { dest, src1, src2 } => {
2250 0b0000001 << 25 | src2.rs2() | src1.rs1() | 0b110 << 12 | dest.rd() | 0b0111011
2251 }
2252 Instruction::REMUW { dest, src1, src2 } => {
2253 0b0000001 << 25 | src2.rs2() | src1.rs1() | 0b111 << 12 | dest.rd() | 0b0111011
2254 }
2255 Instruction::LRW { dest, addr, aq, rl } => {
2256 0b00010 << 27
2257 | aqb(*aq)
2258 | rlb(*rl)
2259 | addr.rs1()
2260 | 0b010 << 12
2261 | dest.rd()
2262 | 0b0101111
2263 }
2264 Instruction::SCW {
2265 dest,
2266 addr,
2267 src,
2268 aq,
2269 rl,
2270 } => {
2271 0b00011 << 27
2272 | aqb(*aq)
2273 | rlb(*rl)
2274 | src.rs2()
2275 | addr.rs1()
2276 | 0b010 << 12
2277 | dest.rd()
2278 | 0b0101111
2279 }
2280 Instruction::AMOSWAPW {
2281 dest,
2282 addr,
2283 src,
2284 aq,
2285 rl,
2286 } => {
2287 0b00001 << 27
2288 | aqb(*aq)
2289 | rlb(*rl)
2290 | src.rs2()
2291 | addr.rs1()
2292 | 0b010 << 12
2293 | dest.rd()
2294 | 0b0101111
2295 }
2296 Instruction::AMOADDW {
2297 dest,
2298 addr,
2299 src,
2300 aq,
2301 rl,
2302 } => {
2303 0b00000 << 27
2304 | aqb(*aq)
2305 | rlb(*rl)
2306 | src.rs2()
2307 | addr.rs1()
2308 | 0b010 << 12
2309 | dest.rd()
2310 | 0b0101111
2311 }
2312 Instruction::AMOXORW {
2313 dest,
2314 addr,
2315 src,
2316 aq,
2317 rl,
2318 } => {
2319 0b00100 << 27
2320 | aqb(*aq)
2321 | rlb(*rl)
2322 | src.rs2()
2323 | addr.rs1()
2324 | 0b010 << 12
2325 | dest.rd()
2326 | 0b0101111
2327 }
2328 Instruction::AMOANDW {
2329 dest,
2330 addr,
2331 src,
2332 aq,
2333 rl,
2334 } => {
2335 0b01100 << 27
2336 | aqb(*aq)
2337 | rlb(*rl)
2338 | src.rs2()
2339 | addr.rs1()
2340 | 0b010 << 12
2341 | dest.rd()
2342 | 0b0101111
2343 }
2344 Instruction::AMOORW {
2345 dest,
2346 addr,
2347 src,
2348 aq,
2349 rl,
2350 } => {
2351 0b01000 << 27
2352 | aqb(*aq)
2353 | rlb(*rl)
2354 | src.rs2()
2355 | addr.rs1()
2356 | 0b010 << 12
2357 | dest.rd()
2358 | 0b0101111
2359 }
2360 Instruction::AMOMINW {
2361 dest,
2362 addr,
2363 src,
2364 aq,
2365 rl,
2366 } => {
2367 0b10000 << 27
2368 | aqb(*aq)
2369 | rlb(*rl)
2370 | src.rs2()
2371 | addr.rs1()
2372 | 0b010 << 12
2373 | dest.rd()
2374 | 0b0101111
2375 }
2376 Instruction::AMOMAXW {
2377 dest,
2378 addr,
2379 src,
2380 aq,
2381 rl,
2382 } => {
2383 0b10100 << 27
2384 | aqb(*aq)
2385 | rlb(*rl)
2386 | src.rs2()
2387 | addr.rs1()
2388 | 0b010 << 12
2389 | dest.rd()
2390 | 0b0101111
2391 }
2392 Instruction::AMOMINUW {
2393 dest,
2394 addr,
2395 src,
2396 aq,
2397 rl,
2398 } => {
2399 0b11000 << 27
2400 | aqb(*aq)
2401 | rlb(*rl)
2402 | src.rs2()
2403 | addr.rs1()
2404 | 0b010 << 12
2405 | dest.rd()
2406 | 0b0101111
2407 }
2408 Instruction::AMOMAXUW {
2409 dest,
2410 addr,
2411 src,
2412 aq,
2413 rl,
2414 } => {
2415 0b11100 << 27
2416 | aqb(*aq)
2417 | rlb(*rl)
2418 | src.rs2()
2419 | addr.rs1()
2420 | 0b010 << 12
2421 | dest.rd()
2422 | 0b0101111
2423 }
2424 Instruction::LRD { dest, addr, aq, rl } => {
2425 0b00010 << 27
2426 | aqb(*aq)
2427 | rlb(*rl)
2428 | addr.rs1()
2429 | 0b011 << 12
2430 | dest.rd()
2431 | 0b0101111
2432 }
2433 Instruction::SCD {
2434 dest,
2435 addr,
2436 src,
2437 aq,
2438 rl,
2439 } => {
2440 0b00011 << 27
2441 | aqb(*aq)
2442 | rlb(*rl)
2443 | src.rs2()
2444 | addr.rs1()
2445 | 0b011 << 12
2446 | dest.rd()
2447 | 0b0101111
2448 }
2449 Instruction::AMOSWAPD {
2450 dest,
2451 addr,
2452 src,
2453 aq,
2454 rl,
2455 } => {
2456 0b00001 << 27
2457 | aqb(*aq)
2458 | rlb(*rl)
2459 | src.rs2()
2460 | addr.rs1()
2461 | 0b011 << 12
2462 | dest.rd()
2463 | 0b0101111
2464 }
2465 Instruction::AMOADDD {
2466 dest,
2467 addr,
2468 src,
2469 aq,
2470 rl,
2471 } => {
2472 0b00000 << 27
2473 | aqb(*aq)
2474 | rlb(*rl)
2475 | src.rs2()
2476 | addr.rs1()
2477 | 0b011 << 12
2478 | dest.rd()
2479 | 0b0101111
2480 }
2481 Instruction::AMOXORD {
2482 dest,
2483 addr,
2484 src,
2485 aq,
2486 rl,
2487 } => {
2488 0b00100 << 27
2489 | aqb(*aq)
2490 | rlb(*rl)
2491 | src.rs2()
2492 | addr.rs1()
2493 | 0b011 << 12
2494 | dest.rd()
2495 | 0b0101111
2496 }
2497 Instruction::AMOANDD {
2498 dest,
2499 addr,
2500 src,
2501 aq,
2502 rl,
2503 } => {
2504 0b01100 << 27
2505 | aqb(*aq)
2506 | rlb(*rl)
2507 | src.rs2()
2508 | addr.rs1()
2509 | 0b011 << 12
2510 | dest.rd()
2511 | 0b0101111
2512 }
2513 Instruction::AMOORD {
2514 dest,
2515 addr,
2516 src,
2517 aq,
2518 rl,
2519 } => {
2520 0b01000 << 27
2521 | aqb(*aq)
2522 | rlb(*rl)
2523 | src.rs2()
2524 | addr.rs1()
2525 | 0b011 << 12
2526 | dest.rd()
2527 | 0b0101111
2528 }
2529 Instruction::AMOMIND {
2530 dest,
2531 addr,
2532 src,
2533 aq,
2534 rl,
2535 } => {
2536 0b10000 << 27
2537 | aqb(*aq)
2538 | rlb(*rl)
2539 | src.rs2()
2540 | addr.rs1()
2541 | 0b011 << 12
2542 | dest.rd()
2543 | 0b0101111
2544 }
2545 Instruction::AMOMAXD {
2546 dest,
2547 addr,
2548 src,
2549 aq,
2550 rl,
2551 } => {
2552 0b10100 << 27
2553 | aqb(*aq)
2554 | rlb(*rl)
2555 | src.rs2()
2556 | addr.rs1()
2557 | 0b011 << 12
2558 | dest.rd()
2559 | 0b0101111
2560 }
2561 Instruction::AMOMINUD {
2562 dest,
2563 addr,
2564 src,
2565 aq,
2566 rl,
2567 } => {
2568 0b11000 << 27
2569 | aqb(*aq)
2570 | rlb(*rl)
2571 | src.rs2()
2572 | addr.rs1()
2573 | 0b011 << 12
2574 | dest.rd()
2575 | 0b0101111
2576 }
2577 Instruction::AMOMAXUD {
2578 dest,
2579 addr,
2580 src,
2581 aq,
2582 rl,
2583 } => {
2584 0b11100 << 27
2585 | aqb(*aq)
2586 | rlb(*rl)
2587 | src.rs2()
2588 | addr.rs1()
2589 | 0b011 << 12
2590 | dest.rd()
2591 | 0b0101111
2592 }
2593 Instruction::FLW { dest, base, offset } => {
2594 offset.to_u32() | base.rs1() | 0b010 << 12 | dest.rd() | 0b0000111
2595 }
2596 Instruction::FSW { base, src, offset } => {
2597 offset.to_u32() | src.rs2() | base.rs1() | 0b010 << 12 | 0b0100111
2598 }
2599 Instruction::FMADDS {
2600 dest,
2601 src1,
2602 src2,
2603 src3,
2604 rm,
2605 } => src3.rs3() | src2.rs2() | src1.rs1() | rm.to_u32() | dest.rd() | 0b1000011,
2606 Instruction::FMSUBS {
2607 dest,
2608 src1,
2609 src2,
2610 src3,
2611 rm,
2612 } => src3.rs3() | src2.rs2() | src1.rs1() | rm.to_u32() | dest.rd() | 0b1000111,
2613 Instruction::FNMSUBS {
2614 dest,
2615 src1,
2616 src2,
2617 src3,
2618 rm,
2619 } => src3.rs3() | src2.rs2() | src1.rs1() | rm.to_u32() | dest.rd() | 0b1001011,
2620 Instruction::FNMADDS {
2621 dest,
2622 src1,
2623 src2,
2624 src3,
2625 rm,
2626 } => src3.rs3() | src2.rs2() | src1.rs1() | rm.to_u32() | dest.rd() | 0b1001111,
2627 Instruction::FADDS {
2628 dest,
2629 src1,
2630 src2,
2631 rm,
2632 } => 0b0000000 << 25 | src2.rs2() | src1.rs1() | rm.to_u32() | dest.rd() | 0b1010011,
2633 Instruction::FSUBS {
2634 dest,
2635 src1,
2636 src2,
2637 rm,
2638 } => 0b0000100 << 25 | src2.rs2() | src1.rs1() | rm.to_u32() | dest.rd() | 0b1010011,
2639 Instruction::FMULS {
2640 dest,
2641 src1,
2642 src2,
2643 rm,
2644 } => 0b0001000 << 25 | src2.rs2() | src1.rs1() | rm.to_u32() | dest.rd() | 0b1010011,
2645 Instruction::FDIVS {
2646 dest,
2647 src1,
2648 src2,
2649 rm,
2650 } => 0b0001100 << 25 | src2.rs2() | src1.rs1() | rm.to_u32() | dest.rd() | 0b1010011,
2651 Instruction::FSQRTS { dest, src, rm } => {
2652 0b0101100 << 25 | src.rs1() | rm.to_u32() | dest.rd() | 0b1010011
2653 }
2654 Instruction::FSGNJS { dest, src1, src2 } => {
2655 0b0010000 << 25 | src2.rs2() | src1.rs1() | 0b000 << 12 | dest.rd() | 0b1010011
2656 }
2657
2658 Instruction::FSGNJNS { dest, src1, src2 } => {
2659 0b0010000 << 25 | src2.rs2() | src1.rs1() | 0b001 << 12 | dest.rd() | 0b1010011
2660 }
2661 Instruction::FSGNJXS { dest, src1, src2 } => {
2662 0b0010000 << 25 | src2.rs2() | src1.rs1() | 0b010 << 12 | dest.rd() | 0b1010011
2663 }
2664 Instruction::FMINS { dest, src1, src2 } => {
2665 0b0010100 << 25 | src2.rs2() | src1.rs1() | 0b000 << 12 | dest.rd() | 0b1010011
2666 }
2667 Instruction::FMAXS { dest, src1, src2 } => {
2668 0b0010100 << 25 | src2.rs2() | src1.rs1() | 0b001 << 12 | dest.rd() | 0b1010011
2669 }
2670 Instruction::FCVTWS { dest, src, rm } => {
2671 0b1100000 << 25 | 0b00000 << 20 | src.rs1() | rm.to_u32() | dest.rd() | 0b1010011
2672 }
2673 Instruction::FCVTWUS { dest, src, rm } => {
2674 0b1100000 << 25 | 0b00001 << 20 | src.rs1() | rm.to_u32() | dest.rd() | 0b1010011
2675 }
2676 Instruction::FMVXW { dest, src } => 0b1110000 << 25 | src.rs1() | dest.rd() | 0b1010011,
2677 Instruction::FEQS { dest, src1, src2 } => {
2678 0b1010000 << 25 | src2.rs2() | src1.rs1() | 0b010 << 12 | dest.rd() | 0b1010011
2679 }
2680 Instruction::FLTS { dest, src1, src2 } => {
2681 0b1010000 << 25 | src2.rs2() | src1.rs1() | 0b001 << 12 | dest.rd() | 0b1010011
2682 }
2683 Instruction::FLES { dest, src1, src2 } => {
2684 0b1010000 << 25 | src2.rs2() | src1.rs1() | 0b000 << 12 | dest.rd() | 0b1010011
2685 }
2686 Instruction::FCLASSS { dest, src } => {
2687 0b1110000 << 25 | src.rs1() | 0b001 << 12 | dest.rd() | 0b1010011
2688 }
2689 Instruction::FCVTSW { dest, src, rm } => {
2690 0b1101000 << 25 | src.rs1() | rm.to_u32() | dest.rd() | 0b1010011
2691 }
2692 Instruction::FCVTSWU { dest, src, rm } => {
2693 0b1101000 << 25 | 0b00001 << 20 | src.rs1() | rm.to_u32() | dest.rd() | 0b1010011
2694 }
2695 Instruction::FMVWX { dest, src } => 0b1111000 << 25 | src.rs1() | dest.rd() | 0b1010011,
2696 Instruction::FCVTLS { dest, src, rm } => {
2697 0b1100000 << 25 | 0b00010 << 20 | src.rs1() | rm.to_u32() | dest.rd() | 0b1010011
2698 }
2699 Instruction::FCVTLUS { dest, src, rm } => {
2700 0b1100000 << 25 | 0b00011 << 20 | src.rs1() | rm.to_u32() | dest.rd() | 0b1010011
2701 }
2702 Instruction::FCVTSL { dest, src, rm } => {
2703 0b1101000 << 25 | 0b00010 << 20 | src.rs1() | rm.to_u32() | dest.rd() | 0b1010011
2704 }
2705 Instruction::FCVTSLU { dest, src, rm } => {
2706 0b1101000 << 25 | 0b00011 << 20 | src.rs1() | rm.to_u32() | dest.rd() | 0b1010011
2707 }
2708 Instruction::CSRRW { dest, src, csr } => {
2709 csr.to_u32() | src.rs1() | 0b001 << 12 | dest.rd() | 0b1110011
2710 }
2711 Instruction::CSRRS { dest, src, csr } => {
2712 csr.to_u32() | src.rs1() | 0b010 << 12 | dest.rd() | 0b1110011
2713 }
2714 Instruction::CSRRC { dest, src, csr } => {
2715 csr.to_u32() | src.rs1() | 0b011 << 12 | dest.rd() | 0b1110011
2716 }
2717 Instruction::CSRRWI { dest, imm, csr } => {
2718 csr.to_u32() | imm.to_u32() | 0b101 << 12 | dest.rd() | 0b1110011
2719 }
2720 Instruction::CSRRSI { dest, imm, csr } => {
2721 csr.to_u32() | imm.to_u32() | 0b110 << 12 | dest.rd() | 0b1110011
2722 }
2723 Instruction::CSRRCI { dest, imm, csr } => {
2724 csr.to_u32() | imm.to_u32() | 0b111 << 12 | dest.rd() | 0b1110011
2725 }
2726 Instruction::FENCEI => 0b001 << 12 | 0b0001111,
2727 }
2728 }
2729}
2730
2731pub fn disassemble_instruction(instruction: &Instruction) -> String {
2733 format!("{}", instruction)
2734}