Added pseudo::shift_assign instructions.

Fixed `pseudo::store` instruction being implemented wrong.
This commit is contained in:
Filipe Rodrigues 2021-01-11 17:47:52 +00:00
parent a00fd15d49
commit 9cc7d81e8e
3 changed files with 120 additions and 11 deletions

View File

@ -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<Item = basic::Inst> + Clone) -> Option<Self> {
// 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),

View File

@ -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<Item = basic::Inst> + Clone) -> Option<Self> {
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}")
}
}

View File

@ -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<Item = basic::Inst> + Clone) -> Option<Self> {
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::<i32>()).as_unsigned()),
kind: store.kind,