Add InsIter

This commit is contained in:
Luke Street 2024-04-30 19:44:46 -06:00
parent d31bf75009
commit d63c94c3e2
3 changed files with 49 additions and 4 deletions

View File

@ -354,7 +354,7 @@ impl ParsedIns {
/// Returns an iterator over the arguments of the instruction,
/// stopping at the first [Argument::None].
#[inline]
pub fn args_iter(&self) -> impl Iterator<Item = &Argument> {
pub fn args_iter(&self) -> impl Iterator<Item=&Argument> {
self.args.iter().take_while(|x| !matches!(x, Argument::None))
}
}
@ -405,3 +405,40 @@ impl LowerHex for SignedHexLiteral<i32> {
}
}
}
pub struct InsIter<'a> {
address: u32,
data: &'a [u8],
}
impl<'a> InsIter<'a> {
pub fn new(data: &'a [u8], address: u32) -> Self {
Self { address, data }
}
pub fn address(&self) -> u32 {
self.address
}
pub fn data(&self) -> &'a [u8] {
self.data
}
}
impl<'a> Iterator for InsIter<'a> {
type Item = (u32, Ins);
fn next(&mut self) -> Option<Self::Item> {
if self.data.len() < 4 {
return None;
}
// SAFETY: The slice is guaranteed to be at least 4 bytes long.
let chunk = unsafe { *(self.data.as_ptr() as *const [u8; 4]) };
let ins = Ins::new(u32::from_be_bytes(chunk));
let addr = self.address;
self.address += 4;
self.data = &self.data[4..];
Some((addr, ins))
}
}

View File

@ -3,7 +3,7 @@ mod disasm;
mod generated;
pub use disasm::{
Argument, BranchDest, CRBit, CRField, Ins, Offset, OpaqueU, ParsedIns, Simm, Uimm, FPR, GPR,
GQR, SPR, SR,
Argument, BranchDest, CRBit, CRField, Ins, InsIter, Offset, OpaqueU, ParsedIns, Simm, Uimm,
FPR, GPR, GQR, SPR, SR,
};
pub use generated::{Arguments, Opcode};

View File

@ -1,4 +1,4 @@
use ppc750cl::{Argument, Ins, Opcode, FPR, GPR};
use ppc750cl::{Argument, Ins, InsIter, Opcode, FPR, GPR};
macro_rules! assert_asm {
($ins:ident, $disasm:literal) => {{
@ -1137,3 +1137,11 @@ fn test_ins_xori() {
fn test_ins_xoris() {
assert_asm!(0x6E3D8000, "xoris r29, r17, 0x8000");
}
#[test]
fn test_ins_iter() {
let mut iter = InsIter::new(&[0x7C, 0x43, 0x22, 0x14, 0x7E, 0x1A, 0x02, 0xA6, 0xFF], 0);
assert_eq!(iter.next(), Some((0, Ins::new(0x7C432214))));
assert_eq!(iter.next(), Some((4, Ins::new(0x7E1A02A6))));
assert_eq!(iter.next(), None);
}