mod data; mod error; mod instr; mod parse; mod patches; pub use parse::parse; #[cfg(test)] mod tests { use crate::parse; use crate::instr::{Op, Flatten}; use crate::data::{Wr, DstDisp, Register, SrcDisp, Rd}; use crate::data::literal::{Value, Addr}; use std::sync::atomic::AtomicU32; #[test] fn test_parse_empty() { let parsed = parse(" () ").unwrap(); assert_eq!(Vec::::new(), parsed); } #[test] fn test_parse_empty_routine() { let parsed = parse(" ( (hello) ) ").unwrap(); assert_eq!(vec![ Op::Routine("hello".into()), Op::Barrier(Some("Routine \"hello\" overrun".into())) ], parsed); let parsed = parse(" ( (hello) (world) ) ").unwrap(); assert_eq!(vec![ Op::Routine("hello".into()), Op::Barrier(Some("Routine \"hello\" overrun".into())), Op::Routine("world".into()), Op::Barrier(Some("Routine \"world\" overrun".into())) ], parsed); } #[test] fn test_parse_data_formats() { let parsed = parse(" ( (move (mov r0 r1) (mov r15 7) (mov r15 0xabcd) (mov r7 0b11110000) (mov r7 arg1) (mov r255 arg255) (mov r7 res0) (mov r7 res255) (mov @r0 @r0) ; test in both Rd and Wr positions (mov @r0 @arg0) (mov @r0 @res0) (mov @123456 @0x123456) (mov @0b010101 @0b010101) ) ) ").unwrap(); assert_eq!(vec![ Op::Routine("move".into()), // (mov r0 r1) Op::Mov( Wr::new(DstDisp::Register(Register::Gen(0))), Rd::new(SrcDisp::Register(Register::Gen(1))), ), // (mov r15 7) Op::Mov( Wr::new(DstDisp::Register(Register::Gen(15))), Rd::new(SrcDisp::Immediate(Value(7))), ), // (mov r15 0xabcd) Op::Mov( Wr::new(DstDisp::Register(Register::Gen(15))), Rd::new(SrcDisp::Immediate(Value(0xabcd))), ), // (mov r7 0b11110000) Op::Mov( Wr::new(DstDisp::Register(Register::Gen(7))), Rd::new(SrcDisp::Immediate(Value(0b11110000))), ), // (mov r7 arg1) Op::Mov( Wr::new(DstDisp::Register(Register::Gen(7))), Rd::new(SrcDisp::Register(Register::Arg(1))), ), // (mov r255 arg255) Op::Mov( Wr::new(DstDisp::Register(Register::Gen(255))), Rd::new(SrcDisp::Register(Register::Arg(255))), ), // (mov r7 res0) Op::Mov( Wr::new(DstDisp::Register(Register::Gen(7))), Rd::new(SrcDisp::Register(Register::Res(0))), ), // (mov r7 res255) Op::Mov( Wr::new(DstDisp::Register(Register::Gen(7))), Rd::new(SrcDisp::Register(Register::Res(255))), ), // (mov @r0 @r0) Op::Mov( Wr::new(DstDisp::RegisterPtr(Register::Gen(0))), Rd::new(SrcDisp::RegisterPtr(Register::Gen(0))), ), // (mov @r0 @arg0) Op::Mov( Wr::new(DstDisp::RegisterPtr(Register::Gen(0))), Rd::new(SrcDisp::RegisterPtr(Register::Arg(0))), ), // (mov @r0 @res0) Op::Mov( Wr::new(DstDisp::RegisterPtr(Register::Gen(0))), Rd::new(SrcDisp::RegisterPtr(Register::Res(0))), ), // (mov @123456 @0x123456) Op::Mov( Wr::new(DstDisp::ImmediatePtr(Addr(123456))), Rd::new(SrcDisp::ImmediatePtr(Addr(0x123456))), ), // (mov @0b010101 @0b010101) Op::Mov( Wr::new(DstDisp::ImmediatePtr(Addr(0b010101))), Rd::new(SrcDisp::ImmediatePtr(Addr(0b010101))), ), Op::Barrier(Some("Routine \"move\" overrun".into())), ], parsed); } fn parse_single_instr(src : &str) -> anyhow::Result> { let num = AtomicU32::new(0); Ok(parse::parse_instructions(vec![sexp::parse(src)?])?.remove(0).flatten(&num)?) } #[test] fn test_parse_single() { let parsed = parse_single_instr("(mov r0 r1)").unwrap(); assert_eq!(vec![ Op::Mov( Wr::new(DstDisp::Register(Register::Gen(0))), Rd::new(SrcDisp::Register(Register::Gen(1))), ), ], parsed); } }