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

floats
Ondřej Hruška 4 years ago
parent d489b214e0
commit 8222efe6da
Signed by untrusted user: 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 /// Label name
#[derive(Debug, Clone, Eq, PartialEq, Hash)] #[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum Label { pub enum Label {

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

@ -9,7 +9,7 @@ use crate::builtin::defs::BuiltinOp;
use crate::runtime::fault::Fault; 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 /// A higher level simple opration
#[derive(Debug)] #[derive(Debug)]

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

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

@ -5,7 +5,7 @@ use crate::asm::data::literal::{Addr, Value};
use super::fault::Fault; use super::fault::Fault;
mod status; pub(crate) mod status;
pub const REG_COUNT: usize = 8; pub const REG_COUNT: usize = 8;
@ -41,79 +41,4 @@ impl StackFrame {
self.res[n] = vals[n]; 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 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 { impl Display for StatusFlags {

@ -4,11 +4,13 @@ use std::sync::Arc;
use std::thread::JoinHandle; use std::thread::JoinHandle;
use std::time::Duration; 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::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::program::Program;
use crate::runtime::fault::Fault; 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)] #[derive(Clone, Copy, Eq, PartialEq, Debug, Ord, PartialOrd)]
pub struct ThreadToken(pub u32); pub struct ThreadToken(pub u32);
@ -27,25 +29,7 @@ pub struct ThreadInfo {
pub cycle_time: Duration, pub cycle_time: Duration,
} }
pub struct RunState { pub mod state;
/// 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()
}
}
impl RunThread { impl RunThread {
pub fn new(id: ThreadToken, program: Arc<Program>, pc: Addr, args: &[u64]) -> Self { 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 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::fault::Fault;
use crsn::runtime::run_thread::{state::RunState, ThreadInfo};
use crate::defs::ArithOp; use crate::defs::ArithOp;
use crsn::runtime::run_thread::{ThreadInfo, RunState};
impl OpTrait for ArithOp { impl OpTrait for ArithOp {
fn execute(&self, _ti: &ThreadInfo, state: &mut RunState) -> Result<EvalRes, Fault> { fn execute(&self, _ti: &ThreadInfo, state: &mut RunState) -> Result<EvalRes, Fault> {
let frame = &mut state.frame;
let eres = EvalRes::default(); let eres = EvalRes::default();
match self { match self {
ArithOp::Test { a } => { ArithOp::Test { a } => {
frame.status.clear(); state.clear_status();
let res = frame.read(*a)?; let res = state.read(*a)?;
frame.status.update(res); state.update_status(res);
} }
ArithOp::Compare { a, b } => { ArithOp::Compare { a, b } => {
frame.status.clear(); state.clear_status();
let x = frame.read(*a)?; let x = state.read(*a)?;
let y = frame.read(*b)?; let y = state.read(*b)?;
frame.status.equal = x == y; state.set_flag(Cond::Equal, x == y);
frame.status.lower = x < y; state.set_flag(Cond::Lower, x < y);
frame.status.greater = x > y; state.set_flag(Cond::Greater, x > y);
// Test flags are set when both arguments have the property // Test flags are set when both arguments have the property
if x == y { if x == y {
frame.status.update(x); state.update_status(x);
} }
} }
ArithOp::Add { dst, a, b } => { ArithOp::Add { dst, a, b } => {
frame.status.clear(); state.clear_status();
let x = frame.read(*a)?; let x = state.read(*a)?;
let y = frame.read(*b)?; let y = state.read(*b)?;
let (res, ov) = if let Some(v) = x.checked_add(y) { let (res, ov) = if let Some(v) = x.checked_add(y) {
(v, false) (v, false)
} else { } else {
(x.wrapping_add(y), true) (x.wrapping_add(y), true)
}; };
frame.status.update(res); state.update_status(res);
frame.status.overflow = ov; state.set_flag(Cond::Overflow, ov);
frame.write(*dst, res)?; state.write(*dst, res)?;
} }
ArithOp::Sub { dst, a, b } => { ArithOp::Sub { dst, a, b } => {
frame.status.clear(); state.clear_status();
let x = frame.read(*a)?; let x = state.read(*a)?;
let y = frame.read(*b)?; let y = state.read(*b)?;
let (res, ov) = if let Some(v) = x.checked_sub(y) { let (res, ov) = if let Some(v) = x.checked_sub(y) {
(v, false) (v, false)
} else { } else {
(x.wrapping_sub(y), true) (x.wrapping_sub(y), true)
}; };
frame.status.update(res); state.update_status(res);
frame.status.overflow = ov; state.set_flag(Cond::Overflow, ov);
frame.write(*dst, res)?; state.write(*dst, res)?;
} }
ArithOp::Mul { dst, a, b } => { ArithOp::Mul { dst, a, b } => {
frame.status.clear(); state.clear_status();
let x = frame.read(*a)?; let x = state.read(*a)?;
let y = frame.read(*b)?; let y = state.read(*b)?;
let (res, ov) = if let Some(v) = x.checked_mul(y) { let (res, ov) = if let Some(v) = x.checked_mul(y) {
(v, false) (v, false)
} else { } else {
(x.wrapping_mul(y), true) (x.wrapping_mul(y), true)
}; };
frame.status.update(res); state.update_status(res);
frame.status.overflow = ov; state.set_flag(Cond::Overflow, ov);
frame.write(*dst, res)?; state.write(*dst, res)?;
} }
ArithOp::Div { dst, rem, a, div } => { ArithOp::Div { dst, rem, a, div } => {
frame.status.clear(); state.clear_status();
let x = frame.read(*a)?; let x = state.read(*a)?;
let d = frame.read(*div)?; let d = state.read(*div)?;
if d == 0 { if d == 0 {
frame.status.invalid = true; state.set_flag(Cond::Invalid, true);
} else { } else {
let (res, remainder, ov) = if let Some(v) = x.checked_div(d) { let (res, remainder, ov) = if let Some(v) = x.checked_div(d) {
(v, x.rem(d), false) (v, x.rem(d), false)
} else { } else {
(x.wrapping_div(d), x.wrapping_rem(d), true) (x.wrapping_div(d), x.wrapping_rem(d), true)
}; };
frame.status.update(res); state.update_status(res);
frame.status.overflow = ov; state.set_flag(Cond::Overflow, ov);
frame.write(*dst, res)?; state.write(*dst, res)?;
frame.write(*rem, remainder)?; state.write(*rem, remainder)?;
} }
} }
ArithOp::Mod { dst, a, div } => { ArithOp::Mod { dst, a, div } => {
frame.status.clear(); state.clear_status();
let x = frame.read(*a)?; let x = state.read(*a)?;
let d = frame.read(*div)?; let d = state.read(*div)?;
if d == 0 { if d == 0 {
frame.status.invalid = true; state.set_flag(Cond::Invalid, true);
} else { } else {
let (remainder, ov) = if let Some(v) = x.checked_rem(d) { let (remainder, ov) = if let Some(v) = x.checked_rem(d) {
(v, false) (v, false)
} else { } else {
(x.wrapping_rem(d), true) (x.wrapping_rem(d), true)
}; };
frame.status.update(remainder); state.update_status(remainder);
frame.status.overflow = ov; state.set_flag(Cond::Overflow, ov);
frame.write(*dst, remainder)?; state.write(*dst, remainder)?;
} }
} }
ArithOp::And { dst, a, b } => { ArithOp::And { dst, a, b } => {
frame.status.clear(); state.clear_status();
let x = frame.read(*a)?; let x = state.read(*a)?;
let y = frame.read(*b)?; let y = state.read(*b)?;
let res = x & y; let res = x & y;
frame.status.update(res); state.update_status(res);
frame.write(*dst, res)?; state.write(*dst, res)?;
} }
ArithOp::Or { dst, a, b } => { ArithOp::Or { dst, a, b } => {
frame.status.clear(); state.clear_status();
let x = frame.read(*a)?; let x = state.read(*a)?;
let y = frame.read(*b)?; let y = state.read(*b)?;
let res = x | y; let res = x | y;
frame.status.update(res); state.update_status(res);
frame.write(*dst, res)?; state.write(*dst, res)?;
} }
ArithOp::Xor { dst, a, b } => { ArithOp::Xor { dst, a, b } => {
frame.status.clear(); state.clear_status();
let x = frame.read(*a)?; let x = state.read(*a)?;
let y = frame.read(*b)?; let y = state.read(*b)?;
let res = x ^ y; let res = x ^ y;
frame.status.update(res); state.update_status(res);
frame.write(*dst, res)?; state.write(*dst, res)?;
} }
ArithOp::Cpl { dst, a } => { ArithOp::Cpl { dst, a } => {
frame.status.clear(); state.clear_status();
let x = frame.read(*a)?; let x = state.read(*a)?;
let res = !x; let res = !x;
frame.status.update(res); state.update_status(res);
frame.write(*dst, res)?; state.write(*dst, res)?;
} }
ArithOp::Rol { dst, a, n } => { ArithOp::Rol { dst, a, n } => {
frame.status.clear(); state.clear_status();
let x = frame.read(*a)?; let x = state.read(*a)?;
let y = frame.read(*n)?; let y = state.read(*n)?;
if y > u32::MAX as u64 { if y > u32::MAX as u64 {
frame.status.invalid = true; state.set_flag(Cond::Invalid, true);
} else { } else {
let res = x.rotate_left(y as u32); let res = x.rotate_left(y as u32);
frame.status.update(res); state.update_status(res);
frame.write(*dst, res)?; state.write(*dst, res)?;
} }
} }
ArithOp::Ror { dst, a, n } => { ArithOp::Ror { dst, a, n } => {
frame.status.clear(); state.clear_status();
let x = frame.read(*a)?; let x = state.read(*a)?;
let y = frame.read(*n)?; let y = state.read(*n)?;
if y > u32::MAX as u64 { if y > u32::MAX as u64 {
frame.status.invalid = true; state.set_flag(Cond::Invalid, true);
} else { } else {
let res = x.rotate_right(y as u32); let res = x.rotate_right(y as u32);
frame.status.update(res); state.update_status(res);
frame.write(*dst, res)?; state.write(*dst, res)?;
} }
} }
ArithOp::Lsl { dst, a, n } => { ArithOp::Lsl { dst, a, n } => {
frame.status.clear(); state.clear_status();
let x = frame.read(*a)?; let x = state.read(*a)?;
let y = frame.read(*n)?; let y = state.read(*n)?;
let res = x << y; let res = x << y;
frame.status.update(res); state.update_status(res);
frame.write(*dst, res)?; state.write(*dst, res)?;
} }
ArithOp::Lsr { dst, a, n } => { ArithOp::Lsr { dst, a, n } => {
frame.status.clear(); state.clear_status();
let x = frame.read(*a)?; let x = state.read(*a)?;
let y = frame.read(*n)?; let y = state.read(*n)?;
let res = x >> y; let res = x >> y;
frame.status.update(res); state.update_status(res);
frame.write(*dst, res)?; state.write(*dst, res)?;
} }
ArithOp::Asr { dst, a, n } => { ArithOp::Asr { dst, a, n } => {
frame.status.clear(); state.clear_status();
let x = frame.read(*a)?; let x = state.read(*a)?;
let y = frame.read(*n)?; let y = state.read(*n)?;
if y > u32::MAX as u64 { if y > u32::MAX as u64 {
frame.status.invalid = true; state.set_flag(Cond::Invalid, true);
} else { } else {
let res = x.signed_shr(y as u32); let res = x.signed_shr(y as u32);
frame.status.update(res); state.update_status(res);
frame.write(*dst, res)?; state.write(*dst, res)?;
} }
} }
} }

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

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

Loading…
Cancel
Save