mirror of
https://github.com/Zenithsiz/dcb.git
synced 2026-02-08 19:34:27 +00:00
Added basic::shift instruction.
This commit is contained in:
@@ -10,6 +10,7 @@ pub mod jmp;
|
||||
pub mod load;
|
||||
pub mod lui;
|
||||
pub mod mult;
|
||||
pub mod shift;
|
||||
pub mod store;
|
||||
pub mod sys;
|
||||
|
||||
@@ -19,6 +20,9 @@ use crate::exe::inst::InstFmt;
|
||||
/// All basic instructions
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
pub enum Inst {
|
||||
/// Shift
|
||||
Shift(shift::Inst),
|
||||
|
||||
/// Store
|
||||
Store(store::Inst),
|
||||
|
||||
@@ -49,6 +53,10 @@ impl Decodable for Inst {
|
||||
fn decode(raw: Self::Raw) -> Option<Self> {
|
||||
let inst = #[bitmatch]
|
||||
match raw {
|
||||
// Shift
|
||||
"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 })?),
|
||||
|
||||
// Jump
|
||||
"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 })?),
|
||||
@@ -91,6 +99,10 @@ impl Encodable for Inst {
|
||||
#[bitmatch::bitmatch]
|
||||
fn encode(&self) -> u32 {
|
||||
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::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"),
|
||||
@@ -133,6 +145,7 @@ impl InstFmt for Inst {
|
||||
Self::Alu(inst) => inst.mnemonic(),
|
||||
Self::Lui(inst) => inst.mnemonic(),
|
||||
Self::Sys(inst) => inst.mnemonic(),
|
||||
Self::Shift(inst) => inst.mnemonic(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,6 +158,7 @@ impl InstFmt for Inst {
|
||||
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::Shift(inst) => inst.fmt(pos, bytes, f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
69
dcb-exe/src/exe/inst/basic/shift.rs
Normal file
69
dcb-exe/src/exe/inst/basic/shift.rs
Normal file
@@ -0,0 +1,69 @@
|
||||
//! Shift instruction
|
||||
|
||||
|
||||
// Modules
|
||||
pub mod imm;
|
||||
pub mod reg;
|
||||
|
||||
// Imports
|
||||
use crate::exe::inst::{
|
||||
basic::{Decodable, Encodable},
|
||||
InstFmt,
|
||||
};
|
||||
|
||||
/// Raw representation
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
#[derive(derive_more::From)]
|
||||
pub enum Raw {
|
||||
/// Immediate
|
||||
Imm(imm::Raw),
|
||||
|
||||
/// Register
|
||||
Reg(reg::Raw),
|
||||
}
|
||||
|
||||
/// Alu register instructions
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
pub enum Inst {
|
||||
/// Immediate
|
||||
Imm(imm::Inst),
|
||||
|
||||
/// Register
|
||||
Reg(reg::Inst),
|
||||
}
|
||||
|
||||
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)?)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl InstFmt for Inst {
|
||||
fn mnemonic(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Imm(inst) => inst.mnemonic(),
|
||||
Self::Reg(inst) => inst.mnemonic(),
|
||||
}
|
||||
}
|
||||
|
||||
fn fmt(&self, pos: crate::Pos, bytes: &[u8], f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Imm(inst) => inst.fmt(pos, bytes, f),
|
||||
Self::Reg(inst) => inst.fmt(pos, bytes, f),
|
||||
}
|
||||
}
|
||||
}
|
||||
113
dcb-exe/src/exe/inst/basic/shift/imm.rs
Normal file
113
dcb-exe/src/exe/inst/basic/shift/imm.rs
Normal file
@@ -0,0 +1,113 @@
|
||||
//! Shift immediate instructions
|
||||
|
||||
// Imports
|
||||
use crate::exe::inst::{
|
||||
basic::{Decodable, Encodable},
|
||||
InstFmt, Register,
|
||||
};
|
||||
use int_conv::{Truncated, ZeroExtended};
|
||||
|
||||
/// Shift immediate instruction kind
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
pub enum Kind {
|
||||
/// Left logical
|
||||
LeftLogical,
|
||||
|
||||
/// Right logical
|
||||
RightLogical,
|
||||
|
||||
/// Right arithmetic
|
||||
RightArithmetic,
|
||||
}
|
||||
|
||||
impl Kind {
|
||||
/// Returns this kind's mnemonic
|
||||
#[must_use]
|
||||
pub const fn mnemonic(self) -> &'static str {
|
||||
match self {
|
||||
Self::LeftLogical => "sll",
|
||||
Self::RightLogical => "srl",
|
||||
Self::RightArithmetic => "sra",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Raw representation
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
pub struct Raw {
|
||||
/// Rt
|
||||
pub t: u32,
|
||||
|
||||
/// Rd
|
||||
pub d: u32,
|
||||
|
||||
/// Immediate
|
||||
pub i: u32,
|
||||
|
||||
/// Function (lower 2 bits)
|
||||
pub f: u32,
|
||||
}
|
||||
|
||||
/// Shift immediate instructions
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
pub struct Inst {
|
||||
/// Destination register
|
||||
pub dst: Register,
|
||||
|
||||
/// Lhs argument
|
||||
pub lhs: Register,
|
||||
|
||||
/// Rhs argument
|
||||
pub rhs: u8,
|
||||
|
||||
/// Kind
|
||||
pub kind: Kind,
|
||||
}
|
||||
|
||||
impl Decodable for Inst {
|
||||
type Raw = Raw;
|
||||
|
||||
fn decode(raw: Self::Raw) -> Option<Self> {
|
||||
let kind = match raw.f {
|
||||
0x0 => Kind::LeftLogical,
|
||||
0x2 => Kind::RightLogical,
|
||||
0x3 => Kind::RightArithmetic,
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
Some(Self {
|
||||
dst: Register::new(raw.d)?,
|
||||
lhs: Register::new(raw.t)?,
|
||||
rhs: raw.i.truncated(),
|
||||
kind,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Encodable for Inst {
|
||||
fn encode(&self) -> Self::Raw {
|
||||
let f = match self.kind {
|
||||
Kind::LeftLogical => 0x0,
|
||||
Kind::RightLogical => 0x2,
|
||||
Kind::RightArithmetic => 0x3,
|
||||
};
|
||||
let t = self.lhs.idx();
|
||||
let d = self.dst.idx();
|
||||
let i = self.rhs.zero_extended();
|
||||
|
||||
Raw { t, d, i, f }
|
||||
}
|
||||
}
|
||||
|
||||
impl InstFmt for Inst {
|
||||
fn mnemonic(&self) -> &'static str {
|
||||
self.kind.mnemonic()
|
||||
}
|
||||
|
||||
fn fmt(&self, _pos: crate::Pos, _bytes: &[u8], f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
let Self { dst, lhs, rhs, kind } = self;
|
||||
let mnemonic = kind.mnemonic();
|
||||
|
||||
write!(f, "{mnemonic} {dst}, {lhs}, {rhs}")
|
||||
}
|
||||
}
|
||||
112
dcb-exe/src/exe/inst/basic/shift/reg.rs
Normal file
112
dcb-exe/src/exe/inst/basic/shift/reg.rs
Normal file
@@ -0,0 +1,112 @@
|
||||
//! Shift register instructions
|
||||
|
||||
// Imports
|
||||
use crate::exe::inst::{
|
||||
basic::{Decodable, Encodable},
|
||||
InstFmt, Register,
|
||||
};
|
||||
|
||||
/// Shift register instruction kind
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
pub enum Kind {
|
||||
/// Left logical
|
||||
LeftLogical,
|
||||
|
||||
/// Right logical
|
||||
RightLogical,
|
||||
|
||||
/// Right arithmetic
|
||||
RightArithmetic,
|
||||
}
|
||||
|
||||
impl Kind {
|
||||
/// Returns this kind's mnemonic
|
||||
#[must_use]
|
||||
pub const fn mnemonic(self) -> &'static str {
|
||||
match self {
|
||||
Self::LeftLogical => "sllv",
|
||||
Self::RightLogical => "srlv",
|
||||
Self::RightArithmetic => "srav",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Raw representation
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
pub struct Raw {
|
||||
/// Rs
|
||||
pub s: u32,
|
||||
|
||||
/// Rt
|
||||
pub t: u32,
|
||||
|
||||
/// Rd
|
||||
pub d: u32,
|
||||
|
||||
/// Func (lower 4 bits)
|
||||
pub f: u32,
|
||||
}
|
||||
|
||||
/// Shift register instructions
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
pub struct Inst {
|
||||
/// Destination register
|
||||
pub dst: Register,
|
||||
|
||||
/// Lhs argument
|
||||
pub lhs: Register,
|
||||
|
||||
/// Rhs argument
|
||||
pub rhs: Register,
|
||||
|
||||
/// Kind
|
||||
pub kind: Kind,
|
||||
}
|
||||
|
||||
impl Decodable for Inst {
|
||||
type Raw = Raw;
|
||||
|
||||
fn decode(raw: Self::Raw) -> Option<Self> {
|
||||
let kind = match raw.f {
|
||||
0x0 => Kind::LeftLogical,
|
||||
0x2 => Kind::RightLogical,
|
||||
0x3 => Kind::RightArithmetic,
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
Some(Self {
|
||||
dst: Register::new(raw.d)?,
|
||||
lhs: Register::new(raw.t)?,
|
||||
rhs: Register::new(raw.s)?,
|
||||
kind,
|
||||
})
|
||||
}
|
||||
}
|
||||
impl Encodable for Inst {
|
||||
fn encode(&self) -> Raw {
|
||||
let f = match self.kind {
|
||||
Kind::LeftLogical => 0x0,
|
||||
Kind::RightLogical => 0x2,
|
||||
Kind::RightArithmetic => 0x3,
|
||||
};
|
||||
|
||||
let d = self.dst.idx();
|
||||
let t = self.lhs.idx();
|
||||
let s = self.rhs.idx();
|
||||
|
||||
Raw { s, t, d, f }
|
||||
}
|
||||
}
|
||||
|
||||
impl InstFmt for Inst {
|
||||
fn mnemonic(&self) -> &'static str {
|
||||
self.kind.mnemonic()
|
||||
}
|
||||
|
||||
fn fmt(&self, _pos: crate::Pos, _bytes: &[u8], f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
let Self { dst, lhs, rhs, kind } = self;
|
||||
let mnemonic = kind.mnemonic();
|
||||
|
||||
write!(f, "{mnemonic} {dst}, {lhs}, {rhs}")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user