1#![allow(dead_code)]
24
25#[derive(Debug, Clone, Copy, PartialEq, Eq)]
31pub enum Inst {
32 Lb {
34 rd: u8,
35 rs1: u8,
36 imm: i32,
37 },
38 Lh {
39 rd: u8,
40 rs1: u8,
41 imm: i32,
42 },
43 Lw {
44 rd: u8,
45 rs1: u8,
46 imm: i32,
47 },
48 Ld {
49 rd: u8,
50 rs1: u8,
51 imm: i32,
52 },
53 Lbu {
54 rd: u8,
55 rs1: u8,
56 imm: i32,
57 },
58 Lhu {
59 rd: u8,
60 rs1: u8,
61 imm: i32,
62 },
63 Lwu {
64 rd: u8,
65 rs1: u8,
66 imm: i32,
67 },
68
69 Sb {
71 rs1: u8,
72 rs2: u8,
73 imm: i32,
74 },
75 Sh {
76 rs1: u8,
77 rs2: u8,
78 imm: i32,
79 },
80 Sw {
81 rs1: u8,
82 rs2: u8,
83 imm: i32,
84 },
85 Sd {
86 rs1: u8,
87 rs2: u8,
88 imm: i32,
89 },
90
91 Addi {
94 rd: u8,
95 rs1: u8,
96 imm: i32,
97 },
98 Slti {
99 rd: u8,
100 rs1: u8,
101 imm: i32,
102 },
103 Sltiu {
104 rd: u8,
105 rs1: u8,
106 imm: i32,
107 },
108 Andi {
109 rd: u8,
110 rs1: u8,
111 imm: i32,
112 },
113 Ori {
114 rd: u8,
115 rs1: u8,
116 imm: i32,
117 },
118 Xori {
119 rd: u8,
120 rs1: u8,
121 imm: i32,
122 },
123 Slli {
124 rd: u8,
125 rs1: u8,
126 shamt: u8,
127 },
128 Srli {
129 rd: u8,
130 rs1: u8,
131 shamt: u8,
132 },
133 Srai {
134 rd: u8,
135 rs1: u8,
136 shamt: u8,
137 },
138 Addiw {
140 rd: u8,
141 rs1: u8,
142 imm: i32,
143 },
144 Slliw {
145 rd: u8,
146 rs1: u8,
147 shamt: u8,
148 },
149 Srliw {
150 rd: u8,
151 rs1: u8,
152 shamt: u8,
153 },
154 Sraiw {
155 rd: u8,
156 rs1: u8,
157 shamt: u8,
158 },
159
160 Add {
163 rd: u8,
164 rs1: u8,
165 rs2: u8,
166 },
167 Sub {
168 rd: u8,
169 rs1: u8,
170 rs2: u8,
171 },
172 Sll {
173 rd: u8,
174 rs1: u8,
175 rs2: u8,
176 },
177 Srl {
178 rd: u8,
179 rs1: u8,
180 rs2: u8,
181 },
182 Sra {
183 rd: u8,
184 rs1: u8,
185 rs2: u8,
186 },
187 Slt {
188 rd: u8,
189 rs1: u8,
190 rs2: u8,
191 },
192 Sltu {
193 rd: u8,
194 rs1: u8,
195 rs2: u8,
196 },
197 Xor {
198 rd: u8,
199 rs1: u8,
200 rs2: u8,
201 },
202 Or {
203 rd: u8,
204 rs1: u8,
205 rs2: u8,
206 },
207 And {
208 rd: u8,
209 rs1: u8,
210 rs2: u8,
211 },
212 Addw {
214 rd: u8,
215 rs1: u8,
216 rs2: u8,
217 },
218 Subw {
219 rd: u8,
220 rs1: u8,
221 rs2: u8,
222 },
223 Sllw {
224 rd: u8,
225 rs1: u8,
226 rs2: u8,
227 },
228 Srlw {
229 rd: u8,
230 rs1: u8,
231 rs2: u8,
232 },
233 Sraw {
234 rd: u8,
235 rs1: u8,
236 rs2: u8,
237 },
238
239 Mul {
241 rd: u8,
242 rs1: u8,
243 rs2: u8,
244 },
245 Mulh {
246 rd: u8,
247 rs1: u8,
248 rs2: u8,
249 },
250 Mulhsu {
251 rd: u8,
252 rs1: u8,
253 rs2: u8,
254 },
255 Mulhu {
256 rd: u8,
257 rs1: u8,
258 rs2: u8,
259 },
260 Div {
261 rd: u8,
262 rs1: u8,
263 rs2: u8,
264 },
265 Divu {
266 rd: u8,
267 rs1: u8,
268 rs2: u8,
269 },
270 Rem {
271 rd: u8,
272 rs1: u8,
273 rs2: u8,
274 },
275 Remu {
276 rd: u8,
277 rs1: u8,
278 rs2: u8,
279 },
280 Mulw {
281 rd: u8,
282 rs1: u8,
283 rs2: u8,
284 },
285 Divw {
286 rd: u8,
287 rs1: u8,
288 rs2: u8,
289 },
290 Divuw {
291 rd: u8,
292 rs1: u8,
293 rs2: u8,
294 },
295 Remw {
296 rd: u8,
297 rs1: u8,
298 rs2: u8,
299 },
300 Remuw {
301 rd: u8,
302 rs1: u8,
303 rs2: u8,
304 },
305
306 Clz {
308 rd: u8,
309 rs1: u8,
310 },
311 Clzw {
312 rd: u8,
313 rs1: u8,
314 },
315 Ctz {
316 rd: u8,
317 rs1: u8,
318 },
319 Ctzw {
320 rd: u8,
321 rs1: u8,
322 },
323 Cpop {
324 rd: u8,
325 rs1: u8,
326 },
327 Cpopw {
328 rd: u8,
329 rs1: u8,
330 },
331 SextB {
332 rd: u8,
333 rs1: u8,
334 },
335 SextH {
336 rd: u8,
337 rs1: u8,
338 },
339 ZextH {
340 rd: u8,
341 rs1: u8,
342 }, Rev8 {
344 rd: u8,
345 rs1: u8,
346 },
347 OrcB {
348 rd: u8,
349 rs1: u8,
350 },
351 Min {
352 rd: u8,
353 rs1: u8,
354 rs2: u8,
355 },
356 Minu {
357 rd: u8,
358 rs1: u8,
359 rs2: u8,
360 },
361 Max {
362 rd: u8,
363 rs1: u8,
364 rs2: u8,
365 },
366 Maxu {
367 rd: u8,
368 rs1: u8,
369 rs2: u8,
370 },
371 Andn {
372 rd: u8,
373 rs1: u8,
374 rs2: u8,
375 },
376 Orn {
377 rd: u8,
378 rs1: u8,
379 rs2: u8,
380 },
381 Xnor {
382 rd: u8,
383 rs1: u8,
384 rs2: u8,
385 },
386 Rol {
387 rd: u8,
388 rs1: u8,
389 rs2: u8,
390 },
391 Ror {
392 rd: u8,
393 rs1: u8,
394 rs2: u8,
395 },
396 Rolw {
397 rd: u8,
398 rs1: u8,
399 rs2: u8,
400 },
401 Rorw {
402 rd: u8,
403 rs1: u8,
404 rs2: u8,
405 },
406 Rori {
407 rd: u8,
408 rs1: u8,
409 shamt: u8,
410 },
411 Roriw {
412 rd: u8,
413 rs1: u8,
414 shamt: u8,
415 },
416
417 Sh1add {
419 rd: u8,
420 rs1: u8,
421 rs2: u8,
422 },
423 Sh2add {
424 rd: u8,
425 rs1: u8,
426 rs2: u8,
427 },
428 Sh3add {
429 rd: u8,
430 rs1: u8,
431 rs2: u8,
432 },
433 Sh1adduw {
434 rd: u8,
435 rs1: u8,
436 rs2: u8,
437 },
438 Sh2adduw {
439 rd: u8,
440 rs1: u8,
441 rs2: u8,
442 },
443 Sh3adduw {
444 rd: u8,
445 rs1: u8,
446 rs2: u8,
447 },
448 Adduw {
449 rd: u8,
450 rs1: u8,
451 rs2: u8,
452 },
453 Slliuw {
454 rd: u8,
455 rs1: u8,
456 shamt: u8,
457 },
458
459 Bclr {
461 rd: u8,
462 rs1: u8,
463 rs2: u8,
464 },
465 Bset {
466 rd: u8,
467 rs1: u8,
468 rs2: u8,
469 },
470 Binv {
471 rd: u8,
472 rs1: u8,
473 rs2: u8,
474 },
475 Bext {
476 rd: u8,
477 rs1: u8,
478 rs2: u8,
479 },
480 Bclri {
481 rd: u8,
482 rs1: u8,
483 shamt: u8,
484 },
485 Bseti {
486 rd: u8,
487 rs1: u8,
488 shamt: u8,
489 },
490 Binvi {
491 rd: u8,
492 rs1: u8,
493 shamt: u8,
494 },
495 Bexti {
496 rd: u8,
497 rs1: u8,
498 shamt: u8,
499 },
500
501 CzeroEqz {
503 rd: u8,
504 rs1: u8,
505 rs2: u8,
506 },
507 CzeroNez {
508 rd: u8,
509 rs1: u8,
510 rs2: u8,
511 },
512
513 Lui {
515 rd: u8,
516 imm: i32,
517 },
518 Auipc {
523 rd: u8,
524 imm: i32,
525 },
526
527 Jal {
532 rd: u8,
533 imm: i32,
534 },
535 Jalr {
541 rd: u8,
542 rs1: u8,
543 imm: i32,
544 },
545 Beq {
546 rs1: u8,
547 rs2: u8,
548 imm: i32,
549 },
550 Bne {
551 rs1: u8,
552 rs2: u8,
553 imm: i32,
554 },
555 Blt {
556 rs1: u8,
557 rs2: u8,
558 imm: i32,
559 },
560 Bge {
561 rs1: u8,
562 rs2: u8,
563 imm: i32,
564 },
565 Bltu {
566 rs1: u8,
567 rs2: u8,
568 imm: i32,
569 },
570 Bgeu {
571 rs1: u8,
572 rs2: u8,
573 imm: i32,
574 },
575
576 Fence,
579 FenceI,
581
582 Trap,
585 EcallJar,
587 Ecalli {
589 imm: i32,
590 },
591 Fallthrough,
595
596 Reserved {
601 raw: u32,
602 },
603}
604
605impl Inst {
606 pub fn uses_reserved_reg(&self) -> bool {
619 use crate::regs::reg_is_reserved as r;
620 use Inst::*;
621 match *self {
622 Add { rd, rs1, rs2 }
624 | Sub { rd, rs1, rs2 }
625 | Sll { rd, rs1, rs2 }
626 | Srl { rd, rs1, rs2 }
627 | Sra { rd, rs1, rs2 }
628 | Slt { rd, rs1, rs2 }
629 | Sltu { rd, rs1, rs2 }
630 | Xor { rd, rs1, rs2 }
631 | Or { rd, rs1, rs2 }
632 | And { rd, rs1, rs2 }
633 | Addw { rd, rs1, rs2 }
634 | Subw { rd, rs1, rs2 }
635 | Sllw { rd, rs1, rs2 }
636 | Srlw { rd, rs1, rs2 }
637 | Sraw { rd, rs1, rs2 }
638 | Mul { rd, rs1, rs2 }
639 | Mulh { rd, rs1, rs2 }
640 | Mulhsu { rd, rs1, rs2 }
641 | Mulhu { rd, rs1, rs2 }
642 | Div { rd, rs1, rs2 }
643 | Divu { rd, rs1, rs2 }
644 | Rem { rd, rs1, rs2 }
645 | Remu { rd, rs1, rs2 }
646 | Mulw { rd, rs1, rs2 }
647 | Divw { rd, rs1, rs2 }
648 | Divuw { rd, rs1, rs2 }
649 | Remw { rd, rs1, rs2 }
650 | Remuw { rd, rs1, rs2 }
651 | Min { rd, rs1, rs2 }
652 | Minu { rd, rs1, rs2 }
653 | Max { rd, rs1, rs2 }
654 | Maxu { rd, rs1, rs2 }
655 | Andn { rd, rs1, rs2 }
656 | Orn { rd, rs1, rs2 }
657 | Xnor { rd, rs1, rs2 }
658 | Rol { rd, rs1, rs2 }
659 | Ror { rd, rs1, rs2 }
660 | Rolw { rd, rs1, rs2 }
661 | Rorw { rd, rs1, rs2 }
662 | Sh1add { rd, rs1, rs2 }
663 | Sh2add { rd, rs1, rs2 }
664 | Sh3add { rd, rs1, rs2 }
665 | Sh1adduw { rd, rs1, rs2 }
666 | Sh2adduw { rd, rs1, rs2 }
667 | Sh3adduw { rd, rs1, rs2 }
668 | Adduw { rd, rs1, rs2 }
669 | Bclr { rd, rs1, rs2 }
670 | Bset { rd, rs1, rs2 }
671 | Binv { rd, rs1, rs2 }
672 | Bext { rd, rs1, rs2 }
673 | CzeroEqz { rd, rs1, rs2 }
674 | CzeroNez { rd, rs1, rs2 } => r(rd) || r(rs1) || r(rs2),
675
676 Lb { rd, rs1, .. }
678 | Lh { rd, rs1, .. }
679 | Lw { rd, rs1, .. }
680 | Ld { rd, rs1, .. }
681 | Lbu { rd, rs1, .. }
682 | Lhu { rd, rs1, .. }
683 | Lwu { rd, rs1, .. }
684 | Addi { rd, rs1, .. }
685 | Slti { rd, rs1, .. }
686 | Sltiu { rd, rs1, .. }
687 | Andi { rd, rs1, .. }
688 | Ori { rd, rs1, .. }
689 | Xori { rd, rs1, .. }
690 | Slli { rd, rs1, .. }
691 | Srli { rd, rs1, .. }
692 | Srai { rd, rs1, .. }
693 | Addiw { rd, rs1, .. }
694 | Slliw { rd, rs1, .. }
695 | Srliw { rd, rs1, .. }
696 | Sraiw { rd, rs1, .. }
697 | Clz { rd, rs1 }
698 | Clzw { rd, rs1 }
699 | Ctz { rd, rs1 }
700 | Ctzw { rd, rs1 }
701 | Cpop { rd, rs1 }
702 | Cpopw { rd, rs1 }
703 | SextB { rd, rs1 }
704 | SextH { rd, rs1 }
705 | ZextH { rd, rs1 }
706 | Rev8 { rd, rs1 }
707 | OrcB { rd, rs1 }
708 | Rori { rd, rs1, .. }
709 | Roriw { rd, rs1, .. }
710 | Slliuw { rd, rs1, .. }
711 | Bclri { rd, rs1, .. }
712 | Bseti { rd, rs1, .. }
713 | Binvi { rd, rs1, .. }
714 | Bexti { rd, rs1, .. }
715 | Jalr { rd, rs1, .. } => r(rd) || r(rs1),
716
717 Sb { rs1, rs2, .. }
719 | Sh { rs1, rs2, .. }
720 | Sw { rs1, rs2, .. }
721 | Sd { rs1, rs2, .. }
722 | Beq { rs1, rs2, .. }
723 | Bne { rs1, rs2, .. }
724 | Blt { rs1, rs2, .. }
725 | Bge { rs1, rs2, .. }
726 | Bltu { rs1, rs2, .. }
727 | Bgeu { rs1, rs2, .. } => r(rs1) || r(rs2),
728
729 Lui { rd, .. } | Auipc { rd, .. } | Jal { rd, .. } => r(rd),
731
732 Fence | FenceI | Trap | EcallJar | Ecalli { .. } | Fallthrough | Reserved { .. } => {
734 false
735 }
736 }
737 }
738}
739
740#[inline]
751fn word_reg_class_hits(w: u32, pred: fn(u8) -> bool) -> bool {
752 let r = |x: u32| pred(x as u8);
753 let rd = (w >> 7) & 0x1F;
754 let rs1 = (w >> 15) & 0x1F;
755 let rs2 = (w >> 20) & 0x1F;
756 match w & 0x7F {
757 0b011_0011 | 0b011_1011 => r(rd) || r(rs1) || r(rs2),
759 0b000_0011 | 0b001_0011 | 0b001_1011 | 0b110_0111 => r(rd) || r(rs1),
761 0b010_0011 | 0b110_0011 => r(rs1) || r(rs2),
763 0b011_0111 | 0b001_0111 | 0b110_1111 => r(rd),
765 _ => false,
768 }
769}
770
771#[inline]
781pub fn word_uses_reserved_reg(w: u32) -> bool {
782 word_reg_class_hits(w, crate::regs::reg_is_reserved)
783}
784
785#[inline]
794pub fn word_uses_spilled_reg(w: u32) -> bool {
795 word_reg_class_hits(w, crate::regs::reg_is_spilled)
796}
797
798const OP_LOAD: u32 = 0b00_000;
801const OP_STORE: u32 = 0b01_000;
802const OP_MADD: u32 = 0b10_000; const OP_BRANCH: u32 = 0b11_000;
804
805const OP_LOAD_FP: u32 = 0b00_001; const OP_STORE_FP: u32 = 0b01_001; const OP_JALR: u32 = 0b11_001;
808
809const OP_CUSTOM_0: u32 = 0b00_010;
810const OP_CUSTOM_1: u32 = 0b01_010; const OP_CUSTOM_2_OR_RV128: u32 = 0b10_010; const OP_MISC_MEM: u32 = 0b00_011;
815const OP_AMO: u32 = 0b01_011; const OP_JAL: u32 = 0b11_011;
817
818const OP_IMM: u32 = 0b00_100;
819const OP_OP: u32 = 0b01_100;
820const OP_OP_FP: u32 = 0b10_100; const OP_SYSTEM: u32 = 0b11_100;
822
823const OP_AUIPC: u32 = 0b00_101;
824const OP_LUI: u32 = 0b01_101;
825const OP_OP_IMM_32: u32 = 0b00_110;
826const OP_OP_32: u32 = 0b01_110;
827
828pub fn decode(bytes: &[u8]) -> Option<(Inst, u8)> {
836 if bytes.len() < 2 {
837 return None;
838 }
839 let lo16 = u16::from_le_bytes([bytes[0], bytes[1]]);
840 if lo16 & 0b11 != 0b11 {
844 let inst = decompress(lo16);
848 let inst = reserve_if_reserved_reg(inst, lo16 as u32);
849 return Some((inst, 2));
850 }
851 if bytes.len() < 4 {
852 return None;
853 }
854 let w = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
855 Some((reserve_if_reserved_reg(decode_32(w), w), 4))
856}
857
858#[inline]
862fn reserve_if_reserved_reg(inst: Inst, raw: u32) -> Inst {
863 if inst.uses_reserved_reg() {
864 Inst::Reserved { raw }
865 } else {
866 inst
867 }
868}
869
870fn decode_32(w: u32) -> Inst {
875 let major = (w >> 2) & 0x1F; if w & 0b11 != 0b11 {
877 return Inst::Reserved { raw: w };
878 }
879 let rd = ((w >> 7) & 0x1F) as u8;
880 let rs1 = ((w >> 15) & 0x1F) as u8;
881 let rs2 = ((w >> 20) & 0x1F) as u8;
882 let funct3 = ((w >> 12) & 0x07) as u8;
883 let funct7 = ((w >> 25) & 0x7F) as u8;
884
885 match major {
886 OP_LOAD => decode_load(w, rd, rs1, funct3),
887 OP_STORE => decode_store(w, rs1, rs2, funct3),
888 OP_IMM => decode_op_imm(w, rd, rs1, funct3),
889 OP_OP_IMM_32 => decode_op_imm_32(w, rd, rs1, funct3),
890 OP_OP => decode_op(rd, rs1, rs2, funct3, funct7, w),
891 OP_OP_32 => decode_op_32(rd, rs1, rs2, funct3, funct7, w),
892 OP_LUI => Inst::Lui {
893 rd,
894 imm: (w & 0xFFFFF000) as i32,
895 },
896 OP_AUIPC => Inst::Auipc {
897 rd,
898 imm: (w & 0xFFFFF000) as i32,
899 },
900 OP_JAL => {
901 let imm = imm_j(w);
902 Inst::Jal { rd, imm }
903 }
904 OP_JALR if funct3 == 0 => Inst::Jalr {
906 rd,
907 rs1,
908 imm: imm_i(w),
909 },
910 OP_BRANCH => decode_branch(rs1, rs2, funct3, imm_b(w), w),
911 OP_MISC_MEM => decode_misc_mem(funct3),
912 OP_SYSTEM => Inst::Reserved { raw: w }, OP_CUSTOM_0 => decode_custom_0(w, rd, rs1, funct3),
914 OP_CUSTOM_1 => Inst::Reserved { raw: w }, _ => Inst::Reserved { raw: w },
916 }
917}
918
919fn decode_load(w: u32, rd: u8, rs1: u8, funct3: u8) -> Inst {
920 let imm = imm_i(w);
921 match funct3 {
922 0b000 => Inst::Lb { rd, rs1, imm },
923 0b001 => Inst::Lh { rd, rs1, imm },
924 0b010 => Inst::Lw { rd, rs1, imm },
925 0b011 => Inst::Ld { rd, rs1, imm },
926 0b100 => Inst::Lbu { rd, rs1, imm },
927 0b101 => Inst::Lhu { rd, rs1, imm },
928 0b110 => Inst::Lwu { rd, rs1, imm },
929 _ => Inst::Reserved { raw: w },
930 }
931}
932
933fn decode_store(w: u32, rs1: u8, rs2: u8, funct3: u8) -> Inst {
934 let imm = imm_s(w);
935 match funct3 {
936 0b000 => Inst::Sb { rs1, rs2, imm },
937 0b001 => Inst::Sh { rs1, rs2, imm },
938 0b010 => Inst::Sw { rs1, rs2, imm },
939 0b011 => Inst::Sd { rs1, rs2, imm },
940 _ => Inst::Reserved { raw: w },
941 }
942}
943
944fn decode_op_imm(w: u32, rd: u8, rs1: u8, funct3: u8) -> Inst {
945 let imm = imm_i(w);
946 let shamt = (w >> 20) & 0x3F; let shtype = (w >> 26) & 0x3F; match funct3 {
949 0b000 => Inst::Addi { rd, rs1, imm },
950 0b010 => Inst::Slti { rd, rs1, imm },
951 0b011 => Inst::Sltiu { rd, rs1, imm },
952 0b100 => Inst::Xori { rd, rs1, imm },
953 0b110 => Inst::Ori { rd, rs1, imm },
954 0b111 => Inst::Andi { rd, rs1, imm },
955 0b001 => match shtype {
956 0b000000 => Inst::Slli {
957 rd,
958 rs1,
959 shamt: shamt as u8,
960 },
961 0b010010 => Inst::Bclri {
963 rd,
964 rs1,
965 shamt: shamt as u8,
966 },
967 0b001010 => Inst::Bseti {
968 rd,
969 rs1,
970 shamt: shamt as u8,
971 },
972 0b011010 => Inst::Binvi {
973 rd,
974 rs1,
975 shamt: shamt as u8,
976 },
977 0b011000 => match rs2_field(w) {
979 0b00000 => Inst::Clz { rd, rs1 },
980 0b00001 => Inst::Ctz { rd, rs1 },
981 0b00010 => Inst::Cpop { rd, rs1 },
982 0b00100 => Inst::SextB { rd, rs1 },
983 0b00101 => Inst::SextH { rd, rs1 },
984 _ => Inst::Reserved { raw: w },
985 },
986 _ => Inst::Reserved { raw: w },
987 },
988 0b101 => match shtype {
989 0b000000 => Inst::Srli {
990 rd,
991 rs1,
992 shamt: shamt as u8,
993 },
994 0b010000 => Inst::Srai {
995 rd,
996 rs1,
997 shamt: shamt as u8,
998 },
999 0b010010 => Inst::Bexti {
1001 rd,
1002 rs1,
1003 shamt: shamt as u8,
1004 },
1005 0b011000 => Inst::Rori {
1007 rd,
1008 rs1,
1009 shamt: shamt as u8,
1010 },
1011 0b001010 => match rs2_field(w) {
1013 0b00111 => Inst::OrcB { rd, rs1 },
1014 _ => Inst::Reserved { raw: w },
1015 },
1016 0b011010 => match rs2_field(w) {
1017 0b11000 => Inst::Rev8 { rd, rs1 },
1018 _ => Inst::Reserved { raw: w },
1019 },
1020 _ => Inst::Reserved { raw: w },
1021 },
1022 _ => Inst::Reserved { raw: w },
1023 }
1024}
1025
1026fn decode_op_imm_32(w: u32, rd: u8, rs1: u8, funct3: u8) -> Inst {
1027 let imm = imm_i(w);
1028 let shamt5 = ((w >> 20) & 0x1F) as u8; let funct7 = (w >> 25) & 0x7F;
1030 match funct3 {
1031 0b000 => Inst::Addiw { rd, rs1, imm },
1032 0b001 => match funct7 {
1033 0b0000000 => Inst::Slliw {
1034 rd,
1035 rs1,
1036 shamt: shamt5,
1037 },
1038 0b0000100 => Inst::Slliuw {
1040 rd,
1041 rs1,
1042 shamt: ((w >> 20) & 0x3F) as u8,
1043 },
1044 0b0110000 => match rs2_field(w) {
1046 0b00000 => Inst::Clzw { rd, rs1 },
1047 0b00001 => Inst::Ctzw { rd, rs1 },
1048 0b00010 => Inst::Cpopw { rd, rs1 },
1049 _ => Inst::Reserved { raw: w },
1050 },
1051 _ => Inst::Reserved { raw: w },
1052 },
1053 0b101 => match funct7 {
1054 0b0000000 => Inst::Srliw {
1055 rd,
1056 rs1,
1057 shamt: shamt5,
1058 },
1059 0b0100000 => Inst::Sraiw {
1060 rd,
1061 rs1,
1062 shamt: shamt5,
1063 },
1064 0b0110000 => Inst::Roriw {
1066 rd,
1067 rs1,
1068 shamt: shamt5,
1069 },
1070 _ => Inst::Reserved { raw: w },
1071 },
1072 _ => Inst::Reserved { raw: w },
1073 }
1074}
1075
1076fn decode_op(rd: u8, rs1: u8, rs2: u8, funct3: u8, funct7: u8, w: u32) -> Inst {
1077 match (funct7, funct3) {
1078 (0b0000000, 0b000) => Inst::Add { rd, rs1, rs2 },
1080 (0b0100000, 0b000) => Inst::Sub { rd, rs1, rs2 },
1081 (0b0000000, 0b001) => Inst::Sll { rd, rs1, rs2 },
1082 (0b0000000, 0b010) => Inst::Slt { rd, rs1, rs2 },
1083 (0b0000000, 0b011) => Inst::Sltu { rd, rs1, rs2 },
1084 (0b0000000, 0b100) => Inst::Xor { rd, rs1, rs2 },
1085 (0b0000000, 0b101) => Inst::Srl { rd, rs1, rs2 },
1086 (0b0100000, 0b101) => Inst::Sra { rd, rs1, rs2 },
1087 (0b0000000, 0b110) => Inst::Or { rd, rs1, rs2 },
1088 (0b0000000, 0b111) => Inst::And { rd, rs1, rs2 },
1089 (0b0000001, 0b000) => Inst::Mul { rd, rs1, rs2 },
1091 (0b0000001, 0b001) => Inst::Mulh { rd, rs1, rs2 },
1092 (0b0000001, 0b010) => Inst::Mulhsu { rd, rs1, rs2 },
1093 (0b0000001, 0b011) => Inst::Mulhu { rd, rs1, rs2 },
1094 (0b0000001, 0b100) => Inst::Div { rd, rs1, rs2 },
1095 (0b0000001, 0b101) => Inst::Divu { rd, rs1, rs2 },
1096 (0b0000001, 0b110) => Inst::Rem { rd, rs1, rs2 },
1097 (0b0000001, 0b111) => Inst::Remu { rd, rs1, rs2 },
1098 (0b0100000, 0b111) => Inst::Andn { rd, rs1, rs2 },
1100 (0b0100000, 0b110) => Inst::Orn { rd, rs1, rs2 },
1101 (0b0100000, 0b100) => Inst::Xnor { rd, rs1, rs2 },
1102 (0b0000101, 0b100) => Inst::Min { rd, rs1, rs2 },
1103 (0b0000101, 0b101) => Inst::Minu { rd, rs1, rs2 },
1104 (0b0000101, 0b110) => Inst::Max { rd, rs1, rs2 },
1105 (0b0000101, 0b111) => Inst::Maxu { rd, rs1, rs2 },
1106 (0b0110000, 0b001) => Inst::Rol { rd, rs1, rs2 },
1107 (0b0110000, 0b101) => Inst::Ror { rd, rs1, rs2 },
1108 (0b0010000, 0b010) => Inst::Sh1add { rd, rs1, rs2 },
1110 (0b0010000, 0b100) => Inst::Sh2add { rd, rs1, rs2 },
1111 (0b0010000, 0b110) => Inst::Sh3add { rd, rs1, rs2 },
1112 (0b0100100, 0b001) => Inst::Bclr { rd, rs1, rs2 },
1114 (0b0010100, 0b001) => Inst::Bset { rd, rs1, rs2 },
1115 (0b0110100, 0b001) => Inst::Binv { rd, rs1, rs2 },
1116 (0b0100100, 0b101) => Inst::Bext { rd, rs1, rs2 },
1117 (0b0000111, 0b101) => Inst::CzeroEqz { rd, rs1, rs2 },
1119 (0b0000111, 0b111) => Inst::CzeroNez { rd, rs1, rs2 },
1120 (0b0000100, 0b100) if rs2 == 0 => Inst::ZextH { rd, rs1 },
1122 _ => Inst::Reserved { raw: w },
1123 }
1124}
1125
1126fn decode_op_32(rd: u8, rs1: u8, rs2: u8, funct3: u8, funct7: u8, w: u32) -> Inst {
1127 match (funct7, funct3) {
1128 (0b0000000, 0b000) => Inst::Addw { rd, rs1, rs2 },
1129 (0b0100000, 0b000) => Inst::Subw { rd, rs1, rs2 },
1130 (0b0000000, 0b001) => Inst::Sllw { rd, rs1, rs2 },
1131 (0b0000000, 0b101) => Inst::Srlw { rd, rs1, rs2 },
1132 (0b0100000, 0b101) => Inst::Sraw { rd, rs1, rs2 },
1133 (0b0000001, 0b000) => Inst::Mulw { rd, rs1, rs2 },
1135 (0b0000001, 0b100) => Inst::Divw { rd, rs1, rs2 },
1136 (0b0000001, 0b101) => Inst::Divuw { rd, rs1, rs2 },
1137 (0b0000001, 0b110) => Inst::Remw { rd, rs1, rs2 },
1138 (0b0000001, 0b111) => Inst::Remuw { rd, rs1, rs2 },
1139 (0b0110000, 0b001) => Inst::Rolw { rd, rs1, rs2 },
1141 (0b0110000, 0b101) => Inst::Rorw { rd, rs1, rs2 },
1142 (0b0000100, 0b000) => Inst::Adduw { rd, rs1, rs2 },
1144 (0b0010000, 0b010) => Inst::Sh1adduw { rd, rs1, rs2 },
1145 (0b0010000, 0b100) => Inst::Sh2adduw { rd, rs1, rs2 },
1146 (0b0010000, 0b110) => Inst::Sh3adduw { rd, rs1, rs2 },
1147 _ => Inst::Reserved { raw: w },
1148 }
1149}
1150
1151fn decode_branch(rs1: u8, rs2: u8, funct3: u8, imm: i32, w: u32) -> Inst {
1152 match funct3 {
1153 0b000 => Inst::Beq { rs1, rs2, imm },
1154 0b001 => Inst::Bne { rs1, rs2, imm },
1155 0b100 => Inst::Blt { rs1, rs2, imm },
1156 0b101 => Inst::Bge { rs1, rs2, imm },
1157 0b110 => Inst::Bltu { rs1, rs2, imm },
1158 0b111 => Inst::Bgeu { rs1, rs2, imm },
1159 _ => Inst::Reserved { raw: w },
1160 }
1161}
1162
1163fn decode_misc_mem(funct3: u8) -> Inst {
1164 match funct3 {
1165 0b000 => Inst::Fence,
1166 0b001 => Inst::FenceI,
1167 _ => Inst::Reserved { raw: 0 },
1168 }
1169}
1170
1171fn decode_custom_0(w: u32, _rd: u8, _rs1: u8, funct3: u8) -> Inst {
1172 match funct3 {
1179 0b000 => Inst::Trap,
1180 0b001 => Inst::EcallJar,
1181 0b010 => Inst::Ecalli { imm: imm_i(w) },
1182 0b100 => Inst::Fallthrough,
1183 _ => Inst::Reserved { raw: w },
1184 }
1185}
1186
1187fn imm_i(w: u32) -> i32 {
1192 (w as i32) >> 20
1194}
1195
1196fn imm_s(w: u32) -> i32 {
1197 let hi = (w >> 25) & 0x7F;
1198 let lo = (w >> 7) & 0x1F;
1199 let raw = ((hi << 5) | lo) as i32;
1200 (raw << 20) >> 20
1202}
1203
1204fn imm_b(w: u32) -> i32 {
1205 let b12 = (w >> 31) & 1;
1206 let b11 = (w >> 7) & 1;
1207 let b10_5 = (w >> 25) & 0x3F;
1208 let b4_1 = (w >> 8) & 0xF;
1209 let raw = (b12 << 12) | (b11 << 11) | (b10_5 << 5) | (b4_1 << 1);
1210 ((raw as i32) << 19) >> 19
1212}
1213
1214fn imm_j(w: u32) -> i32 {
1215 let b20 = (w >> 31) & 1;
1216 let b10_1 = (w >> 21) & 0x3FF;
1217 let b11 = (w >> 20) & 1;
1218 let b19_12 = (w >> 12) & 0xFF;
1219 let raw = (b20 << 20) | (b19_12 << 12) | (b11 << 11) | (b10_1 << 1);
1220 ((raw as i32) << 11) >> 11
1222}
1223
1224fn rs2_field(w: u32) -> u32 {
1225 (w >> 20) & 0x1F
1226}
1227
1228fn decompress(h: u16) -> Inst {
1238 let op = h & 0b11;
1239 let f3 = (h >> 13) & 0b111;
1240 match op {
1241 0b00 => decompress_q0(h, f3),
1242 0b01 => decompress_q1(h, f3),
1243 0b10 => decompress_q2(h, f3),
1244 _ => Inst::Reserved { raw: h as u32 }, }
1246}
1247
1248fn creg(r: u16) -> u8 {
1250 (r + 8) as u8
1251}
1252
1253fn decompress_q0(h: u16, f3: u16) -> Inst {
1254 let rs1c = creg((h >> 7) & 0b111);
1255 let rdrs2c = creg((h >> 2) & 0b111);
1256 match f3 {
1257 0b000 => {
1258 let imm = ((((h >> 7) & 0x30) << 2) | (((h >> 5) & 0x3) << 6) | (((h >> 11) & 0x3) << 4) | (((h >> 2) & 0x1) << 3)) & 0x3FF;
1264 let n = (((h >> 11) & 0x3) << 4) | (((h >> 7) & 0xF) << 6) | (((h >> 6) & 0x1) << 2) | (((h >> 5) & 0x1) << 3); let _ = imm; if n == 0 {
1273 Inst::Reserved { raw: h as u32 } } else {
1275 Inst::Addi {
1276 rd: rdrs2c,
1277 rs1: 2,
1278 imm: n as i32,
1279 }
1280 }
1281 }
1282 0b010 => {
1283 let imm = (((h >> 10) & 0x7) << 3) | (((h >> 6) & 0x1) << 2) | (((h >> 5) & 0x1) << 6); Inst::Lw {
1288 rd: rdrs2c,
1289 rs1: rs1c,
1290 imm: imm as i32,
1291 }
1292 }
1293 0b011 => {
1294 let imm = (((h >> 10) & 0x7) << 3) | (((h >> 5) & 0x3) << 6); Inst::Ld {
1298 rd: rdrs2c,
1299 rs1: rs1c,
1300 imm: imm as i32,
1301 }
1302 }
1303 0b110 => {
1304 let imm = (((h >> 10) & 0x7) << 3) | (((h >> 6) & 0x1) << 2) | (((h >> 5) & 0x1) << 6);
1306 Inst::Sw {
1307 rs1: rs1c,
1308 rs2: rdrs2c,
1309 imm: imm as i32,
1310 }
1311 }
1312 0b111 => {
1313 let imm = (((h >> 10) & 0x7) << 3) | (((h >> 5) & 0x3) << 6);
1315 Inst::Sd {
1316 rs1: rs1c,
1317 rs2: rdrs2c,
1318 imm: imm as i32,
1319 }
1320 }
1321 _ => Inst::Reserved { raw: h as u32 },
1322 }
1323}
1324
1325fn decompress_q1(h: u16, f3: u16) -> Inst {
1326 match f3 {
1327 0b000 => {
1328 let rd = ((h >> 7) & 0x1F) as u8;
1330 let imm = decode_ci_imm6(h);
1331 if rd == 0 {
1332 Inst::Addi {
1334 rd: 0,
1335 rs1: 0,
1336 imm: 0,
1337 }
1338 } else {
1339 Inst::Addi { rd, rs1: rd, imm }
1340 }
1341 }
1342 0b001 => {
1343 let rd = ((h >> 7) & 0x1F) as u8;
1345 if rd == 0 {
1346 return Inst::Reserved { raw: h as u32 };
1347 }
1348 let imm = decode_ci_imm6(h);
1349 Inst::Addiw { rd, rs1: rd, imm }
1350 }
1351 0b010 => {
1352 let rd = ((h >> 7) & 0x1F) as u8;
1354 if rd == 0 {
1355 return Inst::Reserved { raw: h as u32 };
1356 }
1357 let imm = decode_ci_imm6(h);
1358 Inst::Addi { rd, rs1: 0, imm }
1359 }
1360 0b011 => {
1361 let rd = ((h >> 7) & 0x1F) as u8;
1363 if rd == 2 {
1364 let imm = (((h >> 12) & 1) << 9)
1366 | (((h >> 6) & 1) << 4)
1367 | (((h >> 5) & 1) << 6)
1368 | (((h >> 3) & 0x3) << 7)
1369 | (((h >> 2) & 1) << 5);
1370 let sx = ((imm as i32) << 22) >> 22; if sx == 0 {
1372 return Inst::Reserved { raw: h as u32 };
1373 }
1374 Inst::Addi {
1375 rd: 2,
1376 rs1: 2,
1377 imm: sx,
1378 }
1379 } else if rd == 0 {
1380 Inst::Reserved { raw: h as u32 }
1381 } else {
1382 let h = h as u32;
1384 let imm = (((h >> 12) & 1) << 17) | (((h >> 2) & 0x1F) << 12);
1385 let sx = ((imm as i32) << 14) >> 14; if sx == 0 {
1387 return Inst::Reserved { raw: (h & 0xFFFF) };
1388 }
1389 Inst::Lui { rd, imm: sx }
1390 }
1391 }
1392 0b100 => decompress_q1_misc_alu(h),
1393 0b101 => {
1394 let imm = decode_cj_imm(h);
1396 Inst::Jal { rd: 0, imm }
1397 }
1398 0b110 | 0b111 => {
1399 let rs1 = creg((h >> 7) & 0b111);
1401 let imm = decode_cb_imm(h);
1402 if f3 == 0b110 {
1403 Inst::Beq { rs1, rs2: 0, imm }
1404 } else {
1405 Inst::Bne { rs1, rs2: 0, imm }
1406 }
1407 }
1408 _ => Inst::Reserved { raw: h as u32 },
1409 }
1410}
1411
1412fn decompress_q1_misc_alu(h: u16) -> Inst {
1413 let f6_10 = (h >> 10) & 0b11; let rdrs1c = creg((h >> 7) & 0b111);
1415 match f6_10 {
1416 0b00 | 0b01 => {
1417 let shamt = ((((h >> 12) & 1) << 5) | ((h >> 2) & 0x1F)) as u8;
1419 if f6_10 == 0b00 {
1420 Inst::Srli {
1421 rd: rdrs1c,
1422 rs1: rdrs1c,
1423 shamt,
1424 }
1425 } else {
1426 Inst::Srai {
1427 rd: rdrs1c,
1428 rs1: rdrs1c,
1429 shamt,
1430 }
1431 }
1432 }
1433 0b10 => {
1434 let imm = decode_ci_imm6(h);
1436 Inst::Andi {
1437 rd: rdrs1c,
1438 rs1: rdrs1c,
1439 imm,
1440 }
1441 }
1442 0b11 => {
1443 let rs2c = creg((h >> 2) & 0b111);
1445 let bit12 = (h >> 12) & 1;
1446 let f2 = (h >> 5) & 0b11;
1447 match (bit12, f2) {
1448 (0, 0b00) => Inst::Sub {
1449 rd: rdrs1c,
1450 rs1: rdrs1c,
1451 rs2: rs2c,
1452 },
1453 (0, 0b01) => Inst::Xor {
1454 rd: rdrs1c,
1455 rs1: rdrs1c,
1456 rs2: rs2c,
1457 },
1458 (0, 0b10) => Inst::Or {
1459 rd: rdrs1c,
1460 rs1: rdrs1c,
1461 rs2: rs2c,
1462 },
1463 (0, 0b11) => Inst::And {
1464 rd: rdrs1c,
1465 rs1: rdrs1c,
1466 rs2: rs2c,
1467 },
1468 (1, 0b00) => Inst::Subw {
1469 rd: rdrs1c,
1470 rs1: rdrs1c,
1471 rs2: rs2c,
1472 },
1473 (1, 0b01) => Inst::Addw {
1474 rd: rdrs1c,
1475 rs1: rdrs1c,
1476 rs2: rs2c,
1477 },
1478 _ => Inst::Reserved { raw: h as u32 },
1479 }
1480 }
1481 _ => Inst::Reserved { raw: h as u32 },
1482 }
1483}
1484
1485fn decompress_q2(h: u16, f3: u16) -> Inst {
1486 let rdrs1 = ((h >> 7) & 0x1F) as u8;
1487 let rs2 = ((h >> 2) & 0x1F) as u8;
1488 match f3 {
1489 0b000 => {
1490 if rdrs1 == 0 {
1492 return Inst::Reserved { raw: h as u32 };
1493 }
1494 let shamt = ((((h >> 12) & 1) << 5) | ((h >> 2) & 0x1F)) as u8;
1495 Inst::Slli {
1496 rd: rdrs1,
1497 rs1: rdrs1,
1498 shamt,
1499 }
1500 }
1501 0b010 => {
1502 if rdrs1 == 0 {
1504 return Inst::Reserved { raw: h as u32 };
1505 }
1506 let imm = (((h >> 12) & 1) << 5) | (((h >> 4) & 0x7) << 2) | (((h >> 2) & 0x3) << 6);
1507 Inst::Lw {
1508 rd: rdrs1,
1509 rs1: 2,
1510 imm: imm as i32,
1511 }
1512 }
1513 0b011 => {
1514 if rdrs1 == 0 {
1516 return Inst::Reserved { raw: h as u32 };
1517 }
1518 let imm = (((h >> 12) & 1) << 5) | (((h >> 5) & 0x3) << 3) | (((h >> 2) & 0x7) << 6);
1519 Inst::Ld {
1520 rd: rdrs1,
1521 rs1: 2,
1522 imm: imm as i32,
1523 }
1524 }
1525 0b100 => {
1526 let bit12 = (h >> 12) & 1;
1532 match (bit12, rdrs1, rs2) {
1533 (0, r, 0) if r != 0 => Inst::Jalr {
1534 rd: 0,
1535 rs1: r,
1536 imm: 0,
1537 }, (0, r, s) if r != 0 && s != 0 => Inst::Add {
1539 rd: r,
1540 rs1: 0,
1541 rs2: s,
1542 }, (1, 0, 0) => Inst::Reserved { raw: h as u32 }, (1, r, 0) if r != 0 => Inst::Jalr {
1545 rd: 1,
1546 rs1: r,
1547 imm: 0,
1548 }, (1, r, s) if r != 0 && s != 0 => Inst::Add {
1550 rd: r,
1551 rs1: r,
1552 rs2: s,
1553 }, _ => Inst::Reserved { raw: h as u32 },
1555 }
1556 }
1557 0b110 => {
1558 let imm = (((h >> 9) & 0xF) << 2) | (((h >> 7) & 0x3) << 6);
1560 Inst::Sw {
1561 rs1: 2,
1562 rs2,
1563 imm: imm as i32,
1564 }
1565 }
1566 0b111 => {
1567 let imm = (((h >> 10) & 0x7) << 3) | (((h >> 7) & 0x7) << 6);
1569 Inst::Sd {
1570 rs1: 2,
1571 rs2,
1572 imm: imm as i32,
1573 }
1574 }
1575 _ => Inst::Reserved { raw: h as u32 },
1576 }
1577}
1578
1579fn decode_ci_imm6(h: u16) -> i32 {
1581 let imm = (((h >> 12) & 1) << 5) | ((h >> 2) & 0x1F);
1582 ((imm as i32) << 26) >> 26
1583}
1584
1585fn decode_cj_imm(h: u16) -> i32 {
1587 let b11 = (h >> 12) & 1;
1588 let b4 = (h >> 11) & 1;
1589 let b9_8 = (h >> 9) & 0x3;
1590 let b10 = (h >> 8) & 1;
1591 let b6 = (h >> 7) & 1;
1592 let b7 = (h >> 6) & 1;
1593 let b3_1 = (h >> 3) & 0x7;
1594 let b5 = (h >> 2) & 1;
1595 let imm = (b11 << 11)
1596 | (b10 << 10)
1597 | (b9_8 << 8)
1598 | (b7 << 7)
1599 | (b6 << 6)
1600 | (b5 << 5)
1601 | (b4 << 4)
1602 | (b3_1 << 1);
1603 ((imm as i32) << 20) >> 20
1604}
1605
1606fn decode_cb_imm(h: u16) -> i32 {
1608 let b8 = (h >> 12) & 1;
1609 let b4_3 = (h >> 10) & 0x3;
1610 let b7_6 = (h >> 5) & 0x3;
1611 let b2_1 = (h >> 3) & 0x3;
1612 let b5 = (h >> 2) & 1;
1613 let imm = (b8 << 8) | (b7_6 << 6) | (b5 << 5) | (b4_3 << 3) | (b2_1 << 1);
1614 ((imm as i32) << 23) >> 23
1615}
1616
1617#[cfg(test)]
1618mod tests {
1619 use super::*;
1620
1621 #[test]
1622 fn decode_add() {
1623 let bytes = 0x00C58533u32.to_le_bytes();
1625 assert_eq!(
1626 decode(&bytes),
1627 Some((
1628 Inst::Add {
1629 rd: 10,
1630 rs1: 11,
1631 rs2: 12,
1632 },
1633 4
1634 ))
1635 );
1636 }
1637
1638 #[test]
1639 fn decode_ld() {
1640 let bytes = 0x01053283u32.to_le_bytes();
1642 assert_eq!(
1643 decode(&bytes),
1644 Some((
1645 Inst::Ld {
1646 rd: 5,
1647 rs1: 10,
1648 imm: 16,
1649 },
1650 4
1651 ))
1652 );
1653 }
1654
1655 #[test]
1656 fn decode_sd() {
1657 let bytes = 0x00B53423u32.to_le_bytes();
1659 assert_eq!(
1660 decode(&bytes),
1661 Some((
1662 Inst::Sd {
1663 rs1: 10,
1664 rs2: 11,
1665 imm: 8,
1666 },
1667 4
1668 ))
1669 );
1670 }
1671
1672 #[test]
1673 fn decode_addi_negative() {
1674 let bytes = 0xFFC58513u32.to_le_bytes();
1676 assert_eq!(
1677 decode(&bytes),
1678 Some((
1679 Inst::Addi {
1680 rd: 10,
1681 rs1: 11,
1682 imm: -4,
1683 },
1684 4
1685 ))
1686 );
1687 }
1688
1689 #[test]
1690 fn decode_beq() {
1691 let bytes = 0x00B50463u32.to_le_bytes();
1693 assert_eq!(
1694 decode(&bytes),
1695 Some((
1696 Inst::Beq {
1697 rs1: 10,
1698 rs2: 11,
1699 imm: 8,
1700 },
1701 4
1702 ))
1703 );
1704 }
1705
1706 #[test]
1707 fn decode_jal() {
1708 let bytes = 0x00C000EFu32.to_le_bytes();
1710 assert_eq!(decode(&bytes), Some((Inst::Jal { rd: 1, imm: 12 }, 4)));
1711 }
1712
1713 #[test]
1714 fn decode_lui() {
1715 let bytes = 0x123452B7u32.to_le_bytes();
1717 assert_eq!(
1718 decode(&bytes),
1719 Some((
1720 Inst::Lui {
1721 rd: 5,
1722 imm: 0x12345000,
1723 },
1724 4
1725 ))
1726 );
1727 }
1728
1729 #[test]
1730 fn decode_auipc_native() {
1731 let bytes = 0x00010297u32.to_le_bytes();
1733 assert_eq!(
1734 decode(&bytes),
1735 Some((
1736 Inst::Auipc {
1737 rd: 5,
1738 imm: 0x0001_0000,
1739 },
1740 4,
1741 ))
1742 );
1743 }
1744
1745 #[test]
1746 fn decode_ecall_reserved() {
1747 let bytes = 0x00000073u32.to_le_bytes();
1749 match decode(&bytes) {
1750 Some((Inst::Reserved { .. }, 4)) => {}
1751 other => panic!("standard ecall should be Reserved, got {:?}", other),
1752 }
1753 }
1754
1755 #[test]
1756 fn decode_c_mv() {
1757 let bytes = 0x852Eu16.to_le_bytes();
1759 assert_eq!(
1761 decode(&bytes),
1762 Some((
1763 Inst::Add {
1764 rd: 10,
1765 rs1: 0,
1766 rs2: 11,
1767 },
1768 2
1769 ))
1770 );
1771 }
1772
1773 #[test]
1774 fn decode_c_addi() {
1775 let bytes = 0x0505u16.to_le_bytes();
1777 assert_eq!(
1778 decode(&bytes),
1779 Some((
1780 Inst::Addi {
1781 rd: 10,
1782 rs1: 10,
1783 imm: 1,
1784 },
1785 2
1786 ))
1787 );
1788 }
1789
1790 #[test]
1791 fn decode_c_li() {
1792 let bytes = 0x557Du16.to_le_bytes();
1794 assert_eq!(
1795 decode(&bytes),
1796 Some((
1797 Inst::Addi {
1798 rd: 10,
1799 rs1: 0,
1800 imm: -1,
1801 },
1802 2
1803 ))
1804 );
1805 }
1806
1807 #[test]
1808 fn decode_c_j() {
1809 let bytes = 0xA011u16.to_le_bytes();
1811 assert_eq!(decode(&bytes), Some((Inst::Jal { rd: 0, imm: 4 }, 2)));
1812 }
1813
1814 #[test]
1815 fn decode_custom_trap() {
1816 let bytes = 0x0000000Bu32.to_le_bytes();
1818 assert_eq!(decode(&bytes), Some((Inst::Trap, 4)));
1819 }
1820
1821 #[test]
1822 fn decode_custom_ecall_jar() {
1823 let bytes = 0x0000100Bu32.to_le_bytes();
1825 assert_eq!(decode(&bytes), Some((Inst::EcallJar, 4)));
1826 }
1827
1828 #[test]
1829 fn decode_custom_ecalli() {
1830 let w = (5u32 << 20) | (0b010 << 12) | 0x0B;
1833 let bytes = w.to_le_bytes();
1834 assert_eq!(decode(&bytes), Some((Inst::Ecalli { imm: 5 }, 4)));
1835 }
1836
1837 #[test]
1838 fn decode_custom_ecalli_negative() {
1839 let w = (0xFFFu32 << 20) | (0b010 << 12) | 0x0B;
1841 let bytes = w.to_le_bytes();
1842 assert_eq!(decode(&bytes), Some((Inst::Ecalli { imm: -1 }, 4)));
1843 }
1844
1845 #[test]
1846 fn decode_custom0_funct3_011_reserved() {
1847 let w = (42u32 << 20) | (1u32 << 15) | (0b011u32 << 12) | (0b00010u32 << 2) | 0b11;
1850 let bytes = w.to_le_bytes();
1851 assert!(matches!(decode(&bytes).unwrap().0, Inst::Reserved { .. }));
1852 }
1853
1854 #[test]
1855 fn decode_auipc() {
1856 let w = (0x12345u32 << 12) | (5 << 7) | 0b001_0111;
1858 let bytes = w.to_le_bytes();
1859 assert_eq!(
1860 decode(&bytes),
1861 Some((
1862 Inst::Auipc {
1863 rd: 5,
1864 imm: 0x1234_5000,
1865 },
1866 4,
1867 ))
1868 );
1869 }
1870
1871 #[test]
1872 fn decode_jalr() {
1873 let w = (16u32 << 20) | (6 << 15) | (1 << 7) | 0b110_0111;
1875 let bytes = w.to_le_bytes();
1876 assert_eq!(
1877 decode(&bytes),
1878 Some((
1879 Inst::Jalr {
1880 rd: 1,
1881 rs1: 6,
1882 imm: 16,
1883 },
1884 4,
1885 ))
1886 );
1887 }
1888
1889 #[test]
1890 fn decode_custom1_callf_now_reserved() {
1891 let callf_word = 0x0080_002Bu32;
1894 let bytes = callf_word.to_le_bytes();
1895 let decoded = decode(&bytes).unwrap().0;
1896 assert!(matches!(decoded, Inst::Reserved { .. }));
1897 }
1898
1899 #[test]
1900 fn decompress_c_jr_ra_is_jalr() {
1901 let bytes = 0x8082u16.to_le_bytes();
1905 assert_eq!(
1906 decode(&bytes),
1907 Some((
1908 Inst::Jalr {
1909 rd: 0,
1910 rs1: 1,
1911 imm: 0
1912 },
1913 2
1914 ))
1915 );
1916 }
1917
1918 #[test]
1919 fn decompress_c_jalr_ra_is_jalr_link() {
1920 assert_eq!(
1924 decode(&0x9082u16.to_le_bytes()),
1925 Some((
1926 Inst::Jalr {
1927 rd: 1,
1928 rs1: 1,
1929 imm: 0
1930 },
1931 2
1932 ))
1933 );
1934 assert!(matches!(
1935 decode(&0x9002u16.to_le_bytes()).unwrap().0,
1936 Inst::Reserved { .. }
1937 ));
1938 }
1939
1940 #[test]
1943 fn x3_x4_decode_as_live_spilled_registers() {
1944 let add_x3 = 0x0061_82B3u32; assert!(matches!(
1949 decode(&add_x3.to_le_bytes()).unwrap().0,
1950 Inst::Add {
1951 rd: 5,
1952 rs1: 3,
1953 rs2: 6
1954 }
1955 ));
1956 assert!(!word_uses_reserved_reg(add_x3));
1957 assert!(word_uses_spilled_reg(add_x3));
1958
1959 let addi_x3 = 0x0010_0193u32;
1961 assert!(matches!(
1962 decode(&addi_x3.to_le_bytes()).unwrap().0,
1963 Inst::Addi {
1964 rd: 3,
1965 rs1: 0,
1966 imm: 1
1967 }
1968 ));
1969 assert!(!word_uses_reserved_reg(addi_x3));
1970 assert!(word_uses_spilled_reg(addi_x3));
1971
1972 let add_x16 = 0x0062_8833u32; assert!(matches!(
1977 decode(&add_x16.to_le_bytes()).unwrap().0,
1978 Inst::Reserved { .. }
1979 ));
1980 assert!(word_uses_reserved_reg(add_x16));
1981 assert!(!word_uses_spilled_reg(add_x16));
1982 }
1983
1984 #[test]
1985 fn x3_x4_free_instruction_is_unaffected() {
1986 let add_ok = 0x0073_02B3u32;
1989 assert!(matches!(
1990 decode(&add_ok.to_le_bytes()).unwrap().0,
1991 Inst::Add { .. }
1992 ));
1993 assert!(!word_uses_reserved_reg(add_ok));
1994 assert!(!word_uses_spilled_reg(add_ok));
1995 }
1996
1997 #[test]
1998 fn immediate_bits_aliasing_x3_are_not_a_register() {
1999 let lui = 0x0001_82B7u32;
2003 assert!(matches!(
2004 decode(&lui.to_le_bytes()).unwrap().0,
2005 Inst::Lui { rd: 5, .. }
2006 ));
2007 assert!(!word_uses_reserved_reg(lui));
2008 assert!(!word_uses_spilled_reg(lui));
2009 }
2010
2011 #[test]
2012 fn word_predicate_matches_inst_predicate() {
2013 for major in 0u32..0x20 {
2023 let opcode7 = (major << 2) | 0b11; for &rd in &[0u32, 3, 4, 5, 16, 31] {
2025 for &rs1 in &[0u32, 3, 4, 5, 16, 31] {
2026 for &rs2 in &[0u32, 3, 4, 5, 16, 31] {
2027 for funct3 in 0u32..8 {
2028 for &funct7 in &[0u32, 0b000_0001, 0b010_0000, 0b000_0111] {
2029 let w = (funct7 << 25)
2030 | (rs2 << 20)
2031 | (rs1 << 15)
2032 | (funct3 << 12)
2033 | (rd << 7)
2034 | opcode7;
2035 let inst = decode_32(w);
2036 if !matches!(inst, Inst::Reserved { .. }) {
2037 assert_eq!(
2038 word_uses_reserved_reg(w),
2039 inst.uses_reserved_reg(),
2040 "word {w:#010x} -> {inst:?}"
2041 );
2042 }
2043 }
2044 }
2045 }
2046 }
2047 }
2048 }
2049 }
2050}