forked from MightyPork/crsn
parent
3e0aaa71e9
commit
0cd800653f
@ -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)); |
||||
} |
||||
})))) |
||||
} |
||||
} |
Loading…
Reference in new issue