Added dcb_exe::exe::inst::basic::{Decodable, Encodable}.

This commit is contained in:
2021-01-08 14:33:49 +00:00
parent 48e29ec83c
commit 7c196ec4a9
16 changed files with 175 additions and 206 deletions

View File

@@ -19,7 +19,6 @@ pub use pos::Pos;
//pub use func::Func;
// Imports
use self::inst::Inst;
use dcb_bytes::{ByteArray, Bytes};
use dcb_io::GameFile;
use std::io::{Read, Seek, Write};

View File

@@ -16,6 +16,8 @@ pub use reg::Register;
use crate::Pos;
use dcb_util::NextFromBytes;
use self::basic::Decodable;
/// An assembler instruction
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub enum Inst {

View File

@@ -6,7 +6,6 @@
// Modules
pub mod alu;
pub mod cond;
//pub mod iter;
pub mod jmp;
pub mod load;
pub mod lui;
@@ -40,24 +39,24 @@ pub enum Inst {
Sys(sys::Inst),
}
impl Inst {
/// Decodes an instruction
#[must_use]
impl Decodable for Inst {
type Raw = u32;
#[bitmatch::bitmatch]
#[allow(clippy::many_single_char_names)] // `bitmatch` can only output single character names.
pub fn decode(raw: u32) -> Option<Self> {
fn decode(raw: Self::Raw) -> Option<Self> {
let inst = #[bitmatch]
match raw {
// Jump
"00001p_iiiii_iiiii_iiiii_iiiii_iiiiii" => Self::Jmp(jmp::Inst::decode(jmp::imm::Raw { p, i })?),
"000000_sssss_?????_ddddd_?????_00100f" => Self::Jmp(jmp::Inst::decode(jmp::reg::Raw { s, d, f })?),
"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 })?),
"000ppp_sssss_ttttt_iiiii_iiiii_iiiiii" => Self::Cond(cond::Inst::decode(cond::Raw { p, s, t, i })?),
"001111_?????_ttttt_iiiii_iiiii_iiiiii" => Self::Lui(lui::Inst::decode(lui::Raw { t, i })?),
// Alu
"000000_sssss_ttttt_ddddd_?????_10ffff" => Self::Alu(alu::Inst::decode(alu::reg::Raw { s, t, d, f })?),
"001ppp_sssss_ttttt_iiiii_iiiii_iiiiii" => Self::Alu(alu::Inst::decode(alu::imm::Raw { p, s, t, i })?),
"000000_sssss_ttttt_ddddd_?????_10ffff" => Self::Alu(alu::Inst::decode_from(alu::reg::Raw { s, t, d, f })?),
"001ppp_sssss_ttttt_iiiii_iiiii_iiiiii" => Self::Alu(alu::Inst::decode_from(alu::imm::Raw { p, s, t, i })?),
// Syscall
"000000_ccccc_ccccc_ccccc_ccccc_00110f" => Self::Sys(sys::Inst::decode(sys::Raw { c, f })?),
@@ -84,11 +83,11 @@ impl Inst {
Some(inst)
}
}
/// Encodes this instruction
#[must_use]
impl Encodable for Inst {
#[bitmatch::bitmatch]
pub fn encode(self) -> u32 {
fn encode(&self) -> u32 {
match self {
Self::Jmp(inst) => match inst.encode() {
jmp::Raw::Imm(jmp::imm::Raw { p, i }) => bitpack!("00001p_iiiii_iiiii_iiiii_iiiii_iiiiii"),
@@ -121,3 +120,26 @@ impl Inst {
}
}
}
/// A decodable basic instruction
pub trait Decodable: Sized {
/// 'Raw' type to parse from
type Raw;
/// Decodes this instruction
#[must_use]
fn decode(raw: Self::Raw) -> Option<Self>;
/// Decodes this instruction from any type that can be converted into the raw form
#[must_use]
fn decode_from(raw: impl Into<Self::Raw>) -> Option<Self> {
Self::decode(raw.into())
}
}
/// An encodable basic instruction
pub trait Encodable: Decodable {
/// Encodes this instruction
#[must_use]
fn encode(&self) -> Self::Raw;
}

View File

@@ -4,6 +4,9 @@
pub mod imm;
pub mod reg;
// Imports
use crate::exe::inst::basic::{Decodable, Encodable};
/// Raw representation
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
#[derive(derive_more::From)]
@@ -26,19 +29,19 @@ pub enum Inst {
Reg(reg::Inst),
}
impl Inst {
/// Decodes this instruction
#[must_use]
pub fn decode(raw: impl Into<Raw>) -> Option<Self> {
match raw.into() {
impl Decodable for Inst {
type Raw = Raw;
fn decode(raw: Self::Raw) -> Option<Self> {
match raw {
Raw::Imm(raw) => Some(Self::Imm(imm::Inst::decode(raw)?)),
Raw::Reg(raw) => Some(Self::Reg(reg::Inst::decode(raw)?)),
}
}
}
/// Encodes this instruction
#[must_use]
pub fn encode(self) -> 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()),

View File

@@ -1,7 +1,10 @@
//! Alu immediate instructions
// Imports
use crate::exe::inst::Register;
use crate::exe::inst::{
basic::{Decodable, Encodable},
Register,
};
use dcb_util::SignedHex;
use int_conv::{Signed, Truncated, ZeroExtended};
use std::fmt;
@@ -98,10 +101,10 @@ pub struct Inst {
pub kind: Kind,
}
impl Inst {
/// Decodes this instruction
#[must_use]
pub fn decode(raw: Raw) -> Option<Self> {
impl Decodable for Inst {
type Raw = Raw;
fn decode(raw: Self::Raw) -> Option<Self> {
#[rustfmt::skip]
let kind = match raw.p {
0x0 => Kind::Add (raw.i.truncated::<u16>().as_signed()),
@@ -120,10 +123,10 @@ impl Inst {
kind,
})
}
}
/// Encodes this instruction
#[must_use]
pub fn encode(self) -> Raw {
impl Encodable for Inst {
fn encode(&self) -> Self::Raw {
#[rustfmt::skip]
let (p, i) = match self.kind {
Kind::Add (rhs) => (0x0, rhs.as_unsigned().zero_extended::<u32>()),

View File

@@ -1,7 +1,10 @@
//! Alu register instructions
// Imports
use crate::exe::inst::Register;
use crate::exe::inst::{
basic::{Decodable, Encodable},
Register,
};
/// Alu register instruction kind
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
@@ -90,10 +93,10 @@ pub struct Inst {
pub kind: Kind,
}
impl Inst {
/// Decodes this instruction
#[must_use]
pub fn decode(raw: Raw) -> Option<Self> {
impl Decodable for Inst {
type Raw = Raw;
fn decode(raw: Self::Raw) -> Option<Self> {
let kind = match raw.f {
0x0 => Kind::Add,
0x1 => Kind::AddUnsigned,
@@ -115,10 +118,9 @@ impl Inst {
kind,
})
}
/// Encodes this instruction
#[must_use]
pub const fn encode(self) -> Raw {
}
impl Encodable for Inst {
fn encode(&self) -> Raw {
let f = match self.kind {
Kind::Add => 0x0,
Kind::AddUnsigned => 0x1,

View File

@@ -1,7 +1,10 @@
//! Condition branches
// Imports
use crate::exe::inst::Register;
use crate::exe::inst::{
basic::{Decodable, Encodable},
Register,
};
use dcb_util::SignedHex;
use int_conv::{Signed, Truncated, ZeroExtended};
use std::fmt;
@@ -63,10 +66,10 @@ pub struct Inst {
pub kind: Kind,
}
impl Inst {
/// Decodes this instruction
#[must_use]
pub fn decode(raw: Raw) -> Option<Self> {
impl Decodable for Inst {
type Raw = Raw;
fn decode(raw: Self::Raw) -> Option<Self> {
let kind = match raw.p {
0x1 => match raw.t {
0b00000 => Kind::LessThanZero,
@@ -88,10 +91,10 @@ impl Inst {
kind,
})
}
}
/// Encodes this instruction
#[must_use]
pub fn encode(self) -> Raw {
impl Encodable for Inst {
fn encode(&self) -> Raw {
#[rustfmt::skip]
let (p, t) = match self.kind {
Kind::Equal(reg) => (0x4, reg.idx()),

View File

@@ -1,86 +0,0 @@
//! Iterator over instructions
// Imports
use super::BasicInst;
/// Iterator over instructions
#[derive(PartialEq, Eq, Debug)]
pub struct InstIter<'a, I: Iterator<Item = u32> + Clone> {
/// Underlying iterator
iter: &'a mut I,
}
impl<'a, I: Iterator<Item = u32> + Clone> InstIter<'a, I> {
/// Creates a new instruction iterator
pub fn new(iter: &'a mut I) -> Self {
Self { iter }
}
/// Reborrows this iterator with a smaller lifetime
pub fn reborrow<'b>(&'b mut self) -> InstIter<'b, I>
where
'a: 'b,
{
InstIter { iter: self.iter }
}
/// Peeks the next element
pub fn peeker<'b>(&mut self) -> InstPeeker<'b, I>
where
'a: 'b,
{
InstPeeker::new(self)
}
}
/// Instruction Peeker
///
/// On drop, the peeker is applied.
#[derive(PartialEq, Eq, Debug)]
pub struct InstPeeker<'a, I: Iterator<Item = u32> + Clone> {
/// Original iterator to update
iter: InstIter<'a, I>,
/// Last iterator
last_iter: Option<I>,
/// Current iterator
cur_iter: I,
}
impl<'a, I: Iterator<Item = u32> + Clone> InstPeeker<'a, I> {
/// Creates a new peeker
pub(self) fn new(iter: InstIter<'a, I>) -> Self {
Self {
iter,
last_iter: None,
cur_iter: iter.iter.clone(),
}
}
/// Reverts the last element peeked
pub fn undo(&mut self) {
match self.last_iter.take() {
Some(last_iter) => self.cur_iter = last_iter,
None => self.cur_iter = self.iter.clone(),
}
}
/// Applies this peeker into the original iterator.
pub fn apply(self) {
// Apply changes to the original iter.
*self.iter.iter = self.cur_iter;
}
}
impl<'a, I: Iterator<Item = u32> + Clone> Iterator for InstPeeker<'a, I> {
type Item = Option<BasicInst>;
fn next(&mut self) -> Option<Self::Item> {
// Backup our current iter
self.last_iter = self.cur_iter.clone();
// Then get the element from the current iterator.
self.cur_iter.next()
}
}

View File

@@ -4,6 +4,9 @@
pub mod imm;
pub mod reg;
// Imports
use crate::exe::inst::basic::{Decodable, Encodable};
/// Raw representation
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
#[derive(derive_more::From)]
@@ -26,19 +29,19 @@ pub enum Inst {
Reg(reg::Inst),
}
impl Inst {
/// Decodes this instruction
#[must_use]
pub fn decode(raw: impl Into<Raw>) -> Option<Self> {
match raw.into() {
impl Decodable for Inst {
type Raw = Raw;
fn decode(raw: Self::Raw) -> Option<Self> {
match raw {
Raw::Imm(raw) => Some(Self::Imm(imm::Inst::decode(raw)?)),
Raw::Reg(raw) => Some(Self::Reg(reg::Inst::decode(raw)?)),
}
}
}
/// Encodes this instruction
#[must_use]
pub const fn encode(self) -> Raw {
impl Encodable for Inst {
fn encode(&self) -> Raw {
match self {
Self::Imm(inst) => Raw::Imm(inst.encode()),
Self::Reg(inst) => Raw::Reg(inst.encode()),

View File

@@ -1,5 +1,8 @@
//! Jump immediate instructions
// Imports
use crate::exe::inst::basic::{Decodable, Encodable};
/// Jmp immediate instruction kind
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub enum Kind {
@@ -43,10 +46,10 @@ pub struct Inst {
pub kind: Kind,
}
impl Inst {
/// Decodes this instruction
#[must_use]
pub const fn decode(raw: Raw) -> Option<Self> {
impl Decodable for Inst {
type Raw = Raw;
fn decode(raw: Self::Raw) -> Option<Self> {
let kind = match raw.p {
0 => Kind::Jump,
1 => Kind::JumpLink,
@@ -55,10 +58,10 @@ impl Inst {
Some(Self { target: raw.i, kind })
}
}
/// Encodes this instruction
#[must_use]
pub const fn encode(self) -> Raw {
impl Encodable for Inst {
fn encode(&self) -> Raw {
let p = match self.kind {
Kind::Jump => 0,
Kind::JumpLink => 1,

View File

@@ -1,7 +1,10 @@
//! Jump register instructions
// Imports
use crate::exe::inst::Register;
use crate::exe::inst::{
basic::{Decodable, Encodable},
Register,
};
use std::fmt;
/// Jmp register instruction kind
@@ -48,10 +51,10 @@ pub struct Inst {
pub kind: Kind,
}
impl Inst {
/// Decodes this instruction
#[must_use]
pub fn decode(raw: Raw) -> Option<Self> {
impl Decodable for Inst {
type Raw = Raw;
fn decode(raw: Self::Raw) -> Option<Self> {
let kind = match raw.f {
0 => Kind::Jump,
1 => Kind::JumpLink(Register::new(raw.d)?),
@@ -61,10 +64,10 @@ impl Inst {
Some(Self { target, kind })
}
}
/// Encodes this instruction
#[must_use]
pub const fn encode(self) -> Raw {
impl Encodable for Inst {
fn encode(&self) -> Raw {
let (f, d) = match self.kind {
Kind::Jump => (0, 0),
Kind::JumpLink(reg) => (1, reg.idx()),

View File

@@ -1,7 +1,10 @@
//! Load instructions
// Imports
use crate::exe::inst::Register;
use crate::exe::inst::{
basic::{Decodable, Encodable},
Register,
};
use dcb_util::SignedHex;
use int_conv::{Signed, Truncated, ZeroExtended};
use std::convert::TryFrom;
@@ -85,10 +88,10 @@ pub struct Inst {
pub kind: Kind,
}
impl Inst {
/// Decodes this instruction
#[must_use]
pub fn decode(raw: Raw) -> Option<Self> {
impl Decodable for Inst {
type Raw = Raw;
fn decode(raw: Self::Raw) -> Option<Self> {
let op = Kind::try_from(raw.p.truncated::<u8>()).ok()?;
Some(Self {
@@ -98,10 +101,10 @@ impl Inst {
kind: op,
})
}
}
/// Encodes this instruction
#[must_use]
pub fn encode(self) -> Raw {
impl Encodable for Inst {
fn encode(&self) -> Raw {
let t = self.src.idx();
let s = self.dst.idx();
let i = self.offset.as_unsigned().zero_extended::<u32>();

View File

@@ -1,7 +1,10 @@
//! Lui instruction
// Imports
use crate::exe::inst::Register;
use crate::exe::inst::{
basic::{Decodable, Encodable},
Register,
};
use int_conv::{Truncated, ZeroExtended};
/// Raw representation
@@ -26,19 +29,18 @@ pub struct Inst {
pub value: u16,
}
impl Inst {
/// Decodes this instruction
#[must_use]
pub fn decode(raw: Raw) -> Option<Self> {
impl Decodable for Inst {
type Raw = Raw;
fn decode(raw: Self::Raw) -> Option<Self> {
Some(Self {
dst: Register::new(raw.t)?,
value: raw.i.truncated::<u16>(),
})
}
/// Encodes this instruction
#[must_use]
pub fn encode(self) -> Raw {
}
impl Encodable for Inst {
fn encode(&self) -> Raw {
Raw {
t: self.dst.idx(),
i: self.value.zero_extended::<u32>(),

View File

@@ -1,10 +1,13 @@
//! Multiplications
// Imports
use crate::exe::inst::Register;
use crate::exe::inst::{
basic::{Decodable, Encodable},
Register,
};
use std::fmt;
/// Operation func
/// Operation kind
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub enum MultKind {
/// Multiplication
@@ -36,7 +39,7 @@ pub enum MultReg {
/// Raw representation
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub struct MultRaw {
pub struct Raw {
/// Rs
pub s: u32,
@@ -52,7 +55,7 @@ pub struct MultRaw {
/// Multiplication instructions
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub enum MultInst {
pub enum Inst {
/// Multiplication
Mult {
/// Kind
@@ -87,11 +90,11 @@ pub enum MultInst {
},
}
impl MultInst {
/// Decodes this instruction
#[must_use]
impl Decodable for Inst {
type Raw = Raw;
#[rustfmt::skip]
pub fn decode(raw: MultRaw) -> Option<Self> {
fn decode(raw: Self::Raw) -> Option<Self> {
Some(match raw.f {
0x10 => Self::MoveFrom { dst: Register::new(raw.d)?, src: MultReg::Hi },
0x12 => Self::MoveFrom { dst: Register::new(raw.d)?, src: MultReg::Lo },
@@ -107,12 +110,12 @@ impl MultInst {
_ => return None,
})
}
}
/// Encodes this instruction
#[must_use]
pub const fn encode(self) -> MultRaw {
impl Encodable for Inst {
fn encode(&self) -> Raw {
match self {
Self::Mult { kind, mode, lhs, rhs } => MultRaw {
Self::Mult { kind, mode, lhs, rhs } => Raw {
s: lhs.idx(),
t: rhs.idx(),
d: 0,
@@ -123,7 +126,7 @@ impl MultInst {
(MultKind::Div, MultMode::Unsigned) => 0x1b,
},
},
Self::MoveFrom { dst, src } => MultRaw {
Self::MoveFrom { dst, src } => Raw {
s: 0,
t: 0,
d: dst.idx(),
@@ -132,7 +135,7 @@ impl MultInst {
MultReg::Lo => 0x12,
},
},
Self::MoveTo { dst: src, src: dst } => MultRaw {
Self::MoveTo { dst: src, src: dst } => Raw {
s: src.idx(),
t: 0,
d: 0,
@@ -145,7 +148,7 @@ impl MultInst {
}
}
impl fmt::Display for MultInst {
impl fmt::Display for Inst {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
#[rustfmt::skip]

View File

@@ -1,7 +1,10 @@
//! Store instructions
// Imports
use crate::exe::inst::Register;
use crate::exe::inst::{
basic::{Decodable, Encodable},
Register,
};
use dcb_util::SignedHex;
use int_conv::{Signed, Truncated, ZeroExtended};
use std::convert::TryFrom;
@@ -77,10 +80,10 @@ pub struct Inst {
pub kind: Kind,
}
impl Inst {
/// Decodes this instruction
#[must_use]
pub fn decode(raw: Raw) -> Option<Self> {
impl Decodable for Inst {
type Raw = Raw;
fn decode(raw: Self::Raw) -> Option<Self> {
let kind = Kind::try_from(raw.p.truncated::<u8>()).ok()?;
Some(Self {
@@ -90,10 +93,9 @@ impl Inst {
kind,
})
}
/// Encodes this instruction
#[must_use]
pub fn encode(self) -> Raw {
}
impl Encodable for Inst {
fn encode(&self) -> Raw {
let t = self.src.idx();
let s = self.dst.idx();
let i = self.offset.as_unsigned().zero_extended::<u32>();

View File

@@ -1,5 +1,8 @@
//! System calls
// Imports
use crate::exe::inst::basic::{Decodable, Encodable};
/// Sys instruction func
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub enum Kind {
@@ -43,23 +46,22 @@ pub struct Inst {
pub kind: Kind,
}
impl Inst {
/// Decodes this instruction
#[must_use]
pub const fn decode(Raw { c, f }: Raw) -> Option<Self> {
let kind = match f {
impl Decodable for Inst {
type Raw = Raw;
fn decode(raw: Self::Raw) -> Option<Self> {
let kind = match raw.f {
0 => Kind::Sys,
1 => Kind::Break,
_ => return None,
};
Some(Self { comment: c, kind })
Some(Self { comment: raw.c, kind })
}
}
/// Encodes this instruction
#[must_use]
#[allow(clippy::many_single_char_names)] // `Raw` has single character names
pub const fn encode(self) -> Raw {
impl Encodable for Inst {
fn encode(&self) -> Raw {
let c = self.comment;
let f = match self.kind {
Kind::Sys => 0,