From 5ad6f6cb5e4357ae92f5ee7dd1190b0f8c5915df Mon Sep 17 00:00:00 2001 From: Filipe Rodrigues Date: Fri, 8 Jan 2021 16:15:28 +0000 Subject: [PATCH] Added `basic::shift` instruction. --- dcb-exe/src/exe/inst/basic.rs | 14 +++ dcb-exe/src/exe/inst/basic/shift.rs | 69 +++++++++++++++ dcb-exe/src/exe/inst/basic/shift/imm.rs | 113 ++++++++++++++++++++++++ dcb-exe/src/exe/inst/basic/shift/reg.rs | 112 +++++++++++++++++++++++ 4 files changed, 308 insertions(+) create mode 100644 dcb-exe/src/exe/inst/basic/shift.rs create mode 100644 dcb-exe/src/exe/inst/basic/shift/imm.rs create mode 100644 dcb-exe/src/exe/inst/basic/shift/reg.rs diff --git a/dcb-exe/src/exe/inst/basic.rs b/dcb-exe/src/exe/inst/basic.rs index 7833e92..c1c20e6 100644 --- a/dcb-exe/src/exe/inst/basic.rs +++ b/dcb-exe/src/exe/inst/basic.rs @@ -10,6 +10,7 @@ pub mod jmp; pub mod load; pub mod lui; pub mod mult; +pub mod shift; pub mod store; pub mod sys; @@ -19,6 +20,9 @@ use crate::exe::inst::InstFmt; /// All basic instructions #[derive(PartialEq, Eq, Clone, Copy, Debug)] pub enum Inst { + /// Shift + Shift(shift::Inst), + /// Store Store(store::Inst), @@ -49,6 +53,10 @@ impl Decodable for Inst { fn decode(raw: Self::Raw) -> Option { let inst = #[bitmatch] match raw { + // Shift + "000000_?????_ttttt_ddddd_iiiii_0000ff" => Self::Shift(shift::Inst::decode_from(shift::imm::Raw { t, d, i, f })?), + "000000_sssss_ttttt_ddddd_?????_0001ff" => Self::Shift(shift::Inst::decode_from(shift::reg::Raw { s, t, d, f })?), + // Jump "00001p_iiiii_iiiii_iiiii_iiiii_iiiiii" => Self::Jmp(jmp::Inst::decode_from(jmp::imm::Raw { p, i })?), "000000_sssss_?????_ddddd_?????_00100f" => Self::Jmp(jmp::Inst::decode_from(jmp::reg::Raw { s, d, f })?), @@ -91,6 +99,10 @@ impl Encodable for Inst { #[bitmatch::bitmatch] fn encode(&self) -> u32 { match self { + Self::Shift(inst) => match inst.encode() { + shift::Raw::Imm(shift::imm::Raw { t, d, i, f }) => bitpack!("000000_?????_ttttt_ddddd_iiiii_0000ff"), + shift::Raw::Reg(shift::reg::Raw { s, t, d, f }) => bitpack!("000000_sssss_ttttt_ddddd_?????_0001ff"), + }, Self::Jmp(inst) => match inst.encode() { jmp::Raw::Imm(jmp::imm::Raw { p, i }) => bitpack!("00001p_iiiii_iiiii_iiiii_iiiii_iiiiii"), jmp::Raw::Reg(jmp::reg::Raw { s, d, f }) => bitpack!("000000_sssss_?????_ddddd_?????_00100f"), @@ -133,6 +145,7 @@ impl InstFmt for Inst { Self::Alu(inst) => inst.mnemonic(), Self::Lui(inst) => inst.mnemonic(), Self::Sys(inst) => inst.mnemonic(), + Self::Shift(inst) => inst.mnemonic(), } } @@ -145,6 +158,7 @@ impl InstFmt for Inst { Self::Alu(inst) => inst.fmt(pos, bytes, f), Self::Lui(inst) => inst.fmt(pos, bytes, f), Self::Sys(inst) => inst.fmt(pos, bytes, f), + Self::Shift(inst) => inst.fmt(pos, bytes, f), } } } diff --git a/dcb-exe/src/exe/inst/basic/shift.rs b/dcb-exe/src/exe/inst/basic/shift.rs new file mode 100644 index 0000000..f78d26e --- /dev/null +++ b/dcb-exe/src/exe/inst/basic/shift.rs @@ -0,0 +1,69 @@ +//! Shift instruction + + +// Modules +pub mod imm; +pub mod reg; + +// Imports +use crate::exe::inst::{ + basic::{Decodable, Encodable}, + InstFmt, +}; + +/// Raw representation +#[derive(PartialEq, Eq, Clone, Copy, Debug)] +#[derive(derive_more::From)] +pub enum Raw { + /// Immediate + Imm(imm::Raw), + + /// Register + Reg(reg::Raw), +} + +/// Alu register instructions +#[derive(PartialEq, Eq, Clone, Copy, Debug)] +pub enum Inst { + /// Immediate + Imm(imm::Inst), + + /// Register + Reg(reg::Inst), +} + +impl Decodable for Inst { + type Raw = Raw; + + fn decode(raw: Self::Raw) -> Option { + match raw { + Raw::Imm(raw) => Some(Self::Imm(imm::Inst::decode(raw)?)), + Raw::Reg(raw) => Some(Self::Reg(reg::Inst::decode(raw)?)), + } + } +} + +impl Encodable for Inst { + fn encode(&self) -> Self::Raw { + match self { + Self::Imm(inst) => Raw::Imm(inst.encode()), + Self::Reg(inst) => Raw::Reg(inst.encode()), + } + } +} + +impl InstFmt for Inst { + fn mnemonic(&self) -> &'static str { + match self { + Self::Imm(inst) => inst.mnemonic(), + Self::Reg(inst) => inst.mnemonic(), + } + } + + fn fmt(&self, pos: crate::Pos, bytes: &[u8], f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + Self::Imm(inst) => inst.fmt(pos, bytes, f), + Self::Reg(inst) => inst.fmt(pos, bytes, f), + } + } +} diff --git a/dcb-exe/src/exe/inst/basic/shift/imm.rs b/dcb-exe/src/exe/inst/basic/shift/imm.rs new file mode 100644 index 0000000..f88b3c6 --- /dev/null +++ b/dcb-exe/src/exe/inst/basic/shift/imm.rs @@ -0,0 +1,113 @@ +//! Shift immediate instructions + +// Imports +use crate::exe::inst::{ + basic::{Decodable, Encodable}, + InstFmt, Register, +}; +use int_conv::{Truncated, ZeroExtended}; + +/// Shift immediate instruction kind +#[derive(PartialEq, Eq, Clone, Copy, Debug)] +pub enum Kind { + /// Left logical + LeftLogical, + + /// Right logical + RightLogical, + + /// Right arithmetic + RightArithmetic, +} + +impl Kind { + /// Returns this kind's mnemonic + #[must_use] + pub const fn mnemonic(self) -> &'static str { + match self { + Self::LeftLogical => "sll", + Self::RightLogical => "srl", + Self::RightArithmetic => "sra", + } + } +} + +/// Raw representation +#[derive(PartialEq, Eq, Clone, Copy, Debug)] +pub struct Raw { + /// Rt + pub t: u32, + + /// Rd + pub d: u32, + + /// Immediate + pub i: u32, + + /// Function (lower 2 bits) + pub f: u32, +} + +/// Shift immediate instructions +#[derive(PartialEq, Eq, Clone, Copy, Debug)] +pub struct Inst { + /// Destination register + pub dst: Register, + + /// Lhs argument + pub lhs: Register, + + /// Rhs argument + pub rhs: u8, + + /// Kind + pub kind: Kind, +} + +impl Decodable for Inst { + type Raw = Raw; + + fn decode(raw: Self::Raw) -> Option { + let kind = match raw.f { + 0x0 => Kind::LeftLogical, + 0x2 => Kind::RightLogical, + 0x3 => Kind::RightArithmetic, + _ => return None, + }; + + Some(Self { + dst: Register::new(raw.d)?, + lhs: Register::new(raw.t)?, + rhs: raw.i.truncated(), + kind, + }) + } +} + +impl Encodable for Inst { + fn encode(&self) -> Self::Raw { + let f = match self.kind { + Kind::LeftLogical => 0x0, + Kind::RightLogical => 0x2, + Kind::RightArithmetic => 0x3, + }; + let t = self.lhs.idx(); + let d = self.dst.idx(); + let i = self.rhs.zero_extended(); + + Raw { t, d, i, f } + } +} + +impl InstFmt for Inst { + fn mnemonic(&self) -> &'static str { + self.kind.mnemonic() + } + + fn fmt(&self, _pos: crate::Pos, _bytes: &[u8], f: &mut std::fmt::Formatter) -> std::fmt::Result { + let Self { dst, lhs, rhs, kind } = self; + let mnemonic = kind.mnemonic(); + + write!(f, "{mnemonic} {dst}, {lhs}, {rhs}") + } +} diff --git a/dcb-exe/src/exe/inst/basic/shift/reg.rs b/dcb-exe/src/exe/inst/basic/shift/reg.rs new file mode 100644 index 0000000..3d6c130 --- /dev/null +++ b/dcb-exe/src/exe/inst/basic/shift/reg.rs @@ -0,0 +1,112 @@ +//! Shift register instructions + +// Imports +use crate::exe::inst::{ + basic::{Decodable, Encodable}, + InstFmt, Register, +}; + +/// Shift register instruction kind +#[derive(PartialEq, Eq, Clone, Copy, Debug)] +pub enum Kind { + /// Left logical + LeftLogical, + + /// Right logical + RightLogical, + + /// Right arithmetic + RightArithmetic, +} + +impl Kind { + /// Returns this kind's mnemonic + #[must_use] + pub const fn mnemonic(self) -> &'static str { + match self { + Self::LeftLogical => "sllv", + Self::RightLogical => "srlv", + Self::RightArithmetic => "srav", + } + } +} + +/// Raw representation +#[derive(PartialEq, Eq, Clone, Copy, Debug)] +pub struct Raw { + /// Rs + pub s: u32, + + /// Rt + pub t: u32, + + /// Rd + pub d: u32, + + /// Func (lower 4 bits) + pub f: u32, +} + +/// Shift register instructions +#[derive(PartialEq, Eq, Clone, Copy, Debug)] +pub struct Inst { + /// Destination register + pub dst: Register, + + /// Lhs argument + pub lhs: Register, + + /// Rhs argument + pub rhs: Register, + + /// Kind + pub kind: Kind, +} + +impl Decodable for Inst { + type Raw = Raw; + + fn decode(raw: Self::Raw) -> Option { + let kind = match raw.f { + 0x0 => Kind::LeftLogical, + 0x2 => Kind::RightLogical, + 0x3 => Kind::RightArithmetic, + _ => return None, + }; + + Some(Self { + dst: Register::new(raw.d)?, + lhs: Register::new(raw.t)?, + rhs: Register::new(raw.s)?, + kind, + }) + } +} +impl Encodable for Inst { + fn encode(&self) -> Raw { + let f = match self.kind { + Kind::LeftLogical => 0x0, + Kind::RightLogical => 0x2, + Kind::RightArithmetic => 0x3, + }; + + let d = self.dst.idx(); + let t = self.lhs.idx(); + let s = self.rhs.idx(); + + Raw { s, t, d, f } + } +} + +impl InstFmt for Inst { + fn mnemonic(&self) -> &'static str { + self.kind.mnemonic() + } + + fn fmt(&self, _pos: crate::Pos, _bytes: &[u8], f: &mut std::fmt::Formatter) -> std::fmt::Result { + let Self { dst, lhs, rhs, kind } = self; + let mnemonic = kind.mnemonic(); + + write!(f, "{mnemonic} {dst}, {lhs}, {rhs}") + } +}