diff --git a/src/instruction_set.rs b/src/instruction_set.rs index 8bcbbbe..939096b 100644 --- a/src/instruction_set.rs +++ b/src/instruction_set.rs @@ -1,7 +1,22 @@ +use std::fmt::Display; + use crate::{csr::ControlStatusRegisters, processor::Processor}; #[derive(Debug)] -pub enum Exception {} +pub enum Exception { + UnimplementedInstruction(u32), +} + +impl Display for Exception { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::UnimplementedInstruction(instuction) => f.write_fmt(format_args!( + "The given instruction is not yet implemented {:#034b}", + instuction.to_le() + )), + } + } +} pub trait InstructionSet: Sized { type RegisterType; diff --git a/src/instructions/csr.rs b/src/instructions/csr.rs index e020d41..26f7355 100644 --- a/src/instructions/csr.rs +++ b/src/instructions/csr.rs @@ -1,23 +1,12 @@ -use std::ops::Deref; - -pub(super) struct Csr(u16); +pub(super) struct Csr; impl Csr { const MASK: u32 = u32::from_le(0b_1111111_11111_00000_000_00000_0000000); const RSHIFT: usize = 20; -} - -impl From for Csr { - fn from(value: u32) -> Self { - Self(((value & Self::MASK) >> Self::RSHIFT) as u16) - } -} - -impl Deref for Csr { - type Target = u16; - fn deref(&self) -> &Self::Target { - &self.0 + #[inline] + pub(super) const fn decode(value: u32) -> u16 { + ((value & Self::MASK) >> Self::RSHIFT) as u16 } } @@ -27,8 +16,8 @@ mod test { use pretty_assertions::assert_eq; #[test] - fn from_u32() { + fn decode_u32() { let instruction = u32::from_le(0b_1111111_11111_01100_101_11000_0110111); - assert_eq!(*Csr::from(instruction), 4095); + assert_eq!(Csr::decode(instruction), 4095); } } diff --git a/src/instructions/csr_imm.rs b/src/instructions/csr_imm.rs index 9c31184..41bde3d 100644 --- a/src/instructions/csr_imm.rs +++ b/src/instructions/csr_imm.rs @@ -1,23 +1,12 @@ -use std::ops::Deref; - -pub(super) struct CsrImm(u8); +pub(super) struct CsrImm; impl CsrImm { const MASK: u32 = u32::from_le(0b_0000000_00000_11111_000_00000_0000000); const RSHIFT: usize = 15; -} - -impl From for CsrImm { - fn from(value: u32) -> Self { - Self(((value & Self::MASK) >> Self::RSHIFT) as u8) - } -} - -impl Deref for CsrImm { - type Target = u8; - fn deref(&self) -> &Self::Target { - &self.0 + #[inline] + pub(super) const fn decode(value: u32) -> u8 { + ((value & Self::MASK) >> Self::RSHIFT) as u8 } } @@ -27,8 +16,8 @@ mod test { use pretty_assertions::assert_eq; #[test] - fn from_u32() { + fn decode_u32() { let instruction = u32::from_le(0b_0100100_01010_01100_101_01000_0010011); - assert_eq!(*CsrImm::from(instruction), 12); + assert_eq!(CsrImm::decode(instruction), 12); } } diff --git a/src/instructions/funct3.rs b/src/instructions/funct3.rs index af164c6..f5174d9 100644 --- a/src/instructions/funct3.rs +++ b/src/instructions/funct3.rs @@ -1,23 +1,12 @@ -use std::ops::Deref; - -pub(super) struct Funct3(u8); +pub(super) struct Funct3; impl Funct3 { const MASK: u32 = u32::from_le(0b_0000000_00000_00000_111_00000_0000000); const RSHIFT: usize = 12; -} - -impl From for Funct3 { - fn from(value: u32) -> Self { - Self(((value & Self::MASK) >> Self::RSHIFT) as u8) - } -} - -impl Deref for Funct3 { - type Target = u8; - fn deref(&self) -> &Self::Target { - &self.0 + #[inline] + pub(super) const fn decode(value: u32) -> u8 { + ((value & Self::MASK) >> Self::RSHIFT) as u8 } } @@ -27,8 +16,8 @@ mod test { use pretty_assertions::assert_eq; #[test] - fn from_u32() { + fn decode_u32() { let instruction = u32::from_le(0b_0100100_01000_01000_101_00000_0010011); - assert_eq!(*Funct3::from(instruction), 0b_101); + assert_eq!(Funct3::decode(instruction), 0b_101); } } diff --git a/src/instructions/funct6.rs b/src/instructions/funct6.rs index 76888b9..1060676 100644 --- a/src/instructions/funct6.rs +++ b/src/instructions/funct6.rs @@ -1,25 +1,14 @@ -use std::ops::Deref; - /// On 64-bit architectures, bit 25 is part of the shift amount - hence rather than having a funct7, /// we have a funct6 -pub(super) struct Funct6(u8); +pub(super) struct Funct6; impl Funct6 { const MASK: u32 = u32::from_le(0b_1111110_00000_00000_000_00000_0000000); const RSHIFT: usize = 26; -} - -impl From for Funct6 { - fn from(value: u32) -> Self { - Self(((value & Self::MASK) >> Self::RSHIFT) as u8) - } -} - -impl Deref for Funct6 { - type Target = u8; - fn deref(&self) -> &Self::Target { - &self.0 + #[inline] + pub(super) const fn decode(value: u32) -> u8 { + ((value & Self::MASK) >> Self::RSHIFT) as u8 } } @@ -29,8 +18,8 @@ mod test { use pretty_assertions::assert_eq; #[test] - fn from_u32() { + fn decode_u32() { let instruction = u32::from_le(0b_0100100_01000_01000_101_00000_0010011); - assert_eq!(*Funct6::from(instruction), 0b_010010); + assert_eq!(Funct6::decode(instruction), 0b_010010); } } diff --git a/src/instructions/funct7.rs b/src/instructions/funct7.rs index a57ba35..e5f7fa1 100644 --- a/src/instructions/funct7.rs +++ b/src/instructions/funct7.rs @@ -1,23 +1,12 @@ -use std::ops::Deref; - -pub(super) struct Funct7(u8); +pub(super) struct Funct7; impl Funct7 { const MASK: u32 = u32::from_le(0b_1111111_00000_00000_000_00000_0000000); const RSHIFT: usize = 25; -} - -impl From for Funct7 { - fn from(value: u32) -> Self { - Self(((value & Self::MASK) >> Self::RSHIFT) as u8) - } -} - -impl Deref for Funct7 { - type Target = u8; - fn deref(&self) -> &Self::Target { - &self.0 + #[inline] + pub(super) const fn decode(value: u32) -> u8 { + ((value & Self::MASK) >> Self::RSHIFT) as u8 } } @@ -27,8 +16,8 @@ mod test { use pretty_assertions::assert_eq; #[test] - fn from_u32() { + fn decode_u32() { let instruction = u32::from_le(0b_0100100_01000_01000_101_00000_0010011); - assert_eq!(*Funct7::from(instruction), 0b_0100100); + assert_eq!(Funct7::decode(instruction), 0b_0100100); } } diff --git a/src/instructions/immi.rs b/src/instructions/immi.rs index 38017c5..88f5912 100644 --- a/src/instructions/immi.rs +++ b/src/instructions/immi.rs @@ -1,23 +1,12 @@ -use std::ops::Deref; - -pub(super) struct ImmI(i16); +pub(super) struct ImmI; impl ImmI { const MASK: u32 = u32::from_le(0b_1111111_11111_00000_000_00000_0000000); const RSHIFT: usize = 20; -} - -impl From for ImmI { - fn from(value: u32) -> Self { - Self((((value & Self::MASK) as i32) >> Self::RSHIFT) as i16) - } -} - -impl Deref for ImmI { - type Target = i16; - fn deref(&self) -> &Self::Target { - &self.0 + #[inline] + pub(super) const fn decode(value: u32) -> i16 { + (((value & Self::MASK) as i32) >> Self::RSHIFT) as i16 } } @@ -29,26 +18,26 @@ mod test { use super::*; #[test] - fn from_u32() { + fn decode_u32() { let instruction = u32::from_le(0b_0100100_01010_01100_101_01000_0010011); - assert_eq!(*ImmI::from(instruction), i16::from_le(0b_0100100_01010)); + assert_eq!(ImmI::decode(instruction), i16::from_le(0b_0100100_01010)); } #[test] - fn from_u12_negative_one() { + fn decode_u32_negative_one() { let instruction = u32::from_le(0b_1111111_11111_01100_101_01000_0010011); - assert_eq!(*ImmI::from(instruction), -1); + assert_eq!(ImmI::decode(instruction), -1); } #[test] - fn from_u12_min() { + fn decode_u32_min() { let instruction = u32::from_le(0b_1000000_00000_01100_101_01000_0010011); - assert_eq!(*ImmI::from(instruction), i12::MIN); + assert_eq!(ImmI::decode(instruction), i12::MIN); } #[test] - fn from_u12_max() { + fn decode_u32_max() { let instruction = u32::from_le(0b_0111111_11111_01100_101_01000_0010011); - assert_eq!(*ImmI::from(instruction), i12::MAX); + assert_eq!(ImmI::decode(instruction), i12::MAX); } } diff --git a/src/instructions/immu.rs b/src/instructions/immu.rs index 21bd4f2..5a16e68 100644 --- a/src/instructions/immu.rs +++ b/src/instructions/immu.rs @@ -1,23 +1,12 @@ -use std::ops::Deref; - -pub(super) struct ImmU(i32); +pub(super) struct ImmU; impl ImmU { pub(super) const MASK: u32 = u32::from_le(0b_1111111_11111_11111_111_00000_0000000); pub(super) const RSHIFT: usize = 12; -} - -impl From for ImmU { - fn from(value: u32) -> Self { - Self(((value & Self::MASK) >> Self::RSHIFT) as i32) - } -} - -impl Deref for ImmU { - type Target = i32; - fn deref(&self) -> &Self::Target { - &self.0 + #[inline] + pub(super) const fn decode(value: u32) -> i32 { + ((value & Self::MASK) >> Self::RSHIFT) as i32 } } @@ -27,10 +16,10 @@ mod test { use pretty_assertions::assert_eq; #[test] - fn from_u32() { + fn decode_u32() { let instruction = u32::from_le(0b_0100100_01010_01100_101_11000_0110111); assert_eq!( - *ImmU::from(instruction), + ImmU::decode(instruction), i32::from_le(0b_0100100_01010_01100_101) ); } diff --git a/src/instructions/impl_instruction_set.rs b/src/instructions/impl_instruction_set.rs index a6ac95a..daa87e1 100644 --- a/src/instructions/impl_instruction_set.rs +++ b/src/instructions/impl_instruction_set.rs @@ -13,7 +13,7 @@ impl InstructionSet for Instruction { type CSRType = CSR32; fn decode(raw_instruction: u32) -> Result { - Ok(raw_instruction.into()) + raw_instruction.try_into() } fn execute( diff --git a/src/instructions/mod.rs b/src/instructions/mod.rs index abfbdec..ffa8288 100644 --- a/src/instructions/mod.rs +++ b/src/instructions/mod.rs @@ -19,7 +19,7 @@ use self::{ immu::ImmU, rd::Rd, rs1::Rs1, rs2::Rs2, shamt::Shamt, simmi::SImmI, }; -use crate::registers::Register; +use crate::{instruction_set::Exception, registers::Register}; /// An representation of different instructions. /// @@ -444,228 +444,216 @@ pub(super) enum Instruction { CSRRCI { rd: Register, csr: u16, imm: u8 }, } -impl From for Instruction { - fn from(value: u32) -> Self { - match Instruction::op_code(value) { +impl Instruction { + const fn decode(value: u32) -> Result { + let instruction = match Instruction::op_code(value) { 0b_0110111 => Instruction::LUI { - rd: *Rd::from(value), - imm: *ImmU::from(value), + rd: Rd::decode(value), + imm: ImmU::decode(value), }, 0b_0010111 => Instruction::AUIPC { - rd: *Rd::from(value), - imm: *ImmU::from(value), + rd: Rd::decode(value), + imm: ImmU::decode(value), }, - 0b_0010011 => match *Funct3::from(value) { + 0b_0010011 => match Funct3::decode(value) { 0b_000 => Instruction::ADDI { - rd: *Rd::from(value), - rs1: *Rs1::from(value), - imm: *ImmI::from(value), + rd: Rd::decode(value), + rs1: Rs1::decode(value), + imm: ImmI::decode(value), }, 0b_001 => Instruction::SLLI { - rd: *Rd::from(value), - rs1: *Rs1::from(value), - shamt: *Shamt::from(value), + rd: Rd::decode(value), + rs1: Rs1::decode(value), + shamt: Shamt::decode(value), }, 0b_010 => Instruction::SLTI { - rd: *Rd::from(value), - rs1: *Rs1::from(value), - imm: *ImmI::from(value), + rd: Rd::decode(value), + rs1: Rs1::decode(value), + imm: ImmI::decode(value), }, 0b_011 => Instruction::SLTIU { - rd: *Rd::from(value), - rs1: *Rs1::from(value), - imm: *ImmI::from(value), + rd: Rd::decode(value), + rs1: Rs1::decode(value), + imm: ImmI::decode(value), }, 0b_100 => Instruction::XORI { - rd: *Rd::from(value), - rs1: *Rs1::from(value), - imm: *ImmI::from(value), + rd: Rd::decode(value), + rs1: Rs1::decode(value), + imm: ImmI::decode(value), }, - 0b_101 => match *Funct6::from(value) { + 0b_101 => match Funct6::decode(value) { 0b_000000 => Instruction::SRLI { - rd: *Rd::from(value), - rs1: *Rs1::from(value), - shamt: *Shamt::from(value), + rd: Rd::decode(value), + rs1: Rs1::decode(value), + shamt: Shamt::decode(value), }, 0b_010000 => Instruction::SRAI { - rd: *Rd::from(value), - rs1: *Rs1::from(value), - shamt: *Shamt::from(value), + rd: Rd::decode(value), + rs1: Rs1::decode(value), + shamt: Shamt::decode(value), }, - _ => unimplemented!( - "The given instruction is not yet implemented {:#034b}", - value.to_le() - ), + _ => return Err(Exception::UnimplementedInstruction(value)), }, 0b_110 => Instruction::ORI { - rd: *Rd::from(value), - rs1: *Rs1::from(value), - imm: *ImmI::from(value), + rd: Rd::decode(value), + rs1: Rs1::decode(value), + imm: ImmI::decode(value), }, 0b_111 => Instruction::ANDI { - rd: *Rd::from(value), - rs1: *Rs1::from(value), - imm: *ImmI::from(value), + rd: Rd::decode(value), + rs1: Rs1::decode(value), + imm: ImmI::decode(value), }, - _ => unimplemented!( - "The given instruction is not yet implemented {:#034b}", - value.to_le() - ), + _ => return Err(Exception::UnimplementedInstruction(value)), }, - 0b_0110011 => match (*Funct3::from(value), *Funct7::from(value)) { + 0b_0110011 => match (Funct3::decode(value), Funct7::decode(value)) { (0b_000, 0b_0000000) => Instruction::ADD { - rd: *Rd::from(value), - rs1: *Rs1::from(value), - rs2: *Rs2::from(value), + rd: Rd::decode(value), + rs1: Rs1::decode(value), + rs2: Rs2::decode(value), }, (0b_000, 0b_0100000) => Instruction::SUB { - rd: *Rd::from(value), - rs1: *Rs1::from(value), - rs2: *Rs2::from(value), + rd: Rd::decode(value), + rs1: Rs1::decode(value), + rs2: Rs2::decode(value), }, (0b_001, 0b_0000000) => Instruction::SLL { - rd: *Rd::from(value), - rs1: *Rs1::from(value), - rs2: *Rs2::from(value), + rd: Rd::decode(value), + rs1: Rs1::decode(value), + rs2: Rs2::decode(value), }, (0b_010, 0b_0000000) => Instruction::SLT { - rd: *Rd::from(value), - rs1: *Rs1::from(value), - rs2: *Rs2::from(value), + rd: Rd::decode(value), + rs1: Rs1::decode(value), + rs2: Rs2::decode(value), }, (0b_011, 0b_0000000) => Instruction::SLTU { - rd: *Rd::from(value), - rs1: *Rs1::from(value), - rs2: *Rs2::from(value), + rd: Rd::decode(value), + rs1: Rs1::decode(value), + rs2: Rs2::decode(value), }, (0b_100, 0b_0000000) => Instruction::XOR { - rd: *Rd::from(value), - rs1: *Rs1::from(value), - rs2: *Rs2::from(value), + rd: Rd::decode(value), + rs1: Rs1::decode(value), + rs2: Rs2::decode(value), }, (0b_101, 0b_0000000) => Instruction::SRL { - rd: *Rd::from(value), - rs1: *Rs1::from(value), - rs2: *Rs2::from(value), + rd: Rd::decode(value), + rs1: Rs1::decode(value), + rs2: Rs2::decode(value), }, (0b_101, 0b_0100000) => Instruction::SRA { - rd: *Rd::from(value), - rs1: *Rs1::from(value), - rs2: *Rs2::from(value), + rd: Rd::decode(value), + rs1: Rs1::decode(value), + rs2: Rs2::decode(value), }, (0b_110, 0b_0100000) => Instruction::OR { - rd: *Rd::from(value), - rs1: *Rs1::from(value), - rs2: *Rs2::from(value), + rd: Rd::decode(value), + rs1: Rs1::decode(value), + rs2: Rs2::decode(value), }, (0b_111, 0b_0100000) => Instruction::AND { - rd: *Rd::from(value), - rs1: *Rs1::from(value), - rs2: *Rs2::from(value), + rd: Rd::decode(value), + rs1: Rs1::decode(value), + rs2: Rs2::decode(value), }, - _ => unimplemented!( - "The given instruction is not yet implemented {:#034b}", - value.to_le() - ), + _ => return Err(Exception::UnimplementedInstruction(value)), }, - 0b_0000011 => match *Funct3::from(value) { + 0b_0000011 => match Funct3::decode(value) { 0b_000 => Instruction::LB { - rd: *Rd::from(value), - rs1: *Rs1::from(value), - offset: *ImmI::from(value), + rd: Rd::decode(value), + rs1: Rs1::decode(value), + offset: ImmI::decode(value), }, 0b_001 => Instruction::LH { - rd: *Rd::from(value), - rs1: *Rs1::from(value), - offset: *ImmI::from(value), + rd: Rd::decode(value), + rs1: Rs1::decode(value), + offset: ImmI::decode(value), }, 0b_010 => Instruction::LW { - rd: *Rd::from(value), - rs1: *Rs1::from(value), - offset: *ImmI::from(value), + rd: Rd::decode(value), + rs1: Rs1::decode(value), + offset: ImmI::decode(value), }, 0b_100 => Instruction::LBU { - rd: *Rd::from(value), - rs1: *Rs1::from(value), - offset: *ImmI::from(value), + rd: Rd::decode(value), + rs1: Rs1::decode(value), + offset: ImmI::decode(value), }, 0b_101 => Instruction::LHU { - rd: *Rd::from(value), - rs1: *Rs1::from(value), - offset: *ImmI::from(value), + rd: Rd::decode(value), + rs1: Rs1::decode(value), + offset: ImmI::decode(value), }, - _ => unimplemented!( - "The given instruction is not yet implemented {:#034b}", - value.to_le() - ), + _ => return Err(Exception::UnimplementedInstruction(value)), }, - 0b_0100011 => match *Funct3::from(value) { + 0b_0100011 => match Funct3::decode(value) { 0b_000 => Instruction::SB { - rs1: *Rs1::from(value), - rs2: *Rs2::from(value), - offset: *SImmI::from(value), + rs1: Rs1::decode(value), + rs2: Rs2::decode(value), + offset: SImmI::decode(value), }, 0b_001 => Instruction::SH { - rs1: *Rs1::from(value), - rs2: *Rs2::from(value), - offset: *SImmI::from(value), + rs1: Rs1::decode(value), + rs2: Rs2::decode(value), + offset: SImmI::decode(value), }, 0b_010 => Instruction::SW { - rs1: *Rs1::from(value), - rs2: *Rs2::from(value), - offset: *SImmI::from(value), + rs1: Rs1::decode(value), + rs2: Rs2::decode(value), + offset: SImmI::decode(value), }, - _ => unimplemented!( - "The given instruction is not yet implemented {:#034b}", - value.to_le() - ), + _ => return Err(Exception::UnimplementedInstruction(value)), }, - 0b_1110011 => match *Funct3::from(value) { + 0b_1110011 => match Funct3::decode(value) { 0b_001 => Instruction::CSRRW { - rd: *Rd::from(value), - rs1: *Rs1::from(value), - csr: *Csr::from(value), + rd: Rd::decode(value), + rs1: Rs1::decode(value), + csr: Csr::decode(value), }, 0b_010 => Instruction::CSRRS { - rd: *Rd::from(value), - rs1: *Rs1::from(value), - csr: *Csr::from(value), + rd: Rd::decode(value), + rs1: Rs1::decode(value), + csr: Csr::decode(value), }, 0b_011 => Instruction::CSRRC { - rd: *Rd::from(value), - rs1: *Rs1::from(value), - csr: *Csr::from(value), + rd: Rd::decode(value), + rs1: Rs1::decode(value), + csr: Csr::decode(value), }, 0b_101 => Instruction::CSRRWI { - rd: *Rd::from(value), - imm: *CsrImm::from(value), - csr: *Csr::from(value), + rd: Rd::decode(value), + imm: CsrImm::decode(value), + csr: Csr::decode(value), }, 0b_110 => Instruction::CSRRSI { - rd: *Rd::from(value), - imm: *CsrImm::from(value), - csr: *Csr::from(value), + rd: Rd::decode(value), + imm: CsrImm::decode(value), + csr: Csr::decode(value), }, 0b_111 => Instruction::CSRRCI { - rd: *Rd::from(value), - imm: *CsrImm::from(value), - csr: *Csr::from(value), + rd: Rd::decode(value), + imm: CsrImm::decode(value), + csr: Csr::decode(value), }, - _ => unimplemented!( - "The given instruction is not yet implemented {:#034b}", - value.to_le() - ), + _ => return Err(Exception::UnimplementedInstruction(value)), }, - _ => unimplemented!( - "The given instruction is not yet implemented {:#034b}", - value.to_le() - ), - } + _ => return Err(Exception::UnimplementedInstruction(value)), + }; + Ok(instruction) + } +} + +impl TryFrom for Instruction { + type Error = Exception; + fn try_from(value: u32) -> Result { + Instruction::decode(value) } } impl Instruction { - fn op_code(value: u32) -> u8 { + #[inline] + const fn op_code(value: u32) -> u8 { (value & OPP_MASK) as u8 } } @@ -677,6 +665,12 @@ mod test { use crate::{instructions::Instruction, registers::Register}; use pretty_assertions::assert_eq; + impl Instruction { + fn from(value: u32) -> Self { + Self::try_from(value).expect("Unimplemented") + } + } + #[test] fn lui_from_i32() { assert_eq!( diff --git a/src/instructions/rd.rs b/src/instructions/rd.rs index 4221e4d..afa14ae 100644 --- a/src/instructions/rd.rs +++ b/src/instructions/rd.rs @@ -1,25 +1,14 @@ -use std::ops::Deref; - use crate::registers::Register; -pub(super) struct Rd(Register); +pub(super) struct Rd; impl Rd { const MASK: u32 = u32::from_le(0b_0000000_00000_00000_000_11111_0000000); const RSHIFT: usize = 7; -} - -impl From for Rd { - fn from(value: u32) -> Self { - Self(Register::from(((value & Self::MASK) >> Self::RSHIFT) as u8)) - } -} - -impl Deref for Rd { - type Target = Register; - fn deref(&self) -> &Self::Target { - &self.0 + #[inline] + pub(super) const fn decode(value: u32) -> Register { + Register::const_from(((value & Self::MASK) >> Self::RSHIFT) as u8) } } @@ -29,8 +18,8 @@ mod test { use pretty_assertions::assert_eq; #[test] - fn from_u32() { + fn decode_u32() { let instruction = u32::from_le(0b_0100100_01000_01000_101_01000_0010011); - assert_eq!(*Rd::from(instruction), Register::S0); + assert_eq!(Rd::decode(instruction), Register::S0); } } diff --git a/src/instructions/rs1.rs b/src/instructions/rs1.rs index 3cea5cf..c4e1db0 100644 --- a/src/instructions/rs1.rs +++ b/src/instructions/rs1.rs @@ -1,25 +1,14 @@ -use std::ops::Deref; - use crate::registers::Register; -pub(super) struct Rs1(Register); +pub(super) struct Rs1; impl Rs1 { const MASK: u32 = u32::from_le(0b_0000000_00000_11111_000_00000_0000000); const RSHIFT: usize = 15; -} - -impl From for Rs1 { - fn from(value: u32) -> Self { - Self(Register::from(((value & Self::MASK) >> Self::RSHIFT) as u8)) - } -} - -impl Deref for Rs1 { - type Target = Register; - fn deref(&self) -> &Self::Target { - &self.0 + #[inline] + pub(super) const fn decode(value: u32) -> Register { + Register::const_from(((value & Self::MASK) >> Self::RSHIFT) as u8) } } @@ -29,8 +18,8 @@ mod test { use pretty_assertions::assert_eq; #[test] - fn from_u32() { + fn decode_u32() { let instruction = u32::from_le(0b_0100100_01010_01100_101_01000_0010011); - assert_eq!(*Rs1::from(instruction), Register::A2); + assert_eq!(Rs1::decode(instruction), Register::A2); } } diff --git a/src/instructions/rs2.rs b/src/instructions/rs2.rs index 7c68572..6d8b96f 100644 --- a/src/instructions/rs2.rs +++ b/src/instructions/rs2.rs @@ -1,25 +1,14 @@ -use std::ops::Deref; - use crate::registers::Register; -pub(super) struct Rs2(Register); +pub(super) struct Rs2; impl Rs2 { const MASK: u32 = u32::from_le(0b_0000000_11111_00000_000_00000_0000000); const RSHIFT: usize = 20; -} - -impl From for Rs2 { - fn from(value: u32) -> Self { - Self(Register::from(((value & Self::MASK) >> Self::RSHIFT) as u8)) - } -} - -impl Deref for Rs2 { - type Target = Register; - fn deref(&self) -> &Self::Target { - &self.0 + #[inline] + pub(super) const fn decode(value: u32) -> Register { + Register::const_from(((value & Self::MASK) >> Self::RSHIFT) as u8) } } @@ -29,8 +18,8 @@ mod test { use pretty_assertions::assert_eq; #[test] - fn from_u32() { + fn decode_u32() { let instruction = u32::from_le(0b_0100100_01010_01100_101_01000_0010011); - assert_eq!(*Rs2::from(instruction), Register::A0); + assert_eq!(Rs2::decode(instruction), Register::A0); } } diff --git a/src/instructions/shamt.rs b/src/instructions/shamt.rs index 9c13a96..f64cc54 100644 --- a/src/instructions/shamt.rs +++ b/src/instructions/shamt.rs @@ -1,23 +1,11 @@ -use std::ops::Deref; - -pub(super) struct Shamt(u8); +pub(super) struct Shamt; impl Shamt { const MASK: u32 = u32::from_le(0b_0000001_11111_00000_000_00000_0000000); const RSHIFT: usize = 20; -} - -impl From for Shamt { - fn from(value: u32) -> Self { - Self(((value & Self::MASK) >> Self::RSHIFT) as u8) - } -} - -impl Deref for Shamt { - type Target = u8; - fn deref(&self) -> &Self::Target { - &self.0 + pub(super) const fn decode(value: u32) -> u8 { + ((value & Self::MASK) >> Self::RSHIFT) as u8 } } @@ -27,11 +15,11 @@ mod test { use pretty_assertions::assert_eq; #[test] - fn from_u32() { + fn decode_u32() { let instruction = u32::from_le(0b_0100100_00110_01100_101_01000_0010011); - assert_eq!(*Shamt::from(instruction), 6); + assert_eq!(Shamt::decode(instruction), 6); // For 64 bit architectures, bit 25 is intepreted as part of the shift amount let instruction = u32::from_le(0b_0100101_00110_01100_101_01000_0010011); - assert_eq!(*Shamt::from(instruction), 38); + assert_eq!(Shamt::decode(instruction), 38); } } diff --git a/src/instructions/simmi.rs b/src/instructions/simmi.rs index f95267e..12d8324 100644 --- a/src/instructions/simmi.rs +++ b/src/instructions/simmi.rs @@ -1,28 +1,15 @@ -use std::ops::Deref; - -pub(super) struct SImmI(i16); +pub(super) struct SImmI; impl SImmI { const U_MASK: u32 = u32::from_le(0b_1111111_00000_00000_000_00000_0000000); const L_MASK: u32 = u32::from_le(0b_0000000_00000_00000_000_11111_0000000); const U_RSHIFT: usize = 20; const L_RSHIFT: usize = 7; -} - -impl From for SImmI { - fn from(value: u32) -> Self { - Self( - ((((value & Self::U_MASK) as i32) >> Self::U_RSHIFT) - + (((value & Self::L_MASK) as i32) >> Self::L_RSHIFT)) as i16, - ) - } -} - -impl Deref for SImmI { - type Target = i16; - fn deref(&self) -> &Self::Target { - &self.0 + #[inline] + pub(super) const fn decode(value: u32) -> i16 { + ((((value & Self::U_MASK) as i32) >> Self::U_RSHIFT) + + (((value & Self::L_MASK) as i32) >> Self::L_RSHIFT)) as i16 } } @@ -34,26 +21,26 @@ mod test { use super::*; #[test] - fn from_u32() { + fn decode_u32() { let instruction = u32::from_le(0b_0100100_01010_01100_101_01010_0010011); - assert_eq!(*SImmI::from(instruction), i16::from_le(0b_0100100_01010)); + assert_eq!(SImmI::decode(instruction), i16::from_le(0b_0100100_01010)); } #[test] - fn from_u12_negative_one() { + fn decode_u32_negative_one() { let instruction = u32::from_le(0b_1111111_11111_01100_101_11111_0010011); - assert_eq!(*SImmI::from(instruction), -1); + assert_eq!(SImmI::decode(instruction), -1); } #[test] - fn from_u12_min() { + fn decode_u32_min() { let instruction = u32::from_le(0b_1000000_01000_01100_101_00000_0010011); - assert_eq!(*SImmI::from(instruction), i12::MIN); + assert_eq!(SImmI::decode(instruction), i12::MIN); } #[test] - fn from_u12_max() { + fn decode_u32_max() { let instruction = u32::from_le(0b_0111111_11011_01100_101_11111_0010011); - assert_eq!(*SImmI::from(instruction), i12::MAX); + assert_eq!(SImmI::decode(instruction), i12::MAX); } } diff --git a/src/registers.rs b/src/registers.rs index 4e2e031..1f367c9 100644 --- a/src/registers.rs +++ b/src/registers.rs @@ -203,8 +203,8 @@ pub(super) enum Register { T6 = 31, } -impl From for Register { - fn from(value: u8) -> Register { +impl Register { + pub(crate) const fn const_from(value: u8) -> Register { match value & 0b_0001_1111 { 0 => Register::ZERO, 1 => Register::RA, @@ -238,11 +238,17 @@ impl From for Register { 29 => Register::T4, 30 => Register::T5, 31 => Register::T6, - _ => unreachable!("Already masked the value"), + _ => panic!("Unreachable: Already masked the value"), } } } +impl From for Register { + fn from(value: u8) -> Register { + Self::const_from(value) + } +} + impl std::ops::Index for Registers { type Output = T;