pub fn tick(&mut self) -> CpuState {
		self.fetch();

		// decode & execute
		//   upper byte: shift u16 right 8 places, then cast to u8
		//   lower byte: casting u16 -> u8 truncates leading bits
		let op = (self.ir >> 12) as u8;
		match op {
			0x1   => { // MLOAD
				let rloc_o0 = lo_nibble((self.ir >> 8) as u8);
				let mloc_i0 = self.ir as u8;

				self.reg[rloc_o0 as usize] = self.mem[mloc_i0 as usize];
				CpuState::Continue
			},

			0x2   => { // RSET
				let rloc = lo_nibble((self.ir >> 8) as u8);  // lower nibble of first byte
				let rval = self.ir as u8;                    // value is entire second byte

				self.reg[rloc as usize] = rval;               // store value in register
				CpuState::Continue
			},
			
			0x3   => { // MSTOR
				let rloc_i0 = lo_nibble((self.ir >> 8) as u8);
				let mloc_o0 = self.ir as u8;

				self.mem[mloc_o0 as usize] = self.reg[rloc_i0 as usize];
				CpuState::Continue
			},

			0x4   => { // RMOV
				let rloc_i0 = hi_nibble(self.ir as u8);
				let rloc_o0 = lo_nibble(self.ir as u8);

				debug!("moving from {:02X} to {:02X}", rloc_i0, rloc_o0);
				self.reg[rloc_o0 as usize] = self.reg[rloc_i0 as usize];
				CpuState::Continue
			},

			0x5   => { // ADDB
				let rloc_o0 = lo_nibble((self.ir >> 8) as u8);   // first input: lower nibble of first byte
				let rloc_i0 = hi_nibble(self.ir as u8);          // second input: upper nibble of second byte
				let rloc_i1 = lo_nibble(self.ir as u8);          // output: lower nibble of second byte

				self.reg[rloc_o0 as usize] = 
					((self.reg[rloc_i0 as usize] as i8) + (self.reg[rloc_i1 as usize]as i8)) as u8;
				CpuState::Continue
			},

			0x7   => { // OR
				let rloc_o0 = lo_nibble((self.ir >> 8) as u8);
				let rloc_i0 = hi_nibble(self.ir as u8);
				let rloc_i1 = lo_nibble(self.ir as u8);

				self.reg[rloc_o0 as usize] = self.reg[rloc_i0 as usize] | self.reg[rloc_i1 as usize];
				CpuState::Continue
			},

			0x8   => { // AND
				let rloc_o0 = lo_nibble((self.ir >> 8) as u8);
				let rloc_i0 = hi_nibble(self.ir as u8);
				let rloc_i1 = lo_nibble(self.ir as u8);

				self.reg[rloc_o0 as usize] = self.reg[rloc_i0 as usize] & self.reg[rloc_i1 as usize];
				CpuState::Continue
			},

			0x9   => { // XOR
				let rloc_o0 = lo_nibble((self.ir >> 8) as u8);
				let rloc_i0 = hi_nibble(self.ir as u8);
				let rloc_i1 = lo_nibble(self.ir as u8);

				self.reg[rloc_o0 as usize] = self.reg[rloc_i0 as usize] ^ self.reg[rloc_i1 as usize];
				CpuState::Continue
			},

			0xA   => { // ROT
				// LHS shifts <width> bits off the (left) end of the bitstring
				// RHS shifts the bitstring to the right until only the bits which fell off remain.
				//   LHS is the remaining MSB bits; RHS is the remaining LSB bits
				//   ∴ LHS <OR> RHS provides a rotated bitstring
				//
				let rloc_i0   = lo_nibble((self.ir >> 8) as u8) as usize;          // register is first nibble ...
				let swidth    = (hi_nibble(self.ir as u8) & 0b0000_0111) as usize; // last three bytes of second nibble ...
				self.reg[rloc_i0 as usize] = (self.reg[rloc_i0] >> swidth) | (self.reg[rloc_i0] << (BYTE_WIDTH - swidth));

				CpuState::Continue
			},

			0xB  => { // JMPEQ
				let rloc_i0 = lo_nibble((self.ir >> 8) as u8);
				let next_ip = self.ir as u8;

				if self.reg[rloc_i0 as usize] == self.reg[0] { self.ip = next_ip }
				CpuState::Continue
			},

			0xC   => { CpuState::Halt },
			_     => { debug!("halt, cpu on fire: {}", op); CpuState::Halt },
		}
	}
