diff --git a/dcb-exe/src/exe/inst/pseudo.rs b/dcb-exe/src/exe/inst/pseudo.rs index a59b467..5bebf04 100644 --- a/dcb-exe/src/exe/inst/pseudo.rs +++ b/dcb-exe/src/exe/inst/pseudo.rs @@ -11,6 +11,7 @@ pub mod load; pub mod load_imm; pub mod move_reg; pub mod nop; +pub mod shift_assign; pub mod store; // Imports @@ -23,6 +24,9 @@ pub enum Inst { /// Alu self-assign AluAssign(alu_assign::Inst), + /// Shift self-assign + ShiftAssign(shift_assign::Inst), + /// Load immediate LoadImm(load_imm::Inst), @@ -45,14 +49,14 @@ pub enum Inst { impl Decodable for Inst { #[rustfmt::skip] fn decode(insts: impl Iterator + Clone) -> Option { - // Note: Order is important - load_imm ::Inst::decode(insts.clone()).map(Self::LoadImm ) - .or_else( || alu_assign::Inst::decode(insts.clone()).map(Self::AluAssign)) - .or_else( || nop ::Inst::decode(insts.clone()).map(Self::Nop )) - .or_else( || jmp ::Inst::decode(insts.clone()).map(Self::Jmp )) - .or_else( || load ::Inst::decode(insts.clone()).map(Self::Load )) - .or_else( || store ::Inst::decode(insts.clone()).map(Self::Store )) - .or_else(move || move_reg ::Inst::decode( insts ).map(Self::MoveReg )) + load_imm ::Inst::decode(insts.clone()).map(Self::LoadImm ) + .or_else( || nop ::Inst::decode(insts.clone()).map(Self::Nop )) // Note: Nop must come before `shift_assign` + .or_else( || alu_assign ::Inst::decode(insts.clone()).map(Self::AluAssign )) + .or_else( || shift_assign::Inst::decode(insts.clone()).map(Self::ShiftAssign)) + .or_else( || jmp ::Inst::decode(insts.clone()).map(Self::Jmp )) + .or_else( || load ::Inst::decode(insts.clone()).map(Self::Load )) + .or_else( || store ::Inst::decode(insts.clone()).map(Self::Store )) + .or_else(move || move_reg ::Inst::decode( insts ).map(Self::MoveReg )) } } @@ -60,6 +64,7 @@ impl InstSize for Inst { fn size(&self) -> usize { match self { Self::AluAssign(inst) => inst.size(), + Self::ShiftAssign(inst) => inst.size(), Self::LoadImm(inst) => inst.size(), Self::Nop(inst) => inst.size(), Self::MoveReg(inst) => inst.size(), @@ -74,6 +79,7 @@ impl InstFmt for Inst { fn mnemonic(&self) -> &'static str { match self { Self::AluAssign(inst) => inst.mnemonic(), + Self::ShiftAssign(inst) => inst.mnemonic(), Self::LoadImm(inst) => inst.mnemonic(), Self::Nop(inst) => inst.mnemonic(), Self::MoveReg(inst) => inst.mnemonic(), @@ -86,6 +92,7 @@ impl InstFmt for Inst { fn fmt(&self, pos: crate::Pos, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { Self::AluAssign(inst) => inst.fmt(pos, f), + Self::ShiftAssign(inst) => inst.fmt(pos, f), Self::LoadImm(inst) => inst.fmt(pos, f), Self::Nop(inst) => inst.fmt(pos, f), Self::MoveReg(inst) => inst.fmt(pos, f), diff --git a/dcb-exe/src/exe/inst/pseudo/shift_assign.rs b/dcb-exe/src/exe/inst/pseudo/shift_assign.rs new file mode 100644 index 0000000..5270eef --- /dev/null +++ b/dcb-exe/src/exe/inst/pseudo/shift_assign.rs @@ -0,0 +1,102 @@ +//! Shift self-assign instructions + +// Imports +use super::Decodable; +use crate::exe::inst::{ + basic::{self, shift}, + InstFmt, InstSize, Register, +}; +use std::{convert::TryInto, fmt}; + +/// Shift assign kind +#[derive(PartialEq, Eq, Clone, Copy, Debug)] +pub enum Kind { + /// Immediate + Imm { + /// Kind + kind: shift::imm::Kind, + + /// Argument + rhs: u8, + }, + + /// Register + Reg { + /// Kind + kind: shift::reg::Kind, + + /// Argument + rhs: Register, + }, +} + +impl Kind { + /// Returns this kind's mnemonic + #[must_use] + pub const fn mnemonic(self) -> &'static str { + match self { + Self::Imm { kind, .. } => kind.mnemonic(), + Self::Reg { kind, .. } => kind.mnemonic(), + } + } + + /// Returns a displayable with the value of this kind + #[must_use] + pub fn value_fmt(self) -> impl fmt::Display { + dcb_util::DisplayWrapper::new(move |f| match self { + Self::Imm { rhs, .. } => write!(f, "{:#x}", rhs), + Self::Reg { rhs, .. } => write!(f, "{}", rhs), + }) + } +} + +/// Shift self-assign instructions +/// +/// Alias for +/// ```mips +/// [shift] $dst, $dst, ... +/// ``` +#[derive(PartialEq, Eq, Clone, Copy, Debug)] +pub struct Inst { + /// Destination and source register + pub dst: Register, + + /// Kind + pub kind: Kind, +} + +impl Decodable for Inst { + fn decode(mut insts: impl Iterator + Clone) -> Option { + match insts.next()?.try_into().ok()? { + shift::Inst::Imm(shift::imm::Inst { dst, lhs, rhs, kind }) if dst == lhs => Some(Self { + dst, + kind: Kind::Imm { kind, rhs }, + }), + shift::Inst::Reg(shift::reg::Inst { dst, lhs, rhs, kind }) if dst == lhs => Some(Self { + dst, + kind: Kind::Reg { kind, rhs }, + }), + _ => None, + } + } +} + +impl InstSize for Inst { + fn size(&self) -> usize { + 4 + } +} + +impl InstFmt for Inst { + fn mnemonic(&self) -> &'static str { + self.kind.mnemonic() + } + + fn fmt(&self, _pos: crate::Pos, f: &mut std::fmt::Formatter) -> std::fmt::Result { + let Self { dst, kind } = self; + let mnemonic = kind.mnemonic(); + let value = kind.value_fmt(); + + write!(f, "{mnemonic} {dst}, {value}") + } +} diff --git a/dcb-exe/src/exe/inst/pseudo/store.rs b/dcb-exe/src/exe/inst/pseudo/store.rs index d53ee4a..0d3e1fe 100644 --- a/dcb-exe/src/exe/inst/pseudo/store.rs +++ b/dcb-exe/src/exe/inst/pseudo/store.rs @@ -13,7 +13,7 @@ use super::Decodable; /// /// Alias for /// ```mips -/// lui $dst, {hi} +/// lui $at, {hi} /// s* $dst, {lo}($at) /// ``` #[derive(PartialEq, Eq, Clone, Copy, Debug)] @@ -31,8 +31,8 @@ pub struct Inst { impl Decodable for Inst { fn decode(mut insts: impl Iterator + Clone) -> Option { let inst = match insts.next()? { - basic::Inst::Lui(lui) => match insts.next()? { - basic::Inst::Store(store) if store.dst == lui.dst && store.src == Register::At => Self { + basic::Inst::Lui(lui) if lui.dst == Register::At => match insts.next()? { + basic::Inst::Store(store) if store.src == Register::At => Self { dst: lui.dst, target: Pos((u32::join(0, lui.value).as_signed() + store.offset.sign_extended::()).as_unsigned()), kind: store.kind,