M src/lib.rs => src/lib.rs +110 -85
@@ 1,113 1,138 @@
+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: Vec<u16>,
- pub stack_b: Vec<u16>,
- pub memory: [u16;0xFFFFF],
+ pub stack_a: Stack,
+ pub stack_b: Stack,
+ pub memory: [u16;MEMORY_SIZE],
pub carry: bool,
- pub pc: u16 //program counter
+ pub pc: usize
}
impl Processor {
pub fn run(&mut self) -> bool {
- let instruction = self.memory[self.pc as usize];
+ 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;
- 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;
- }
+
+ 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 => {
+ 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);
}
- 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;
- }
- 0x3F => return false,
- _ => ()
- }
+ 7 => { //over
+ let a = stack.pop();
+ let b = stack.pop();
+ stack.push(b);
+ stack.push(a);
+ stack.push(b);
}
+ 0x7F => return false,
+ _ => ()
}
- _ => unreachable!()
}
if !is_jump {self.pc += 1};
true
}
}
-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);
+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 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;
+ 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]) -> [u32;(2<<14)-1] {
- let mut result = [0u32;(2<<14)-1];
+pub fn mem_to_buf(memory: &[u16]) -> [u32;SCREEN_WIDTH*SCREEN_HEIGHT] {
+ let mut result = [0u32;SCREEN_WIDTH*SCREEN_HEIGHT];
let mut i = 0;
- for byte in &memory[(2<<20)-(2<<14)..(2<<20)-1] {
+ for byte in &memory[(MEMORY_SIZE-SCREEN_WIDTH*SCREEN_HEIGHT)..MEMORY_SIZE] {
result[i] = (((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
i += 1;
}
M src/main.rs => src/main.rs +18 -11
@@ 4,17 4,16 @@ use implementation::*;
fn main() {
let mut filename = String::new();
- print!("Enter filename of the program to load into memory");
+ println!("Enter filename of the program to load into memory");
io::stdin().read_line(&mut filename).unwrap();
- let program = fs::read_to_string(filename).unwrap();
+ let program = fs::read_to_string(filename.trim()).unwrap();
let mut i = 0;
- let mut memory = [0u16;0xFFFFF];
+ let mut memory = [0u16;MEMORY_SIZE];
for line in program.lines() {
let mut byte = 0u16;
let mut count = 0;
for digit in line.chars() {
- count += 1;
match digit {
'0' => {
byte = byte << 1;
@@ 26,25 25,33 @@ fn main() {
}
_ => ()
}
- if count > 10 {panic!("10 bits only :)")};
+ if count > 10 {panic!("10 bits only :)\nFailed at line {i}")};
}
memory[i] = byte;
i += 1;
}
let mut processor = Processor {
- stack_a: Vec::new(),
- stack_b: Vec::new(),
+ stack_a: new_stack(),
+ stack_b: new_stack(),
memory,
carry: false,
pc: 0
};
- let mut window = Window::new("STT Display", 128, 128, WindowOptions::default()).unwrap();
+ let mut window = Window::new("STT Display", SCREEN_WIDTH, SCREEN_HEIGHT, WindowOptions::default()).unwrap();
+ window.update_with_buffer(&[0;(1<<14)],128,128).unwrap();
+ let mut instructions_run = 0;
while window.is_open() && processor.run() {
- if processor.memory[(2<<20)-(2<<14)-1] != 0 {
- processor.memory[(2<<20)-(2<<14)-1] = 0;
- window.update_with_buffer(&mem_to_buf(&processor.memory), 128, 128).unwrap();
+ if processor.memory[SCREEN_UPDATE_ADDRESS] != 0 {
+ processor.memory[SCREEN_UPDATE_ADDRESS] = 0;
+ window.update_with_buffer(&mem_to_buf(&processor.memory), SCREEN_WIDTH, SCREEN_HEIGHT).unwrap();
+ }
+ instructions_run += 1;
+ if instructions_run%1000 == 0 {
+ println!("Program running");
}
}
+
+ println!("Stack A: {0:?}\nStack B: {1:?}", processor.stack_a, processor.stack_b);
}