/// Runs the entire fetch, execute, decode cycle against the current IP
Runs the entire fetch, execute, decode cycle against the current IP
Runs the entire fetch execute decode cycle against the current IP
pub fn tick(&mut self) -> CpuState {
		self.fetch();
		// decode & execute
		//   upper byte: shift u16 right 8 places, then cast to u8
		//   lower byte: casting u16 -> u8 truncates leading bits
		let op = (self.ir >> 12) as u8;
		match op {
			0x1   => { // MLOAD
				let rloc_o0 = lo_nibble((self.ir >> 8) as u8);
				let mloc_i0 = self.ir as u8;
				self.reg[rloc_o0 as usize] = self.mem[mloc_i0 as usize];
				CpuState::Continue
			},
			0x2   => { // RSET
				let rloc = lo_nibble((self.ir >> 8) as u8);  // lower nibble of first byte
				let rval = self.ir as u8;                    // value is entire second byte
				self.reg[rloc as usize] = rval;               // store value in register
				CpuState::Continue
			},
			0x3   => { // MSTOR
				let rloc_i0 = lo_nibble((self.ir >> 8) as u8);
				let mloc_o0 = self.ir as u8;
				self.mem[mloc_o0 as usize] = self.reg[rloc_i0 as usize];
				CpuState::Continue
			},
			0x4   => { // RMOV
				let rloc_i0 = hi_nibble(self.ir as u8);
				let rloc_o0 = lo_nibble(self.ir as u8);
				debug!("moving from {:02X} to {:02X}", rloc_i0, rloc_o0);
				self.reg[rloc_o0 as usize] = self.reg[rloc_i0 as usize];
				CpuState::Continue
			},
			0x5   => { // ADDB
				let rloc_o0 = lo_nibble((self.ir >> 8) as u8);   // first input: lower nibble of first byte
				let rloc_i0 = hi_nibble(self.ir as u8);          // second input: upper nibble of second byte
				let rloc_i1 = lo_nibble(self.ir as u8);          // output: lower nibble of second byte
				self.reg[rloc_o0 as usize] = 
					((self.reg[rloc_i0 as usize] as i8) + (self.reg[rloc_i1 as usize]as i8)) as u8;
				CpuState::Continue
			},
			0x7   => { // OR
				let rloc_o0 = lo_nibble((self.ir >> 8) as u8);
				let rloc_i0 = hi_nibble(self.ir as u8);
				let rloc_i1 = lo_nibble(self.ir as u8);
				self.reg[rloc_o0 as usize] = self.reg[rloc_i0 as usize] | self.reg[rloc_i1 as usize];
				CpuState::Continue
			},
			0x8   => { // AND
				let rloc_o0 = lo_nibble((self.ir >> 8) as u8);
				let rloc_i0 = hi_nibble(self.ir as u8);
				let rloc_i1 = lo_nibble(self.ir as u8);
				self.reg[rloc_o0 as usize] = self.reg[rloc_i0 as usize] & self.reg[rloc_i1 as usize];
				CpuState::Continue
			},
			0x9   => { // XOR
				let rloc_o0 = lo_nibble((self.ir >> 8) as u8);
				let rloc_i0 = hi_nibble(self.ir as u8);
				let rloc_i1 = lo_nibble(self.ir as u8);
				self.reg[rloc_o0 as usize] = self.reg[rloc_i0 as usize] ^ self.reg[rloc_i1 as usize];
				CpuState::Continue
			},
			0xA   => { // ROT
				// LHS shifts <width> bits off the (left) end of the bitstring
				// RHS shifts the bitstring to the right until only the bits which fell off remain.
				//   LHS is the remaining MSB bits; RHS is the remaining LSB bits
				//   ∴ LHS <OR> RHS provides a rotated bitstring
				//
				let rloc_i0   = lo_nibble((self.ir >> 8) as u8) as usize;          // register is first nibble ...
				let swidth    = (hi_nibble(self.ir as u8) & 0b0000_0111) as usize; // last three bytes of second nibble ...
				self.reg[rloc_i0 as usize] = (self.reg[rloc_i0] >> swidth) | (self.reg[rloc_i0] << (BYTE_WIDTH - swidth));
				CpuState::Continue
			},
			0xB  => { // JMPEQ
				let rloc_i0 = lo_nibble((self.ir >> 8) as u8);
				let next_ip = self.ir as u8;
				if self.reg[rloc_i0 as usize] == self.reg[0] { self.ip = next_ip }
				CpuState::Continue
			},
			0xC   => { CpuState::Halt },
			_     => { debug!("halt, cpu on fire: {}", op); CpuState::Halt },
		}
	}
