~maddie/STT-implementation

ref: 34000e48a5a7162ad7e71da727a3c296bb674f02 STT-implementation/src/lib.rs -rw-r--r-- 4.4 KiB
34000e48 — kn0000 Add long addresses for jump, push and pop instructions 24 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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
struct Processor {
    stack_a: Vec<u16>,
    stack_b: Vec<u16>,
    pub memory: Vec<u16>,
    carry: bool,
    pub pc: u16 //program counter
}

impl Processor {
    pub fn run(&mut self) {
        let instruction = self.memory[self.pc as usize];
        let mut is_jump = false;
        match instruction & 0x300 {
            0x000 => self.carry = calc(&mut self.stack_a, instruction, self.carry),
            0x100 => self.carry = calc(&mut self.stack_a, instruction, self.carry),
            0x200 => self.stack_a.push(instruction & 0xFF),
            0x300 => {
                if (instruction & 0x80) != 0 {
                    let conditional = (instruction & 0x40) != 0;
                    let relative = (instruction & 0x20) != 0;
                    let save_pc = (instruction & 0x10) != 0;
                    let long_address = (instruction & 0x8) != 0;
                    if !conditional || self.carry {
                        let address;
                        if long_address {address = self.stack_a.pop().unwrap_or(0) | (self.stack_a.pop().unwrap_or(0) << 10)} //lower value on stack is high half of long address
                        else {address = self.stack_a.pop().unwrap_or(0)};
                        if save_pc {self.stack_a.push(self.pc+1)};
                        if relative {self.pc += address}
                        else {self.pc = address};
                        is_jump = true;
                    }
                }
                else {
                    let toggle = (instruction & 0x40) != 0;
                    let stack;
                    if toggle {stack = &mut self.stack_b;}
                    else {stack = &mut self.stack_a;};
                    match instruction & 0x3F {
                        0 => { //swap top 2
                            let a = stack.pop().unwrap_or(0);
                            let b = stack.pop().unwrap_or(0);
                            stack.push(a);
                            stack.push(b);
                        }
                        1 => { //clone top
                            let a = stack.pop().unwrap_or(0);
                            stack.push(a);
                            stack.push(a);
                        }
                        2 => { //clone second
                            let a = stack.pop().unwrap_or(0);
                            let b = stack.pop().unwrap_or(0);
                            stack.push(b);
                            stack.push(a);
                            stack.push(b);
                        }
                        3 => { //move between stacks
                            if toggle {self.stack_a.push(self.stack_b.pop().unwrap_or(0));}
                            else {self.stack_b.push(self.stack_a.pop().unwrap_or(0));};
                        }
                        4 => { //push/pop
                            let addr = self.stack_a.pop().unwrap_or(0) as usize;
                            if toggle {
                                let value = self.stack_a.pop().unwrap_or(0);
                                self.memory[addr] = value;
                            }
                            else {self.stack_a.push(self.memory[addr])};
                        }
                        5 => { //long addr push/pop
                            let addr = (self.stack_a.pop().unwrap_or(0) | (self.stack_a.pop().unwrap_or(0) << 10)) as usize;
                            if toggle {
                                let value = self.stack_a.pop().unwrap_or(0);
                                self.memory[addr] = value;
                            }
                            else {self.stack_a.push(self.memory[addr])};
                        }
                        6 => { //set/clear carry
                            self.carry = toggle;
                        }
                        _ => ()
                    }
                }
            }
            _ => unreachable!()
        }
        if !is_jump {self.pc += 1};
    }
}

fn calc(stack: &mut Vec::<u16>, instruction: u16, carry_in: bool) -> bool {
    let operand_a = stack.pop().unwrap_or(0);
    let operand_b = stack.pop().unwrap_or(0);
    let mut carry = carry_in;
    let mut result = 0;
    for i in 0..10 {
        let bit = 1 << i;
        let count = ((operand_a & bit) >> i) + ((operand_b & bit) >> i) + carry as u16;
        result += ((instruction & (1<<(count+4))) >> count) << i;
        carry = (instruction & (1<<count)) != 0;
    }
    stack.push(result);
    carry
}