~maddie/STT-implementation

ref: b048caf359c2e0308cac6b8c68da86654de03e73 STT-implementation/src/lib.rs -rw-r--r-- 4.6 KiB
b048caf3 — kn0000 Small additions, as well as changing mem to buf to use a vec for avoiding a stack overflow 6 months 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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
const STACK_SIZE: usize = 1024;
pub const MEMORY_SIZE: usize = 1<<20;
pub const SCREEN_WIDTH: usize = 512;
pub const SCREEN_HEIGHT: usize = 512;
pub const SCREEN_UPDATE_ADDRESS: usize = 0x7FFFF;

#[derive(Debug)]
pub struct Stack {
    buffer: [u16;STACK_SIZE],
    index: usize
}

impl Stack {
    fn push(&mut self, value: u16) {
        self.buffer[self.index] = value;
        self.index = (self.index + 1) % STACK_SIZE;
    }

    fn pop(&mut self) -> u16 {
        self.index = (self.index + STACK_SIZE - 1) % STACK_SIZE;
        self.buffer[self.index]
    }
}

pub fn new_stack() -> Stack {
    Stack{
        buffer: [0u16;STACK_SIZE],
        index: 0
    }
}

pub struct Processor {
    pub stack_a: Stack,
    pub stack_b: Stack,
    pub memory: [u16;MEMORY_SIZE],
    pub carry: bool,
    pub pc: usize
}

impl Processor {
    pub fn run(&mut self) -> bool {
        let instruction = self.memory[self.pc] & 0x3FF;
        let (mut stack, off_stack)  = {
            if (instruction & 0x200) == 0 {
                (&mut self.stack_a, &mut self.stack_b)
            }
            else {(&mut self.stack_b, &mut self.stack_a)}
        };
        let mut is_jump = false;

        if instruction & 0x100 == 0 { //calculation
            self.carry = calc(&mut stack, instruction, self.carry);
        }
        else if instruction & 0x80 == 0 { //jump
            let push_pc = (instruction & 0x40) != 0;
            let conditional = (instruction & 0x20) != 0;
            if !conditional || self.carry {
                let address = (stack.pop() as usize) | ((stack.pop() as usize) << 10);
                is_jump = true;
                if push_pc {
                    let a = self.pc + 1;
                    let upper = a & 0b11111111110000000000 >> 10;
                    let lower = a & 0b1111111111;
                    stack.push(upper as u16);
                    stack.push(lower as u16);
                }
                self.pc = address;
            }
        }
        else {
            match instruction & 0x7F {
                0 => { //immediate value
                    self.pc += 1;
                    stack.push(self.memory[self.pc] & 0x3FF);
                }
                1 => { //push pc
                    let upper = self.pc & 0b11111111110000000000 >> 10;
                    let lower = self.pc & 0b1111111111;
                    stack.push(upper as u16);
                    stack.push(lower as u16);
                }
                2 => { //swap
                    let a = stack.pop();
                    let b = stack.pop();
                    stack.push(a);
                    stack.push(b);
                }
                3 => off_stack.push(stack.pop()), //move between stacks
                4 => { //push from memory
                    let address = (stack.pop() as usize) | ((stack.pop() as usize) << 10);
                    stack.push(self.memory[address]);
                }
                5 => { //pop to memory
                    let address = (stack.pop() as usize) | ((stack.pop() as usize) << 10);
                    self.memory[address] = stack.pop();
                }
                6 => { //dup
                    let a = stack.pop();
                    stack.push(a);
                    stack.push(a);
                }
                7 => { //over
                    let a = stack.pop();
                    let b = stack.pop();
                    stack.push(b);
                    stack.push(a);
                    stack.push(b);
                }
                8 => self.carry = false, //clear/set carry
                9 => self.carry = true,
                10 => _ = stack.pop(), //drop value
                0x7F => return false,
                _ => ()
            }
        }
        if !is_jump {self.pc += 1};
        true
    }
}

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

pub fn mem_to_buf(memory: &[u16]) -> Vec<u32> {
    let mut result = Vec::new();
    for byte in &memory[(MEMORY_SIZE-SCREEN_WIDTH*SCREEN_HEIGHT)..MEMORY_SIZE] {
        result.push((((byte & 0b111000000) as u32) << 15) | (((byte & 0b111000) as u32) << 10) | (((byte & 0b111) as u32) << 5)); //shifts 3 bits of each 10 bit value into the rgb channels of the buffer, from the last region of memory
    }
    result
}