remove "immediate ptr" data type, move read, write funcs to RunState, add %objectPtr syntax

pull/21/head
Ondřej Hruška 4 years ago
parent d489b214e0
commit 8222efe6da
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 7
      crsn/src/asm/data/literal.rs
  2. 36
      crsn/src/asm/data/mod.rs
  3. 2
      crsn/src/asm/instr/op.rs
  4. 9
      crsn/src/asm/parse/parse_data.rs
  5. 57
      crsn/src/builtin/exec.rs
  6. 77
      crsn/src/runtime/frame.rs
  7. 37
      crsn/src/runtime/frame/status.rs
  8. 26
      crsn/src/runtime/run_thread.rs
  9. 126
      crsn/src/runtime/run_thread/state.rs
  10. 188
      crsn_arith/src/exec.rs
  11. 26
      crsn_stacks/src/exec.rs
  12. 6
      launcher/src/main.rs

@ -61,6 +61,13 @@ impl From<Addr> for u64 {
}
}
impl From<Addr> for i64 {
fn from(addr: Addr) -> Self {
addr.0 as i64
}
}
/// Label name
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum Label {

@ -19,12 +19,10 @@ pub mod mask;
pub enum DataDisp {
/// Constant value
Immediate(Value),
/// Constant memory address
ImmediatePtr(Addr),
/// Register
Register(Register),
/// Pointer into memory, stored in a numbered register
RegisterPtr(Register),
/// Object pointer
ObjectPtr(Register),
/// Discard the written value
Discard,
}
@ -35,14 +33,11 @@ impl Display for DataDisp {
DataDisp::Immediate(v) => {
write!(f, "{}", as_signed(*v))
}
DataDisp::ImmediatePtr(a) => {
write!(f, "@0x{:#18x}", a.0)
}
DataDisp::Register(r) => {
write!(f, "{}", r)
}
DataDisp::RegisterPtr(r) => {
write!(f, "@{}", r)
DataDisp::ObjectPtr(r) => {
write!(f, "%{}", r)
}
DataDisp::Discard => {
write!(f, "_")
@ -55,9 +50,8 @@ impl From<SrcDisp> for DataDisp {
fn from(s: SrcDisp) -> Self {
match s {
SrcDisp::Immediate(x) => DataDisp::Immediate(x),
SrcDisp::ImmediatePtr(x) => DataDisp::ImmediatePtr(x),
SrcDisp::Register(x) => DataDisp::Register(x),
SrcDisp::RegisterPtr(x) => DataDisp::RegisterPtr(x),
SrcDisp::ObjectPtr(x) => DataDisp::ObjectPtr(x),
}
}
}
@ -65,9 +59,8 @@ impl From<SrcDisp> for DataDisp {
impl From<DstDisp> for DataDisp {
fn from(s: DstDisp) -> Self {
match s {
DstDisp::ImmediatePtr(x) => DataDisp::ImmediatePtr(x),
DstDisp::Register(x) => DataDisp::Register(x),
DstDisp::RegisterPtr(x) => DataDisp::RegisterPtr(x),
DstDisp::ObjectPtr(x) => DataDisp::ObjectPtr(x),
DstDisp::Discard => DataDisp::Discard,
}
}
@ -78,12 +71,10 @@ impl From<DstDisp> for DataDisp {
pub enum SrcDisp {
/// Constant value
Immediate(Value),
/// Constant memory address
ImmediatePtr(Addr),
/// Register
Register(Register),
/// Pointer into memory, stored in a numbered register
RegisterPtr(Register),
ObjectPtr(Register),
}
impl TryFrom<DataDisp> for SrcDisp {
@ -92,9 +83,8 @@ impl TryFrom<DataDisp> for SrcDisp {
fn try_from(value: DataDisp) -> Result<Self, Self::Error> {
match value {
DataDisp::Immediate(x) => Ok(SrcDisp::Immediate(x)),
DataDisp::ImmediatePtr(x) => Ok(SrcDisp::ImmediatePtr(x)),
DataDisp::Register(x) => Ok(SrcDisp::Register(x)),
DataDisp::RegisterPtr(x) => Ok(SrcDisp::RegisterPtr(x)),
DataDisp::ObjectPtr(x) => Ok(SrcDisp::ObjectPtr(x)),
DataDisp::Discard => Err(AsmError::DiscardAsValue),
}
}
@ -103,12 +93,10 @@ impl TryFrom<DataDisp> for SrcDisp {
/// Data destination disposition
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum DstDisp {
/// Constant memory address
ImmediatePtr(Addr),
/// Register
Register(Register),
/// Pointer into memory, stored in a numbered register
RegisterPtr(Register),
ObjectPtr(Register),
/// Discard the written value
Discard,
}
@ -116,9 +104,8 @@ pub enum DstDisp {
impl From<DstDisp> for SrcDisp {
fn from(s: DstDisp) -> Self {
match s {
DstDisp::ImmediatePtr(x) => SrcDisp::ImmediatePtr(x),
DstDisp::Register(x) => SrcDisp::Register(x),
DstDisp::RegisterPtr(x) => SrcDisp::RegisterPtr(x),
DstDisp::ObjectPtr(x) => SrcDisp::ObjectPtr(x),
DstDisp::Discard => SrcDisp::Immediate(0),
}
}
@ -130,9 +117,8 @@ impl TryFrom<DataDisp> for DstDisp {
fn try_from(value: DataDisp) -> Result<Self, Self::Error> {
match value {
DataDisp::Immediate(_x) => Err(AsmError::ValueAsOutput),
DataDisp::ImmediatePtr(x) => Ok(DstDisp::ImmediatePtr(x)),
DataDisp::Register(x) => Ok(DstDisp::Register(x)),
DataDisp::RegisterPtr(x) => Ok(DstDisp::RegisterPtr(x)),
DataDisp::ObjectPtr(x) => Ok(DstDisp::ObjectPtr(x)),
DataDisp::Discard => Ok(DstDisp::Discard),
}
}

@ -9,7 +9,7 @@ use crate::builtin::defs::BuiltinOp;
use crate::runtime::fault::Fault;
use crate::runtime::run_thread::{RunState, ThreadInfo};
use crate::runtime::run_thread::{state::RunState, ThreadInfo};
/// A higher level simple opration
#[derive(Debug)]

@ -32,13 +32,8 @@ pub fn parse_data_disp(tok: Option<Sexp>) -> Result<DataDisp, Error> {
return Ok(DataDisp::Discard);
}
if let Some(reference) = s.strip_prefix('@') {
if reference.starts_with(|c: char| c.is_ascii_digit()) {
let val: u64 = parse_u64(reference)?;
Ok(DataDisp::ImmediatePtr(Addr(val)))
} else {
Ok(DataDisp::RegisterPtr(reg::parse_reg(reference)?))
}
if let Some(reference) = s.strip_prefix('%') {
Ok(DataDisp::ObjectPtr(reg::parse_reg(reference)?))
} else if s.starts_with(|c: char| c.is_ascii_digit()) {
Ok(DataDisp::Immediate(unsafe { std::mem::transmute(parse_i64(s)?) }))
} else {

@ -8,11 +8,10 @@ use crate::runtime::frame::{StackFrame};
use crate::builtin::defs::BuiltinOp;
use crate::asm::data::literal::Addr;
use crate::runtime::run_thread::{ThreadInfo, RunState};
use crate::runtime::run_thread::{ThreadInfo, state::RunState};
impl OpTrait for BuiltinOp {
fn execute(&self, info: &ThreadInfo, state: &mut RunState) -> Result<EvalRes, Fault> {
let frame = &mut state.frame;
let program = &info.program;
let mut res = EvalRes::default();
match self {
@ -38,7 +37,7 @@ impl OpTrait for BuiltinOp {
BuiltinOp::FarJump(name) => {
match program.find_far_label(name) {
Ok(pos) => {
frame.pc = pos;
state.set_pc(pos);
}
Err(e) => {
return Err(e);
@ -46,9 +45,9 @@ impl OpTrait for BuiltinOp {
}
}
BuiltinOp::Jump(name) => {
match program.find_local_label(frame.pc, name) {
match program.find_local_label(state.get_pc(), name) {
Ok(pos) => {
frame.pc = pos;
state.set_pc(pos);
}
Err(e) => {
return Err(e);
@ -56,10 +55,10 @@ impl OpTrait for BuiltinOp {
}
}
BuiltinOp::JumpIf(cond, name) => {
if frame.status.test(*cond) {
match program.find_local_label(frame.pc, name) {
if state.test_cond(*cond) {
match program.find_local_label(state.get_pc(), name) {
Ok(pos) => {
frame.pc = pos;
state.set_pc(pos);
}
Err(e) => {
return Err(e);
@ -68,10 +67,10 @@ impl OpTrait for BuiltinOp {
}
}
BuiltinOp::FarJumpIf(cond, name) => {
if frame.status.test(*cond) {
if state.test_cond(*cond) {
match program.find_far_label(name) {
Ok(pos) => {
frame.pc = pos;
state.set_pc(pos);
}
Err(e) => {
return Err(e);
@ -84,11 +83,11 @@ impl OpTrait for BuiltinOp {
Ok(pos) => {
let mut values = Vec::with_capacity(args.len());
for arg in args {
values.push(frame.read(*arg)?);
values.push(state.read(*arg)?);
}
let mut frame2 = StackFrame::new(pos, &values);
std::mem::swap(frame, &mut frame2);
std::mem::swap(&mut state.frame, &mut frame2);
state.call_stack.push(frame2);
res.advance = 0;
}
@ -102,10 +101,10 @@ impl OpTrait for BuiltinOp {
Some(previous) => {
let mut values = Vec::with_capacity(retvals.len());
for arg in retvals {
values.push(frame.read(*arg)?);
values.push(state.read(*arg)?);
}
*frame = previous;
frame.set_retvals(&values);
state.frame = previous;
state.frame.set_retvals(&values);
}
None => {
return Err(Fault::CallStackUnderflow);
@ -113,31 +112,33 @@ impl OpTrait for BuiltinOp {
}
}
BuiltinOp::Skip(val) => {
let steps = frame.read(*val)?;
let steps = state.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))?;
let pc = state.get_pc();
program.validate_jump(pc, Addr((pc.0 as i64 + res.advance) as u64))?;
}
BuiltinOp::SkipIf(cond, val) => {
if frame.status.test(*cond) {
if state.test_cond(*cond) {
debug!("Skipping");
let steps = frame.read(*val)?;
let steps = state.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))?;
let pc = state.get_pc();
program.validate_jump(pc, Addr((pc.0 as i64 + res.advance) as u64))?;
}
}
BuiltinOp::Move { dst, src } => {
frame.status.clear();
let val = frame.read(*src)?;
frame.status.update(val);
frame.write(*dst, val)?;
state.clear_status();
let val = state.read(*src)?;
state.update_status(val);
state.write(*dst, val)?;
}
BuiltinOp::StoreStatus { dst } => {
let packed = frame.status.store();
frame.write(*dst, packed)?;
let packed = state.frame.status.store();
state.write(*dst, packed)?;
}
BuiltinOp::LoadStatus { src } => {
let x = frame.read(*src)?;
frame.status.load(x);
let x = state.read(*src)?;
state.frame.status.load(x);
}
}

@ -5,7 +5,7 @@ use crate::asm::data::literal::{Addr, Value};
use super::fault::Fault;
mod status;
pub(crate) mod status;
pub const REG_COUNT: usize = 8;
@ -41,79 +41,4 @@ impl StackFrame {
self.res[n] = vals[n];
}
}
pub fn read(&mut self, rd: Rd) -> Result<Value, Fault> {
match rd.d() {
SrcDisp::Immediate(v) => Ok(v),
SrcDisp::ImmediatePtr(_) => {
unimplemented!("Immediate ptr")
}
SrcDisp::Register(Register::Res(rn)) => {
if rn >= REG_COUNT as u8 {
Err(Fault::RegisterNotExist { reg: Register::Res(rn) }) // TODO use match after @ when stabilized https://github.com/rust-lang/rust/issues/65490
} else {
trace!("Rd {:?} = {}", rd, self.res[rn as usize]);
Ok(self.res[rn as usize])
}
}
SrcDisp::Register(Register::Arg(rn)) => {
if rn >= REG_COUNT as u8 {
Err(Fault::RegisterNotExist { reg: Register::Arg(rn) })
} else {
trace!("Rd {:?} = {}", rd, self.arg[rn as usize]);
Ok(self.arg[rn as usize])
}
}
SrcDisp::Register(Register::Gen(rn)) => {
if rn >= REG_COUNT as u8 {
Err(Fault::RegisterNotExist { reg: Register::Gen(rn) })
} else {
trace!("Rd {:?} = {}", rd, self.gen[rn as usize]);
Ok(self.gen[rn as usize])
}
}
SrcDisp::RegisterPtr(_) => {
unimplemented!("Register ptr")
}
}
}
pub fn write(&mut self, wr: Wr, val: Value) -> Result<(), Fault> {
trace!("WR {:?} := {}", wr, val);
match wr.d() {
DstDisp::ImmediatePtr(_) => {
unimplemented!("Immediate ptr")
}
DstDisp::Discard => {
/* Discard */
Ok(())
}
DstDisp::Register(Register::Res(rn)) => {
if rn >= REG_COUNT as u8 {
Err(Fault::RegisterNotExist { reg: Register::Res(rn) }) // TODO use match after @ when stabilized https://github.com/rust-lang/rust/issues/65490
} else {
Err(Fault::RegisterNotWritable { reg: Register::Res(rn) })
}
}
DstDisp::Register(Register::Arg(rn)) => {
if rn >= REG_COUNT as u8 {
Err(Fault::RegisterNotExist { reg: Register::Arg(rn) })
} else {
Err(Fault::RegisterNotWritable { reg: Register::Res(rn) })
}
}
DstDisp::Register(Register::Gen(rn)) => {
if rn >= REG_COUNT as u8 {
Err(Fault::RegisterNotExist { reg: Register::Gen(rn) })
} else {
self.gen[rn as usize] = val;
Ok(())
}
}
DstDisp::RegisterPtr(_) => {
unimplemented!("Register ptr")
}
}
}
}

@ -85,6 +85,43 @@ impl StatusFlags {
Cond::NotCarry => !self.carry
}
}
pub fn set(&mut self, cond: Cond) {
match cond {
Cond::Equal => {
self.equal = true;
},
Cond::Zero => {
self.zero = true;
},
Cond::Lower => {
self.lower = true;
},
Cond::Greater => {
self.lower = false;
self.equal = false;
self.greater = true;
},
Cond::Positive => {
self.positive = true;
},
Cond::Negative => {
self.negative = true;
},
Cond::Overflow => {
self.overflow = true;
},
Cond::Invalid => {
self.invalid = true;
},
Cond::Carry => {
self.carry = true;
},
other => {
panic!("cannot set cond by {:?}", other);
}
}
}
}
impl Display for StatusFlags {

@ -4,11 +4,13 @@ use std::sync::Arc;
use std::thread::JoinHandle;
use std::time::Duration;
use crate::asm::data::literal::Addr;
use crate::asm::data::literal::{Addr, Value};
use crate::asm::instr::op::EvalRes;
use crate::runtime::frame::{CallStack, StackFrame};
use crate::runtime::frame::{CallStack, StackFrame, REG_COUNT, status::StatusFlags};
use crate::runtime::program::Program;
use crate::runtime::fault::Fault;
use crate::asm::data::{Rd, SrcDisp, Register, Wr, DstDisp};
use crate::runtime::run_thread::state::RunState;
#[derive(Clone, Copy, Eq, PartialEq, Debug, Ord, PartialOrd)]
pub struct ThreadToken(pub u32);
@ -27,25 +29,7 @@ pub struct ThreadInfo {
pub cycle_time: Duration,
}
pub struct RunState {
/// Active stack frame
pub frame: StackFrame,
/// Call stack
pub call_stack: CallStack,
/// Extension data
ext_data: HashMap<TypeId, Box<dyn Any + Send>>,
}
impl RunState {
pub fn ext_mut<T: Send + Default + 'static>(&mut self) -> &mut T {
if !self.ext_data.contains_key(&TypeId::of::<T>()) {
self.ext_data.insert(TypeId::of::<T>(), Box::new(T::default()));
}
self.ext_data.get_mut(&TypeId::of::<T>()).unwrap()
.downcast_mut().unwrap()
}
}
pub mod state;
impl RunThread {
pub fn new(id: ThreadToken, program: Arc<Program>, pc: Addr, args: &[u64]) -> Self {

@ -0,0 +1,126 @@
use std::any::{Any, TypeId};
use std::collections::HashMap;
use crate::asm::data::{DstDisp, Rd, Register, SrcDisp, Wr};
use crate::asm::data::literal::{Addr, Value};
use crate::asm::instr::op::EvalRes;
use crate::runtime::fault::Fault;
use crate::runtime::frame::{CallStack, REG_COUNT, StackFrame};
use crate::runtime::program::Program;
use crate::asm::instr::Cond;
use crate::runtime::frame::status::StatusFlags;
pub struct RunState {
/// Active stack frame
pub frame: StackFrame,
/// Call stack
pub call_stack: CallStack,
/// Extension data
pub ext_data: HashMap<TypeId, Box<dyn Any + Send>>,
}
impl RunState {
pub fn ext_mut<T: Send + Default + 'static>(&mut self) -> &mut T {
if !self.ext_data.contains_key(&TypeId::of::<T>()) {
self.ext_data.insert(TypeId::of::<T>(), Box::new(T::default()));
}
self.ext_data.get_mut(&TypeId::of::<T>()).unwrap()
.downcast_mut().unwrap()
}
pub fn set_flag(&mut self, cond : Cond, set : bool) {
if set {
self.frame.status.set(cond);
}
}
pub fn test_cond(&self, cond : Cond) -> bool {
self.frame.status.test(cond)
}
pub fn set_pc(&mut self, pc: Addr) {
self.frame.pc = pc;
}
pub fn get_pc(&self) -> Addr {
self.frame.pc
}
pub fn clear_status(&mut self) {
self.frame.status.clear();
}
pub fn update_status(&mut self, val: Value) {
self.frame.status.update(val);
}
pub fn read(&mut self, rd: Rd) -> Result<Value, Fault> {
match rd.d() {
SrcDisp::Immediate(v) => Ok(v),
SrcDisp::Register(Register::Res(rn)) => {
if rn >= REG_COUNT as u8 {
Err(Fault::RegisterNotExist { reg: Register::Res(rn) }) // TODO use match after @ when stabilized https://github.com/rust-lang/rust/issues/65490
} else {
trace!("Rd {:?} = {}", rd, self.frame.res[rn as usize]);
Ok(self.frame.res[rn as usize])
}
}
SrcDisp::Register(Register::Arg(rn)) => {
if rn >= REG_COUNT as u8 {
Err(Fault::RegisterNotExist { reg: Register::Arg(rn) })
} else {
trace!("Rd {:?} = {}", rd, self.frame.arg[rn as usize]);
Ok(self.frame.arg[rn as usize])
}
}
SrcDisp::Register(Register::Gen(rn)) => {
if rn >= REG_COUNT as u8 {
Err(Fault::RegisterNotExist { reg: Register::Gen(rn) })
} else {
trace!("Rd {:?} = {}", rd, self.frame.gen[rn as usize]);
Ok(self.frame.gen[rn as usize])
}
}
SrcDisp::ObjectPtr(_) => {
unimplemented!("Read object ptr")
}
}
}
pub fn write(&mut self, wr: Wr, val: Value) -> Result<(), Fault> {
trace!("WR {:?} := {}", wr, val);
match wr.d() {
DstDisp::Discard => {
/* Discard */
Ok(())
}
DstDisp::Register(Register::Res(rn)) => {
if rn >= REG_COUNT as u8 {
Err(Fault::RegisterNotExist { reg: Register::Res(rn) }) // TODO use match after @ when stabilized https://github.com/rust-lang/rust/issues/65490
} else {
Err(Fault::RegisterNotWritable { reg: Register::Res(rn) })
}
}
DstDisp::Register(Register::Arg(rn)) => {
if rn >= REG_COUNT as u8 {
Err(Fault::RegisterNotExist { reg: Register::Arg(rn) })
} else {
Err(Fault::RegisterNotWritable { reg: Register::Res(rn) })
}
}
DstDisp::Register(Register::Gen(rn)) => {
if rn >= REG_COUNT as u8 {
Err(Fault::RegisterNotExist { reg: Register::Gen(rn) })
} else {
self.frame.gen[rn as usize] = val;
Ok(())
}
}
DstDisp::ObjectPtr(_) => {
unimplemented!("Write object ptr")
}
}
}
}

@ -2,191 +2,189 @@ use std::ops::Rem;
use num_traits::PrimInt;
use crsn::asm::instr::op::{OpTrait, EvalRes};
use crsn::asm::instr::Cond;
use crsn::asm::instr::op::{EvalRes, OpTrait};
use crsn::runtime::fault::Fault;
use crsn::runtime::run_thread::{state::RunState, ThreadInfo};
use crate::defs::ArithOp;
use crsn::runtime::run_thread::{ThreadInfo, RunState};
impl OpTrait for ArithOp {
fn execute(&self, _ti: &ThreadInfo, state: &mut RunState) -> Result<EvalRes, Fault> {
let frame = &mut state.frame;
let eres = EvalRes::default();
match self {
ArithOp::Test { a } => {
frame.status.clear();
let res = frame.read(*a)?;
frame.status.update(res);
state.clear_status();
let res = state.read(*a)?;
state.update_status(res);
}
ArithOp::Compare { a, b } => {
frame.status.clear();
let x = frame.read(*a)?;
let y = frame.read(*b)?;
frame.status.equal = x == y;
frame.status.lower = x < y;
frame.status.greater = x > y;
state.clear_status();
let x = state.read(*a)?;
let y = state.read(*b)?;
state.set_flag(Cond::Equal, x == y);
state.set_flag(Cond::Lower, x < y);
state.set_flag(Cond::Greater, x > y);
// Test flags are set when both arguments have the property
if x == y {
frame.status.update(x);
state.update_status(x);
}
}
ArithOp::Add { dst, a, b } => {
frame.status.clear();
let x = frame.read(*a)?;
let y = frame.read(*b)?;
state.clear_status();
let x = state.read(*a)?;
let y = state.read(*b)?;
let (res, ov) = if let Some(v) = x.checked_add(y) {
(v, false)
} else {
(x.wrapping_add(y), true)
};
frame.status.update(res);
frame.status.overflow = ov;
frame.write(*dst, res)?;
state.update_status(res);
state.set_flag(Cond::Overflow, ov);
state.write(*dst, res)?;
}
ArithOp::Sub { dst, a, b } => {
frame.status.clear();
let x = frame.read(*a)?;
let y = frame.read(*b)?;
state.clear_status();
let x = state.read(*a)?;
let y = state.read(*b)?;
let (res, ov) = if let Some(v) = x.checked_sub(y) {
(v, false)
} else {
(x.wrapping_sub(y), true)
};
frame.status.update(res);
frame.status.overflow = ov;
frame.write(*dst, res)?;
state.update_status(res);
state.set_flag(Cond::Overflow, ov);
state.write(*dst, res)?;
}
ArithOp::Mul { dst, a, b } => {
frame.status.clear();
let x = frame.read(*a)?;
let y = frame.read(*b)?;
state.clear_status();
let x = state.read(*a)?;
let y = state.read(*b)?;
let (res, ov) = if let Some(v) = x.checked_mul(y) {
(v, false)
} else {
(x.wrapping_mul(y), true)
};
frame.status.update(res);
frame.status.overflow = ov;
frame.write(*dst, res)?;
state.update_status(res);
state.set_flag(Cond::Overflow, ov);
state.write(*dst, res)?;
}
ArithOp::Div { dst, rem, a, div } => {
frame.status.clear();
let x = frame.read(*a)?;
let d = frame.read(*div)?;
state.clear_status();
let x = state.read(*a)?;
let d = state.read(*div)?;
if d == 0 {
frame.status.invalid = true;
state.set_flag(Cond::Invalid, true);
} else {
let (res, remainder, ov) = if let Some(v) = x.checked_div(d) {
(v, x.rem(d), false)
} else {
(x.wrapping_div(d), x.wrapping_rem(d), true)
};
frame.status.update(res);
frame.status.overflow = ov;
frame.write(*dst, res)?;
frame.write(*rem, remainder)?;
state.update_status(res);
state.set_flag(Cond::Overflow, ov);
state.write(*dst, res)?;
state.write(*rem, remainder)?;
}
}
ArithOp::Mod { dst, a, div } => {
frame.status.clear();
let x = frame.read(*a)?;
let d = frame.read(*div)?;
state.clear_status();
let x = state.read(*a)?;
let d = state.read(*div)?;
if d == 0 {
frame.status.invalid = true;
state.set_flag(Cond::Invalid, true);
} else {
let (remainder, ov) = if let Some(v) = x.checked_rem(d) {
(v, false)
} else {
(x.wrapping_rem(d), true)
};
frame.status.update(remainder);
frame.status.overflow = ov;
frame.write(*dst, remainder)?;
state.update_status(remainder);
state.set_flag(Cond::Overflow, ov);
state.write(*dst, remainder)?;
}
}
ArithOp::And { dst, a, b } => {
frame.status.clear();
let x = frame.read(*a)?;
let y = frame.read(*b)?;
state.clear_status();
let x = state.read(*a)?;
let y = state.read(*b)?;
let res = x & y;
frame.status.update(res);
frame.write(*dst, res)?;
state.update_status(res);
state.write(*dst, res)?;
}
ArithOp::Or { dst, a, b } => {
frame.status.clear();
let x = frame.read(*a)?;
let y = frame.read(*b)?;
state.clear_status();
let x = state.read(*a)?;
let y = state.read(*b)?;
let res = x | y;
frame.status.update(res);
frame.write(*dst, res)?;
state.update_status(res);
state.write(*dst, res)?;
}
ArithOp::Xor { dst, a, b } => {
frame.status.clear();
let x = frame.read(*a)?;
let y = frame.read(*b)?;
state.clear_status();
let x = state.read(*a)?;
let y = state.read(*b)?;
let res = x ^ y;
frame.status.update(res);
frame.write(*dst, res)?;
state.update_status(res);
state.write(*dst, res)?;
}
ArithOp::Cpl { dst, a } => {
frame.status.clear();
let x = frame.read(*a)?;
state.clear_status();
let x = state.read(*a)?;
let res = !x;
frame.status.update(res);
frame.write(*dst, res)?;
state.update_status(res);
state.write(*dst, res)?;
}
ArithOp::Rol { dst, a, n } => {
frame.status.clear();
let x = frame.read(*a)?;
let y = frame.read(*n)?;
state.clear_status();
let x = state.read(*a)?;
let y = state.read(*n)?;
if y > u32::MAX as u64 {
frame.status.invalid = true;
state.set_flag(Cond::Invalid, true);
} else {
let res = x.rotate_left(y as u32);
frame.status.update(res);
frame.write(*dst, res)?;
state.update_status(res);
state.write(*dst, res)?;
}
}
ArithOp::Ror { dst, a, n } => {
frame.status.clear();
let x = frame.read(*a)?;
let y = frame.read(*n)?;
state.clear_status();
let x = state.read(*a)?;
let y = state.read(*n)?;
if y > u32::MAX as u64 {
frame.status.invalid = true;
state.set_flag(Cond::Invalid, true);
} else {
let res = x.rotate_right(y as u32);
frame.status.update(res);
frame.write(*dst, res)?;
state.update_status(res);
state.write(*dst, res)?;
}
}
ArithOp::Lsl { dst, a, n } => {
frame.status.clear();
let x = frame.read(*a)?;
let y = frame.read(*n)?;
state.clear_status();
let x = state.read(*a)?;
let y = state.read(*n)?;
let res = x << y;
frame.status.update(res);
frame.write(*dst, res)?;
state.update_status(res);
state.write(*dst, res)?;
}
ArithOp::Lsr { dst, a, n } => {
frame.status.clear();
let x = frame.read(*a)?;
let y = frame.read(*n)?;
state.clear_status();
let x = state.read(*a)?;
let y = state.read(*n)?;
let res = x >> y;
frame.status.update(res);
frame.write(*dst, res)?;
state.update_status(res);
state.write(*dst, res)?;
}
ArithOp::Asr { dst, a, n } => {
frame.status.clear();
let x = frame.read(*a)?;
let y = frame.read(*n)?;
state.clear_status();
let x = state.read(*a)?;
let y = state.read(*n)?;
if y > u32::MAX as u64 {
frame.status.invalid = true;
state.set_flag(Cond::Invalid, true);
} else {
let res = x.signed_shr(y as u32);
frame.status.update(res);
frame.write(*dst, res)?;
state.update_status(res);
state.write(*dst, res)?;
}
}
}

@ -1,14 +1,12 @@
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 crsn::runtime::run_thread::{state::RunState, ThreadInfo};
use crate::defs::StackOp;
use crsn::asm::instr::Cond;
struct Stacks {
stacks: Vec<VecDeque<Value>>,
@ -27,34 +25,34 @@ impl OpTrait for StackOp {
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)?;
state.clear_status();
let stack_num = state.read(*num)?;
let val = state.read(*src)?;
if stack_num > 8 {
state.frame.status.invalid = true;
state.set_flag(Cond::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)?;
state.clear_status();
let stack_num = state.read(*num)?;
if stack_num > 8 {
state.frame.status.invalid = true;
state.set_flag(Cond::Invalid, true);
} else {
let obj: &mut Stacks = state.ext_mut();
let val = obj.stacks[stack_num as usize].pop_back();
if obj.stacks[stack_num as usize].is_empty() {
state.frame.status.zero = true;
state.set_flag(Cond::Zero, true);
}
let val = match val {
None => {
state.frame.status.overflow = true;
state.set_flag(Cond::Overflow, true);
0
}
Some(val) => {
@ -62,7 +60,7 @@ impl OpTrait for StackOp {
}
};
state.frame.write(*dst, val)?;
state.write(*dst, val)?;
}
// TODO

@ -51,15 +51,15 @@ fn main() {
(ld _ arg0)
(fault)
(:lbl)
(call fibo 5)
(call fac 5)
(ld r0 res0)
)
(fibo
(fac
(cmp arg0 2
(eq? (ret 2)))
(ld r0 arg0)
(dec r0)
(call fibo r0)
(call fac r0)
(ld r0 arg0)
(mul r0 res0)
(ret r0)

Loading…
Cancel
Save