mirror of
https://github.com/Zenithsiz/dcb.git
synced 2026-02-09 03:40:23 +00:00
Finished the co-processor instructions.
This commit is contained in:
@@ -1,18 +1,21 @@
|
||||
//! Co-processor instructions
|
||||
|
||||
// Modules
|
||||
//pub mod exec;
|
||||
//pub mod move_reg;
|
||||
//pub mod cond;
|
||||
//pub mod load;
|
||||
//pub mod store;
|
||||
|
||||
// Imports
|
||||
use crate::exe::inst::{
|
||||
basic::{Decodable, Encodable},
|
||||
InstFmt, Register,
|
||||
};
|
||||
use int_conv::{Signed, Truncated};
|
||||
use int_conv::{Signed, Truncated, ZeroExtended};
|
||||
|
||||
/// Co-processor register kind
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
pub enum RegisterKind {
|
||||
/// Data
|
||||
Data,
|
||||
|
||||
/// Control
|
||||
Control,
|
||||
}
|
||||
|
||||
/// Co-processor instruction kind
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
@@ -23,55 +26,43 @@ pub enum Kind {
|
||||
imm: u32,
|
||||
},
|
||||
|
||||
/// Move data register from co-processor
|
||||
MfcN {
|
||||
/// Move register from co-processor
|
||||
MoveFrom {
|
||||
/// Destination
|
||||
dst: Register,
|
||||
|
||||
/// Source
|
||||
src: Register,
|
||||
src: u8,
|
||||
|
||||
/// Register kind
|
||||
kind: RegisterKind,
|
||||
},
|
||||
|
||||
/// Move control register from co-processor
|
||||
CfcN {
|
||||
/// Move register to co-processor
|
||||
MoveTo {
|
||||
/// Destination
|
||||
dst: Register,
|
||||
dst: u8,
|
||||
|
||||
/// Source
|
||||
src: Register,
|
||||
},
|
||||
/// Move data register to co-processor
|
||||
MtcN {
|
||||
/// Destination
|
||||
dst: Register,
|
||||
|
||||
/// Source
|
||||
src: Register,
|
||||
/// Register kind
|
||||
kind: RegisterKind,
|
||||
},
|
||||
/// Move control register to co-processor
|
||||
CtcN {
|
||||
/// Destination
|
||||
dst: Register,
|
||||
|
||||
/// Source
|
||||
src: Register,
|
||||
},
|
||||
/// Branch if true
|
||||
BcNf {
|
||||
/// Branch if
|
||||
Branch {
|
||||
/// Offset
|
||||
offset: i16,
|
||||
},
|
||||
|
||||
/// Branch if false
|
||||
BcNt {
|
||||
/// Offset
|
||||
offset: i16,
|
||||
/// Value to branch on
|
||||
on: bool,
|
||||
},
|
||||
|
||||
/// Load co-processor
|
||||
LwcN {
|
||||
Load {
|
||||
/// Destination
|
||||
dst: Register,
|
||||
dst: u8,
|
||||
|
||||
/// Source
|
||||
src: Register,
|
||||
@@ -81,9 +72,9 @@ pub enum Kind {
|
||||
},
|
||||
|
||||
/// Store co-processor
|
||||
SwcN {
|
||||
Store {
|
||||
/// Destination
|
||||
dst: Register,
|
||||
dst: u8,
|
||||
|
||||
/// Source
|
||||
src: Register,
|
||||
@@ -108,17 +99,21 @@ impl Decodable for Inst {
|
||||
|
||||
#[bitmatch::bitmatch]
|
||||
fn decode(raw: Self::Raw) -> Option<Self> {
|
||||
// Get `n`
|
||||
#[bitmatch]
|
||||
let "????nn_?????_?????_?????_?????_??????" = raw;
|
||||
|
||||
#[rustfmt::skip]
|
||||
let (n, kind) = #[bitmatch] match raw {
|
||||
"0100nn_1iiii_iiiii_iiiii_iiiii_iiiiii" => (n, Kind::CopN { imm: i }),
|
||||
"0100nn_00000_ttttt_ddddd_?????_000000" => (n, Kind::MfcN { dst: Register::new(t)?, src: Register::new(d)? }),
|
||||
"0100nn_00010_ttttt_ddddd_?????_000000" => (n, Kind::CfcN { dst: Register::new(t)?, src: Register::new(d)? }),
|
||||
"0100nn_00100_ttttt_ddddd_?????_000000" => (n, Kind::MtcN { dst: Register::new(d)?, src: Register::new(t)? }),
|
||||
"0100nn_00110_ttttt_ddddd_?????_000000" => (n, Kind::CtcN { dst: Register::new(d)?, src: Register::new(t)? }),
|
||||
"0100nn_01000_00000_iiiii_iiiii_iiiiii" => (n, Kind::BcNf { offset: i.truncated::<u16>().as_signed() }),
|
||||
"0100nn_01000_00001_iiiii_iiiii_iiiiii" => (n, Kind::BcNt { offset: i.truncated::<u16>().as_signed() }),
|
||||
"1100nn_sssss_ttttt_iiiii_iiiii_iiiiii" => (n, Kind::LwcN { dst: Register::new(t)?, src: Register::new(s)?, offset: i.truncated::<u16>().as_signed() }),
|
||||
"1110nn_sssss_ttttt_iiiii_iiiii_iiiiii" => (n, Kind::SwcN { dst: Register::new(s)?, src: Register::new(t)?, offset: i.truncated::<u16>().as_signed() }),
|
||||
let kind = #[bitmatch] match raw {
|
||||
"0100??_1iiii_iiiii_iiiii_iiiii_iiiiii" => Kind::CopN { imm: i },
|
||||
"0100??_00000_ttttt_ddddd_?????_000000" => Kind::MoveFrom { dst: Register::new(t)?, src: d.truncated(), kind: RegisterKind::Data },
|
||||
"0100??_00010_ttttt_ddddd_?????_000000" => Kind::MoveFrom { dst: Register::new(t)?, src: d.truncated(), kind: RegisterKind::Control },
|
||||
"0100??_00100_ttttt_ddddd_?????_000000" => Kind::MoveTo { dst: d.truncated(), src: Register::new(t)?, kind: RegisterKind::Data },
|
||||
"0100??_00110_ttttt_ddddd_?????_000000" => Kind::MoveTo { dst: d.truncated(), src: Register::new(t)?, kind: RegisterKind::Control },
|
||||
"0100??_01000_00000_iiiii_iiiii_iiiiii" => Kind::Branch { offset: i.truncated::<u16>().as_signed(), on: false },
|
||||
"0100??_01000_00001_iiiii_iiiii_iiiiii" => Kind::Branch { offset: i.truncated::<u16>().as_signed(), on: true },
|
||||
"1100??_sssss_ttttt_iiiii_iiiii_iiiiii" => Kind::Load { dst: t.truncated(), src: Register::new(s)?, offset: i.truncated::<u16>().as_signed() },
|
||||
"1110??_sssss_ttttt_iiiii_iiiii_iiiiii" => Kind::Store { dst: t.truncated(), src: Register::new(s)?, offset: i.truncated::<u16>().as_signed() },
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
@@ -126,13 +121,71 @@ impl Decodable for Inst {
|
||||
}
|
||||
}
|
||||
impl Encodable for Inst {
|
||||
#[bitmatch::bitmatch]
|
||||
fn encode(&self) -> Self::Raw {
|
||||
todo!();
|
||||
let n = self.n;
|
||||
|
||||
match self.kind {
|
||||
Kind::CopN { imm: i } => bitpack!("0100nn_1iiii_iiiii_iiiii_iiiii_iiiiii"),
|
||||
Kind::MoveFrom { dst, src, kind } => {
|
||||
let t = dst.idx();
|
||||
let d = src.zero_extended::<u32>();
|
||||
match kind {
|
||||
RegisterKind::Data => bitpack!("0100nn_00000_ttttt_ddddd_?????_000000"),
|
||||
RegisterKind::Control => bitpack!("0100nn_00010_ttttt_ddddd_?????_000000"),
|
||||
}
|
||||
},
|
||||
Kind::MoveTo { dst, src, kind } => {
|
||||
let d = dst.zero_extended::<u32>();
|
||||
let t = src.idx();
|
||||
match kind {
|
||||
RegisterKind::Data => bitpack!("0100nn_00100_ttttt_ddddd_?????_000000"),
|
||||
RegisterKind::Control => bitpack!("0100nn_00110_ttttt_ddddd_?????_000000"),
|
||||
}
|
||||
},
|
||||
Kind::Branch { offset, on } => {
|
||||
let i = offset.as_unsigned().zero_extended::<u32>();
|
||||
match on {
|
||||
true => bitpack!("0100nn_01000_00001_iiiii_iiiii_iiiiii"),
|
||||
false => bitpack!("0100nn_01000_00000_iiiii_iiiii_iiiiii"),
|
||||
}
|
||||
},
|
||||
Kind::Load { dst, src, offset } => {
|
||||
let t = dst.zero_extended::<u32>();
|
||||
let s = src.idx();
|
||||
let i = offset.as_unsigned().zero_extended::<u32>();
|
||||
bitpack!("1100nn_sssss_ttttt_iiiii_iiiii_iiiiii")
|
||||
},
|
||||
Kind::Store { dst, src, offset } => {
|
||||
let t = dst.zero_extended::<u32>();
|
||||
let s = src.idx();
|
||||
let i = offset.as_unsigned().zero_extended::<u32>();
|
||||
bitpack!("1110nn_sssss_ttttt_iiiii_iiiii_iiiiii")
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl InstFmt for Inst {
|
||||
fn fmt(&self, _pos: crate::Pos, _f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
todo!();
|
||||
#[rustfmt::skip]
|
||||
fn fmt(&self, _pos: crate::Pos, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
let Self { n, kind } = self;
|
||||
match kind {
|
||||
Kind::CopN { imm } => write!(f, "cop{n} {imm:#x}"),
|
||||
Kind::MoveFrom { dst, src, kind } => match kind {
|
||||
RegisterKind::Control => write!(f, "cfc{n} {dst}, ${src:#x}"),
|
||||
RegisterKind::Data => write!(f, "mfc{n} {dst}, ${src:#x}"),
|
||||
}
|
||||
Kind::MoveTo { dst, src, kind } => match kind {
|
||||
RegisterKind::Data => write!(f, "mtc{n} {src}, ${dst:#x}"),
|
||||
RegisterKind::Control => write!(f, "ctc{n} {src}, ${dst:#x}"),
|
||||
}
|
||||
Kind::Branch { offset, on } => match on {
|
||||
true => write!(f, "bc{n}f {offset:#x}"),
|
||||
false => write!(f, "bc{n}t {offset:#x}"),
|
||||
}
|
||||
Kind::Load { dst, src, offset } => write!(f, "lwc{n} ${dst:#x}, {offset:#x}({src})"),
|
||||
Kind::Store { dst, src, offset } => write!(f, "swc{n} ${dst:#x}, {offset:#x}({src})"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,9 @@
|
||||
// We only use wildcards when we only care about certain variants
|
||||
#![allow(clippy::wildcard_enum_match_arm, clippy::match_wildcard_for_single_variants)]
|
||||
// We're fine with shadowing, as long as it's related
|
||||
#![allow(clippy::shadow_reuse)]
|
||||
#![allow(clippy::shadow_reuse, clippy::shadow_same)]
|
||||
// Matching on booleans can look better than `if / else`
|
||||
#![allow(clippy::match_bool)]
|
||||
|
||||
// Modules
|
||||
pub mod exe;
|
||||
|
||||
Reference in New Issue
Block a user