Revised inst::basic's documentation and added an extra indirection with basic::Raw.

This commit is contained in:
2021-01-09 15:43:33 +00:00
parent 88db3def6f
commit 00bcbd1422
2 changed files with 146 additions and 99 deletions

View File

@@ -1,7 +1,8 @@
//! Basic instructions
//!
//! This modules defines all the basic instructions from the psx.
//! They are all 1 word (`u32`) long.
//! All instructions in this module are a single word long, and
//! may be decoded from a `u32` via the [`Inst::decode`](<Inst as Decodable>::decode) method,
//! using the [`Decodable`] trait.
// Modules
pub mod alu;
@@ -17,57 +18,58 @@ pub mod sys;
// Imports
use crate::exe::inst::InstFmt;
/// All basic instructions
/// Raw instruction
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub enum Inst {
/// Shift
Shift(shift::Inst),
/// Multiplication
Mult(mult::Inst),
/// Store
Store(store::Inst),
/// Load
Load(load::Inst),
pub enum Raw {
/// Alu
Alu(alu::Raw),
/// Condition
Cond(cond::Inst),
Cond(cond::Raw),
/// Jump
Jmp(jmp::Inst),
Jmp(jmp::Raw),
/// Alu
Alu(alu::Inst),
/// Load
Load(load::Raw),
/// Load upper immediate
Lui(lui::Inst),
Lui(lui::Raw),
/// Multiplication
Mult(mult::Raw),
/// Shift
Shift(shift::Raw),
/// Store
Store(store::Raw),
/// Syscall
Sys(sys::Inst),
Sys(sys::Raw),
}
impl Decodable for Inst {
type Raw = u32;
impl Raw {
/// Constructs a raw instruction from a `u32`.
#[must_use]
#[bitmatch::bitmatch]
#[allow(clippy::many_single_char_names)] // `bitmatch` can only output single character names.
fn decode(raw: Self::Raw) -> Option<Self> {
let inst = #[bitmatch]
pub fn from_u32(raw: u32) -> Option<Self> {
#[rustfmt::skip]
let raw = #[bitmatch]
match raw {
"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 })?),
"000000_sssss_?????_ddddd_?????_00100f" => Self::Jmp(jmp::Inst::decode_from(jmp::reg::Raw { s, d, f })?),
"000000_ccccc_ccccc_ccccc_ccccc_00110f" => Self::Sys(sys::Inst::decode(sys::Raw { c, f })?),
"000000_sssss_ttttt_ddddd_?????_01ffff" => Self::Mult(mult::Inst::decode(mult::Raw { s, t, d, f })?),
"000000_sssss_ttttt_ddddd_?????_10ffff" => Self::Alu(alu::Inst::decode_from(alu::reg::Raw { s, t, d, f })?),
"00001p_iiiii_iiiii_iiiii_iiiii_iiiiii" => Self::Jmp(jmp::Inst::decode_from(jmp::imm::Raw { p, i })?),
"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 })?),
"001ppp_sssss_ttttt_iiiii_iiiii_iiiiii" => Self::Alu(alu::Inst::decode_from(alu::imm::Raw { p, s, t, i })?),
"100ppp_sssss_ttttt_iiiii_iiiii_iiiiii" => Self::Load(load::Inst::decode(load::Raw { p, s, t, i })?),
"101ppp_sssss_ttttt_iiiii_iiiii_iiiiii" => Self::Store(store::Inst::decode(store::Raw { p, s, t, i })?),
"000000_?????_ttttt_ddddd_iiiii_0000ff" => Self::Shift(shift::Raw::Imm(shift::imm::Raw { t, d, i, f })),
"000000_sssss_ttttt_ddddd_?????_0001ff" => Self::Shift(shift::Raw::Reg(shift::reg::Raw { s, t, d, f })),
"000000_sssss_?????_ddddd_?????_00100f" => Self::Jmp (jmp ::Raw::Reg(jmp ::reg::Raw { s, d, f })),
"000000_ccccc_ccccc_ccccc_ccccc_00110f" => Self::Sys ( sys :: Raw { c, f } ),
"000000_sssss_ttttt_ddddd_?????_01ffff" => Self::Mult ( mult :: Raw { s, t, d, f } ),
"000000_sssss_ttttt_ddddd_?????_10ffff" => Self::Alu (alu ::Raw::Reg(alu ::reg::Raw { s, t, d, f })),
"00001p_iiiii_iiiii_iiiii_iiiii_iiiiii" => Self::Jmp (jmp ::Raw::Imm(jmp ::imm::Raw { p, i })),
"000ppp_sssss_ttttt_iiiii_iiiii_iiiiii" => Self::Cond ( cond :: Raw { p, s, t, i } ),
"001111_?????_ttttt_iiiii_iiiii_iiiiii" => Self::Lui ( lui :: Raw { t, i } ),
"001ppp_sssss_ttttt_iiiii_iiiii_iiiiii" => Self::Alu (alu ::Raw::Imm(alu ::imm::Raw { p, s, t, i })),
"100ppp_sssss_ttttt_iiiii_iiiii_iiiiii" => Self::Load ( load :: Raw { p, s, t, i } ),
"101ppp_sssss_ttttt_iiiii_iiiii_iiiiii" => Self::Store( store:: Raw { p, s, t, i } ),
/*
"0100nn_1iiii_iiiii_iiiii_iiiii_iiiiii" => CopN { n: n.truncate(), imm: i},
@@ -83,80 +85,131 @@ impl Decodable for Inst {
_ => return None,
};
Some(raw)
}
/// Encodes this raw as a `u32`
#[must_use]
#[bitmatch::bitmatch]
#[rustfmt::skip]
pub const fn as_u32(&self) -> u32 {
match *self {
Self::Shift(shift::Raw::Imm(shift::imm::Raw { t, d, i, f })) => bitpack!("000000_?????_ttttt_ddddd_iiiii_0000ff"),
Self::Shift(shift::Raw::Reg(shift::reg::Raw { s, t, d, f })) => bitpack!("000000_sssss_ttttt_ddddd_?????_0001ff"),
Self::Jmp (jmp ::Raw::Reg(jmp ::reg::Raw { s, d, f })) => bitpack!("000000_sssss_?????_ddddd_?????_00100f"),
Self::Sys ( sys :: Raw { c, f } ) => bitpack!("000000_ccccc_ccccc_ccccc_ccccc_00110f"),
Self::Mult ( mult :: Raw { s, t, d, f } ) => bitpack!("000000_sssss_ttttt_ddddd_?????_01ffff"),
Self::Alu (alu ::Raw::Reg(alu ::reg::Raw { s, t, d, f })) => bitpack!("000000_sssss_ttttt_ddddd_?????_10ffff"),
Self::Jmp (jmp ::Raw::Imm(jmp ::imm::Raw { p, i })) => bitpack!("00001p_iiiii_iiiii_iiiii_iiiii_iiiiii"),
Self::Cond ( cond :: Raw { p, s, t, i } ) => bitpack!("000ppp_sssss_ttttt_iiiii_iiiii_iiiiii"),
Self::Lui ( lui :: Raw { t, i } ) => bitpack!("001111_?????_ttttt_iiiii_iiiii_iiiiii"),
Self::Alu (alu ::Raw::Imm(alu ::imm::Raw { p, s, t, i })) => bitpack!("001ppp_sssss_ttttt_iiiii_iiiii_iiiiii"),
Self::Load ( load :: Raw { p, s, t, i } ) => bitpack!("100ppp_sssss_ttttt_iiiii_iiiii_iiiiii"),
Self::Store( store:: Raw { p, s, t, i } ) => bitpack!("101ppp_sssss_ttttt_iiiii_iiiii_iiiiii"),
}
}
}
/// All basic instructions
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub enum Inst {
/// Alu
Alu(alu::Inst),
/// Condition
Cond(cond::Inst),
/// Jump
Jmp(jmp::Inst),
/// Load
Load(load::Inst),
/// Load upper immediate
Lui(lui::Inst),
/// Multiplication
Mult(mult::Inst),
/// Shift
Shift(shift::Inst),
/// Store
Store(store::Inst),
/// Syscall
Sys(sys::Inst),
}
impl Decodable for Inst {
type Raw = Raw;
fn decode(raw: Self::Raw) -> Option<Self> {
#[rustfmt::skip]
let inst =
match raw {
Raw::Alu (raw) => Self::Alu (alu ::Inst::decode(raw)?),
Raw::Cond (raw) => Self::Cond (cond ::Inst::decode(raw)?),
Raw::Jmp (raw) => Self::Jmp (jmp ::Inst::decode(raw)?),
Raw::Load (raw) => Self::Load (load ::Inst::decode(raw)?),
Raw::Lui (raw) => Self::Lui (lui ::Inst::decode(raw)?),
Raw::Mult (raw) => Self::Mult (mult ::Inst::decode(raw)?),
Raw::Shift(raw) => Self::Shift(shift::Inst::decode(raw)?),
Raw::Store(raw) => Self::Store(store::Inst::decode(raw)?),
Raw::Sys (raw) => Self::Sys (sys ::Inst::decode(raw)?),
};
Some(inst)
}
}
impl Encodable for Inst {
#[bitmatch::bitmatch]
fn encode(&self) -> u32 {
#[rustfmt::skip]
fn encode(&self) -> Self::Raw {
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::Mult(inst) => {
let mult::Raw { s, t, d, f } = inst.encode();
bitpack!("000000_sssss_ttttt_ddddd_?????_01ffff")
},
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"),
},
Self::Cond(inst) => {
let cond::Raw { p, s, t, i } = inst.encode();
bitpack!("000ppp_sssss_ttttt_iiiii_iiiii_iiiiii")
},
Self::Lui(inst) => {
let lui::Raw { t, i } = inst.encode();
bitpack!("001111_?????_ttttt_iiiii_iiiii_iiiiii")
},
Self::Alu(inst) => match inst.encode() {
alu::Raw::Imm(alu::imm::Raw { p, s, t, i }) => bitpack!("001ppp_sssss_ttttt_iiiii_iiiii_iiiiii"),
alu::Raw::Reg(alu::reg::Raw { s, t, d, f }) => bitpack!("000000_sssss_ttttt_ddddd_?????_10ffff"),
},
Self::Sys(inst) => {
let sys::Raw { c, f } = inst.encode();
bitpack!("000000_ccccc_ccccc_ccccc_ccccc_00110f")
},
Self::Store(inst) => {
let store::Raw { p, s, t, i } = inst.encode();
bitpack!("100ppp_sssss_ttttt_iiiii_iiiii_iiiiii")
},
Self::Load(inst) => {
let load::Raw { p, s, t, i } = inst.encode();
bitpack!("101ppp_sssss_ttttt_iiiii_iiiii_iiiiii")
},
Self::Alu (inst) => Raw::Alu (inst.encode()),
Self::Cond (inst) => Raw::Cond (inst.encode()),
Self::Jmp (inst) => Raw::Jmp (inst.encode()),
Self::Load (inst) => Raw::Load (inst.encode()),
Self::Lui (inst) => Raw::Lui (inst.encode()),
Self::Mult (inst) => Raw::Mult (inst.encode()),
Self::Shift(inst) => Raw::Shift(inst.encode()),
Self::Store(inst) => Raw::Store(inst.encode()),
Self::Sys (inst) => Raw::Sys (inst.encode()),
}
}
}
impl InstFmt for Inst {
#[rustfmt::skip]
fn mnemonic(&self) -> &'static str {
match self {
Self::Store(inst) => inst.mnemonic(),
Self::Load(inst) => inst.mnemonic(),
Self::Cond(inst) => inst.mnemonic(),
Self::Mult(inst) => inst.mnemonic(),
Self::Jmp(inst) => inst.mnemonic(),
Self::Alu(inst) => inst.mnemonic(),
Self::Lui(inst) => inst.mnemonic(),
Self::Sys(inst) => inst.mnemonic(),
Self::Alu (inst) => inst.mnemonic(),
Self::Cond (inst) => inst.mnemonic(),
Self::Jmp (inst) => inst.mnemonic(),
Self::Load (inst) => inst.mnemonic(),
Self::Lui (inst) => inst.mnemonic(),
Self::Mult (inst) => inst.mnemonic(),
Self::Shift(inst) => inst.mnemonic(),
Self::Store(inst) => inst.mnemonic(),
Self::Sys (inst) => inst.mnemonic(),
}
}
#[rustfmt::skip]
fn fmt(&self, pos: crate::Pos, bytes: &[u8], f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Self::Store(inst) => inst.fmt(pos, bytes, f),
Self::Load(inst) => inst.fmt(pos, bytes, f),
Self::Cond(inst) => inst.fmt(pos, bytes, f),
Self::Jmp(inst) => inst.fmt(pos, bytes, f),
Self::Mult(inst) => inst.fmt(pos, bytes, f),
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::Alu (inst) => inst.fmt(pos, bytes, f),
Self::Cond (inst) => inst.fmt(pos, bytes, f),
Self::Jmp (inst) => inst.fmt(pos, bytes, f),
Self::Load (inst) => inst.fmt(pos, bytes, f),
Self::Lui (inst) => inst.fmt(pos, bytes, f),
Self::Mult (inst) => inst.fmt(pos, bytes, f),
Self::Shift(inst) => inst.fmt(pos, bytes, f),
Self::Store(inst) => inst.fmt(pos, bytes, f),
Self::Sys (inst) => inst.fmt(pos, bytes, f),
}
}
}
@@ -169,12 +222,6 @@ pub trait Decodable: Sized {
/// 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

View File

@@ -48,7 +48,7 @@ impl<'a> Iterator for ParseIter<'a> {
}
// Else decode an instruction, falling back to a directive if unable to
match self.bytes.next_u32().and_then(basic::Inst::decode) {
match self.bytes.next_u32().and_then(basic::Raw::from_u32).and_then(basic::Inst::decode) {
// If we got one, update our bytes and check if it's a pseudo instruction
Some(inst) => {
self.bytes = &self.bytes[4..];