|
|
@ -9,10 +9,11 @@ pub use parse::parse; |
|
|
|
#[cfg(test)] |
|
|
|
#[cfg(test)] |
|
|
|
mod tests { |
|
|
|
mod tests { |
|
|
|
use crate::parse; |
|
|
|
use crate::parse; |
|
|
|
use crate::instr::{Op, Flatten}; |
|
|
|
use crate::instr::{Op, Flatten, Instr}; |
|
|
|
use crate::data::{Wr, DstDisp, Register, SrcDisp, Rd}; |
|
|
|
use crate::data::{Wr, DstDisp, Register, SrcDisp, Rd}; |
|
|
|
use crate::data::literal::{Value, Addr}; |
|
|
|
use crate::data::literal::{Value, Addr, Label}; |
|
|
|
use std::sync::atomic::AtomicU32; |
|
|
|
use std::sync::atomic::AtomicU32; |
|
|
|
|
|
|
|
use crate::instr::Cond; |
|
|
|
|
|
|
|
|
|
|
|
#[test] |
|
|
|
#[test] |
|
|
|
fn test_parse_empty() { |
|
|
|
fn test_parse_empty() { |
|
|
@ -140,14 +141,18 @@ mod tests { |
|
|
|
], parsed); |
|
|
|
], parsed); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fn parse_single_instr(src : &str) -> anyhow::Result<Vec<Op>> { |
|
|
|
fn parse_single_instr(src : &str) -> anyhow::Result<Instr> { |
|
|
|
|
|
|
|
Ok(parse::parse_instructions(vec![sexp::parse(src)?])?.remove(0)) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn parse_single_op(src : &str) -> anyhow::Result<Vec<Op>> { |
|
|
|
let num = AtomicU32::new(0); |
|
|
|
let num = AtomicU32::new(0); |
|
|
|
Ok(parse::parse_instructions(vec![sexp::parse(src)?])?.remove(0).flatten(&num)?) |
|
|
|
Ok(parse_single_instr(src)?.flatten(&num)?) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#[test] |
|
|
|
#[test] |
|
|
|
fn test_parse_single() { |
|
|
|
fn test_parse_single() { |
|
|
|
let parsed = parse_single_instr("(mov r0 r1)").unwrap(); |
|
|
|
let parsed = parse_single_op("(mov r0 r1)").unwrap(); |
|
|
|
assert_eq!(vec![ |
|
|
|
assert_eq!(vec![ |
|
|
|
Op::Mov( |
|
|
|
Op::Mov( |
|
|
|
Wr::new(DstDisp::Register(Register::Gen(0))), |
|
|
|
Wr::new(DstDisp::Register(Register::Gen(0))), |
|
|
@ -155,4 +160,99 @@ mod tests { |
|
|
|
), |
|
|
|
), |
|
|
|
], parsed); |
|
|
|
], parsed); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[test] |
|
|
|
|
|
|
|
fn test_branches_instr() { |
|
|
|
|
|
|
|
let parsed = parse_single_instr(" |
|
|
|
|
|
|
|
(cmp r0 r1 (eq? (mov r0 r0) (mov r1 r2)) (>? (mov r0 r0) (mov r1 r1))) |
|
|
|
|
|
|
|
").unwrap(); |
|
|
|
|
|
|
|
assert_eq!( |
|
|
|
|
|
|
|
Instr { |
|
|
|
|
|
|
|
op: Op::Cmp( |
|
|
|
|
|
|
|
Rd::new(SrcDisp::Register(Register::Gen(0))), |
|
|
|
|
|
|
|
Rd::new(SrcDisp::Register(Register::Gen(1))), |
|
|
|
|
|
|
|
), |
|
|
|
|
|
|
|
branches: Some(vec![ |
|
|
|
|
|
|
|
( |
|
|
|
|
|
|
|
Cond::Equal, |
|
|
|
|
|
|
|
vec![ |
|
|
|
|
|
|
|
Instr { |
|
|
|
|
|
|
|
op: Op::Mov( |
|
|
|
|
|
|
|
Wr::new(DstDisp::Register(Register::Gen(0))), |
|
|
|
|
|
|
|
Rd::new(SrcDisp::Register(Register::Gen(0))), |
|
|
|
|
|
|
|
), |
|
|
|
|
|
|
|
branches: None |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
Instr { |
|
|
|
|
|
|
|
op: Op::Mov( |
|
|
|
|
|
|
|
Wr::new(DstDisp::Register(Register::Gen(1))), |
|
|
|
|
|
|
|
Rd::new(SrcDisp::Register(Register::Gen(2))), |
|
|
|
|
|
|
|
), |
|
|
|
|
|
|
|
branches: None |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
), |
|
|
|
|
|
|
|
( |
|
|
|
|
|
|
|
Cond::Greater, |
|
|
|
|
|
|
|
vec![ |
|
|
|
|
|
|
|
Instr { |
|
|
|
|
|
|
|
op: Op::Mov( |
|
|
|
|
|
|
|
Wr::new(DstDisp::Register(Register::Gen(0))), |
|
|
|
|
|
|
|
Rd::new(SrcDisp::Register(Register::Gen(0))), |
|
|
|
|
|
|
|
), |
|
|
|
|
|
|
|
branches: None |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
Instr { |
|
|
|
|
|
|
|
op: Op::Mov( |
|
|
|
|
|
|
|
Wr::new(DstDisp::Register(Register::Gen(1))), |
|
|
|
|
|
|
|
Rd::new(SrcDisp::Register(Register::Gen(1))), |
|
|
|
|
|
|
|
), |
|
|
|
|
|
|
|
branches: None |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
]) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
, parsed); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[test] |
|
|
|
|
|
|
|
fn test_branches_op() { |
|
|
|
|
|
|
|
let parsed = parse_single_op(" |
|
|
|
|
|
|
|
(cmp r0 r1 |
|
|
|
|
|
|
|
(eq? |
|
|
|
|
|
|
|
(mov r0 r0) |
|
|
|
|
|
|
|
(mov r1 r2)) |
|
|
|
|
|
|
|
(>? |
|
|
|
|
|
|
|
(mov r0 r0) |
|
|
|
|
|
|
|
(mov r1 r1))) |
|
|
|
|
|
|
|
").unwrap(); |
|
|
|
|
|
|
|
assert_eq!( |
|
|
|
|
|
|
|
vec![ |
|
|
|
|
|
|
|
Op::Cmp( |
|
|
|
|
|
|
|
Rd::new(SrcDisp::Register(Register::Gen(0))), |
|
|
|
|
|
|
|
Rd::new(SrcDisp::Register(Register::Gen(1))), |
|
|
|
|
|
|
|
), |
|
|
|
|
|
|
|
Op::JumpIf(Cond::NotEqual, Label::Numbered(0)), |
|
|
|
|
|
|
|
Op::Mov( |
|
|
|
|
|
|
|
Wr::new(DstDisp::Register(Register::Gen(0))), |
|
|
|
|
|
|
|
Rd::new(SrcDisp::Register(Register::Gen(0))), |
|
|
|
|
|
|
|
), |
|
|
|
|
|
|
|
Op::Mov( |
|
|
|
|
|
|
|
Wr::new(DstDisp::Register(Register::Gen(1))), |
|
|
|
|
|
|
|
Rd::new(SrcDisp::Register(Register::Gen(2))), |
|
|
|
|
|
|
|
), |
|
|
|
|
|
|
|
Op::Label(Label::Numbered(0)), |
|
|
|
|
|
|
|
Op::JumpIf(Cond::LessOrEqual, Label::Numbered(1)), |
|
|
|
|
|
|
|
Op::Mov( |
|
|
|
|
|
|
|
Wr::new(DstDisp::Register(Register::Gen(0))), |
|
|
|
|
|
|
|
Rd::new(SrcDisp::Register(Register::Gen(0))), |
|
|
|
|
|
|
|
), |
|
|
|
|
|
|
|
Op::Mov( |
|
|
|
|
|
|
|
Wr::new(DstDisp::Register(Register::Gen(1))), |
|
|
|
|
|
|
|
Rd::new(SrcDisp::Register(Register::Gen(1))), |
|
|
|
|
|
|
|
), |
|
|
|
|
|
|
|
Op::Label(Label::Numbered(1)), |
|
|
|
|
|
|
|
], parsed); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|