Example extension: Stacks; fixes to allow module data storage in thread context

This commit is contained in:
2020-09-26 22:49:06 +02:00
parent 3e0aaa71e9
commit 0cd800653f
21 changed files with 285 additions and 74 deletions
+10
View File
@@ -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" }
+7
View File
@@ -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 },
}
+71
View File
@@ -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)
}
//
}
+6
View File
@@ -0,0 +1,6 @@
pub use parse::StackOps;
mod defs;
mod parse;
mod exec;
+48
View File
@@ -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));
}
}))))
}
}