diff --git a/crsn/src/asm/instr/flatten.rs b/crsn/src/asm/instr/flatten.rs index bb2fe66..511af83 100644 --- a/crsn/src/asm/instr/flatten.rs +++ b/crsn/src/asm/instr/flatten.rs @@ -4,15 +4,15 @@ use std::sync::atomic::AtomicU32; use crate::asm::data::{Rd, SrcDisp}; use crate::asm::data::literal::{Label, Value}; use crate::asm::error::{AsmError, Error}; -use crate::asm::instr::{Cond, OpWrapper, Instr, Op, Routine}; +use crate::asm::instr::{Cond, Instr, Op, Routine}; /// 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 +29,18 @@ impl Flatten for Instr { } else { Label::unique(label_num) }; - ops.push(OpWrapper::JumpIf(!cond, next_lbl.clone())); + ops.push(Op::JumpIf(!cond, next_lbl.clone())); for branch_instr in branch { ops.extend(branch_instr.flatten(label_num)?); } if cnt != branch_count - 1 { - ops.push(OpWrapper::Jump(end_lbl.clone())); - ops.push(OpWrapper::Label(next_lbl)); + ops.push(Op::Jump(end_lbl.clone())); + ops.push(Op::Label(next_lbl)); } } - ops.push(OpWrapper::Label(end_lbl)); + ops.push(Op::Label(end_lbl)); } Ok(ops) @@ -48,7 +48,7 @@ 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()).into(), ]; @@ -61,44 +61,3 @@ impl Flatten for Routine { Ok(ops) } } - -/// Convert jumps to relative skips -pub fn lower(ops: Vec) -> Result, Error> { - let mut label_positions = HashMap::::new(); - for (n, op) in ops.iter().enumerate() { - if let OpWrapper::Label(name) = op { - label_positions.insert(name.clone(), n - label_positions.len()); - } - } - - let mut cleaned = vec![]; - let mut skipped = 0; - for (n, op) in ops.into_iter().enumerate() { - match op { - OpWrapper::Label(_) => { - skipped += 1; - } - OpWrapper::Jump(target) => { - if let Some(dest) = label_positions.get(&target) { - let skip = *dest as isize - n as isize + skipped; - cleaned.push(Op::Skip(Rd::new(SrcDisp::Immediate(skip as Value)))); - } else { - return Err(Error::Asm(AsmError::LabelNotDefined(target))); - } - } - OpWrapper::JumpIf(cond, target) => { - if let Some(dest) = label_positions.get(&target) { - let skip = *dest as isize - n as isize + skipped; - cleaned.push(Op::SkipIf(cond, Rd::new(SrcDisp::Immediate(skip as Value)))); - } else { - return Err(Error::Asm(AsmError::LabelNotDefined(target))); - } - } - OpWrapper::Op(op) => { - cleaned.push(op); - } - } - } - - Ok(cleaned) -} diff --git a/crsn/src/asm/instr/mod.rs b/crsn/src/asm/instr/mod.rs index 1c69c87..f1f7ead 100644 --- a/crsn/src/asm/instr/mod.rs +++ b/crsn/src/asm/instr/mod.rs @@ -1,7 +1,5 @@ pub use cond::Cond; pub use flatten::Flatten; -pub use flatten::lower; -pub use op::OpWrapper; pub use op::Op; use crate::asm::data::literal::RoutineName; @@ -13,7 +11,7 @@ mod flatten; /// A higher-level instruction #[derive(Debug)] pub struct Instr { - pub op: OpWrapper, + pub op: Op, pub branches: Option)>>, } diff --git a/crsn/src/asm/instr/op.rs b/crsn/src/asm/instr/op.rs index 7fc5a1a..ae9213e 100644 --- a/crsn/src/asm/instr/op.rs +++ b/crsn/src/asm/instr/op.rs @@ -6,6 +6,7 @@ use crate::asm::data::{ Rd, Wr, }; +use crate::asm::data::literal::Addr; use crate::asm::error::Error; use crate::asm::instr::Cond; use crate::asm::parse::arg_parser::ArgParser; @@ -15,22 +16,15 @@ use crate::runtime::program::Program; /// A higher level simple opration #[derive(Debug)] -pub enum OpWrapper { +pub enum Op { + /// Do nothing + Nop, /// Mark a jump target. Label(Label), /// Jump to a label Jump(Label), /// Jump to a label if a flag is set JumpIf(Cond, Label), - /// Low level op - Op(Op), -} - -/// A low level instruction -#[derive(Debug)] -pub enum Op { - /// Do nothing - Nop, /// Mark a far jump target (can be jumped to from another routine). /// This label is preserved in optimized code. FarLabel(Label), @@ -58,23 +52,16 @@ pub enum Op { StoreStatus { dst: Wr }, /// Load runtime status from a register LoadStatus { src: Rd }, - + /// Instruction added by an extension Extension(Box), } -/// Make "into" work -impl From for OpWrapper { - fn from(op: Op) -> Self { - OpWrapper::Op(op) - } -} - pub trait OpTrait: Debug + Send + Sync + 'static { - fn execute(&self, program: &Program, call_stack: &mut CallStack, frame: &mut StackFrame) -> Result<(), Fault>; + fn execute(&self, program: &Program, call_stack: &mut CallStack, frame: &mut StackFrame) -> Result; } pub enum ParseOpResult { - Parsed(Box), + Parsed(Box), Unknown(ArgParser), } @@ -89,3 +76,141 @@ pub trait AsmModule: Debug + Send + 'static { /// If the instruction keyword is not recognized, return Unknown with the unchanged argument list. fn parse_op(&self, keyword: &str, arg_tokens: ArgParser) -> Result; } + + +pub type CyclesSpent = usize; + +#[derive(Debug)] +pub struct EvalRes { + pub cycles: CyclesSpent, + pub advance: i64, +} + +impl Default for EvalRes { + fn default() -> Self { + Self { + cycles: 1, + advance: 1, + } + } +} + + +impl OpTrait for Op { + fn execute(&self, program: &Program, call_stack: &mut CallStack, frame: &mut StackFrame) -> Result { + let mut res = EvalRes::default(); + match self { + Op::Nop => {} + Op::Label(_) | Op::FarLabel(_) | Op::Routine(_) => { + /* this is nop, but without any cost - just markers */ + res.cycles = 0; + } + Op::Barrier(msg) => { + return Err(Fault::Barrier { + msg: msg.clone().unwrap_or_else(|| "BARRIER".into()) + }); + } + Op::Fault(msg) => { + return Err(Fault::FaultInstr { + msg: msg.clone().unwrap_or_else(|| "FAULT".into()) + }); + } + Op::FarJump(name) => { + match program.find_far_label(name) { + Ok(pos) => { + frame.pc = pos; + } + Err(e) => { + return Err(e); + } + } + } + Op::Jump(name) => { + match program.find_local_label(frame.pc, name) { + Ok(pos) => { + frame.pc = pos; + } + Err(e) => { + return Err(e); + } + } + } + Op::JumpIf(cond, name) => { + if frame.status.test(*cond) { + match program.find_local_label(frame.pc, name) { + Ok(pos) => { + frame.pc = pos; + } + Err(e) => { + return Err(e); + } + } + } + } + Op::Call(name, args) => { + match program.find_routine(&name) { + Ok(pos) => { + let mut values = Vec::with_capacity(args.len()); + for arg in args { + values.push(frame.read(*arg)?); + } + + let mut frame2 = StackFrame::new(pos, &values); + std::mem::swap(frame, &mut frame2); + call_stack.push(frame2); + res.advance = 0; + } + Err(e) => { + return Err(e); + } + } + } + Op::Ret(retvals) => { + match call_stack.pop() { + Some(previous) => { + let mut values = Vec::with_capacity(retvals.len()); + for arg in retvals { + values.push(frame.read(*arg)?); + } + *frame = previous; + frame.set_retvals(&values); + } + None => { + return Err(Fault::CallStackUnderflow); + } + } + } + Op::Skip(val) => { + let steps = frame.read(*val)?; + res.advance = i64::from_ne_bytes(steps.to_ne_bytes()); + program.validate_jump(frame.pc, Addr((frame.pc.0 as i64 + res.advance) as u64))?; + } + Op::SkipIf(cond, val) => { + if frame.status.test(*cond) { + let steps = frame.read(*val)?; + res.advance = i64::from_ne_bytes(steps.to_ne_bytes()); + program.validate_jump(frame.pc, Addr((frame.pc.0 as i64 + res.advance) as u64))?; + } + } + Op::Move { dst, src } => { + frame.status.clear(); + let val = frame.read(*src)?; + frame.status.update(val); + frame.write(*dst, val)?; + } + Op::StoreStatus { dst } => { + let packed = frame.status.store(); + frame.write(*dst, packed)?; + } + Op::LoadStatus { src } => { + let x = frame.read(*src)?; + frame.status.load(x); + } + Op::Extension(xop) => { + xop.execute(&program, call_stack, frame)?; + } + } + + Ok(res) + } +} diff --git a/crsn/src/asm/mod.rs b/crsn/src/asm/mod.rs index 00c9e96..2b69dea 100644 --- a/crsn/src/asm/mod.rs +++ b/crsn/src/asm/mod.rs @@ -1,5 +1,8 @@ -use crate::asm::instr::{lower, Op}; +use std::sync::Arc; + +use crate::asm::instr::Op; use crate::asm::instr::op::AsmModule; +use crate::runtime::program::Program; pub mod data; pub mod error; @@ -8,7 +11,7 @@ pub mod parse; pub mod patches; /// Parse a program from string and assemble a low level instruction sequence from it. -pub fn assemble(source: &str, parsers: &[Box]) -> Result, error::Error> { - let parsed = parse::parse(source, parsers)?; - Ok(lower(parsed)?) +pub fn assemble(source: &str, parsers: &[Box]) -> Result, error::Error> { + let ops = parse::parse(source, parsers)?; + Ok(Program::new(ops)) } diff --git a/crsn/src/asm/parse/arg_parser.rs b/crsn/src/asm/parse/arg_parser.rs index 776f20a..caf8680 100644 --- a/crsn/src/asm/parse/arg_parser.rs +++ b/crsn/src/asm/parse/arg_parser.rs @@ -1,4 +1,5 @@ use sexp::Sexp; + use crate::asm::data::{Rd, Wr}; use crate::asm::parse::parse_data::{parse_rd, parse_wr}; use crate::asm::parse::sexp_expect::expect_string_atom; @@ -24,7 +25,7 @@ impl ArgParser { args.reverse(); Self { orig_len: args.len(), - args + args, } } diff --git a/crsn/src/asm/parse/mod.rs b/crsn/src/asm/parse/mod.rs index 211e703..b74e38e 100644 --- a/crsn/src/asm/parse/mod.rs +++ b/crsn/src/asm/parse/mod.rs @@ -4,7 +4,7 @@ pub use parse_instr::parse_instructions; use parse_routines::parse_routines; use crate::asm::error::Error; -use crate::asm::instr::{Flatten, OpWrapper, Routine}; +use crate::asm::instr::{Flatten, Op, Routine}; use crate::asm::instr::op::AsmModule; use crate::asm::parse::sexp_expect::expect_list; @@ -17,7 +17,7 @@ mod parse_op; pub mod arg_parser; -pub fn parse(source: &str, parsers: &[Box]) -> Result, Error> { +pub fn parse(source: &str, parsers: &[Box]) -> Result, Error> { let root = sexp::parse(source)?; let subs: Vec = parse_routines(expect_list(Some(root), true)?, parsers)?; diff --git a/crsn/src/asm/parse/parse_instr.rs b/crsn/src/asm/parse/parse_instr.rs index b982165..8dd4b3e 100644 --- a/crsn/src/asm/parse/parse_instr.rs +++ b/crsn/src/asm/parse/parse_instr.rs @@ -3,12 +3,12 @@ use sexp::Sexp; use crate::asm::error::Error; use crate::asm::instr::Instr; use crate::asm::instr::op::AsmModule; +use crate::asm::parse::arg_parser::ArgParser; use crate::asm::parse::parse_cond::parse_cond_branch; use crate::asm::parse::sexp_expect::{expect_list, expect_string_atom}; use crate::asm::patches::SexpIsA; use super::parse_op::parse_op; -use crate::asm::parse::arg_parser::ArgParser; pub fn parse_instructions(instrs: Vec, parsers: &[Box]) -> Result, Error> { let mut parsed = vec![]; diff --git a/crsn/src/asm/parse/parse_op.rs b/crsn/src/asm/parse/parse_op.rs index e13bd63..249da6b 100644 --- a/crsn/src/asm/parse/parse_op.rs +++ b/crsn/src/asm/parse/parse_op.rs @@ -1,20 +1,20 @@ use crate::asm::data::literal::{Label, RoutineName}; use crate::asm::error::Error; -use crate::asm::instr::{Op, OpWrapper}; +use crate::asm::instr::Op; use crate::asm::instr::cond::parse_cond; use crate::asm::instr::op::{AsmModule, ParseOpResult}; use crate::asm::parse::arg_parser::ArgParser; use crate::asm::parse::parse_data::{parse_label, parse_rd}; use crate::asm::parse::sexp_expect::expect_string_atom; -pub fn parse_op(keyword: &str, far: bool, mut arg_tokens: ArgParser, parsers: &[Box]) -> Result { +pub fn parse_op(keyword: &str, far: bool, mut arg_tokens: ArgParser, parsers: &[Box]) -> Result { Ok(match keyword { "j" => { let dest = parse_label(arg_tokens.next())?; if far { - OpWrapper::Op(Op::FarJump(dest)) + Op::FarJump(dest) } else { - OpWrapper::Jump(dest) + Op::Jump(dest) } } @@ -25,7 +25,7 @@ pub fn parse_op(keyword: &str, far: bool, mut arg_tokens: ArgParser, parsers: &[ for t in arg_tokens { args.push(parse_rd(Some(t))?); } - OpWrapper::Op(Op::Call(dest, args)) + Op::Call(dest, args) } "ret" => { @@ -33,63 +33,63 @@ pub fn parse_op(keyword: &str, far: bool, mut arg_tokens: ArgParser, parsers: &[ for t in arg_tokens { args.push(parse_rd(Some(t))?); } - OpWrapper::Op(Op::Ret(args)) + Op::Ret(args) } "routine" => { let dest = RoutineName(arg_tokens.next_string()?); - OpWrapper::Op(Op::Routine(dest)) + Op::Routine(dest) } "s" => { - OpWrapper::Op(Op::Skip(arg_tokens.next_rd()?)) + Op::Skip(arg_tokens.next_rd()?) } "sif" => { let cond = parse_cond(&arg_tokens.next_string()?)?; let offs = arg_tokens.next_rd()?; - OpWrapper::Op(Op::SkipIf(cond, offs)) + Op::SkipIf(cond, offs) } "jif" => { let cond = parse_cond(&arg_tokens.next_string()?)?; let dest = parse_label(arg_tokens.next())?; - OpWrapper::JumpIf(cond, dest) + Op::JumpIf(cond, dest) } "barrier" => { - OpWrapper::Op(Op::Barrier(match arg_tokens.next() { + Op::Barrier(match arg_tokens.next() { None => None, Some(s) => Some(expect_string_atom(Some(s))?.into()), - })) + }) } "fault" => { - OpWrapper::Op(Op::Fault(match arg_tokens.next() { + Op::Fault(match arg_tokens.next() { None => None, Some(s) => Some(expect_string_atom(Some(s))?.into()), - })) + }) } "ld" => { - OpWrapper::Op(Op::Move { + Op::Move { dst: arg_tokens.next_wr()?, src: arg_tokens.next_rd()?, - }) + } } other => { if let Some(label) = other.strip_prefix(':') { let label = Label::Named(label.to_string()); if far { - OpWrapper::Op(Op::FarLabel(label)) + Op::FarLabel(label) } else { - OpWrapper::Label(label) + Op::Label(label) } } else { for p in parsers { arg_tokens = match p.parse_op(keyword, arg_tokens) { - Ok(ParseOpResult::Parsed(op)) => return Ok(OpWrapper::Op(Op::Extension(op))), + Ok(ParseOpResult::Parsed(op)) => return Ok(Op::Extension(op)), Ok(ParseOpResult::Unknown(to_reuse)) => { if to_reuse.parsing_started() { panic!("Module \"{}\" started parsing {}, but returned Unknown!", p.name(), keyword); diff --git a/crsn/src/runtime/exec/mod.rs b/crsn/src/runtime/exec/mod.rs index b7037e8..94914fc 100644 --- a/crsn/src/runtime/exec/mod.rs +++ b/crsn/src/runtime/exec/mod.rs @@ -1,16 +1,10 @@ use crate::asm::data::literal::Addr; use crate::asm::instr::Op; +use crate::asm::instr::op::{EvalRes, OpTrait}; use crate::runtime::fault::Fault; use crate::runtime::frame::StackFrame; use crate::runtime::run_thread::RunThread; -pub type CyclesSpent = usize; - -pub struct EvalRes { - pub cycles: u8, - pub advance: i64, -} - impl RunThread { // TODO unit tests pub fn eval_op(&mut self) -> Result { @@ -27,101 +21,7 @@ impl RunThread { /* Operations can be given different execution times when run in slow mode. */ /* Presently, all that do anything use 1 cycle. */ - match op { - Op::Nop => {} - Op::FarLabel(_) | Op::Routine(_) => { - /* this is nop, but without any cost - just markers */ - cycles = 0; - } - Op::Barrier(msg) => { - return Err(Fault::Barrier { - msg: msg.clone().unwrap_or_else(|| "No msg".into()) - }); - } - Op::Fault(msg) => { - return Err(Fault::FaultInstr { - msg: msg.clone().unwrap_or_else(|| "No msg".into()) - }); - } - Op::FarJump(name) => { - debug!("Far jump to {}", name); - match self.program.find_far_label(name) { - Ok(pos) => { - debug!("label is at {}", pos); - self.frame.pc = pos; - } - Err(e) => { - return Err(e); - } - } - } - Op::Call(name, args) => { - debug!("Call routine {}", name); - match self.program.find_routine(name) { - Ok(pos) => { - debug!("routine is at {}", pos); - - let mut values = Vec::with_capacity(args.len()); - for arg in args { - values.push(self.frame.read(*arg)?); - } - - let mut frame2 = StackFrame::new(pos, &values); - std::mem::swap(&mut self.frame, &mut frame2); - self.call_stack.push(frame2); - advance = 0; - } - Err(e) => { - return Err(e); - } - } - } - Op::Ret(retvals) => { - match self.call_stack.pop() { - Some(previous) => { - let mut values = Vec::with_capacity(retvals.len()); - for arg in retvals { - values.push(frame.read(*arg)?); - } - *frame = previous; - frame.set_retvals(&values); - advance = 1; // advance past the call - } - None => { - return Err(Fault::CallStackUnderflow); - } - } - } - Op::Skip(val) => { - let steps = frame.read(*val)?; - advance = i64::from_ne_bytes(steps.to_ne_bytes()); - self.program.validate_jump(frame.pc, Addr((frame.pc.0 as i64 + advance) as u64))?; - } - Op::SkipIf(cond, val) => { - if frame.status.test(*cond) { - let steps = frame.read(*val)?; - advance = i64::from_ne_bytes(steps.to_ne_bytes()); - self.program.validate_jump(frame.pc, Addr((frame.pc.0 as i64 + advance) as u64))?; - } - } - Op::Move { dst, src } => { - frame.status.clear(); - let val = frame.read(*src)?; - frame.status.update(val); - frame.write(*dst, val)?; - } - Op::Extension(xop) => { - xop.execute(&self.program, &mut self.call_stack, frame)?; - } - Op::StoreStatus { dst } => { - let packed = frame.status.store(); - frame.write(*dst, packed)?; - } - Op::LoadStatus { src } => { - let x = frame.read(*src)?; - frame.status.load(x); - } - } + op.execute(&self.program, &mut self.call_stack, frame)?; Ok(EvalRes { cycles, diff --git a/crsn/src/runtime/fault.rs b/crsn/src/runtime/fault.rs index c76275f..951ce8e 100644 --- a/crsn/src/runtime/fault.rs +++ b/crsn/src/runtime/fault.rs @@ -49,7 +49,7 @@ pub enum Fault { }, #[error("Jump to undefined far label: {label}")] - NoSuchFarLabel { + NoSuchLabel { label: Label, }, diff --git a/crsn/src/runtime/program.rs b/crsn/src/runtime/program.rs index 1713e12..6b756d1 100644 --- a/crsn/src/runtime/program.rs +++ b/crsn/src/runtime/program.rs @@ -1,14 +1,13 @@ - use std::collections::HashMap; +use std::sync::Arc; use crate::asm::data::literal::{Addr, Label, RoutineName}; use crate::asm::instr::Op; use crate::runtime::fault::Fault; -use std::sync::Arc; #[derive(Debug)] pub struct Program { - ops: Vec, + pub ops: Vec, routines: HashMap, far_labels: HashMap, barriers: Vec, @@ -82,7 +81,39 @@ impl Program { /// Find far label by name pub fn find_far_label(&self, name: &Label) -> Result { self.far_labels.get(name).copied() - .ok_or_else(|| Fault::NoSuchFarLabel { label: name.clone() }) + .ok_or_else(|| Fault::NoSuchLabel { label: name.clone() }) + } + + /// Find local label by name (label within a boundary-delimited region). + /// If more than one such label exists, the outcome is undefined. + pub fn find_local_label(&self, pc: Addr, name: &Label) -> Result { + // TODO more efficient impl with look-up + + for at in (0..=pc.0).rev() { + match &self.ops[at as usize] { + Op::Label(lbl) if lbl == name => { + return Ok(at.into()); + } + Op::Barrier(_) => { + break; + } + _ => {} + } + } + + for at in pc.0..(self.ops.len() as u64) { + match &self.ops[at as usize] { + Op::Label(lbl) if lbl == name => { + return Ok(at.into()); + } + Op::Barrier(_) => { + break; + } + _ => {} + } + } + + Err(Fault::NoSuchLabel { label: name.clone() }) } } diff --git a/crsn/src/runtime/run_thread.rs b/crsn/src/runtime/run_thread.rs index 4ba46c4..8945375 100644 --- a/crsn/src/runtime/run_thread.rs +++ b/crsn/src/runtime/run_thread.rs @@ -1,14 +1,13 @@ use std::any::{Any, TypeId}; use std::collections::HashMap; +use std::sync::Arc; use std::thread::JoinHandle; use std::time::Duration; use crate::asm::data::literal::Addr; -use crate::runtime::exec::EvalRes; +use crate::asm::instr::op::EvalRes; use crate::runtime::frame::{CallStack, StackFrame}; use crate::runtime::program::Program; -use std::sync::Arc; - const CYCLE_TIME: Duration = Duration::from_millis(0); //const CYCLE_TIME : Duration = Duration::from_millis(100); diff --git a/crsn_arith/src/exec.rs b/crsn_arith/src/exec.rs index c0ed51b..5602829 100644 --- a/crsn_arith/src/exec.rs +++ b/crsn_arith/src/exec.rs @@ -2,7 +2,7 @@ use std::ops::Rem; use num_traits::PrimInt; -use crsn::asm::instr::op::OpTrait; +use crsn::asm::instr::op::{OpTrait, EvalRes}; use crsn::runtime::fault::Fault; use crsn::runtime::frame::{CallStack, StackFrame}; use crsn::runtime::program::Program; @@ -10,7 +10,8 @@ use crsn::runtime::program::Program; use crate::defs::ArithOp; impl OpTrait for ArithOp { - fn execute(&self, _program: &Program, _call_stack: &mut CallStack, frame: &mut StackFrame) -> Result<(), Fault> { + fn execute(&self, _program: &Program, _call_stack: &mut CallStack, frame: &mut StackFrame) -> Result { + let eres = EvalRes::default(); match self { ArithOp::Test { a } => { frame.status.clear(); @@ -188,7 +189,7 @@ impl OpTrait for ArithOp { } } - Ok(()) + Ok(eres) } // } diff --git a/launcher/src/main.rs b/launcher/src/main.rs index abf871e..9178ff6 100644 --- a/launcher/src/main.rs +++ b/launcher/src/main.rs @@ -45,7 +45,10 @@ fn main() { let program = " ( (main + (j :lbl) (ld _ arg0) + (fault) + (:lbl) (call fibo 5) (ld r0 res0) ) @@ -69,12 +72,12 @@ fn main() { let parsed = crsn::asm::assemble(program, parsers.as_slice()).unwrap(); debug!("---"); - for op in &parsed { + for op in &parsed.ops { debug!("{:?}", op); } debug!("---"); - let thread = RunThread::new(ThreadToken(0), Program::new(parsed), Addr(0), &[]); + let thread = RunThread::new(ThreadToken(0), parsed, Addr(0), &[]); thread.start().join().unwrap(); }