From c019533617ee9609dd63e4ba9fbb9c69b6e062cd Mon Sep 17 00:00:00 2001 From: Cassie Jones Date: Sat, 11 Jan 2020 19:35:23 -0500 Subject: [PATCH] Add instruction formatter --- toolchain/proptest-regressions/inst/test.txt | 2 + toolchain/src/inst.rs | 1 + toolchain/src/inst/format.rs | 90 ++++++++++++++++++++ toolchain/src/inst/parse.rs | 12 ++- toolchain/src/inst/test.rs | 6 ++ 5 files changed, 108 insertions(+), 3 deletions(-) create mode 100644 toolchain/src/inst/format.rs diff --git a/toolchain/proptest-regressions/inst/test.txt b/toolchain/proptest-regressions/inst/test.txt index 03111a6..29b62c8 100644 --- a/toolchain/proptest-regressions/inst/test.txt +++ b/toolchain/proptest-regressions/inst/test.txt @@ -7,3 +7,5 @@ cc ecdd893edc935d8d4eb2eb12057b49f81f30d7211ffe3821f199f895e6c1dfb3 # shrinks to inst = LdD(D1, Reg(U3(0)), false) cc a7153639ea7f091987410d362c4639c35081fc2ecccf65bb9971a8570ae230d9 # shrinks to inst = Jump(OffImm(0)) cc 316327f54ddfe6fb212d24b80e401bea293a0c836cba642afafe92df51f0480f # shrinks to inst = Swap(Reg(U3(0))) +cc 522cccd0010f31b23002b57b05f29184dca074603944d1618f7a3db3d0204b73 # shrinks to inst = AluI(Add(AddImm(10))) +cc 8b07613f990cb839991917fd9e8e8ba8ac20a135a8e4d14ee26c0c4eb809d67b # shrinks to inst = AluI(Compact(Lsl, U3(0))) diff --git a/toolchain/src/inst.rs b/toolchain/src/inst.rs index eddfd34..9f2eaf6 100644 --- a/toolchain/src/inst.rs +++ b/toolchain/src/inst.rs @@ -1,5 +1,6 @@ pub mod decode; pub mod encode; +mod format; pub mod parse; #[cfg(test)] pub mod test; diff --git a/toolchain/src/inst/format.rs b/toolchain/src/inst/format.rs new file mode 100644 index 0000000..f9f9028 --- /dev/null +++ b/toolchain/src/inst/format.rs @@ -0,0 +1,90 @@ +use super::{AddImm, AluI as OpI, Data, Inst, Op1, OpI3, OpR, Reg, Special, Target, U3}; +use std::fmt::{self, Display, Formatter}; + +fn data(d: Data) -> &'static str { + match d { + Data::D1 => "1", + Data::D2 => "2", + } +} + +fn special(s: Special) -> &'static str { + match s { + Special::Data(d) => data(d), + Special::Code => "C", + } +} + +fn flag(x: bool) -> &'static str { + if x { + "!" + } else { + "" + } +} + +impl Display for Inst { + fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { + use Inst::*; + match *self { + Trap => write!(fmt, "TRAP"), + Jump(Target::Abs) => write!(fmt, "JABS"), + Call(Target::Abs) => write!(fmt, "CABS"), + Jump(Target::Off) => write!(fmt, "JOFF"), + Call(Target::Off) => write!(fmt, "COFF"), + Swap(r) => write!(fmt, "SWAP {}", r), + GetR(r) => write!(fmt, "GETR {}", r), + SetR(r) => write!(fmt, "SETR {}", r), + Get(s) => write!(fmt, "GET{}", special(s)), + Set(s) => write!(fmt, "SET{}", special(s)), + Alu1(Op1::Zero) => write!(fmt, "ZERO"), + Alu1(Op1::Lsl1) => write!(fmt, "LSL1"), + Alu1(Op1::Lsr1) => write!(fmt, "LSR1"), + Alu1(Op1::Asr1) => write!(fmt, "ASR1"), + Alu1(Op1::Incr) => write!(fmt, "INCR"), + Alu1(Op1::Decr) => write!(fmt, "DECR"), + Alu1(Op1::Comp) => write!(fmt, "COMP"), + Alu1(Op1::Negt) => write!(fmt, "NEGT"), + IsLt(r) => write!(fmt, "ISLT {}", r), + AluR(OpR::Add, r) => write!(fmt, "ADDR {}", r), + AluR(OpR::Sub, r) => write!(fmt, "SUBR {}", r), + AluR(OpR::And, r) => write!(fmt, "ANDR {}", r), + AluR(OpR::Ior, r) => write!(fmt, "IORR {}", r), + AluR(OpR::Xor, r) => write!(fmt, "XORR {}", r), + AluR(OpR::Lsl, r) => write!(fmt, "LSLR {}", r), + AluR(OpR::Lsr, r) => write!(fmt, "LSRR {}", r), + AluR(OpR::Asr, r) => write!(fmt, "ASRR {}", r), + LdD(d, r, i) => write!(fmt, "LD{}U {}{}", data(d), r, flag(i)), + StD(d, r, i) => write!(fmt, "ST{}U {}{}", data(d), r, flag(i)), + AluI(OpI::And(i)) => write!(fmt, "ANDI #x{:02X}", i), + AluI(OpI::Ior(i)) => write!(fmt, "IORI #x{:02X}", i), + AluI(OpI::Xor(i)) => write!(fmt, "XORI #x{:02X}", i), + AluI(OpI::Add(AddImm(i))) => write!(fmt, "ADDI #{}", i), + AluI(OpI::Compact(op, i)) => match op { + OpI3::Rol => write!(fmt, "ROLI #{}", i), + OpI3::Lsl => write!(fmt, "LSLI #{}", i), + OpI3::Lsr => write!(fmt, "LSRI #{}", i), + OpI3::Asr => write!(fmt, "ASRI #{}", i), + OpI3::Clr => write!(fmt, "CLRI #{}", i), + OpI3::Set => write!(fmt, "SETI #{}", i), + OpI3::Tog => write!(fmt, "TOGI #{}", i), + OpI3::Ext => write!(fmt, "EXTI #{}", i), + }, + BEzI(off) => write!(fmt, "BEZI #{}", off), + Jump(Target::OffImm(i)) => write!(fmt, "JOFI #{}", i), + Call(Target::OffImm(i)) => write!(fmt, "COFI #{}", i), + } + } +} + +impl Display for Reg { + fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { + write!(fmt, "r{}", self.0) + } +} + +impl Display for U3 { + fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { + write!(fmt, "{}", self.0) + } +} diff --git a/toolchain/src/inst/parse.rs b/toolchain/src/inst/parse.rs index 94574d7..d761c00 100644 --- a/toolchain/src/inst/parse.rs +++ b/toolchain/src/inst/parse.rs @@ -103,17 +103,23 @@ fn imm_dec(s: &str) -> IResult<&str, i16> { fn imm_hex(s: &str) -> IResult<&str, i16> { let text = recognize(hex_digit1); - map_res(preceded(tag_no_case("#x"), text), |x| i16::from_str_radix(x, 16))(s) + map_res(preceded(tag_no_case("#x"), text), |x| { + i16::from_str_radix(x, 16) + })(s) } fn imm_oct(s: &str) -> IResult<&str, i16> { let text = recognize(oct_digit1); - map_res(preceded(tag_no_case("#o"), text), |x| i16::from_str_radix(x, 8))(s) + map_res(preceded(tag_no_case("#o"), text), |x| { + i16::from_str_radix(x, 8) + })(s) } fn imm_bin(s: &str) -> IResult<&str, i16> { let text = recognize(many1(one_of("01"))); - map_res(preceded(tag_no_case("#b"), text), |x| i16::from_str_radix(x, 2))(s) + map_res(preceded(tag_no_case("#b"), text), |x| { + i16::from_str_radix(x, 2) + })(s) } fn imm(s: &str) -> IResult<&str, i16> { diff --git a/toolchain/src/inst/test.rs b/toolchain/src/inst/test.rs index 20fb028..1c1b5dd 100644 --- a/toolchain/src/inst/test.rs +++ b/toolchain/src/inst/test.rs @@ -12,6 +12,12 @@ proptest! { let decoded = Inst::decode(&mut cursor).expect("to decode"); prop_assert_eq!(inst, decoded); } + + #[test] + fn format_roundtrip(inst: Inst) { + let formatted = format!("{}", inst); + prop_assert_eq!(parse::parse_inst(&formatted).unwrap(), inst, "formatted as {:?}", formatted); + } } fn display(buf: &[u8]) -> String { -- 2.47.0