@@ 2,8 2,8 @@ pub struct Processor<'a> {
reg: [u16;32],
flags: [bool;2], //flag A, then B
itr_toggle: bool,
- pub memory: &'a mut [u16],
- pub disk: &'a mut [u16],
+ pub memory: &'a mut [u16], //Public since memory should be modifiable by the system.
+ pub disk: &'a mut [u16],
}
pub fn new<'a>(memory: &'a mut [u16], disk: &'a mut [u16]) -> Processor<'a> {
@@ 18,18 18,69 @@ pub fn new<'a>(memory: &'a mut [u16], disk: &'a mut [u16]) -> Processor<'a> {
impl <'a> Processor<'a> {
///Runs the processor through one instruction.
- pub fn run(&mut self) {
+ ///Returns false for normal operation, and true to indicate that it should halt.
+ pub fn run(&mut self) -> bool {
let instruction: (u16,u16) = (self.disk[self.reg[31] as usize],self.disk[self.reg[31] as usize +1]);
let conditions: ((bool,bool),(bool,bool)) = (( //.0.x is activations, .1.x is conditions
- (instruction.0 & 0x80) != 0,
- (instruction.0 & 0x40) != 0),(
- (instruction.0 & 0x20) != 0,
- (instruction.0 & 0x10) != 0)
+ (instruction.0 & 0x8000) != 0,
+ (instruction.0 & 0x4000) != 0),(
+ (instruction.0 & 0x2000) != 0,
+ (instruction.0 & 0x1000) != 0)
);
if (conditions.0.0 && (conditions.1.0 != self.flags[0])) || (conditions.0.1 && (conditions.1.1 != self.flags[1])) {
- self.reg[31] += 2; //update the program counter at the end of the instruction
+ self.reg[31] += 2; //update the program counter at the end of instruction
//execution.
- return; //if the conditions are not met, perform no further calculations.
+ return false; //if the conditions are not met, perform no further calculations.
+ }
+
+ match instruction.0 & 0x0F00 {
+ 0x0100 => {
+ //Arithmetic operations.
+ let toggles: (bool,bool,bool,bool) = ( //S,C,F,I, see ISA for meanings
+ (instruction.0 & 0x0080) != 0,
+ (instruction.0 & 0x0040) != 0,
+ (instruction.0 & 0x0020) != 0,
+ (instruction.0 & 0x0010) != 0,
+ );
+ let operands: (usize, usize, usize) = (
+ ((instruction.1 & 0xF800) >> 11) as usize,
+ ((instruction.1 & 0x07C0) >> 6) as usize,
+ ((instruction.1 & 0x004E) >> 1) as usize,
+ );
+ let mut pc_overwrite: Option<u16> = None;
+ if operands.2 == 31 { //program counter is unwritable for non-control flow
+ //instructions, but the overflow checks should still occur,
+ //so hold onto the next value and replace it later.
+ pc_overwrite = Some(self.reg[31] + 2);
+ }
+
+ match instruction.0 & 0x000F {
+ 0x0000 => { //Addition
+ if toggles.1 { //If C=1, then extra logic is required to correctly identify
+ //carries
+ (self.reg[operands.2], self.flags[toggles.2 as usize]) = {
+ if toggles.0 { //If dealing with signed values, cast the register
+ //values before passing them to overflowing_add.
+ let (uncast_return, flag) = (self.reg[operands.0] as i16).overflowing_add(self.reg[operands.1] as i16);
+ (uncast_return as u16, flag)
+ }
+ else { //Otherwise just pass them straight to overflowing_add.
+ self.reg[operands.0].overflowing_add(self.reg[operands.1])
+ }
+ };
+ }
+ else {self.reg[operands.2] = self.reg[operands.0].wrapping_add(self.reg[operands.1])};
+ }
+ 0x0001 => { //Subtraction
+
+ }
+ _ => return true
+ }
+ if toggles.3 {self.reg[operands.2] = !self.reg[operands.2]};
+ if let Some(addr) = pc_overwrite {self.reg[31] = addr};
+ return false
+ }
+ _ => return true,
}
}
}