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 alloc::borrow::ToOwned;
7use alloc::fmt::{Display, Formatter};
8use alloc::format;
9use alloc::string::String;
10
11#[derive(Debug, PartialEq, Clone, Copy)]
12pub enum RoundingMode {
13 RNE = 0b000,
15 RTZ = 0b001,
17 RDN = 0b010,
19 RUP = 0b011,
21 RMM = 0b100,
23 DYN = 0b111,
25}
26
27impl Display for RoundingMode {
28 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), alloc::fmt::Error> {
29 match self {
30 RoundingMode::RNE => write!(f, "rne"),
31 RoundingMode::RTZ => write!(f, "rtz"),
32 RoundingMode::RDN => write!(f, "rdn"),
33 RoundingMode::RUP => write!(f, "rup"),
34 RoundingMode::RMM => write!(f, "rmm"),
35 RoundingMode::DYN => write!(f, "dyn"),
36 }
37 }
38}
39
40impl RoundingMode {
41 pub fn from_int(x: u32) -> Result<RoundingMode, String> {
42 match x {
43 0b000 => Ok(RoundingMode::RNE),
44 0b001 => Ok(RoundingMode::RTZ),
45 0b010 => Ok(RoundingMode::RDN),
46 0b011 => Ok(RoundingMode::RUP),
47 0b100 => Ok(RoundingMode::RMM),
48 0b111 => Ok(RoundingMode::DYN),
49 _ => Err("attempted to create invalid rounding mode".to_owned()),
50 }
51 }
52 pub fn from_str(x: &str) -> Result<RoundingMode, String> {
53 match x {
54 "rne" => Ok(RoundingMode::RNE),
55 "rtz" => Ok(RoundingMode::RTZ),
56 "rdn" => Ok(RoundingMode::RDN),
57 "rup" => Ok(RoundingMode::RUP),
58 "rmm" => Ok(RoundingMode::RMM),
59 "dyn" => Ok(RoundingMode::DYN),
60 _ => Err("attempted to create invalid rounding mode".to_owned()),
61 }
62 }
63
64 pub fn to_u32(self) -> u32 {
65 return (self as u32) << 12;
66 }
67}
68
69#[derive(Debug, PartialEq)]
70pub enum Instruction {
71 Lui {
76 dest: IRegister,
77 imm: UImmediate,
78 },
79 Auipc {
81 dest: IRegister,
82 imm: UImmediate,
83 },
84 Jal {
86 dest: IRegister,
87 offset: JImmediate,
88 },
89 Jalr {
91 dest: IRegister,
92 base: IRegister,
93 offset: IImmediate,
94 },
95 Beq {
96 src1: IRegister,
97 src2: IRegister,
98 offset: BImmediate,
99 },
100 Bne {
101 src1: IRegister,
102 src2: IRegister,
103 offset: BImmediate,
104 },
105 Blt {
106 src1: IRegister,
107 src2: IRegister,
108 offset: BImmediate,
109 },
110 Bge {
111 src1: IRegister,
112 src2: IRegister,
113 offset: BImmediate,
114 },
115 Bltu {
116 src1: IRegister,
117 src2: IRegister,
118 offset: BImmediate,
119 },
120 Bgeu {
121 src1: IRegister,
122 src2: IRegister,
123 offset: BImmediate,
124 },
125 Lb {
127 dest: IRegister,
128 base: IRegister,
129 offset: IImmediate,
130 },
131 Lh {
133 dest: IRegister,
134 base: IRegister,
135 offset: IImmediate,
136 },
137 Lw {
139 dest: IRegister,
140 base: IRegister,
141 offset: IImmediate,
142 },
143 Lbu {
145 dest: IRegister,
146 base: IRegister,
147 offset: IImmediate,
148 },
149 Lhu {
151 dest: IRegister,
152 base: IRegister,
153 offset: IImmediate,
154 },
155 Sb {
157 src: IRegister,
158 base: IRegister,
159 offset: SImmediate,
160 },
161 Sh {
163 src: IRegister,
164 base: IRegister,
165 offset: SImmediate,
166 },
167 Sw {
169 src: IRegister,
170 base: IRegister,
171 offset: SImmediate,
172 },
173 Addi {
174 dest: IRegister,
175 src: IRegister,
176 imm: IImmediate,
177 },
178 Slti {
179 dest: IRegister,
180 src: IRegister,
181 imm: IImmediate,
182 },
183 Sltiu {
184 dest: IRegister,
185 src: IRegister,
186 imm: IImmediate,
187 },
188 Xori {
189 dest: IRegister,
190 src: IRegister,
191 imm: IImmediate,
192 },
193 Ori {
194 dest: IRegister,
195 src: IRegister,
196 imm: IImmediate,
197 },
198 Andi {
199 dest: IRegister,
200 src: IRegister,
201 imm: IImmediate,
202 },
203 Slli {
205 dest: IRegister,
206 src: IRegister,
207 shamt: Shamt,
208 },
209 Srli {
211 dest: IRegister,
212 src: IRegister,
213 shamt: Shamt,
214 },
215 Srai {
217 dest: IRegister,
218 src: IRegister,
219 shamt: Shamt,
220 },
221 Add {
222 dest: IRegister,
223 src1: IRegister,
224 src2: IRegister,
225 },
226 Sub {
227 dest: IRegister,
228 src1: IRegister,
229 src2: IRegister,
230 },
231 Sll {
233 dest: IRegister,
234 src1: IRegister,
235 src2: IRegister,
236 },
237 Slt {
238 dest: IRegister,
239 src1: IRegister,
240 src2: IRegister,
241 },
242 Sltu {
243 dest: IRegister,
244 src1: IRegister,
245 src2: IRegister,
246 },
247 Xor {
248 dest: IRegister,
249 src1: IRegister,
250 src2: IRegister,
251 },
252 Srl {
254 dest: IRegister,
255 src1: IRegister,
256 src2: IRegister,
257 },
258 Sra {
260 dest: IRegister,
261 src1: IRegister,
262 src2: IRegister,
263 },
264 Or {
265 dest: IRegister,
266 src1: IRegister,
267 src2: IRegister,
268 },
269 And {
270 dest: IRegister,
271 src1: IRegister,
272 src2: IRegister,
273 },
274 Fence {
275 rd: IRegister,
276 rs1: IRegister,
277 ops: u8,
278 fm: u8,
279 },
280 Ecall,
281 Ebreak,
282 Lwu {
287 dest: IRegister,
288 base: IRegister,
289 offset: IImmediate,
290 },
291 Ld {
293 dest: IRegister,
294 base: IRegister,
295 offset: IImmediate,
296 },
297 Sd {
299 src: IRegister,
300 base: IRegister,
301 offset: SImmediate,
302 },
303 Addiw {
305 dest: IRegister,
306 src: IRegister,
307 imm: IImmediate,
308 },
309 Slliw {
311 dest: IRegister,
312 src: IRegister,
313 shamt: ShamtW,
314 },
315 Srliw {
317 dest: IRegister,
318 src: IRegister,
319 shamt: ShamtW,
320 },
321 Sraiw {
323 dest: IRegister,
324 src: IRegister,
325 shamt: ShamtW,
326 },
327 Addw {
329 dest: IRegister,
330 src1: IRegister,
331 src2: IRegister,
332 },
333 Subw {
335 dest: IRegister,
336 src1: IRegister,
337 src2: IRegister,
338 },
339 Sllw {
341 dest: IRegister,
342 src1: IRegister,
343 src2: IRegister,
344 },
345 Srlw {
347 dest: IRegister,
348 src1: IRegister,
349 src2: IRegister,
350 },
351 Sraw {
353 dest: IRegister,
354 src1: IRegister,
355 src2: IRegister,
356 },
357 Mul {
362 dest: IRegister,
363 src1: IRegister,
364 src2: IRegister,
365 },
366 Mulh {
368 dest: IRegister,
369 src1: IRegister,
370 src2: IRegister,
371 },
372 Mulhsu {
374 dest: IRegister,
375 src1: IRegister,
376 src2: IRegister,
377 },
378 Mulhu {
380 dest: IRegister,
381 src1: IRegister,
382 src2: IRegister,
383 },
384 Div {
386 dest: IRegister,
387 src1: IRegister,
388 src2: IRegister,
389 },
390 Divu {
392 dest: IRegister,
393 src1: IRegister,
394 src2: IRegister,
395 },
396 Rem {
398 dest: IRegister,
399 src1: IRegister,
400 src2: IRegister,
401 },
402 Remu {
404 dest: IRegister,
405 src1: IRegister,
406 src2: IRegister,
407 },
408 Mulw {
410 dest: IRegister,
411 src1: IRegister,
412 src2: IRegister,
413 },
414 Divw {
416 dest: IRegister,
417 src1: IRegister,
418 src2: IRegister,
419 },
420 Divuw {
422 dest: IRegister,
423 src1: IRegister,
424 src2: IRegister,
425 },
426 Remw {
428 dest: IRegister,
429 src1: IRegister,
430 src2: IRegister,
431 },
432 Remuw {
434 dest: IRegister,
435 src1: IRegister,
436 src2: IRegister,
437 },
438 LrW {
444 dest: IRegister,
445 addr: IRegister,
446 aq: bool,
447 rl: bool,
448 },
449 ScW {
450 dest: IRegister,
451 addr: IRegister,
452 src: IRegister,
453 aq: bool,
454 rl: bool,
455 },
456 AmoswapW {
457 dest: IRegister,
458 addr: IRegister,
459 src: IRegister,
460 aq: bool,
461 rl: bool,
462 },
463 AmoaddW {
464 dest: IRegister,
465 addr: IRegister,
466 src: IRegister,
467 aq: bool,
468 rl: bool,
469 },
470 AmoxorW {
471 dest: IRegister,
472 addr: IRegister,
473 src: IRegister,
474 aq: bool,
475 rl: bool,
476 },
477 AmoandW {
478 dest: IRegister,
479 addr: IRegister,
480 src: IRegister,
481 aq: bool,
482 rl: bool,
483 },
484 AmoorW {
485 dest: IRegister,
486 addr: IRegister,
487 src: IRegister,
488 aq: bool,
489 rl: bool,
490 },
491 AmominW {
492 dest: IRegister,
493 addr: IRegister,
494 src: IRegister,
495 aq: bool,
496 rl: bool,
497 },
498 AmomaxW {
499 dest: IRegister,
500 addr: IRegister,
501 src: IRegister,
502 aq: bool,
503 rl: bool,
504 },
505 AmominuW {
506 dest: IRegister,
507 addr: IRegister,
508 src: IRegister,
509 aq: bool,
510 rl: bool,
511 },
512 AmomaxuW {
513 dest: IRegister,
514 addr: IRegister,
515 src: IRegister,
516 aq: bool,
517 rl: bool,
518 },
519 LrD {
521 dest: IRegister,
522 addr: IRegister,
523 aq: bool,
524 rl: bool,
525 },
526 ScD {
527 dest: IRegister,
528 addr: IRegister,
529 src: IRegister,
530 aq: bool,
531 rl: bool,
532 },
533 AmoswapD {
534 dest: IRegister,
535 addr: IRegister,
536 src: IRegister,
537 aq: bool,
538 rl: bool,
539 },
540 AmoaddD {
541 dest: IRegister,
542 addr: IRegister,
543 src: IRegister,
544 aq: bool,
545 rl: bool,
546 },
547 AmoxorD {
548 dest: IRegister,
549 addr: IRegister,
550 src: IRegister,
551 aq: bool,
552 rl: bool,
553 },
554 AmoandD {
555 dest: IRegister,
556 addr: IRegister,
557 src: IRegister,
558 aq: bool,
559 rl: bool,
560 },
561 AmoorD {
562 dest: IRegister,
563 addr: IRegister,
564 src: IRegister,
565 aq: bool,
566 rl: bool,
567 },
568 AmominD {
569 dest: IRegister,
570 addr: IRegister,
571 src: IRegister,
572 aq: bool,
573 rl: bool,
574 },
575 AmomaxD {
576 dest: IRegister,
577 addr: IRegister,
578 src: IRegister,
579 aq: bool,
580 rl: bool,
581 },
582 AmominuD {
583 dest: IRegister,
584 addr: IRegister,
585 src: IRegister,
586 aq: bool,
587 rl: bool,
588 },
589 AmomaxuD {
590 dest: IRegister,
591 addr: IRegister,
592 src: IRegister,
593 aq: bool,
594 rl: bool,
595 },
596 Flw {
600 dest: FRegister,
601 base: IRegister,
602 offset: IImmediate,
603 },
604 Fsw {
605 base: IRegister,
606 src: FRegister,
607 offset: SImmediate,
608 },
609 FmaddS {
610 dest: FRegister,
611 src1: FRegister,
612 src2: FRegister,
613 src3: FRegister,
614 rm: RoundingMode,
615 },
616 FmsubS {
617 dest: FRegister,
618 src1: FRegister,
619 src2: FRegister,
620 src3: FRegister,
621 rm: RoundingMode,
622 },
623 FnmsubS {
624 dest: FRegister,
625 src1: FRegister,
626 src2: FRegister,
627 src3: FRegister,
628 rm: RoundingMode,
629 },
630 FnmaddS {
631 dest: FRegister,
632 src1: FRegister,
633 src2: FRegister,
634 src3: FRegister,
635 rm: RoundingMode,
636 },
637 FaddS {
638 dest: FRegister,
639 src1: FRegister,
640 src2: FRegister,
641 rm: RoundingMode,
642 },
643 FsubS {
644 dest: FRegister,
645 src1: FRegister,
646 src2: FRegister,
647 rm: RoundingMode,
648 },
649 FmulS {
650 dest: FRegister,
651 src1: FRegister,
652 src2: FRegister,
653 rm: RoundingMode,
654 },
655 FdivS {
656 dest: FRegister,
657 src1: FRegister,
658 src2: FRegister,
659 rm: RoundingMode,
660 },
661 FsqrtS {
662 dest: FRegister,
663 src: FRegister,
664 rm: RoundingMode,
665 },
666 FsgnjS {
667 dest: FRegister,
668 src1: FRegister,
669 src2: FRegister,
670 },
671 FsgnjnS {
672 dest: FRegister,
673 src1: FRegister,
674 src2: FRegister,
675 },
676 FsgnjxS {
677 dest: FRegister,
678 src1: FRegister,
679 src2: FRegister,
680 },
681 FminS {
682 dest: FRegister,
683 src1: FRegister,
684 src2: FRegister,
685 },
686 FmaxS {
687 dest: FRegister,
688 src1: FRegister,
689 src2: FRegister,
690 },
691 FcvtWS {
692 dest: IRegister,
693 src: FRegister,
694 rm: RoundingMode,
695 },
696 FcvtWuS {
697 dest: IRegister,
698 src: FRegister,
699 rm: RoundingMode,
700 },
701 FmvXW {
702 dest: IRegister,
703 src: FRegister,
704 },
705 FeqS {
706 dest: IRegister,
707 src1: FRegister,
708 src2: FRegister,
709 },
710 FltS {
711 dest: IRegister,
712 src1: FRegister,
713 src2: FRegister,
714 },
715 FleS {
716 dest: IRegister,
717 src1: FRegister,
718 src2: FRegister,
719 },
720 FclassS {
721 dest: IRegister,
722 src: FRegister,
723 },
724 FcvtSW {
725 dest: FRegister,
726 src: IRegister,
727 rm: RoundingMode,
728 },
729 FcvtSWu {
730 dest: FRegister,
731 src: IRegister,
732 rm: RoundingMode,
733 },
734 FmvWX {
735 dest: FRegister,
736 src: IRegister,
737 },
738 FcvtLS {
742 dest: IRegister,
743 src: FRegister,
744 rm: RoundingMode,
745 },
746 FcvtLuS {
747 dest: IRegister,
748 src: FRegister,
749 rm: RoundingMode,
750 },
751 FcvtSL {
752 dest: FRegister,
753 src: IRegister,
754 rm: RoundingMode,
755 },
756 FcvtSLu {
757 dest: FRegister,
758 src: IRegister,
759 rm: RoundingMode,
760 },
761 Csrrw {
765 dest: IRegister,
766 src: IRegister,
767 csr: CSR,
768 },
769 Csrrs {
770 dest: IRegister,
771 src: IRegister,
772 csr: CSR,
773 },
774 Csrrc {
775 dest: IRegister,
776 src: IRegister,
777 csr: CSR,
778 },
779 Csrrwi {
780 dest: IRegister,
781 imm: CSRImmediate,
782 csr: CSR,
783 },
784 Csrrsi {
785 dest: IRegister,
786 imm: CSRImmediate,
787 csr: CSR,
788 },
789 Csrrci {
790 dest: IRegister,
791 imm: CSRImmediate,
792 csr: CSR,
793 },
794 FenceI,
798 Fld {
802 dest: FRegister,
803 base: IRegister,
804 offset: IImmediate,
805 },
806 Fsd {
807 src: FRegister,
808 base: IRegister,
809 offset: SImmediate,
810 },
811 FmaddD {
812 dest: FRegister,
813 src1: FRegister,
814 src2: FRegister,
815 src3: FRegister,
816 rm: RoundingMode,
817 },
818 FmsubD {
819 dest: FRegister,
820 src1: FRegister,
821 src2: FRegister,
822 src3: FRegister,
823 rm: RoundingMode,
824 },
825 FnmaddD {
826 dest: FRegister,
827 src1: FRegister,
828 src2: FRegister,
829 src3: FRegister,
830 rm: RoundingMode,
831 },
832 FnmsubD {
833 dest: FRegister,
834 src1: FRegister,
835 src2: FRegister,
836 src3: FRegister,
837 rm: RoundingMode,
838 },
839 FaddD {
840 dest: FRegister,
841 src1: FRegister,
842 src2: FRegister,
843 rm: RoundingMode,
844 },
845 FsubD {
846 dest: FRegister,
847 src1: FRegister,
848 src2: FRegister,
849 rm: RoundingMode,
850 },
851 FmulD {
852 dest: FRegister,
853 src1: FRegister,
854 src2: FRegister,
855 rm: RoundingMode,
856 },
857 FdivD {
858 dest: FRegister,
859 src1: FRegister,
860 src2: FRegister,
861 rm: RoundingMode,
862 },
863 FsqrtD {
864 dest: FRegister,
865 src: FRegister,
866 rm: RoundingMode,
867 },
868 FsgnjD {
869 dest: FRegister,
870 src1: FRegister,
871 src2: FRegister,
872 },
873 FsgnjnD {
874 dest: FRegister,
875 src1: FRegister,
876 src2: FRegister,
877 },
878 FsgnjxD {
879 dest: FRegister,
880 src1: FRegister,
881 src2: FRegister,
882 },
883 FminD {
884 dest: FRegister,
885 src1: FRegister,
886 src2: FRegister,
887 },
888 FmaxD {
889 dest: FRegister,
890 src1: FRegister,
891 src2: FRegister,
892 },
893 FcvtSD {
894 dest: FRegister,
895 src: FRegister,
896 rm: RoundingMode,
897 },
898 FcvtDS {
899 dest: FRegister,
900 src: FRegister,
901 rm: RoundingMode,
902 },
903 FeqD {
904 dest: IRegister,
905 src1: FRegister,
906 src2: FRegister,
907 },
908 FltD {
909 dest: IRegister,
910 src1: FRegister,
911 src2: FRegister,
912 },
913 FleD {
914 dest: IRegister,
915 src1: FRegister,
916 src2: FRegister,
917 },
918 FclassD {
919 dest: IRegister,
920 src1: FRegister,
921 },
922 FcvtWD {
923 dest: IRegister,
924 src1: FRegister,
925 rm: RoundingMode,
926 },
927 FcvtWuD {
928 dest: IRegister,
929 src1: FRegister,
930 rm: RoundingMode,
931 },
932 FcvtDW {
933 dest: FRegister,
934 src1: IRegister,
935 rm: RoundingMode,
936 },
937 FcvtDWu {
938 dest: FRegister,
939 src1: IRegister,
940 rm: RoundingMode,
941 },
942 FcvtLD {
943 dest: IRegister,
944 src1: FRegister,
945 rm: RoundingMode,
946 },
947 FcvtLuD {
948 dest: IRegister,
949 src1: FRegister,
950 rm: RoundingMode,
951 },
952 FmvXD {
953 dest: IRegister,
954 src: FRegister,
955 },
956 FcvtDL {
957 dest: FRegister,
958 src: IRegister,
959 rm: RoundingMode,
960 },
961 FcvtDLu {
962 dest: FRegister,
963 src: IRegister,
964 rm: RoundingMode,
965 },
966 FmvDX {
967 dest: FRegister,
968 src: IRegister,
969 },
970}
971
972fn aq_rl_suffix(aq: &bool, rl: &bool) -> &'static str {
973 match (aq, rl) {
974 (true, true) => ".aqrl",
975 (true, false) => ".aq",
976 (false, true) => ".rl",
977 (false, false) => "",
978 }
979}
980
981fn aqb(aq: bool) -> u32 {
983 if aq { 1 << 26 } else { 0 }
984}
985
986fn rlb(rl: bool) -> u32 {
988 if rl { 1 << 25 } else { 0 }
989}
990
991impl Display for Instruction {
992 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), alloc::fmt::Error> {
993 match self {
994 Instruction::Lui { dest, imm } => write!(f, "lui {dest},{imm}"),
995 Instruction::Auipc { dest, imm } => write!(f, "auipc {dest},{imm}"),
996 Instruction::Jal { dest, offset } => write!(f, "jal {dest},{offset}"),
997 Instruction::Jalr { dest, base, offset } => write!(f, "jalr {dest},{offset}({base})"),
998 Instruction::Beq { src1, src2, offset } => write!(f, "beq {src1},{src2},{offset}"),
999 Instruction::Bne { src1, src2, offset } => write!(f, "bne {src1},{src2},{offset}"),
1000 Instruction::Blt { src1, src2, offset } => write!(f, "blt {src1},{src2},{offset}"),
1001 Instruction::Bge { src1, src2, offset } => write!(f, "bge {src1},{src2},{offset}"),
1002 Instruction::Bltu { src1, src2, offset } => write!(f, "bltu {src1},{src2},{offset}"),
1003 Instruction::Bgeu { src1, src2, offset } => write!(f, "bgeu {src1},{src2},{offset}"),
1004 Instruction::Lb { dest, base, offset } => write!(f, "lb {dest},{offset}({base})"),
1005 Instruction::Lh { dest, base, offset } => write!(f, "lh {dest},{offset}({base})"),
1006 Instruction::Lw { dest, base, offset } => write!(f, "lw {dest},{offset}({base})"),
1007 Instruction::Lbu { dest, base, offset } => write!(f, "lbu {dest},{offset}({base})"),
1008 Instruction::Lhu { dest, base, offset } => write!(f, "lhu {dest},{offset}({base})"),
1009 Instruction::Sb { src, base, offset } => write!(f, "sb {src},{offset}({base})"),
1010 Instruction::Sh { src, base, offset } => write!(f, "sh {src},{offset}({base})"),
1011 Instruction::Sw { src, base, offset } => write!(f, "sw {src},{offset}({base})"),
1012 Instruction::Addi { dest, src, imm } => write!(f, "addi {dest},{src},{imm}"),
1013 Instruction::Slti { dest, src, imm } => write!(f, "slti {dest},{src},{imm}"),
1014 Instruction::Sltiu { dest, src, imm } => write!(f, "sltiu {dest},{src},{imm}"),
1015 Instruction::Xori { dest, src, imm } => write!(f, "xori {dest},{src},{imm}"),
1016 Instruction::Ori { dest, src, imm } => write!(f, "ori {dest},{src},{imm}"),
1017 Instruction::Andi { dest, src, imm } => write!(f, "andi {dest},{src},{imm}"),
1018 Instruction::Slli { dest, src, shamt } => write!(f, "slli {dest},{src},{shamt}"),
1019 Instruction::Srli { dest, src, shamt } => write!(f, "srli {dest},{src},{shamt}"),
1020 Instruction::Srai { dest, src, shamt } => write!(f, "srai {dest},{src},{shamt}"),
1021 Instruction::Add { dest, src1, src2 } => write!(f, "add {dest},{src1},{src2}"),
1022 Instruction::Sub { dest, src1, src2 } => write!(f, "sub {dest},{src1},{src2}"),
1023 Instruction::Sll { dest, src1, src2 } => write!(f, "sll {dest},{src1},{src2}"),
1024 Instruction::Slt { dest, src1, src2 } => write!(f, "slt {dest},{src1},{src2}"),
1025 Instruction::Sltu { dest, src1, src2 } => write!(f, "sltu {dest},{src1},{src2}"),
1026 Instruction::Xor { dest, src1, src2 } => write!(f, "xor {dest},{src1},{src2}"),
1027 Instruction::Srl { dest, src1, src2 } => write!(f, "srl {dest},{src1},{src2}"),
1028 Instruction::Sra { dest, src1, src2 } => write!(f, "sra {dest},{src1},{src2}"),
1029 Instruction::Or { dest, src1, src2 } => write!(f, "or {dest},{src1},{src2}"),
1030 Instruction::And { dest, src1, src2 } => write!(f, "and {dest},{src1},{src2}"),
1031 Instruction::Fence { .. } => write!(f, "{}", self.fmt_fence()),
1032 Instruction::Ecall => write!(f, "ecall"),
1033 Instruction::Ebreak => write!(f, "ebreak"),
1034 Instruction::Lwu { dest, base, offset } => write!(f, "lwu {dest},{offset}({base})"),
1035 Instruction::Ld { dest, base, offset } => write!(f, "ld {dest},{offset}({base})"),
1036 Instruction::Sd { src, base, offset } => write!(f, "sd {src},{offset}({base})"),
1037 Instruction::Addiw { dest, src, imm } => write!(f, "addiw {dest},{src},{imm}"),
1038 Instruction::Slliw { dest, src, shamt } => write!(f, "slliw {dest},{src},{shamt}"),
1039 Instruction::Srliw { dest, src, shamt } => write!(f, "srliw {dest},{src},{shamt}"),
1040 Instruction::Sraiw { dest, src, shamt } => write!(f, "sraiw {dest},{src},{shamt}"),
1041 Instruction::Addw { dest, src1, src2 } => write!(f, "addw {dest},{src1},{src2}"),
1042 Instruction::Subw { dest, src1, src2 } => write!(f, "subw {dest},{src1},{src2}"),
1043 Instruction::Sllw { dest, src1, src2 } => write!(f, "sllw {dest},{src1},{src2}"),
1044 Instruction::Srlw { dest, src1, src2 } => write!(f, "srlw {dest},{src1},{src2}"),
1045 Instruction::Sraw { dest, src1, src2 } => write!(f, "sraw {dest},{src1},{src2}"),
1046 Instruction::Mul { dest, src1, src2 } => write!(f, "mul {dest},{src1},{src2}"),
1047 Instruction::Mulh { dest, src1, src2 } => write!(f, "mulh {dest},{src1},{src2}"),
1048 Instruction::Mulhsu { dest, src1, src2 } => write!(f, "mulhsu {dest},{src1},{src2}"),
1049 Instruction::Mulhu { dest, src1, src2 } => write!(f, "mulhu {dest},{src1},{src2}"),
1050 Instruction::Div { dest, src1, src2 } => write!(f, "div {dest},{src1},{src2}"),
1051 Instruction::Divu { dest, src1, src2 } => write!(f, "divu {dest},{src1},{src2}"),
1052 Instruction::Rem { dest, src1, src2 } => write!(f, "rem {dest},{src1},{src2}"),
1053 Instruction::Remu { dest, src1, src2 } => write!(f, "remu {dest},{src1},{src2}"),
1054 Instruction::Mulw { dest, src1, src2 } => write!(f, "mulw {dest},{src1},{src2}"),
1055 Instruction::Divw { dest, src1, src2 } => write!(f, "divw {dest},{src1},{src2}"),
1056 Instruction::Divuw { dest, src1, src2 } => write!(f, "divuw {dest},{src1},{src2}"),
1057 Instruction::Remw { dest, src1, src2 } => write!(f, "remw {dest},{src1},{src2}"),
1058 Instruction::Remuw { dest, src1, src2 } => write!(f, "remuw {dest},{src1},{src2}"),
1059 Instruction::LrW { dest, addr, aq, rl } => {
1060 write!(f, "lr.w{} {dest},{addr}", aq_rl_suffix(aq, rl))
1061 }
1062 Instruction::ScW {
1063 dest,
1064 addr,
1065 src,
1066 aq,
1067 rl,
1068 } => {
1069 write!(f, "sc.w{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
1070 }
1071 Instruction::AmoswapW {
1072 dest,
1073 addr,
1074 src,
1075 aq,
1076 rl,
1077 } => {
1078 write!(f, "amoswap.w{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
1079 }
1080 Instruction::AmoaddW {
1081 dest,
1082 addr,
1083 src,
1084 aq,
1085 rl,
1086 } => {
1087 write!(f, "amoadd.w{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
1088 }
1089 Instruction::AmoxorW {
1090 dest,
1091 addr,
1092 src,
1093 aq,
1094 rl,
1095 } => {
1096 write!(f, "amoxor.w{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
1097 }
1098 Instruction::AmoandW {
1099 dest,
1100 addr,
1101 src,
1102 aq,
1103 rl,
1104 } => {
1105 write!(f, "amoand.w{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
1106 }
1107 Instruction::AmoorW {
1108 dest,
1109 addr,
1110 src,
1111 aq,
1112 rl,
1113 } => {
1114 write!(f, "amoor.w{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
1115 }
1116 Instruction::AmominW {
1117 dest,
1118 addr,
1119 src,
1120 aq,
1121 rl,
1122 } => {
1123 write!(f, "amomin.w{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
1124 }
1125 Instruction::AmomaxW {
1126 dest,
1127 addr,
1128 src,
1129 aq,
1130 rl,
1131 } => {
1132 write!(f, "amomax.w{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
1133 }
1134 Instruction::AmominuW {
1135 dest,
1136 addr,
1137 src,
1138 aq,
1139 rl,
1140 } => {
1141 write!(f, "amominu.w{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
1142 }
1143 Instruction::AmomaxuW {
1144 dest,
1145 addr,
1146 src,
1147 aq,
1148 rl,
1149 } => {
1150 write!(f, "amomaxu.w{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
1151 }
1152 Instruction::LrD { dest, addr, aq, rl } => {
1153 write!(f, "lr.d{} {dest},{addr}", aq_rl_suffix(aq, rl))
1154 }
1155 Instruction::ScD {
1156 dest,
1157 addr,
1158 src,
1159 aq,
1160 rl,
1161 } => {
1162 write!(f, "sc.d{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
1163 }
1164 Instruction::AmoswapD {
1165 dest,
1166 addr,
1167 src,
1168 aq,
1169 rl,
1170 } => {
1171 write!(f, "amoswap.d{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
1172 }
1173 Instruction::AmoaddD {
1174 dest,
1175 addr,
1176 src,
1177 aq,
1178 rl,
1179 } => {
1180 write!(f, "amoadd.d{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
1181 }
1182 Instruction::AmoxorD {
1183 dest,
1184 addr,
1185 src,
1186 aq,
1187 rl,
1188 } => {
1189 write!(f, "amoxor.d{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
1190 }
1191 Instruction::AmoandD {
1192 dest,
1193 addr,
1194 src,
1195 aq,
1196 rl,
1197 } => {
1198 write!(f, "amoand.d{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
1199 }
1200 Instruction::AmoorD {
1201 dest,
1202 addr,
1203 src,
1204 aq,
1205 rl,
1206 } => {
1207 write!(f, "amoor.d{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
1208 }
1209 Instruction::AmominD {
1210 dest,
1211 addr,
1212 src,
1213 aq,
1214 rl,
1215 } => {
1216 write!(f, "amomin.d{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
1217 }
1218 Instruction::AmomaxD {
1219 dest,
1220 addr,
1221 src,
1222 aq,
1223 rl,
1224 } => {
1225 write!(f, "amomax.d{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
1226 }
1227 Instruction::AmominuD {
1228 dest,
1229 addr,
1230 src,
1231 aq,
1232 rl,
1233 } => {
1234 write!(f, "amominu.d{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
1235 }
1236 Instruction::AmomaxuD {
1237 dest,
1238 addr,
1239 src,
1240 aq,
1241 rl,
1242 } => {
1243 write!(f, "amomaxu.d{} {dest},{addr},{src}", aq_rl_suffix(aq, rl))
1244 }
1245 Instruction::Flw { dest, base, offset } => write!(f, "flw {dest},{offset}({base})"),
1246 Instruction::Fsw { base, src, offset } => write!(f, "fsw {src},{offset}({base})"),
1247 Instruction::FmaddS {
1248 dest,
1249 src1,
1250 src2,
1251 src3,
1252 rm,
1253 } => {
1254 write!(f, "fmadd.s {dest},{src1},{src2},{src3},{rm}")
1255 }
1256 Instruction::FmsubS {
1257 dest,
1258 src1,
1259 src2,
1260 src3,
1261 rm,
1262 } => {
1263 write!(f, "fmsub.s {dest},{src1},{src2},{src3},{rm}")
1264 }
1265 Instruction::FnmsubS {
1266 dest,
1267 src1,
1268 src2,
1269 src3,
1270 rm,
1271 } => {
1272 write!(f, "fnmsub.s {dest},{src1},{src2},{src3},{rm}")
1273 }
1274 Instruction::FnmaddS {
1275 dest,
1276 src1,
1277 src2,
1278 src3,
1279 rm,
1280 } => {
1281 write!(f, "fnmadd.s {dest},{src1},{src2},{src3},{rm}")
1282 }
1283 Instruction::FaddS {
1284 dest,
1285 src1,
1286 src2,
1287 rm,
1288 } => write!(f, "fadd.s {dest},{src1},{src2},{rm}"),
1289 Instruction::FsubS {
1290 dest,
1291 src1,
1292 src2,
1293 rm,
1294 } => write!(f, "fsub.s {dest},{src1},{src2},{rm}"),
1295 Instruction::FmulS {
1296 dest,
1297 src1,
1298 src2,
1299 rm,
1300 } => write!(f, "fmul.s {dest},{src1},{src2},{rm}"),
1301 Instruction::FdivS {
1302 dest,
1303 src1,
1304 src2,
1305 rm,
1306 } => write!(f, "fdiv.s {dest},{src1},{src2},{rm}"),
1307 Instruction::FsqrtS { dest, src, rm } => write!(f, "fsqrt.s {dest},{src},{rm}"),
1308 Instruction::FsgnjS { dest, src1, src2 } => write!(f, "fsgnj.s {dest},{src1},{src2}"),
1309 Instruction::FsgnjnS { dest, src1, src2 } => write!(f, "fsgnjn.s {dest},{src1},{src2}"),
1310 Instruction::FsgnjxS { dest, src1, src2 } => write!(f, "fsgnjx.s {dest},{src1},{src2}"),
1311 Instruction::FminS { dest, src1, src2 } => write!(f, "fmin.s {dest},{src1},{src2}"),
1312 Instruction::FmaxS { dest, src1, src2 } => write!(f, "fmax.s {dest},{src1},{src2}"),
1313 Instruction::FcvtWS { dest, src, rm } => write!(f, "fcvt.w.s {dest},{src},{rm}"),
1314 Instruction::FcvtWuS { dest, src, rm } => write!(f, "fcvt.wu.s {dest},{src},{rm}"),
1315 Instruction::FmvXW { dest, src } => write!(f, "fmv.x.w {dest},{src}"),
1316 Instruction::FeqS { dest, src1, src2 } => write!(f, "feq.s {dest},{src1},{src2}"),
1317 Instruction::FltS { dest, src1, src2 } => write!(f, "flt.s {dest},{src1},{src2}"),
1318 Instruction::FleS { dest, src1, src2 } => write!(f, "fle.s {dest},{src1},{src2}"),
1319 Instruction::FclassS { dest, src } => write!(f, "fclass.s {dest},{src}"),
1320 Instruction::FcvtSW { dest, src, rm } => write!(f, "fcvt.s.w {dest},{src},{rm}"),
1321 Instruction::FcvtSWu { dest, src, rm } => write!(f, "fcvt.s.wu {dest},{src},{rm}"),
1322 Instruction::FmvWX { dest, src } => write!(f, "fmv.w.x {dest},{src}"),
1323 Instruction::FcvtLS { dest, src, rm } => write!(f, "fcvt.l.s {dest},{src},{rm}"),
1324 Instruction::FcvtLuS { dest, src, rm } => write!(f, "fcvt.lu.s {dest},{src},{rm}"),
1325 Instruction::FcvtSL { dest, src, rm } => write!(f, "fcvt.s.l {dest},{src},{rm}"),
1326 Instruction::FcvtSLu { dest, src, rm } => write!(f, "fcvt.s.lu {dest},{src},{rm}"),
1327 Instruction::Csrrw { dest, src, csr } => write!(f, "csrrw {dest},{csr},{src}"),
1328 Instruction::Csrrs { dest, src, csr } => write!(f, "csrrs {dest},{csr},{src}"),
1329 Instruction::Csrrc { dest, src, csr } => write!(f, "csrrc {dest},{csr},{src}"),
1330 Instruction::Csrrwi { dest, imm, csr } => write!(f, "csrrwi {dest},{csr},{imm}"),
1331 Instruction::Csrrsi { dest, imm, csr } => write!(f, "csrrsi {dest},{csr},{imm}"),
1332 Instruction::Csrrci { dest, imm, csr } => write!(f, "csrrci {dest},{csr},{imm}"),
1333 Instruction::FenceI => write!(f, "fence.i"),
1334 Instruction::Fld { dest, base, offset } => write!(f, "fld {dest},{offset}({base})"),
1335 Instruction::Fsd { src, base, offset } => write!(f, "fsd {src},{offset}({base})"),
1336 Instruction::FmaddD {
1337 dest,
1338 src1,
1339 src2,
1340 src3,
1341 rm,
1342 } => write!(f, "fmadd.d {dest},{src1},{src2},{src3},{rm}"),
1343 Instruction::FmsubD {
1344 dest,
1345 src1,
1346 src2,
1347 src3,
1348 rm,
1349 } => write!(f, "fmsub.d {dest},{src1},{src2},{src3},{rm}"),
1350 Instruction::FnmaddD {
1351 dest,
1352 src1,
1353 src2,
1354 src3,
1355 rm,
1356 } => write!(f, "fnmadd.d {dest},{src1},{src2},{src3},{rm}"),
1357 Instruction::FnmsubD {
1358 dest,
1359 src1,
1360 src2,
1361 src3,
1362 rm,
1363 } => write!(f, "fnmsub.d {dest},{src1},{src2},{src3},{rm}"),
1364 Instruction::FaddD {
1365 dest,
1366 src1,
1367 src2,
1368 rm,
1369 } => write!(f, "fadd.d {dest},{src1},{src2},{rm}"),
1370 Instruction::FsubD {
1371 dest,
1372 src1,
1373 src2,
1374 rm,
1375 } => write!(f, "fsub.d {dest},{src1},{src2},{rm}"),
1376 Instruction::FmulD {
1377 dest,
1378 src1,
1379 src2,
1380 rm,
1381 } => write!(f, "fmul.d {dest},{src1},{src2},{rm}"),
1382 Instruction::FdivD {
1383 dest,
1384 src1,
1385 src2,
1386 rm,
1387 } => write!(f, "fdiv.d {dest},{src1},{src2},{rm}"),
1388 Instruction::FsqrtD {
1389 dest,
1390 src: src1,
1391 rm,
1392 } => write!(f, "fsqrt.d {dest},{src1},{rm}"),
1393 Instruction::FsgnjD { dest, src1, src2 } => write!(f, "fsgnj.d {dest},{src1},{src2}"),
1394 Instruction::FsgnjnD { dest, src1, src2 } => write!(f, "fsgnjn.d {dest},{src1},{src2}"),
1395 Instruction::FsgnjxD { dest, src1, src2 } => write!(f, "fsgnjx.d {dest},{src1},{src2}"),
1396 Instruction::FminD { dest, src1, src2 } => write!(f, "fmin.d {dest},{src1},{src2}"),
1397 Instruction::FmaxD { dest, src1, src2 } => write!(f, "fmax.d {dest},{src1},{src2}"),
1398 Instruction::FcvtSD { dest, src, rm } => write!(f, "fcvt.s.d {dest},{src},{rm}"),
1399 Instruction::FcvtDS { dest, src, rm } => write!(f, "fcvt.d.s {dest},{src},{rm}"),
1400 Instruction::FeqD { dest, src1, src2 } => write!(f, "feq.d {dest},{src1},{src2}"),
1401 Instruction::FltD { dest, src1, src2 } => write!(f, "flt.d {dest},{src1},{src2}"),
1402 Instruction::FleD { dest, src1, src2 } => write!(f, "fle.d {dest},{src1},{src2}"),
1403 Instruction::FclassD { dest, src1 } => write!(f, "fclass.d {dest},{src1}"),
1404 Instruction::FcvtWD { dest, src1, rm } => write!(f, "fcvt.w.d {dest},{src1},{rm}"),
1405 Instruction::FcvtWuD { dest, src1, rm } => write!(f, "fcvt.wu.d {dest},{src1},{rm}"),
1406 Instruction::FcvtDW { dest, src1, rm } => write!(f, "fcvt.d.w {dest},{src1},{rm}"),
1407 Instruction::FcvtDWu { dest, src1, rm } => write!(f, "fcvt.d.wu {dest},{src1},{rm}"),
1408 Instruction::FcvtLD { dest, src1, rm } => write!(f, "fcvt.l.d {dest},{src1},{rm}"),
1409 Instruction::FcvtLuD { dest, src1, rm } => write!(f, "fcvt.lu.d {dest},{src1},{rm}"),
1410 Instruction::FmvXD { dest, src } => write!(f, "fmv.x.d {dest},{src}"),
1411 Instruction::FcvtDL {
1412 dest,
1413 src: src1,
1414 rm,
1415 } => write!(f, "fcvt.d.l {dest},{src1},{rm}"),
1416 Instruction::FcvtDLu {
1417 dest,
1418 src: src1,
1419 rm,
1420 } => write!(f, "fcvt.d.lu {dest},{src1},{rm}"),
1421 Instruction::FmvDX { dest, src } => write!(f, "fmv.d.x {dest},{src}"),
1422 }
1423 }
1424}
1425
1426impl Instruction {
1427 fn fmt_fence(&self) -> String {
1428 if let Instruction::Fence {
1429 rd: _,
1430 rs1: _,
1431 ops,
1432 fm,
1433 } = *self
1434 {
1435 let sw = if ops & 0b0000_0001 != 0 { "w" } else { "" };
1436 let sr = if ops & 0b0000_0010 != 0 { "r" } else { "" };
1437 let so = if ops & 0b0000_0100 != 0 { "o" } else { "" };
1438 let si = if ops & 0b0000_1000 != 0 { "i" } else { "" };
1439 let pw = if ops & 0b0001_0000 != 0 { "w" } else { "" };
1440 let pr = if ops & 0b0010_0000 != 0 { "r" } else { "" };
1441 let po = if ops & 0b0100_0000 != 0 { "o" } else { "" };
1442 let pi = if ops & 0b1000_0000 != 0 { "i" } else { "" };
1443 if fm == 0b1000 {
1444 format!("fence.tso {pi}{po}{pr}{pw},{si}{so}{sr}{sw}")
1445 } else {
1446 format!("fence {pi}{po}{pr}{pw},{si}{so}{sr}{sw}")
1447 }
1448 } else {
1449 unreachable!();
1450 }
1451 }
1452
1453 pub fn decode(instruction: u32) -> Result<Instruction, String> {
1455 let opcode = Opcode::from_int(instruction & 0b111_1111);
1456
1457 let func3 = (instruction >> 12) & 0b111;
1458 let func7 = (instruction >> 25) & 0b111_1111;
1459
1460 let rd = IRegister::from_int((instruction >> 7) & 0b1_1111);
1461 let rs1 = IRegister::from_int((instruction >> 15) & 0b1_1111);
1462 let rs2 = IRegister::from_int((instruction >> 20) & 0b1_1111);
1463
1464 let frd = FRegister::try_from((instruction >> 7) & 0b1_1111).unwrap();
1465 let frs1 = FRegister::try_from((instruction >> 15) & 0b1_1111).unwrap();
1466 let frs2 = FRegister::try_from((instruction >> 20) & 0b1_1111).unwrap();
1467 let frs3 = FRegister::try_from((instruction >> 27) & 0b1_1111).unwrap();
1468
1469 let i_immediate: IImmediate = IImmediate::from_u32(instruction);
1470
1471 let s_immediate: SImmediate = SImmediate::from_u32(instruction);
1472
1473 let u_immediate = UImmediate::from_u32(instruction);
1474
1475 let b_immediate = BImmediate::from_u32(instruction);
1476
1477 let shamt: Shamt = Shamt::from_u32(instruction);
1478
1479 let shamtw: ShamtW = ShamtW::from_u32(instruction);
1480
1481 let aq: bool = ((instruction >> 26) & 0b1) == 0b1;
1483 let rl: bool = ((instruction >> 25) & 0b1) == 0b1;
1484
1485 match opcode {
1486 Opcode::Load => match func3 {
1487 0b000 => Ok(Instruction::Lb {
1488 dest: rd,
1489 base: rs1,
1490 offset: i_immediate,
1491 }),
1492 0b001 => Ok(Instruction::Lh {
1493 dest: rd,
1494 base: rs1,
1495 offset: i_immediate,
1496 }),
1497 0b010 => Ok(Instruction::Lw {
1498 dest: rd,
1499 base: rs1,
1500 offset: i_immediate,
1501 }),
1502 0b011 => Ok(Instruction::Ld {
1503 dest: rd,
1504 base: rs1,
1505 offset: i_immediate,
1506 }),
1507 0b100 => Ok(Instruction::Lbu {
1508 dest: rd,
1509 base: rs1,
1510 offset: i_immediate,
1511 }),
1512 0b101 => Ok(Instruction::Lhu {
1513 dest: rd,
1514 base: rs1,
1515 offset: i_immediate,
1516 }),
1517 0b110 => Ok(Instruction::Lwu {
1518 dest: rd,
1519 base: rs1,
1520 offset: i_immediate,
1521 }),
1522 0b111 => Err("Invalid load func3".to_owned()),
1523 _ => unreachable!(),
1524 },
1525 Opcode::Auipc => Ok(Instruction::Auipc {
1526 dest: rd,
1527 imm: u_immediate,
1528 }),
1529 Opcode::Store => match func3 {
1530 0b000 => Ok(Instruction::Sb {
1531 src: rs2,
1532 base: rs1,
1533 offset: s_immediate,
1534 }),
1535 0b001 => Ok(Instruction::Sh {
1536 src: rs2,
1537 base: rs1,
1538 offset: s_immediate,
1539 }),
1540 0b010 => Ok(Instruction::Sw {
1541 src: rs2,
1542 base: rs1,
1543 offset: s_immediate,
1544 }),
1545 0b011 => Ok(Instruction::Sd {
1546 src: rs2,
1547 base: rs1,
1548 offset: s_immediate,
1549 }),
1550 x => Err(format!("invalid store func3: {}", x)),
1551 },
1552 Opcode::Lui => Ok(Instruction::Lui {
1553 dest: rd,
1554 imm: u_immediate,
1555 }),
1556 Opcode::Op => match (func7, func3) {
1557 (0b000_0000, 0b000) => Ok(Instruction::Add {
1558 dest: rd,
1559 src1: rs1,
1560 src2: rs2,
1561 }),
1562 (0b000_0000, 0b001) => Ok(Instruction::Sll {
1563 dest: rd,
1564 src1: rs1,
1565 src2: rs2,
1566 }),
1567 (0b000_0000, 0b010) => Ok(Instruction::Slt {
1568 dest: rd,
1569 src1: rs1,
1570 src2: rs2,
1571 }),
1572 (0b000_0000, 0b011) => Ok(Instruction::Sltu {
1573 dest: rd,
1574 src1: rs1,
1575 src2: rs2,
1576 }),
1577 (0b000_0000, 0b100) => Ok(Instruction::Xor {
1578 dest: rd,
1579 src1: rs1,
1580 src2: rs2,
1581 }),
1582 (0b000_0000, 0b101) => Ok(Instruction::Srl {
1583 dest: rd,
1584 src1: rs1,
1585 src2: rs2,
1586 }),
1587 (0b000_0000, 0b110) => Ok(Instruction::Or {
1588 dest: rd,
1589 src1: rs1,
1590 src2: rs2,
1591 }),
1592 (0b000_0000, 0b111) => Ok(Instruction::And {
1593 dest: rd,
1594 src1: rs1,
1595 src2: rs2,
1596 }),
1597 (0b010_0000, 0b000) => Ok(Instruction::Sub {
1598 dest: rd,
1599 src1: rs1,
1600 src2: rs2,
1601 }),
1602 (0b010_0000, 0b101) => Ok(Instruction::Sra {
1603 dest: rd,
1604 src1: rs1,
1605 src2: rs2,
1606 }),
1607 (0b000_0001, 0b000) => Ok(Instruction::Mul {
1608 dest: rd,
1609 src1: rs1,
1610 src2: rs2,
1611 }),
1612 (0b000_0001, 0b001) => Ok(Instruction::Mulh {
1613 dest: rd,
1614 src1: rs1,
1615 src2: rs2,
1616 }),
1617 (0b000_0001, 0b010) => Ok(Instruction::Mulhsu {
1618 dest: rd,
1619 src1: rs1,
1620 src2: rs2,
1621 }),
1622 (0b000_0001, 0b011) => Ok(Instruction::Mulhu {
1623 dest: rd,
1624 src1: rs1,
1625 src2: rs2,
1626 }),
1627 (0b000_0001, 0b100) => Ok(Instruction::Div {
1628 dest: rd,
1629 src1: rs1,
1630 src2: rs2,
1631 }),
1632 (0b000_0001, 0b101) => Ok(Instruction::Divu {
1633 dest: rd,
1634 src1: rs1,
1635 src2: rs2,
1636 }),
1637 (0b000_0001, 0b110) => Ok(Instruction::Rem {
1638 dest: rd,
1639 src1: rs1,
1640 src2: rs2,
1641 }),
1642 (0b000_0001, 0b111) => Ok(Instruction::Remu {
1643 dest: rd,
1644 src1: rs1,
1645 src2: rs2,
1646 }),
1647 _ => Err(format!("unknown Op. func3: {}, func7: {}", func3, func7)),
1648 },
1649 Opcode::Op32 => match (func3, func7) {
1650 (0b000, 0b000_0000) => Ok(Instruction::Addw {
1651 dest: rd,
1652 src1: rs1,
1653 src2: rs2,
1654 }),
1655 (0b000, 0b000_0001) => Ok(Instruction::Mulw {
1656 dest: rd,
1657 src1: rs1,
1658 src2: rs2,
1659 }),
1660 (0b000, 0b010_0000) => Ok(Instruction::Subw {
1661 dest: rd,
1662 src1: rs1,
1663 src2: rs2,
1664 }),
1665 (0b001, 0b000_0000) => Ok(Instruction::Sllw {
1666 dest: rd,
1667 src1: rs1,
1668 src2: rs2,
1669 }),
1670 (0b100, 0b0000_001) => Ok(Instruction::Divw {
1671 dest: rd,
1672 src1: rs1,
1673 src2: rs2,
1674 }),
1675 (0b101, 0b000_0000) => Ok(Instruction::Srlw {
1676 dest: rd,
1677 src1: rs1,
1678 src2: rs2,
1679 }),
1680 (0b101, 0b000_0001) => Ok(Instruction::Divuw {
1681 dest: rd,
1682 src1: rs1,
1683 src2: rs2,
1684 }),
1685 (0b101, 0b010_0000) => Ok(Instruction::Sraw {
1686 dest: rd,
1687 src1: rs1,
1688 src2: rs2,
1689 }),
1690 (0b110, 0b000_0001) => Ok(Instruction::Remw {
1691 dest: rd,
1692 src1: rs1,
1693 src2: rs2,
1694 }),
1695 (0b111, 0b000_0001) => Ok(Instruction::Remuw {
1696 dest: rd,
1697 src1: rs1,
1698 src2: rs2,
1699 }),
1700 _ => Err(format!("unknown Op32. func3: {}, func7: {}", func3, func7)),
1701 },
1702 Opcode::OpImm => match func3 {
1703 0b000 => Ok(Instruction::Addi {
1704 dest: rd,
1705 src: rs1,
1706 imm: i_immediate,
1707 }),
1708 0b001 => match func7 | 0b1 {
1710 0b000000_1 => Ok(Instruction::Slli {
1711 dest: rd,
1712 src: rs1,
1713 shamt,
1714 }),
1715 _ => Err(format!("unknown OpImm. func3: {}, func7: {}", func3, func7)),
1716 },
1717 0b010 => Ok(Instruction::Slti {
1718 dest: rd,
1719 src: rs1,
1720 imm: i_immediate,
1721 }),
1722 0b011 => Ok(Instruction::Sltiu {
1723 dest: rd,
1724 src: rs1,
1725 imm: i_immediate,
1726 }),
1727 0b100 => Ok(Instruction::Xori {
1728 dest: rd,
1729 src: rs1,
1730 imm: i_immediate,
1731 }),
1732 0b101 => match func7 | 0b1 {
1734 0b000000_1 => Ok(Instruction::Srli {
1735 dest: rd,
1736 src: rs1,
1737 shamt,
1738 }),
1739 0b010000_1 => Ok(Instruction::Srai {
1740 dest: rd,
1741 src: rs1,
1742 shamt,
1743 }),
1744 _ => Err(format!("unknown OpImm. func3: {}, func7: {}", func3, func7)),
1745 },
1746 0b110 => Ok(Instruction::Ori {
1747 dest: rd,
1748 src: rs1,
1749 imm: i_immediate,
1750 }),
1751 0b111 => Ok(Instruction::Andi {
1752 dest: rd,
1753 src: rs1,
1754 imm: i_immediate,
1755 }),
1756 _ => Err(format!("unknown OpImm. func3: {}, func7: {}", func3, func7)),
1757 },
1758 Opcode::OpImm32 => match func3 {
1759 0b000 => Ok(Instruction::Addiw {
1760 dest: rd,
1761 src: rs1,
1762 imm: i_immediate,
1763 }),
1764 0b001 => match func7 {
1765 0b000_0000 => Ok(Instruction::Slliw {
1766 dest: rd,
1767 src: rs1,
1768 shamt: shamtw,
1769 }),
1770 x => Err(format!("unknown OpImm32(001) func7: {}", x).to_owned()),
1771 },
1772 0b101 => match func7 {
1773 0b000_0000 => Ok(Instruction::Srliw {
1774 dest: rd,
1775 src: rs1,
1776 shamt: shamtw,
1777 }),
1778 0b010_0000 => Ok(Instruction::Sraiw {
1779 dest: rd,
1780 src: rs1,
1781 shamt: shamtw,
1782 }),
1783 x => Err(format!("unknown OpImm32(101) func7: {}", x).to_owned()),
1784 },
1785 x => Err(format!("unkown OpImm32 func3: {}", x).to_owned()),
1786 },
1787 Opcode::Jalr => match func3 {
1788 0b000 => Ok(Instruction::Jalr {
1789 dest: rd,
1790 base: rs1,
1791 offset: i_immediate,
1792 }),
1793 x => Err(format!("unknown Jalr func3: {}", x)),
1794 },
1795 Opcode::Jal => Ok(Instruction::Jal {
1796 dest: rd,
1797 offset: JImmediate::from_u32(instruction),
1798 }),
1799 Opcode::Branch => match func3 {
1800 0b000 => Ok(Instruction::Beq {
1801 src1: rs1,
1802 src2: rs2,
1803 offset: b_immediate,
1804 }),
1805 0b001 => Ok(Instruction::Bne {
1806 src1: rs1,
1807 src2: rs2,
1808 offset: b_immediate,
1809 }),
1810 0b100 => Ok(Instruction::Blt {
1811 src1: rs1,
1812 src2: rs2,
1813 offset: b_immediate,
1814 }),
1815 0b101 => Ok(Instruction::Bge {
1816 src1: rs1,
1817 src2: rs2,
1818 offset: b_immediate,
1819 }),
1820 0b110 => Ok(Instruction::Bltu {
1821 src1: rs1,
1822 src2: rs2,
1823 offset: b_immediate,
1824 }),
1825 0b111 => Ok(Instruction::Bgeu {
1826 src1: rs1,
1827 src2: rs2,
1828 offset: b_immediate,
1829 }),
1830 x => Err(format!("invalid branch func3: {x}").to_owned()),
1831 },
1832 Opcode::MiscMem => match func3 {
1833 0b000 => {
1834 if rd != IRegister::Zero || rs1 != IRegister::Zero {
1835 Err("reserved register fields not set to zero".to_owned())
1837 } else {
1838 let fm = ((instruction >> 28) & 0b1111) as u8;
1839 if fm != 0 && fm != 0b1000 {
1840 Err(format!("reserved fence FM: {fm}").to_owned())
1841 } else if fm == 0b1000 && ((instruction >> 20) & 0xFF) != 0b0011_0011 {
1842 Err("fence.tso must be rw,rw".to_owned())
1843 } else {
1844 Ok(Instruction::Fence {
1845 rd,
1846 rs1,
1847 ops: ((instruction >> 20) & 0xFF) as u8,
1848 fm: ((instruction >> 28) & 0b1111) as u8,
1849 })
1850 }
1851 }
1852 }
1853 0b001 => {
1854 if rd != IRegister::Zero || rs1 != IRegister::Zero {
1855 Err("reserved register fields not set to zero".to_owned())
1857 } else {
1858 let func12 = instruction >> 20;
1859 if func12 != 0 {
1860 Err("reserved register fields not set to zero".to_owned())
1861 } else {
1862 Ok(Instruction::FenceI)
1863 }
1864 }
1865 }
1866 x => Err(format!("unknown fence func3: {x}")),
1867 },
1868 Opcode::AMO => match (func3, func7 >> 2) {
1869 (0b010, 0b00010) => {
1870 if rs2 != IRegister::Zero {
1871 Err("LR.W expects rs2 to be 0".to_owned())
1872 } else {
1873 Ok(Instruction::LrW {
1874 dest: rd,
1875 addr: rs1,
1876 aq,
1877 rl,
1878 })
1879 }
1880 }
1881 (0b011, 0b00010) => {
1882 if rs2 != IRegister::Zero {
1883 Err("LR.D expects rs2 to be 0".to_owned())
1884 } else {
1885 Ok(Instruction::LrD {
1886 dest: rd,
1887 addr: rs1,
1888 aq,
1889 rl,
1890 })
1891 }
1892 }
1893 (0b010, 0b00011) => Ok(Instruction::ScW {
1894 dest: rd,
1895 addr: rs1,
1896 src: rs2,
1897 aq,
1898 rl,
1899 }),
1900 (0b011, 0b00011) => Ok(Instruction::ScD {
1901 dest: rd,
1902 addr: rs1,
1903 src: rs2,
1904 aq,
1905 rl,
1906 }),
1907 (0b010, 0b00001) => Ok(Instruction::AmoswapW {
1908 dest: rd,
1909 addr: rs1,
1910 src: rs2,
1911 aq,
1912 rl,
1913 }),
1914 (0b011, 0b00001) => Ok(Instruction::AmoswapD {
1915 dest: rd,
1916 addr: rs1,
1917 src: rs2,
1918 aq,
1919 rl,
1920 }),
1921 (0b010, 0b00000) => Ok(Instruction::AmoaddW {
1922 dest: rd,
1923 addr: rs1,
1924 src: rs2,
1925 aq,
1926 rl,
1927 }),
1928 (0b011, 0b00000) => Ok(Instruction::AmoaddD {
1929 dest: rd,
1930 addr: rs1,
1931 src: rs2,
1932 aq,
1933 rl,
1934 }),
1935 (0b010, 0b00100) => Ok(Instruction::AmoxorW {
1936 dest: rd,
1937 addr: rs1,
1938 src: rs2,
1939 aq,
1940 rl,
1941 }),
1942 (0b011, 0b00100) => Ok(Instruction::AmoxorD {
1943 dest: rd,
1944 addr: rs1,
1945 src: rs2,
1946 aq,
1947 rl,
1948 }),
1949 (0b010, 0b01100) => Ok(Instruction::AmoandW {
1950 dest: rd,
1951 addr: rs1,
1952 src: rs2,
1953 aq,
1954 rl,
1955 }),
1956 (0b011, 0b01100) => Ok(Instruction::AmoandD {
1957 dest: rd,
1958 addr: rs1,
1959 src: rs2,
1960 aq,
1961 rl,
1962 }),
1963 (0b010, 0b01000) => Ok(Instruction::AmoorW {
1964 dest: rd,
1965 addr: rs1,
1966 src: rs2,
1967 aq,
1968 rl,
1969 }),
1970 (0b011, 0b01000) => Ok(Instruction::AmoorD {
1971 dest: rd,
1972 addr: rs1,
1973 src: rs2,
1974 aq,
1975 rl,
1976 }),
1977 (0b010, 0b10000) => Ok(Instruction::AmominW {
1978 dest: rd,
1979 addr: rs1,
1980 src: rs2,
1981 aq,
1982 rl,
1983 }),
1984 (0b011, 0b10000) => Ok(Instruction::AmominD {
1985 dest: rd,
1986 addr: rs1,
1987 src: rs2,
1988 aq,
1989 rl,
1990 }),
1991 (0b010, 0b10100) => Ok(Instruction::AmomaxW {
1992 dest: rd,
1993 addr: rs1,
1994 src: rs2,
1995 aq,
1996 rl,
1997 }),
1998 (0b011, 0b10100) => Ok(Instruction::AmomaxD {
1999 dest: rd,
2000 addr: rs1,
2001 src: rs2,
2002 aq,
2003 rl,
2004 }),
2005 (0b010, 0b11000) => Ok(Instruction::AmominuW {
2006 dest: rd,
2007 addr: rs1,
2008 src: rs2,
2009 aq,
2010 rl,
2011 }),
2012 (0b011, 0b11000) => Ok(Instruction::AmominuD {
2013 dest: rd,
2014 addr: rs1,
2015 src: rs2,
2016 aq,
2017 rl,
2018 }),
2019 (0b010, 0b11100) => Ok(Instruction::AmomaxuW {
2020 dest: rd,
2021 addr: rs1,
2022 src: rs2,
2023 aq,
2024 rl,
2025 }),
2026 (0b011, 0b11100) => Ok(Instruction::AmomaxuD {
2027 dest: rd,
2028 addr: rs1,
2029 src: rs2,
2030 aq,
2031 rl,
2032 }),
2033 _ => Err(format!("unknown AMO. func3: {func3}, func7: {func7}")),
2034 },
2035 Opcode::LoadFp => match func3 {
2036 0b010 => Ok(Instruction::Flw {
2037 dest: frd,
2038 base: rs1,
2039 offset: i_immediate,
2040 }),
2041 0b011 => Ok(Instruction::Fld {
2042 dest: frd,
2043 base: rs1,
2044 offset: i_immediate,
2045 }),
2046 _ => Err(format!("unknown func3: {func3} in opcode LoadFp")),
2047 },
2048 Opcode::StoreFp => match func3 {
2049 0b010 => Ok(Instruction::Fsw {
2050 src: frs2,
2051 base: rs1,
2052 offset: s_immediate,
2053 }),
2054 0b011 => Ok(Instruction::Fsd {
2055 src: frs2,
2056 base: rs1,
2057 offset: s_immediate,
2058 }),
2059 _ => Err(format!("unknown func3: {func3} in opcode StoreFp")),
2060 },
2061 Opcode::OpFp => match func7 {
2062 0b000_0000 => Ok(Instruction::FaddS {
2063 dest: frd,
2064 src1: frs1,
2065 src2: frs2,
2066 rm: RoundingMode::from_int(func3)?,
2067 }),
2068 0b000_0001 => Ok(Instruction::FaddD {
2069 dest: frd,
2070 src1: frs1,
2071 src2: frs2,
2072 rm: RoundingMode::from_int(func3)?,
2073 }),
2074 0b000_0100 => Ok(Instruction::FsubS {
2075 dest: frd,
2076 src1: frs1,
2077 src2: frs2,
2078 rm: RoundingMode::from_int(func3)?,
2079 }),
2080 0b000_0101 => Ok(Instruction::FsubD {
2081 dest: frd,
2082 src1: frs1,
2083 src2: frs2,
2084 rm: RoundingMode::from_int(func3)?,
2085 }),
2086 0b000_1000 => Ok(Instruction::FmulS {
2087 dest: frd,
2088 src1: frs1,
2089 src2: frs2,
2090 rm: RoundingMode::from_int(func3)?,
2091 }),
2092 0b000_1001 => Ok(Instruction::FmulD {
2093 dest: frd,
2094 src1: frs1,
2095 src2: frs2,
2096 rm: RoundingMode::from_int(func3)?,
2097 }),
2098 0b000_1100 => Ok(Instruction::FdivS {
2099 dest: frd,
2100 src1: frs1,
2101 src2: frs2,
2102 rm: RoundingMode::from_int(func3)?,
2103 }),
2104 0b000_1101 => Ok(Instruction::FdivD {
2105 dest: frd,
2106 src1: frs1,
2107 src2: frs2,
2108 rm: RoundingMode::from_int(func3)?,
2109 }),
2110 0b010_0000 => {
2111 if instruction >> 20 & 0b11111 != 0b0_0001 {
2112 Err("expected rs2=0b0_0001 in OpFp func7=0b010_0000".to_owned())
2113 } else {
2114 Ok(Instruction::FcvtSD {
2115 dest: frd,
2116 src: frs1,
2117 rm: RoundingMode::from_int(func3)?,
2118 })
2119 }
2120 }
2121 0b010_0001 => {
2122 if instruction >> 20 & 0b11111 != 0b0_0000 {
2123 Err("expected rs2=0b0_0000 in OpFp func7=0b010_0001".to_owned())
2124 } else {
2125 Ok(Instruction::FcvtDS {
2126 dest: frd,
2127 src: frs1,
2128 rm: RoundingMode::from_int(func3)?,
2129 })
2130 }
2131 }
2132 0b010_1100 => {
2133 if instruction >> 20 & 0b11111 != 0b0_0000 {
2134 Err("expected rs2=0b0_0000 in OpFp func7=0b010_1100".to_owned())
2135 } else {
2136 Ok(Instruction::FsqrtS {
2137 dest: frd,
2138 src: frs1,
2139 rm: RoundingMode::from_int(func3)?,
2140 })
2141 }
2142 }
2143 0b010_1101 => {
2144 if instruction >> 20 & 0b11111 != 0b0_0000 {
2145 Err("expected rs2=0b0_0000 in OpFp func7=0b010_1101".to_owned())
2146 } else {
2147 Ok(Instruction::FsqrtD {
2148 dest: frd,
2149 src: frs1,
2150 rm: RoundingMode::from_int(func3)?,
2151 })
2152 }
2153 },
2154 0b001_0000 => match func3 {
2155 0b000 => Ok(Instruction::FsgnjS {
2156 dest: frd,
2157 src1: frs1,
2158 src2: frs2,
2159 }),
2160 0b001 => Ok(Instruction::FsgnjnS {
2161 dest: frd,
2162 src1: frs1,
2163 src2: frs2,
2164 }),
2165 0b010 => Ok(Instruction::FsgnjxS {
2166 dest: frd,
2167 src1: frs1,
2168 src2: frs2,
2169 }),
2170 x => Err(format!("unknown OpFp func7=0b001_0000 func3: {}", x)),
2171 },
2172 0b001_0001 => match func3 {
2173 0b000 => Ok(Instruction::FsgnjD {
2174 dest: frd,
2175 src1: frs1,
2176 src2: frs2,
2177 }),
2178 0b001 => Ok(Instruction::FsgnjnD {
2179 dest: frd,
2180 src1: frs1,
2181 src2: frs2,
2182 }),
2183 0b010 => Ok(Instruction::FsgnjxD {
2184 dest: frd,
2185 src1: frs1,
2186 src2: frs2,
2187 }),
2188 x => Err(format!("unknown OpFp func7=0b001_0001 func3: {}", x)),
2189 },
2190 0b001_0100 => match func3 {
2191 0b000 => Ok(Instruction::FminS {
2192 dest: frd,
2193 src1: frs1,
2194 src2: frs2,
2195 }),
2196 0b001 => Ok(Instruction::FmaxS {
2197 dest: frd,
2198 src1: frs1,
2199 src2: frs2,
2200 }),
2201 x => Err(format!("unknown OpFp func7=0b001_0100 func3: {}", x)),
2202 },
2203 0b001_0101 => match func3 {
2204 0b000 => Ok(Instruction::FminD {
2205 dest: frd,
2206 src1: frs1,
2207 src2: frs2,
2208 }),
2209 0b001 => Ok(Instruction::FmaxD {
2210 dest: frd,
2211 src1: frs1,
2212 src2: frs2,
2213 }),
2214 x => Err(format!("unknown OpFp func7=0b001_0101 func3: {}", x)),
2215 },
2216 0b101_0000 => match func3 {
2217 0b000 => Ok(Instruction::FleS {
2218 dest: rd,
2219 src1: frs1,
2220 src2: frs2,
2221 }),
2222 0b001 => Ok(Instruction::FltS {
2223 dest: rd,
2224 src1: frs1,
2225 src2: frs2,
2226 }),
2227 0b010 => Ok(Instruction::FeqS {
2228 dest: rd,
2229 src1: frs1,
2230 src2: frs2,
2231 }),
2232 x => Err(format!("unknown OpFp func7=0b101_0000 func3: {}", x)),
2233 },
2234 0b101_0001 => match func3 {
2235 0b000 => Ok(Instruction::FleD {
2236 dest: rd,
2237 src1: frs1,
2238 src2: frs2,
2239 }),
2240 0b001 => Ok(Instruction::FltD {
2241 dest: rd,
2242 src1: frs1,
2243 src2: frs2,
2244 }),
2245 0b010 => Ok(Instruction::FeqD {
2246 dest: rd,
2247 src1: frs1,
2248 src2: frs2,
2249 }),
2250 x => Err(format!("unknown OpFp func7=0b101_0000 func3: {}", x)),
2251 },
2252 0b110_0000 => match (instruction >> 20) & 0b1_1111 {
2253 0b0_0000 => Ok(Instruction::FcvtWS {
2254 dest: rd,
2255 src: frs1,
2256 rm: RoundingMode::from_int(func3)?,
2257 }),
2258 0b0_0001 => Ok(Instruction::FcvtWuS {
2259 dest: rd,
2260 src: frs1,
2261 rm: RoundingMode::from_int(func3)?,
2262 }),
2263 0b0_0010 => Ok(Instruction::FcvtLS {
2264 dest: rd,
2265 src: frs1,
2266 rm: RoundingMode::from_int(func3)?,
2267 }),
2268 0b0_0011 => Ok(Instruction::FcvtLuS {
2269 dest: rd,
2270 src: frs1,
2271 rm: RoundingMode::from_int(func3)?,
2272 }),
2273 x => Err(format!("unknown OpFp func7=0b001_0100 rs2: {}", x)),
2274 },
2275 0b110_0001 => match (instruction >> 20) & 0b1_1111 {
2276 0b0_0000 => Ok(Instruction::FcvtWD {
2277 dest: rd,
2278 src1: frs1,
2279 rm: RoundingMode::from_int(func3)?,
2280 }),
2281 0b0_0001 => Ok(Instruction::FcvtWuD {
2282 dest: rd,
2283 src1: frs1,
2284 rm: RoundingMode::from_int(func3)?,
2285 }),
2286 0b0_0010 => Ok(Instruction::FcvtLD {
2287 dest: rd,
2288 src1: frs1,
2289 rm: RoundingMode::from_int(func3)?,
2290 }),
2291 0b0_0011 => Ok(Instruction::FcvtLuD {
2292 dest: rd,
2293 src1: frs1,
2294 rm: RoundingMode::from_int(func3)?,
2295 }),
2296 x => Err(format!("unknown OpFp func7=0b001_0100 rs2: {}", x)),
2297 },
2298 0b110_1000 => match (instruction >> 20) & 0b1_1111 {
2299 0b0_0000 => Ok(Instruction::FcvtSW {
2300 dest: frd,
2301 src: rs1,
2302 rm: RoundingMode::from_int(func3)?,
2303 }),
2304 0b0_0001 => Ok(Instruction::FcvtSWu {
2305 dest: frd,
2306 src: rs1,
2307 rm: RoundingMode::from_int(func3)?,
2308 }),
2309 0b0_0010 => Ok(Instruction::FcvtSL {
2310 dest: frd,
2311 src: rs1,
2312 rm: RoundingMode::from_int(func3)?,
2313 }),
2314 0b0_0011 => Ok(Instruction::FcvtSLu {
2315 dest: frd,
2316 src: rs1,
2317 rm: RoundingMode::from_int(func3)?,
2318 }),
2319 x => Err(format!("unknown OpFp func7=0b001_0100 rs2: {}", x)),
2320 },
2321 0b110_1001 => match (instruction >> 20) & 0b1_1111 {
2322 0b0_0000 => Ok(Instruction::FcvtDW {
2323 dest: frd,
2324 src1: rs1,
2325 rm: RoundingMode::from_int(func3)?,
2326 }),
2327 0b0_0001 => Ok(Instruction::FcvtDWu {
2328 dest: frd,
2329 src1: rs1,
2330 rm: RoundingMode::from_int(func3)?,
2331 }),
2332 0b0_0010 => Ok(Instruction::FcvtDL {
2333 dest: frd,
2334 src: rs1,
2335 rm: RoundingMode::from_int(func3)?,
2336 }),
2337 0b0_0011 => Ok(Instruction::FcvtDLu {
2338 dest: frd,
2339 src: rs1,
2340 rm: RoundingMode::from_int(func3)?,
2341 }),
2342 x => Err(format!("unknown OpFp func7=0b001_0101 rs2: {}", x)),
2343 },
2344 0b111_0000 => {
2345 if (instruction >> 20) & 0b1_1111 == 0 {
2346 if func3 == 0 {
2347 Ok(Instruction::FmvXW {
2348 dest: rd,
2349 src: frs1,
2350 })
2351 } else if func3 == 1 {
2352 Ok(Instruction::FclassS {
2353 dest: rd,
2354 src: frs1,
2355 })
2356 } else {
2357 Err(format!(
2358 "unknown OpFp func7=0b111_0000 rs2=0 func3: {}",
2359 func3
2360 ))
2361 }
2362 } else {
2363 Err(format!(
2364 "unknown OpFp func7=0b111_0000 unknown rs2: {} and func3: {}",
2365 (instruction >> 20) & 0b1_1111,
2366 func3
2367 ))
2368 }
2369 }
2370 0b111_0001 => {
2371 if (instruction >> 20) & 0b1_1111 == 0 {
2372 if func3 == 0 {
2373 Ok(Instruction::FmvXD {
2374 dest: rd,
2375 src: frs1,
2376 })
2377 } else if func3 == 1 {
2378 Ok(Instruction::FclassD {
2379 dest: rd,
2380 src1: frs1,
2381 })
2382 } else {
2383 Err(format!(
2384 "unknown OpFp func7=0b111_0001 rs2=0 func3: {}",
2385 func3
2386 ))
2387 }
2388 } else {
2389 Err(format!(
2390 "unknown OpFp func7=0b111_0001 unknown rs2: {} and func3: {}",
2391 (instruction >> 20) & 0b1_1111,
2392 func3
2393 ))
2394 }
2395 }
2396 0b111_1000 => {
2397 if (instruction >> 20) & 0b1_1111 == 0 {
2398 if func3 == 0 {
2399 Ok(Instruction::FmvWX {
2400 dest: frd,
2401 src: rs1,
2402 })
2403 } else {
2404 Err(format!(
2405 "unknown OpFp func7=0b111_1000 rs2=0 func3: {}",
2406 func3
2407 ))
2408 }
2409 } else {
2410 Err(format!(
2411 "unknown OpFp func7=0b111_0000 unknown rs2: {} and func3: {}",
2412 (instruction >> 20) & 0b1_1111,
2413 func3
2414 ))
2415 }
2416 }
2417 0b111_1001 => {
2418 if (instruction >> 20) & 0b1_1111 == 0 {
2419 if func3 == 0 {
2420 Ok(Instruction::FmvDX {
2421 dest: frd,
2422 src: rs1,
2423 })
2424 } else {
2425 Err(format!(
2426 "unknown OpFp func7=0b111_1001 rs2=0 func3: {}",
2427 func3
2428 ))
2429 }
2430 } else {
2431 Err(format!(
2432 "unknown OpFp func7=0b111_0001 unknown rs2: {} and func3: {}",
2433 (instruction >> 20) & 0b1_1111,
2434 func3
2435 ))
2436 }
2437 }
2438 x => Err(format!("Unknown OpFp func7: {x}")),
2439 },
2440 Opcode::Reserved => Err("instruction uses reserved opcode".to_owned()),
2441 Opcode::Madd => match func7 & 0b11 {
2442 0b00 => Ok(Instruction::FmaddS {
2443 dest: frd,
2444 src1: frs1,
2445 src2: frs2,
2446 src3: frs3,
2447 rm: RoundingMode::from_int(func3)?,
2448 }),
2449 0b01 => Ok(Instruction::FmaddD {
2450 dest: frd,
2451 src1: frs1,
2452 src2: frs2,
2453 src3: frs3,
2454 rm: RoundingMode::from_int(func3)?,
2455 }),
2456 _ => Err(format!(
2457 "Fmadd unknown lower 2 bits of func7: {}",
2458 func7 & 0b11
2459 )),
2460 },
2461 Opcode::Msub => match func7 & 0b11 {
2462 0b00 => Ok(Instruction::FmsubS {
2463 dest: frd,
2464 src1: frs1,
2465 src2: frs2,
2466 src3: frs3,
2467 rm: RoundingMode::from_int(func3)?,
2468 }),
2469 0b01 => Ok(Instruction::FmsubD {
2470 dest: frd,
2471 src1: frs1,
2472 src2: frs2,
2473 src3: frs3,
2474 rm: RoundingMode::from_int(func3)?,
2475 }),
2476 _ => Err(format!(
2477 "Fmsub unknown lower 2 bits of func7: {}",
2478 func7 & 0b11
2479 )),
2480 },
2481 Opcode::Nmsub => match func7 & 0b11 {
2482 0b00 => Ok(Instruction::FnmsubS {
2483 dest: frd,
2484 src1: frs1,
2485 src2: frs2,
2486 src3: frs3,
2487 rm: RoundingMode::from_int(func3)?,
2488 }),
2489 0b01 => Ok(Instruction::FnmsubD {
2490 dest: frd,
2491 src1: frs1,
2492 src2: frs2,
2493 src3: frs3,
2494 rm: RoundingMode::from_int(func3)?,
2495 }),
2496 _ => Err(format!(
2497 "Fnmsub unknown lower 2 bits of func7: {}",
2498 func7 & 0b11
2499 )),
2500 },
2501 Opcode::Nmadd => match func7 & 0b11 {
2502 0b00 => Ok(Instruction::FnmaddS {
2503 dest: frd,
2504 src1: frs1,
2505 src2: frs2,
2506 src3: frs3,
2507 rm: RoundingMode::from_int(func3)?,
2508 }),
2509 0b01 => Ok(Instruction::FnmaddD {
2510 dest: frd,
2511 src1: frs1,
2512 src2: frs2,
2513 src3: frs3,
2514 rm: RoundingMode::from_int(func3)?,
2515 }),
2516 _ => Err(format!(
2517 "Fmadd unknown lower 2 bits of func7: {}",
2518 func7 & 0b11
2519 )),
2520 },
2521 Opcode::System => match func3 {
2522 0b000 => Err("Reserved func3 in Opcode SYSTEM".to_owned()),
2523 0b001 => Ok(Instruction::Csrrw {
2524 dest: rd,
2525 src: rs1,
2526 csr: CSR::from_u32(instruction),
2527 }),
2528 0b010 => Ok(Instruction::Csrrs {
2529 dest: rd,
2530 src: rs1,
2531 csr: CSR::from_u32(instruction),
2532 }),
2533 0b011 => Ok(Instruction::Csrrc {
2534 dest: rd,
2535 src: rs1,
2536 csr: CSR::from_u32(instruction),
2537 }),
2538 0b100 => Err("Reserved func3 in Opcode SYSTEM".to_owned()),
2539 0b101 => Ok(Instruction::Csrrwi {
2540 dest: rd,
2541 imm: CSRImmediate::from_u32(instruction),
2542 csr: CSR::from_u32(instruction),
2543 }),
2544 0b110 => Ok(Instruction::Csrrsi {
2545 dest: rd,
2546 imm: CSRImmediate::from_u32(instruction),
2547 csr: CSR::from_u32(instruction),
2548 }),
2549 0b111 => Ok(Instruction::Csrrci {
2550 dest: rd,
2551 imm: CSRImmediate::from_u32(instruction),
2552 csr: CSR::from_u32(instruction),
2553 }),
2554 _ => unreachable!(),
2555 },
2556 }
2557 }
2558
2559 pub fn encode(instruction: &Instruction) -> u32 {
2560 match instruction {
2561 Instruction::Lui { dest, imm } => imm.to_u32() | dest.rd() | 0b0110111,
2562 Instruction::Auipc { dest, imm } => imm.to_u32() | dest.rd() | 0b0010111,
2563 Instruction::Jal { dest, offset } => offset.to_u32() | dest.rd() | 0b1101111,
2564 Instruction::Jalr { dest, base, offset } => {
2565 offset.to_u32() | base.rs1() | dest.rd() | 0b1100111
2566 }
2567 Instruction::Beq { src1, src2, offset } => {
2568 offset.to_u32() | src2.rs2() | src1.rs1() | 0b000 << 12 | 0b1100011
2569 }
2570 Instruction::Bne { src1, src2, offset } => {
2571 offset.to_u32() | src2.rs2() | src1.rs1() | 0b001 << 12 | 0b1100011
2572 }
2573 Instruction::Blt { src1, src2, offset } => {
2574 offset.to_u32() | src2.rs2() | src1.rs1() | 0b100 << 12 | 0b1100011
2575 }
2576 Instruction::Bge { src1, src2, offset } => {
2577 offset.to_u32() | src2.rs2() | src1.rs1() | 0b101 << 12 | 0b1100011
2578 }
2579 Instruction::Bltu { src1, src2, offset } => {
2580 offset.to_u32() | src2.rs2() | src1.rs1() | 0b110 << 12 | 0b1100011
2581 }
2582 Instruction::Bgeu { src1, src2, offset } => {
2583 offset.to_u32() | src2.rs2() | src1.rs1() | 0b111 << 12 | 0b1100011
2584 }
2585 Instruction::Lb { dest, base, offset } => {
2586 offset.to_u32() | base.rs1() | 0b000 << 12 | dest.rd() | 0b0000011
2587 }
2588 Instruction::Lh { dest, base, offset } => {
2589 offset.to_u32() | base.rs1() | 0b001 << 12 | dest.rd() | 0b0000011
2590 }
2591 Instruction::Lw { dest, base, offset } => {
2592 offset.to_u32() | base.rs1() | 0b010 << 12 | dest.rd() | 0b0000011
2593 }
2594 Instruction::Lbu { dest, base, offset } => {
2595 offset.to_u32() | base.rs1() | 0b100 << 12 | dest.rd() | 0b0000011
2596 }
2597 Instruction::Lhu { dest, base, offset } => {
2598 offset.to_u32() | base.rs1() | 0b101 << 12 | dest.rd() | 0b0000011
2599 }
2600 Instruction::Sb { src, base, offset } => {
2601 offset.to_u32() | src.rs2() | base.rs1() | 0b000 << 12 | 0b0100011
2602 }
2603 Instruction::Sh { src, base, offset } => {
2604 offset.to_u32() | src.rs2() | base.rs1() | 0b001 << 12 | 0b0100011
2605 }
2606 Instruction::Sw { src, base, offset } => {
2607 offset.to_u32() | src.rs2() | base.rs1() | 0b010 << 12 | 0b0100011
2608 }
2609 Instruction::Addi { dest, src, imm } => {
2610 imm.to_u32() | src.rs1() | 0b000 << 12 | dest.rd() | 0b0010011
2611 }
2612 Instruction::Slti { dest, src, imm } => {
2613 imm.to_u32() | src.rs1() | 0b010 << 12 | dest.rd() | 0b0010011
2614 }
2615 Instruction::Sltiu { dest, src, imm } => {
2616 imm.to_u32() | src.rs1() | 0b011 << 12 | dest.rd() | 0b0010011
2617 }
2618 Instruction::Xori { dest, src, imm } => {
2619 imm.to_u32() | src.rs1() | 0b100 << 12 | dest.rd() | 0b0010011
2620 }
2621 Instruction::Ori { dest, src, imm } => {
2622 imm.to_u32() | src.rs1() | 0b110 << 12 | dest.rd() | 0b0010011
2623 }
2624 Instruction::Andi { dest, src, imm } => {
2625 imm.to_u32() | src.rs1() | 0b111 << 12 | dest.rd() | 0b0010011
2626 }
2627 Instruction::Slli { dest, src, shamt } => {
2628 shamt.to_u32() | src.rs1() | 0b001 << 12 | dest.rd() | 0b0010011
2629 }
2630 Instruction::Srli { dest, src, shamt } => {
2631 shamt.to_u32() | src.rs1() | 0b101 << 12 | dest.rd() | 0b0010011
2632 }
2633 Instruction::Srai { dest, src, shamt } => {
2634 0b0100000 << 25 | shamt.to_u32() | src.rs1() | 0b101 << 12 | dest.rd() | 0b0010011
2635 }
2636 Instruction::Add { dest, src1, src2 } => {
2637 src2.rs2() | src1.rs1() | 0b000 << 12 | dest.rd() | 0b0110011
2638 }
2639 Instruction::Sub { dest, src1, src2 } => {
2640 0b0100000 << 25 | src2.rs2() | src1.rs1() | 0b000 << 12 | dest.rd() | 0b0110011
2641 }
2642 Instruction::Sll { dest, src1, src2 } => {
2643 src2.rs2() | src1.rs1() | 0b001 << 12 | dest.rd() | 0b0110011
2644 }
2645 Instruction::Slt { dest, src1, src2 } => {
2646 src2.rs2() | src1.rs1() | 0b010 << 12 | dest.rd() | 0b0110011
2647 }
2648 Instruction::Sltu { dest, src1, src2 } => {
2649 src2.rs2() | src1.rs1() | 0b011 << 12 | dest.rd() | 0b0110011
2650 }
2651 Instruction::Xor { dest, src1, src2 } => {
2652 src2.rs2() | src1.rs1() | 0b100 << 12 | dest.rd() | 0b0110011
2653 }
2654 Instruction::Srl { dest, src1, src2 } => {
2655 src2.rs2() | src1.rs1() | 0b101 << 12 | dest.rd() | 0b0110011
2656 }
2657 Instruction::Sra { dest, src1, src2 } => {
2658 0b0100000 << 25 | src2.rs2() | src1.rs1() | 0b0101 << 12 | dest.rd() | 0b0110011
2659 }
2660 Instruction::Or { dest, src1, src2 } => {
2661 src2.rs2() | src1.rs1() | 0b110 << 12 | dest.rd() | 0b0110011
2662 }
2663 Instruction::And { dest, src1, src2 } => {
2664 src2.rs2() | src1.rs1() | 0b111 << 12 | dest.rd() | 0b0110011
2665 }
2666 Instruction::Fence { rd, rs1, ops, fm } => {
2667 (*fm as u32) << 28 | (*ops as u32) << 20 | rs1.rs1() | rd.rd() | 0b0001111
2668 }
2669 Instruction::Ecall => 0b1110011,
2670 Instruction::Ebreak => 0b1 << 20 | 0b1110011,
2671 Instruction::Lwu { dest, base, offset } => {
2672 offset.to_u32() | base.rs1() | 0b110 << 12 | dest.rd() | 0b0000011
2673 }
2674 Instruction::Ld { dest, base, offset } => {
2675 offset.to_u32() | base.rs1() | 0b011 << 12 | dest.rd() | 0b0000011
2676 }
2677 Instruction::Sd { src, base, offset } => {
2678 offset.to_u32() | src.rs2() | base.rs1() | 0b011 << 12 | 0b0100011
2679 }
2680 Instruction::Addiw { dest, src, imm } => {
2681 imm.to_u32() | src.rs1() | 0b000 << 12 | dest.rd() | 0b0011011
2682 }
2683 Instruction::Slliw { dest, src, shamt } => {
2684 shamt.to_u32() | src.rs1() | 0b001 << 12 | dest.rd() | 0b0011011
2685 }
2686 Instruction::Srliw { dest, src, shamt } => {
2687 shamt.to_u32() | src.rs1() | 0b101 << 12 | dest.rd() | 0b0011011
2688 }
2689 Instruction::Sraiw { dest, src, shamt } => {
2690 0b0100000 << 25 | shamt.to_u32() | src.rs1() | 0b101 << 12 | dest.rd() | 0b0011011
2691 }
2692 Instruction::Addw { dest, src1, src2 } => {
2693 src2.rs2() | src1.rs1() | 0b000 << 12 | dest.rd() | 0b0111011
2694 }
2695 Instruction::Subw { dest, src1, src2 } => {
2696 0b0100000 << 25 | src2.rs2() | src1.rs1() | 0b000 << 12 | dest.rd() | 0b0111011
2697 }
2698 Instruction::Sllw { dest, src1, src2 } => {
2699 src2.rs2() | src1.rs1() | 0b001 << 12 | dest.rd() | 0b0111011
2700 }
2701 Instruction::Srlw { dest, src1, src2 } => {
2702 src2.rs2() | src1.rs1() | 0b101 << 12 | dest.rd() | 0b0111011
2703 }
2704 Instruction::Sraw { dest, src1, src2 } => {
2705 0b0100000 << 25 | src2.rs2() | src1.rs1() | 0b101 << 12 | dest.rd() | 0b0111011
2706 }
2707 Instruction::Mul { dest, src1, src2 } => {
2708 0b0000001 << 25 | src2.rs2() | src1.rs1() | 0b000 << 12 | dest.rd() | 0b0110011
2709 }
2710 Instruction::Mulh { dest, src1, src2 } => {
2711 0b0000001 << 25 | src2.rs2() | src1.rs1() | 0b001 << 12 | dest.rd() | 0b0110011
2712 }
2713 Instruction::Mulhsu { dest, src1, src2 } => {
2714 0b0000001 << 25 | src2.rs2() | src1.rs1() | 0b010 << 12 | dest.rd() | 0b0110011
2715 }
2716 Instruction::Mulhu { dest, src1, src2 } => {
2717 0b0000001 << 25 | src2.rs2() | src1.rs1() | 0b011 << 12 | dest.rd() | 0b0110011
2718 }
2719 Instruction::Div { dest, src1, src2 } => {
2720 0b0000001 << 25 | src2.rs2() | src1.rs1() | 0b100 << 12 | dest.rd() | 0b0110011
2721 }
2722 Instruction::Divu { dest, src1, src2 } => {
2723 0b0000001 << 25 | src2.rs2() | src1.rs1() | 0b101 << 12 | dest.rd() | 0b0110011
2724 }
2725 Instruction::Rem { dest, src1, src2 } => {
2726 0b0000001 << 25 | src2.rs2() | src1.rs1() | 0b110 << 12 | dest.rd() | 0b0110011
2727 }
2728 Instruction::Remu { dest, src1, src2 } => {
2729 0b0000001 << 25 | src2.rs2() | src1.rs1() | 0b111 << 12 | dest.rd() | 0b0110011
2730 }
2731 Instruction::Mulw { dest, src1, src2 } => {
2732 0b0000001 << 25 | src2.rs2() | src1.rs1() | 0b000 << 12 | dest.rd() | 0b0111011
2733 }
2734 Instruction::Divw { dest, src1, src2 } => {
2735 0b0000001 << 25 | src2.rs2() | src1.rs1() | 0b100 << 12 | dest.rd() | 0b0111011
2736 }
2737 Instruction::Divuw { dest, src1, src2 } => {
2738 0b0000001 << 25 | src2.rs2() | src1.rs1() | 0b101 << 12 | dest.rd() | 0b0111011
2739 }
2740 Instruction::Remw { dest, src1, src2 } => {
2741 0b0000001 << 25 | src2.rs2() | src1.rs1() | 0b110 << 12 | dest.rd() | 0b0111011
2742 }
2743 Instruction::Remuw { dest, src1, src2 } => {
2744 0b0000001 << 25 | src2.rs2() | src1.rs1() | 0b111 << 12 | dest.rd() | 0b0111011
2745 }
2746 Instruction::LrW { dest, addr, aq, rl } => {
2747 0b00010 << 27
2748 | aqb(*aq)
2749 | rlb(*rl)
2750 | addr.rs1()
2751 | 0b010 << 12
2752 | dest.rd()
2753 | 0b0101111
2754 }
2755 Instruction::ScW {
2756 dest,
2757 addr,
2758 src,
2759 aq,
2760 rl,
2761 } => {
2762 0b00011 << 27
2763 | aqb(*aq)
2764 | rlb(*rl)
2765 | src.rs2()
2766 | addr.rs1()
2767 | 0b010 << 12
2768 | dest.rd()
2769 | 0b0101111
2770 }
2771 Instruction::AmoswapW {
2772 dest,
2773 addr,
2774 src,
2775 aq,
2776 rl,
2777 } => {
2778 0b00001 << 27
2779 | aqb(*aq)
2780 | rlb(*rl)
2781 | src.rs2()
2782 | addr.rs1()
2783 | 0b010 << 12
2784 | dest.rd()
2785 | 0b0101111
2786 }
2787 Instruction::AmoaddW {
2788 dest,
2789 addr,
2790 src,
2791 aq,
2792 rl,
2793 } => {
2794 0b00000 << 27
2795 | aqb(*aq)
2796 | rlb(*rl)
2797 | src.rs2()
2798 | addr.rs1()
2799 | 0b010 << 12
2800 | dest.rd()
2801 | 0b0101111
2802 }
2803 Instruction::AmoxorW {
2804 dest,
2805 addr,
2806 src,
2807 aq,
2808 rl,
2809 } => {
2810 0b00100 << 27
2811 | aqb(*aq)
2812 | rlb(*rl)
2813 | src.rs2()
2814 | addr.rs1()
2815 | 0b010 << 12
2816 | dest.rd()
2817 | 0b0101111
2818 }
2819 Instruction::AmoandW {
2820 dest,
2821 addr,
2822 src,
2823 aq,
2824 rl,
2825 } => {
2826 0b01100 << 27
2827 | aqb(*aq)
2828 | rlb(*rl)
2829 | src.rs2()
2830 | addr.rs1()
2831 | 0b010 << 12
2832 | dest.rd()
2833 | 0b0101111
2834 }
2835 Instruction::AmoorW {
2836 dest,
2837 addr,
2838 src,
2839 aq,
2840 rl,
2841 } => {
2842 0b01000 << 27
2843 | aqb(*aq)
2844 | rlb(*rl)
2845 | src.rs2()
2846 | addr.rs1()
2847 | 0b010 << 12
2848 | dest.rd()
2849 | 0b0101111
2850 }
2851 Instruction::AmominW {
2852 dest,
2853 addr,
2854 src,
2855 aq,
2856 rl,
2857 } => {
2858 0b10000 << 27
2859 | aqb(*aq)
2860 | rlb(*rl)
2861 | src.rs2()
2862 | addr.rs1()
2863 | 0b010 << 12
2864 | dest.rd()
2865 | 0b0101111
2866 }
2867 Instruction::AmomaxW {
2868 dest,
2869 addr,
2870 src,
2871 aq,
2872 rl,
2873 } => {
2874 0b10100 << 27
2875 | aqb(*aq)
2876 | rlb(*rl)
2877 | src.rs2()
2878 | addr.rs1()
2879 | 0b010 << 12
2880 | dest.rd()
2881 | 0b0101111
2882 }
2883 Instruction::AmominuW {
2884 dest,
2885 addr,
2886 src,
2887 aq,
2888 rl,
2889 } => {
2890 0b11000 << 27
2891 | aqb(*aq)
2892 | rlb(*rl)
2893 | src.rs2()
2894 | addr.rs1()
2895 | 0b010 << 12
2896 | dest.rd()
2897 | 0b0101111
2898 }
2899 Instruction::AmomaxuW {
2900 dest,
2901 addr,
2902 src,
2903 aq,
2904 rl,
2905 } => {
2906 0b11100 << 27
2907 | aqb(*aq)
2908 | rlb(*rl)
2909 | src.rs2()
2910 | addr.rs1()
2911 | 0b010 << 12
2912 | dest.rd()
2913 | 0b0101111
2914 }
2915 Instruction::LrD { dest, addr, aq, rl } => {
2916 0b00010 << 27
2917 | aqb(*aq)
2918 | rlb(*rl)
2919 | addr.rs1()
2920 | 0b011 << 12
2921 | dest.rd()
2922 | 0b0101111
2923 }
2924 Instruction::ScD {
2925 dest,
2926 addr,
2927 src,
2928 aq,
2929 rl,
2930 } => {
2931 0b00011 << 27
2932 | aqb(*aq)
2933 | rlb(*rl)
2934 | src.rs2()
2935 | addr.rs1()
2936 | 0b011 << 12
2937 | dest.rd()
2938 | 0b0101111
2939 }
2940 Instruction::AmoswapD {
2941 dest,
2942 addr,
2943 src,
2944 aq,
2945 rl,
2946 } => {
2947 0b00001 << 27
2948 | aqb(*aq)
2949 | rlb(*rl)
2950 | src.rs2()
2951 | addr.rs1()
2952 | 0b011 << 12
2953 | dest.rd()
2954 | 0b0101111
2955 }
2956 Instruction::AmoaddD {
2957 dest,
2958 addr,
2959 src,
2960 aq,
2961 rl,
2962 } => {
2963 0b00000 << 27
2964 | aqb(*aq)
2965 | rlb(*rl)
2966 | src.rs2()
2967 | addr.rs1()
2968 | 0b011 << 12
2969 | dest.rd()
2970 | 0b0101111
2971 }
2972 Instruction::AmoxorD {
2973 dest,
2974 addr,
2975 src,
2976 aq,
2977 rl,
2978 } => {
2979 0b00100 << 27
2980 | aqb(*aq)
2981 | rlb(*rl)
2982 | src.rs2()
2983 | addr.rs1()
2984 | 0b011 << 12
2985 | dest.rd()
2986 | 0b0101111
2987 }
2988 Instruction::AmoandD {
2989 dest,
2990 addr,
2991 src,
2992 aq,
2993 rl,
2994 } => {
2995 0b01100 << 27
2996 | aqb(*aq)
2997 | rlb(*rl)
2998 | src.rs2()
2999 | addr.rs1()
3000 | 0b011 << 12
3001 | dest.rd()
3002 | 0b0101111
3003 }
3004 Instruction::AmoorD {
3005 dest,
3006 addr,
3007 src,
3008 aq,
3009 rl,
3010 } => {
3011 0b01000 << 27
3012 | aqb(*aq)
3013 | rlb(*rl)
3014 | src.rs2()
3015 | addr.rs1()
3016 | 0b011 << 12
3017 | dest.rd()
3018 | 0b0101111
3019 }
3020 Instruction::AmominD {
3021 dest,
3022 addr,
3023 src,
3024 aq,
3025 rl,
3026 } => {
3027 0b10000 << 27
3028 | aqb(*aq)
3029 | rlb(*rl)
3030 | src.rs2()
3031 | addr.rs1()
3032 | 0b011 << 12
3033 | dest.rd()
3034 | 0b0101111
3035 }
3036 Instruction::AmomaxD {
3037 dest,
3038 addr,
3039 src,
3040 aq,
3041 rl,
3042 } => {
3043 0b10100 << 27
3044 | aqb(*aq)
3045 | rlb(*rl)
3046 | src.rs2()
3047 | addr.rs1()
3048 | 0b011 << 12
3049 | dest.rd()
3050 | 0b0101111
3051 }
3052 Instruction::AmominuD {
3053 dest,
3054 addr,
3055 src,
3056 aq,
3057 rl,
3058 } => {
3059 0b11000 << 27
3060 | aqb(*aq)
3061 | rlb(*rl)
3062 | src.rs2()
3063 | addr.rs1()
3064 | 0b011 << 12
3065 | dest.rd()
3066 | 0b0101111
3067 }
3068 Instruction::AmomaxuD {
3069 dest,
3070 addr,
3071 src,
3072 aq,
3073 rl,
3074 } => {
3075 0b11100 << 27
3076 | aqb(*aq)
3077 | rlb(*rl)
3078 | src.rs2()
3079 | addr.rs1()
3080 | 0b011 << 12
3081 | dest.rd()
3082 | 0b0101111
3083 }
3084 Instruction::Flw { dest, base, offset } => {
3085 offset.to_u32() | base.rs1() | 0b010 << 12 | dest.rd() | 0b0000111
3086 }
3087 Instruction::Fsw { base, src, offset } => {
3088 offset.to_u32() | src.rs2() | base.rs1() | 0b010 << 12 | 0b0100111
3089 }
3090 Instruction::FmaddS {
3091 dest,
3092 src1,
3093 src2,
3094 src3,
3095 rm,
3096 } => src3.rs3() | src2.rs2() | src1.rs1() | rm.to_u32() | dest.rd() | 0b1000011,
3097 Instruction::FmsubS {
3098 dest,
3099 src1,
3100 src2,
3101 src3,
3102 rm,
3103 } => src3.rs3() | src2.rs2() | src1.rs1() | rm.to_u32() | dest.rd() | 0b1000111,
3104 Instruction::FnmsubS {
3105 dest,
3106 src1,
3107 src2,
3108 src3,
3109 rm,
3110 } => src3.rs3() | src2.rs2() | src1.rs1() | rm.to_u32() | dest.rd() | 0b1001011,
3111 Instruction::FnmaddS {
3112 dest,
3113 src1,
3114 src2,
3115 src3,
3116 rm,
3117 } => src3.rs3() | src2.rs2() | src1.rs1() | rm.to_u32() | dest.rd() | 0b1001111,
3118 Instruction::FaddS {
3119 dest,
3120 src1,
3121 src2,
3122 rm,
3123 } => 0b0000000 << 25 | src2.rs2() | src1.rs1() | rm.to_u32() | dest.rd() | 0b1010011,
3124 Instruction::FsubS {
3125 dest,
3126 src1,
3127 src2,
3128 rm,
3129 } => 0b0000100 << 25 | src2.rs2() | src1.rs1() | rm.to_u32() | dest.rd() | 0b1010011,
3130 Instruction::FmulS {
3131 dest,
3132 src1,
3133 src2,
3134 rm,
3135 } => 0b0001000 << 25 | src2.rs2() | src1.rs1() | rm.to_u32() | dest.rd() | 0b1010011,
3136 Instruction::FdivS {
3137 dest,
3138 src1,
3139 src2,
3140 rm,
3141 } => 0b0001100 << 25 | src2.rs2() | src1.rs1() | rm.to_u32() | dest.rd() | 0b1010011,
3142 Instruction::FsqrtS { dest, src, rm } => {
3143 0b0101100 << 25 | src.rs1() | rm.to_u32() | dest.rd() | 0b1010011
3144 }
3145 Instruction::FsgnjS { dest, src1, src2 } => {
3146 0b0010000 << 25 | src2.rs2() | src1.rs1() | 0b000 << 12 | dest.rd() | 0b1010011
3147 }
3148 Instruction::FsgnjnS { dest, src1, src2 } => {
3149 0b0010000 << 25 | src2.rs2() | src1.rs1() | 0b001 << 12 | dest.rd() | 0b1010011
3150 }
3151 Instruction::FsgnjxS { dest, src1, src2 } => {
3152 0b0010000 << 25 | src2.rs2() | src1.rs1() | 0b010 << 12 | dest.rd() | 0b1010011
3153 }
3154 Instruction::FminS { dest, src1, src2 } => {
3155 0b0010100 << 25 | src2.rs2() | src1.rs1() | 0b000 << 12 | dest.rd() | 0b1010011
3156 }
3157 Instruction::FmaxS { dest, src1, src2 } => {
3158 0b0010100 << 25 | src2.rs2() | src1.rs1() | 0b001 << 12 | dest.rd() | 0b1010011
3159 }
3160 Instruction::FcvtWS { dest, src, rm } => {
3161 0b1100000 << 25 | 0b00000 << 20 | src.rs1() | rm.to_u32() | dest.rd() | 0b1010011
3162 }
3163 Instruction::FcvtWuS { dest, src, rm } => {
3164 0b1100000 << 25 | 0b00001 << 20 | src.rs1() | rm.to_u32() | dest.rd() | 0b1010011
3165 }
3166 Instruction::FmvXW { dest, src } => 0b1110000 << 25 | src.rs1() | dest.rd() | 0b1010011,
3167 Instruction::FeqS { dest, src1, src2 } => {
3168 0b1010000 << 25 | src2.rs2() | src1.rs1() | 0b010 << 12 | dest.rd() | 0b1010011
3169 }
3170 Instruction::FltS { dest, src1, src2 } => {
3171 0b1010000 << 25 | src2.rs2() | src1.rs1() | 0b001 << 12 | dest.rd() | 0b1010011
3172 }
3173 Instruction::FleS { dest, src1, src2 } => {
3174 0b1010000 << 25 | src2.rs2() | src1.rs1() | 0b000 << 12 | dest.rd() | 0b1010011
3175 }
3176 Instruction::FclassS { dest, src } => {
3177 0b1110000 << 25 | src.rs1() | 0b001 << 12 | dest.rd() | 0b1010011
3178 }
3179 Instruction::FcvtSW { dest, src, rm } => {
3180 0b1101000 << 25 | src.rs1() | rm.to_u32() | dest.rd() | 0b1010011
3181 }
3182 Instruction::FcvtSWu { dest, src, rm } => {
3183 0b1101000 << 25 | 0b00001 << 20 | src.rs1() | rm.to_u32() | dest.rd() | 0b1010011
3184 }
3185 Instruction::FmvWX { dest, src } => 0b1111000 << 25 | src.rs1() | dest.rd() | 0b1010011,
3186 Instruction::FcvtLS { dest, src, rm } => {
3187 0b1100000 << 25 | 0b00010 << 20 | src.rs1() | rm.to_u32() | dest.rd() | 0b1010011
3188 }
3189 Instruction::FcvtLuS { dest, src, rm } => {
3190 0b1100000 << 25 | 0b00011 << 20 | src.rs1() | rm.to_u32() | dest.rd() | 0b1010011
3191 }
3192 Instruction::FcvtSL { dest, src, rm } => {
3193 0b1101000 << 25 | 0b00010 << 20 | src.rs1() | rm.to_u32() | dest.rd() | 0b1010011
3194 }
3195 Instruction::FcvtSLu { dest, src, rm } => {
3196 0b1101000 << 25 | 0b00011 << 20 | src.rs1() | rm.to_u32() | dest.rd() | 0b1010011
3197 }
3198 Instruction::Csrrw { dest, src, csr } => {
3199 csr.to_u32() | src.rs1() | 0b001 << 12 | dest.rd() | 0b1110011
3200 }
3201 Instruction::Csrrs { dest, src, csr } => {
3202 csr.to_u32() | src.rs1() | 0b010 << 12 | dest.rd() | 0b1110011
3203 }
3204 Instruction::Csrrc { dest, src, csr } => {
3205 csr.to_u32() | src.rs1() | 0b011 << 12 | dest.rd() | 0b1110011
3206 }
3207 Instruction::Csrrwi { dest, imm, csr } => {
3208 csr.to_u32() | imm.to_u32() | 0b101 << 12 | dest.rd() | 0b1110011
3209 }
3210 Instruction::Csrrsi { dest, imm, csr } => {
3211 csr.to_u32() | imm.to_u32() | 0b110 << 12 | dest.rd() | 0b1110011
3212 }
3213 Instruction::Csrrci { dest, imm, csr } => {
3214 csr.to_u32() | imm.to_u32() | 0b111 << 12 | dest.rd() | 0b1110011
3215 }
3216 Instruction::FenceI => 0b001 << 12 | 0b0001111,
3217 Instruction::Fld { dest, base, offset } => {
3218 offset.to_u32() | base.rs1() | 0b011 << 12 | dest.rd() | 0b0000111
3219 }
3220 Instruction::Fsd { src, base, offset } => {
3221 offset.to_u32() | base.rs1() | 0b011 << 12 | src.rs2() | 0b0100111
3222 }
3223 Instruction::FmaddD {
3224 dest,
3225 src1,
3226 src2,
3227 src3,
3228 rm,
3229 } => {
3230 src3.rs3()
3231 | 0b01 << 25
3232 | src2.rs2()
3233 | src1.rs1()
3234 | rm.to_u32()
3235 | dest.rd()
3236 | 0b1000011
3237 }
3238 Instruction::FmsubD {
3239 dest,
3240 src1,
3241 src2,
3242 src3,
3243 rm,
3244 } => {
3245 src3.rs3()
3246 | 0b01 << 25
3247 | src2.rs2()
3248 | src1.rs1()
3249 | rm.to_u32()
3250 | dest.rd()
3251 | 0b1000111
3252 }
3253 Instruction::FnmaddD {
3254 dest,
3255 src1,
3256 src2,
3257 src3,
3258 rm,
3259 } => {
3260 src3.rs3()
3261 | 0b01 << 25
3262 | src2.rs2()
3263 | src1.rs1()
3264 | rm.to_u32()
3265 | dest.rd()
3266 | 0b1001111
3267 }
3268 Instruction::FnmsubD {
3269 dest,
3270 src1,
3271 src2,
3272 src3,
3273 rm,
3274 } => {
3275 src3.rs3()
3276 | 0b01 << 25
3277 | src2.rs2()
3278 | src1.rs1()
3279 | rm.to_u32()
3280 | dest.rd()
3281 | 0b1001011
3282 }
3283 Instruction::FaddD {
3284 dest,
3285 src1,
3286 src2,
3287 rm,
3288 } => 0b0000001 << 25 | src2.rs2() | src1.rs1() | rm.to_u32() | dest.rd() | 0b1010011,
3289 Instruction::FsubD {
3290 dest,
3291 src1,
3292 src2,
3293 rm,
3294 } => 0b0000101 << 25 | src2.rs2() | src1.rs1() | rm.to_u32() | dest.rd() | 0b1010011,
3295 Instruction::FmulD {
3296 dest,
3297 src1,
3298 src2,
3299 rm,
3300 } => 0b0001001 << 25 | src2.rs2() | src1.rs1() | rm.to_u32() | dest.rd() | 0b1010011,
3301 Instruction::FdivD {
3302 dest,
3303 src1,
3304 src2,
3305 rm,
3306 } => 0b0001101 << 25 | src2.rs2() | src1.rs1() | rm.to_u32() | dest.rd() | 0b1010011,
3307 Instruction::FsqrtD {
3308 dest,
3309 src: src1,
3310 rm,
3311 } => 0b0101101 << 25 | src1.rs1() | rm.to_u32() | dest.rd() | 0b1010011,
3312 Instruction::FsgnjD { dest, src1, src2 } => {
3313 0b0010001 << 25 | src2.rs2() | src1.rs1() | 0b000 << 12 | dest.rd() | 0b1010011
3314 }
3315 Instruction::FsgnjnD { dest, src1, src2 } => {
3316 0b0010001 << 25 | src2.rs2() | src1.rs1() | 0b001 << 12 | dest.rd() | 0b1010011
3317 }
3318 Instruction::FsgnjxD { dest, src1, src2 } => {
3319 0b0010001 << 25 | src2.rs2() | src1.rs1() | 0b010 << 12 | dest.rd() | 0b1010011
3320 }
3321 Instruction::FminD { dest, src1, src2 } => {
3322 0b0010101 << 25 | src2.rs2() | src1.rs1() | 0b000 << 12 | dest.rd() | 0b1010011
3323 }
3324 Instruction::FmaxD { dest, src1, src2 } => {
3325 0b0010101 << 25 | src2.rs2() | src1.rs1() | 0b001 << 12 | dest.rd() | 0b1010011
3326 }
3327 Instruction::FcvtSD { dest, src, rm } => {
3328 0b0100000 << 25 | 0b00001 << 20 | src.rs1() | rm.to_u32() | dest.rd() | 0b1010011
3329 }
3330 Instruction::FcvtDS { dest, src, rm } => {
3331 0b0100001 << 25 | 0b00000 << 20 | src.rs1() | rm.to_u32() | dest.rd() | 0b1010011
3332 }
3333 Instruction::FeqD { dest, src1, src2 } => {
3334 0b1010001 << 25 | src2.rs2() | src1.rs1() | 0b010 << 12 | dest.rd() | 0b1010011
3335 }
3336 Instruction::FltD { dest, src1, src2 } => {
3337 0b1010001 << 25 | src2.rs2() | src1.rs1() | 0b001 << 12 | dest.rd() | 0b1010011
3338 }
3339 Instruction::FleD { dest, src1, src2 } => {
3340 0b1010001 << 25 | src2.rs2() | src1.rs1() | 0b000 << 12 | dest.rd() | 0b1010011
3341 }
3342 Instruction::FclassD { dest, src1 } => {
3343 0b1110001 << 25 | 0b00000 << 20 | src1.rs1() | 0b001 << 12 | dest.rd() | 0b1010011
3344 }
3345 Instruction::FcvtWD { dest, src1, rm } => {
3346 0b1100001 << 25 | 0b00000 << 20 | src1.rs1() | rm.to_u32() | dest.rd() | 0b1010011
3347 }
3348 Instruction::FcvtWuD { dest, src1, rm } => {
3349 0b1100001 << 25 | 0b00001 << 20 | src1.rs1() | rm.to_u32() | dest.rd() | 0b1010011
3350 }
3351 Instruction::FcvtDW { dest, src1, rm } => {
3352 0b1101001 << 25 | 0b00000 << 20 | src1.rs1() | rm.to_u32() | dest.rd() | 0b1010011
3353 }
3354 Instruction::FcvtDWu { dest, src1, rm } => {
3355 0b1101001 << 25 | 0b00001 << 20 | src1.rs1() | rm.to_u32() | dest.rd() | 0b1010011
3356 }
3357 Instruction::FcvtLD { dest, src1, rm } => {
3358 0b1100001 << 25 | 0b00010 << 20 | src1.rs1() | rm.to_u32() | dest.rd() | 0b1010011
3359 }
3360 Instruction::FcvtLuD { dest, src1, rm } => {
3361 0b1100001 << 25 | 0b00011 << 20 | src1.rs1() | rm.to_u32() | dest.rd() | 0b1010011
3362 }
3363 Instruction::FmvXD { dest, src } => {
3364 0b1110001 << 25 | 0b00000 << 20 | src.rs1() | 0b000 << 12 | dest.rd() | 0b1010011
3365 }
3366 Instruction::FcvtDL {
3367 dest,
3368 src: src1,
3369 rm,
3370 } => 0b1101001 << 25 | 0b00010 << 20 | src1.rs1() | rm.to_u32() | dest.rd() | 0b1010011,
3371 Instruction::FcvtDLu {
3372 dest,
3373 src: src1,
3374 rm,
3375 } => 0b1101001 << 25 | 0b00011 << 20 | src1.rs1() | rm.to_u32() | dest.rd() | 0b1010011,
3376 Instruction::FmvDX { dest, src } => {
3377 0b1111001 << 25 | 0b00000 << 20 | src.rs1() | 0b000 << 12 | dest.rd() | 0b1010011
3378 }
3379 }
3380 }
3381}
3382
3383pub fn disassemble_instruction(instruction: &Instruction) -> String {
3385 format!("{}", instruction)
3386}