Added inst::InstSize.

Removed `Pos + i16` implementation.
Added `Pos + usize` implementation.
This commit is contained in:
2021-01-11 13:45:16 +00:00
parent f0258052ba
commit 847e88d490
13 changed files with 82 additions and 51 deletions

View File

@@ -54,7 +54,7 @@ impl Data {
/// Returns the size, in bytes, of this data
#[must_use]
pub fn size(&self) -> u32 {
pub fn size(&self) -> usize {
self.ty.size()
}
}

View File

@@ -14,6 +14,7 @@ pub mod error;
// Exports
pub use error::GetKnownError;
use inst::directive::Directive;
use int_conv::SignExtended;
// Imports
use super::{Data, DataType};
@@ -88,7 +89,7 @@ impl DataTable {
.clone()
.filter_map(|(pos, inst)| match inst {
Inst::Basic(basic::Inst::Load(basic::load::Inst { offset, .. }) | basic::Inst::Store(basic::store::Inst { offset, .. })) => {
Some(pos + offset)
Some(pos + offset.sign_extended::<i32>())
},
/*
Instruction::Pseudo(

View File

@@ -33,14 +33,14 @@ pub enum DataType {
ty: Box<DataType>,
/// Array length
len: u32,
len: usize,
},
}
impl DataType {
/// Returns the size of this data kind
#[must_use]
pub fn size(&self) -> u32 {
pub fn size(&self) -> usize {
match self {
Self::Word => 4,
Self::HalfWord => 2,
@@ -107,7 +107,7 @@ impl std::str::FromStr for DataType {
let ty = Self::from_str(ty).map_err(|err| FromStrError::InvalidArrayTy(Box::new(err)))?;
let ty = Box::new(ty);
let len = self::parse_u32(len).map_err(|err| FromStrError::InvalidArrayLen { len: len.to_owned(), err })?;
let len = self::parse_usize(len).map_err(|err| FromStrError::InvalidArrayLen { len: len.to_owned(), err })?;
return Ok(Self::Array { ty, len });
}
@@ -160,13 +160,13 @@ impl serde::Serialize for DataType {
}
/// Helper function to parse a `u32` from a string with any base.
pub fn parse_u32(s: &str) -> Result<u32, std::num::ParseIntError> {
pub fn parse_usize(s: &str) -> Result<usize, std::num::ParseIntError> {
let (s, base) = match s.trim().as_bytes() {
[b'0', b'x', len @ ..] => (len, 16),
[b'0', b'o', len @ ..] => (len, 8),
[b'0', b'b', len @ ..] => (len, 2),
[b'0', b'x', rest @ ..] => (rest, 16),
[b'0', b'o', rest @ ..] => (rest, 8),
[b'0', b'b', rest @ ..] => (rest, 2),
s => (s, 10),
};
let s = std::str::from_utf8(s).expect("Failed to convert `str` -> `[u8]` -> `str`");
u32::from_str_radix(s, base)
usize::from_str_radix(s, base)
}

View File

@@ -14,6 +14,7 @@ pub mod error;
// Exports
pub use error::GetKnownError;
use int_conv::SignExtended;
//pub use iter::WithInstructionsIter;
// Imports
@@ -136,7 +137,7 @@ impl FuncTable {
},
))) => Some(inst.address(pos)),
// Conditional jumps
Inst::Basic(basic::Inst::Cond(basic::cond::Inst { offset, .. })) => Some(pos + offset),
Inst::Basic(basic::Inst::Cond(basic::cond::Inst { offset, .. })) => Some(pos + offset.sign_extended::<i32>()),
_ => None,
})
.filter(|target| Inst::CODE_RANGE.contains(target))

View File

@@ -25,12 +25,14 @@ pub mod fmt;
pub mod iter;
pub mod pseudo;
pub mod reg;
pub mod size;
// Exports
pub use directive::Directive;
pub use fmt::InstFmt;
pub use iter::ParseIter;
pub use reg::Register;
pub use size::InstSize;
// Imports
use crate::Pos;
@@ -57,6 +59,16 @@ impl Inst {
pub const CODE_START: Pos = Pos(0x80013e4c);
}
impl InstSize for Inst {
fn size(&self) -> usize {
match self {
Self::Basic(inst) => inst.size(),
Self::Pseudo(inst) => inst.size(),
Self::Directive(directive) => directive.size(),
}
}
}
impl InstFmt for Inst {
fn mnemonic(&self) -> &'static str {
match self {

View File

@@ -16,6 +16,7 @@ pub mod store;
pub mod sys;
// Imports
use super::InstSize;
use crate::exe::inst::InstFmt;
/// Raw instruction
@@ -183,6 +184,13 @@ impl Encodable for Inst {
}
}
// Any basic decodable instruction is 4 bytes
impl<T: Decodable> InstSize for T {
fn size(&self) -> usize {
4
}
}
impl InstFmt for Inst {
#[rustfmt::skip]
fn mnemonic(&self) -> &'static str {

View File

@@ -5,7 +5,7 @@ use crate::exe::inst::{
basic::{Decodable, Encodable},
InstFmt, Register,
};
use int_conv::{Signed, Truncated, ZeroExtended};
use int_conv::{SignExtended, Signed, Truncated, ZeroExtended};
use std::fmt;
/// Raw representation
@@ -136,11 +136,11 @@ impl InstFmt for Inst {
}
fn fmt(&self, pos: crate::Pos, _bytes: &[u8], f: &mut fmt::Formatter) -> fmt::Result {
let address = pos + 4 * self.offset;
let mnemonic = self.kind.mnemonic();
let arg = self.arg;
let Self { arg, offset, kind } = self;
let mnemonic = kind.mnemonic();
let address = pos + 4 * offset.sign_extended::<i32>();
match self.kind {
match kind {
Kind::Equal(reg) | Kind::NotEqual(reg) => write!(f, "{mnemonic} {arg}, {reg}, {address}"),
Kind::LessOrEqualZero |
Kind::GreaterThanZero |

View File

@@ -2,7 +2,7 @@
// Imports
//use super::{FromRawIter, Instruction, Raw};
use super::{Inst, InstFmt};
use super::{Inst, InstFmt, InstSize};
use crate::exe::Pos;
use ascii::{AsciiChar, AsciiStr};
use dcb_util::NextFromBytes;
@@ -26,7 +26,7 @@ pub enum Directive {
/// Ascii string
Ascii {
/// String length
len: u32,
len: usize,
},
}
@@ -94,19 +94,6 @@ impl Directive {
kind: ForceDecodeKind::Word,
},
];
/// Returns the size of this directive
#[must_use]
pub const fn size(self) -> u32 {
match self {
Self::Dw(_) => 4,
Self::Dh(_) => 2,
Self::Db(_) => 1,
// Round ascii strings' len up to the
// nearest word (or one after if exactly 1 word).
Self::Ascii { len } => len + 4 - (len % 4),
}
}
}
impl Directive {
@@ -139,6 +126,19 @@ impl Directive {
}
}
impl InstSize for Directive {
fn size(&self) -> usize {
match self {
Self::Dw(_) => 4,
Self::Dh(_) => 2,
Self::Db(_) => 1,
// Round ascii strings' len up to the
// nearest word (or one after if exactly 1 word).
Self::Ascii { len } => len + 4 - (len % 4),
}
}
}
impl InstFmt for Directive {
fn mnemonic(&self) -> &'static str {
match self {
@@ -170,7 +170,7 @@ impl InstFmt for Directive {
///
/// Will always read in multiples of a word (4 bytes), including the null.
#[allow(clippy::as_conversions, clippy::cast_possible_truncation)] // Our length will always fit into a `u32`.
fn read_ascii_until_null(pos: Pos, bytes: &[u8]) -> Option<(u32, usize)> {
fn read_ascii_until_null(pos: Pos, bytes: &[u8]) -> Option<(usize, usize)> {
// Get the next null or invalid character
let (idx, null) = bytes.iter().enumerate().find_map(|(idx, &byte)| match AsciiChar::from_ascii(byte) {
Ok(AsciiChar::Null) => Some((idx, true)),
@@ -191,5 +191,5 @@ fn read_ascii_until_null(pos: Pos, bytes: &[u8]) -> Option<(u32, usize)> {
}
// Else return both lengths
Some((idx as u32, idx + nulls_len))
Some((idx, idx + nulls_len))
}

View File

@@ -4,12 +4,13 @@
use super::{
basic::{self, Decodable as _},
pseudo::{self, Decodable as _},
Directive, Inst,
Directive, Inst, InstSize,
};
use crate::Pos;
use std::convert::TryFrom;
/// Parsing iterator, reads instructions from a `[u8]` slice
/// Parsing iterator.
///
/// Parses instructions from a byte slice, `[u8]` along with it's position.
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct ParseIter<'a> {
/// Remaining bytes
@@ -59,8 +60,8 @@ impl<'a> Iterator for ParseIter<'a> {
// Try to decode a pseudo-instruction
if let Some(inst) = pseudo::Inst::decode(insts.clone()) {
let len = inst.size() * 4;
self.bytes = &self.bytes[usize::try_from(len).expect("Instruction size didn't fit into a `usize`")..];
let len = inst.size();
self.bytes = &self.bytes[len..];
let pos = self.cur_pos;
self.cur_pos += len;
return Some((pos, Inst::Pseudo(inst)));

View File

@@ -14,7 +14,7 @@ pub mod alu_assign;
//pub mod store;
// Imports
use super::{basic, InstFmt};
use super::{basic, InstFmt, InstSize};
/// A pseudo instruction
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
@@ -65,8 +65,10 @@ impl Decodable for Inst {
fn decode(insts: impl Iterator<Item = basic::Inst> + Clone) -> Option<Self> {
alu_assign::Inst::decode(insts).map(Self::AluAssign)
}
}
fn size(&self) -> u32 {
impl InstSize for Inst {
fn size(&self) -> usize {
match self {
Self::AluAssign(inst) => inst.size(),
}
@@ -102,13 +104,10 @@ impl PseudoInst {
*/
/// A decodable pseudo instruction
pub trait Decodable: Sized {
pub trait Decodable: InstSize + Sized {
/// Decodes this instruction
#[must_use]
fn decode(insts: impl Iterator<Item = basic::Inst> + Clone) -> Option<Self>;
/// Returns how many _words_ long this instruction is
fn size(&self) -> u32;
}
/*

View File

@@ -4,7 +4,7 @@
use super::Decodable;
use crate::exe::inst::{
basic::{self, alu},
InstFmt, Register,
InstFmt, InstSize, Register,
};
use std::{convert::TryInto, fmt};
@@ -76,9 +76,11 @@ impl Decodable for Inst {
_ => None,
}
}
}
fn size(&self) -> u32 {
1
impl InstSize for Inst {
fn size(&self) -> usize {
4
}
}

View File

@@ -0,0 +1,7 @@
//! Instruction sizes
/// Trait to report the size of an instruction
pub trait InstSize {
/// Returns the size of this instruction, in bytes.
fn size(&self) -> usize;
}

View File

@@ -47,12 +47,12 @@ impl ops::Add<i32> for Pos {
}
}
// `Pos + i16 = Pos`
impl ops::Add<i16> for Pos {
// `Pos + usize = Pos`
impl ops::Add<usize> for Pos {
type Output = Self;
fn add(self, rhs: i16) -> Self::Output {
self + rhs.sign_extended::<i32>()
fn add(self, rhs: usize) -> Self::Output {
self + u32::try_from(rhs).expect("Value was too large")
}
}