From 86418b49a48e7555a9243024dd42a94abc36a7b7 Mon Sep 17 00:00:00 2001 From: Madeline Cronin Date: Fri, 30 Aug 2024 16:40:18 +0100 Subject: [PATCH] Implemented addition and the generalised parts of handling arithmetic ops. In particular, implemented the invert (I) flag, and ensured that the program counter is unwritable for arithmetic instructions. --- src/processor.rs | 69 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 60 insertions(+), 9 deletions(-) diff --git a/src/processor.rs b/src/processor.rs index 96e7025..2ee654a 100644 --- a/src/processor.rs +++ b/src/processor.rs @@ -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 = 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, } } } -- 2.43.4