Example extension: Stacks; fixes to allow module data storage in thread context
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "crsn_stacks"
|
||||
version = "0.1.0"
|
||||
authors = ["Ondřej Hruška <ondra@ondrovo.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
crsn = { path = "../crsn" }
|
||||
@@ -0,0 +1,7 @@
|
||||
use crsn::asm::data::{Rd, Wr};
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub enum StackOp {
|
||||
Push { num: Rd, src: Rd },
|
||||
Pop { dst: Wr, num: Rd },
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
use std::collections::VecDeque;
|
||||
|
||||
|
||||
use crsn::asm::data::literal::Value;
|
||||
use crsn::asm::instr::op::{EvalRes, OpTrait};
|
||||
use crsn::runtime::fault::Fault;
|
||||
|
||||
|
||||
use crsn::runtime::run_thread::{RunState, ThreadInfo};
|
||||
|
||||
use crate::defs::StackOp;
|
||||
|
||||
struct Stacks {
|
||||
stacks: Vec<VecDeque<Value>>,
|
||||
}
|
||||
|
||||
impl Default for Stacks {
|
||||
fn default() -> Self {
|
||||
Stacks {
|
||||
stacks: vec![VecDeque::default(); 8],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl OpTrait for StackOp {
|
||||
fn execute(&self, _ti: &ThreadInfo, state: &mut RunState) -> Result<EvalRes, Fault> {
|
||||
let eres = EvalRes::default();
|
||||
match self {
|
||||
StackOp::Push { num, src } => {
|
||||
state.frame.status.clear();
|
||||
let stack_num = state.frame.read(*num)?;
|
||||
let val = state.frame.read(*src)?;
|
||||
|
||||
if stack_num > 8 {
|
||||
state.frame.status.invalid = true;
|
||||
} else {
|
||||
let obj: &mut Stacks = state.ext_mut();
|
||||
obj.stacks[stack_num as usize].push_back(val);
|
||||
}
|
||||
}
|
||||
StackOp::Pop { dst, num } => {
|
||||
state.frame.status.clear();
|
||||
let stack_num = state.frame.read(*num)?;
|
||||
|
||||
if stack_num > 8 {
|
||||
state.frame.status.invalid = true;
|
||||
} else {
|
||||
let obj: &mut Stacks = state.ext_mut();
|
||||
let val = obj.stacks[stack_num as usize].pop_back();
|
||||
|
||||
let val = match val {
|
||||
None => {
|
||||
state.frame.status.overflow = true;
|
||||
0
|
||||
}
|
||||
Some(val) => {
|
||||
val
|
||||
}
|
||||
};
|
||||
|
||||
state.frame.write(*dst, val)?;
|
||||
}
|
||||
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
Ok(eres)
|
||||
}
|
||||
//
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
pub use parse::StackOps;
|
||||
|
||||
mod defs;
|
||||
mod parse;
|
||||
mod exec;
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
|
||||
use crsn::asm::error::Error;
|
||||
use crsn::asm::instr::op::{AsmModule, ParseOpResult};
|
||||
use crsn::asm::instr::Op;
|
||||
use crsn::asm::parse::arg_parser::ArgParser;
|
||||
|
||||
use crate::defs::StackOp;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct StackOps {
|
||||
_internal: ()
|
||||
}
|
||||
|
||||
impl StackOps {
|
||||
pub fn new() -> Box<dyn AsmModule> {
|
||||
Box::new(Self {
|
||||
_internal: ()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl AsmModule for StackOps {
|
||||
fn name(&self) -> &'static str {
|
||||
"stacks"
|
||||
}
|
||||
|
||||
fn parse_op(&self, keyword: &str, mut args: ArgParser) -> Result<ParseOpResult, Error> {
|
||||
Ok(ParseOpResult::Parsed(Op::Ext(Box::new(match keyword {
|
||||
"push" => {
|
||||
StackOp::Push {
|
||||
num: args.next_rd()?,
|
||||
src: args.next_rd()?,
|
||||
}
|
||||
}
|
||||
|
||||
"pop" => {
|
||||
StackOp::Pop {
|
||||
dst: args.next_wr()?,
|
||||
num: args.next_rd()?,
|
||||
}
|
||||
}
|
||||
|
||||
_other => {
|
||||
return Ok(ParseOpResult::Unknown(args));
|
||||
}
|
||||
}))))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user