add explicit retval arg to all instrs (can be shortened), add Wr::discard()

This commit is contained in:
2020-09-25 22:45:57 +02:00
parent f652ff6669
commit 8e7689df48
13 changed files with 726 additions and 420 deletions
+147 -193
View File
@@ -1,9 +1,9 @@
use crate::run_thread::{ThreadToken, RunThread};
use asm::instr::{Op, Cond};
use crate::run_thread::{RunThread};
use asm::instr::{Op};
use crate::fault::Fault;
use crate::frame::StackFrame;
use asm::data::literal::{Value, is_positive, is_negative, Addr};
use std::ops::{Rem, BitXor, Shl};
use asm::data::literal::{Addr};
use std::ops::{Rem};
use num_traits::PrimInt;
pub type CyclesSpent = usize;
@@ -38,12 +38,12 @@ impl RunThread {
Op::Barrier(msg) => {
return Err(Fault::Barrier {
msg: msg.clone().unwrap_or_else(|| "No msg".into())
})
});
}
Op::Fault(msg) => {
return Err(Fault::FaultInstr {
msg: msg.clone().unwrap_or_else(|| "No msg".into())
})
});
}
Op::FarJump(name) => {
debug!("Far jump to {}", name);
@@ -56,7 +56,7 @@ impl RunThread {
return Err(e);
}
}
},
}
Op::Call(name, args) => {
debug!("Call routine {}", name);
match self.program.find_routine(name) {
@@ -77,7 +77,7 @@ impl RunThread {
return Err(e);
}
}
},
}
Op::Ret(retvals) => {
match self.call_stack.pop() {
Some(previous) => {
@@ -93,7 +93,7 @@ impl RunThread {
return Err(Fault::CallStackUnderflow);
}
}
},
}
Op::Skip(val) => {
let steps = frame.read(*val)?;
advance = i64::from_ne_bytes(steps.to_ne_bytes());
@@ -106,239 +106,193 @@ impl RunThread {
self.program.validate_jump(frame.pc, Addr((frame.pc.0 as i64 + advance) as u64))?;
}
}
Op::Mov(dst, src) => {
Op::Move { dst, src } => {
frame.status.clear();
let val = frame.read(*src)?;
frame.status.zero = (val == 0);
frame.status.positive = is_positive(val);
frame.status.negative = is_negative(val);
frame.status.update(val);
frame.write(*dst, val)?;
}
Op::Cmp(a, b) => {
Op::Test { a } => {
frame.status.clear();
let a = frame.read(*a)?;
let b = frame.read(*b)?;
frame.status.equal = a == b;
frame.status.zero = a == 0 && b == 0;
frame.status.lower = a < b;
frame.status.greater = a > b;
frame.status.positive = is_positive(a) && is_positive(b);
frame.status.negative = is_negative(a) && is_negative(b);
let res = frame.read(*a)?;
frame.status.update(res);
}
Op::Inc(reg) => {
Op::Compare { a, b } => {
frame.status.clear();
let mut val = frame.read(reg.as_rd())?;
val = val.wrapping_add(1);
frame.status.overflow = (val == 0);
frame.status.zero = (val == 0);
frame.status.positive = is_positive(val);
frame.status.negative = is_negative(val);
frame.write(*reg, val)?;
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;
// Test flags are set when both arguments have the property
if x == y {
frame.status.update(x);
}
}
Op::Dec(reg) => {
Op::Add { dst, a, b } => {
frame.status.clear();
let mut val = frame.read(reg.as_rd())?;
frame.status.overflow = (val == 0); // will overflow
val = val.wrapping_sub(1);
frame.status.zero = (val == 0);
frame.status.positive = is_positive(val);
frame.status.negative = is_negative(val);
frame.write(*reg, val)?;
}
Op::Add(dst, src) => {
frame.status.clear();
let mut a = frame.read(dst.as_rd())?;
let mut b = frame.read(*src)?;
let (val, ov) = if let Some(v) = a.checked_add(b) {
let x = frame.read(*a)?;
let y = frame.read(*b)?;
let (res, ov) = if let Some(v) = x.checked_add(y) {
(v, false)
} else {
(a.wrapping_add(b), true)
(x.wrapping_add(y), true)
};
frame.status.zero = (val == 0);
frame.status.positive = is_positive(val);
frame.status.negative = is_negative(val);
frame.status.update(res);
frame.status.overflow = ov;
frame.write(*dst, val)?;
frame.write(*dst, res)?;
}
Op::Sub(dst, src) => {
Op::Sub { dst, a, b } => {
frame.status.clear();
let mut a = frame.read(dst.as_rd())?;
let mut b = frame.read(*src)?;
let (val, ov) = if let Some(v) = a.checked_sub(b) {
let x = frame.read(*a)?;
let y = frame.read(*b)?;
let (res, ov) = if let Some(v) = x.checked_sub(y) {
(v, false)
} else {
(a.wrapping_sub(b), true)
(x.wrapping_sub(y), true)
};
frame.status.zero = (val == 0);
frame.status.positive = is_positive(val);
frame.status.negative = is_negative(val);
frame.status.update(res);
frame.status.overflow = ov;
frame.write(*dst, val)?;
frame.write(*dst, res)?;
}
Op::Mul(dst, src) => {
Op::Mul { dst, a, b } => {
frame.status.clear();
let mut a = frame.read(dst.as_rd())?;
let mut b = frame.read(*src)?;
let (val, ov) = if let Some(v) = a.checked_mul(b) {
let x = frame.read(*a)?;
let y = frame.read(*b)?;
let (res, ov) = if let Some(v) = x.checked_mul(y) {
(v, false)
} else {
(a.wrapping_mul(b), true)
(x.wrapping_mul(y), true)
};
frame.status.zero = (val == 0);
frame.status.positive = is_positive(val);
frame.status.negative = is_negative(val);
frame.status.update(res);
frame.status.overflow = ov;
frame.write(*dst, val)?;
frame.write(*dst, res)?;
}
Op::Div(dst, src) => {
Op::Div { dst, rem, a, div } => {
frame.status.clear();
let mut a = frame.read(dst.as_rd())?;
let mut b = frame.read(*src)?;
if b == 0 {
frame.status.overflow = true;
// TODO ?
let x = frame.read(*a)?;
let d = frame.read(*div)?;
if d == 0 {
frame.status.invalid = true;
} else {
let (val, ov) = if let Some(v) = a.checked_div(b) {
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)?;
}
}
Op::Mod { dst, a, div } => {
frame.status.clear();
let x = frame.read(*a)?;
let d = frame.read(*div)?;
if d == 0 {
frame.status.invalid = true;
} else {
let (remainder, ov) = if let Some(v) = x.checked_rem(d) {
(v, false)
} else {
(a.wrapping_div(b), true)
(x.wrapping_rem(d), true)
};
frame.status.zero = (val == 0);
frame.status.positive = is_positive(val);
frame.status.negative = is_negative(val);
frame.status.update(remainder);
frame.status.overflow = ov;
frame.write(*dst, val)?;
frame.write(*dst, remainder)?;
}
}
Op::Mod(dst, src) => {
Op::And { dst, a, b } => {
frame.status.clear();
let mut a = frame.read(dst.as_rd())?;
let mut b = frame.read(*src)?;
if b == 0 {
frame.status.overflow = true;
// TODO ?
let x = frame.read(*a)?;
let y = frame.read(*b)?;
let res = x & y;
frame.status.update(res);
frame.write(*dst, res)?;
}
Op::Or { dst, a, b } => {
frame.status.clear();
let x = frame.read(*a)?;
let y = frame.read(*b)?;
let res = x | y;
frame.status.update(res);
frame.write(*dst, res)?;
}
Op::Xor { dst, a, b } => {
frame.status.clear();
let x = frame.read(*a)?;
let y = frame.read(*b)?;
let res = x ^ y;
frame.status.update(res);
frame.write(*dst, res)?;
}
Op::Cpl { dst, a } => {
frame.status.clear();
let x = frame.read(*a)?;
let res = !x;
frame.status.update(res);
frame.write(*dst, res)?;
}
Op::Rol { dst, a, n } => {
frame.status.clear();
let x = frame.read(*a)?;
let y = frame.read(*n)?;
if y > u32::MAX as u64 {
frame.status.invalid = true;
} else {
let (val, ov) = if let Some(v) = a.checked_rem(b) {
(v, false)
} else {
(a.wrapping_rem(b), true)
};
frame.status.zero = (val == 0);
frame.status.positive = is_positive(val);
frame.status.negative = is_negative(val);
frame.status.overflow = ov;
frame.write(*dst, val)?;
let res = x.rotate_left(y as u32);
frame.status.update(res);
frame.write(*dst, res)?;
}
}
Op::DivRem(dst, remptr, src) => {
Op::Ror { dst, a, n } => {
frame.status.clear();
let mut a = frame.read(dst.as_rd())?;
let mut b = frame.read(*src)?;
if b == 0 {
frame.status.overflow = true;
// TODO ?
let x = frame.read(*a)?;
let y = frame.read(*n)?;
if y > u32::MAX as u64 {
frame.status.invalid = true;
} else {
let (val, rem, ov) = if let Some(v) = a.checked_div(b) {
(v, a.rem(b), false)
} else {
(a.wrapping_div(b), a.wrapping_rem(b), true)
};
frame.status.zero = (val == 0);
frame.status.positive = is_positive(val);
frame.status.negative = is_negative(val);
frame.status.overflow = ov;
frame.write(*dst, val)?;
frame.write(*remptr, rem)?;
let res = x.rotate_right(y as u32);
frame.status.update(res);
frame.write(*dst, res)?;
}
}
Op::And(dst, src) => {
Op::Lsl { dst, a, n } => {
frame.status.clear();
let mut val = frame.read(dst.as_rd())?;
let mut b = frame.read(*src)?;
val &= b;
frame.status.zero = (val == 0);
frame.status.positive = is_positive(val);
frame.status.negative = is_negative(val);
frame.write(*dst, val)?;
let x = frame.read(*a)?;
let y = frame.read(*n)?;
let res = x << y;
frame.status.update(res);
frame.write(*dst, res)?;
}
Op::Or(dst, src) => {
Op::Lsr { dst, a, n } => {
frame.status.clear();
let mut val = frame.read(dst.as_rd())?;
let mut b = frame.read(*src)?;
val |= b;
frame.status.zero = (val == 0);
frame.status.positive = is_positive(val);
frame.status.negative = is_negative(val);
frame.write(*dst, val)?;
let x = frame.read(*a)?;
let y = frame.read(*n)?;
let res = x >> y;
frame.status.update(res);
frame.write(*dst, res)?;
}
Op::Xor(dst, src) => {
Op::Asr { dst, a, n } => {
frame.status.clear();
let mut val = frame.read(dst.as_rd())?;
let mut b = frame.read(*src)?;
val ^= b;
frame.status.zero = (val == 0);
frame.status.positive = is_positive(val);
frame.status.negative = is_negative(val);
frame.write(*dst, val)?;
let x = frame.read(*a)?;
let y = frame.read(*n)?;
if y > u32::MAX as u64 {
frame.status.invalid = true;
} else {
let res = x.signed_shr(y as u32);
frame.status.update(res);
frame.write(*dst, res)?;
}
}
Op::Cpl(dst) => {
frame.status.clear();
let mut val = frame.read(dst.as_rd())?;
val = !val;
frame.status.zero = (val == 0);
frame.status.positive = is_positive(val);
frame.status.negative = is_negative(val);
frame.write(*dst, val)?;
Op::StoreStatus { dst } => {
let packed = frame.status.store();
frame.write(*dst, packed)?;
}
Op::Rol(dst, num) => {
frame.status.clear();
let mut val = frame.read(dst.as_rd())?;
let mut b = frame.read(*num)?;
val = val.rotate_left(b as u32); // FIXME check overflow
frame.status.zero = (val == 0);
frame.status.positive = is_positive(val);
frame.status.negative = is_negative(val);
frame.write(*dst, val)?;
}
Op::Ror(dst, num) => {
frame.status.clear();
let mut val = frame.read(dst.as_rd())?;
let mut b = frame.read(*num)?;
val = val.rotate_right(b as u32); // FIXME check overflow
frame.status.zero = (val == 0);
frame.status.positive = is_positive(val);
frame.status.negative = is_negative(val);
frame.write(*dst, val)?;
}
Op::Lsl(dst, num) => {
frame.status.clear();
let mut val = frame.read(dst.as_rd())?;
let mut b = frame.read(*num)?;
val = val << b;
frame.status.zero = (val == 0);
frame.status.positive = is_positive(val);
frame.status.negative = is_negative(val);
frame.write(*dst, val)?;
}
Op::Lsr(dst, num) => {
frame.status.clear();
let mut val = frame.read(dst.as_rd())?;
let mut b = frame.read(*num)?;
val = val >> b;
frame.status.zero = (val == 0);
frame.status.positive = is_positive(val);
frame.status.negative = is_negative(val);
frame.write(*dst, val)?;
}
Op::Asr(dst, num) => {
frame.status.clear();
let mut val = frame.read(dst.as_rd())?;
let mut b = frame.read(*num)?;
val = val.signed_shr(b as u32); // FIXME check overflow
frame.status.zero = (val == 0);
frame.status.positive = is_positive(val);
frame.status.negative = is_negative(val);
frame.write(*dst, val)?;
Op::LoadStatus { src } => {
let x = frame.read(*src)?;
frame.status.load(x);
}
}
+14 -14
View File
@@ -1,7 +1,7 @@
use thiserror::Error;
use super::span::MemorySpan;
use crate::run_thread::ThreadToken;
use crate::mlock::ClaimId;
// use super::span::MemorySpan;
// use crate::run_thread::ThreadToken;
// use crate::mlock::ClaimId;
use asm::data::literal::{DebugMsg, RoutineName, Label};
use asm::data::Register;
@@ -23,17 +23,17 @@ pub enum Fault {
msg: DebugMsg,
},
#[error("Memory region {area:?} is locked by thread {owner:?}")]
MemoryLocked {
area: MemorySpan,
owner: ThreadToken
},
#[error("Memory claim {claim:?} owned by thread {owner:?} does not exist")]
ClaimNotExist {
claim: ClaimId,
owner: ThreadToken
},
// #[error("Memory region {area:?} is locked by thread {owner:?}")]
// MemoryLocked {
// area: MemorySpan,
// owner: ThreadToken
// },
//
// #[error("Memory claim {claim:?} owned by thread {owner:?} does not exist")]
// ClaimNotExist {
// claim: ClaimId,
// owner: ThreadToken
// },
#[error("Register does not exist: {reg:?}")]
RegisterNotExist {
+11 -84
View File
@@ -1,92 +1,15 @@
use asm::data::literal::{Addr, Value};
use asm::data::{Rd, SrcDisp, Register, Wr, DstDisp};
use crate::fault::Fault;
use asm::instr::Cond;
use std::fmt::{Display, Formatter, Write};
use std::fmt;
mod status;
use status::StatusFlags;
pub const REG_COUNT: usize = 8;
#[derive(Default, Clone, Debug)]
pub struct StatusFlags {
/// Arguments are equal
pub equal: bool,
/// Register is zero
pub zero: bool,
/// A < B
pub lower: bool,
/// A > B
pub greater: bool,
/// Register is positive
pub positive: bool,
/// Register is negative
pub negative: bool,
/// Overflow (multiplication etc.)
pub overflow: bool,
/// Arithmetic carry
pub carry: bool,
}
impl Display for StatusFlags {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.write_str("[")?;
if self.equal {
f.write_str(" E")?;
}
if self.zero {
f.write_str(" Z")?;
}
if self.lower {
f.write_str(" L")?;
}
if self.greater {
f.write_str(" G")?;
}
if self.positive {
f.write_str(" P")?;
}
if self.negative {
f.write_str(" N")?;
}
if self.overflow {
f.write_str(" V")?;
}
if self.carry {
f.write_str(" C")?;
}
f.write_str(" ]")?;
Ok(())
}
}
impl StatusFlags {
pub fn clear(&mut self) {
*self = Self::default();
}
pub fn test(&self, cond: Cond) -> bool {
match cond {
Cond::Equal => self.equal,
Cond::NotEqual => !self.equal,
Cond::Zero => self.zero,
Cond::NotZero => !self.zero,
Cond::Lower => self.lower,
Cond::LowerOrEqual => self.lower || self.equal,
Cond::Greater => self.greater,
Cond::GreaterOrEqual => self.greater || self.equal,
Cond::Positive => self.positive,
Cond::NonPositive => !self.positive,
Cond::Negative => self.negative,
Cond::NonNegative => !self.negative,
Cond::Overflow => self.overflow,
Cond::NotOverflow => !self.overflow,
Cond::Carry => self.carry,
Cond::NotCarry => !self.carry
}
}
}
#[derive(Default, Clone, Debug)]
pub struct StackFrame {
/// Program counter, address of the executed instruction
@@ -118,7 +41,7 @@ impl StackFrame {
}
}
pub fn read(&mut self, rd: Rd) -> Result<u64, Fault> {
pub fn read(&mut self, rd: Rd) -> Result<Value, Fault> {
match rd.d() {
SrcDisp::Immediate(v) => Ok(v),
SrcDisp::ImmediatePtr(_) => {
@@ -161,6 +84,10 @@ impl StackFrame {
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
+123
View File
@@ -0,0 +1,123 @@
use std::fmt::{Display, Formatter};
use std::fmt;
use asm::data::literal::{Value, is_positive, is_negative};
use asm::instr::Cond;
#[derive(Default, Clone, Debug)]
pub struct StatusFlags {
/// Arguments are equal
pub equal: bool,
/// A < B
pub lower: bool,
/// A > B
pub greater: bool,
/// Register is zero
pub zero: bool,
/// Register is positive
pub positive: bool,
/// Register is negative
pub negative: bool,
/// Overflow (multiplication etc.)
pub overflow: bool,
/// Invalid flag
pub invalid: bool,
/// Arithmetic carry
pub carry: bool,
}
impl StatusFlags {
pub fn clear(&mut self) {
*self = Self::default();
}
pub fn store(&self) -> Value {
let mut val = 0u64;
if self.equal { val |= 0x01; }
if self.lower { val |= 0x02; }
if self.greater { val |= 0x04; }
if self.zero { val |= 0x08; }
if self.positive { val |= 0x10; }
if self.negative { val |= 0x20; }
if self.overflow { val |= 0x40; }
if self.invalid { val |= 0x80; }
if self.carry { val |= 0x100; }
val
}
pub fn load(&mut self, val : Value) {
if val & 0x01 != 0 { self.equal = true; }
if val & 0x02 != 0 { self.lower = true; }
if val & 0x04 != 0 { self.greater = true; }
if val & 0x08 != 0 { self.zero = true; }
if val & 0x10 != 0 { self.positive = true; }
if val & 0x20 != 0 { self.negative = true; }
if val & 0x40 != 0 { self.overflow = true; }
if val & 0x80 != 0 { self.invalid = true; }
if val & 0x100 != 0 { self.carry = true; }
}
pub fn update(&mut self, val: Value) {
self.zero = val == 0;
self.positive = is_positive(val);
self.negative = is_negative(val);
}
pub fn test(&self, cond: Cond) -> bool {
match cond {
Cond::Equal => self.equal,
Cond::NotEqual => !self.equal,
Cond::Zero => self.zero,
Cond::NotZero => !self.zero,
Cond::Lower => self.lower,
Cond::LowerOrEqual => self.lower || self.equal,
Cond::Greater => self.greater,
Cond::GreaterOrEqual => self.greater || self.equal,
Cond::Positive => self.positive,
Cond::NonPositive => !self.positive,
Cond::Negative => self.negative,
Cond::NonNegative => !self.negative,
Cond::Overflow => self.overflow,
Cond::NotOverflow => !self.overflow,
Cond::Invalid => self.invalid,
Cond::Valid => !self.invalid,
Cond::Carry => self.carry,
Cond::NotCarry => !self.carry
}
}
}
impl Display for StatusFlags {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.write_str("[")?;
if self.equal {
f.write_str(" E")?;
}
if self.zero {
f.write_str(" Z")?;
}
if self.lower {
f.write_str(" L")?;
}
if self.greater {
f.write_str(" G")?;
}
if self.positive {
f.write_str(" P")?;
}
if self.negative {
f.write_str(" N")?;
}
if self.overflow {
f.write_str(" V")?;
}
if self.invalid {
f.write_str(" X")?;
}
if self.carry {
f.write_str(" C")?;
}
f.write_str(" ]")?;
Ok(())
}
}
+2 -2
View File
@@ -1,8 +1,8 @@
#[macro_use] extern crate log;
pub mod run_thread;
pub mod mlock;
pub mod sparse;
// pub mod mlock;
// pub mod sparse;
pub mod fault;
pub mod span;
pub mod exec;
+5 -5
View File
@@ -1,11 +1,11 @@
use std::time::Duration;
use std::thread::JoinHandle;
use asm::data::literal::{Addr, Value};
use asm::instr::Op;
use crate::exec;
use asm::data::{Rd, SrcDisp, reg::Register, Wr, DstDisp};
use crate::fault::Fault;
use asm::data::literal::{Addr};
use crate::frame::StackFrame;
use crate::program::Program;
use crate::exec::EvalRes;