Improved dcb-exe slightly, now gets compiled.

This commit is contained in:
Filipe Rodrigues 2020-11-11 20:07:12 +00:00
parent 38ea8db1db
commit c78822db7e
19 changed files with 335 additions and 492 deletions

View File

@ -4,7 +4,7 @@ members = [
"dcb",
"dcb-io",
"dcb-util",
# "dcb-exe",
"dcb-exe",
"dcb-bytes",
"dcb-bytes-derive",
"dcb-tools"

View File

@ -7,7 +7,9 @@ edition = "2018"
[dependencies]
# Dcb
dcb-bytes = { version = "0.1", path = "../dcb-bytes" }
dcb-bytes = { path = "../dcb-bytes" }
dcb-io = { path = "../dcb-io" }
dcb-util = { path = "../dcb-util" }
# Log
log = "0.4"

View File

@ -20,8 +20,8 @@ pub use instruction::Instruction;
pub use pos::Pos;
// Imports
use crate::{io::address::Data as DataAddress, GameFile};
use dcb_bytes::{ByteArray, Bytes};
use dcb_io::GameFile;
use std::{
convert::TryFrom,
io::{Read, Seek, Write},
@ -45,7 +45,7 @@ impl Exe {
/// Everything outside of this range will be considered data.
pub const CODE_RANGE: std::ops::Range<Pos> = Pos(0x80013e4c)..Pos(0x8006dd3c);
/// Start address of the executable
const START_ADDRESS: DataAddress = DataAddress::from_u64(0x58b9000);
const START_ADDRESS: dcb_io::Data = dcb_io::Data::from_u64(0x58b9000);
}
impl Exe {

View File

@ -16,7 +16,8 @@ pub use error::GetKnownError;
// Imports
use super::Data;
use crate::{exe::Pos, util::DiscardingSortedMergeIter};
use crate::exe::Pos;
use dcb_util::DiscardingSortedMergeIter;
use std::{collections::BTreeSet, fs::File, iter::FromIterator};
/// Data table

View File

@ -9,12 +9,9 @@ use std::fmt;
pub use error::{FromBytesError, ToBytesError};
// Import
use crate::{
util::{array_split, null_ascii_string::NullAsciiString},
AsciiStrArr,
};
use byteorder::{ByteOrder, LittleEndian};
use dcb_bytes::Bytes;
use dcb_util::{array_split, null_ascii_string::NullAsciiString, AsciiStrArr};
/// The header of the executable.
#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)]

View File

@ -2,7 +2,7 @@
// Imports
use super::Header;
use crate::util::null_ascii_string;
use dcb_util::null_ascii_string;
/// Error type for [`Bytes::from_bytes`](dcb_bytes::Bytes::from_bytes)
#[derive(PartialEq, Eq, Clone, Copy, Debug, thiserror::Error)]

View File

@ -10,7 +10,6 @@ pub mod iter;
pub mod jmp;
pub mod load;
pub mod lui;
//pub mod special;
pub mod mult;
pub mod store;
pub mod sys;
@ -19,12 +18,12 @@ pub mod sys;
pub use alu::{AluInst, AluInstRaw};
pub use cond::{CondInst, CondRaw};
pub use iter::InstIter;
pub use jmp::{JmpInst, JmpRaw};
pub use jmp::{JmpInst, JmpInstRaw};
pub use load::{LoadInst, LoadRaw};
pub use lui::{LuiInst, LuiRaw};
//pub use special::{SpecialInst, SpecialRaw};
pub use store::{StoreInst, StoreRaw};
pub use sys::{SysInst, SysRaw};
pub use sys::{SysInst, SysInstRaw};
/// All basic instructions
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
@ -35,7 +34,7 @@ pub enum BasicInst {
/// Load
Load(LoadInst),
/// Condition
Cond(CondInst),
@ -47,48 +46,53 @@ pub enum BasicInst {
/// Load upper immediate
Lui(LuiInst),
/// Syscalls
Sys(SysInst),s
// Syscall
Sys(SysInst),
}
impl BasicInst {
// TODO: MAybe extract the strings if the bitmatch macro allows for it.
/// Decodes this instruction
#[must_use]
#[bitmatch::bitmatch]
#[allow(clippy::many_single_char_names)] // `bitmatch` can only output single character names.
pub fn decode(raw: u32) -> Option<Self> {
Some(
#[bitmatch]
match raw {
//"000000_sssss_ttttt_ddddd_iiiii_ffffff" => Self::Special(SpecialInst::decode(SpecialRaw { s, t, d, i, f })?),
"00001p_iiiii_iiiii_iiiii_iiiii_iiiiii" => Self::Jmp(JmpInst::decode(JmpRaw { p, i })),
"000ppp_sssss_ttttt_iiiii_iiiii_iiiiii" => Self::Cond(CondInst::decode(CondRaw { p, s, t, i })?),
"001111_?????_ttttt_iiiii_iiiii_iiiiii" => Self::Lui(LuiInst::decode(LuiRaw { t, i })?),
//"001ppp_sssss_ttttt_iiiii_iiiii_iiiiii" => Self::Alu(AluInst::decode(AluInstRaw { p, s, t, i })?),
"100ppp_sssss_ttttt_iiiii_iiiii_iiiiii" => Self::Store(StoreInst::decode(StoreRaw { p, s, t, i })?),
"101ppp_sssss_ttttt_iiiii_iiiii_iiiiii" => Self::Load(LoadInst::decode(LoadRaw { p, s, t, i })?),
use BasicInst::*;
let inst = #[bitmatch]
match raw {
// Jump
"00001p_iiiii_iiiii_iiiii_iiiii_iiiiii" => Jmp(JmpInst::decode(JmpInstRaw::Imm(jmp::JmpImmInstRaw { p, i }))),
"000000_sssss_?????_ddddd_?????_00100f" => Jmp(JmpInst::decode(JmpInstRaw::Reg(jmp::JmpRegInstRaw { s, d, f }))),
// Alu
"000000_sssss_ttttt_ddddd_?????_ffffff" => Self::Alu(AluInst::decode(AluInstRaw::Imm(alu::AluRegInstRaw { s, t, d, f }))?),
"001ppp_sssss_ttttt_iiiii_iiiii_iiiiii" => Self::Alu(AluInst::decode(AluInstRaw::Reg(alu::AluImmInstRaw { p, s, t, i }))?),
"000ppp_sssss_ttttt_iiiii_iiiii_iiiiii" => Cond(CondInst::decode(CondRaw { p, s, t, i })?),
"001111_?????_ttttt_iiiii_iiiii_iiiiii" => Lui(LuiInst::decode(LuiRaw { t, i })?),
/*
"0100nn_1iiii_iiiii_iiiii_iiiii_iiiiii" => CopN { n: n.truncate(), imm: i},
"0100nn_00000_ttttt_ddddd_?????_000000" => MfcN { n: n.truncate(), rt: reg(t)?, rd: reg(d)? },
"0100nn_00010_ttttt_ddddd_?????_000000" => CfcN { n: n.truncate(), rt: reg(t)?, rd: reg(d)? },
"0100nn_00100_ttttt_ddddd_?????_000000" => MtcN { n: n.truncate(), rt: reg(t)?, rd: reg(d)? },
"0100nn_00110_ttttt_ddddd_?????_000000" => CtcN { n: n.truncate(), rt: reg(t)?, rd: reg(d)? },
"0100nn_01000_00000_iiiii_iiiii_iiiiii" => BcNf { n: n.truncate(), target: i.truncate() },
"0100nn_01000_00001_iiiii_iiiii_iiiiii" => BcNt { n: n.truncate(), target: i.truncate() },
"1100nn_sssss_ttttt_iiiii_iiiii_iiiiii" => LwcN { n: n.truncate(), rs: reg(s)?, rt: reg(t)?, imm: i.truncate() },
"1110nn_sssss_ttttt_iiiii_iiiii_iiiiii" => SwcN { n: n.truncate(), rs: reg(s)?, rt: reg(t)?, imm: i.truncate() },
*/
_ => return None,
},
)
// Alu
"000000_sssss_ttttt_ddddd_?????_10ffff" => Alu(AluInst::decode(AluInstRaw::Imm(alu::AluRegInstRaw { s, t, d, f }))?),
"001ppp_sssss_ttttt_iiiii_iiiii_iiiiii" => Alu(AluInst::decode(AluInstRaw::Reg(alu::AluImmInstRaw { p, s, t, i }))?),
// Syscall
"000000_ccccc_ccccc_ccccc_ccccc_00110f" => Sys(SysInst::decode(SysInstRaw { c, f })?),
// Store / Load
"100ppp_sssss_ttttt_iiiii_iiiii_iiiiii" => Store(StoreInst::decode(StoreRaw { p, s, t, i })?),
"101ppp_sssss_ttttt_iiiii_iiiii_iiiiii" => Load(LoadInst::decode(LoadRaw { p, s, t, i })?),
/*
"0100nn_1iiii_iiiii_iiiii_iiiii_iiiiii" => CopN { n: n.truncate(), imm: i},
"0100nn_00000_ttttt_ddddd_?????_000000" => MfcN { n: n.truncate(), rt: reg(t)?, rd: reg(d)? },
"0100nn_00010_ttttt_ddddd_?????_000000" => CfcN { n: n.truncate(), rt: reg(t)?, rd: reg(d)? },
"0100nn_00100_ttttt_ddddd_?????_000000" => MtcN { n: n.truncate(), rt: reg(t)?, rd: reg(d)? },
"0100nn_00110_ttttt_ddddd_?????_000000" => CtcN { n: n.truncate(), rt: reg(t)?, rd: reg(d)? },
"0100nn_01000_00000_iiiii_iiiii_iiiiii" => BcNf { n: n.truncate(), target: i.truncate() },
"0100nn_01000_00001_iiiii_iiiii_iiiiii" => BcNt { n: n.truncate(), target: i.truncate() },
"1100nn_sssss_ttttt_iiiii_iiiii_iiiiii" => LwcN { n: n.truncate(), rs: reg(s)?, rt: reg(t)?, imm: i.truncate() },
"1110nn_sssss_ttttt_iiiii_iiiii_iiiiii" => SwcN { n: n.truncate(), rs: reg(s)?, rt: reg(t)?, imm: i.truncate() },
*/
_ => return None,
};
Some(inst)
}
/// Encodes this instruction
@ -97,14 +101,7 @@ impl BasicInst {
pub fn encode(self) -> u32 {
#[rustfmt::skip]
match self {
//Self::Special(inst) => { let SpecialRaw { s, t, d, i, f } = inst.encode(); bitpack!("000000_sssss_ttttt_ddddd_iiiii_ffffff") },
Self::Jmp (inst) => { let JmpRaw { p, i } = inst.encode(); bitpack!("00001p_iiiii_iiiii_iiiii_iiiii_iiiiii") },
Self::Cond (inst) => { let CondRaw { p, s, t, i } = inst.encode(); bitpack!("000ppp_sssss_ttttt_iiiii_iiiii_iiiiii") },
Self::Lui (inst) => { let LuiRaw { t, i } = inst.encode(); bitpack!("001111_00000_ttttt_iiiii_iiiii_iiiiii") },
//Self::Alu (inst) => { let AluInstRaw { p, s, t, i } = inst.encode(); bitpack!("001ppp_sssss_ttttt_iiiii_iiiii_iiiiii") },
Self::Alu(_) => todo!(),
Self::Store(inst) => { let StoreRaw { p, s, t, i } = inst.encode(); bitpack!("100ppp_sssss_ttttt_iiiii_iiiii_iiiiii") },
Self::Load (inst) => { let LoadRaw { p, s, t, i } = inst.encode(); bitpack!("101ppp_sssss_ttttt_iiiii_iiiii_iiiiii") },
_ => todo!(),
}
}
}

View File

@ -1,27 +1,11 @@
//! Alu immediate instructions
// Imports
use crate::{exe::instruction::Register, util::SignedHex};
use crate::exe::instruction::Register;
use dcb_util::SignedHex;
use int_conv::{Signed, Truncated, ZeroExtended};
use std::fmt;
/// Raw representation
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub struct AluImmInstRaw {
/// Opcode (lower 3 bits)
pub p: u32,
/// Rs
pub s: u32,
/// Rt
pub t: u32,
/// Immediate
pub i: u32,
}
/// Alu immediate instruction kind
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub enum AluImmInstKind {
@ -81,6 +65,22 @@ impl AluImmInstKind {
}
}
/// Raw representation
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub struct AluImmInstRaw {
/// Opcode (lower 3 bits)
pub p: u32,
/// Rs
pub s: u32,
/// Rt
pub t: u32,
/// Immediate
pub i: u32,
}
/// Alu register instructions
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
#[derive(derive_more::Display)]

View File

@ -3,22 +3,6 @@
// Imports
use crate::exe::instruction::Register;
/// Raw representation
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub struct AluRegInstRaw {
/// Rs
s: u32,
/// Rt
t: u32,
/// Rd
d: u32,
/// Func
f: u32,
}
/// Alu register instruction kind
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
#[derive(derive_more::Display)]
@ -64,6 +48,22 @@ pub enum AluRegInstKind {
SetLessThanUnsigned,
}
/// Raw representation
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub struct AluRegInstRaw {
/// Rs
s: u32,
/// Rt
t: u32,
/// Rd
d: u32,
/// Func (lower 4 bits)
f: u32,
}
/// Alu register instructions
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
#[derive(derive_more::Display)]
@ -87,16 +87,16 @@ impl AluRegInst {
#[must_use]
pub fn decode(raw: AluRegInstRaw) -> Option<Self> {
let kind = match raw.f {
0x20 => AluRegInstKind::Add,
0x21 => AluRegInstKind::AddUnsigned,
0x22 => AluRegInstKind::Sub,
0x23 => AluRegInstKind::SubUnsigned,
0x24 => AluRegInstKind::And,
0x25 => AluRegInstKind::Or,
0x26 => AluRegInstKind::Xor,
0x27 => AluRegInstKind::Nor,
0x2a => AluRegInstKind::SetLessThan,
0x2b => AluRegInstKind::SetLessThanUnsigned,
0x0 => AluRegInstKind::Add,
0x1 => AluRegInstKind::AddUnsigned,
0x2 => AluRegInstKind::Sub,
0x3 => AluRegInstKind::SubUnsigned,
0x4 => AluRegInstKind::And,
0x5 => AluRegInstKind::Or,
0x6 => AluRegInstKind::Xor,
0x7 => AluRegInstKind::Nor,
0xa => AluRegInstKind::SetLessThan,
0xb => AluRegInstKind::SetLessThanUnsigned,
_ => return None,
};
@ -112,16 +112,16 @@ impl AluRegInst {
#[must_use]
pub fn encode(self) -> AluRegInstRaw {
let f = match self.kind {
AluRegInstKind::Add => 0x20,
AluRegInstKind::AddUnsigned => 0x21,
AluRegInstKind::Sub => 0x22,
AluRegInstKind::SubUnsigned => 0x23,
AluRegInstKind::And => 0x24,
AluRegInstKind::Or => 0x25,
AluRegInstKind::Xor => 0x26,
AluRegInstKind::Nor => 0x27,
AluRegInstKind::SetLessThan => 0x2a,
AluRegInstKind::SetLessThanUnsigned => 0x2b,
AluRegInstKind::Add => 0x0,
AluRegInstKind::AddUnsigned => 0x1,
AluRegInstKind::Sub => 0x2,
AluRegInstKind::SubUnsigned => 0x3,
AluRegInstKind::And => 0x4,
AluRegInstKind::Or => 0x5,
AluRegInstKind::Xor => 0x6,
AluRegInstKind::Nor => 0x7,
AluRegInstKind::SetLessThan => 0xa,
AluRegInstKind::SetLessThanUnsigned => 0xb,
};
let d = self.dst.idx();

View File

@ -1,7 +1,8 @@
//! Condition branches
// Imports
use crate::{exe::instruction::Register, util::SignedHex};
use crate::exe::instruction::Register;
use dcb_util::SignedHex;
use int_conv::{Signed, Truncated, ZeroExtended};
use std::fmt;

View File

@ -1,74 +1,50 @@
//! Alu register instructions
//! Jmp register instructions
// Imports
use std::fmt;
// Modules
pub mod imm;
pub mod reg;
/// Alu register func (bottom bit)
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub enum JmpKind {
/// Jump
Jump,
/// Jump and link
Link,
}
// Exports
pub use imm::{JmpImmInst, JmpImmInstRaw};
pub use reg::{JmpRegInst, JmpRegInstRaw};
/// Raw representation
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub struct JmpRaw {
/// Opcode (bottom bit)
pub p: u32,
pub enum JmpInstRaw {
/// Immediate
pub i: u32,
Imm(JmpImmInstRaw),
/// Register
Reg(JmpRegInstRaw),
}
/// Alu register instructions
/// Jmp register instructions
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub struct JmpInst {
/// Target
pub target: u32,
#[derive(derive_more::Display)]
pub enum JmpInst {
/// Immediate
Imm(JmpImmInst),
/// Kind
pub kind: JmpKind,
/// Register
Reg(JmpRegInst),
}
impl JmpInst {
/// Decodes this instruction
#[must_use]
pub fn decode(raw: JmpRaw) -> Self {
let kind = match raw.p {
0 => JmpKind::Jump,
1 => JmpKind::Link,
_ => unreachable!("Received invalid bit in opcode."),
};
Self { target: raw.i, kind }
pub fn decode(raw: JmpInstRaw) -> Option<Self> {
match raw {
JmpInstRaw::Imm(raw) => Self::Imm(JmpImmInst::decode(raw)?),
JmpInstRaw::Reg(raw) => Self::Reg(JmpRegInst::decode(raw)?),
}
}
/// Encodes this instruction
#[must_use]
pub const fn encode(self) -> JmpRaw {
let p = match self.kind {
JmpKind::Jump => 0,
JmpKind::Link => 1,
};
JmpRaw { p, i: self.target }
}
}
// TODO: Format with `pc` / `label`.
impl fmt::Display for JmpInst {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let Self { target, kind } = self;
let mnemonic = match kind {
JmpKind::Jump => "j",
JmpKind::Link => "jal",
};
write!(f, "{mnemonic} {target:#x}")
pub fn encode(self) -> JmpInstRaw {
match self {
JmpInst::Imm(inst) => JmpInstRaw::Imm(inst.encode()),
JmpInst::Reg(inst) => JmpInstRaw::Reg(inst.encode()),
}
}
}

View File

@ -0,0 +1,69 @@
//! Jump immediate instructions
/// Jmp immediate instruction kind
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub enum JmpImmInstKind {
/// Jump
Jump,
/// Jump and link
JumpLink,
}
impl JmpImmInstKind {
/// Returns this kind's mnemonic
pub fn mnemonic(self) -> &'static str {
match self {
JmpImmInstKind::Jump => "j",
JmpImmInstKind::JumpLink => "jal",
}
}
}
/// Raw representation
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub struct JmpImmInstRaw {
/// Opcode (lower bit)
pub p: u32,
/// Immediate
pub i: u32,
}
/// Jmp register instructions
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
#[derive(derive_more::Display)]
#[display(fmt = "{} {target}", "kind.mnemonic()")]
pub struct JmpImmInst {
/// Target
pub target: u32,
/// Kind
pub kind: JmpImmInstKind,
}
impl JmpImmInst {
/// Decodes this instruction
#[must_use]
pub fn decode(raw: JmpImmInstRaw) -> Option<Self> {
let kind = match raw.p {
0 => JmpImmInstKind::Jump,
1 => JmpImmInstKind::JumpLink,
_ => return None,
};
Some(Self { target: raw.i, kind })
}
/// Encodes this instruction
#[must_use]
pub fn encode(self) -> JmpImmInstRaw {
let (p, i) = match self.kind {
JmpImmInstKind::Jump => 0,
JmpImmInstKind::JumpLink => 1,
};
let i = self.target;
JmpImmInstRaw { p, i }
}
}

View File

@ -0,0 +1,87 @@
//! Jump register instructions
// Imports
use crate::exe::instruction::Register;
use std::fmt;
/// Jmp register instruction kind
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub enum JmpRegInstKind {
/// Jump
Jump,
/// Jump and link
JumpLink(Register),
}
impl JmpRegInstKind {
/// Returns this kind's mnemonic
pub fn mnemonic(self) -> &'static str {
match self {
JmpRegInstKind::Jump => "j",
JmpRegInstKind::JumpLink(_) => "jal",
}
}
}
/// Raw representation
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub struct JmpRegInstRaw {
/// Rs
s: u32,
/// Rd
d: u32,
/// Func (lower bit)
f: u32,
}
/// Jmp register instructions
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub struct JmpRegInst {
/// Target
pub target: Register,
/// Kind
pub kind: JmpRegInstKind,
}
impl JmpRegInst {
/// Decodes this instruction
#[must_use]
pub fn decode(raw: JmpRegInstRaw) -> Option<Self> {
let kind = match raw.f {
0 => JmpRegInstKind::Jump,
1 => JmpRegInstKind::JumpLink(Register::new(raw.d)?),
_ => return None,
};
let target = Register::new(raw.s)?;
Some(Self { target, kind })
}
/// Encodes this instruction
#[must_use]
pub fn encode(self) -> JmpRegInstRaw {
let (f, d) = match self.kind {
JmpRegInstKind::Jump => (0, 0),
JmpRegInstKind::JumpLink(reg) => (1, reg.idx()),
};
let s = self.target.idx();
JmpRegInstRaw { s, d, f }
}
}
impl fmt::Display for JmpRegInst {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mnemonic = self.kind.mnemonic();
let target = self.target;
match self.kind {
JmpRegInstKind::Jump => write!(f, "{mnemonic} {target}"),
JmpRegInstKind::JumpLink(reg) => write!(f, "{mnemonic} {target}, {reg}"),
}
}
}

View File

@ -1,7 +1,8 @@
//! Load instructions
// Imports
use crate::{exe::instruction::Register, util::SignedHex};
use crate::exe::instruction::Register;
use dcb_util::SignedHex;
use int_conv::{Signed, Truncated, ZeroExtended};
use std::convert::TryFrom;

View File

@ -1,139 +0,0 @@
//! ALU instructions
// Modules
pub mod jmp;
pub mod mult;
pub mod shift;
// Exports
pub use jmp::{JmpInst, JmpRaw};
pub use mult::{MultInst, MultRaw};
pub use shift::{ShiftInst, ShiftRaw};
/// Raw representation
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub struct SpecialRaw {
/// Rs
pub s: u32,
/// Rt
pub t: u32,
/// Rd
pub d: u32,
/// Immediate
pub i: u32,
/// Func
pub f: u32,
}
impl From<SpecialRaw> for ShiftRaw {
fn from(SpecialRaw { t, d, s, i, f }: SpecialRaw) -> Self {
Self { t, d, s, i, f }
}
}
impl From<ShiftRaw> for SpecialRaw {
fn from(ShiftRaw { t, d, s, i, f }: ShiftRaw) -> Self {
Self { t, d, s, i, f }
}
}
impl From<SpecialRaw> for JmpRaw {
fn from(SpecialRaw { d, s, f, .. }: SpecialRaw) -> Self {
Self { d, s, f }
}
}
impl From<JmpRaw> for SpecialRaw {
fn from(JmpRaw { d, s, f }: JmpRaw) -> Self {
Self { t: 0, d, s, i: 0, f }
}
}
impl From<SpecialRaw> for SysRaw {
fn from(SpecialRaw { t, d, s, i, f }: SpecialRaw) -> Self {
Self { t, d, s, i, f }
}
}
impl From<SysRaw> for SpecialRaw {
fn from(SysRaw { t, d, s, i, f }: SysRaw) -> Self {
Self { t, d, s, i, f }
}
}
impl From<SpecialRaw> for MultRaw {
fn from(SpecialRaw { t, d, s, f, .. }: SpecialRaw) -> Self {
Self { t, d, s, f }
}
}
impl From<MultRaw> for SpecialRaw {
fn from(MultRaw { t, d, s, f }: MultRaw) -> Self {
Self { t, d, s, i: 0, f }
}
}
impl From<SpecialRaw> for AluRegRaw {
fn from(SpecialRaw { t, d, s, f, .. }: SpecialRaw) -> Self {
Self { t, d, s, f }
}
}
impl From<AluRegRaw> for SpecialRaw {
fn from(AluRegRaw { t, d, s, f }: AluRegRaw) -> Self {
Self { t, d, s, i: 0, f }
}
}
/// Special instructions for `opcode: 0`
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
#[derive(derive_more::Display)]
pub enum SpecialInst {
/// Shift instruction
Shift(ShiftInst),
/// Jump
Jmp(JmpInst),
/// Sys
Sys(SysInst),
/// Mult
Mult(MultInst),
/// Alu
Alu(AluRegInst),
}
impl SpecialInst {
/// Decodes this instruction
#[must_use]
pub fn decode(raw: SpecialRaw) -> Option<Self> {
Some(match raw.f {
0x00..0x08 => Self::Shift(ShiftInst::decode(raw.into())?),
0x08..0x0c => Self::Jmp(JmpInst::decode(raw.into())?),
0x0c..0x10 => Self::Sys(SysInst::decode(raw.into())?),
0x10..0x20 => Self::Mult(MultInst::decode(raw.into())?),
0x20..0x30 => Self::Alu(AluRegInst::decode(raw.into())?),
0x30..0x40 => return None,
_ => unreachable!("Func was larger than 6 bits."),
})
}
/// Encodes this instruction
#[must_use]
pub fn encode(self) -> SpecialRaw {
match self {
Self::Shift(inst) => inst.encode().into(),
Self::Jmp(inst) => inst.encode().into(),
Self::Sys(inst) => inst.encode().into(),
Self::Mult(inst) => inst.encode().into(),
Self::Alu(inst) => inst.encode().into(),
}
}
}

View File

@ -1,129 +0,0 @@
//! Alu register instructions
// Imports
use crate::exe::instruction::Register;
use int_conv::{Truncated, ZeroExtended};
use std::{convert::TryFrom, fmt};
/// Alu register instruction kind
///
/// Each variant's value is equal to the lower 4 bits of the opcode
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
#[derive(num_enum::IntoPrimitive, num_enum::TryFromPrimitive)]
#[repr(u8)]
pub enum AluRegKind {
/// Add
Add = 0x20,
/// Add unsigned
AddUnsigned = 0x21,
/// Sub
Sub = 0x22,
/// Sub unsigned
SubUnsigned = 0x23,
/// And
And = 0x24,
/// Or
Or = 0x25,
/// Xor
Xor = 0x26,
/// Nor
Nor = 0x27,
/// Set less than
SetLessThan = 0x2a,
/// Set less than unsigned
SetLessThanUnsigned = 0x2b,
}
impl AluRegKind {
pub fn mnemonic(self) -> &'static str {
match self {
Self::Add => "add",
Self::AddUnsigned => "addu",
Self::Sub => "sub",
Self::SubUnsigned => "subu",
Self::And => "and",
Self::Or => "or",
Self::Xor => "xor",
Self::Nor => "nor",
Self::SetLessThan => "slt",
Self::SetLessThanUnsigned => "sltu",
}
}
}
/// Raw representation
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub struct AluRegRaw {
/// Rs
pub s: u32,
/// Rt
pub t: u32,
/// Rd
pub d: u32,
/// Func
pub f: u32,
}
/// Alu register instructions
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub struct AluRegInst {
/// Destination register, `rd`
pub dst: Register,
/// Lhs argument, `rs`
pub lhs: Register,
/// Rhs argument, `rt`
pub rhs: Register,
/// Kind
pub kind: AluRegKind,
}
impl AluRegInst {
/// Decodes this instruction
#[must_use]
pub fn decode(raw: AluRegRaw) -> Option<Self> {
let kind = AluRegKind::try_from(raw.f.truncated::<u8>()).ok()?;
Some(Self {
dst: Register::new(raw.d)?,
lhs: Register::new(raw.s)?,
rhs: Register::new(raw.t)?,
kind,
})
}
/// Encodes this instruction
#[must_use]
pub fn encode(self) -> AluRegRaw {
let d = self.dst.idx();
let s = self.lhs.idx();
let t = self.rhs.idx();
let f = u8::from(self.kind).zero_extended::<u32>();
AluRegRaw { f, t, d, s }
}
}
impl fmt::Display for AluRegInst {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let Self { dst, lhs, rhs, kind } = self;
let mnemonic = kind.mnemonic();
write!(f, "{mnemonic} {dst}, {lhs}, {rhs}")
}
}

View File

@ -1,7 +1,8 @@
//! Store instructions
// Imports
use crate::{exe::instruction::Register, util::SignedHex};
use crate::exe::instruction::Register;
use dcb_util::SignedHex;
use int_conv::{Signed, Truncated, ZeroExtended};
use std::convert::TryFrom;

View File

@ -1,89 +1,70 @@
//! System calls
// Imports
use int_conv::{Truncated, ZeroExtended};
use std::{convert::TryFrom, fmt};
/// Sys instruction func
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
#[derive(num_enum::IntoPrimitive, num_enum::TryFromPrimitive)]
#[repr(u8)]
pub enum SysFunc {
/// Sys
Sys = 0xc,
pub enum SysInstKind {
/// Syscall
Sys,
/// Break
Break = 0xd,
Break,
}
impl SysInstKind {
/// Returns the mnemonic associated with this syscall kind
pub fn mnemonic(self) -> &'static str {
match self {
SysInstKind::Sys => "sys",
SysInstKind::Break => "break",
}
}
}
/// Raw representation
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub struct SysRaw {
/// Rs
pub s: u32,
pub struct SysInstRaw {
/// Comment
pub c: u32,
/// Rt
pub t: u32,
/// Rd
pub d: u32,
/// Immediate
pub i: u32,
/// Func
/// Func (bottom bit)
pub f: u32,
}
/// Syscall instructions
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
#[derive(derive_more::Display)]
#[display(fmt = "{}, {comment:#x}", "kind.mnemonic()")]
pub struct SysInst {
/// Comment
pub comment: u32,
/// Function
pub func: SysFunc,
/// Kind
pub kind: SysInstKind,
}
impl SysInst {
/// Decodes this instruction
#[must_use]
pub fn decode(SysRaw { t, d, s, i, f }: SysRaw) -> Option<Self> {
let s = s.truncated::<u8>();
let t = t.truncated::<u8>();
let d = d.truncated::<u8>();
let i = i.truncated::<u8>();
let comment = u32::from_be_bytes([s, t, d, i]);
pub fn decode(SysInstRaw { c, f }: SysInstRaw) -> Option<Self> {
let kind = match f {
0 => SysInstKind::Sys,
1 => SysInstKind::Break,
_ => return None,
};
let func = SysFunc::try_from(f.truncated::<u8>()).ok()?;
Some(Self { comment, func })
Some(Self { comment: c, kind })
}
/// Encodes this instruction
#[must_use]
#[allow(clippy::many_single_char_names)] // `Raw` has single character names
pub fn encode(self) -> SysRaw {
let [s, t, d, i] = self.comment.to_be_bytes();
let s = s.zero_extended::<u32>();
let t = t.zero_extended::<u32>();
let d = d.zero_extended::<u32>();
let i = i.zero_extended::<u32>();
let f = u8::from(self.func).zero_extended::<u32>();
SysRaw { s, t, d, i, f }
}
}
impl fmt::Display for SysInst {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let Self { func, comment } = self;
let mnemonic = match func {
SysFunc::Sys => "sys",
SysFunc::Break => "break",
pub fn encode(self) -> SysInstRaw {
let c = self.comment.to_be_bytes();
let f = match self.kind {
SysInstKind::Sys => 0,
SysInstKind::Break => 1,
};
write!(f, "{mnemonic} {comment:#x}")
SysInstRaw { c, f }
}
}

View File

@ -1,13 +1,11 @@
//! Load immediate
// Imports
use crate::{
exe::instruction::{
basic::{alu_imm::AluImmKind, AluImmInst, InstIter},
BasicInst, Register,
},
util::SignedHex,
use crate::exe::instruction::{
basic::{alu_imm::AluImmKind, AluImmInst, InstIter},
BasicInst, Register,
};
use dcb_util::SignedHex;
use std::fmt;
/// Immediate kind