~maddie/custom-processor-simulator

ref: 86418b49a48e7555a9243024dd42a94abc36a7b7 custom-processor-simulator/src/processor.rs -rw-r--r-- 4.0 KiB
86418b49Madeline Cronin Implemented addition and the generalised parts of handling arithmetic ops. 20 days ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
pub struct Processor<'a> {
    reg: [u16;32],
    flags: [bool;2], //flag A, then B
    itr_toggle: bool,
    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> {
    Processor {
        reg: [0;32],
        flags: [false;2],
        itr_toggle: false,
        memory,
        disk
    }
}

impl <'a> Processor<'a> {
    ///Runs the processor through one instruction.
    ///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 & 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 instruction
                               //execution.
            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,
        }
    }
}