| 
						
						
						
					 | 
					 | 
					@ -1,5 +1,5 @@ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					use std::any::{Any, TypeId}; | 
					 | 
					 | 
					 | 
					use std::any::{Any, TypeId}; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					use std::collections::HashMap; | 
					 | 
					 | 
					 | 
					use std::collections::{HashMap, VecDeque}; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					use crate::asm::data::{Rd, RdData, RdObj, Register, Wr, WrData}; | 
					 | 
					 | 
					 | 
					use crate::asm::data::{Rd, RdData, RdObj, Register, Wr, WrData}; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					use crate::asm::data::literal::{Addr, Value}; | 
					 | 
					 | 
					 | 
					use crate::asm::data::literal::{Addr, Value}; | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -12,34 +12,98 @@ use nudge::{likely}; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					use crate::asm::instr::cond::Flag; | 
					 | 
					 | 
					 | 
					use crate::asm::instr::cond::Flag; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					use std::fmt::{Debug, Formatter}; | 
					 | 
					 | 
					 | 
					use std::fmt::{Debug, Formatter}; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					use std::fmt; | 
					 | 
					 | 
					 | 
					use std::fmt; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					use std::time::Instant; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					pub struct RunState { | 
					 | 
					 | 
					 | 
					pub struct RunState { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    pub thread_info: Arc<ThreadInfo>, | 
					 | 
					 | 
					 | 
					    pub thread_info: Arc<ThreadInfo>, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    /// Active stack frame
 | 
					 | 
					 | 
					 | 
					    /// The active coroutine
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    pub frame: StackFrame, | 
					 | 
					 | 
					 | 
					    pub cr: CoroutineContext, | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    /// Call stack
 | 
					 | 
					 | 
					 | 
					    /// Parked coroutines
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    pub call_stack: CallStack, | 
					 | 
					 | 
					 | 
					    pub parked: VecDeque<CoroutineContext>, | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    /// General purpose registers that stay valid for the entire run-time of the thread
 | 
					 | 
					 | 
					 | 
					    /// General purpose registers that stay valid for the entire run-time of the thread
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    pub global_regs: [Value; REG_COUNT], | 
					 | 
					 | 
					 | 
					    pub global_regs: [Value; REG_COUNT], | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    /// Extension data
 | 
					 | 
					 | 
					 | 
					    /// Extension data
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    pub ext_data: ExtensionDataStore, | 
					 | 
					 | 
					 | 
					    pub ext_data: ExtensionDataStore, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    /// Execution deadline, if multi-tasked
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    pub cr_deadline: Option<Instant>, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					#[derive(Debug,Default)] | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					pub struct CoroutineContext { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    pub handle: Value, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    /// Active stack frame
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    pub frame: StackFrame, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    /// Call stack
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    pub call_stack: CallStack, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    /// Coroutine run state
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    pub cr_state: CoroutineState, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					/// Execution state of an inactive coroutine
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					#[derive(Debug, Eq, PartialEq)] | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					pub enum CoroutineState { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    /// Ready to run, just started, or interrupted by the scheduler
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    Ready, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    /// Delay in progress
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    Sleep { due: Instant }, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    /// The task finished
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    Finished(Vec<Value>), | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    /// The task yielded a value that must be consumed before it can resume.
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    /// State switches to Ready when the value is read.
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    YieldedValue(Value), | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					impl CoroutineState { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    pub fn is_alive(&self) -> bool { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        match self { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            CoroutineState::Ready => true, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            CoroutineState::Sleep { .. } => true, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            CoroutineState::Finished(_) => false, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            CoroutineState::YieldedValue(_) => true, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					impl Default for CoroutineState { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    fn default() -> Self { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        Self::Ready | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					impl RunState { | 
					 | 
					 | 
					 | 
					impl RunState { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    /// Clear everything. Caution: when done at runtime, this effectively reboots the thread
 | 
					 | 
					 | 
					 | 
					    /// Clear everything. Caution: when done at runtime, this effectively reboots the thread
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    pub fn clear_all(&mut self) { | 
					 | 
					 | 
					 | 
					    pub fn clear_all(&mut self) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        self.frame = Default::default(); | 
					 | 
					 | 
					 | 
					        self.cr = Default::default(); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        self.call_stack = Default::default(); | 
					 | 
					 | 
					 | 
					        self.parked = Default::default(); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        self.global_regs = Default::default(); | 
					 | 
					 | 
					 | 
					        self.global_regs = Default::default(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        self.ext_data = Default::default(); | 
					 | 
					 | 
					 | 
					        self.ext_data = Default::default(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    /// Add a coroutine, marked as Ready, to run next
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    pub fn add_coroutine(&mut self, frame : StackFrame) -> Value { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        let handle = self.thread_info.unique_handle(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        trace!("Spawn cr {:#}", handle); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        // front - so it runs ASAP
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        self.parked.push_front(CoroutineContext { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            handle, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            frame, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            call_stack: vec![], | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            cr_state: Default::default() | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        }); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        if self.cr_deadline.is_none() { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            // start context switching
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            self.cr_deadline = Some(Instant::now() + self.thread_info.scheduler_interval); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        handle | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					impl Debug for RunState { | 
					 | 
					 | 
					 | 
					impl Debug for RunState { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { | 
					 | 
					 | 
					 | 
					    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        f.debug_struct("RunState") | 
					 | 
					 | 
					 | 
					        f.debug_struct("RunState") | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            .field("frame", &self.frame) | 
					 | 
					 | 
					 | 
					            .field("cr", &self.cr) | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            .field("call_stack", &self.call_stack) | 
					 | 
					 | 
					 | 
					            .field("parked", &self.parked) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            .field("global_regs", &self.global_regs) | 
					 | 
					 | 
					 | 
					            .field("global_regs", &self.global_regs) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            //.field("ext_data", &self.ext_data)
 | 
					 | 
					 | 
					 | 
					            //.field("ext_data", &self.ext_data)
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            .finish() | 
					 | 
					 | 
					 | 
					            .finish() | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -79,44 +143,44 @@ impl RunState { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    #[inline(always)] | 
					 | 
					 | 
					 | 
					    #[inline(always)] | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    pub fn set_flag(&mut self, flag: Flag, set: bool) { | 
					 | 
					 | 
					 | 
					    pub fn set_flag(&mut self, flag: Flag, set: bool) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        trace!("Flag {} = {:?}", flag, set); | 
					 | 
					 | 
					 | 
					        trace!("Flag {} = {:?}", flag, set); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        self.frame.status.set(flag, set); | 
					 | 
					 | 
					 | 
					        self.cr.frame.status.set(flag, set); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    /// Check status flags for a condition
 | 
					 | 
					 | 
					 | 
					    /// Check status flags for a condition
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    #[inline(always)] | 
					 | 
					 | 
					 | 
					    #[inline(always)] | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    pub fn test_cond(&self, cond: Cond) -> bool { | 
					 | 
					 | 
					 | 
					    pub fn test_cond(&self, cond: Cond) -> bool { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        self.frame.status.test(cond) | 
					 | 
					 | 
					 | 
					        self.cr.frame.status.test(cond) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    /// Set program counter - address of the next instruction to run
 | 
					 | 
					 | 
					 | 
					    /// Set program counter - address of the next instruction to run
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    pub fn set_pc(&mut self, pc: Addr) { | 
					 | 
					 | 
					 | 
					    pub fn set_pc(&mut self, pc: Addr) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        trace!("PC := {}", pc); | 
					 | 
					 | 
					 | 
					        trace!("PC := {}", pc); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        self.frame.pc = pc; | 
					 | 
					 | 
					 | 
					        self.cr.frame.pc = pc; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    /// Get program counter - address of the next instruction to run
 | 
					 | 
					 | 
					 | 
					    /// Get program counter - address of the next instruction to run
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    pub fn get_pc(&self) -> Addr { | 
					 | 
					 | 
					 | 
					    pub fn get_pc(&self) -> Addr { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        self.frame.pc | 
					 | 
					 | 
					 | 
					        self.cr.frame.pc | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    /// Clear status flags
 | 
					 | 
					 | 
					 | 
					    /// Clear status flags
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    #[inline(always)] | 
					 | 
					 | 
					 | 
					    #[inline(always)] | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    pub fn clear_status(&mut self) { | 
					 | 
					 | 
					 | 
					    pub fn clear_status(&mut self) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        self.frame.status.clear(); | 
					 | 
					 | 
					 | 
					        self.cr.frame.status.clear(); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    /// Update status flags using a variable.
 | 
					 | 
					 | 
					 | 
					    /// Update status flags using a variable.
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    /// The update is additive - call `clear_status()` first if desired!
 | 
					 | 
					 | 
					 | 
					    /// The update is additive - call `clear_status()` first if desired!
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    #[inline(always)] | 
					 | 
					 | 
					 | 
					    #[inline(always)] | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    pub fn update_status(&mut self, val: Value) { | 
					 | 
					 | 
					 | 
					    pub fn update_status(&mut self, val: Value) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        self.frame.status.update(val); | 
					 | 
					 | 
					 | 
					        self.cr.frame.status.update(val); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    /// Update status flags using a variable.
 | 
					 | 
					 | 
					 | 
					    /// Update status flags using a variable.
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    /// The update is additive - call `clear_status()` first if desired!
 | 
					 | 
					 | 
					 | 
					    /// The update is additive - call `clear_status()` first if desired!
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    #[inline(always)] | 
					 | 
					 | 
					 | 
					    #[inline(always)] | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    pub fn update_status_float(&mut self, val: f64) { | 
					 | 
					 | 
					 | 
					    pub fn update_status_float(&mut self, val: f64) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        self.frame.status.update_float(val); | 
					 | 
					 | 
					 | 
					        self.cr.frame.status.update_float(val); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    /// Read object handle value
 | 
					 | 
					 | 
					 | 
					    /// Read object handle value
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -133,8 +197,8 @@ impl RunState { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            RdData::Immediate(v) => Ok(v), | 
					 | 
					 | 
					 | 
					            RdData::Immediate(v) => Ok(v), | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            RdData::Register(Register::Gen(rn)) => { | 
					 | 
					 | 
					 | 
					            RdData::Register(Register::Gen(rn)) => { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                if likely(rn < REG_COUNT as u8) { | 
					 | 
					 | 
					 | 
					                if likely(rn < REG_COUNT as u8) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                    trace!("Rd {:?} = {}", rd, self.frame.gen[rn as usize]); | 
					 | 
					 | 
					 | 
					                    trace!("Rd {:?} = {}", rd, self.cr.frame.gen[rn as usize]); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                    Ok(self.frame.gen[rn as usize]) | 
					 | 
					 | 
					 | 
					                    Ok(self.cr.frame.gen[rn as usize]) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                } else { | 
					 | 
					 | 
					 | 
					                } else { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                    Err(Fault::RegisterNotExist { reg: Register::Gen(rn) }) | 
					 | 
					 | 
					 | 
					                    Err(Fault::RegisterNotExist { reg: Register::Gen(rn) }) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                } | 
					 | 
					 | 
					 | 
					                } | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -149,16 +213,16 @@ impl RunState { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            } | 
					 | 
					 | 
					 | 
					            } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            RdData::Register(Register::Arg(rn)) => { | 
					 | 
					 | 
					 | 
					            RdData::Register(Register::Arg(rn)) => { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                if likely(rn < REG_COUNT as u8) { | 
					 | 
					 | 
					 | 
					                if likely(rn < REG_COUNT as u8) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                    trace!("Rd {:?} = {}", rd, self.frame.arg[rn as usize]); | 
					 | 
					 | 
					 | 
					                    trace!("Rd {:?} = {}", rd, self.cr.frame.arg[rn as usize]); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                    Ok(self.frame.arg[rn as usize]) | 
					 | 
					 | 
					 | 
					                    Ok(self.cr.frame.arg[rn as usize]) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                } else { | 
					 | 
					 | 
					 | 
					                } else { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                    Err(Fault::RegisterNotExist { reg: Register::Arg(rn) }) | 
					 | 
					 | 
					 | 
					                    Err(Fault::RegisterNotExist { reg: Register::Arg(rn) }) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                } | 
					 | 
					 | 
					 | 
					                } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            } | 
					 | 
					 | 
					 | 
					            } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            RdData::Register(Register::Res(rn)) => { | 
					 | 
					 | 
					 | 
					            RdData::Register(Register::Res(rn)) => { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                if likely(rn < REG_COUNT as u8) { | 
					 | 
					 | 
					 | 
					                if likely(rn < REG_COUNT as u8) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                    trace!("Rd {:?} = {}", rd, self.frame.res[rn as usize]); | 
					 | 
					 | 
					 | 
					                    trace!("Rd {:?} = {}", rd, self.cr.frame.res[rn as usize]); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                    Ok(self.frame.res[rn as usize]) | 
					 | 
					 | 
					 | 
					                    Ok(self.cr.frame.res[rn as usize]) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                } else { | 
					 | 
					 | 
					 | 
					                } else { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                    Err(Fault::RegisterNotExist { reg: Register::Res(rn) }) // TODO use match after @ when stabilized https://github.com/rust-lang/rust/issues/65490
 | 
					 | 
					 | 
					 | 
					                    Err(Fault::RegisterNotExist { reg: Register::Res(rn) }) // TODO use match after @ when stabilized https://github.com/rust-lang/rust/issues/65490
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                } | 
					 | 
					 | 
					 | 
					                } | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -174,6 +238,26 @@ impl RunState { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    fn read_object(&mut self, reference: Value) -> Result<Value, Fault> { | 
					 | 
					 | 
					 | 
					    fn read_object(&mut self, reference: Value) -> Result<Value, Fault> { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        // values yielded from coroutines
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        for cr in &mut self.parked { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            if cr.handle == reference { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                match cr.cr_state { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                    CoroutineState::Ready | CoroutineState::Sleep { .. } => { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                        return Err(Fault::Blocked); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                    CoroutineState::Finished(_) => { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                        self.set_flag(Flag::Eof, true); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                        warn!("Attempt to read yielded value of a finished coroutine"); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                        return Ok(0); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                    CoroutineState::YieldedValue(v) => { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                        cr.cr_state = CoroutineState::Ready; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                        return Ok(v); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        // This is a shitty dirty hack to allow iterating over the extensions while passing a mutable reference
 | 
					 | 
					 | 
					 | 
					        // This is a shitty dirty hack to allow iterating over the extensions while passing a mutable reference
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        // to self to the reading methods. Since the extensions array is in an Arc, it can't be mutated internally
 | 
					 | 
					 | 
					 | 
					        // to self to the reading methods. Since the extensions array is in an Arc, it can't be mutated internally
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        // anyway, and we know it will still live after the method returns - unless someone does something incredibly stupid.
 | 
					 | 
					 | 
					 | 
					        // anyway, and we know it will still live after the method returns - unless someone does something incredibly stupid.
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -213,7 +297,7 @@ impl RunState { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        match wr.0 { | 
					 | 
					 | 
					 | 
					        match wr.0 { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            WrData::Register(Register::Gen(rn)) => { | 
					 | 
					 | 
					 | 
					            WrData::Register(Register::Gen(rn)) => { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                if likely(rn < REG_COUNT as u8) { | 
					 | 
					 | 
					 | 
					                if likely(rn < REG_COUNT as u8) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                    self.frame.gen[rn as usize] = val; | 
					 | 
					 | 
					 | 
					                    self.cr.frame.gen[rn as usize] = val; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                    Ok(()) | 
					 | 
					 | 
					 | 
					                    Ok(()) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                } else { | 
					 | 
					 | 
					 | 
					                } else { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                    Err(Fault::RegisterNotExist { reg: Register::Gen(rn) }) | 
					 | 
					 | 
					 | 
					                    Err(Fault::RegisterNotExist { reg: Register::Gen(rn) }) | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
					 | 
					
  |