~maddie/custom-processor-simulator

86418b49a48e7555a9243024dd42a94abc36a7b7 — Madeline Cronin 3 months ago 67a7a43
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.
1 files changed, 60 insertions(+), 9 deletions(-)

M src/processor.rs
M src/processor.rs => src/processor.rs +60 -9
@@ 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,
        }
    }
}