Skip to content

Commit

Permalink
Make decode function const
Browse files Browse the repository at this point in the history
  • Loading branch information
Johnabell committed Sep 5, 2023
1 parent 4769260 commit 6eb6f7a
Show file tree
Hide file tree
Showing 15 changed files with 247 additions and 367 deletions.
17 changes: 16 additions & 1 deletion src/instruction_set.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
23 changes: 6 additions & 17 deletions src/instructions/csr.rs
Original file line number Diff line number Diff line change
@@ -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<u32> 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
}
}

Expand All @@ -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);
}
}
23 changes: 6 additions & 17 deletions src/instructions/csr_imm.rs
Original file line number Diff line number Diff line change
@@ -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<u32> 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
}
}

Expand All @@ -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);
}
}
23 changes: 6 additions & 17 deletions src/instructions/funct3.rs
Original file line number Diff line number Diff line change
@@ -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<u32> 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
}
}

Expand All @@ -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);
}
}
23 changes: 6 additions & 17 deletions src/instructions/funct6.rs
Original file line number Diff line number Diff line change
@@ -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<u32> 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
}
}

Expand All @@ -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);
}
}
23 changes: 6 additions & 17 deletions src/instructions/funct7.rs
Original file line number Diff line number Diff line change
@@ -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<u32> 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
}
}

Expand All @@ -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);
}
}
35 changes: 12 additions & 23 deletions src/instructions/immi.rs
Original file line number Diff line number Diff line change
@@ -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<u32> 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
}
}

Expand All @@ -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);
}
}
23 changes: 6 additions & 17 deletions src/instructions/immu.rs
Original file line number Diff line number Diff line change
@@ -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<u32> 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
}
}

Expand All @@ -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)
);
}
Expand Down
Loading

0 comments on commit 6eb6f7a

Please sign in to comment.