Croissant Runtime
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
crsn/csn_asm/src/lib.rs

158 lines
4.9 KiB

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::<Op>::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<Vec<Op>> {
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);
}
}