diff --git a/src/asm.rs b/src/asm.rs index d2ffbbbe0fe6ab8aafd32c2add32de7b0b9934a9..a41442f3fe1f996f220dec96d1b29c9ab4fcff6e 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -3,7 +3,7 @@ pub mod rv32i; pub mod rv64i; pub mod rvzicsr; -use crate::value::IntSigned; +use crate::value::{IntSigned, IntUnsigned}; use core::fmt; #[derive(Clone, Copy, PartialEq, Eq)] @@ -120,6 +120,21 @@ impl IType { | opcode.bits() as u32, ) } + pub fn new_csr_uimm( + opcode: Opcode, + funct3: Funct3, + rd: RegInteger, + csr: IntUnsigned<12, 0>, + uimm5: IntUnsigned<5, 0>, + ) -> Self { + Self( + (u32::try_from(csr).unwrap() << 20) + | (u32::try_from(uimm5).unwrap() << 15) + | (funct3.bits() as u32) << 12 + | ((rd as u32) << 7) + | opcode.bits() as u32, + ) + } pub const fn from_bits(bits: u32) -> Self { Self(bits) } @@ -144,6 +159,12 @@ impl IType { pub const fn shamt5(self) -> IntSigned<5, 0> { IntSigned::new_lsb(self.0 >> 20) } + pub const fn csr(self) -> IntUnsigned<12, 0> { + IntUnsigned::new_lsb(self.0 >> 20) + } + pub const fn uimm5(self) -> IntUnsigned<5, 0> { + IntUnsigned::new_lsb((self.0 >> 15) & 0b1_1111) + } } impl fmt::Debug for IType { diff --git a/src/asm/rv32i.rs b/src/asm/rv32i.rs index db053e306ca1eaa4641d48a3cee014c984f37e7b..386978d222c54e837c29efe9f28f26a9c23f2803 100644 --- a/src/asm/rv32i.rs +++ b/src/asm/rv32i.rs @@ -13,7 +13,7 @@ const OPCODE_LUI: Opcode = Opcode::from_bits(0b011_0111); const OPCODE_BRANCH: Opcode = Opcode::from_bits(0b110_0011); const OPCODE_JALR: Opcode = Opcode::from_bits(0b110_0111); const OPCODE_JAL: Opcode = Opcode::from_bits(0b110_1111); -const OPCODE_SYSTEM: Opcode = Opcode::from_bits(0b111_0011); +pub(crate) const OPCODE_SYSTEM: Opcode = Opcode::from_bits(0b111_0011); const FUNCT3_JALR_JALR: Funct3 = Funct3::from_bits(0b000); const FUNCT3_BRANCH_BEQ: Funct3 = Funct3::from_bits(0b000); diff --git a/src/asm/rvzicsr.rs b/src/asm/rvzicsr.rs index 348d0d30e1f1262df4eff6d86eda4fe18676c723..cbd779cc4742d22cc4df099b12e3583dfc5b9036 100644 --- a/src/asm/rvzicsr.rs +++ b/src/asm/rvzicsr.rs @@ -1,7 +1,10 @@ // csrrw, csrrs, csrrc // csrriw, csrrsi, csrrci -use super::Funct3; +use super::{Funct3, IType, RegInteger}; +use crate::asm::rv32i::OPCODE_SYSTEM; +use crate::value::IntUnsigned; +use core::fmt; const FUNCT3_SYSTEM_CSRRW: Funct3 = Funct3::from_bits(0b001); const FUNCT3_SYSTEM_CSRRS: Funct3 = Funct3::from_bits(0b010); @@ -9,3 +12,122 @@ const FUNCT3_SYSTEM_CSRRC: Funct3 = Funct3::from_bits(0b011); const FUNCT3_SYSTEM_CSRRWI: Funct3 = Funct3::from_bits(0b101); const FUNCT3_SYSTEM_CSRRSI: Funct3 = Funct3::from_bits(0b110); const FUNCT3_SYSTEM_CSRRCI: Funct3 = Funct3::from_bits(0b111); + +#[derive(Clone, Copy)] +pub enum InsnRVZicsr { + Csrrw(IType), + Csrrs(IType), + Csrrc(IType), + Csrrwi(IType), + Csrrsi(IType), + Csrrci(IType), +} + +impl fmt::Debug for InsnRVZicsr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Csrrw(i) => write!(f, "csrrw {:?}, {:?}, {:?}", i.rd(), i.csr(), i.rs1()), + Self::Csrrs(i) => write!(f, "csrri {:?}, {:?}, {:?}", i.rd(), i.csr(), i.rs1()), + Self::Csrrc(i) => write!(f, "csrrc {:?}, {:?}, {:?}", i.rd(), i.csr(), i.rs1()), + Self::Csrrwi(i) => write!(f, "csrrc {:?}, {:?}, {:?}", i.rd(), i.csr(), i.uimm5()), + Self::Csrrsi(i) => write!(f, "csrrc {:?}, {:?}, {:?}", i.rd(), i.csr(), i.uimm5()), + Self::Csrrci(i) => write!(f, "csrrc {:?}, {:?}, {:?}", i.rd(), i.csr(), i.uimm5()), + } + } +} + +pub fn csrrw(rd: RegInteger, csr: impl Into>, rs: RegInteger) -> T +where + InsnRVZicsr: Into, +{ + InsnRVZicsr::Csrrw(IType::new( + OPCODE_SYSTEM, + FUNCT3_SYSTEM_CSRRW, + rd, + rs, + csr.into().signed(), + )) + .into() +} + +pub fn csrrs(rd: RegInteger, csr: impl Into>, rs: RegInteger) -> T +where + InsnRVZicsr: Into, +{ + InsnRVZicsr::Csrrs(IType::new( + OPCODE_SYSTEM, + FUNCT3_SYSTEM_CSRRS, + rd, + rs, + csr.into().signed(), + )) + .into() +} + +pub fn csrrc(rd: RegInteger, csr: impl Into>, rs: RegInteger) -> T +where + InsnRVZicsr: Into, +{ + InsnRVZicsr::Csrrc(IType::new( + OPCODE_SYSTEM, + FUNCT3_SYSTEM_CSRRC, + rd, + rs, + csr.into().signed(), + )) + .into() +} + +pub fn csrrwi( + rd: RegInteger, + csr: impl Into>, + uimm: impl Into>, +) -> T +where + InsnRVZicsr: Into, +{ + InsnRVZicsr::Csrrwi(IType::new_csr_uimm( + OPCODE_SYSTEM, + FUNCT3_SYSTEM_CSRRWI, + rd, + csr.into(), + uimm.into(), + )) + .into() +} + +pub fn csrrsi( + rd: RegInteger, + csr: impl Into>, + uimm: impl Into>, +) -> T +where + InsnRVZicsr: Into, +{ + InsnRVZicsr::Csrrsi(IType::new_csr_uimm( + OPCODE_SYSTEM, + FUNCT3_SYSTEM_CSRRSI, + rd, + csr.into(), + uimm.into(), + )) + .into() +} + +pub fn csrrci( + rd: RegInteger, + csr: impl Into>, + uimm: impl Into>, +) -> T +where + InsnRVZicsr: Into, +{ + InsnRVZicsr::Csrrci(IType::new_csr_uimm( + OPCODE_SYSTEM, + FUNCT3_SYSTEM_CSRRCI, + rd, + csr.into(), + uimm.into(), + )) + .into() +} diff --git a/src/value/int.rs b/src/value/int.rs index b79b43e568e8b8c488be11db536d4bb32491da51..042318366edabf30f5f15fcc8b291e6269ef355c 100644 --- a/src/value/int.rs +++ b/src/value/int.rs @@ -35,6 +35,12 @@ impl fmt::Debug for IntSigned { } } +impl fmt::Debug for IntUnsigned { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.value.fmt(f) + } +} + impl SignExtend for IntSigned { fn sext(self) -> IntSigned { let mut ans = self.value; @@ -100,6 +106,14 @@ impl TryFrom> for u32 { } } +impl TryFrom> for u32 { + type Error = TryFromIntError; + + fn try_from(src: IntUnsigned) -> Result { + Ok(src.value) + } +} + impl TryFrom for IntSigned { type Error = TryFromIntError;