diff --git a/dcb-exe/src/exe/inst/basic.rs b/dcb-exe/src/exe/inst/basic.rs index c1c20e6..c0294b2 100644 --- a/dcb-exe/src/exe/inst/basic.rs +++ b/dcb-exe/src/exe/inst/basic.rs @@ -23,6 +23,9 @@ pub enum Inst { /// Shift Shift(shift::Inst), + /// Multiplication + Mult(mult::Inst), + /// Store Store(store::Inst), @@ -53,29 +56,18 @@ impl Decodable for Inst { fn decode(raw: Self::Raw) -> Option { 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 })?), - + "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 })?), - - // Alu - "000000_sssss_ttttt_ddddd_?????_10ffff" => Self::Alu(alu::Inst::decode_from(alu::reg::Raw { s, t, d, f })?), "001ppp_sssss_ttttt_iiiii_iiiii_iiiiii" => Self::Alu(alu::Inst::decode_from(alu::imm::Raw { p, s, t, i })?), - - // Syscall - "000000_ccccc_ccccc_ccccc_ccccc_00110f" => Self::Sys(sys::Inst::decode(sys::Raw { c, f })?), - - // Store / Load - "100ppp_sssss_ttttt_iiiii_iiiii_iiiiii" => Self::Store(store::Inst::decode(store::Raw { p, s, t, i })?), - "101ppp_sssss_ttttt_iiiii_iiiii_iiiiii" => Self::Load(load::Inst::decode(load::Raw { p, s, t, i })?), - - // TODO: Remaining instructions, such as shift + "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 })?), /* "0100nn_1iiii_iiiii_iiiii_iiiii_iiiiii" => CopN { n: n.truncate(), imm: i}, @@ -103,6 +95,10 @@ impl Encodable for Inst { 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"), @@ -141,6 +137,7 @@ impl InstFmt for Inst { 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(), @@ -155,6 +152,7 @@ impl InstFmt for Inst { 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), diff --git a/dcb-exe/src/exe/inst/basic/cond.rs b/dcb-exe/src/exe/inst/basic/cond.rs index d6f70f1..1e0eb01 100644 --- a/dcb-exe/src/exe/inst/basic/cond.rs +++ b/dcb-exe/src/exe/inst/basic/cond.rs @@ -136,7 +136,7 @@ impl InstFmt for Inst { } fn fmt(&self, pos: crate::Pos, _bytes: &[u8], f: &mut fmt::Formatter) -> fmt::Result { - let address = pos + self.offset; + let address = pos + 4 * self.offset; let mnemonic = self.kind.mnemonic(); let arg = self.arg; diff --git a/dcb-exe/src/exe/inst/basic/jmp/imm.rs b/dcb-exe/src/exe/inst/basic/jmp/imm.rs index f2ff5bd..6b287fd 100644 --- a/dcb-exe/src/exe/inst/basic/jmp/imm.rs +++ b/dcb-exe/src/exe/inst/basic/jmp/imm.rs @@ -81,6 +81,6 @@ impl InstFmt for Inst { fn fmt(&self, _pos: crate::Pos, _bytes: &[u8], f: &mut std::fmt::Formatter) -> std::fmt::Result { let Self { kind, target } = self; - write!(f, "{} {target}", kind.mnemonic()) + write!(f, "{} {target:#x}", kind.mnemonic()) } } diff --git a/dcb-exe/src/exe/inst/basic/load.rs b/dcb-exe/src/exe/inst/basic/load.rs index e4900b3..4bbe820 100644 --- a/dcb-exe/src/exe/inst/basic/load.rs +++ b/dcb-exe/src/exe/inst/basic/load.rs @@ -6,35 +6,30 @@ use crate::exe::inst::{ InstFmt, Register, }; use int_conv::{Signed, Truncated, ZeroExtended}; -use std::convert::TryFrom; /// Load instruction kind -/// -/// Each variant's value is equal to the lower 3 bits of the opcode #[derive(PartialEq, Eq, Clone, Copy, Debug)] -#[derive(num_enum::IntoPrimitive, num_enum::TryFromPrimitive)] -#[repr(u8)] pub enum Kind { /// Byte, `i8` - Byte = 0x0, + Byte, /// Half-word, `i16` - HalfWord = 0x1, + HalfWord, /// Word left-bits, `u32` - WordLeft = 0x2, + WordLeft, /// Word, `u32` - Word = 0x3, + Word, /// Byte unsigned, `u8` - ByteUnsigned = 0x4, + ByteUnsigned, /// Half-word unsigned, `u16` - HalfWordUnsigned = 0x5, + HalfWordUnsigned, /// Word right-bits, `u32` - WordRight = 0x6, + WordRight, } impl Kind { @@ -89,23 +84,40 @@ impl Decodable for Inst { type Raw = Raw; fn decode(raw: Self::Raw) -> Option { - let op = Kind::try_from(raw.p.truncated::()).ok()?; + let kind = match raw.p { + 0x0 => Kind::Byte, + 0x1 => Kind::HalfWord, + 0x2 => Kind::WordLeft, + 0x3 => Kind::Word, + 0x4 => Kind::ByteUnsigned, + 0x5 => Kind::HalfWordUnsigned, + 0x6 => Kind::WordRight, + _ => return None, + }; Some(Self { - src: Register::new(raw.t)?, - dst: Register::new(raw.s)?, + src: Register::new(raw.t)?, + dst: Register::new(raw.s)?, offset: raw.i.truncated::().as_signed(), - kind: op, + kind, }) } } impl Encodable for Inst { fn encode(&self) -> Raw { + let p = match self.kind { + Kind::Byte => 0x0, + Kind::HalfWord => 0x1, + Kind::WordLeft => 0x2, + Kind::Word => 0x3, + Kind::ByteUnsigned => 0x4, + Kind::HalfWordUnsigned => 0x5, + Kind::WordRight => 0x6, + }; let t = self.src.idx(); let s = self.dst.idx(); let i = self.offset.as_unsigned().zero_extended::(); - let p = u8::from(self.kind).zero_extended::(); Raw { p, s, t, i } } @@ -119,7 +131,7 @@ impl InstFmt for Inst { fn fmt(&self, pos: crate::Pos, _bytes: &[u8], f: &mut std::fmt::Formatter) -> std::fmt::Result { let Self { dst, src, offset, kind } = self; let mnemonic = kind.mnemonic(); - let address = pos + *offset; + let address = pos + 4 * offset; write!(f, "{mnemonic} {dst}, {address}({src})") } diff --git a/dcb-exe/src/exe/inst/basic/mult.rs b/dcb-exe/src/exe/inst/basic/mult.rs index 3ce65f3..1ffb412 100644 --- a/dcb-exe/src/exe/inst/basic/mult.rs +++ b/dcb-exe/src/exe/inst/basic/mult.rs @@ -48,7 +48,7 @@ pub struct Raw { /// Rd pub d: u32, - /// Func + /// Func (bottom 4 bits) pub f: u32, } @@ -95,16 +95,19 @@ impl Decodable for Inst { #[rustfmt::skip] fn decode(raw: Self::Raw) -> Option { Some(match raw.f { - 0x10 => Self::MoveFrom { dst: Register::new(raw.d)?, src: MultReg::Hi }, - 0x12 => Self::MoveFrom { dst: Register::new(raw.d)?, src: MultReg::Lo }, + // 00x0 + 0x0 => Self::MoveFrom { dst: Register::new(raw.d)?, src: MultReg::Hi }, + 0x2 => Self::MoveFrom { dst: Register::new(raw.d)?, src: MultReg::Lo }, - 0x11 => Self::MoveTo { src: Register::new(raw.s)?, dst: MultReg::Hi }, - 0x13 => Self::MoveTo { src: Register::new(raw.s)?, dst: MultReg::Lo }, + // 00x1 + 0x1 => Self::MoveTo { src: Register::new(raw.s)?, dst: MultReg::Hi }, + 0x3 => Self::MoveTo { src: Register::new(raw.s)?, dst: MultReg::Lo }, - 0x18 => Self::Mult { kind: MultKind::Mult, mode: MultMode:: Signed, lhs: Register::new(raw.s)?, rhs: Register::new(raw.t)? }, - 0x19 => Self::Mult { kind: MultKind::Mult, mode: MultMode::Unsigned, lhs: Register::new(raw.s)?, rhs: Register::new(raw.t)? }, - 0x1a => Self::Mult { kind: MultKind::Div , mode: MultMode:: Signed, lhs: Register::new(raw.s)?, rhs: Register::new(raw.t)? }, - 0x1b => Self::Mult { kind: MultKind::Div , mode: MultMode::Unsigned, lhs: Register::new(raw.s)?, rhs: Register::new(raw.t)? }, + // 10xx + 0x8 => Self::Mult { kind: MultKind::Mult, mode: MultMode:: Signed, lhs: Register::new(raw.s)?, rhs: Register::new(raw.t)? }, + 0x9 => Self::Mult { kind: MultKind::Mult, mode: MultMode::Unsigned, lhs: Register::new(raw.s)?, rhs: Register::new(raw.t)? }, + 0xa => Self::Mult { kind: MultKind::Div , mode: MultMode:: Signed, lhs: Register::new(raw.s)?, rhs: Register::new(raw.t)? }, + 0xb => Self::Mult { kind: MultKind::Div , mode: MultMode::Unsigned, lhs: Register::new(raw.s)?, rhs: Register::new(raw.t)? }, _ => return None, }) @@ -118,11 +121,12 @@ impl Encodable for Inst { s: lhs.idx(), t: rhs.idx(), d: 0, + f: match (kind, mode) { - (MultKind::Mult, MultMode::Signed) => 0x18, - (MultKind::Mult, MultMode::Unsigned) => 0x19, - (MultKind::Div, MultMode::Signed) => 0x1a, - (MultKind::Div, MultMode::Unsigned) => 0x1b, + (MultKind::Mult, MultMode::Signed) => 0x8, + (MultKind::Mult, MultMode::Unsigned) => 0x9, + (MultKind::Div, MultMode::Signed) => 0xa, + (MultKind::Div, MultMode::Unsigned) => 0xb, }, }, Self::MoveFrom { dst, src } => Raw { @@ -130,8 +134,8 @@ impl Encodable for Inst { t: 0, d: dst.idx(), f: match src { - MultReg::Hi => 0x10, - MultReg::Lo => 0x12, + MultReg::Hi => 0x0, + MultReg::Lo => 0x2, }, }, Self::MoveTo { dst, src } => Raw { @@ -139,8 +143,8 @@ impl Encodable for Inst { t: 0, d: 0, f: match dst { - MultReg::Hi => 0x11, - MultReg::Lo => 0x13, + MultReg::Hi => 0x1, + MultReg::Lo => 0x3, }, }, } diff --git a/dcb-exe/src/exe/inst/basic/store.rs b/dcb-exe/src/exe/inst/basic/store.rs index ef2963d..2c74725 100644 --- a/dcb-exe/src/exe/inst/basic/store.rs +++ b/dcb-exe/src/exe/inst/basic/store.rs @@ -6,29 +6,24 @@ use crate::exe::inst::{ InstFmt, Register, }; use int_conv::{Signed, Truncated, ZeroExtended}; -use std::convert::TryFrom; /// Store instruction kind -/// -/// Each variant's value is equal to the lower 3 bits of the opcode #[derive(PartialEq, Eq, Clone, Copy, Debug)] -#[derive(num_enum::IntoPrimitive, num_enum::TryFromPrimitive)] -#[repr(u8)] pub enum Kind { - /// Byte, `u8` - Byte = 0x0, + /// Byte, `i8` + Byte, - /// Half-word, `u16` - HalfWord = 0x1, + /// Half-word, `i16` + HalfWord, /// Word left-bits, `u32` - WordLeft = 0x2, + WordLeft, /// Word, `u32` - Word = 0x3, + Word, /// Word right-bits, `u32` - WordRight = 0x6, + WordRight, } impl Kind { @@ -81,7 +76,14 @@ impl Decodable for Inst { type Raw = Raw; fn decode(raw: Self::Raw) -> Option { - let kind = Kind::try_from(raw.p.truncated::()).ok()?; + let kind = match raw.p { + 0x0 => Kind::Byte, + 0x1 => Kind::HalfWord, + 0x2 => Kind::WordLeft, + 0x3 => Kind::Word, + 0x6 => Kind::WordRight, + _ => return None, + }; Some(Self { src: Register::new(raw.t)?, @@ -93,10 +95,16 @@ impl Decodable for Inst { } impl Encodable for Inst { fn encode(&self) -> Raw { + let p = match self.kind { + Kind::Byte => 0x0, + Kind::HalfWord => 0x1, + Kind::WordLeft => 0x2, + Kind::Word => 0x3, + Kind::WordRight => 0x6, + }; let t = self.src.idx(); let s = self.dst.idx(); let i = self.offset.as_unsigned().zero_extended::(); - let p = u8::from(self.kind).zero_extended::(); Raw { p, s, t, i } } @@ -110,7 +118,7 @@ impl InstFmt for Inst { fn fmt(&self, pos: crate::Pos, _bytes: &[u8], f: &mut std::fmt::Formatter) -> std::fmt::Result { let Self { dst, src, offset, kind } = self; let mnemonic = kind.mnemonic(); - let address = pos + *offset; + let address = pos + 4 * offset; write!(f, "{mnemonic} {dst}, {address}({src})") } diff --git a/dcb-exe/src/exe/inst/basic/sys.rs b/dcb-exe/src/exe/inst/basic/sys.rs index 7779b3c..8c61e10 100644 --- a/dcb-exe/src/exe/inst/basic/sys.rs +++ b/dcb-exe/src/exe/inst/basic/sys.rs @@ -83,6 +83,6 @@ impl InstFmt for Inst { let Self { comment, kind } = self; let mnemonic = kind.mnemonic(); - write!(f, "{mnemonic}, {comment:#x}") + write!(f, "{mnemonic} {comment:#x}") } }