pub fn tick ( & mut self ) -> CpuState { self . fetch ( ) ; // decode & execute //   upper byte: shift u16 right 8 places, then cast to u8 //   lower byte: casting u16 -> u8 truncates leading bits let op = ( self . ir >> 12 ) as u8 ; match op { 0x1 => { // MLOAD let rloc_o0 = lo_nibble ( ( self . ir >> 8 ) as u8 ) ; let mloc_i0 = self . ir as u8 ; self . reg [ rloc_o0 as usize ] = self . mem [ mloc_i0 as usize ] ; CpuState :: Continue } , 0x2 => { // RSET let rloc = lo_nibble ( ( self . ir >> 8 ) as u8 ) ; // lower nibble of first byte let rval = self . ir as u8 ; // value is entire second byte self . reg [ rloc as usize ] = rval ; // store value in register CpuState :: Continue } , 0x3 => { // MSTOR let rloc_i0 = lo_nibble ( ( self . ir >> 8 ) as u8 ) ; let mloc_o0 = self . ir as u8 ; self . mem [ mloc_o0 as usize ] = self . reg [ rloc_i0 as usize ] ; CpuState :: Continue } , 0x4 => { // RMOV let rloc_i0 = hi_nibble ( self . ir as u8 ) ; let rloc_o0 = lo_nibble ( self . ir as u8 ) ; debug ! ( " " rloc_i0 rloc_o0 ) ; self . reg [ rloc_o0 as usize ] = self . reg [ rloc_i0 as usize ] ; CpuState :: Continue } , 0x5 => { // ADDB let rloc_o0 = lo_nibble ( ( self . ir >> 8 ) as u8 ) ; // first input: lower nibble of first byte let rloc_i0 = hi_nibble ( self . ir as u8 ) ; // second input: upper nibble of second byte let rloc_i1 = lo_nibble ( self . ir as u8 ) ; // output: lower nibble of second byte self . reg [ rloc_o0 as usize ] = ( ( self . reg [ rloc_i0 as usize ] as i8 ) + ( self . reg [ rloc_i1 as usize ] as i8 ) ) as u8 ; CpuState :: Continue } , 0x7 => { // OR let rloc_o0 = lo_nibble ( ( self . ir >> 8 ) as u8 ) ; let rloc_i0 = hi_nibble ( self . ir as u8 ) ; let rloc_i1 = lo_nibble ( self . ir as u8 ) ; self . reg [ rloc_o0 as usize ] = self . reg [ rloc_i0 as usize ] | self . reg [ rloc_i1 as usize ] ; CpuState :: Continue } , 0x8 => { // AND let rloc_o0 = lo_nibble ( ( self . ir >> 8 ) as u8 ) ; let rloc_i0 = hi_nibble ( self . ir as u8 ) ; let rloc_i1 = lo_nibble ( self . ir as u8 ) ; self . reg [ rloc_o0 as usize ] = self . reg [ rloc_i0 as usize ] & self . reg [ rloc_i1 as usize ] ; CpuState :: Continue } , 0x9 => { // XOR let rloc_o0 = lo_nibble ( ( self . ir >> 8 ) as u8 ) ; let rloc_i0 = hi_nibble ( self . ir as u8 ) ; let rloc_i1 = lo_nibble ( self . ir as u8 ) ; self . reg [ rloc_o0 as usize ] = self . reg [ rloc_i0 as usize ] ^ self . reg [ rloc_i1 as usize ] ; CpuState :: Continue } , 0xA => { // ROT // LHS shifts <width> bits off the (left) end of the bitstring // RHS shifts the bitstring to the right until only the bits which fell off remain. //   LHS is the remaining MSB bits; RHS is the remaining LSB bits //   ∴ LHS <OR> RHS provides a rotated bitstring // let rloc_i0 = lo_nibble ( ( self . ir >> 8 ) as u8 ) as usize ; // register is first nibble ... let swidth = ( hi_nibble ( self . ir as u8 ) & 0b0000_0111 ) as usize ; // last three bytes of second nibble ... self . reg [ rloc_i0 as usize ] = ( self . reg [ rloc_i0 ] >> swidth ) | ( self . reg [ rloc_i0 ] << ( BYTE_WIDTH - swidth ) ) ; CpuState :: Continue } , 0xB => { // JMPEQ let rloc_i0 = lo_nibble ( ( self . ir >> 8 ) as u8 ) ; let next_ip = self . ir as u8 ; if self . reg [ rloc_i0 as usize ] == self . reg [ 0 ] { self . ip = next_ip } CpuState :: Continue } , 0xC => { CpuState :: Halt } , _ => { debug ! ( " " op ) ; CpuState :: Halt } , } }
Runs the entire fetch, execute, decode cycle against the current IP
Runs the entire fetch execute decode cycle against the current IP
&mut self