summaryrefslogtreecommitdiff
path: root/src/display.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/display.rs')
-rw-r--r--src/display.rs453
1 files changed, 453 insertions, 0 deletions
diff --git a/src/display.rs b/src/display.rs
new file mode 100644
index 0000000..0dc4c06
--- /dev/null
+++ b/src/display.rs
@@ -0,0 +1,453 @@
+use core::fmt;
+
+use crate::{Opcode, Operand, Instruction};
+
+impl fmt::Display for Instruction {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self.opcode {
+ Opcode::And => {
+ return write!(f, "ad{} {}", self.operands[0], self.operands[1]);
+ },
+ Opcode::Load => {
+ return write!(f, "l{}f{}", self.operands[0], self.operands[1]);
+ },
+ Opcode::Exchange => {
+ return write!(f, "ex{}{}", self.operands[0], self.operands[1]);
+ },
+ Opcode::AddJK => {
+ return write!(f, "ajk {}", self.operands[0]);
+ },
+ Opcode::SubJK => {
+ return write!(f, "sjk {}", self.operands[0]);
+ },
+ Opcode::AddR => {
+ return write!(f, "ad{} {}", self.operands[0], self.operands[1]);
+ },
+ Opcode::SubR => {
+ return write!(f, "sb{} {}", self.operands[0], self.operands[1]);
+ },
+ Opcode::NegAddJK => {
+ return write!(f, "najk {}", self.operands[0]);
+ },
+ Opcode::NegSubJK => {
+ return write!(f, "nsjk {}", self.operands[0]);
+ },
+ Opcode::NegAddR => {
+ return write!(f, "nad{} {}", self.operands[0], self.operands[1]);
+ },
+ Opcode::NegSubR => {
+ return write!(f, "nsb{} {}", self.operands[0], self.operands[1]);
+ },
+ Opcode::Shift => {
+ return write!(f, "sftz {}, {}", self.operands[0], self.operands[1]);
+ },
+ Opcode::Rotate => {
+ return write!(f, "rotd {}, {}", self.operands[0], self.operands[1]);
+ },
+ _ => {}
+ }
+
+ write!(f, "{}", self.opcode)?;
+ let mut first_separate_op = 0;
+ if [Opcode::TWSM, Opcode::TWSB, Opcode::TWAD, Opcode::TWLD, Opcode::TWST].contains(&self.opcode) {
+ write!(f, "{}", self.operands[0])?;
+ first_separate_op += 1;
+ }
+
+ for i in 0..(self.operand_count() as usize){
+ if let Operand::Absolute(true, _) | Operand::Displacement(true, _) = self.operands[i] {
+ write!(f, "@")?;
+ break;
+ }
+ }
+
+ if let Some(field) = self.referenced_field.as_ref() {
+ write!(f, " field={}", field.num())?;
+ }
+ for i in first_separate_op..self.operand_count() {
+ f.write_str(" ")?;
+ format_operand(f, &self.operands[i as usize])?;
+ if i + 1 < self.operand_count() {
+ f.write_str(",")?;
+ }
+ }
+ Ok(())
+ }
+}
+
+impl fmt::Debug for Operand {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ <Operand as fmt::Display>::fmt(self, f)
+ }
+}
+
+impl fmt::Display for Operand {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ use crate::Operand::*;
+ match self {
+ Nothing => f.write_str("BUG"),
+ J => f.write_str("j"),
+ K => f.write_str("k"),
+ JK => f.write_str("jk"),
+ R => f.write_str("r"),
+ S => f.write_str("s"),
+ RS => f.write_str("rs"),
+ OverflowBit => f.write_str("o"),
+ FlagBit => f.write_str("f"),
+ Displacement(indirect, offset) => {
+ if *indirect {
+ f.write_str("(indirect) ")?;
+ }
+ if *offset < 0 {
+ write!(f, "$-{:#02x}", -offset)
+ } else {
+ write!(f, "$+{:#02x}", offset)
+ }
+ },
+ Absolute(indirect, addr) => {
+ if *indirect {
+ f.write_str("(indirect) ")?;
+ }
+ write!(f, "0o{:04o}", addr)
+ }
+ Literal(value) => {
+ write!(f, "${:03x}", value)
+ },
+ }
+ }
+}
+
+// mostly the same as the `Display` impl, but does not print `indirect`, since that's supposed to
+// be handled by the mnemonic part of the instruction.
+fn format_operand(f: &mut fmt::Formatter, op: &Operand) -> fmt::Result {
+ use crate::Operand::*;
+ match op {
+ Nothing => f.write_str(""),
+ J => f.write_str("j"),
+ K => f.write_str("k"),
+ JK => f.write_str("jk"),
+ R => f.write_str("r"),
+ S => f.write_str("s"),
+ RS => f.write_str("rs"),
+ OverflowBit => f.write_str("o"),
+ FlagBit => f.write_str("f"),
+ Displacement(_, offset) => {
+ if *offset < 0 {
+ write!(f, "$-{:#02x}", -offset)
+ } else {
+ write!(f, "$+{:#02x}", offset)
+ }
+ },
+ Absolute(_, addr) => {
+ write!(f, "0o{:04o}", addr)
+ }
+ Literal(value) => {
+ write!(f, "${:03x}", value)
+ },
+ }
+
+}
+
+impl fmt::Debug for Opcode {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ <Opcode as fmt::Display>::fmt(self, f)
+ }
+}
+
+impl fmt::Display for Opcode {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ Opcode::STOP => {
+ f.write_str("stop")
+ },
+ Opcode::IDLE => {
+ f.write_str("idle")
+ },
+ Opcode::CHSF => {
+ f.write_str("chsf")
+ },
+ Opcode::CSPF => {
+ f.write_str("cspf")
+ },
+ Opcode::CSFM => {
+ f.write_str("csfm")
+ },
+ Opcode::CSET => {
+ f.write_str("cset")
+ },
+ Opcode::CHSR => {
+ f.write_str("chsr")
+ },
+ Opcode::CSNE => {
+ f.write_str("csne")
+ },
+ Opcode::CSTR => {
+ f.write_str("cstr")
+ },
+ Opcode::CSBT => {
+ f.write_str("csbt")
+ },
+ Opcode::CCLF => {
+ f.write_str("cclf")
+ },
+ Opcode::CSRR => {
+ f.write_str("csrr")
+ },
+ Opcode::CRDT => {
+ f.write_str("crdt")
+ },
+ Opcode::CWFM => {
+ f.write_str("cwfm")
+ },
+ Opcode::CSWR => {
+ f.write_str("cswr")
+ },
+ Opcode::CWRT => {
+ f.write_str("cwrt")
+ },
+ Opcode::TWSM => {
+ f.write_str("twsm")
+ },
+ Opcode::TWDSZ => {
+ f.write_str("twdsz")
+ },
+ Opcode::TWISZ => {
+ f.write_str("twisz")
+ },
+ Opcode::TWSB => {
+ f.write_str("twsb")
+ },
+ Opcode::TWAD => {
+ f.write_str("twad")
+ },
+ Opcode::TWLD => {
+ f.write_str("twld")
+ },
+ Opcode::TWST => {
+ f.write_str("twst")
+ },
+ Opcode::TWJMP => {
+ f.write_str("twjmp")
+ },
+ Opcode::TWJPS => {
+ f.write_str("twjps")
+ },
+ Opcode::MPY => {
+ f.write_str("mpy")
+ },
+ Opcode::DIV => {
+ f.write_str("div")
+ },
+ Opcode::RFOV => {
+ f.write_str("rfov")
+ },
+ Opcode::IOFF => {
+ f.write_str("ioff")
+ },
+ Opcode::IONH => {
+ f.write_str("ionh")
+ },
+ Opcode::IONA => {
+ f.write_str("iona")
+ },
+ Opcode::IONB => {
+ f.write_str("ionb")
+ },
+ Opcode::IONN => {
+ f.write_str("ionn")
+ },
+ Opcode::LJSW => {
+ f.write_str("ljsw")
+ },
+ Opcode::LJST => {
+ f.write_str("ljst")
+ },
+ Opcode::And => {
+ f.write_str("and")
+ },
+ Opcode::Load => {
+ f.write_str("load")
+ }, // load op[0] from [1]
+ Opcode::Exchange => {
+ f.write_str("exchange")
+ }, // exchange op[0], op[1]
+ Opcode::AddJK => {
+ f.write_str("addjk")
+ }, // `op[0] + op[1] to op[2]`
+ Opcode::SubJK => {
+ f.write_str("subjk")
+ }, // `op[0] - op[1] to op[2]`
+ Opcode::AddR => {
+ f.write_str("addr")
+ }, // `op[0] + op[1] to op[2]`
+ Opcode::SubR => {
+ f.write_str("subr")
+ }, // `op[0] - op[1] to op[2]`
+ Opcode::NegAddJK => {
+ f.write_str("negaddjk")
+ }, // `-(op[0] + op[1]) to op[2]`
+ Opcode::NegSubJK => {
+ f.write_str("negsubjk")
+ }, // `(op[1] - op[0]) to op[2]`
+ Opcode::NegAddR => {
+ f.write_str("negaddr")
+ }, // `-(op[0] + op[1]) to op[2]`
+ Opcode::NegSubR => {
+ f.write_str("negsubr")
+ }, // `(op[1] - op[0]) to op[2]`
+ Opcode::Shift => {
+ f.write_str("shift")
+ }, // `j <<= N`, what is N?
+ Opcode::Rotate => {
+ f.write_str("rotate")
+ }, // `j <<= N`, what is N?
+ Opcode::SNZ => {
+ f.write_str("snz")
+ },
+ Opcode::SIZ => {
+ f.write_str("siz")
+ },
+ Opcode::CLR => {
+ f.write_str("clr")
+ },
+ Opcode::CMP => {
+ f.write_str("cmp")
+ },
+ Opcode::SET => {
+ f.write_str("set")
+ },
+ Opcode::SKPL => {
+ f.write_str("skpl")
+ },
+ Opcode::PION => {
+ f.write_str("pion")
+ },
+ Opcode::PIOF => {
+ f.write_str("piof")
+ },
+ Opcode::SIP => {
+ f.write_str("sip")
+ },
+ Opcode::INC => {
+ f.write_str("inc")
+ },
+ Opcode::SIN => {
+ f.write_str("sin")
+ },
+ Opcode::NEG => {
+ f.write_str("neg")
+ },
+ Opcode::ANDF => {
+ f.write_str("andf")
+ },
+ Opcode::ANDL => {
+ f.write_str("andl")
+ },
+ Opcode::ADDL => {
+ f.write_str("addl")
+ },
+ Opcode::SUBL => {
+ f.write_str("subl")
+ },
+ Opcode::SMJ => {
+ f.write_str("smj")
+ },
+ Opcode::DSZ => {
+ f.write_str("dsz")
+ },
+ Opcode::ISZ => {
+ f.write_str("isz")
+ },
+ Opcode::SBJ => {
+ f.write_str("sbj")
+ },
+ Opcode::ADJ => {
+ f.write_str("adj")
+ },
+ Opcode::LDJ => {
+ f.write_str("ldj")
+ },
+ Opcode::STJ => {
+ f.write_str("stj")
+ },
+ Opcode::JMP => {
+ f.write_str("jmp")
+ },
+ Opcode::SKIP => {
+ f.write_str("skip")
+ },
+ Opcode::JPS => {
+ f.write_str("jps")
+ },
+ Opcode::XCT => {
+ f.write_str("xct")
+ },
+ Opcode::TIF => {
+ f.write_str("tif")
+ },
+ Opcode::TIR => {
+ f.write_str("tir")
+ },
+ Opcode::TRF => {
+ f.write_str("trf")
+ },
+ Opcode::TIS => {
+ f.write_str("tis")
+ },
+ Opcode::TOC => {
+ f.write_str("toc")
+ },
+ Opcode::TOP => {
+ f.write_str("top")
+ },
+ Opcode::TCP => {
+ f.write_str("tcp")
+ },
+ Opcode::TOS => {
+ f.write_str("tos")
+ },
+ Opcode::HIF => {
+ f.write_str("hif")
+ },
+ Opcode::HIR => {
+ f.write_str("hir")
+ },
+ Opcode::HRF => {
+ f.write_str("hrf")
+ },
+ Opcode::HIS => {
+ f.write_str("his")
+ },
+ Opcode::HOP => {
+ f.write_str("hop")
+ },
+ Opcode::HOL => {
+ f.write_str("hol")
+ },
+ Opcode::HLP => {
+ f.write_str("hlp")
+ },
+ Opcode::HOS => {
+ f.write_str("hos")
+ },
+ Opcode::CSLCT1 => {
+ f.write_str("cslct1")
+ },
+ Opcode::CSLCT2 => {
+ f.write_str("cslct2")
+ },
+ Opcode::CSLCT3 => {
+ f.write_str("cslct3")
+ },
+ Opcode::LDREG => {
+ f.write_str("ldreg")
+ },
+ Opcode::LDJK => {
+ f.write_str("ldjk")
+ },
+ Opcode::RJIB => {
+ f.write_str("rjib")
+ },
+ }
+ }
+}