| 817 | } |
| 818 | |
| 819 | fn decode_system(word: u32) -> Result<DecodedInsn, VmError> { |
| 820 | // Check for SFENCE.VMA first (opcode 0x73, funct3=0, but with specific pattern) |
| 821 | // SFENCE.VMA: imm[11:0]=0b0001_0001_0000, rs1 and rs2 can be non-zero |
| 822 | if funct3(word) == 0 { |
| 823 | let imm = field(word, 31, 20); |
| 824 | match imm { |
| 825 | 0 => Ok(DecodedInsn::Ecall), |
| 826 | 1 => Ok(DecodedInsn::Ebreak), |
| 827 | 0x302 => Ok(DecodedInsn::Mret), |
| 828 | 0x102 => Ok(DecodedInsn::Sret), |
| 829 | 0x120 => Ok(DecodedInsn::SfenceVma), // SFENCE.VMA |
| 830 | 0x105 => Ok(DecodedInsn::Wfi), // WFI |
| 831 | _ => Err(VmError::IllegalInstruction(word)), |
| 832 | } |
| 833 | } else { |
| 834 | // CSR instructions |
| 835 | Ok(DecodedInsn::Csr { |
| 836 | funct3: funct3(word), |
| 837 | rd: rd(word), |
| 838 | rs1_uimm: rs1(word), // for CSRRWI/CSRRSI/CSRRCI this is the uimm[4:0] |
| 839 | csr: field(word, 31, 20) as u16, |
| 840 | }) |
| 841 | } |
| 842 | } |
| 843 | |
| 844 | fn fmac(word: u32, op: FMacOp) -> DecodedInsn { |
| 845 | DecodedInsn::FMac { |