From def2fc8db08839e42145d1b5fac1fecabb28e938 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Wed, 23 Sep 2020 00:14:37 +0200 Subject: [PATCH] add low level ops enum --- csn_asm/src/data/mod.rs | 11 +- csn_asm/src/data/reg.rs | 18 +++- csn_asm/src/error.rs | 2 + csn_asm/src/instr/flatten.rs | 41 ++++---- csn_asm/src/instr/mod.rs | 5 +- csn_asm/src/instr/op.rs | 41 +++++--- csn_asm/src/lib.rs | 176 +++++++++++++++++--------------- csn_asm/src/parse/mod.rs | 4 +- csn_asm/src/parse/parse_data.rs | 26 ++--- csn_asm/src/parse/parse_op.rs | 64 +++++++----- 10 files changed, 206 insertions(+), 182 deletions(-) diff --git a/csn_asm/src/data/mod.rs b/csn_asm/src/data/mod.rs index c01cfc7..5b9b419 100644 --- a/csn_asm/src/data/mod.rs +++ b/csn_asm/src/data/mod.rs @@ -1,15 +1,14 @@ use super::error::AsmError; -pub(crate) mod literal; -mod reg; -mod mask; +pub mod literal; +pub mod reg; +pub mod mask; pub use reg::Register; pub use mask::Mask; use literal::Addr; - use std::convert::TryFrom; use crate::data::literal::Value; @@ -79,7 +78,7 @@ impl TryFrom for DstDisp { /// Data source argument (read-only) #[derive(Debug, Clone, Copy, Eq, PartialEq)] -pub struct Rd(pub SrcDisp, pub Mask); +pub struct Rd(SrcDisp, Mask); impl Rd { pub fn new(src : SrcDisp) -> Self { @@ -89,7 +88,7 @@ impl Rd { /// Data destination argument (read-write) #[derive(Debug, Clone, Copy, Eq, PartialEq)] -pub struct Wr(pub DstDisp, pub Mask); +pub struct Wr(DstDisp, Mask); impl Wr { pub fn new(dst : DstDisp) -> Self { diff --git a/csn_asm/src/data/reg.rs b/csn_asm/src/data/reg.rs index 1c85844..2109817 100644 --- a/csn_asm/src/data/reg.rs +++ b/csn_asm/src/data/reg.rs @@ -1,4 +1,5 @@ use std::fmt::{self, Display, Formatter}; +use crate::error::Error; /// Register name #[derive(Debug, Clone, Copy, Eq, PartialEq)] @@ -8,7 +9,7 @@ pub enum Register { /// Result register, read-only Res(u8), /// General purpose register - Gen(u8) + Gen(u8), } impl Display for Register { @@ -20,3 +21,18 @@ impl Display for Register { } } } + +pub fn parse_reg(name : &str) -> anyhow::Result { + if let Some(rn) = name.strip_prefix("arg") { + let val : u8 = rn.parse()?; + Ok(Register::Arg(val)) + } else if let Some(rn) = name.strip_prefix("res") { + let val : u8 = rn.parse()?; + Ok(Register::Res(val)) + } else if let Some(rn) = name.strip_prefix("r") { + let val : u8 = rn.parse()?; + Ok(Register::Gen(val)) + } else { + Err(Error::Parse(format!("Bad reg name: {}", name).into()))? + } +} diff --git a/csn_asm/src/error.rs b/csn_asm/src/error.rs index 8c785df..bee9bc4 100644 --- a/csn_asm/src/error.rs +++ b/csn_asm/src/error.rs @@ -37,6 +37,8 @@ pub enum AsmError { ConditionalAlreadyUsed(Cond), #[error("Label \"{0:?}\" not defined")] LabelNotDefined(Label), + #[error("Bad register type: {0}")] + BadRegisterType(Register), } /// Architectural error - the code is syntactically OK, but cannot run diff --git a/csn_asm/src/instr/flatten.rs b/csn_asm/src/instr/flatten.rs index 42fa0d3..b8d0eeb 100644 --- a/csn_asm/src/instr/flatten.rs +++ b/csn_asm/src/instr/flatten.rs @@ -1,18 +1,17 @@ use std::sync::atomic::AtomicU32; -use crate::instr::{Op, Instr, Cond, Routine}; +use crate::instr::{HLOp, Instr, Cond, Routine, Op}; use crate::error::{Error, AsmError}; use std::collections::HashMap; use crate::data::literal::{Label, Value}; -use crate::instr::op::Op::{Skip, SkipIf}; -use crate::data::{Rd, SrcDisp, Mask}; +use crate::data::{Rd, SrcDisp}; /// A trait for something that can turn into multiple instructions pub trait Flatten { - fn flatten(self, label_num: &AtomicU32) -> Result, Error>; + fn flatten(self, label_num: &AtomicU32) -> Result, Error>; } impl Flatten for Instr { - fn flatten(self, label_num: &AtomicU32) -> Result, Error> { + fn flatten(self, label_num: &AtomicU32) -> Result, Error> { let mut ops = vec![self.op]; if let Some(branches) = self.branches { @@ -29,18 +28,18 @@ impl Flatten for Instr { } else { Label::unique(label_num) }; - ops.push(Op::JumpIf(!cond, next_lbl.clone())); + ops.push(HLOp::JumpIf(!cond, next_lbl.clone())); for branch_instr in branch { ops.extend(branch_instr.flatten(label_num)?); } if cnt != branch_count - 1 { - ops.push(Op::Jump(end_lbl.clone())); - ops.push(Op::Label(next_lbl)); + ops.push(HLOp::Jump(end_lbl.clone())); + ops.push(HLOp::Label(next_lbl)); } } - ops.push(Op::Label(end_lbl)); + ops.push(HLOp::Label(end_lbl)); } Ok(ops) @@ -48,25 +47,25 @@ impl Flatten for Instr { } impl Flatten for Routine { - fn flatten(self, label_num: &AtomicU32) -> Result, Error> { + fn flatten(self, label_num: &AtomicU32) -> Result, Error> { let mut ops = vec![ - Op::Routine(self.name.clone()), + Op::Routine(self.name.clone()).into(), ]; for instr in self.body { ops.extend(instr.flatten(label_num)?); } - ops.push(Op::Barrier(Some(format!("Routine \"{}\" overrun", self.name).into()))); + ops.push(Op::Barrier(Some(format!("Routine \"{}\" overrun", self.name).into())).into()); Ok(ops) } } /// Convert jumps to relative skips -pub fn jumps_to_skips(ops: Vec) -> Result, Error> { +pub fn lower(ops: Vec) -> Result, Error> { let mut label_positions = HashMap::::new(); for (n, op) in ops.iter().enumerate() { - if let Op::Label(name) = op { + if let HLOp::Label(name) = op { label_positions.insert(name.clone(), n - label_positions.len()); } } @@ -75,27 +74,27 @@ pub fn jumps_to_skips(ops: Vec) -> Result, Error> { let mut skipped = 0; for (n, op) in ops.into_iter().enumerate() { match op { - Op::Label(_) => { + HLOp::Label(_) => { skipped += 1; } - Op::Jump(target) => { + HLOp::Jump(target) => { if let Some(dest) = label_positions.get(&target) { let skip = *dest as isize - n as isize + skipped; - cleaned.push(Skip(Rd(SrcDisp::Immediate(Value(skip as i64)), Mask::default()))); + cleaned.push(Op::Skip(Rd::new(SrcDisp::Immediate(Value(skip as i64))))); } else { return Err(Error::Asm(AsmError::LabelNotDefined(target))); } } - Op::JumpIf(cond, target) => { + HLOp::JumpIf(cond, target) => { if let Some(dest) = label_positions.get(&target) { let skip = *dest as isize - n as isize + skipped; - cleaned.push(SkipIf(cond, Rd(SrcDisp::Immediate(Value(skip as i64)), Mask::default()))); + cleaned.push(Op::SkipIf(cond, Rd::new(SrcDisp::Immediate(Value(skip as i64))))); } else { return Err(Error::Asm(AsmError::LabelNotDefined(target))); } } - other => { - cleaned.push(other); + HLOp::L(op) => { + cleaned.push(op); } } } diff --git a/csn_asm/src/instr/mod.rs b/csn_asm/src/instr/mod.rs index 1dc420f..4c58a59 100644 --- a/csn_asm/src/instr/mod.rs +++ b/csn_asm/src/instr/mod.rs @@ -3,8 +3,9 @@ mod cond; mod flatten; pub use flatten::Flatten; -pub use flatten::jumps_to_skips; +pub use flatten::lower; +pub use op::HLOp; pub use op::Op; pub use cond::Cond; use crate::data::literal::{RoutineName}; @@ -15,7 +16,7 @@ use crate::data::literal::{RoutineName}; /// A higher-level instruction #[derive(Debug, Clone, Eq, PartialEq)] pub struct Instr { - pub op: Op, + pub op: HLOp, pub branches: Option)>>, } diff --git a/csn_asm/src/instr/op.rs b/csn_asm/src/instr/op.rs index 9709997..b7a5e28 100644 --- a/csn_asm/src/instr/op.rs +++ b/csn_asm/src/instr/op.rs @@ -6,37 +6,37 @@ use crate::data::{ }; use crate::instr::{Cond}; -/// A low level instruction +/// A higher level simple opration #[derive(Clone, Debug, Eq, PartialEq)] -pub enum Op { - /* Marker instructions */ - +pub enum HLOp { /// Mark a jump target. - /// Is optimized out when jumps are replaced by relative skips Label(Label), + /// Jump to a label + Jump(Label), + /// Jump to a label if a flag is set + JumpIf(Cond, Label), + /// Low level op + L(Op), +} + +/// A low level instruction +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum Op { /// Mark a far jump target (can be jumped to from another routine). /// This label is preserved in optimized code. FarLabel(Label), - - /* Control flow */ - - /// Jump to a label - Jump(Label), /// Jump to a label that can be in another function FarJump(Label), - /// Call a routine with arguments + /// Call a routine with arguments. + /// The arguments are passed as argX. Return values are stored in resX registers. Call(RoutineName, Vec), /// Exit the current routine with return values Ret(Vec), - - /* Synthetic instructions */ - - /// Mark a routine entry point (call target) + /// Mark a routine entry point (call target). + /// Kept in the low level instruction file for position-independent code Routine(RoutineName), /// Skip backward or forward Skip(Rd), - /// Jump to a label if a flag is set - JumpIf(Cond, Label), /// Skip if a flag is set SkipIf(Cond, Rd), /// Deny jumps, skips and run across this address, producing a run-time fault with a message. @@ -57,3 +57,10 @@ pub enum Op { // TODO arithmetics, bit manipulation, byte operations } + +/// Make "into" work +impl From for HLOp { + fn from(op: Op) -> Self { + HLOp::L(op) + } +} diff --git a/csn_asm/src/lib.rs b/csn_asm/src/lib.rs index 68bcc8d..19df1ba 100644 --- a/csn_asm/src/lib.rs +++ b/csn_asm/src/lib.rs @@ -1,15 +1,21 @@ -mod data; -mod error; -mod instr; -mod parse; -mod patches; +pub mod data; +pub mod error; +pub mod instr; +pub mod parse; +pub mod patches; -pub use parse::parse; +use crate::instr::{Op, lower}; + +/// Parse a program from string and assemble a low level instruction sequence from it. +pub fn assemble(source : &str) -> Result, error::Error> { + let parsed = parse::parse(source)?; + Ok(lower(parsed)?) +} #[cfg(test)] mod tests { - use crate::parse; - use crate::instr::{Op, Flatten, Instr, jumps_to_skips}; + use crate::parse::{parse, parse_instructions}; + use crate::instr::{HLOp, Op, Flatten, Instr, lower}; use crate::data::{Wr, DstDisp, Register, SrcDisp, Rd}; use crate::data::literal::{Value, Addr, Label}; use std::sync::atomic::AtomicU32; @@ -20,7 +26,7 @@ mod tests { let parsed = parse(" () ").unwrap(); - assert_eq!(Vec::::new(), parsed); + assert_eq!(Vec::::new(), parsed); } #[test] @@ -31,8 +37,8 @@ mod tests { ) ").unwrap(); assert_eq!(vec![ - Op::Routine("hello".into()), - Op::Barrier(Some("Routine \"hello\" overrun".into())) + HLOp::L(Op::Routine("hello".into())), + HLOp::L(Op::Barrier(Some("Routine \"hello\" overrun".into()))) ], parsed); let parsed = parse(" @@ -42,10 +48,10 @@ mod tests { ) ").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())) + HLOp::L(Op::Routine("hello".into())), + HLOp::L(Op::Barrier(Some("Routine \"hello\" overrun".into()))), + HLOp::L(Op::Routine("world".into())), + HLOp::L(Op::Barrier(Some("Routine \"world\" overrun".into()))) ], parsed); } @@ -71,81 +77,81 @@ mod tests { ) ").unwrap(); assert_eq!(vec![ - Op::Routine("move".into()), + HLOp::L(Op::Routine("move".into())), // (mov r0 r1) - Op::Mov( + HLOp::L(Op::Mov( Wr::new(DstDisp::Register(Register::Gen(0))), Rd::new(SrcDisp::Register(Register::Gen(1))), - ), + )), // (mov r15 7) - Op::Mov( + HLOp::L(Op::Mov( Wr::new(DstDisp::Register(Register::Gen(15))), Rd::new(SrcDisp::Immediate(Value(7))), - ), + )), // (mov r15 0xabcd) - Op::Mov( + HLOp::L(Op::Mov( Wr::new(DstDisp::Register(Register::Gen(15))), Rd::new(SrcDisp::Immediate(Value(0xabcd))), - ), + )), // (mov r7 0b11110000) - Op::Mov( + HLOp::L(Op::Mov( Wr::new(DstDisp::Register(Register::Gen(7))), Rd::new(SrcDisp::Immediate(Value(0b11110000))), - ), + )), // (mov r7 arg1) - Op::Mov( + HLOp::L(Op::Mov( Wr::new(DstDisp::Register(Register::Gen(7))), Rd::new(SrcDisp::Register(Register::Arg(1))), - ), + )), // (mov r255 arg255) - Op::Mov( + HLOp::L(Op::Mov( Wr::new(DstDisp::Register(Register::Gen(255))), Rd::new(SrcDisp::Register(Register::Arg(255))), - ), + )), // (mov r7 res0) - Op::Mov( + HLOp::L(Op::Mov( Wr::new(DstDisp::Register(Register::Gen(7))), Rd::new(SrcDisp::Register(Register::Res(0))), - ), + )), // (mov r7 res255) - Op::Mov( + HLOp::L(Op::Mov( Wr::new(DstDisp::Register(Register::Gen(7))), Rd::new(SrcDisp::Register(Register::Res(255))), - ), + )), // (mov @r0 @r0) - Op::Mov( + HLOp::L(Op::Mov( Wr::new(DstDisp::RegisterPtr(Register::Gen(0))), Rd::new(SrcDisp::RegisterPtr(Register::Gen(0))), - ), + )), // (mov @r0 @arg0) - Op::Mov( + HLOp::L(Op::Mov( Wr::new(DstDisp::RegisterPtr(Register::Gen(0))), Rd::new(SrcDisp::RegisterPtr(Register::Arg(0))), - ), + )), // (mov @r0 @res0) - Op::Mov( + HLOp::L(Op::Mov( Wr::new(DstDisp::RegisterPtr(Register::Gen(0))), Rd::new(SrcDisp::RegisterPtr(Register::Res(0))), - ), + )), // (mov @123456 @0x123456) - Op::Mov( + HLOp::L(Op::Mov( Wr::new(DstDisp::ImmediatePtr(Addr(123456))), Rd::new(SrcDisp::ImmediatePtr(Addr(0x123456))), - ), + )), // (mov @0b010101 @0b010101) - Op::Mov( + HLOp::L(Op::Mov( Wr::new(DstDisp::ImmediatePtr(Addr(0b010101))), Rd::new(SrcDisp::ImmediatePtr(Addr(0b010101))), - ), - Op::Barrier(Some("Routine \"move\" overrun".into())), + )), + HLOp::L(Op::Barrier(Some("Routine \"move\" overrun".into()))), ], parsed); } fn parse_single_instr(src : &str) -> anyhow::Result { - Ok(parse::parse_instructions(vec![sexp::parse(src)?])?.remove(0)) + Ok(parse_instructions(vec![sexp::parse(src)?])?.remove(0)) } - fn parse_single_op(src : &str) -> anyhow::Result> { + fn parse_single_op(src : &str) -> anyhow::Result> { let num = AtomicU32::new(0); Ok(parse_single_instr(src)?.flatten(&num)?) } @@ -154,10 +160,10 @@ mod tests { fn test_parse_single() { let parsed = parse_single_op("(mov r0 r1)").unwrap(); assert_eq!(vec![ - Op::Mov( + HLOp::L(Op::Mov( Wr::new(DstDisp::Register(Register::Gen(0))), Rd::new(SrcDisp::Register(Register::Gen(1))), - ), + )), ], parsed); } @@ -168,26 +174,26 @@ mod tests { ").unwrap(); assert_eq!( Instr { - op: Op::Cmp( + op: HLOp::L(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( + op: HLOp::L(Op::Mov( Wr::new(DstDisp::Register(Register::Gen(0))), Rd::new(SrcDisp::Register(Register::Gen(0))), - ), + )), branches: None }, Instr { - op: Op::Mov( + op: HLOp::L(Op::Mov( Wr::new(DstDisp::Register(Register::Gen(1))), Rd::new(SrcDisp::Register(Register::Gen(2))), - ), + )), branches: None } ] @@ -196,17 +202,17 @@ mod tests { Cond::Greater, vec![ Instr { - op: Op::Mov( + op: HLOp::L(Op::Mov( Wr::new(DstDisp::Register(Register::Gen(0))), Rd::new(SrcDisp::Register(Register::Gen(0))), - ), + )), branches: None }, Instr { - op: Op::Mov( + op: HLOp::L(Op::Mov( Wr::new(DstDisp::Register(Register::Gen(1))), Rd::new(SrcDisp::Register(Register::Gen(1))), - ), + )), branches: None } ] @@ -229,31 +235,31 @@ mod tests { ").unwrap(); assert_eq!( vec![ - Op::Cmp( + HLOp::L(Op::Cmp( Rd::new(SrcDisp::Register(Register::Gen(0))), Rd::new(SrcDisp::Register(Register::Gen(1))), - ), - Op::JumpIf(Cond::NotEqual, Label::Numbered(1)), - Op::Mov( + )), + HLOp::JumpIf(Cond::NotEqual, Label::Numbered(1)), + HLOp::L(Op::Mov( Wr::new(DstDisp::Register(Register::Gen(0))), Rd::new(SrcDisp::Register(Register::Gen(0))), - ), - Op::Mov( + )), + HLOp::L(Op::Mov( Wr::new(DstDisp::Register(Register::Gen(1))), Rd::new(SrcDisp::Register(Register::Gen(2))), - ), - Op::Jump(Label::Numbered(0)), - Op::Label(Label::Numbered(1)), - Op::JumpIf(Cond::LessOrEqual, Label::Numbered(0)), - Op::Mov( + )), + HLOp::Jump(Label::Numbered(0)), + HLOp::Label(Label::Numbered(1)), + HLOp::JumpIf(Cond::LessOrEqual, Label::Numbered(0)), + HLOp::L(Op::Mov( Wr::new(DstDisp::Register(Register::Gen(0))), Rd::new(SrcDisp::Register(Register::Gen(0))), - ), - Op::Mov( + )), + HLOp::L(Op::Mov( Wr::new(DstDisp::Register(Register::Gen(1))), Rd::new(SrcDisp::Register(Register::Gen(1))), - ), - Op::Label(Label::Numbered(0)), + )), + HLOp::Label(Label::Numbered(0)), ], parsed); } @@ -277,32 +283,32 @@ mod tests { assert_eq!( vec![ - Op::Routine("foo".into()), - Op::Label(Label::Named("foo".to_string())), - Op::Label(Label::Named("unused".to_string())), - Op::Label(Label::Named("whatever".to_string())), + Op::Routine("foo".into()).into(), + HLOp::Label(Label::Named("foo".to_string())), + HLOp::Label(Label::Named("unused".to_string())), + HLOp::Label(Label::Named("whatever".to_string())), Op::Mov( Wr::new(DstDisp::Register(Register::Gen(0))), Rd::new(SrcDisp::Register(Register::Gen(0))), - ), - Op::Jump(Label::Named("foo".to_string())), - Op::Jump(Label::Named("foo".to_string())), + ).into(), + HLOp::Jump(Label::Named("foo".to_string())), + HLOp::Jump(Label::Named("foo".to_string())), Op::Mov( Wr::new(DstDisp::Register(Register::Gen(0))), Rd::new(SrcDisp::Register(Register::Gen(0))), - ), + ).into(), Op::Mov( Wr::new(DstDisp::Register(Register::Gen(0))), Rd::new(SrcDisp::Register(Register::Gen(0))), - ), - Op::Jump(Label::Named("whatever".to_string())), - Op::JumpIf(Cond::Equal, Label::Named("whatever".to_string())), - Op::Barrier(Some("Routine \"foo\" overrun".into())), + ).into(), + HLOp::Jump(Label::Named("whatever".to_string())), + HLOp::JumpIf(Cond::Equal, Label::Named("whatever".to_string())), + Op::Barrier(Some("Routine \"foo\" overrun".into())).into(), ], parsed); // Labels are removed and jumps become skips - let cleaned = jumps_to_skips(parsed).unwrap(); + let cleaned = lower(parsed).unwrap(); assert_eq!( vec![ diff --git a/csn_asm/src/parse/mod.rs b/csn_asm/src/parse/mod.rs index d878b47..18845a7 100644 --- a/csn_asm/src/parse/mod.rs +++ b/csn_asm/src/parse/mod.rs @@ -1,5 +1,5 @@ -use crate::instr::{Routine, Op, Flatten}; +use crate::instr::{Routine, HLOp, Flatten}; use crate::error::Error; @@ -16,7 +16,7 @@ mod parse_op; use parse_routines::parse_routines; pub use parse_instr::parse_instructions; -pub fn parse(source: &str) -> Result, Error> { +pub fn parse(source: &str) -> Result, Error> { let root = sexp::parse(source)?; let subs: Vec = parse_routines(expect_list(Some(root), true)?)?; diff --git a/csn_asm/src/parse/parse_data.rs b/csn_asm/src/parse/parse_data.rs index 3d4b6f8..96db275 100644 --- a/csn_asm/src/parse/parse_data.rs +++ b/csn_asm/src/parse/parse_data.rs @@ -1,10 +1,11 @@ use sexp::{Sexp, Atom}; -use crate::data::{DataDisp, Register, Rd, Mask, Wr, DstDisp, SrcDisp}; +use crate::data::{DataDisp, Rd, Wr, DstDisp, SrcDisp, reg}; use crate::error::Error; use crate::data::literal::{Value, Addr, Label}; use std::convert::TryFrom; use crate::parse::sexp_expect::expect_string_atom; +/// Parse a label pub fn parse_label(name : Option) -> Result { let name = expect_string_atom(name)?; Ok(Label::Named(name.trim_start_matches(':').into())) @@ -30,12 +31,12 @@ pub fn parse_data_disp(tok: Option) -> Result { let val : u64 = parse_u64(reference)?; Ok(DataDisp::ImmediatePtr(Addr(val))) } else { - Ok(DataDisp::RegisterPtr(parse_reg(reference)?)) + Ok(DataDisp::RegisterPtr(reg::parse_reg(reference)?)) } } else if s.starts_with(|c : char| c.is_ascii_digit()) { Ok(DataDisp::Immediate(Value(parse_i64(s)?))) } else { - Ok(DataDisp::Register(parse_reg(s)?)) + Ok(DataDisp::Register(reg::parse_reg(s)?)) } }, _ => { @@ -44,21 +45,6 @@ pub fn parse_data_disp(tok: Option) -> Result { } } -pub fn parse_reg(name : &str) -> anyhow::Result { - if let Some(rn) = name.strip_prefix("arg") { - let val : u8 = rn.parse()?; - Ok(Register::Arg(val)) - } else if let Some(rn) = name.strip_prefix("res") { - let val : u8 = rn.parse()?; - Ok(Register::Res(val)) - } else if let Some(rn) = name.strip_prefix("r") { - let val : u8 = rn.parse()?; - Ok(Register::Gen(val)) - } else { - Err(Error::Parse(format!("Bad reg name: {}", name).into()))? - } -} - pub fn parse_u64(literal : &str) -> anyhow::Result { if let Some(hex) = literal.strip_prefix("0x") { Ok(u64::from_str_radix(hex, 16)?) @@ -78,9 +64,9 @@ pub fn parse_i64(literal : &str) -> anyhow::Result { } pub fn parse_rd(tok: Option) -> anyhow::Result { - Ok(Rd(SrcDisp::try_from(parse_data_disp(tok)?)?, Mask::default())) + Ok(Rd::new(SrcDisp::try_from(parse_data_disp(tok)?)?)) } pub fn parse_wr(tok: Option) -> anyhow::Result { - Ok(Wr(DstDisp::try_from(parse_data_disp(tok)?)?, Mask::default())) + Ok(Wr::new(DstDisp::try_from(parse_data_disp(tok)?)?)) } diff --git a/csn_asm/src/parse/parse_op.rs b/csn_asm/src/parse/parse_op.rs index 1dc30b9..6b49034 100644 --- a/csn_asm/src/parse/parse_op.rs +++ b/csn_asm/src/parse/parse_op.rs @@ -1,4 +1,4 @@ -use crate::instr::Op; +use crate::instr::{HLOp, Op}; use sexp::Sexp; use crate::error::Error; use crate::data::literal::{RoutineName, Label}; @@ -6,14 +6,14 @@ use crate::parse::sexp_expect::expect_string_atom; use crate::parse::parse_data::{parse_rd, parse_wr, parse_label}; use crate::parse::parse_cond::parse_cond; -pub fn parse_op(keyword: &str, far : bool, mut arg_tokens: impl Iterator) -> Result { +pub fn parse_op(keyword: &str, far : bool, mut arg_tokens: impl Iterator) -> Result { Ok(match keyword { - "jmp" | "j" => { + "j" => { let dest = parse_label(arg_tokens.next())?; if far { - Op::FarJump(dest) + HLOp::L(Op::FarJump(dest)) } else { - Op::Jump(dest) + HLOp::Jump(dest) } } @@ -24,7 +24,7 @@ pub fn parse_op(keyword: &str, far : bool, mut arg_tokens: impl Iterator { @@ -32,71 +32,79 @@ pub fn parse_op(keyword: &str, far : bool, mut arg_tokens: impl Iterator { + "routine" => { let dest = RoutineName(expect_string_atom(arg_tokens.next())?); - Op::Routine(dest) + HLOp::L(Op::Routine(dest)) } - "skip" => { - Op::Skip(parse_rd(arg_tokens.next())?) + "sk" => { + HLOp::L(Op::Skip(parse_rd(arg_tokens.next())?)) } - "jmp.if" | "j.if" => { + "csk" => { + let cond = parse_cond(&expect_string_atom(arg_tokens.next())?)?; + let offs = parse_rd(arg_tokens.next())?; + HLOp::L(Op::SkipIf(cond, offs)) + } + + "cj" => { let cond = parse_cond(&expect_string_atom(arg_tokens.next())?)?; let dest = parse_label(arg_tokens.next())?; - Op::JumpIf(cond, dest) + HLOp::JumpIf(cond, dest) } "barrier" => { - Op::Barrier(match arg_tokens.next() { + HLOp::L(Op::Barrier(match arg_tokens.next() { None => None, Some(s) => Some(expect_string_atom(Some(s))?.into()), - }) + })) } "fault" => { - Op::Fault(match arg_tokens.next() { + HLOp::L(Op::Fault(match arg_tokens.next() { None => None, Some(s) => Some(expect_string_atom(Some(s))?.into()), - }) + })) } - "mov" | "ld" | "mv" => { - Op::Mov( + "ld" => { + HLOp::L(Op::Mov( parse_wr(arg_tokens.next())?, parse_rd(arg_tokens.next())? - ) + )) } "cmp" => { - Op::Cmp( + HLOp::L(Op::Cmp( parse_rd(arg_tokens.next())?, parse_rd(arg_tokens.next())? - ) + )) } "inc" => { - Op::Inc( + HLOp::L(Op::Inc( parse_wr(arg_tokens.next())? - ) + )) } "dec" => { - Op::Dec( + HLOp::L(Op::Dec( parse_wr(arg_tokens.next())? - ) + )) } + // TODO more instructions + other => { if let Some(label) = other.strip_prefix(':') { let label = Label::Named(label.to_string()); if far { - Op::FarLabel(label) + HLOp::L(Op::FarLabel(label)) } else { - Op::Label(label) + HLOp::Label(label) } } else { return Err(Error::Parse(format!("Unknown instruction: {}", other).into()));