use std::io::Read; use std::ffi::CStr; #[repr(C)] #[derive(Debug)] struct PPCD_CB { pc: u64, instr: u32, _pad: u32, mnemonic: [u8; 16], operands: [u8; 64], immed: u32, r: [i32; 4], target: u64, iclass: i32, } const PPC_DISA_ILLEGAL: i32 = 0x1000; unsafe extern "C" { fn PPCDisasm(dis_out: *mut PPCD_CB); } fn dolphin_dis(address: u32, code: u32) -> Option { let mut dis = PPCD_CB { pc: address as u64, instr: code, _pad: 0, mnemonic: [0; 16], operands: [0; 64], immed: 0, r: [0; 4], target: 0, iclass: 0, }; unsafe { PPCDisasm(&mut dis) } if dis.iclass == PPC_DISA_ILLEGAL { return None; } let mnemonic = unsafe { CStr::from_ptr(dis.mnemonic.as_ptr() as *const _) }; let operands = unsafe { CStr::from_ptr(dis.operands.as_ptr() as *const _) }; let mnemonic = mnemonic.to_str().expect("can unwrap"); let operands = operands.to_str().expect("can unwrap"); Some(format!("{} {}", mnemonic, operands)) } pub fn main() { let mut args = std::env::args(); args.next().expect("exists"); let hex0 = args.next().expect("byte 0"); if hex0.trim() == "-" { dis_stdin(); return; } let hex1 = args.next().expect("byte 1"); let hex2 = args.next().expect("byte 2"); let hex3 = args.next().expect("byte 3"); let bs: [u8; 4] = [ u8::from_str_radix(&hex0, 16).expect("byte 0 parses"), u8::from_str_radix(&hex1, 16).expect("byte 1 parses"), u8::from_str_radix(&hex2, 16).expect("byte 2 parses"), u8::from_str_radix(&hex3, 16).expect("byte 3 parses"), ]; dis_bytes(bs); } fn dis_stdin() { let mut buf = Vec::new(); std::io::stdin().read_to_end(&mut buf).expect("can read"); for i in 0..buf.len() / 4 { let bs: [u8; 4] = buf[i * 4..][..4].try_into().expect("four bytes"); dis_bytes(u32::from_le_bytes(bs).to_be_bytes()); } } fn dis_bytes(bs: [u8; 4]) { let word = u32::from_be_bytes(bs); if let Some(ok) = dolphin_dis(0x00000004, word) { println!("{}", ok.as_str()); } else { println!(".long 0x{:08x}", word); } }