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
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||
pub enum Label {
|
||||
|
||||
+11
-25
@@ -19,12 +19,10 @@ pub mod mask;
|
||||
pub enum DataDisp {
|
||||
/// Constant value
|
||||
Immediate(Value),
|
||||
/// Constant memory address
|
||||
ImmediatePtr(Addr),
|
||||
/// Register
|
||||
Register(Register),
|
||||
/// Pointer into memory, stored in a numbered register
|
||||
RegisterPtr(Register),
|
||||
/// Object pointer
|
||||
ObjectPtr(Register),
|
||||
/// Discard the written value
|
||||
Discard,
|
||||
}
|
||||
@@ -35,14 +33,11 @@ impl Display for DataDisp {
|
||||
DataDisp::Immediate(v) => {
|
||||
write!(f, "{}", as_signed(*v))
|
||||
}
|
||||
DataDisp::ImmediatePtr(a) => {
|
||||
write!(f, "@0x{:#18x}", a.0)
|
||||
}
|
||||
DataDisp::Register(r) => {
|
||||
write!(f, "{}", r)
|
||||
}
|
||||
DataDisp::RegisterPtr(r) => {
|
||||
write!(f, "@{}", r)
|
||||
DataDisp::ObjectPtr(r) => {
|
||||
write!(f, "%{}", r)
|
||||
}
|
||||
DataDisp::Discard => {
|
||||
write!(f, "_")
|
||||
@@ -55,9 +50,8 @@ impl From<SrcDisp> for DataDisp {
|
||||
fn from(s: SrcDisp) -> Self {
|
||||
match s {
|
||||
SrcDisp::Immediate(x) => DataDisp::Immediate(x),
|
||||
SrcDisp::ImmediatePtr(x) => DataDisp::ImmediatePtr(x),
|
||||
SrcDisp::Register(x) => DataDisp::Register(x),
|
||||
SrcDisp::RegisterPtr(x) => DataDisp::RegisterPtr(x),
|
||||
SrcDisp::ObjectPtr(x) => DataDisp::ObjectPtr(x),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -65,9 +59,8 @@ impl From<SrcDisp> for DataDisp {
|
||||
impl From<DstDisp> for DataDisp {
|
||||
fn from(s: DstDisp) -> Self {
|
||||
match s {
|
||||
DstDisp::ImmediatePtr(x) => DataDisp::ImmediatePtr(x),
|
||||
DstDisp::Register(x) => DataDisp::Register(x),
|
||||
DstDisp::RegisterPtr(x) => DataDisp::RegisterPtr(x),
|
||||
DstDisp::ObjectPtr(x) => DataDisp::ObjectPtr(x),
|
||||
DstDisp::Discard => DataDisp::Discard,
|
||||
}
|
||||
}
|
||||
@@ -78,12 +71,10 @@ impl From<DstDisp> for DataDisp {
|
||||
pub enum SrcDisp {
|
||||
/// Constant value
|
||||
Immediate(Value),
|
||||
/// Constant memory address
|
||||
ImmediatePtr(Addr),
|
||||
/// Register
|
||||
Register(Register),
|
||||
/// Pointer into memory, stored in a numbered register
|
||||
RegisterPtr(Register),
|
||||
ObjectPtr(Register),
|
||||
}
|
||||
|
||||
impl TryFrom<DataDisp> for SrcDisp {
|
||||
@@ -92,9 +83,8 @@ impl TryFrom<DataDisp> for SrcDisp {
|
||||
fn try_from(value: DataDisp) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
DataDisp::Immediate(x) => Ok(SrcDisp::Immediate(x)),
|
||||
DataDisp::ImmediatePtr(x) => Ok(SrcDisp::ImmediatePtr(x)),
|
||||
DataDisp::Register(x) => Ok(SrcDisp::Register(x)),
|
||||
DataDisp::RegisterPtr(x) => Ok(SrcDisp::RegisterPtr(x)),
|
||||
DataDisp::ObjectPtr(x) => Ok(SrcDisp::ObjectPtr(x)),
|
||||
DataDisp::Discard => Err(AsmError::DiscardAsValue),
|
||||
}
|
||||
}
|
||||
@@ -103,12 +93,10 @@ impl TryFrom<DataDisp> for SrcDisp {
|
||||
/// Data destination disposition
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
pub enum DstDisp {
|
||||
/// Constant memory address
|
||||
ImmediatePtr(Addr),
|
||||
/// Register
|
||||
Register(Register),
|
||||
/// Pointer into memory, stored in a numbered register
|
||||
RegisterPtr(Register),
|
||||
ObjectPtr(Register),
|
||||
/// Discard the written value
|
||||
Discard,
|
||||
}
|
||||
@@ -116,9 +104,8 @@ pub enum DstDisp {
|
||||
impl From<DstDisp> for SrcDisp {
|
||||
fn from(s: DstDisp) -> Self {
|
||||
match s {
|
||||
DstDisp::ImmediatePtr(x) => SrcDisp::ImmediatePtr(x),
|
||||
DstDisp::Register(x) => SrcDisp::Register(x),
|
||||
DstDisp::RegisterPtr(x) => SrcDisp::RegisterPtr(x),
|
||||
DstDisp::ObjectPtr(x) => SrcDisp::ObjectPtr(x),
|
||||
DstDisp::Discard => SrcDisp::Immediate(0),
|
||||
}
|
||||
}
|
||||
@@ -130,9 +117,8 @@ impl TryFrom<DataDisp> for DstDisp {
|
||||
fn try_from(value: DataDisp) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
DataDisp::Immediate(_x) => Err(AsmError::ValueAsOutput),
|
||||
DataDisp::ImmediatePtr(x) => Ok(DstDisp::ImmediatePtr(x)),
|
||||
DataDisp::Register(x) => Ok(DstDisp::Register(x)),
|
||||
DataDisp::RegisterPtr(x) => Ok(DstDisp::RegisterPtr(x)),
|
||||
DataDisp::ObjectPtr(x) => Ok(DstDisp::ObjectPtr(x)),
|
||||
DataDisp::Discard => Ok(DstDisp::Discard),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ use crate::builtin::defs::BuiltinOp;
|
||||
use crate::runtime::fault::Fault;
|
||||
|
||||
|
||||
use crate::runtime::run_thread::{RunState, ThreadInfo};
|
||||
use crate::runtime::run_thread::{state::RunState, ThreadInfo};
|
||||
|
||||
/// A higher level simple opration
|
||||
#[derive(Debug)]
|
||||
|
||||
@@ -32,13 +32,8 @@ pub fn parse_data_disp(tok: Option<Sexp>) -> Result<DataDisp, Error> {
|
||||
return Ok(DataDisp::Discard);
|
||||
}
|
||||
|
||||
if let Some(reference) = s.strip_prefix('@') {
|
||||
if reference.starts_with(|c: char| c.is_ascii_digit()) {
|
||||
let val: u64 = parse_u64(reference)?;
|
||||
Ok(DataDisp::ImmediatePtr(Addr(val)))
|
||||
} else {
|
||||
Ok(DataDisp::RegisterPtr(reg::parse_reg(reference)?))
|
||||
}
|
||||
if let Some(reference) = s.strip_prefix('%') {
|
||||
Ok(DataDisp::ObjectPtr(reg::parse_reg(reference)?))
|
||||
} else if s.starts_with(|c: char| c.is_ascii_digit()) {
|
||||
Ok(DataDisp::Immediate(unsafe { std::mem::transmute(parse_i64(s)?) }))
|
||||
} else {
|
||||
|
||||
+29
-28
@@ -8,11 +8,10 @@ use crate::runtime::frame::{StackFrame};
|
||||
|
||||
use crate::builtin::defs::BuiltinOp;
|
||||
use crate::asm::data::literal::Addr;
|
||||
use crate::runtime::run_thread::{ThreadInfo, RunState};
|
||||
use crate::runtime::run_thread::{ThreadInfo, state::RunState};
|
||||
|
||||
impl OpTrait for BuiltinOp {
|
||||
fn execute(&self, info: &ThreadInfo, state: &mut RunState) -> Result<EvalRes, Fault> {
|
||||
let frame = &mut state.frame;
|
||||
let program = &info.program;
|
||||
let mut res = EvalRes::default();
|
||||
match self {
|
||||
@@ -38,7 +37,7 @@ impl OpTrait for BuiltinOp {
|
||||
BuiltinOp::FarJump(name) => {
|
||||
match program.find_far_label(name) {
|
||||
Ok(pos) => {
|
||||
frame.pc = pos;
|
||||
state.set_pc(pos);
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(e);
|
||||
@@ -46,9 +45,9 @@ impl OpTrait for BuiltinOp {
|
||||
}
|
||||
}
|
||||
BuiltinOp::Jump(name) => {
|
||||
match program.find_local_label(frame.pc, name) {
|
||||
match program.find_local_label(state.get_pc(), name) {
|
||||
Ok(pos) => {
|
||||
frame.pc = pos;
|
||||
state.set_pc(pos);
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(e);
|
||||
@@ -56,10 +55,10 @@ impl OpTrait for BuiltinOp {
|
||||
}
|
||||
}
|
||||
BuiltinOp::JumpIf(cond, name) => {
|
||||
if frame.status.test(*cond) {
|
||||
match program.find_local_label(frame.pc, name) {
|
||||
if state.test_cond(*cond) {
|
||||
match program.find_local_label(state.get_pc(), name) {
|
||||
Ok(pos) => {
|
||||
frame.pc = pos;
|
||||
state.set_pc(pos);
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(e);
|
||||
@@ -68,10 +67,10 @@ impl OpTrait for BuiltinOp {
|
||||
}
|
||||
}
|
||||
BuiltinOp::FarJumpIf(cond, name) => {
|
||||
if frame.status.test(*cond) {
|
||||
if state.test_cond(*cond) {
|
||||
match program.find_far_label(name) {
|
||||
Ok(pos) => {
|
||||
frame.pc = pos;
|
||||
state.set_pc(pos);
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(e);
|
||||
@@ -84,11 +83,11 @@ impl OpTrait for BuiltinOp {
|
||||
Ok(pos) => {
|
||||
let mut values = Vec::with_capacity(args.len());
|
||||
for arg in args {
|
||||
values.push(frame.read(*arg)?);
|
||||
values.push(state.read(*arg)?);
|
||||
}
|
||||
|
||||
let mut frame2 = StackFrame::new(pos, &values);
|
||||
std::mem::swap(frame, &mut frame2);
|
||||
std::mem::swap(&mut state.frame, &mut frame2);
|
||||
state.call_stack.push(frame2);
|
||||
res.advance = 0;
|
||||
}
|
||||
@@ -102,10 +101,10 @@ impl OpTrait for BuiltinOp {
|
||||
Some(previous) => {
|
||||
let mut values = Vec::with_capacity(retvals.len());
|
||||
for arg in retvals {
|
||||
values.push(frame.read(*arg)?);
|
||||
values.push(state.read(*arg)?);
|
||||
}
|
||||
*frame = previous;
|
||||
frame.set_retvals(&values);
|
||||
state.frame = previous;
|
||||
state.frame.set_retvals(&values);
|
||||
}
|
||||
None => {
|
||||
return Err(Fault::CallStackUnderflow);
|
||||
@@ -113,31 +112,33 @@ impl OpTrait for BuiltinOp {
|
||||
}
|
||||
}
|
||||
BuiltinOp::Skip(val) => {
|
||||
let steps = frame.read(*val)?;
|
||||
let steps = state.read(*val)?;
|
||||
res.advance = i64::from_ne_bytes(steps.to_ne_bytes());
|
||||
program.validate_jump(frame.pc, Addr((frame.pc.0 as i64 + res.advance) as u64))?;
|
||||
let pc = state.get_pc();
|
||||
program.validate_jump(pc, Addr((pc.0 as i64 + res.advance) as u64))?;
|
||||
}
|
||||
BuiltinOp::SkipIf(cond, val) => {
|
||||
if frame.status.test(*cond) {
|
||||
if state.test_cond(*cond) {
|
||||
debug!("Skipping");
|
||||
let steps = frame.read(*val)?;
|
||||
let steps = state.read(*val)?;
|
||||
res.advance = i64::from_ne_bytes(steps.to_ne_bytes());
|
||||
program.validate_jump(frame.pc, Addr((frame.pc.0 as i64 + res.advance) as u64))?;
|
||||
let pc = state.get_pc();
|
||||
program.validate_jump(pc, Addr((pc.0 as i64 + res.advance) as u64))?;
|
||||
}
|
||||
}
|
||||
BuiltinOp::Move { dst, src } => {
|
||||
frame.status.clear();
|
||||
let val = frame.read(*src)?;
|
||||
frame.status.update(val);
|
||||
frame.write(*dst, val)?;
|
||||
state.clear_status();
|
||||
let val = state.read(*src)?;
|
||||
state.update_status(val);
|
||||
state.write(*dst, val)?;
|
||||
}
|
||||
BuiltinOp::StoreStatus { dst } => {
|
||||
let packed = frame.status.store();
|
||||
frame.write(*dst, packed)?;
|
||||
let packed = state.frame.status.store();
|
||||
state.write(*dst, packed)?;
|
||||
}
|
||||
BuiltinOp::LoadStatus { src } => {
|
||||
let x = frame.read(*src)?;
|
||||
frame.status.load(x);
|
||||
let x = state.read(*src)?;
|
||||
state.frame.status.load(x);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ use crate::asm::data::literal::{Addr, Value};
|
||||
|
||||
use super::fault::Fault;
|
||||
|
||||
mod status;
|
||||
pub(crate) mod status;
|
||||
|
||||
pub const REG_COUNT: usize = 8;
|
||||
|
||||
@@ -41,79 +41,4 @@ impl StackFrame {
|
||||
self.res[n] = vals[n];
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read(&mut self, rd: Rd) -> Result<Value, Fault> {
|
||||
match rd.d() {
|
||||
SrcDisp::Immediate(v) => Ok(v),
|
||||
SrcDisp::ImmediatePtr(_) => {
|
||||
unimplemented!("Immediate ptr")
|
||||
}
|
||||
SrcDisp::Register(Register::Res(rn)) => {
|
||||
if rn >= REG_COUNT as u8 {
|
||||
Err(Fault::RegisterNotExist { reg: Register::Res(rn) }) // TODO use match after @ when stabilized https://github.com/rust-lang/rust/issues/65490
|
||||
} else {
|
||||
trace!("Rd {:?} = {}", rd, self.res[rn as usize]);
|
||||
Ok(self.res[rn as usize])
|
||||
}
|
||||
}
|
||||
SrcDisp::Register(Register::Arg(rn)) => {
|
||||
if rn >= REG_COUNT as u8 {
|
||||
Err(Fault::RegisterNotExist { reg: Register::Arg(rn) })
|
||||
} else {
|
||||
trace!("Rd {:?} = {}", rd, self.arg[rn as usize]);
|
||||
Ok(self.arg[rn as usize])
|
||||
}
|
||||
}
|
||||
SrcDisp::Register(Register::Gen(rn)) => {
|
||||
if rn >= REG_COUNT as u8 {
|
||||
Err(Fault::RegisterNotExist { reg: Register::Gen(rn) })
|
||||
} else {
|
||||
trace!("Rd {:?} = {}", rd, self.gen[rn as usize]);
|
||||
Ok(self.gen[rn as usize])
|
||||
}
|
||||
}
|
||||
SrcDisp::RegisterPtr(_) => {
|
||||
unimplemented!("Register ptr")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write(&mut self, wr: Wr, val: Value) -> Result<(), Fault> {
|
||||
trace!("WR {:?} := {}", wr, val);
|
||||
|
||||
match wr.d() {
|
||||
DstDisp::ImmediatePtr(_) => {
|
||||
unimplemented!("Immediate ptr")
|
||||
}
|
||||
DstDisp::Discard => {
|
||||
/* Discard */
|
||||
Ok(())
|
||||
}
|
||||
DstDisp::Register(Register::Res(rn)) => {
|
||||
if rn >= REG_COUNT as u8 {
|
||||
Err(Fault::RegisterNotExist { reg: Register::Res(rn) }) // TODO use match after @ when stabilized https://github.com/rust-lang/rust/issues/65490
|
||||
} else {
|
||||
Err(Fault::RegisterNotWritable { reg: Register::Res(rn) })
|
||||
}
|
||||
}
|
||||
DstDisp::Register(Register::Arg(rn)) => {
|
||||
if rn >= REG_COUNT as u8 {
|
||||
Err(Fault::RegisterNotExist { reg: Register::Arg(rn) })
|
||||
} else {
|
||||
Err(Fault::RegisterNotWritable { reg: Register::Res(rn) })
|
||||
}
|
||||
}
|
||||
DstDisp::Register(Register::Gen(rn)) => {
|
||||
if rn >= REG_COUNT as u8 {
|
||||
Err(Fault::RegisterNotExist { reg: Register::Gen(rn) })
|
||||
} else {
|
||||
self.gen[rn as usize] = val;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
DstDisp::RegisterPtr(_) => {
|
||||
unimplemented!("Register ptr")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,6 +85,43 @@ impl StatusFlags {
|
||||
Cond::NotCarry => !self.carry
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set(&mut self, cond: Cond) {
|
||||
match cond {
|
||||
Cond::Equal => {
|
||||
self.equal = true;
|
||||
},
|
||||
Cond::Zero => {
|
||||
self.zero = true;
|
||||
},
|
||||
Cond::Lower => {
|
||||
self.lower = true;
|
||||
},
|
||||
Cond::Greater => {
|
||||
self.lower = false;
|
||||
self.equal = false;
|
||||
self.greater = true;
|
||||
},
|
||||
Cond::Positive => {
|
||||
self.positive = true;
|
||||
},
|
||||
Cond::Negative => {
|
||||
self.negative = true;
|
||||
},
|
||||
Cond::Overflow => {
|
||||
self.overflow = true;
|
||||
},
|
||||
Cond::Invalid => {
|
||||
self.invalid = true;
|
||||
},
|
||||
Cond::Carry => {
|
||||
self.carry = true;
|
||||
},
|
||||
other => {
|
||||
panic!("cannot set cond by {:?}", other);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for StatusFlags {
|
||||
|
||||
@@ -4,11 +4,13 @@ use std::sync::Arc;
|
||||
use std::thread::JoinHandle;
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::asm::data::literal::Addr;
|
||||
use crate::asm::data::literal::{Addr, Value};
|
||||
use crate::asm::instr::op::EvalRes;
|
||||
use crate::runtime::frame::{CallStack, StackFrame};
|
||||
use crate::runtime::frame::{CallStack, StackFrame, REG_COUNT, status::StatusFlags};
|
||||
use crate::runtime::program::Program;
|
||||
use crate::runtime::fault::Fault;
|
||||
use crate::asm::data::{Rd, SrcDisp, Register, Wr, DstDisp};
|
||||
use crate::runtime::run_thread::state::RunState;
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Debug, Ord, PartialOrd)]
|
||||
pub struct ThreadToken(pub u32);
|
||||
@@ -27,25 +29,7 @@ pub struct ThreadInfo {
|
||||
pub cycle_time: Duration,
|
||||
}
|
||||
|
||||
pub struct RunState {
|
||||
/// Active stack frame
|
||||
pub frame: StackFrame,
|
||||
/// Call stack
|
||||
pub call_stack: CallStack,
|
||||
/// Extension data
|
||||
ext_data: HashMap<TypeId, Box<dyn Any + Send>>,
|
||||
}
|
||||
|
||||
impl RunState {
|
||||
pub fn ext_mut<T: Send + Default + 'static>(&mut self) -> &mut T {
|
||||
if !self.ext_data.contains_key(&TypeId::of::<T>()) {
|
||||
self.ext_data.insert(TypeId::of::<T>(), Box::new(T::default()));
|
||||
}
|
||||
|
||||
self.ext_data.get_mut(&TypeId::of::<T>()).unwrap()
|
||||
.downcast_mut().unwrap()
|
||||
}
|
||||
}
|
||||
pub mod state;
|
||||
|
||||
impl RunThread {
|
||||
pub fn new(id: ThreadToken, program: Arc<Program>, pc: Addr, args: &[u64]) -> Self {
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
use std::any::{Any, TypeId};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::asm::data::{DstDisp, Rd, Register, SrcDisp, Wr};
|
||||
use crate::asm::data::literal::{Addr, Value};
|
||||
use crate::asm::instr::op::EvalRes;
|
||||
use crate::runtime::fault::Fault;
|
||||
use crate::runtime::frame::{CallStack, REG_COUNT, StackFrame};
|
||||
use crate::runtime::program::Program;
|
||||
use crate::asm::instr::Cond;
|
||||
use crate::runtime::frame::status::StatusFlags;
|
||||
|
||||
pub struct RunState {
|
||||
/// Active stack frame
|
||||
pub frame: StackFrame,
|
||||
/// Call stack
|
||||
pub call_stack: CallStack,
|
||||
/// Extension data
|
||||
pub ext_data: HashMap<TypeId, Box<dyn Any + Send>>,
|
||||
}
|
||||
|
||||
impl RunState {
|
||||
pub fn ext_mut<T: Send + Default + 'static>(&mut self) -> &mut T {
|
||||
if !self.ext_data.contains_key(&TypeId::of::<T>()) {
|
||||
self.ext_data.insert(TypeId::of::<T>(), Box::new(T::default()));
|
||||
}
|
||||
|
||||
self.ext_data.get_mut(&TypeId::of::<T>()).unwrap()
|
||||
.downcast_mut().unwrap()
|
||||
}
|
||||
|
||||
pub fn set_flag(&mut self, cond : Cond, set : bool) {
|
||||
if set {
|
||||
self.frame.status.set(cond);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn test_cond(&self, cond : Cond) -> bool {
|
||||
self.frame.status.test(cond)
|
||||
}
|
||||
|
||||
pub fn set_pc(&mut self, pc: Addr) {
|
||||
self.frame.pc = pc;
|
||||
}
|
||||
|
||||
pub fn get_pc(&self) -> Addr {
|
||||
self.frame.pc
|
||||
}
|
||||
|
||||
pub fn clear_status(&mut self) {
|
||||
self.frame.status.clear();
|
||||
}
|
||||
|
||||
pub fn update_status(&mut self, val: Value) {
|
||||
self.frame.status.update(val);
|
||||
}
|
||||
|
||||
pub fn read(&mut self, rd: Rd) -> Result<Value, Fault> {
|
||||
match rd.d() {
|
||||
SrcDisp::Immediate(v) => Ok(v),
|
||||
SrcDisp::Register(Register::Res(rn)) => {
|
||||
if rn >= REG_COUNT as u8 {
|
||||
Err(Fault::RegisterNotExist { reg: Register::Res(rn) }) // TODO use match after @ when stabilized https://github.com/rust-lang/rust/issues/65490
|
||||
} else {
|
||||
trace!("Rd {:?} = {}", rd, self.frame.res[rn as usize]);
|
||||
Ok(self.frame.res[rn as usize])
|
||||
}
|
||||
}
|
||||
SrcDisp::Register(Register::Arg(rn)) => {
|
||||
if rn >= REG_COUNT as u8 {
|
||||
Err(Fault::RegisterNotExist { reg: Register::Arg(rn) })
|
||||
} else {
|
||||
trace!("Rd {:?} = {}", rd, self.frame.arg[rn as usize]);
|
||||
Ok(self.frame.arg[rn as usize])
|
||||
}
|
||||
}
|
||||
SrcDisp::Register(Register::Gen(rn)) => {
|
||||
if rn >= REG_COUNT as u8 {
|
||||
Err(Fault::RegisterNotExist { reg: Register::Gen(rn) })
|
||||
} else {
|
||||
trace!("Rd {:?} = {}", rd, self.frame.gen[rn as usize]);
|
||||
Ok(self.frame.gen[rn as usize])
|
||||
}
|
||||
}
|
||||
SrcDisp::ObjectPtr(_) => {
|
||||
unimplemented!("Read object ptr")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write(&mut self, wr: Wr, val: Value) -> Result<(), Fault> {
|
||||
trace!("WR {:?} := {}", wr, val);
|
||||
|
||||
match wr.d() {
|
||||
DstDisp::Discard => {
|
||||
/* Discard */
|
||||
Ok(())
|
||||
}
|
||||
DstDisp::Register(Register::Res(rn)) => {
|
||||
if rn >= REG_COUNT as u8 {
|
||||
Err(Fault::RegisterNotExist { reg: Register::Res(rn) }) // TODO use match after @ when stabilized https://github.com/rust-lang/rust/issues/65490
|
||||
} else {
|
||||
Err(Fault::RegisterNotWritable { reg: Register::Res(rn) })
|
||||
}
|
||||
}
|
||||
DstDisp::Register(Register::Arg(rn)) => {
|
||||
if rn >= REG_COUNT as u8 {
|
||||
Err(Fault::RegisterNotExist { reg: Register::Arg(rn) })
|
||||
} else {
|
||||
Err(Fault::RegisterNotWritable { reg: Register::Res(rn) })
|
||||
}
|
||||
}
|
||||
DstDisp::Register(Register::Gen(rn)) => {
|
||||
if rn >= REG_COUNT as u8 {
|
||||
Err(Fault::RegisterNotExist { reg: Register::Gen(rn) })
|
||||
} else {
|
||||
self.frame.gen[rn as usize] = val;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
DstDisp::ObjectPtr(_) => {
|
||||
unimplemented!("Write object ptr")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+94
-96
@@ -2,191 +2,189 @@ use std::ops::Rem;
|
||||
|
||||
use num_traits::PrimInt;
|
||||
|
||||
use crsn::asm::instr::op::{OpTrait, EvalRes};
|
||||
use crsn::asm::instr::Cond;
|
||||
use crsn::asm::instr::op::{EvalRes, OpTrait};
|
||||
use crsn::runtime::fault::Fault;
|
||||
|
||||
|
||||
use crsn::runtime::run_thread::{state::RunState, ThreadInfo};
|
||||
|
||||
use crate::defs::ArithOp;
|
||||
use crsn::runtime::run_thread::{ThreadInfo, RunState};
|
||||
|
||||
impl OpTrait for ArithOp {
|
||||
fn execute(&self, _ti : &ThreadInfo, state: &mut RunState) -> Result<EvalRes, Fault> {
|
||||
let frame = &mut state.frame;
|
||||
fn execute(&self, _ti: &ThreadInfo, state: &mut RunState) -> Result<EvalRes, Fault> {
|
||||
let eres = EvalRes::default();
|
||||
match self {
|
||||
ArithOp::Test { a } => {
|
||||
frame.status.clear();
|
||||
let res = frame.read(*a)?;
|
||||
frame.status.update(res);
|
||||
state.clear_status();
|
||||
let res = state.read(*a)?;
|
||||
state.update_status(res);
|
||||
}
|
||||
ArithOp::Compare { a, b } => {
|
||||
frame.status.clear();
|
||||
let x = frame.read(*a)?;
|
||||
let y = frame.read(*b)?;
|
||||
frame.status.equal = x == y;
|
||||
frame.status.lower = x < y;
|
||||
frame.status.greater = x > y;
|
||||
state.clear_status();
|
||||
let x = state.read(*a)?;
|
||||
let y = state.read(*b)?;
|
||||
state.set_flag(Cond::Equal, x == y);
|
||||
state.set_flag(Cond::Lower, x < y);
|
||||
state.set_flag(Cond::Greater, x > y);
|
||||
// Test flags are set when both arguments have the property
|
||||
if x == y {
|
||||
frame.status.update(x);
|
||||
state.update_status(x);
|
||||
}
|
||||
}
|
||||
ArithOp::Add { dst, a, b } => {
|
||||
frame.status.clear();
|
||||
let x = frame.read(*a)?;
|
||||
let y = frame.read(*b)?;
|
||||
state.clear_status();
|
||||
let x = state.read(*a)?;
|
||||
let y = state.read(*b)?;
|
||||
let (res, ov) = if let Some(v) = x.checked_add(y) {
|
||||
(v, false)
|
||||
} else {
|
||||
(x.wrapping_add(y), true)
|
||||
};
|
||||
frame.status.update(res);
|
||||
frame.status.overflow = ov;
|
||||
frame.write(*dst, res)?;
|
||||
state.update_status(res);
|
||||
state.set_flag(Cond::Overflow, ov);
|
||||
state.write(*dst, res)?;
|
||||
}
|
||||
ArithOp::Sub { dst, a, b } => {
|
||||
frame.status.clear();
|
||||
let x = frame.read(*a)?;
|
||||
let y = frame.read(*b)?;
|
||||
state.clear_status();
|
||||
let x = state.read(*a)?;
|
||||
let y = state.read(*b)?;
|
||||
let (res, ov) = if let Some(v) = x.checked_sub(y) {
|
||||
(v, false)
|
||||
} else {
|
||||
(x.wrapping_sub(y), true)
|
||||
};
|
||||
frame.status.update(res);
|
||||
frame.status.overflow = ov;
|
||||
frame.write(*dst, res)?;
|
||||
state.update_status(res);
|
||||
state.set_flag(Cond::Overflow, ov);
|
||||
state.write(*dst, res)?;
|
||||
}
|
||||
ArithOp::Mul { dst, a, b } => {
|
||||
frame.status.clear();
|
||||
let x = frame.read(*a)?;
|
||||
let y = frame.read(*b)?;
|
||||
state.clear_status();
|
||||
let x = state.read(*a)?;
|
||||
let y = state.read(*b)?;
|
||||
let (res, ov) = if let Some(v) = x.checked_mul(y) {
|
||||
(v, false)
|
||||
} else {
|
||||
(x.wrapping_mul(y), true)
|
||||
};
|
||||
frame.status.update(res);
|
||||
frame.status.overflow = ov;
|
||||
frame.write(*dst, res)?;
|
||||
state.update_status(res);
|
||||
state.set_flag(Cond::Overflow, ov);
|
||||
state.write(*dst, res)?;
|
||||
}
|
||||
ArithOp::Div { dst, rem, a, div } => {
|
||||
frame.status.clear();
|
||||
let x = frame.read(*a)?;
|
||||
let d = frame.read(*div)?;
|
||||
state.clear_status();
|
||||
let x = state.read(*a)?;
|
||||
let d = state.read(*div)?;
|
||||
if d == 0 {
|
||||
frame.status.invalid = true;
|
||||
state.set_flag(Cond::Invalid, true);
|
||||
} else {
|
||||
let (res, remainder, ov) = if let Some(v) = x.checked_div(d) {
|
||||
(v, x.rem(d), false)
|
||||
} else {
|
||||
(x.wrapping_div(d), x.wrapping_rem(d), true)
|
||||
};
|
||||
frame.status.update(res);
|
||||
frame.status.overflow = ov;
|
||||
frame.write(*dst, res)?;
|
||||
frame.write(*rem, remainder)?;
|
||||
state.update_status(res);
|
||||
state.set_flag(Cond::Overflow, ov);
|
||||
state.write(*dst, res)?;
|
||||
state.write(*rem, remainder)?;
|
||||
}
|
||||
}
|
||||
ArithOp::Mod { dst, a, div } => {
|
||||
frame.status.clear();
|
||||
let x = frame.read(*a)?;
|
||||
let d = frame.read(*div)?;
|
||||
state.clear_status();
|
||||
let x = state.read(*a)?;
|
||||
let d = state.read(*div)?;
|
||||
if d == 0 {
|
||||
frame.status.invalid = true;
|
||||
state.set_flag(Cond::Invalid, true);
|
||||
} else {
|
||||
let (remainder, ov) = if let Some(v) = x.checked_rem(d) {
|
||||
(v, false)
|
||||
} else {
|
||||
(x.wrapping_rem(d), true)
|
||||
};
|
||||
frame.status.update(remainder);
|
||||
frame.status.overflow = ov;
|
||||
frame.write(*dst, remainder)?;
|
||||
state.update_status(remainder);
|
||||
state.set_flag(Cond::Overflow, ov);
|
||||
state.write(*dst, remainder)?;
|
||||
}
|
||||
}
|
||||
ArithOp::And { dst, a, b } => {
|
||||
frame.status.clear();
|
||||
let x = frame.read(*a)?;
|
||||
let y = frame.read(*b)?;
|
||||
state.clear_status();
|
||||
let x = state.read(*a)?;
|
||||
let y = state.read(*b)?;
|
||||
let res = x & y;
|
||||
frame.status.update(res);
|
||||
frame.write(*dst, res)?;
|
||||
state.update_status(res);
|
||||
state.write(*dst, res)?;
|
||||
}
|
||||
ArithOp::Or { dst, a, b } => {
|
||||
frame.status.clear();
|
||||
let x = frame.read(*a)?;
|
||||
let y = frame.read(*b)?;
|
||||
state.clear_status();
|
||||
let x = state.read(*a)?;
|
||||
let y = state.read(*b)?;
|
||||
let res = x | y;
|
||||
frame.status.update(res);
|
||||
frame.write(*dst, res)?;
|
||||
state.update_status(res);
|
||||
state.write(*dst, res)?;
|
||||
}
|
||||
ArithOp::Xor { dst, a, b } => {
|
||||
frame.status.clear();
|
||||
let x = frame.read(*a)?;
|
||||
let y = frame.read(*b)?;
|
||||
state.clear_status();
|
||||
let x = state.read(*a)?;
|
||||
let y = state.read(*b)?;
|
||||
let res = x ^ y;
|
||||
frame.status.update(res);
|
||||
frame.write(*dst, res)?;
|
||||
state.update_status(res);
|
||||
state.write(*dst, res)?;
|
||||
}
|
||||
ArithOp::Cpl { dst, a } => {
|
||||
frame.status.clear();
|
||||
let x = frame.read(*a)?;
|
||||
state.clear_status();
|
||||
let x = state.read(*a)?;
|
||||
let res = !x;
|
||||
frame.status.update(res);
|
||||
frame.write(*dst, res)?;
|
||||
state.update_status(res);
|
||||
state.write(*dst, res)?;
|
||||
}
|
||||
ArithOp::Rol { dst, a, n } => {
|
||||
frame.status.clear();
|
||||
let x = frame.read(*a)?;
|
||||
let y = frame.read(*n)?;
|
||||
state.clear_status();
|
||||
let x = state.read(*a)?;
|
||||
let y = state.read(*n)?;
|
||||
if y > u32::MAX as u64 {
|
||||
frame.status.invalid = true;
|
||||
state.set_flag(Cond::Invalid, true);
|
||||
} else {
|
||||
let res = x.rotate_left(y as u32);
|
||||
frame.status.update(res);
|
||||
frame.write(*dst, res)?;
|
||||
state.update_status(res);
|
||||
state.write(*dst, res)?;
|
||||
}
|
||||
}
|
||||
ArithOp::Ror { dst, a, n } => {
|
||||
frame.status.clear();
|
||||
let x = frame.read(*a)?;
|
||||
let y = frame.read(*n)?;
|
||||
state.clear_status();
|
||||
let x = state.read(*a)?;
|
||||
let y = state.read(*n)?;
|
||||
if y > u32::MAX as u64 {
|
||||
frame.status.invalid = true;
|
||||
state.set_flag(Cond::Invalid, true);
|
||||
} else {
|
||||
let res = x.rotate_right(y as u32);
|
||||
frame.status.update(res);
|
||||
frame.write(*dst, res)?;
|
||||
state.update_status(res);
|
||||
state.write(*dst, res)?;
|
||||
}
|
||||
}
|
||||
ArithOp::Lsl { dst, a, n } => {
|
||||
frame.status.clear();
|
||||
let x = frame.read(*a)?;
|
||||
let y = frame.read(*n)?;
|
||||
state.clear_status();
|
||||
let x = state.read(*a)?;
|
||||
let y = state.read(*n)?;
|
||||
let res = x << y;
|
||||
frame.status.update(res);
|
||||
frame.write(*dst, res)?;
|
||||
state.update_status(res);
|
||||
state.write(*dst, res)?;
|
||||
}
|
||||
ArithOp::Lsr { dst, a, n } => {
|
||||
frame.status.clear();
|
||||
let x = frame.read(*a)?;
|
||||
let y = frame.read(*n)?;
|
||||
state.clear_status();
|
||||
let x = state.read(*a)?;
|
||||
let y = state.read(*n)?;
|
||||
let res = x >> y;
|
||||
frame.status.update(res);
|
||||
frame.write(*dst, res)?;
|
||||
state.update_status(res);
|
||||
state.write(*dst, res)?;
|
||||
}
|
||||
ArithOp::Asr { dst, a, n } => {
|
||||
frame.status.clear();
|
||||
let x = frame.read(*a)?;
|
||||
let y = frame.read(*n)?;
|
||||
state.clear_status();
|
||||
let x = state.read(*a)?;
|
||||
let y = state.read(*n)?;
|
||||
if y > u32::MAX as u64 {
|
||||
frame.status.invalid = true;
|
||||
state.set_flag(Cond::Invalid, true);
|
||||
} else {
|
||||
let res = x.signed_shr(y as u32);
|
||||
frame.status.update(res);
|
||||
frame.write(*dst, res)?;
|
||||
state.update_status(res);
|
||||
state.write(*dst, res)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
-14
@@ -1,14 +1,12 @@
|
||||
use std::collections::VecDeque;
|
||||
|
||||
|
||||
use crsn::asm::data::literal::Value;
|
||||
use crsn::asm::instr::op::{EvalRes, OpTrait};
|
||||
use crsn::runtime::fault::Fault;
|
||||
|
||||
|
||||
use crsn::runtime::run_thread::{RunState, ThreadInfo};
|
||||
use crsn::runtime::run_thread::{state::RunState, ThreadInfo};
|
||||
|
||||
use crate::defs::StackOp;
|
||||
use crsn::asm::instr::Cond;
|
||||
|
||||
struct Stacks {
|
||||
stacks: Vec<VecDeque<Value>>,
|
||||
@@ -27,34 +25,34 @@ impl OpTrait for StackOp {
|
||||
let eres = EvalRes::default();
|
||||
match self {
|
||||
StackOp::Push { num, src } => {
|
||||
state.frame.status.clear();
|
||||
let stack_num = state.frame.read(*num)?;
|
||||
let val = state.frame.read(*src)?;
|
||||
state.clear_status();
|
||||
let stack_num = state.read(*num)?;
|
||||
let val = state.read(*src)?;
|
||||
|
||||
if stack_num > 8 {
|
||||
state.frame.status.invalid = true;
|
||||
state.set_flag(Cond::Invalid, true);
|
||||
} else {
|
||||
let obj: &mut Stacks = state.ext_mut();
|
||||
obj.stacks[stack_num as usize].push_back(val);
|
||||
}
|
||||
}
|
||||
StackOp::Pop { dst, num } => {
|
||||
state.frame.status.clear();
|
||||
let stack_num = state.frame.read(*num)?;
|
||||
state.clear_status();
|
||||
let stack_num = state.read(*num)?;
|
||||
|
||||
if stack_num > 8 {
|
||||
state.frame.status.invalid = true;
|
||||
state.set_flag(Cond::Invalid, true);
|
||||
} else {
|
||||
let obj: &mut Stacks = state.ext_mut();
|
||||
let val = obj.stacks[stack_num as usize].pop_back();
|
||||
|
||||
if obj.stacks[stack_num as usize].is_empty() {
|
||||
state.frame.status.zero = true;
|
||||
state.set_flag(Cond::Zero, true);
|
||||
}
|
||||
|
||||
let val = match val {
|
||||
None => {
|
||||
state.frame.status.overflow = true;
|
||||
state.set_flag(Cond::Overflow, true);
|
||||
0
|
||||
}
|
||||
Some(val) => {
|
||||
@@ -62,7 +60,7 @@ impl OpTrait for StackOp {
|
||||
}
|
||||
};
|
||||
|
||||
state.frame.write(*dst, val)?;
|
||||
state.write(*dst, val)?;
|
||||
}
|
||||
|
||||
// TODO
|
||||
|
||||
@@ -51,15 +51,15 @@ fn main() {
|
||||
(ld _ arg0)
|
||||
(fault)
|
||||
(:lbl)
|
||||
(call fibo 5)
|
||||
(call fac 5)
|
||||
(ld r0 res0)
|
||||
)
|
||||
(fibo
|
||||
(fac
|
||||
(cmp arg0 2
|
||||
(eq? (ret 2)))
|
||||
(ld r0 arg0)
|
||||
(dec r0)
|
||||
(call fibo r0)
|
||||
(call fac r0)
|
||||
(ld r0 arg0)
|
||||
(mul r0 res0)
|
||||
(ret r0)
|
||||
|
||||
Reference in New Issue
Block a user