1use std::borrow::Cow;
8use std::fmt;
9use std::fmt::Debug;
10use std::marker::PhantomData;
11use std::mem;
12
13use byteorder::{ByteOrder, LittleEndian};
14
15#[derive(Copy, Clone, Debug, Eq, PartialEq)]
16pub enum Error {
17 TooShort,
18 UnhandledLength,
19 Unaligned,
20 InvalidOpcode,
21 InvalidSubop,
22 BadRegister,
23}
24
25pub type DisResult<T> = Result<T, Error>;
26
27#[derive(Copy, Clone, Debug)]
28pub enum Op<D: RiscVDisassembler> {
29 Load(LoadTypeInst<D>),
35
36 Fence(ITypeIntInst<D>),
38 FenceI(ITypeIntInst<D>),
39
40 AddI(ITypeIntInst<D>),
42 SltI(ITypeIntInst<D>),
43 SltIU(ITypeIntInst<D>),
44 XorI(ITypeIntInst<D>),
45 OrI(ITypeIntInst<D>),
46 AndI(ITypeIntInst<D>),
47 SllI(ITypeIntInst<D>),
48 SrlI(ITypeIntInst<D>),
49 SraI(ITypeIntInst<D>),
50
51 Auipc(UTypeInst<D>),
53
54 Store(StoreTypeInst<D>),
56
57 Add(RTypeIntInst<D>),
59 Sll(RTypeIntInst<D>),
60 Slt(RTypeIntInst<D>),
61 SltU(RTypeIntInst<D>),
62 Xor(RTypeIntInst<D>),
63 Srl(RTypeIntInst<D>),
64 Or(RTypeIntInst<D>),
65 And(RTypeIntInst<D>),
66 Sub(RTypeIntInst<D>),
67 Sra(RTypeIntInst<D>),
68
69 Lui(UTypeInst<D>),
71
72 Beq(BTypeInst<D>),
74 Bne(BTypeInst<D>),
75 Blt(BTypeInst<D>),
76 Bge(BTypeInst<D>),
77 BltU(BTypeInst<D>),
78 BgeU(BTypeInst<D>),
79
80 Jalr(ITypeIntInst<D>),
82
83 Jal(JTypeInst<D>),
85
86 Ecall,
88 Ebreak,
89 Csrrw(CsrTypeInst<D>),
90 Csrrs(CsrTypeInst<D>),
91 Csrrc(CsrTypeInst<D>),
92 CsrrwI(CsrITypeInst<D>),
93 CsrrsI(CsrITypeInst<D>),
94 CsrrcI(CsrITypeInst<D>),
95
96 Uret,
97 Sret,
98 Mret,
99 Wfi,
100 SfenceVm(RTypeIntInst<D>),
101 SfenceVma(RTypeIntInst<D>),
102
103 AddIW(ITypeIntInst<D>),
109 SllIW(ITypeIntInst<D>),
110 SrlIW(ITypeIntInst<D>),
111 SraIW(ITypeIntInst<D>),
112
113 AddW(RTypeIntInst<D>),
115 SllW(RTypeIntInst<D>),
116 SrlW(RTypeIntInst<D>),
117 SubW(RTypeIntInst<D>),
118 SraW(RTypeIntInst<D>),
119
120 Mul(RTypeIntInst<D>),
126 MulH(RTypeIntInst<D>),
127 MulHSU(RTypeIntInst<D>),
128 MulHU(RTypeIntInst<D>),
129 Div(RTypeIntInst<D>),
130 DivU(RTypeIntInst<D>),
131 Rem(RTypeIntInst<D>),
132 RemU(RTypeIntInst<D>),
133
134 MulW(RTypeIntInst<D>),
140 DivW(RTypeIntInst<D>),
141 DivUW(RTypeIntInst<D>),
142 RemW(RTypeIntInst<D>),
143 RemUW(RTypeIntInst<D>),
144
145 Lr(AtomicInst<D>),
151 Sc(AtomicInst<D>),
152 AmoSwap(AtomicInst<D>),
153 AmoAdd(AtomicInst<D>),
154 AmoXor(AtomicInst<D>),
155 AmoAnd(AtomicInst<D>),
156 AmoOr(AtomicInst<D>),
157 AmoMin(AtomicInst<D>),
158 AmoMax(AtomicInst<D>),
159 AmoMinU(AtomicInst<D>),
160 AmoMaxU(AtomicInst<D>),
161
162 LoadFp(FpMemInst<D>),
166 StoreFp(FpMemInst<D>),
167 Fmadd(FpMAddInst<D>),
168 Fmsub(FpMAddInst<D>),
169 Fnmsub(FpMAddInst<D>),
170 Fnmadd(FpMAddInst<D>),
171 Fadd(RTypeFloatRoundInst<D>),
172 Fsub(RTypeFloatRoundInst<D>),
173 Fmul(RTypeFloatRoundInst<D>),
174 Fdiv(RTypeFloatRoundInst<D>),
175 Fsqrt(RTypeFloatRoundInst<D>),
176 Fsgnj(RTypeFloatInst<D>),
177 Fsgnjn(RTypeFloatInst<D>),
178 Fsgnjx(RTypeFloatInst<D>),
179 Fmin(RTypeFloatInst<D>),
180 Fmax(RTypeFloatInst<D>),
181 Fle(RTypeFloatCmpInst<D>),
182 Flt(RTypeFloatCmpInst<D>),
183 Feq(RTypeFloatCmpInst<D>),
184 Fcvt(FpCvtInst<D>),
185 FcvtToInt(FpCvtToIntInst<D>),
186 FcvtFromInt(FpCvtFromIntInst<D>),
187 FmvToInt(FpMvToIntInst<D>),
188 FmvFromInt(FpMvFromIntInst<D>),
189 Fclass(FpClassInst<D>),
190}
191
192pub trait Register {
193 fn new(id: u32) -> Self;
194
195 fn id(&self) -> u32;
196 fn valid(&self) -> bool;
197}
198
199#[derive(Copy, Clone, Debug, PartialEq, Eq)]
200pub enum RoundMode {
201 RoundNearestEven,
202 RoundTowardZero,
203 RoundDown,
204 RoundUp,
205 RoundMaxMagnitude,
206 Dynamic,
207}
208
209#[derive(Copy, Clone, Debug, Eq, PartialEq)]
210pub struct IntReg<D: RiscVDisassembler> {
211 reg_id: u8,
212 _dis: PhantomData<D>,
213}
214
215impl<D: RiscVDisassembler> Register for IntReg<D> {
216 #[inline(always)]
217 fn new(id: u32) -> Self {
218 let ret = Self {
219 reg_id: id as u8,
220 _dis: PhantomData,
221 };
222
223 debug_assert!(ret.valid());
224
225 ret
226 }
227
228 #[inline(always)]
229 fn id(&self) -> u32 {
230 self.reg_id as u32
231 }
232
233 #[inline(always)]
234 fn valid(&self) -> bool {
235 (self.reg_id as u32) < <D::RegFile as RegFile>::int_reg_count()
236 }
237}
238
239#[derive(Copy, Clone, Debug, Eq, PartialEq)]
240pub struct FloatReg<D: RiscVDisassembler> {
241 reg_id: u8,
242 _dis: PhantomData<D>,
243}
244
245impl<D: RiscVDisassembler> Register for FloatReg<D> {
246 #[inline(always)]
247 fn new(id: u32) -> Self {
248 let ret = Self {
249 reg_id: id as u8,
250 _dis: PhantomData,
251 };
252
253 debug_assert!(ret.valid());
254
255 ret
256 }
257
258 #[inline(always)]
259 fn id(&self) -> u32 {
260 self.reg_id as u32
261 }
262
263 #[inline(always)]
264 fn valid(&self) -> bool {
265 (self.reg_id as u32) < <D::RegFile as RegFile>::int_reg_count()
266 }
267}
268
269pub trait IntRegType: Sized {
270 #[inline(always)]
271 fn width() -> usize {
272 mem::size_of::<Self>()
273 }
274}
275
276pub trait FloatRegType: Sized {
277 #[inline(always)]
278 fn width() -> usize {
279 mem::size_of::<Self>()
280 }
281
282 #[inline(always)]
283 fn present() -> bool {
284 mem::size_of::<Self>() != 0
285 }
286}
287
288impl IntRegType for u32 {}
289impl IntRegType for u64 {}
290impl FloatRegType for () {}
291impl FloatRegType for f32 {}
292impl FloatRegType for f64 {}
293
294pub trait RegFile: Debug + Sized + Copy + Clone + Send + Sync + 'static {
295 type Int: IntRegType;
296 type Float: FloatRegType;
297
298 #[inline(always)]
299 fn int_reg_count() -> u32 {
300 32
301 }
302}
303
304#[derive(Copy, Clone, Debug)]
305pub struct Rv32IRegs;
306impl RegFile for Rv32IRegs {
307 type Int = u32;
308 type Float = ();
309}
310
311#[derive(Copy, Clone, Debug)]
312pub struct Rv32ERegs;
313impl RegFile for Rv32ERegs {
314 type Int = u32;
315 type Float = ();
316
317 #[inline(always)]
318 fn int_reg_count() -> u32 {
319 16
320 }
321}
322
323#[derive(Copy, Clone, Debug)]
324pub struct Rv32GRegs;
325impl RegFile for Rv32GRegs {
326 type Int = u32;
327 type Float = f64;
328}
329
330#[derive(Copy, Clone, Debug)]
331pub struct Rv64GRegs;
332impl RegFile for Rv64GRegs {
333 type Int = u64;
334 type Float = f64;
335}
336
337pub enum Operand<D: RiscVDisassembler> {
338 R(IntReg<D>),
339 F(FloatReg<D>),
340 I(i32),
341 M(i32, IntReg<D>), RM(RoundMode),
343}
344
345impl<D: RiscVDisassembler> fmt::Display for Operand<D> {
346 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
347 match *self {
348 Operand::R(r) => write!(f, "x{}", r.id()),
349 Operand::F(r) => write!(f, "f{}", r.id()),
350 Operand::I(i) => match i {
351 -0x80000..=-1 => write!(f, "-{:x}", -i),
352 _ => write!(f, "{:x}", i),
353 },
354 Operand::M(i, r) => {
355 if i < 0 {
356 write!(f, "-{:x}(x{})", -i, r.id())
357 } else {
358 write!(f, "{:x}(x{})", i, r.id())
359 }
360 }
361 Operand::RM(r) => write!(f, "{}", r.name()),
362 }
363 }
364}
365
366#[derive(Copy, Clone, Debug)]
367struct Instr32(u32);
368impl Instr32 {
369 #[inline(always)]
370 fn extract_bits(self, start_bit: u32, width: u32) -> u32 {
371 self.0.wrapping_shr(start_bit) & 1u32.wrapping_shl(width).wrapping_sub(1)
372 }
373
374 #[inline(always)]
375 fn opcode(self) -> u32 {
376 self.extract_bits(0, 7)
377 }
378
379 #[inline(always)]
380 fn rd(self) -> u32 {
381 self.extract_bits(7, 5)
382 }
383
384 #[inline(always)]
385 fn rs1(self) -> u32 {
386 self.extract_bits(15, 5)
387 }
388
389 #[inline(always)]
390 fn rs2(self) -> u32 {
391 self.extract_bits(20, 5)
392 }
393
394 #[inline(always)]
395 fn rs3(self) -> u32 {
396 self.extract_bits(27, 5)
397 }
398
399 #[inline(always)]
400 fn funct3(self) -> u32 {
401 self.extract_bits(12, 3)
402 }
403
404 #[inline(always)]
405 fn funct7(self) -> u32 {
406 self.extract_bits(25, 7)
407 }
408
409 #[inline(always)]
410 fn rm(self) -> u32 {
411 self.extract_bits(12, 3)
412 }
413
414 #[inline(always)]
415 fn fsize(self) -> u32 {
416 self.extract_bits(25, 2)
417 }
418
419 #[inline(always)]
420 fn fop(self) -> u32 {
421 self.extract_bits(27, 5)
422 }
423
424 #[inline(always)]
425 fn i_imm(self) -> i32 {
426 (self.0 as i32) >> 20
427 }
428
429 #[inline(always)]
430 fn s_imm(self) -> i32 {
431 (((self.0 as i32) >> 20) & !0x1f) | self.extract_bits(7, 5) as i32
432 }
433
434 #[inline(always)]
435 fn b_imm(self) -> i32 {
436 let b_imm = self.s_imm();
437 (b_imm & !0x801) | ((b_imm & 1) << 11)
438 }
439
440 #[inline(always)]
441 fn u_imm(self) -> i32 {
442 (self.0 & !0xfff) as i32
443 }
444
445 #[inline(always)]
446 fn j_imm(self) -> i32 {
447 let mut j_imm = (((self.0 as i32) >> 11) as u32) & 0xfff00000;
448 j_imm |= 0x000ff000 & self.0;
449 j_imm |= self.extract_bits(20, 11);
450 ((j_imm & !0x801) | ((j_imm & 1) << 11)) as i32
451 }
452}
453
454impl RoundMode {
455 fn from_bits(bits: u32) -> DisResult<RoundMode> {
456 match bits {
457 0b000 => Ok(RoundMode::RoundNearestEven),
458 0b001 => Ok(RoundMode::RoundTowardZero),
459 0b010 => Ok(RoundMode::RoundDown),
460 0b011 => Ok(RoundMode::RoundUp),
461 0b100 => Ok(RoundMode::RoundMaxMagnitude),
462 0b111 => Ok(RoundMode::Dynamic),
463 _ => Err(Error::InvalidSubop),
464 }
465 }
466
467 pub fn name(&self) -> &'static str {
468 match self {
469 RoundMode::RoundNearestEven => "rne",
470 RoundMode::RoundTowardZero => "rtz",
471 RoundMode::RoundDown => "rdn",
472 RoundMode::RoundUp => "rup",
473 RoundMode::RoundMaxMagnitude => "rmm",
474 RoundMode::Dynamic => "dyn",
475 }
476 }
477
478 pub fn all() -> &'static [RoundMode] {
479 &[
480 RoundMode::RoundNearestEven,
481 RoundMode::RoundTowardZero,
482 RoundMode::RoundDown,
483 RoundMode::RoundUp,
484 RoundMode::RoundMaxMagnitude,
485 RoundMode::Dynamic,
486 ]
487 }
488}
489
490#[derive(Copy, Clone, Debug)]
491pub struct LoadTypeInst<D: RiscVDisassembler> {
492 width: u8,
493 zx: bool,
494 rd: IntReg<D>,
495 rs1: IntReg<D>,
496 imm: i16,
497 _dis: PhantomData<D>,
498}
499
500impl<D: RiscVDisassembler> LoadTypeInst<D> {
501 #[inline(always)]
502 fn new(width: usize, zx: bool, rd: IntReg<D>, rs1: IntReg<D>, imm: i32) -> DisResult<Self> {
503 if width + zx as usize > <D::RegFile as RegFile>::Int::width() {
504 return Err(Error::InvalidSubop);
505 } else if !rd.valid() || !rs1.valid() {
506 return Err(Error::BadRegister);
507 }
508
509 Ok(Self {
510 width: width as u8,
511 zx,
512 rd,
513 rs1,
514 imm: imm as i16,
515 _dis: PhantomData,
516 })
517 }
518
519 #[inline(always)]
520 fn from_instr32(inst: Instr32) -> DisResult<Self> {
521 let width = 1u32.wrapping_shl(inst.extract_bits(12, 2)) as u8;
522 let zx = inst.extract_bits(14, 1) == 1;
523 let rd = IntReg::new(inst.rd());
524 let rs1 = IntReg::new(inst.rs1());
525
526 if width as usize + zx as usize > <D::RegFile as RegFile>::Int::width() {
527 return Err(Error::InvalidSubop);
528 } else if !rd.valid() || !rs1.valid() {
529 return Err(Error::BadRegister);
530 }
531
532 Ok(Self {
533 width,
534 zx,
535 rd,
536 rs1,
537 imm: inst.i_imm() as i16,
538 _dis: PhantomData,
539 })
540 }
541
542 #[inline(always)]
543 pub fn width(&self) -> usize {
544 self.width as usize
545 }
546
547 #[inline(always)]
548 pub fn zx(&self) -> bool {
549 self.zx
550 }
551
552 #[inline(always)]
553 pub fn rd(&self) -> IntReg<D> {
554 self.rd
555 }
556
557 #[inline(always)]
558 pub fn rs1(&self) -> IntReg<D> {
559 self.rs1
560 }
561
562 #[inline(always)]
563 pub fn imm(&self) -> i32 {
564 self.imm as i32
565 }
566}
567
568#[derive(Copy, Clone, Debug)]
569pub struct StoreTypeInst<D: RiscVDisassembler> {
570 width: u8,
571 rs1: IntReg<D>,
572 rs2: IntReg<D>,
573 imm: i16,
574 _dis: PhantomData<D>,
575}
576
577impl<D: RiscVDisassembler> StoreTypeInst<D> {
578 #[inline(always)]
579 fn new(width: usize, rs2: IntReg<D>, rs1: IntReg<D>, imm: i32) -> DisResult<Self> {
580 if width > <D::RegFile as RegFile>::Int::width() {
581 return Err(Error::InvalidSubop);
582 } else if !rs1.valid() || !rs2.valid() {
583 return Err(Error::BadRegister);
584 }
585
586 Ok(Self {
587 width: width as u8,
588 rs1,
589 rs2,
590 imm: imm as i16,
591 _dis: PhantomData,
592 })
593 }
594
595 #[inline(always)]
596 fn from_instr32(inst: Instr32) -> DisResult<Self> {
597 let width = 1u32.wrapping_shl(inst.extract_bits(12, 3)) as u8;
598 let rs1 = IntReg::new(inst.rs1());
599 let rs2 = IntReg::new(inst.rs2());
600
601 if width as usize > <D::RegFile as RegFile>::Int::width() {
602 return Err(Error::InvalidSubop);
603 } else if !rs1.valid() || !rs2.valid() {
604 return Err(Error::BadRegister);
605 }
606
607 Ok(Self {
608 width,
609 rs1,
610 rs2,
611 imm: inst.s_imm() as i16,
612 _dis: PhantomData,
613 })
614 }
615
616 #[inline(always)]
617 pub fn width(&self) -> usize {
618 self.width as usize
619 }
620
621 #[inline(always)]
622 pub fn rs1(&self) -> IntReg<D> {
623 self.rs1
624 }
625
626 #[inline(always)]
627 pub fn rs2(&self) -> IntReg<D> {
628 self.rs2
629 }
630
631 #[inline(always)]
632 pub fn imm(&self) -> i32 {
633 self.imm as i32
634 }
635}
636
637#[derive(Copy, Clone, Debug)]
638pub struct ITypeInst<Rd, Rs1>
639where
640 Rd: Register,
641 Rs1: Register,
642{
643 inst: Instr32,
644 _rd: PhantomData<Rd>,
645 _rs1: PhantomData<Rs1>,
646}
647
648pub type ITypeIntInst<D> = ITypeInst<IntReg<D>, IntReg<D>>;
649
650impl<Rd, Rs1> ITypeInst<Rd, Rs1>
651where
652 Rd: Register,
653 Rs1: Register,
654{
655 #[inline(always)]
656 fn new(inst: Instr32) -> DisResult<Self> {
657 let ret = Self {
658 inst,
659 _rd: PhantomData,
660 _rs1: PhantomData,
661 };
662
663 if !ret.rd().valid() || !ret.rs1().valid() {
664 return Err(Error::BadRegister);
665 }
666
667 Ok(ret)
668 }
669
670 #[inline(always)]
671 fn from_ops(rd: Rd, rs1: Rs1, imm: i32) -> Self {
672 let imm = imm as u32;
673 let raw: u32 = (imm << 20) | (rd.id() << 7) | (rs1.id() << 15);
674
675 Self {
676 inst: Instr32(raw),
677 _rd: PhantomData,
678 _rs1: PhantomData,
679 }
680 }
681
682 #[inline(always)]
683 pub fn rd(&self) -> Rd {
684 Rd::new(self.inst.rd())
685 }
686
687 #[inline(always)]
688 pub fn rs1(&self) -> Rs1 {
689 Rs1::new(self.inst.rs1())
690 }
691
692 #[inline(always)]
693 pub fn imm(&self) -> i32 {
694 self.inst.i_imm()
695 }
696}
697
698#[derive(Copy, Clone, Debug)]
699pub struct CsrITypeInst<D: RiscVDisassembler> {
700 inst: Instr32,
701 _dis: PhantomData<D>,
702}
703
704impl<D: RiscVDisassembler> CsrITypeInst<D> {
705 #[inline(always)]
706 fn new(inst: Instr32) -> DisResult<Self> {
707 let ret = Self {
708 inst,
709 _dis: PhantomData,
710 };
711
712 if !ret.rd().valid() {
713 return Err(Error::BadRegister);
714 }
715
716 Ok(ret)
717 }
718
719 #[inline(always)]
720 pub fn rd(&self) -> IntReg<D> {
721 IntReg::new(self.inst.rd())
722 }
723
724 #[inline(always)]
725 pub fn imm(&self) -> u32 {
726 self.inst.rs1()
727 }
728
729 #[inline(always)]
730 pub fn csr(&self) -> u32 {
731 self.inst.i_imm() as u32 & 0xfff
732 }
733}
734
735#[derive(Copy, Clone, Debug)]
736pub struct CsrTypeInst<D: RiscVDisassembler> {
737 inst: Instr32,
738 _dis: PhantomData<D>,
739 _rs1: PhantomData<IntReg<D>>,
740}
741
742impl<D: RiscVDisassembler> CsrTypeInst<D> {
743 #[inline(always)]
744 fn new(inst: Instr32) -> DisResult<Self> {
745 let ret = Self {
746 inst,
747 _dis: PhantomData,
748 _rs1: PhantomData,
749 };
750
751 if !ret.rd().valid() || !ret.rs1().valid() {
752 return Err(Error::BadRegister);
753 }
754
755 Ok(ret)
756 }
757
758 #[inline(always)]
759 pub fn rd(&self) -> IntReg<D> {
760 IntReg::new(self.inst.rd())
761 }
762
763 #[inline(always)]
764 pub fn rs1(&self) -> IntReg<D> {
765 IntReg::new(self.inst.rs1())
766 }
767
768 #[inline(always)]
769 pub fn csr(&self) -> u32 {
770 self.inst.i_imm() as u32 & 0xfff
771 }
772}
773
774#[derive(Copy, Clone, Debug)]
775pub struct RTypeInst<Rd, Rs1, Rs2>
776where
777 Rd: Register,
778 Rs1: Register,
779 Rs2: Register,
780{
781 inst: Instr32,
782 _rd: PhantomData<Rd>,
783 _rs1: PhantomData<Rs1>,
784 _rs2: PhantomData<Rs2>,
785}
786
787pub type RTypeIntInst<D> = RTypeInst<IntReg<D>, IntReg<D>, IntReg<D>>;
788
789impl<Rd, Rs1, Rs2> RTypeInst<Rd, Rs1, Rs2>
790where
791 Rd: Register,
792 Rs1: Register,
793 Rs2: Register,
794{
795 #[inline(always)]
796 fn new(inst: Instr32) -> DisResult<Self> {
797 let ret = Self {
798 inst,
799 _rd: PhantomData,
800 _rs1: PhantomData,
801 _rs2: PhantomData,
802 };
803
804 if !ret.rd().valid() || !ret.rs1().valid() || !ret.rs2().valid() {
805 return Err(Error::BadRegister);
806 }
807
808 Ok(ret)
809 }
810
811 #[inline(always)]
812 fn from_ops(rd: Rd, rs1: Rs1, rs2: Rs2) -> Self {
813 let raw: u32 = (rd.id() << 7) | (rs1.id() << 15) | (rs2.id() << 20);
814
815 Self {
816 inst: Instr32(raw),
817 _rd: PhantomData,
818 _rs1: PhantomData,
819 _rs2: PhantomData,
820 }
821 }
822
823 #[inline(always)]
824 pub fn rd(&self) -> Rd {
825 Rd::new(self.inst.rd())
826 }
827
828 #[inline(always)]
829 pub fn rs1(&self) -> Rs1 {
830 Rs1::new(self.inst.rs1())
831 }
832
833 #[inline(always)]
834 pub fn rs2(&self) -> Rs2 {
835 Rs2::new(self.inst.rs2())
836 }
837}
838
839#[derive(Copy, Clone, Debug)]
840pub struct RTypeFloatInst<D: RiscVDisassembler> {
841 width: u8,
842 rd: FloatReg<D>,
843 rs1: FloatReg<D>,
844 rs2: FloatReg<D>,
845}
846
847impl<D: RiscVDisassembler> RTypeFloatInst<D> {
848 #[inline(always)]
849 fn from_instr32(inst: Instr32) -> DisResult<Self> {
850 let width = match inst.fsize() {
851 0b00 => 4,
852 0b01 => 8,
853 0b11 => 16,
854 _ => return Err(Error::InvalidSubop),
855 };
856
857 if width > <D::RegFile as RegFile>::Float::width() {
858 return Err(Error::InvalidSubop);
859 }
860
861 let rd = FloatReg::new(inst.rd());
862 let rs1 = FloatReg::new(inst.rs1());
863 let rs2 = FloatReg::new(inst.rs2());
864
865 if !rd.valid() || !rs1.valid() || !rs2.valid() {
866 return Err(Error::BadRegister);
867 }
868
869 Ok(Self {
870 width: width as u8,
871 rd,
872 rs1,
873 rs2,
874 })
875 }
876
877 #[inline(always)]
878 pub fn width(&self) -> u8 {
879 self.width
880 }
881
882 #[inline(always)]
883 pub fn rd(&self) -> FloatReg<D> {
884 self.rd
885 }
886
887 #[inline(always)]
888 pub fn rs1(&self) -> FloatReg<D> {
889 self.rs1
890 }
891
892 #[inline(always)]
893 pub fn rs2(&self) -> FloatReg<D> {
894 self.rs2
895 }
896}
897
898#[derive(Copy, Clone, Debug)]
899pub struct RTypeFloatCmpInst<D: RiscVDisassembler> {
900 width: u8,
901 rd: IntReg<D>,
902 rs1: FloatReg<D>,
903 rs2: FloatReg<D>,
904}
905
906impl<D: RiscVDisassembler> RTypeFloatCmpInst<D> {
907 #[inline(always)]
908 fn from_instr32(inst: Instr32) -> DisResult<Self> {
909 let width = match inst.fsize() {
910 0b00 => 4,
911 0b01 => 8,
912 0b11 => 16,
913 _ => return Err(Error::InvalidSubop),
914 };
915
916 if width > <D::RegFile as RegFile>::Float::width() {
917 return Err(Error::InvalidSubop);
918 }
919
920 let rd = IntReg::new(inst.rd());
921 let rs1 = FloatReg::new(inst.rs1());
922 let rs2 = FloatReg::new(inst.rs2());
923
924 if !rd.valid() || !rs1.valid() || !rs2.valid() {
925 return Err(Error::BadRegister);
926 }
927
928 Ok(Self {
929 width: width as u8,
930 rd,
931 rs1,
932 rs2,
933 })
934 }
935
936 #[inline(always)]
937 pub fn width(&self) -> u8 {
938 self.width
939 }
940
941 #[inline(always)]
942 pub fn rd(&self) -> IntReg<D> {
943 self.rd
944 }
945
946 #[inline(always)]
947 pub fn rs1(&self) -> FloatReg<D> {
948 self.rs1
949 }
950
951 #[inline(always)]
952 pub fn rs2(&self) -> FloatReg<D> {
953 self.rs2
954 }
955}
956
957#[derive(Copy, Clone, Debug)]
958pub struct RTypeFloatRoundInst<D: RiscVDisassembler> {
959 width: u8,
960 rd: FloatReg<D>,
961 rs1: FloatReg<D>,
962 rs2: FloatReg<D>,
963 rm: RoundMode,
964}
965
966impl<D: RiscVDisassembler> RTypeFloatRoundInst<D> {
967 #[inline(always)]
968 fn from_instr32(inst: Instr32) -> DisResult<Self> {
969 let width = match inst.fsize() {
970 0b00 => 4,
971 0b01 => 8,
972 0b11 => 16,
973 _ => return Err(Error::InvalidSubop),
974 };
975
976 if width > <D::RegFile as RegFile>::Float::width() {
977 return Err(Error::InvalidSubop);
978 }
979
980 let rd = FloatReg::new(inst.rd());
981 let rs1 = FloatReg::new(inst.rs1());
982 let rs2 = FloatReg::new(inst.rs2());
983 let rm = RoundMode::from_bits(inst.rm())?;
984
985 if !rd.valid() || !rs1.valid() || !rs2.valid() {
986 return Err(Error::BadRegister);
987 }
988
989 Ok(Self {
990 width: width as u8,
991 rd,
992 rs1,
993 rs2,
994 rm,
995 })
996 }
997
998 #[inline(always)]
999 pub fn width(&self) -> u8 {
1000 self.width
1001 }
1002
1003 #[inline(always)]
1004 pub fn rd(&self) -> FloatReg<D> {
1005 self.rd
1006 }
1007
1008 #[inline(always)]
1009 pub fn rs1(&self) -> FloatReg<D> {
1010 self.rs1
1011 }
1012
1013 #[inline(always)]
1014 pub fn rs2(&self) -> FloatReg<D> {
1015 self.rs2
1016 }
1017
1018 #[inline(always)]
1019 pub fn rm(&self) -> RoundMode {
1020 self.rm
1021 }
1022}
1023
1024#[derive(Copy, Clone, Debug)]
1025pub struct BTypeInst<D: RiscVDisassembler> {
1026 rs1: IntReg<D>,
1027 rs2: IntReg<D>,
1028 imm: i16,
1029 _dis: PhantomData<D>,
1030}
1031
1032impl<D: RiscVDisassembler> BTypeInst<D> {
1033 #[inline(always)]
1034 fn new(rs1: IntReg<D>, rs2: IntReg<D>, imm: i32) -> DisResult<Self> {
1035 if !rs1.valid() || !rs2.valid() {
1036 return Err(Error::BadRegister);
1037 }
1038
1039 Ok(Self {
1040 rs1,
1041 rs2,
1042 imm: imm as i16,
1043 _dis: PhantomData,
1044 })
1045 }
1046
1047 #[inline(always)]
1048 fn from_instr32(inst: Instr32) -> DisResult<Self> {
1049 let rs1 = IntReg::new(inst.rs1());
1050 let rs2 = IntReg::new(inst.rs2());
1051
1052 if !rs1.valid() || !rs2.valid() {
1053 return Err(Error::BadRegister);
1054 }
1055
1056 Ok(Self {
1057 rs1,
1058 rs2,
1059 imm: inst.b_imm() as i16,
1060 _dis: PhantomData,
1061 })
1062 }
1063
1064 #[inline(always)]
1065 pub fn rs1(&self) -> IntReg<D> {
1066 self.rs1
1067 }
1068
1069 #[inline(always)]
1070 pub fn rs2(&self) -> IntReg<D> {
1071 self.rs2
1072 }
1073
1074 #[inline(always)]
1075 pub fn imm(&self) -> i32 {
1076 self.imm as i32
1077 }
1078}
1079
1080#[derive(Copy, Clone, Debug)]
1081pub struct UTypeInst<D: RiscVDisassembler> {
1082 rd: IntReg<D>,
1083 imm: i32,
1084 _dis: PhantomData<D>,
1085}
1086
1087impl<D: RiscVDisassembler> UTypeInst<D> {
1088 #[inline(always)]
1089 fn new(rd: IntReg<D>, imm: i32) -> DisResult<Self> {
1090 if !rd.valid() {
1091 return Err(Error::BadRegister);
1092 }
1093
1094 Ok(Self {
1095 rd,
1096 imm,
1097 _dis: PhantomData,
1098 })
1099 }
1100
1101 #[inline(always)]
1102 fn from_instr32(inst: Instr32) -> DisResult<Self> {
1103 let rd = IntReg::new(inst.rd());
1104
1105 if !rd.valid() {
1106 return Err(Error::BadRegister);
1107 }
1108
1109 Ok(Self {
1110 rd,
1111 imm: inst.u_imm(),
1112 _dis: PhantomData,
1113 })
1114 }
1115
1116 #[inline(always)]
1117 pub fn rd(&self) -> IntReg<D> {
1118 self.rd
1119 }
1120
1121 #[inline(always)]
1122 pub fn imm(&self) -> i32 {
1123 self.imm
1124 }
1125}
1126
1127#[derive(Copy, Clone, Debug)]
1128pub struct JTypeInst<D: RiscVDisassembler> {
1129 rd: IntReg<D>,
1130 imm: i32,
1131 _dis: PhantomData<D>,
1132}
1133
1134impl<D: RiscVDisassembler> JTypeInst<D> {
1135 #[inline(always)]
1136 fn new(rd: IntReg<D>, imm: i32) -> DisResult<Self> {
1137 if !rd.valid() {
1138 return Err(Error::BadRegister);
1139 }
1140
1141 Ok(Self {
1142 rd,
1143 imm,
1144 _dis: PhantomData,
1145 })
1146 }
1147
1148 #[inline(always)]
1149 fn from_instr32(inst: Instr32) -> DisResult<Self> {
1150 let rd = IntReg::new(inst.rd());
1151
1152 if !rd.valid() {
1153 return Err(Error::BadRegister);
1154 }
1155
1156 Ok(Self {
1157 rd,
1158 imm: inst.j_imm(),
1159 _dis: PhantomData,
1160 })
1161 }
1162
1163 #[inline(always)]
1164 pub fn rd(&self) -> IntReg<D> {
1165 self.rd
1166 }
1167
1168 #[inline(always)]
1169 pub fn imm(&self) -> i32 {
1170 self.imm
1171 }
1172}
1173
1174#[derive(Copy, Clone, Debug)]
1175pub struct AtomicInst<D: RiscVDisassembler> {
1176 inst: Instr32,
1177 _dis: PhantomData<D>,
1178}
1179
1180impl<D: RiscVDisassembler> AtomicInst<D> {
1181 #[inline(always)]
1182 fn new(inst: Instr32) -> DisResult<Self> {
1183 let ret = Self {
1184 inst,
1185 _dis: PhantomData,
1186 };
1187
1188 let width = ret.width();
1189
1190 if width < 4 || width > <D::RegFile as RegFile>::Int::width() {
1191 return Err(Error::InvalidSubop);
1192 } else if !ret.rd().valid() || !ret.rs1().valid() || !ret.rs2().valid() {
1193 return Err(Error::BadRegister);
1194 }
1195
1196 Ok(ret)
1197 }
1198
1199 #[inline(always)]
1200 pub fn rd(&self) -> IntReg<D> {
1201 IntReg::new(self.inst.rd())
1202 }
1203
1204 #[inline(always)]
1205 pub fn rs1(&self) -> IntReg<D> {
1206 IntReg::new(self.inst.rs1())
1207 }
1208
1209 #[inline(always)]
1210 pub fn rs2(&self) -> IntReg<D> {
1211 IntReg::new(self.inst.rs2())
1212 }
1213
1214 #[inline(always)]
1215 pub fn width(&self) -> usize {
1216 1usize.wrapping_shl(self.inst.funct3())
1217 }
1218
1219 #[inline(always)]
1220 pub fn aq(&self) -> bool {
1221 self.inst.extract_bits(26, 1) != 0
1222 }
1223
1224 #[inline(always)]
1225 pub fn rl(&self) -> bool {
1226 self.inst.extract_bits(25, 1) != 0
1227 }
1228}
1229
1230#[derive(Copy, Clone, Debug)]
1231pub struct FpMemInst<D: RiscVDisassembler> {
1232 width: u8,
1233 fr: FloatReg<D>,
1234 rs1: IntReg<D>,
1235 imm: i16,
1236 _dis: PhantomData<D>,
1237}
1238
1239impl<D: RiscVDisassembler> FpMemInst<D> {
1240 #[inline(always)]
1241 fn new(width: usize, fr: FloatReg<D>, rs1: IntReg<D>, imm: i32) -> DisResult<Self> {
1242 if width > <D::RegFile as RegFile>::Float::width() {
1243 return Err(Error::InvalidSubop);
1244 } else if !fr.valid() || !rs1.valid() {
1245 return Err(Error::BadRegister);
1246 }
1247
1248 Ok(Self {
1249 width: width as u8,
1250 fr,
1251 rs1,
1252 imm: imm as i16,
1253 _dis: PhantomData,
1254 })
1255 }
1256
1257 #[inline(always)]
1258 pub fn width(&self) -> usize {
1259 self.width as usize
1260 }
1261
1262 #[inline(always)]
1263 pub fn fr(&self) -> FloatReg<D> {
1264 self.fr
1265 }
1266
1267 #[inline(always)]
1268 pub fn rs1(&self) -> IntReg<D> {
1269 self.rs1
1270 }
1271
1272 #[inline(always)]
1273 pub fn imm(&self) -> i32 {
1274 self.imm as i32
1275 }
1276}
1277
1278#[derive(Copy, Clone, Debug)]
1279pub struct FpMAddInst<D: RiscVDisassembler> {
1280 width: u8,
1281 rd: FloatReg<D>,
1282 rs1: FloatReg<D>,
1283 rs2: FloatReg<D>,
1284 rs3: FloatReg<D>,
1285 rm: RoundMode,
1286 _dis: PhantomData<D>,
1287}
1288
1289impl<D: RiscVDisassembler> FpMAddInst<D> {
1290 #[inline(always)]
1291 fn from_instr32(inst: Instr32) -> DisResult<Self> {
1292 let width = match inst.fsize() {
1293 0b00 => 4,
1294 0b01 => 8,
1295 0b11 => 16,
1296 _ => return Err(Error::InvalidSubop),
1297 };
1298
1299 if width > <D::RegFile as RegFile>::Float::width() {
1300 return Err(Error::InvalidSubop);
1301 }
1302
1303 let rd = FloatReg::new(inst.rd());
1304 let rs1 = FloatReg::new(inst.rs1());
1305 let rs2 = FloatReg::new(inst.rs2());
1306 let rs3 = FloatReg::new(inst.rs3());
1307 let rm = RoundMode::from_bits(inst.rm())?;
1308
1309 if !rd.valid() || !rs1.valid() || !rs2.valid() || !rs3.valid() {
1310 return Err(Error::BadRegister);
1311 }
1312
1313 Ok(Self {
1314 width: width as u8,
1315 rd,
1316 rs1,
1317 rs2,
1318 rs3,
1319 rm,
1320 _dis: PhantomData,
1321 })
1322 }
1323
1324 #[inline(always)]
1325 pub fn width(&self) -> u8 {
1326 self.width
1327 }
1328
1329 #[inline(always)]
1330 pub fn rd(&self) -> FloatReg<D> {
1331 self.rd
1332 }
1333
1334 #[inline(always)]
1335 pub fn rs1(&self) -> FloatReg<D> {
1336 self.rs1
1337 }
1338
1339 #[inline(always)]
1340 pub fn rs2(&self) -> FloatReg<D> {
1341 self.rs2
1342 }
1343
1344 #[inline(always)]
1345 pub fn rs3(&self) -> FloatReg<D> {
1346 self.rs3
1347 }
1348
1349 #[inline(always)]
1350 pub fn rm(&self) -> RoundMode {
1351 self.rm
1352 }
1353}
1354
1355#[derive(Copy, Clone, Debug)]
1356pub struct FpCvtInst<D: RiscVDisassembler> {
1357 rd_width: u8,
1358 rs1_width: u8,
1359 rd: FloatReg<D>,
1360 rs1: FloatReg<D>,
1361 rm: RoundMode,
1362 _dis: PhantomData<D>,
1363}
1364
1365impl<D: RiscVDisassembler> FpCvtInst<D> {
1366 #[inline(always)]
1367 fn new(
1368 rd: FloatReg<D>,
1369 rd_width: u8,
1370 rs1: FloatReg<D>,
1371 rs1_width: u8,
1372 rm: RoundMode,
1373 ) -> DisResult<Self> {
1374 Ok(Self {
1375 rd_width,
1376 rs1_width,
1377 rd,
1378 rs1,
1379 rm,
1380 _dis: PhantomData,
1381 })
1382 }
1383
1384 #[inline(always)]
1385 pub fn rd_width(&self) -> u8 {
1386 self.rd_width
1387 }
1388
1389 #[inline(always)]
1390 pub fn rs1_width(&self) -> u8 {
1391 self.rs1_width
1392 }
1393
1394 #[inline(always)]
1395 pub fn rd(&self) -> FloatReg<D> {
1396 self.rd
1397 }
1398
1399 #[inline(always)]
1400 pub fn rs1(&self) -> FloatReg<D> {
1401 self.rs1
1402 }
1403
1404 #[inline(always)]
1405 pub fn rm(&self) -> RoundMode {
1406 self.rm
1407 }
1408}
1409
1410#[derive(Copy, Clone, Debug)]
1411pub struct FpCvtToIntInst<D: RiscVDisassembler> {
1412 rd_width: u8,
1413 rs1_width: u8,
1414 zx: bool,
1415 rd: IntReg<D>,
1416 rs1: FloatReg<D>,
1417 rm: RoundMode,
1418 _dis: PhantomData<D>,
1419}
1420
1421impl<D: RiscVDisassembler> FpCvtToIntInst<D> {
1422 #[inline(always)]
1423 fn new(
1424 rd: IntReg<D>,
1425 rd_width: u8,
1426 zx: bool,
1427 rs1: FloatReg<D>,
1428 rs1_width: u8,
1429 rm: RoundMode,
1430 ) -> DisResult<Self> {
1431 Ok(Self {
1432 rd_width,
1433 rs1_width,
1434 zx,
1435 rd,
1436 rs1,
1437 rm,
1438 _dis: PhantomData,
1439 })
1440 }
1441
1442 #[inline(always)]
1443 pub fn rd_width(&self) -> u8 {
1444 self.rd_width
1445 }
1446
1447 #[inline(always)]
1448 pub fn rs1_width(&self) -> u8 {
1449 self.rs1_width
1450 }
1451
1452 #[inline(always)]
1453 pub fn zx(&self) -> bool {
1454 self.zx
1455 }
1456
1457 #[inline(always)]
1458 pub fn rd(&self) -> IntReg<D> {
1459 self.rd
1460 }
1461
1462 #[inline(always)]
1463 pub fn rs1(&self) -> FloatReg<D> {
1464 self.rs1
1465 }
1466
1467 #[inline(always)]
1468 pub fn rm(&self) -> RoundMode {
1469 self.rm
1470 }
1471}
1472
1473#[derive(Copy, Clone, Debug)]
1474pub struct FpCvtFromIntInst<D: RiscVDisassembler> {
1475 rd_width: u8,
1476 rs1_width: u8,
1477 zx: bool,
1478 rd: FloatReg<D>,
1479 rs1: IntReg<D>,
1480 rm: RoundMode,
1481 _dis: PhantomData<D>,
1482}
1483
1484impl<D: RiscVDisassembler> FpCvtFromIntInst<D> {
1485 #[inline(always)]
1486 fn new(
1487 rd: FloatReg<D>,
1488 rd_width: u8,
1489 rs1: IntReg<D>,
1490 rs1_width: u8,
1491 zx: bool,
1492 rm: RoundMode,
1493 ) -> DisResult<Self> {
1494 Ok(Self {
1495 rd_width,
1496 rs1_width,
1497 zx,
1498 rd,
1499 rs1,
1500 rm,
1501 _dis: PhantomData,
1502 })
1503 }
1504
1505 #[inline(always)]
1506 pub fn rd_width(&self) -> u8 {
1507 self.rd_width
1508 }
1509
1510 #[inline(always)]
1511 pub fn rs1_width(&self) -> u8 {
1512 self.rs1_width
1513 }
1514
1515 #[inline(always)]
1516 pub fn zx(&self) -> bool {
1517 self.zx
1518 }
1519
1520 #[inline(always)]
1521 pub fn rd(&self) -> FloatReg<D> {
1522 self.rd
1523 }
1524
1525 #[inline(always)]
1526 pub fn rs1(&self) -> IntReg<D> {
1527 self.rs1
1528 }
1529
1530 #[inline(always)]
1531 pub fn rm(&self) -> RoundMode {
1532 self.rm
1533 }
1534}
1535
1536#[derive(Copy, Clone, Debug)]
1537pub struct FpMvToIntInst<D: RiscVDisassembler> {
1538 width: u8,
1539 rd: IntReg<D>,
1540 rs1: FloatReg<D>,
1541 _dis: PhantomData<D>,
1542}
1543
1544impl<D: RiscVDisassembler> FpMvToIntInst<D> {
1545 #[inline(always)]
1546 fn from_instr32(inst: Instr32) -> DisResult<Self> {
1547 let width = match inst.fsize() {
1548 0b00 => 4,
1549 0b01 => 8,
1550 0b11 => 16,
1551 _ => return Err(Error::InvalidSubop),
1552 };
1553
1554 if width > <D::RegFile as RegFile>::Float::width()
1555 || width > <D::RegFile as RegFile>::Int::width()
1556 {
1557 return Err(Error::InvalidSubop);
1558 }
1559
1560 let rd = IntReg::new(inst.rd());
1561 let rs1 = FloatReg::new(inst.rs1());
1562
1563 if !rd.valid() || !rs1.valid() {
1564 return Err(Error::BadRegister);
1565 }
1566
1567 Ok(Self {
1568 width: width as u8,
1569 rd,
1570 rs1,
1571 _dis: PhantomData,
1572 })
1573 }
1574
1575 #[inline(always)]
1576 pub fn width(&self) -> u8 {
1577 self.width
1578 }
1579
1580 #[inline(always)]
1581 pub fn rd(&self) -> IntReg<D> {
1582 self.rd
1583 }
1584
1585 #[inline(always)]
1586 pub fn rs1(&self) -> FloatReg<D> {
1587 self.rs1
1588 }
1589}
1590
1591#[derive(Copy, Clone, Debug)]
1592pub struct FpMvFromIntInst<D: RiscVDisassembler> {
1593 width: u8,
1594 rd: FloatReg<D>,
1595 rs1: IntReg<D>,
1596 _dis: PhantomData<D>,
1597}
1598
1599impl<D: RiscVDisassembler> FpMvFromIntInst<D> {
1600 #[inline(always)]
1601 fn from_instr32(inst: Instr32) -> DisResult<Self> {
1602 let width = match inst.fsize() {
1603 0b00 => 4,
1604 0b01 => 8,
1605 0b11 => 16,
1606 _ => return Err(Error::InvalidSubop),
1607 };
1608
1609 if width > <D::RegFile as RegFile>::Float::width()
1610 || width > <D::RegFile as RegFile>::Int::width()
1611 {
1612 return Err(Error::InvalidSubop);
1613 }
1614
1615 let rd = FloatReg::new(inst.rd());
1616 let rs1 = IntReg::new(inst.rs1());
1617
1618 if !rd.valid() || !rs1.valid() {
1619 return Err(Error::BadRegister);
1620 }
1621
1622 Ok(Self {
1623 width: width as u8,
1624 rd,
1625 rs1,
1626 _dis: PhantomData,
1627 })
1628 }
1629
1630 #[inline(always)]
1631 pub fn width(&self) -> u8 {
1632 self.width
1633 }
1634
1635 #[inline(always)]
1636 pub fn rd(&self) -> FloatReg<D> {
1637 self.rd
1638 }
1639
1640 #[inline(always)]
1641 pub fn rs1(&self) -> IntReg<D> {
1642 self.rs1
1643 }
1644}
1645
1646#[derive(Copy, Clone, Debug)]
1647pub struct FpClassInst<D: RiscVDisassembler> {
1648 width: u8,
1649 rd: IntReg<D>,
1650 rs1: FloatReg<D>,
1651 _dis: PhantomData<D>,
1652}
1653
1654impl<D: RiscVDisassembler> FpClassInst<D> {
1655 #[inline(always)]
1656 fn from_instr32(inst: Instr32) -> DisResult<Self> {
1657 let width = match inst.fsize() {
1658 0b00 => 4,
1659 0b01 => 8,
1660 0b11 => 16,
1661 _ => return Err(Error::InvalidSubop),
1662 };
1663
1664 if width > <D::RegFile as RegFile>::Float::width() {
1665 return Err(Error::InvalidSubop);
1666 }
1667
1668 let rd = IntReg::new(inst.rd());
1669 let rs1 = FloatReg::new(inst.rs1());
1670
1671 if !rd.valid() || !rs1.valid() {
1672 return Err(Error::BadRegister);
1673 }
1674
1675 Ok(Self {
1676 width: width as u8,
1677 rd,
1678 rs1,
1679 _dis: PhantomData,
1680 })
1681 }
1682
1683 #[inline(always)]
1684 pub fn width(&self) -> u8 {
1685 self.width
1686 }
1687
1688 #[inline(always)]
1689 pub fn rd(&self) -> IntReg<D> {
1690 self.rd
1691 }
1692
1693 #[inline(always)]
1694 pub fn rs1(&self) -> FloatReg<D> {
1695 self.rs1
1696 }
1697}
1698
1699#[derive(Copy, Clone, Debug)]
1700pub struct Instr16(u16);
1701impl Instr16 {
1702 #[inline(always)]
1703 fn extract_bits(self, start_bit: u32, width: u32) -> u16 {
1704 self.0.wrapping_shr(start_bit) & 1u16.wrapping_shl(width).wrapping_sub(1)
1705 }
1706
1707 #[inline(always)]
1708 fn sp_load_imm(self, size: usize) -> i32 {
1709 let size = size as u32 >> 3;
1710 let start = 4 + size;
1711
1712 let res = (self.extract_bits(start, 3 - size) << (2 + size))
1713 | (self.extract_bits(2, 2 + size) << 6);
1714
1715 (res | (self.extract_bits(12, 1) << 5)) as i32
1716 }
1717
1718 #[inline(always)]
1719 fn mem_imm(self, size: usize) -> i32 {
1720 let upper = self.extract_bits(10, 3) << 3;
1721
1722 let res = match size {
1723 4 => upper | self.extract_bits(6, 1) << 2 | self.extract_bits(5, 1) << 6,
1724 8 => upper | self.extract_bits(5, 2) << 6,
1725 _ => unimplemented!(),
1726 };
1727
1728 res as i32
1729 }
1730
1731 #[inline(always)]
1732 fn sp_store_imm(self, size: usize) -> i32 {
1733 let size = size as u32 >> 3;
1734 let start = 9 + size;
1735
1736 ((self.extract_bits(start, 4 - size) << (2 + size)) | (self.extract_bits(7, 2 + size) << 6))
1737 as i32
1738 }
1739
1740 #[inline(always)]
1741 fn cb_imm(self) -> i32 {
1742 let mut imm = self.extract_bits(2, 1) << 5;
1743 imm |= self.extract_bits(3, 2) << 1;
1744 imm |= self.extract_bits(5, 2) << 6;
1745 imm |= self.extract_bits(10, 2) << 3;
1746
1747 if self.extract_bits(12, 1) != 0 {
1748 imm |= !0xff;
1749 }
1750
1751 imm as i16 as i32
1752 }
1753
1754 #[inline(always)]
1755 fn cj_imm(self) -> i32 {
1756 let mut imm = self.extract_bits(2, 1) << 5;
1757 imm |= self.extract_bits(3, 3) << 1;
1758 imm |= self.extract_bits(6, 1) << 7;
1759 imm |= self.extract_bits(7, 1) << 6;
1760 imm |= self.extract_bits(8, 1) << 10;
1761 imm |= self.extract_bits(9, 2) << 8;
1762 imm |= self.extract_bits(11, 1) << 4;
1763
1764 if self.extract_bits(12, 1) != 0 {
1765 imm |= !0x7ff;
1766 }
1767
1768 imm as i16 as i32
1769 }
1770}
1771
1772pub enum Instr<D: RiscVDisassembler> {
1773 Rv16(Op<D>),
1774 Rv32(Op<D>),
1775}
1776
1777impl<D: RiscVDisassembler> Instr<D> {
1778 pub fn mnem(&self) -> Mnem<'_, D> {
1779 Mnem(self)
1780 }
1781
1782 pub fn operands(&self) -> Vec<Operand<D>> {
1783 let mut ops = Vec::new();
1784
1785 match *self {
1786 Instr::Rv32(ref op) | Instr::Rv16(ref op) => match *op {
1788 Op::Load(ref l) => {
1789 ops.push(Operand::R(l.rd()));
1790 ops.push(Operand::M(l.imm(), l.rs1()));
1791 }
1792 Op::Store(ref s) => {
1793 ops.push(Operand::R(s.rs2()));
1794 ops.push(Operand::M(s.imm(), s.rs1()));
1795 }
1796 Op::Fence(ref i)
1797 | Op::FenceI(ref i)
1798 | Op::AddI(ref i)
1799 | Op::SltI(ref i)
1800 | Op::SltIU(ref i)
1801 | Op::XorI(ref i)
1802 | Op::OrI(ref i)
1803 | Op::AndI(ref i)
1804 | Op::SllI(ref i)
1805 | Op::SrlI(ref i)
1806 | Op::SraI(ref i)
1807 | Op::AddIW(ref i)
1808 | Op::SllIW(ref i)
1809 | Op::SrlIW(ref i)
1810 | Op::SraIW(ref i) => {
1811 ops.push(Operand::R(i.rd()));
1812 ops.push(Operand::R(i.rs1()));
1813 ops.push(Operand::I(i.imm()));
1814 }
1815 Op::Auipc(ref u) | Op::Lui(ref u) => {
1816 ops.push(Operand::R(u.rd()));
1817 ops.push(Operand::I(u.imm()));
1818 }
1819 Op::Add(ref r)
1820 | Op::Sll(ref r)
1821 | Op::Slt(ref r)
1822 | Op::SltU(ref r)
1823 | Op::Xor(ref r)
1824 | Op::Srl(ref r)
1825 | Op::Or(ref r)
1826 | Op::And(ref r)
1827 | Op::Sub(ref r)
1828 | Op::Sra(ref r)
1829 | Op::AddW(ref r)
1830 | Op::SllW(ref r)
1831 | Op::SrlW(ref r)
1832 | Op::SubW(ref r)
1833 | Op::SraW(ref r)
1834 | Op::Mul(ref r)
1835 | Op::MulH(ref r)
1836 | Op::MulHSU(ref r)
1837 | Op::MulHU(ref r)
1838 | Op::Div(ref r)
1839 | Op::DivU(ref r)
1840 | Op::Rem(ref r)
1841 | Op::RemU(ref r)
1842 | Op::MulW(ref r)
1843 | Op::DivW(ref r)
1844 | Op::DivUW(ref r)
1845 | Op::RemW(ref r)
1846 | Op::RemUW(ref r) => {
1847 ops.push(Operand::R(r.rd()));
1848 ops.push(Operand::R(r.rs1()));
1849 ops.push(Operand::R(r.rs2()));
1850 }
1851 Op::Beq(ref b)
1852 | Op::Bne(ref b)
1853 | Op::Blt(ref b)
1854 | Op::Bge(ref b)
1855 | Op::BltU(ref b)
1856 | Op::BgeU(ref b) => {
1857 ops.push(Operand::R(b.rs1()));
1858 ops.push(Operand::R(b.rs2()));
1859 ops.push(Operand::I(b.imm()));
1860 }
1861 Op::Jalr(ref i) => {
1862 ops.push(Operand::R(i.rd()));
1863 ops.push(Operand::R(i.rs1()));
1864 ops.push(Operand::I(i.imm()));
1865 }
1866 Op::Jal(ref j) => {
1867 ops.push(Operand::R(j.rd()));
1868 ops.push(Operand::I(j.imm()));
1869 }
1870 Op::SfenceVm(ref _r) => {}
1871 Op::SfenceVma(ref r) => {
1872 ops.push(Operand::R(r.rs1()));
1873 ops.push(Operand::R(r.rs2()));
1874 }
1875 Op::Csrrw(ref i) | Op::Csrrs(ref i) | Op::Csrrc(ref i) => {
1876 ops.push(Operand::R(i.rd()));
1877 ops.push(Operand::I(i.csr() as i32));
1878 ops.push(Operand::R(i.rs1()));
1879 }
1880 Op::CsrrwI(ref i) | Op::CsrrsI(ref i) | Op::CsrrcI(ref i) => {
1881 ops.push(Operand::R(i.rd()));
1882 ops.push(Operand::I(i.csr() as i32));
1883 ops.push(Operand::I(i.imm() as i32));
1884 }
1885 Op::Ecall | Op::Ebreak | Op::Uret | Op::Sret | Op::Mret | Op::Wfi => {}
1886 Op::Lr(ref a)
1887 | Op::Sc(ref a)
1888 | Op::AmoSwap(ref a)
1889 | Op::AmoAdd(ref a)
1890 | Op::AmoXor(ref a)
1891 | Op::AmoAnd(ref a)
1892 | Op::AmoOr(ref a)
1893 | Op::AmoMin(ref a)
1894 | Op::AmoMax(ref a)
1895 | Op::AmoMinU(ref a)
1896 | Op::AmoMaxU(ref a) => {
1897 ops.push(Operand::R(a.rd()));
1898
1899 if let Op::Lr(..) = *op {
1900 } else {
1901 ops.push(Operand::R(a.rs2()));
1902 }
1903
1904 ops.push(Operand::M(0, a.rs1()));
1905 }
1906 Op::LoadFp(ref m) | Op::StoreFp(ref m) => {
1907 ops.push(Operand::F(m.fr()));
1908 ops.push(Operand::M(m.imm(), m.rs1()));
1909 }
1910 Op::Fmadd(ref f) | Op::Fmsub(ref f) | Op::Fnmadd(ref f) | Op::Fnmsub(ref f) => {
1911 ops.push(Operand::F(f.rd()));
1912 ops.push(Operand::F(f.rs1()));
1913 ops.push(Operand::F(f.rs2()));
1914 ops.push(Operand::F(f.rs3()));
1915 if f.rm() != RoundMode::Dynamic {
1916 ops.push(Operand::RM(f.rm()));
1917 }
1918 }
1919 Op::Fadd(ref f) | Op::Fsub(ref f) | Op::Fmul(ref f) | Op::Fdiv(ref f) => {
1920 ops.push(Operand::F(f.rd()));
1921 ops.push(Operand::F(f.rs1()));
1922 ops.push(Operand::F(f.rs2()));
1923 if f.rm() != RoundMode::Dynamic {
1924 ops.push(Operand::RM(f.rm()));
1925 }
1926 }
1927 Op::Fsqrt(ref f) => {
1928 ops.push(Operand::F(f.rd()));
1929 ops.push(Operand::F(f.rs1()));
1930 if f.rm() != RoundMode::Dynamic {
1931 ops.push(Operand::RM(f.rm()));
1932 }
1933 }
1934 Op::Fsgnj(ref f)
1935 | Op::Fsgnjn(ref f)
1936 | Op::Fsgnjx(ref f)
1937 | Op::Fmin(ref f)
1938 | Op::Fmax(ref f) => {
1939 ops.push(Operand::F(f.rd()));
1940 ops.push(Operand::F(f.rs1()));
1941 ops.push(Operand::F(f.rs2()));
1942 }
1943 Op::Fle(ref f) | Op::Flt(ref f) | Op::Feq(ref f) => {
1944 ops.push(Operand::R(f.rd()));
1945 ops.push(Operand::F(f.rs1()));
1946 ops.push(Operand::F(f.rs2()));
1947 }
1948 Op::Fcvt(ref f) => {
1949 ops.push(Operand::F(f.rd()));
1950 ops.push(Operand::F(f.rs1()));
1951 if f.rm() != RoundMode::Dynamic {
1952 ops.push(Operand::RM(f.rm()));
1953 }
1954 }
1955 Op::FcvtToInt(ref f) => {
1956 ops.push(Operand::R(f.rd()));
1957 ops.push(Operand::F(f.rs1()));
1958 if f.rm() != RoundMode::Dynamic {
1959 ops.push(Operand::RM(f.rm()));
1960 }
1961 }
1962 Op::FcvtFromInt(ref f) => {
1963 ops.push(Operand::F(f.rd()));
1964 ops.push(Operand::R(f.rs1()));
1965 if f.rm() != RoundMode::Dynamic {
1966 ops.push(Operand::RM(f.rm()));
1967 }
1968 }
1969 Op::FmvToInt(ref f) => {
1970 ops.push(Operand::R(f.rd()));
1971 ops.push(Operand::F(f.rs1()));
1972 }
1973 Op::FmvFromInt(ref f) => {
1974 ops.push(Operand::F(f.rd()));
1975 ops.push(Operand::R(f.rs1()));
1976 }
1977 Op::Fclass(ref f) => {
1978 ops.push(Operand::R(f.rd()));
1979 ops.push(Operand::F(f.rs1()));
1980 }
1981 },
1982 }
1983
1984 ops
1985 }
1986}
1987
1988pub struct Mnem<'a, D: RiscVDisassembler + 'a>(&'a Instr<D>);
1989impl<'a, D: RiscVDisassembler + 'a> Mnem<'a, D> {
1990 fn mnem(&self) -> &str {
1991 match self.0 {
1992 &Instr::Rv32(ref op) | &Instr::Rv16(ref op) => match *op {
1993 Op::Load(..) => "l",
1994 Op::Fence(..) => "fence",
1995 Op::FenceI(..) => "fence.i",
1996
1997 Op::AddI(..) => "addi",
1998 Op::SltI(..) => "slti",
1999 Op::SltIU(..) => "sltiu",
2000 Op::XorI(..) => "xori",
2001 Op::OrI(..) => "ori",
2002 Op::AndI(..) => "andi",
2003 Op::SllI(..) => "slli",
2004 Op::SrlI(..) => "srli",
2005 Op::SraI(..) => "srai",
2006
2007 Op::Auipc(..) => "auipc",
2008
2009 Op::AddIW(..) => "addiw",
2010 Op::SllIW(..) => "slliw",
2011 Op::SrlIW(..) => "srliw",
2012 Op::SraIW(..) => "sraiw",
2013
2014 Op::Store(..) => "s",
2015
2016 Op::Lr(..) => "lr",
2017 Op::Sc(..) => "sc",
2018 Op::AmoSwap(..) => "amoswap",
2019 Op::AmoAdd(..) => "amoadd",
2020 Op::AmoXor(..) => "amoxor",
2021 Op::AmoAnd(..) => "amoand",
2022 Op::AmoOr(..) => "amoor",
2023 Op::AmoMin(..) => "amoamin",
2024 Op::AmoMax(..) => "amoamax",
2025 Op::AmoMinU(..) => "amoaminu",
2026 Op::AmoMaxU(..) => "amoamaxu",
2027
2028 Op::Add(..) => "add",
2029 Op::Sll(..) => "sll",
2030 Op::Slt(..) => "slt",
2031 Op::SltU(..) => "sltu",
2032 Op::Xor(..) => "xor",
2033 Op::Srl(..) => "srl",
2034 Op::Or(..) => "or",
2035 Op::And(..) => "and",
2036 Op::Sub(..) => "sub",
2037 Op::Sra(..) => "sra",
2038
2039 Op::Mul(..) => "mul",
2040 Op::MulH(..) => "mulh",
2041 Op::MulHSU(..) => "mulhsu",
2042 Op::MulHU(..) => "mulhu",
2043 Op::Div(..) => "div",
2044 Op::DivU(..) => "divu",
2045 Op::Rem(..) => "rem",
2046 Op::RemU(..) => "remu",
2047
2048 Op::Lui(..) => "lui",
2049
2050 Op::AddW(..) => "addw",
2051 Op::SllW(..) => "sllw",
2052 Op::SrlW(..) => "srlw",
2053 Op::SubW(..) => "subw",
2054 Op::SraW(..) => "sraw",
2055
2056 Op::MulW(..) => "mulw",
2057 Op::DivW(..) => "divw",
2058 Op::DivUW(..) => "divuw",
2059 Op::RemW(..) => "remw",
2060 Op::RemUW(..) => "remuw",
2061
2062 Op::Beq(..) => "beq",
2063 Op::Bne(..) => "bne",
2064 Op::Blt(..) => "blt",
2065 Op::Bge(..) => "bge",
2066 Op::BltU(..) => "bltu",
2067 Op::BgeU(..) => "bgeu",
2068
2069 Op::Jalr(..) => "jalr",
2070 Op::Jal(..) => "jal",
2071
2072 Op::Ecall => "ecall",
2073 Op::Ebreak => "ebreak",
2074
2075 Op::Uret => "uret",
2076 Op::Sret => "sret",
2077 Op::Mret => "mret",
2078
2079 Op::Wfi => "wfi",
2080
2081 Op::SfenceVm(..) => "sfence.vm",
2082 Op::SfenceVma(..) => "sfence.vma",
2083
2084 Op::Csrrw(..) => "csrrw",
2085 Op::Csrrs(..) => "csrrs",
2086 Op::Csrrc(..) => "csrrc",
2087
2088 Op::CsrrwI(..) => "csrrwi",
2089 Op::CsrrsI(..) => "csrrsi",
2090 Op::CsrrcI(..) => "csrrci",
2091
2092 Op::LoadFp(..) => "fl",
2093 Op::StoreFp(..) => "fs",
2094
2095 Op::Fmadd(..) => "fmadd",
2096 Op::Fmsub(..) => "fmsub",
2097 Op::Fnmadd(..) => "fnmadd",
2098 Op::Fnmsub(..) => "fnmsub",
2099 Op::Fadd(..) => "fadd",
2100 Op::Fsub(..) => "fsub",
2101 Op::Fmul(..) => "fmul",
2102 Op::Fdiv(..) => "fdiv",
2103 Op::Fsqrt(..) => "fsqrt",
2104 Op::Fsgnj(..) => "fsgnj",
2105 Op::Fsgnjn(..) => "fsgnjn",
2106 Op::Fsgnjx(..) => "fsgnjx",
2107 Op::Fmin(..) => "fmin",
2108 Op::Fmax(..) => "fmax",
2109 Op::Fle(..) => "fle",
2110 Op::Flt(..) => "flt",
2111 Op::Feq(..) => "feq",
2112 Op::Fcvt(..) | Op::FcvtToInt(..) | Op::FcvtFromInt(..) => "fcvt",
2113 Op::FmvToInt(..) | Op::FmvFromInt(..) => "fmv",
2114 Op::Fclass(..) => "fclass",
2115 },
2116 }
2117 }
2118
2119 fn suffix(&self) -> Option<Cow<'_, str>> {
2120 match self.0 {
2121 &Instr::Rv32(ref op) | &Instr::Rv16(ref op) => match *op {
2123 Op::Load(ref l) => {
2124 let zx = if l.zx() { "u" } else { "" };
2125 let width = match l.width() {
2126 1 => "b",
2127 2 => "h",
2128 4 => "w",
2129 8 => "d",
2130 _ => unreachable!(),
2131 };
2132
2133 Some(format!("{}{}", width, zx).into())
2134 }
2135 Op::Store(ref s) => Some(
2136 match s.width() {
2137 1 => "b",
2138 2 => "h",
2139 4 => "w",
2140 8 => "d",
2141 _ => unreachable!(),
2142 }
2143 .into(),
2144 ),
2145 Op::Lr(ref a)
2146 | Op::Sc(ref a)
2147 | Op::AmoSwap(ref a)
2148 | Op::AmoAdd(ref a)
2149 | Op::AmoXor(ref a)
2150 | Op::AmoAnd(ref a)
2151 | Op::AmoOr(ref a)
2152 | Op::AmoMin(ref a)
2153 | Op::AmoMax(ref a)
2154 | Op::AmoMinU(ref a)
2155 | Op::AmoMaxU(ref a) => {
2156 let width = match a.width() {
2157 4 => ".w",
2158 8 => ".d",
2159 _ => unreachable!(),
2160 };
2161 let aq = if a.aq() { ".aq" } else { "" };
2162 let rl = if a.rl() { ".rl" } else { "" };
2163
2164 Some(format!("{}{}{}", width, aq, rl).into())
2165 }
2166 Op::LoadFp(ref m) | Op::StoreFp(ref m) => {
2167 let suf = match m.width() {
2168 4 => "w",
2169 8 => "d",
2170 16 => "q",
2171 _ => unreachable!(),
2172 };
2173
2174 Some(suf.into())
2175 }
2176 Op::Fmadd(ref f) | Op::Fmsub(ref f) | Op::Fnmadd(ref f) | Op::Fnmsub(ref f) => {
2177 let suf = match f.width() {
2178 4 => ".s",
2179 8 => ".d",
2180 16 => ".q",
2181 _ => unreachable!(),
2182 };
2183
2184 Some(suf.into())
2185 }
2186 Op::Fadd(ref f) | Op::Fsub(ref f) | Op::Fmul(ref f) | Op::Fdiv(ref f) => {
2187 let suf = match f.width() {
2188 4 => ".s",
2189 8 => ".d",
2190 16 => ".q",
2191 _ => unreachable!(),
2192 };
2193
2194 Some(suf.into())
2195 }
2196 Op::Fsgnj(ref f)
2197 | Op::Fsgnjn(ref f)
2198 | Op::Fsgnjx(ref f)
2199 | Op::Fmin(ref f)
2200 | Op::Fmax(ref f) => {
2201 let suf = match f.width() {
2202 4 => ".s",
2203 8 => ".d",
2204 16 => ".q",
2205 _ => unreachable!(),
2206 };
2207
2208 Some(suf.into())
2209 }
2210 Op::Fle(ref f) | Op::Flt(ref f) | Op::Feq(ref f) => {
2211 let suf = match f.width() {
2212 4 => ".s",
2213 8 => ".d",
2214 16 => ".q",
2215 _ => unreachable!(),
2216 };
2217
2218 Some(suf.into())
2219 }
2220 Op::Fcvt(ref f) => {
2221 let rd_suf = match f.rd_width() {
2222 4 => ".s",
2223 8 => ".d",
2224 16 => ".q",
2225 _ => unreachable!(),
2226 };
2227 let rs1_suf = match f.rs1_width() {
2228 4 => ".s",
2229 8 => ".d",
2230 16 => ".q",
2231 _ => unreachable!(),
2232 };
2233
2234 Some(format!("{}{}", rd_suf, rs1_suf).into())
2235 }
2236 Op::FcvtToInt(ref f) => {
2237 let rd_suf = match f.rd_width() {
2238 4 => ".w",
2239 8 => ".l",
2240 _ => unreachable!(),
2241 };
2242 let zx_suf = if f.zx() { "u" } else { "" };
2243 let rs1_suf = match f.rs1_width() {
2244 4 => ".s",
2245 8 => ".d",
2246 16 => ".q",
2247 _ => unreachable!(),
2248 };
2249
2250 Some(format!("{}{}{}", rd_suf, zx_suf, rs1_suf).into())
2251 }
2252 Op::FcvtFromInt(ref f) => {
2253 let rd_suf = match f.rs1_width() {
2254 4 => ".s",
2255 8 => ".d",
2256 16 => ".q",
2257 _ => unreachable!(),
2258 };
2259 let rs1_suf = match f.rd_width() {
2260 4 => ".w",
2261 8 => ".l",
2262 _ => unreachable!(),
2263 };
2264 let zx_suf = if f.zx() { "u" } else { "" };
2265
2266 Some(format!("{}{}{}", rd_suf, rs1_suf, zx_suf).into())
2267 }
2268 Op::FmvToInt(ref f) => {
2269 let suf = match f.width() {
2270 4 => ".x.w",
2271 8 => ".x.d",
2272 _ => unreachable!(),
2273 };
2274
2275 Some(suf.into())
2276 }
2277 Op::FmvFromInt(ref f) => {
2278 let suf = match f.width() {
2279 4 => ".w.x",
2280 8 => ".d.x",
2281 _ => unreachable!(),
2282 };
2283
2284 Some(suf.into())
2285 }
2286 Op::Fclass(ref f) => {
2287 let suf = match f.width() {
2288 4 => ".s",
2289 8 => ".d",
2290 16 => ".q",
2291 _ => unreachable!(),
2292 };
2293
2294 Some(suf.into())
2295 }
2296 _ => None,
2297 },
2298 }
2299 }
2300}
2301
2302impl<D: RiscVDisassembler> fmt::Display for Mnem<'_, D> {
2303 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2304 match (self.mnem(), self.suffix()) {
2305 (m, None) => f.pad(m),
2306 (m, Some(s)) => {
2307 let s = format!("{}{}", m, s);
2308 f.pad(&s)
2309 }
2310 }
2311 }
2312}
2313
2314pub trait StandardExtension {
2315 fn supported() -> bool;
2316}
2317
2318pub struct ExtensionNotImplemented;
2319impl StandardExtension for ExtensionNotImplemented {
2320 #[inline(always)]
2321 fn supported() -> bool {
2322 false
2323 }
2324}
2325
2326pub struct ExtensionSupported;
2327impl StandardExtension for ExtensionSupported {
2328 #[inline(always)]
2329 fn supported() -> bool {
2330 true
2331 }
2332}
2333
2334pub trait RiscVDisassembler: 'static + Debug + Sized + Copy + Clone + Send + Sync {
2335 type RegFile: RegFile;
2336 type MulDivExtension: StandardExtension;
2337 type AtomicExtension: StandardExtension;
2338 type CompressedExtension: StandardExtension;
2339
2340 fn decode(addr: u64, bytes: &[u8]) -> DisResult<Instr<Self>> {
2341 use Error::*;
2342
2343 let required_alignment: u64 = if Self::CompressedExtension::supported() {
2344 2
2345 } else {
2346 4
2347 };
2348
2349 if addr & required_alignment.wrapping_sub(1) != 0
2350 || bytes.len() < required_alignment as usize
2351 {
2352 return Err(Unaligned);
2353 }
2354
2355 let parcel = LittleEndian::read_u16(bytes);
2356
2357 let inst_len = match parcel {
2358 p if (p & 0b11) != 0b11 => 2,
2359 p if (p & 0b11111) != 0b11111 => 4,
2360 _ => {
2361 return Err(UnhandledLength);
2362 }
2363 };
2364
2365 match inst_len {
2366 2 if bytes.len() >= 2 && Self::CompressedExtension::supported() => {
2367 let inst = Instr16(parcel);
2368
2369 let opcode = (parcel >> 11 & !3) | (parcel & 3);
2373 let int_width = <Self::RegFile as RegFile>::Int::width();
2374 let float_width = <Self::RegFile as RegFile>::Float::width();
2375
2376 let decoded = match opcode {
2377 0b000_00 if parcel != 0 => {
2378 let rd = 8 + inst.extract_bits(2, 3) as u32;
2380 let mut imm = inst.extract_bits(5, 1) << 3;
2381 imm |= inst.extract_bits(6, 1) << 2;
2382 imm |= inst.extract_bits(7, 4) << 6;
2383 imm |= inst.extract_bits(11, 2) << 4;
2384
2385 if imm == 0 {
2386 return Err(InvalidSubop);
2387 }
2388
2389 Op::AddI(ITypeInst::from_ops(
2390 IntReg::new(rd),
2391 IntReg::new(2),
2392 imm as i32,
2393 ))
2394 }
2395 0b000_01 => {
2396 let rd = inst.extract_bits(7, 5) as u32;
2398 let mut imm = inst.extract_bits(2, 5) as u32;
2399
2400 if inst.extract_bits(12, 1) == 1 {
2402 imm |= !0x1f;
2403 }
2404
2405 Op::AddI(ITypeInst::from_ops(
2406 IntReg::new(rd),
2407 IntReg::new(rd),
2408 imm as i32,
2409 ))
2410 }
2411 0b000_10 if int_width >= 8 || inst.extract_bits(12, 1) == 0 => {
2413 let shamt =
2416 (inst.extract_bits(12, 1) << 5 | inst.extract_bits(2, 5)) as u32;
2417 let rd = inst.extract_bits(7, 5) as u32;
2418
2419 Op::SllI(ITypeInst::from_ops(
2422 IntReg::new(rd),
2423 IntReg::new(rd),
2424 shamt as i32,
2425 ))
2426 }
2427
2428 0b001_00 if float_width >= 8 => {
2430 let rd = FloatReg::new(8 + inst.extract_bits(2, 3) as u32);
2432 let rs1 = IntReg::new(8 + inst.extract_bits(7, 3) as u32);
2433
2434 let imm = inst.mem_imm(8);
2435 Op::LoadFp(FpMemInst::new(8, rd, rs1, imm)?)
2436 }
2437 0b001_01 if int_width == 4 => {
2438 Op::Jal(JTypeInst::new(IntReg::new(1), inst.cj_imm())?)
2440 }
2441 0b001_01 => {
2442 let rd = inst.extract_bits(7, 5) as u32;
2444 let mut imm = inst.extract_bits(2, 5) as u32;
2445
2446 if inst.extract_bits(12, 1) == 1 {
2449 imm |= !0x1f;
2450 }
2451
2452 Op::AddIW(ITypeInst::from_ops(
2453 IntReg::new(rd),
2454 IntReg::new(rd),
2455 imm as i32,
2456 ))
2457 }
2458 0b001_10 if float_width >= 8 => {
2460 let rd = FloatReg::new(inst.extract_bits(7, 5) as u32);
2462 let imm = inst.sp_load_imm(8);
2463
2464 Op::LoadFp(FpMemInst::new(8, rd, IntReg::new(2), imm)?)
2465 }
2466
2467 0b010_00 => {
2468 let rd = IntReg::new(8 + inst.extract_bits(2, 3) as u32);
2470 let rs1 = IntReg::new(8 + inst.extract_bits(7, 3) as u32);
2471
2472 let imm = inst.mem_imm(4);
2473 Op::Load(LoadTypeInst::new(4, false, rd, rs1, imm)?)
2474 }
2475 0b010_01 => {
2476 let rd = inst.extract_bits(7, 5) as u32;
2478
2479 if rd == 0 {
2481 return Err(InvalidSubop);
2482 }
2483
2484 let mut imm = inst.extract_bits(2, 5) as u32;
2486 if inst.extract_bits(12, 1) == 1 {
2487 imm |= !0x1f;
2488 }
2489
2490 Op::AddI(ITypeInst::from_ops(
2491 IntReg::new(rd),
2492 IntReg::new(0),
2493 imm as i32,
2494 ))
2495 }
2496 0b010_10 => {
2497 let rd = IntReg::new(inst.extract_bits(7, 5) as u32);
2499 let imm = inst.sp_load_imm(4);
2500
2501 if rd.id() == 0 {
2502 return Err(InvalidOpcode);
2503 }
2504
2505 Op::Load(LoadTypeInst::new(4, false, rd, IntReg::new(2), imm)?)
2506 }
2507
2508 0b011_00 if int_width >= 8 => {
2509 let rd = IntReg::new(8 + inst.extract_bits(2, 3) as u32);
2511 let rs1 = IntReg::new(8 + inst.extract_bits(7, 3) as u32);
2512
2513 let imm = inst.mem_imm(8);
2514 Op::Load(LoadTypeInst::new(8, false, rd, rs1, imm)?)
2515 }
2516 0b011_00 if float_width >= 4 => {
2517 let rd = FloatReg::new(8 + inst.extract_bits(2, 3) as u32);
2519 let rs1 = IntReg::new(8 + inst.extract_bits(7, 3) as u32);
2520
2521 let imm = inst.mem_imm(4);
2522 Op::LoadFp(FpMemInst::new(4, rd, rs1, imm)?)
2523 }
2524 0b011_01 => {
2525 let rd = inst.extract_bits(7, 5) as u32;
2527
2528 match rd {
2529 0 => return Err(InvalidSubop),
2530 2 => {
2531 let mut imm = inst.extract_bits(2, 1) << 5;
2533 imm |= inst.extract_bits(3, 2) << 7;
2534 imm |= inst.extract_bits(5, 1) << 6;
2535 imm |= inst.extract_bits(6, 1) << 4;
2536
2537 if inst.extract_bits(12, 1) == 1 {
2538 imm |= !0x1ff;
2539 }
2540
2541 if imm == 0 {
2542 return Err(InvalidSubop);
2543 }
2544
2545 Op::AddI(ITypeInst::from_ops(
2546 IntReg::new(2),
2547 IntReg::new(2),
2548 imm as i16 as i32,
2549 ))
2550 }
2551 _ => {
2552 let mut imm = inst.extract_bits(2, 5) as u32;
2554 if inst.extract_bits(12, 1) == 1 {
2555 imm |= !0x1f;
2556 }
2557
2558 let imm = (imm as i32) << 12;
2559 Op::Lui(UTypeInst::new(IntReg::new(rd), imm)?)
2560 }
2561 }
2562 }
2563 0b011_10 if int_width >= 8 => {
2564 let rd = IntReg::new(inst.extract_bits(7, 5) as u32);
2566 let imm = inst.sp_load_imm(8);
2567
2568 if rd.id() == 0 {
2569 return Err(InvalidOpcode);
2570 }
2571
2572 Op::Load(LoadTypeInst::new(8, false, rd, IntReg::new(2), imm)?)
2573 }
2574 0b011_10 if float_width >= 4 => {
2575 let rd = FloatReg::new(inst.extract_bits(7, 5) as u32);
2577 let imm = inst.sp_load_imm(4);
2578
2579 Op::LoadFp(FpMemInst::new(4, rd, IntReg::new(2), imm)?)
2580 }
2581
2582 0b100_01 => {
2584 let rd = 8 + inst.extract_bits(7, 3) as u32;
2586
2587 let shamt =
2589 (inst.extract_bits(12, 1) << 5 | inst.extract_bits(2, 5)) as u32;
2590
2591 let mut mask = inst.extract_bits(2, 5) as u32;
2592 if inst.extract_bits(12, 1) == 1 {
2593 mask |= !0x1f;
2594 }
2595
2596 match inst.extract_bits(10, 2) {
2603 0 => Op::SrlI(ITypeInst::from_ops(
2604 IntReg::new(rd),
2605 IntReg::new(rd),
2606 shamt as i32,
2607 )), 1 => Op::SraI(ITypeInst::from_ops(
2609 IntReg::new(rd),
2610 IntReg::new(rd),
2611 shamt as i32,
2612 )), 2 => Op::AndI(ITypeInst::from_ops(
2614 IntReg::new(rd),
2615 IntReg::new(rd),
2616 mask as i32,
2617 )), 3 => {
2619 let op = inst.extract_bits(5, 2) | (inst.extract_bits(12, 1) << 2);
2620 let rs2 = 8 + inst.extract_bits(2, 3) as u32;
2621 let rtype = RTypeInst::from_ops(
2622 IntReg::new(rd),
2623 IntReg::new(rd),
2624 IntReg::new(rs2),
2625 );
2626
2627 match op {
2628 0 => Op::Sub(rtype), 1 => Op::Xor(rtype), 2 => Op::Or(rtype), 3 => Op::And(rtype), 4 if int_width >= 8 => Op::SubW(rtype), 5 if int_width >= 8 => Op::AddW(rtype), _ => return Err(InvalidSubop),
2635 }
2636 }
2637 _ => unreachable!(),
2638 }
2639 }
2640 0b100_10 => {
2641 let reg1 = inst.extract_bits(7, 5) as u32;
2643 let reg2 = inst.extract_bits(2, 5) as u32;
2644 let bit = inst.extract_bits(12, 1) as u32;
2645
2646 match (bit, reg1, reg2) {
2647 (link, rs1, 0) if rs1 != 0 => {
2648 Op::Jalr(ITypeInst::from_ops(
2650 IntReg::new(link),
2651 IntReg::new(rs1),
2652 0,
2653 ))
2654 }
2655 (0, rd, rs2) if rd != 0 && rs2 != 0 => {
2656 Op::AddI(ITypeInst::from_ops(IntReg::new(rd), IntReg::new(rs2), 0))
2658 }
2659 (1, 0, 0) => Op::Ebreak,
2660 (1, rd, rs2) if rs2 != 0 => {
2661 Op::Add(RTypeInst::from_ops(
2663 IntReg::new(rd),
2664 IntReg::new(rd),
2665 IntReg::new(rs2),
2666 ))
2667 }
2668 _ => return Err(InvalidSubop),
2669 }
2670 }
2671
2672 0b101_00 if float_width >= 8 => {
2674 let rd = FloatReg::new(8 + inst.extract_bits(2, 3) as u32);
2676 let rs1 = IntReg::new(8 + inst.extract_bits(7, 3) as u32);
2677
2678 let imm = inst.mem_imm(8);
2679 Op::StoreFp(FpMemInst::new(8, rd, rs1, imm)?)
2680 }
2681 0b101_01 => {
2682 Op::Jal(JTypeInst::new(IntReg::new(0), inst.cj_imm())?)
2684 }
2685 0b101_10 if float_width >= 8 => {
2687 let rd = FloatReg::new(inst.extract_bits(7, 5) as u32);
2689 let imm = inst.sp_load_imm(8);
2690
2691 Op::StoreFp(FpMemInst::new(8, rd, IntReg::new(2), imm)?)
2692 }
2693
2694 0b110_00 => {
2695 let rs2 = IntReg::new(8 + inst.extract_bits(2, 3) as u32);
2697 let rs1 = IntReg::new(8 + inst.extract_bits(7, 3) as u32);
2698
2699 let imm = inst.mem_imm(4);
2700 Op::Store(StoreTypeInst::new(4, rs2, rs1, imm)?)
2701 }
2702 0b110_01 => {
2703 let rs1 = IntReg::new(8 + inst.extract_bits(7, 3) as u32);
2705 Op::Beq(BTypeInst::new(rs1, IntReg::new(0), inst.cb_imm())?)
2706 }
2707 0b110_10 => {
2708 let rs2 = IntReg::new(inst.extract_bits(2, 5) as u32);
2710 let imm = inst.sp_store_imm(4);
2711
2712 Op::Store(StoreTypeInst::new(4, rs2, IntReg::new(2), imm)?)
2713 }
2714
2715 0b111_00 if int_width >= 8 => {
2716 let rs2 = IntReg::new(8 + inst.extract_bits(2, 3) as u32);
2718 let rs1 = IntReg::new(8 + inst.extract_bits(7, 3) as u32);
2719
2720 let imm = inst.mem_imm(8);
2721 Op::Store(StoreTypeInst::new(8, rs2, rs1, imm)?)
2722 }
2723 0b111_00 if float_width >= 4 => {
2724 let rd = FloatReg::new(8 + inst.extract_bits(2, 3) as u32);
2726 let rs1 = IntReg::new(8 + inst.extract_bits(7, 3) as u32);
2727
2728 let imm = inst.mem_imm(4);
2729 Op::StoreFp(FpMemInst::new(4, rd, rs1, imm)?)
2730 }
2731 0b111_01 => {
2732 let rs1 = IntReg::new(8 + inst.extract_bits(7, 3) as u32);
2734 Op::Bne(BTypeInst::new(rs1, IntReg::new(0), inst.cb_imm())?)
2735 }
2736 0b111_10 if int_width >= 8 => {
2737 let rs2 = IntReg::new(inst.extract_bits(2, 5) as u32);
2739 let imm = inst.sp_store_imm(8);
2740
2741 Op::Store(StoreTypeInst::new(8, rs2, IntReg::new(2), imm)?)
2742 }
2743 0b111_10 if float_width >= 4 => {
2744 let rd = FloatReg::new(inst.extract_bits(7, 5) as u32);
2746 let imm = inst.sp_load_imm(4);
2747
2748 Op::StoreFp(FpMemInst::new(4, rd, IntReg::new(2), imm)?)
2749 }
2750
2751 _ => return Err(InvalidOpcode),
2752 };
2753
2754 Ok(Instr::Rv16(decoded))
2755 }
2756 4 if bytes.len() >= 4 => {
2757 let inst = LittleEndian::read_u32(bytes);
2758 let inst = Instr32(inst);
2759
2760 let int_width = <Self::RegFile as RegFile>::Int::width();
2761 let float_width = <Self::RegFile as RegFile>::Float::width();
2762
2763 let decoded = match inst.opcode() >> 2 {
2764 0b00000 => Op::Load(LoadTypeInst::from_instr32(inst)?), 0b00001 if float_width > 0 => {
2766 let width = 1usize.wrapping_shl(inst.funct3());
2768 let fr = FloatReg::new(inst.rd());
2769 let rs1 = IntReg::new(inst.rs1());
2770 let imm = inst.i_imm();
2771
2772 if width < 4 || width > float_width {
2773 return Err(InvalidSubop);
2774 }
2775
2776 Op::LoadFp(FpMemInst::new(width, fr, rs1, imm)?)
2777 }
2778 0b00011 => {
2780 let itype = ITypeInst::new(inst)?;
2782
2783 match inst.funct3() {
2784 0b000 => Op::Fence(itype),
2785 0b001 => Op::FenceI(itype),
2786 _ => return Err(InvalidSubop),
2787 }
2788 }
2789 0b00100 => {
2790 let mut itype = ITypeInst::new(inst)?;
2792 match inst.funct3() {
2793 0b000 => Op::AddI(itype),
2794 0b010 => Op::SltI(itype),
2795 0b011 => Op::SltIU(itype),
2796 0b100 => Op::XorI(itype),
2797 0b110 => Op::OrI(itype),
2798 0b111 => Op::AndI(itype),
2799 0b001 => Op::SllI(itype), 0b101 => {
2801 if inst.0 & 0x40000000 == 0 {
2802 Op::SrlI(itype)
2803 } else {
2804 itype.inst.0 &= !0x40000000;
2806 Op::SraI(itype)
2807 }
2808 }
2809 _ => unreachable!(),
2810 }
2811 }
2812
2813 0b00101 => Op::Auipc(UTypeInst::from_instr32(inst)?), 0b00110 if int_width > 4 => {
2816 let mut itype = ITypeInst::new(inst)?;
2818 match inst.funct3() {
2819 0b000 => Op::AddIW(itype),
2820 0b001 => Op::SllIW(itype), 0b101 => {
2822 if inst.0 & 0x40000000 == 0 {
2823 Op::SrlIW(itype)
2824 } else {
2825 itype.inst.0 &= !0x40000000;
2827 Op::SraIW(itype)
2828 }
2829 }
2830 _ => return Err(InvalidSubop),
2831 }
2832 }
2833
2834 0b01000 => Op::Store(StoreTypeInst::from_instr32(inst)?), 0b01001 if float_width > 0 => {
2836 let width = 1usize.wrapping_shl(inst.funct3());
2838 let fr = FloatReg::new(inst.rs2());
2839 let rs1 = IntReg::new(inst.rs1());
2840 let imm = inst.s_imm();
2841
2842 if width < 4 || width > float_width {
2843 return Err(InvalidSubop);
2844 }
2845
2846 Op::StoreFp(FpMemInst::new(width, fr, rs1, imm)?)
2847 }
2848 0b01011 if Self::AtomicExtension::supported() => {
2850 let atomic = AtomicInst::new(inst)?;
2852
2853 match inst.funct7() >> 2 {
2855 0b00010 if inst.rs2() == 0 => Op::Lr(atomic),
2856 0b00011 => Op::Sc(atomic),
2857 0b00001 => Op::AmoSwap(atomic),
2858 0b00000 => Op::AmoAdd(atomic),
2859 0b00100 => Op::AmoXor(atomic),
2860 0b01100 => Op::AmoAnd(atomic),
2861 0b01000 => Op::AmoOr(atomic),
2862 0b10000 => Op::AmoMin(atomic),
2863 0b10100 => Op::AmoMax(atomic),
2864 0b11000 => Op::AmoMinU(atomic),
2865 0b11100 => Op::AmoMaxU(atomic),
2866 _ => return Err(InvalidSubop),
2867 }
2868 }
2869 0b01100 => {
2870 let rtype = RTypeIntInst::new(inst)?;
2872 match inst.funct7() {
2873 0b0000000 => match inst.funct3() {
2874 0b000 => Op::Add(rtype),
2875 0b001 => Op::Sll(rtype),
2876 0b010 => Op::Slt(rtype),
2877 0b011 => Op::SltU(rtype),
2878 0b100 => Op::Xor(rtype),
2879 0b101 => Op::Srl(rtype),
2880 0b110 => Op::Or(rtype),
2881 0b111 => Op::And(rtype),
2882 _ => unreachable!(),
2883 },
2884 0b0100000 => match inst.funct3() {
2885 0b000 => Op::Sub(rtype),
2886 0b101 => Op::Sra(rtype),
2887 _ => return Err(InvalidSubop),
2888 },
2889 0b0000001 if Self::MulDivExtension::supported() => {
2890 match inst.funct3() {
2891 0b000 => Op::Mul(rtype),
2892 0b001 => Op::MulH(rtype),
2893 0b010 => Op::MulHSU(rtype),
2894 0b011 => Op::MulHU(rtype),
2895 0b100 => Op::Div(rtype),
2896 0b101 => Op::DivU(rtype),
2897 0b110 => Op::Rem(rtype),
2898 0b111 => Op::RemU(rtype),
2899 _ => unreachable!(),
2900 }
2901 }
2902 _ => return Err(InvalidSubop),
2903 }
2904 }
2905 0b01101 => Op::Lui(UTypeInst::from_instr32(inst)?), 0b01110 if int_width > 4 => {
2907 let rtype = RTypeIntInst::new(inst)?;
2909 match inst.funct7() {
2910 0b0000000 => match inst.funct3() {
2911 0b000 => Op::AddW(rtype),
2912 0b001 => Op::SllW(rtype),
2913 0b101 => Op::SrlW(rtype),
2914 _ => return Err(InvalidSubop),
2915 },
2916 0b0100000 => match inst.funct3() {
2917 0b000 => Op::SubW(rtype),
2918 0b101 => Op::SraW(rtype),
2919 _ => return Err(InvalidSubop),
2920 },
2921 0b0000001 if Self::MulDivExtension::supported() => {
2922 match inst.funct3() {
2923 0b000 => Op::MulW(rtype),
2924 0b100 => Op::DivW(rtype),
2925 0b101 => Op::DivUW(rtype),
2926 0b110 => Op::RemW(rtype),
2927 0b111 => Op::RemUW(rtype),
2928 _ => return Err(InvalidSubop),
2929 }
2930 }
2931 _ => return Err(InvalidSubop),
2932 }
2933 }
2934 0b10000 if float_width > 0 => Op::Fmadd(FpMAddInst::from_instr32(inst)?), 0b10001 if float_width > 0 => Op::Fmsub(FpMAddInst::from_instr32(inst)?), 0b10010 if float_width > 0 => Op::Fnmsub(FpMAddInst::from_instr32(inst)?), 0b10011 if float_width > 0 => Op::Fnmadd(FpMAddInst::from_instr32(inst)?), 0b10100 if float_width > 0 => {
2939 match inst.fop() {
2941 0b00000 => Op::Fadd(RTypeFloatRoundInst::from_instr32(inst)?),
2942 0b00001 => Op::Fsub(RTypeFloatRoundInst::from_instr32(inst)?),
2943 0b00010 => Op::Fmul(RTypeFloatRoundInst::from_instr32(inst)?),
2944 0b00011 => Op::Fdiv(RTypeFloatRoundInst::from_instr32(inst)?),
2945 0b00100 => match inst.funct3() {
2946 0b000 => Op::Fsgnj(RTypeFloatInst::from_instr32(inst)?),
2947 0b001 => Op::Fsgnjn(RTypeFloatInst::from_instr32(inst)?),
2948 0b010 => Op::Fsgnjx(RTypeFloatInst::from_instr32(inst)?),
2949 _ => return Err(InvalidSubop),
2950 },
2951 0b00101 => match inst.funct3() {
2952 0b000 => Op::Fmin(RTypeFloatInst::from_instr32(inst)?),
2953 0b001 => Op::Fmax(RTypeFloatInst::from_instr32(inst)?),
2954 _ => return Err(InvalidSubop),
2955 },
2956 0b01000 => {
2957 let rd_width = match inst.fsize() {
2958 0b00 => 4,
2959 0b01 => 8,
2960 0b11 => 16,
2961 _ => return Err(InvalidSubop),
2962 };
2963 let rs1_width = match inst.rs2() {
2964 0b00000 => 4,
2965 0b00001 => 8,
2966 0b00011 => 16,
2967 _ => return Err(InvalidSubop),
2968 };
2969
2970 if rd_width > float_width
2971 || rs1_width > float_width
2972 || rd_width == rs1_width
2973 {
2974 return Err(InvalidSubop);
2975 }
2976
2977 let rd = FloatReg::new(inst.rd());
2978 let rs1 = FloatReg::new(inst.rs1());
2979 let rm = RoundMode::from_bits(inst.rm())?;
2980
2981 Op::Fcvt(FpCvtInst::new(
2982 rd,
2983 rd_width as u8,
2984 rs1,
2985 rs1_width as u8,
2986 rm,
2987 )?)
2988 }
2989 0b10100 => match inst.funct3() {
2990 0b000 => Op::Fle(RTypeFloatCmpInst::from_instr32(inst)?),
2991 0b001 => Op::Flt(RTypeFloatCmpInst::from_instr32(inst)?),
2992 0b010 => Op::Feq(RTypeFloatCmpInst::from_instr32(inst)?),
2993 _ => return Err(InvalidSubop),
2994 },
2995 0b01011 if inst.rs2() == 0 => {
2996 Op::Fsqrt(RTypeFloatRoundInst::from_instr32(inst)?)
2997 }
2998 0b11000 => {
2999 let rs1_width = match inst.fsize() {
3000 0b00 => 4,
3001 0b01 => 8,
3002 0b11 => 16,
3003 _ => return Err(InvalidSubop),
3004 };
3005
3006 if rs1_width > float_width {
3007 return Err(InvalidSubop);
3008 }
3009
3010 let rd = IntReg::new(inst.rd());
3011 let rs1 = FloatReg::new(inst.rs1());
3012 let rm = RoundMode::from_bits(inst.rm())?;
3013
3014 match inst.rs2() {
3015 0b00000 => Op::FcvtToInt(FpCvtToIntInst::new(
3016 rd,
3017 4,
3018 false,
3019 rs1,
3020 rs1_width as u8,
3021 rm,
3022 )?),
3023 0b00001 => Op::FcvtToInt(FpCvtToIntInst::new(
3024 rd,
3025 4,
3026 true,
3027 rs1,
3028 rs1_width as u8,
3029 rm,
3030 )?),
3031 0b00010 if int_width >= 8 => {
3032 Op::FcvtToInt(FpCvtToIntInst::new(
3033 rd,
3034 8,
3035 false,
3036 rs1,
3037 rs1_width as u8,
3038 rm,
3039 )?)
3040 }
3041 0b00011 if int_width >= 8 => Op::FcvtToInt(
3042 FpCvtToIntInst::new(rd, 8, true, rs1, rs1_width as u8, rm)?,
3043 ),
3044 _ => return Err(InvalidSubop),
3045 }
3046 }
3047 0b11010 => {
3048 let rd_width = match inst.fsize() {
3049 0b00 => 4,
3050 0b01 => 8,
3051 0b11 => 16,
3052 _ => return Err(InvalidSubop),
3053 };
3054
3055 if rd_width > float_width {
3056 return Err(InvalidSubop);
3057 }
3058
3059 let rd = FloatReg::new(inst.rd());
3060 let rs1 = IntReg::new(inst.rs1());
3061 let rm = RoundMode::from_bits(inst.rm())?;
3062
3063 match inst.rs2() {
3064 0b00000 => Op::FcvtFromInt(FpCvtFromIntInst::new(
3065 rd,
3066 rd_width as u8,
3067 rs1,
3068 4,
3069 false,
3070 rm,
3071 )?),
3072 0b00001 => Op::FcvtFromInt(FpCvtFromIntInst::new(
3073 rd,
3074 rd_width as u8,
3075 rs1,
3076 4,
3077 true,
3078 rm,
3079 )?),
3080 0b00010 if int_width >= 8 => {
3081 Op::FcvtFromInt(FpCvtFromIntInst::new(
3082 rd,
3083 rd_width as u8,
3084 rs1,
3085 8,
3086 false,
3087 rm,
3088 )?)
3089 }
3090 0b00011 if int_width >= 8 => {
3091 Op::FcvtFromInt(FpCvtFromIntInst::new(
3092 rd,
3093 rd_width as u8,
3094 rs1,
3095 8,
3096 true,
3097 rm,
3098 )?)
3099 }
3100 _ => return Err(InvalidSubop),
3101 }
3102 }
3103 0b11100 if inst.rs2() == 0 => match inst.funct3() {
3104 0b000 => Op::FmvToInt(FpMvToIntInst::from_instr32(inst)?),
3105 0b001 => Op::Fclass(FpClassInst::from_instr32(inst)?),
3106 _ => return Err(InvalidSubop),
3107 },
3108 0b11110 if inst.rs2() == 0 && inst.funct3() == 0 => {
3109 Op::FmvFromInt(FpMvFromIntInst::from_instr32(inst)?)
3110 }
3111 _ => return Err(InvalidSubop),
3112 }
3113 }
3114 0b11000 => {
3116 let btype = BTypeInst::from_instr32(inst)?;
3118 match inst.funct3() {
3119 0b000 => Op::Beq(btype),
3120 0b001 => Op::Bne(btype),
3121 0b100 => Op::Blt(btype),
3122 0b101 => Op::Bge(btype),
3123 0b110 => Op::BltU(btype),
3124 0b111 => Op::BgeU(btype),
3125 _ => return Err(InvalidSubop),
3126 }
3127 }
3128 0b11001 if inst.funct3() == 0b000 => Op::Jalr(ITypeIntInst::new(inst)?), 0b11011 => Op::Jal(JTypeInst::from_instr32(inst)?), 0b11100 => {
3131 match inst.funct3() {
3133 0b000 => {
3134 let funct12 = inst.0 >> 20;
3135
3136 match funct12 {
3137 f if (f & 0xfe0) == 0x120 => {
3141 Op::SfenceVma(RTypeIntInst::new(inst)?)
3142 }
3143 0x104 => Op::SfenceVm(RTypeIntInst::new(inst)?),
3144
3145 0x000 => Op::Ecall,
3146 0x001 => Op::Ebreak,
3147
3148 0x002 => Op::Uret,
3149 0x102 => Op::Sret,
3150 0x302 => Op::Mret,
3151
3152 0x105 => Op::Wfi,
3153 _ => return Err(InvalidSubop),
3154 }
3155 }
3156 0b001 => Op::Csrrw(CsrTypeInst::new(inst)?),
3157 0b010 => Op::Csrrs(CsrTypeInst::new(inst)?),
3158 0b011 => Op::Csrrc(CsrTypeInst::new(inst)?),
3159 0b101 => Op::CsrrwI(CsrITypeInst::new(inst)?),
3160 0b110 => Op::CsrrsI(CsrITypeInst::new(inst)?),
3161 0b111 => Op::CsrrcI(CsrITypeInst::new(inst)?),
3162 _ => return Err(InvalidSubop),
3163 }
3164 }
3165
3166 _ => return Err(InvalidOpcode),
3167 };
3168
3169 Ok(Instr::Rv32(decoded))
3170 }
3171 _ => Err(TooShort),
3172 }
3173 }
3174}
3175
3176#[derive(Copy, Clone, Debug)]
3177pub struct RiscVIMACDisassembler<RF: RegFile>(PhantomData<RF>);
3178
3179impl<RF: RegFile> RiscVDisassembler for RiscVIMACDisassembler<RF> {
3180 type RegFile = RF;
3181 type MulDivExtension = ExtensionSupported;
3182 type AtomicExtension = ExtensionSupported;
3183 type CompressedExtension = ExtensionSupported;
3184}