diff options
author | iximeow <git@iximeow.net> | 2024-09-29 00:37:26 +0000 |
---|---|---|
committer | iximeow <git@iximeow.net> | 2024-09-29 00:37:26 +0000 |
commit | f9758104ea1ed7be4c8dda2707637629c0ddef11 (patch) | |
tree | 903706a6f5ce683b284d30d7d59eeda881b9fdbe /src/display.rs | |
parent | 137a9479310bb54367db1d9bd95cd7b84978ba3a (diff) |
starting to look like a disassembler
Diffstat (limited to 'src/display.rs')
-rw-r--r-- | src/display.rs | 153 |
1 files changed, 151 insertions, 2 deletions
diff --git a/src/display.rs b/src/display.rs index d84807d..84bc06b 100644 --- a/src/display.rs +++ b/src/display.rs @@ -1,7 +1,156 @@ use core::fmt; -use crate::{Opcode, Operand}; +use crate::{Instruction, InstructionPacket, Opcode, Operand}; + +impl fmt::Display for InstructionPacket { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str("{ ")?; + write!(f, "{}", self.instructions[0])?; + for i in 1..self.instruction_count { + write!(f, "; {}", self.instructions[i as usize])?; + } + + f.write_str(" }")?; + if self.loop_effect.end_0() { + f.write_str(":endloop0")?; + } + if self.loop_effect.end_1() { + f.write_str(":endloop1")?; + } + + Ok(()) + } +} + +impl fmt::Display for Instruction { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if let Some(predication) = self.predicate { + write!(f, "if ({}P{}{}) ", + if predication.negated() { "!" } else { "" }, + predication.num(), + if predication.pred_new() { ".new" } else { "" }, + )?; + } + + // V73 Section 10.11 + // > The assembler encodes some Hexagon processor instructions as variants of other + // > instructions. The encoding as a variant done for Operations that are functionally + // > equivalent to other instructions, but are still defined as separate instructions because + // > of their programming utility as common operations. + // ... + // | Instruction | Mapping | + // |--------------|------------------| + // | Rd = not(Rs) | Rd = sub(#-1,Rs) | + // | Rd = neg(Rs) | Rd = sub(#0,Rs) | + // | Rdd = Rss | Rdd = combine(Rss.H32, Rss.L32) | + if let Some(o) = self.dest.as_ref() { + write!(f, "{} = ", o)?; + } + + // TransferRegister and TransferImmediate display the source operand atypically. + if self.opcode == Opcode::TransferRegister || self.opcode == Opcode::TransferImmediate { + write!(f, "{}", self.sources[0])?; + return Ok(()); + } + + if self.negated { + f.write_str("!")?; + } + write!(f, "{}", self.opcode)?; + + if self.sources_count > 0 { + f.write_str("(")?; + write!(f, "{}", self.sources[0])?; + for i in 1..self.sources_count { + write!(f, ", {}", self.sources[i as usize])?; + } + f.write_str(")")?; + } + + Ok(()) + } +} impl fmt::Display for Opcode { - + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Opcode::BUG => { f.write_str("BUG") }, + Opcode::Nop => { f.write_str("nop") }, + Opcode::Jump => { f.write_str("jump") }, + Opcode::Memb => { f.write_str("memb") }, + Opcode::Memub => { f.write_str("memub") }, + Opcode::Memh => { f.write_str("memh") }, + Opcode::Memuh => { f.write_str("memuh") }, + Opcode::Memw => { f.write_str("memw") }, + Opcode::Memd => { f.write_str("memd") }, + Opcode::Membh => { f.write_str("membh") }, + Opcode::MemhFifo => { f.write_str("memh_fifo") }, + Opcode::Memubh => { f.write_str("memubh") }, + Opcode::MembFifo => { f.write_str("memb_fifo") }, + + Opcode::Aslh => { f.write_str("aslh") }, + Opcode::Asrh => { f.write_str("asrh") }, + Opcode::TransferRegister => { f.write_str("transfer_register") }, + Opcode::TransferImmediate => { f.write_str("transfer_immediate") }, + Opcode::Zxtb => { f.write_str("zxtb") }, + Opcode::Sxtb => { f.write_str("sxtb") }, + Opcode::Zxth => { f.write_str("zxth") }, + Opcode::Sxth => { f.write_str("sxth") }, + Opcode::Mux => { f.write_str("mux") }, + Opcode::Combine => { f.write_str("combine") }, + Opcode::CmpEq => { f.write_str("cmp.eq") }, + Opcode::CmpGt => { f.write_str("cmp.gt") }, + Opcode::CmpGtu => { f.write_str("cmp.gtu") }, + Opcode::Add => { f.write_str("add") }, + Opcode::And => { f.write_str("and") }, + Opcode::Sub => { f.write_str("sub") }, + Opcode::Or => { f.write_str("or") }, + } + } +} + +impl fmt::Display for Operand { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Operand::Nothing => { + f.write_str("BUG (operand)") + } + Operand::PCRel32 { rel } => { + f.write_str("idk!") + } + Operand::Gpr { reg } => { + write!(f, "R{}", reg) + } + Operand::GprLow { reg } => { + write!(f, "R{}.L", reg) + } + Operand::GprHigh { reg } => { + write!(f, "R{}.H", reg) + } + Operand::Gpr64b { reg_low } => { + write!(f, "R{}:{}", reg_low + 1, reg_low) + } + Operand::PredicateReg { reg } => { + write!(f, "P{}", reg) + } + Operand::RegOffset { base, offset } => { + write!(f, "R{}+#{}", base, offset) + } + Operand::RegShiftedReg { base, index, shift } => { + write!(f, "R{} + R{} << {}", base, index, shift) + } + Operand::ImmU8 { imm } => { + write!(f, "#0x{:x}", imm) + } + Operand::ImmU16 { imm } => { + write!(f, "#0x{:x}", imm) + } + Operand::ImmI8 { imm } => { + write!(f, "#{:}", imm) + } + Operand::ImmI16 { imm } => { + write!(f, "#{:}", imm) + } + } + } } |