mirror of
https://github.com/Zenithsiz/dcb.git
synced 2026-02-08 19:34:27 +00:00
Added inst::InstSize.
Removed `Pos + i16` implementation. Added `Pos + usize` implementation.
This commit is contained in:
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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)));
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
7
dcb-exe/src/exe/inst/size.rs
Normal file
7
dcb-exe/src/exe/inst/size.rs
Normal 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;
|
||||
}
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user