Finished the co-processor instructions.

This commit is contained in:
2021-01-11 19:45:57 +00:00
parent ec0d1bcf0c
commit 267cfd1cd7
2 changed files with 108 additions and 53 deletions

View File

@@ -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})"),
}
}
}

View File

@@ -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;