Fixed basic::Inst not decoding everything correctly.

This commit is contained in:
Filipe Rodrigues 2021-01-08 17:43:06 +00:00
parent 5ad6f6cb5e
commit 854d90858e
7 changed files with 92 additions and 70 deletions

View File

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

View File

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

View File

@ -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())
}
}

View File

@ -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<Self> {
let op = Kind::try_from(raw.p.truncated::<u8>()).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::<u16>().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::<u32>();
let p = u8::from(self.kind).zero_extended::<u32>();
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})")
}

View File

@ -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<Self> {
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,
},
},
}

View File

@ -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<Self> {
let kind = Kind::try_from(raw.p.truncated::<u8>()).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::<u32>();
let p = u8::from(self.kind).zero_extended::<u32>();
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})")
}

View File

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