remove "immediate ptr" data type, move read, write funcs to RunState, add %objectPtr syntax
This commit is contained in:
@@ -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 {
|
||||||
|
|||||||
+11
-25
@@ -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 {
|
||||||
|
|||||||
+29
-28
@@ -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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+94
-96
@@ -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)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-14
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user