|
|
@ -3,7 +3,6 @@ use std::ops::Rem; |
|
|
|
use num_traits::PrimInt; |
|
|
|
use num_traits::PrimInt; |
|
|
|
|
|
|
|
|
|
|
|
use crsn::asm::data::{Rd, Wr}; |
|
|
|
use crsn::asm::data::{Rd, Wr}; |
|
|
|
use crsn::asm::instr::Cond; |
|
|
|
|
|
|
|
use crsn::module::{EvalRes, OpTrait}; |
|
|
|
use crsn::module::{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::{state::RunState, ThreadInfo}; |
|
|
@ -12,6 +11,7 @@ use crsn::sexp::Sexp; |
|
|
|
use crsn::utils::A; |
|
|
|
use crsn::utils::A; |
|
|
|
|
|
|
|
|
|
|
|
use crate::defs::ArithOp; |
|
|
|
use crate::defs::ArithOp; |
|
|
|
|
|
|
|
use crsn::asm::instr::cond::Flag; |
|
|
|
|
|
|
|
|
|
|
|
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> { |
|
|
@ -26,9 +26,9 @@ impl OpTrait for ArithOp { |
|
|
|
state.clear_status(); |
|
|
|
state.clear_status(); |
|
|
|
let x = state.read(a)?; |
|
|
|
let x = state.read(a)?; |
|
|
|
let y = state.read(b)?; |
|
|
|
let y = state.read(b)?; |
|
|
|
state.set_flag(Cond::Equal, x == y); |
|
|
|
state.set_flag(Flag::Equal, x == y); |
|
|
|
state.set_flag(Cond::Lower, x < y); |
|
|
|
state.set_flag(Flag::Lower, x < y); |
|
|
|
state.set_flag(Cond::Greater, x > y); |
|
|
|
state.set_flag(Flag::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 { |
|
|
|
state.update_status(x); |
|
|
|
state.update_status(x); |
|
|
@ -39,9 +39,9 @@ impl OpTrait for ArithOp { |
|
|
|
let val = state.read(val)?; |
|
|
|
let val = state.read(val)?; |
|
|
|
let a = state.read(a)?; |
|
|
|
let a = state.read(a)?; |
|
|
|
let b = state.read(b)?; |
|
|
|
let b = state.read(b)?; |
|
|
|
state.set_flag(Cond::Equal, val >= a && val <= b); |
|
|
|
state.set_flag(Flag::Equal, val >= a && val <= b); |
|
|
|
state.set_flag(Cond::Lower, val < a); |
|
|
|
state.set_flag(Flag::Lower, val < a); |
|
|
|
state.set_flag(Cond::Greater, val > b); |
|
|
|
state.set_flag(Flag::Greater, val > b); |
|
|
|
state.update_status(val); |
|
|
|
state.update_status(val); |
|
|
|
} |
|
|
|
} |
|
|
|
ArithOp::Add { dst, a, b } => { |
|
|
|
ArithOp::Add { dst, a, b } => { |
|
|
@ -54,7 +54,7 @@ impl OpTrait for ArithOp { |
|
|
|
(x.wrapping_add(y), true) |
|
|
|
(x.wrapping_add(y), true) |
|
|
|
}; |
|
|
|
}; |
|
|
|
state.update_status(res); |
|
|
|
state.update_status(res); |
|
|
|
state.set_flag(Cond::Overflow, ov); |
|
|
|
state.set_flag(Flag::Overflow, ov); |
|
|
|
state.write(dst, res)?; |
|
|
|
state.write(dst, res)?; |
|
|
|
} |
|
|
|
} |
|
|
|
ArithOp::Sub { dst, a, b } => { |
|
|
|
ArithOp::Sub { dst, a, b } => { |
|
|
@ -67,7 +67,7 @@ impl OpTrait for ArithOp { |
|
|
|
(x.wrapping_sub(y), true) |
|
|
|
(x.wrapping_sub(y), true) |
|
|
|
}; |
|
|
|
}; |
|
|
|
state.update_status(res); |
|
|
|
state.update_status(res); |
|
|
|
state.set_flag(Cond::Overflow, ov); |
|
|
|
state.set_flag(Flag::Overflow, ov); |
|
|
|
state.write(dst, res)?; |
|
|
|
state.write(dst, res)?; |
|
|
|
} |
|
|
|
} |
|
|
|
ArithOp::Mul { dst, a, b } => { |
|
|
|
ArithOp::Mul { dst, a, b } => { |
|
|
@ -77,7 +77,7 @@ impl OpTrait for ArithOp { |
|
|
|
let res = if let Some(v) = x.checked_mul(y) { |
|
|
|
let res = if let Some(v) = x.checked_mul(y) { |
|
|
|
v |
|
|
|
v |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
state.set_flag(Cond::Overflow, true); |
|
|
|
state.set_flag(Flag::Overflow, true); |
|
|
|
x.wrapping_mul(y) |
|
|
|
x.wrapping_mul(y) |
|
|
|
}; |
|
|
|
}; |
|
|
|
state.update_status(res); |
|
|
|
state.update_status(res); |
|
|
@ -88,7 +88,7 @@ impl OpTrait for ArithOp { |
|
|
|
let x = state.read(a)?; |
|
|
|
let x = state.read(a)?; |
|
|
|
let d = state.read(div)?; |
|
|
|
let d = state.read(div)?; |
|
|
|
if d == 0 { |
|
|
|
if d == 0 { |
|
|
|
state.set_flag(Cond::Invalid, true); |
|
|
|
state.set_flag(Flag::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) |
|
|
@ -96,7 +96,7 @@ impl OpTrait for ArithOp { |
|
|
|
(x.wrapping_div(d), x.wrapping_rem(d), true) |
|
|
|
(x.wrapping_div(d), x.wrapping_rem(d), true) |
|
|
|
}; |
|
|
|
}; |
|
|
|
state.update_status(res); |
|
|
|
state.update_status(res); |
|
|
|
state.set_flag(Cond::Overflow, ov); |
|
|
|
state.set_flag(Flag::Overflow, ov); |
|
|
|
state.write(dst, res)?; |
|
|
|
state.write(dst, res)?; |
|
|
|
state.write(rem, remainder)?; |
|
|
|
state.write(rem, remainder)?; |
|
|
|
} |
|
|
|
} |
|
|
@ -106,7 +106,7 @@ impl OpTrait for ArithOp { |
|
|
|
let x = state.read(a)?; |
|
|
|
let x = state.read(a)?; |
|
|
|
let d = state.read(div)?; |
|
|
|
let d = state.read(div)?; |
|
|
|
if d == 0 { |
|
|
|
if d == 0 { |
|
|
|
state.set_flag(Cond::Invalid, true); |
|
|
|
state.set_flag(Flag::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) |
|
|
@ -114,7 +114,7 @@ impl OpTrait for ArithOp { |
|
|
|
(x.wrapping_rem(d), true) |
|
|
|
(x.wrapping_rem(d), true) |
|
|
|
}; |
|
|
|
}; |
|
|
|
state.update_status(remainder); |
|
|
|
state.update_status(remainder); |
|
|
|
state.set_flag(Cond::Overflow, ov); |
|
|
|
state.set_flag(Flag::Overflow, ov); |
|
|
|
state.write(dst, remainder)?; |
|
|
|
state.write(dst, remainder)?; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -154,7 +154,7 @@ impl OpTrait for ArithOp { |
|
|
|
let x = state.read(a)?; |
|
|
|
let x = state.read(a)?; |
|
|
|
let y = state.read(n)?; |
|
|
|
let y = state.read(n)?; |
|
|
|
if y > u32::MAX as u64 { |
|
|
|
if y > u32::MAX as u64 { |
|
|
|
state.set_flag(Cond::Invalid, true); |
|
|
|
state.set_flag(Flag::Invalid, true); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
let res = x.rotate_left(y as u32); |
|
|
|
let res = x.rotate_left(y as u32); |
|
|
|
state.update_status(res); |
|
|
|
state.update_status(res); |
|
|
@ -166,7 +166,7 @@ impl OpTrait for ArithOp { |
|
|
|
let x = state.read(a)?; |
|
|
|
let x = state.read(a)?; |
|
|
|
let y = state.read(n)?; |
|
|
|
let y = state.read(n)?; |
|
|
|
if y > u32::MAX as u64 { |
|
|
|
if y > u32::MAX as u64 { |
|
|
|
state.set_flag(Cond::Invalid, true); |
|
|
|
state.set_flag(Flag::Invalid, true); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
let res = x.rotate_right(y as u32); |
|
|
|
let res = x.rotate_right(y as u32); |
|
|
|
state.update_status(res); |
|
|
|
state.update_status(res); |
|
|
@ -194,7 +194,7 @@ impl OpTrait for ArithOp { |
|
|
|
let x = state.read(a)?; |
|
|
|
let x = state.read(a)?; |
|
|
|
let y = state.read(n)?; |
|
|
|
let y = state.read(n)?; |
|
|
|
if y > u32::MAX as u64 { |
|
|
|
if y > u32::MAX as u64 { |
|
|
|
state.set_flag(Cond::Invalid, true); |
|
|
|
state.set_flag(Flag::Invalid, true); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
let res = x.signed_shr(y as u32); |
|
|
|
let res = x.signed_shr(y as u32); |
|
|
|
state.update_status(res); |
|
|
|
state.update_status(res); |
|
|
|