Made Directive::Decode respect alignment.

Added several methods to `Pos` for alignment.
This commit is contained in:
2021-01-11 14:20:20 +00:00
parent adf8538736
commit 7fb0030128
2 changed files with 55 additions and 5 deletions

View File

@@ -100,6 +100,7 @@ impl Directive {
/// Decodes a directive
#[must_use]
pub fn decode(pos: Pos, bytes: &[u8]) -> Option<Self> {
/*
// Check if we need to force decode it
if let Some(ForceDecodeRange { kind, .. }) = Self::FORCE_DECODE_RANGES.iter().find(|range| range.contains(&pos)) {
#[rustfmt::skip]
@@ -109,19 +110,33 @@ impl Directive {
ForceDecodeKind::Byte => bytes.next_u8 ().map(Self::Db),
};
}
*/
// TODO: Respect alignment
// If we're not half-word aligned, read a byte
if !pos.is_half_word_aligned() {
return Some(Self::Db(bytes.next_u8()?));
}
// Else try to get a string
// If we're not word aligned, read a half-word
if !pos.is_word_aligned() {
return Some(Self::Dh(bytes.next_u16()?));
}
// Else try to get a string, since we're word aligned
if let Some(len) = self::read_ascii_until_null(bytes) {
return Some(Self::Ascii { len });
}
// Else try to read a `u32`
// Else try to read a word
if let Some(value) = bytes.next_u32() {
return Some(Self::Dw(value));
}
// Else try to read a half-word
if let Some(value) = bytes.next_u16() {
return Some(Self::Dh(value));
}
// Else read a single byte
bytes.next_u8().map(Self::Db)
}
@@ -158,8 +173,15 @@ impl InstFmt for Directive {
Self::Db(value) => write!(f, "{mnemonic} {value:#x}"),
&Self::Ascii { len } => {
let pos = pos.as_mem_idx();
let string = &bytes[pos..pos + len];
let string = AsciiStr::from_ascii(string).expect("Ascii string was invalid").as_str();
let mut bytes = &bytes[pos..pos + len];
// Strip any nulls from the strings
while let [start @ .., 0] = bytes {
bytes = start;
}
// Then convert it to a string
let string = AsciiStr::from_ascii(bytes).expect("Ascii string was invalid").as_str();
write!(f, "{mnemonic} \"{}\"", string.escape_debug())
},
}

View File

@@ -28,6 +28,34 @@ impl Pos {
}
}
// Alignment
impl Pos {
/// Returns if this memory address is aligned to `align`
#[must_use]
pub fn is_aligned_to(self, align: usize) -> bool {
// We're definitely not aligned to anything above
// `u32::MAX`
let align = match u32::try_from(align) {
Ok(align) => align,
Err(_) => return false,
};
self.0 % align == 0
}
/// Returns if this memory address is aligned to a word
#[must_use]
pub fn is_word_aligned(self) -> bool {
self.is_aligned_to(4)
}
/// Returns if this memory address is aligned to a half-word
#[must_use]
pub fn is_half_word_aligned(self) -> bool {
self.is_aligned_to(2)
}
}
// `Pos + u32 = Pos`
impl ops::Add<u32> for Pos {