From 2dde5a8fcaa187ff3d35d10bc6adc4fdacf0e674 Mon Sep 17 00:00:00 2001 From: Michael Preisach Date: Wed, 23 May 2018 14:13:32 +0200 Subject: [PATCH] self test running except instruction "in" --- src/alu.rs | 51 ++++++ src/cpu.rs | 370 +++++++++++++++++++++++++++++++++++++++ src/main.rs | 486 +-------------------------------------------------- src/tests.rs | 16 ++ 4 files changed, 445 insertions(+), 478 deletions(-) create mode 100644 src/alu.rs create mode 100644 src/cpu.rs create mode 100644 src/tests.rs diff --git a/src/alu.rs b/src/alu.rs new file mode 100644 index 0000000..51f3ddd --- /dev/null +++ b/src/alu.rs @@ -0,0 +1,51 @@ +pub struct Alu { + op: u16, + a: u16, + b: u16, + c: u16, +} + +impl Alu { + pub fn new() -> Alu { + Alu { + op: 0, + a: 0, + b: 0, + c: 0, + } + } + pub fn set_input(&mut self, a: u16, b:u16) { + self.a = a % 32768; + self.b = b % 32768; + } + + pub fn set_op(&mut self, op: u16) { + self.op = op; + } + + pub fn get_res(&self) -> u16 { + self.c + } + pub fn execute(&mut self) { + match self.op { + 0 => self.c = match self.a == self.b { //eq + true => 1, + false => 0, + }, + 1 => self.c = match self.a > self.b { //gt + true => 1, + false => 0, + }, + 2 => self.c = (self.a + self.b) % 32768, //add + 3 => self.c = ((self.a as u32 * self.b as u32) % 32768) as u16, //mult + 4 => self.c = self.a % self.b, //mod + 5 => self.c = self.a & self.b, //and + 6 => self.c = self.a | self.b, //or + 7 => self.c = (!self.a) % 32768, //not + _ => self.c = self.a, //other + } + if super::DEBUG { + println!("\tAlu{{op: {}, a: {}, b: {}, res: {}", self.op, self.a, self.b, self.c); + } + } +} \ No newline at end of file diff --git a/src/cpu.rs b/src/cpu.rs new file mode 100644 index 0000000..24e5387 --- /dev/null +++ b/src/cpu.rs @@ -0,0 +1,370 @@ +use std::fmt; +use std::fs::File; +use std::path::Path; +use std::io::prelude::*; +use super::*; + +pub struct Cpu { + stack: Vec, + mem: Vec, + reg: Vec, + pc: u16, + alu: Alu, +} + +impl fmt::Debug for Cpu { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Cpu {{ pc = {}, ", self.pc)?; + write!(f, "reg = ")?; + for i in 0..7 { + write!(f, "[{}]: {}, ", i, self.reg[i])?; + } + write!(f, "stack = ")?; + for i in 0..self.stack.len() { + write!(f, "[{}]: {}, ", i, self.stack[i])?; + } + for i in 0..self.mem.len() { + write!(f, "[{}]: {}, ", i, self.mem[i])?; + } + write!(f, "}}")?; + Ok(()) + } +} + +impl Cpu { + pub fn new() -> Cpu { + Cpu { + stack: Vec::new(), + mem: vec![0; 32768], + reg: vec![0; 8], + pc: 0, + alu: Alu::new(), + } + } + + pub fn read_program(&mut self, prog: Vec) { + self.pc = 0; + for i in prog { + self.mem[self.pc as usize] = i; + self.inc_pc(); + } + self.pc = 0; + } + + pub fn read_program_from_file(&mut self, filepath: &str) -> std::io::Result<()> { + self.reg = vec![0; 8]; + self.mem = vec![0; 32768]; + self.stack = Vec::new(); + let path = Path::new(filepath); + let mut file = File::open(path)?; + let mut content : Vec = Vec::new(); + file.read_to_end(&mut content)?; + self.pc = 0; + let mut counter = 0; + for i in content { + match counter % 2 { + 0 => self.mem[counter / 2] = i as u16, + _ => self.mem[counter / 2] += (i as u16) << 8, + } + counter += 1; + } + let prog = self.mem.clone(); + Ok(()) + } + + pub fn execute(&mut self) -> Result<(), &'static str> { + let mut running : bool; + if self.mem.is_empty() { + return Err("No Program"); + } else { + running = true; + while running { + match self.readmem(self.pc).unwrap() { + 0 => { //halt: stop execution and terminate the program + if DEBUG { + println!("{}: halt", self.pc); + } + running = false; + }, + 1 => { //set : set register to the value of + if DEBUG { + println!("{}: set {} {}", self.pc, self.mem[(self.pc + 1) as usize], self.mem[(self.pc + 2) as usize]); + } + self.inc_pc(); + let reg = self.readmem(self.pc).unwrap(); + self.inc_pc(); + let val = self.read(self.readmem(self.pc).unwrap()).unwrap(); + self.write(reg, val)?; + self.inc_pc(); + }, + 2 => { //push : push onto the stack + if DEBUG { + println!("{}: push {}", self.pc, self.mem[(self.pc + 1) as usize]); + } + self.inc_pc(); + let val = self.read(self.readmem(self.pc).unwrap()).unwrap(); + self.push(val); + self.inc_pc(); + }, + 3 => { //pop : remove the top element from the stack and write it into ; empty stack = error + if DEBUG { + println!("{}: pop {}", self.pc, self.mem[(self.pc + 1) as usize]); + } + self.inc_pc(); + match self.pop() { + None => { + return Err("Pop: Empty Stack") + }, + Some(i) => { + let addr = self.readmem(self.pc).unwrap(); + self.write(addr, i)?; + self.inc_pc(); + }, + } + }, + 4|5 => { //eq : set to 1 if is equal to ; set it to 0 otherwise + if DEBUG { //gt : set to 1 if is greater than ; set it to 0 otherwise + println!("{}: comp_op {} {} {}", self.pc, self.mem[(self.pc + 1) as usize], self.mem[(self.pc + 2) as usize], self.mem[(self.pc + 3) as usize]); + } + let op:u16 = self.readmem(self.pc).unwrap() - 4; + self.inc_pc(); + let resaddr = self.readmem(self.pc).unwrap(); + self.inc_pc(); + let a = self.read(self.readmem(self.pc).unwrap()).unwrap(); + self.inc_pc(); + let b = self.read(self.readmem(self.pc).unwrap()).unwrap(); + self.alu.set_input(a, b); + self.alu.set_op(op); //alu eq|gt + self.alu.execute(); + let res = self.alu.get_res(); + self.write(resaddr, res)?; + self.inc_pc(); + }, + 6 => { //jmp : jump to + if DEBUG { + println!("{}: jmp {}", self.pc, self.mem[(self.pc + 1) as usize]); + } + self.inc_pc(); + let target = self.readmem(self.pc).unwrap(); + self.jump(target)?; + }, + 7 => { //jt : if is nonzero, jump to + if DEBUG { + println!("{}: jt {} {}", self.pc, self.mem[(self.pc + 1) as usize], self.mem[(self.pc + 2) as usize]); + } + self.inc_pc(); + let a = self.read(self.readmem(self.pc).unwrap()).unwrap(); + self.alu.set_input(a, 0); + self.alu.set_op(0); //alu op: eq + self.alu.execute(); + self.inc_pc(); + let target = self.read(self.readmem(self.pc).unwrap()).unwrap(); + match self.alu.get_res() { + 0 => { + self.jump(target)?; + }, + _ => { + self.inc_pc(); + }, + } + }, + 8 => { //jf : if is zero, jump to + if DEBUG { + println!("{}: jf {} {}", self.pc, self.mem[(self.pc + 1) as usize], self.mem[(self.pc + 2) as usize]); + } + self.inc_pc(); + let a = self.read(self.readmem(self.pc).unwrap()).unwrap(); + self.alu.set_input(a, 0); + self.alu.set_op(0); //alu op: eq + self.alu.execute(); + self.inc_pc(); + let target = self.read(self.readmem(self.pc).unwrap()).unwrap(); + match self.alu.get_res() { + 0 => { + self.inc_pc(); + }, + _ => { + self.jump(target)?; + }, + } + }, + 9...13 => { //aluop : compute result in alu with = op + if DEBUG { + println!("{}: aluop {} {} {}", self.pc, self.mem[(self.pc + 1) as usize], self.mem[(self.pc + 2) as usize], self.mem[(self.pc + 3) as usize]); + } + let op:u16 = self.readmem(self.pc).unwrap() - 7; + self.inc_pc(); + let resaddr = self.readmem(self.pc).unwrap(); + self.inc_pc(); + let a = self.read(self.readmem(self.pc).unwrap()).unwrap(); + self.inc_pc(); + let b = self.read(self.readmem(self.pc).unwrap()).unwrap(); + self.alu.set_input(a, b); + self.alu.set_op(op); //alu add|mult|mod|and|or + self.alu.execute(); + let res = self.alu.get_res(); + self.write(resaddr, res)?; + self.inc_pc(); + }, + 14 => { //not : stores 15-bit bitwise inverse of in + if DEBUG { + println!("{}: not {} {}", self.pc, self.mem[(self.pc + 1) as usize], self.mem[(self.pc + 2) as usize]); + } + self.inc_pc(); + let resaddr = self.readmem(self.pc).unwrap(); + self.inc_pc(); + let a = self.read(self.readmem(self.pc).unwrap()).unwrap(); + self.alu.set_input(a, 0); + self.alu.set_op(7); //alu op: not + self.alu.execute(); + let res = self.alu.get_res(); + self.write(resaddr, res)?; + self.inc_pc(); + }, + 15 => { //rmem : read memory at address and write it to + if DEBUG { + println!("{}: rmem {} {}", self.pc, self.mem[(self.pc + 1) as usize], self.mem[(self.pc + 2) as usize]); + } + self.inc_pc(); + let resaddr = self.readmem(self.pc).unwrap(); + self.inc_pc(); + let result = self.readmem(self.readmem(self.pc).unwrap()).unwrap(); + self.write(resaddr, result)?; + self.inc_pc(); + }, + 16 => { //wmem : write the value from into memory at address + if DEBUG { + println!("{}: wmem {} {}", self.pc, self.mem[(self.pc + 1) as usize], self.mem[(self.pc + 2) as usize]); + } + self.inc_pc(); + let resaddr = self.readmem(self.pc).unwrap(); + self.inc_pc(); + let result = self.read(self.readmem(self.pc).unwrap()).unwrap(); + self.writemem(resaddr, result)?; + self.inc_pc(); + }, + 17 => { //call : write the address of the next instruction to the stack and jump to + if DEBUG { + println!("{}: call {}", self.pc, self.mem[(self.pc + 1) as usize]); + } + self.inc_pc(); + let target = self.read(self.readmem(self.pc).unwrap()).unwrap(); + self.inc_pc(); + let pc = self.pc; + self.push(pc); + self.jump(target)?; + }, + 18 => { //ret: remove the top element from the stack and jump to it; empty stack = halt + if DEBUG { + println!("{}: ret", self.pc); + } + match self.pop() { + None => { + running = false; + }, + Some(target) => { + self.jump(target)?; + }, + } + }, + 19 => { //out : write the character represented by ascii code to the terminal + if DEBUG { + println!("{}: out {}", self.pc, self.mem[(self.pc + 1) as usize]); + } + self.inc_pc(); + let c : char = self.read(self.readmem(self.pc).unwrap()).unwrap() as u8 as char; + print!("{}", c); + self.inc_pc(); + }, + 20 => { //in : read a character from the terminal and write its ascii code to ; it can be assumed that once input starts, it will continue until a newline is encountered; this means that you can safely read whole lines from the keyboard and trust that they will be fully read + if DEBUG { + println!("{}: in {}", self.pc, self.mem[(self.pc + 1) as usize]); + } + running = false; + }, + 21 => { //noop: no operation + if DEBUG { + println!("{}: noop", self.pc); + } + self.inc_pc(); + }, + _ => { //invalid + if DEBUG { + println!("{}: {} (invalid)", self.pc, self.mem[self.pc as usize]); + } + return Err("Invalid Instruction"); + } + } + } + } + return Ok(()); + } + + fn read(&self, val: u16) -> Option { + match val { + 0...32767 => Some(val), + 32768...32775 => Some(self.reg[(val - 32768) as usize]), + _ => None + } + } + + fn readmem(&self, addr: u16) -> Option { + match self.read(addr) { + Some(address) => { + match address { + 0...32767 => Some(self.mem[address as usize]), + _ => None + } + }, + None => None + } + } + + fn pop(&mut self) -> Option { + self.stack.pop() + } + + fn write(&mut self, addr: u16, val: u16) -> Result<(), &'static str> { + match addr { + 32768...32775 => { + self.reg[(addr - 32768) as usize] = val; + Ok(()) + } + _ => Err("Write: Invalid register") + } + } + + fn writemem(&mut self, addr: u16, val: u16) -> Result<(), &'static str> { + match self.read(addr) { + Some(address) => { + match address { + 0...32767 => { + self.mem[address as usize] = val; + Ok(()) + }, + _ => Err("Write: Invalid address") + } + }, + None => Err("Write: Invalid address") + } + } + + fn push(&mut self, val: u16) { + self.stack.push(val); + } + + fn jump(&mut self, target: u16) -> Result<(), &'static str> { + match target { + 0...32767 => { + self.pc = target; + Ok(()) + }, + _ => Err("Jump: Invalid address") + } + } + + fn inc_pc(&mut self) { + self.pc += 1; + self.pc %= 32768; + } +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index f0ae0d8..15f6f7b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,13 +1,15 @@ -use std::fmt; -use std::ops::*; +mod cpu; +mod alu; -const debug: bool = true; +use cpu::Cpu; +use alu::Alu; + +pub const DEBUG: bool = true; fn main() { let mut cpu = Cpu::new(); - let program:Vec = vec![9,32768,32769,'a' as u16,19,32768]; - cpu.write_program(program); - let mut result = cpu.execute(); + cpu.read_program_from_file("challenge.bin"); + let result = cpu.execute(); if result.is_ok() { println!("Execution successful!"); } else { @@ -15,475 +17,3 @@ fn main() { } } -pub struct Cpu { - stack: Vec, - mem: Vec, - reg: Vec, - pc: Number, - alu: Alu, -} - -impl fmt::Debug for Cpu { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "Cpu {{ pc = {}, ", self.pc.value)?; - write!(f, "reg = ")?; - for i in 0 .. 7 { - write!(f, "[{}]: {}, ", i, self.reg[i]); - } - write!(f, "stack = ")?; - for i in 0 .. self.stack.len() { - write!(f, "[{}]: {}, ", i, self.stack[i])?; - } - for i in 0 .. self.mem.len() { - write!(f, "[{}]: {}, ", i, self.mem[i])?; - } - write!(f, "}}")?; - Ok(()) - } -} - -impl Cpu { - pub fn new() -> Cpu { - Cpu { - stack: Vec::new(), - mem: vec![0; 32768], - reg: vec![0; 8], - pc: Number::new(), - alu: Alu::new(), - } - } - - pub fn write_program(&mut self, prog: Vec) { - self.pc.value = 0; - for i in prog { - self.mem[self.pc.value as usize] = i; - self.pc.inc(); - } - self.pc.value = 0; - } - - pub fn execute(&mut self) -> Result<&'static str, &'static str>{ - let mut running = true; - let mut err = 0; - if self.mem.is_empty() { - running = false; - err = 2; - } - while running { - match self.read(self.pc.value).unwrap() { - 0 => { //halt: stop execution and terminate the program - if debug { - println!("{}: halt", self.pc); - } - running = false; - }, - 1 => { //set : set register to the value of - if debug { - println!("{}: set {} {}", self.pc, self.mem[(self.pc.value + 1) as usize], self.mem[(self.pc.value + 2) as usize]); - } - self.pc.inc(); - let reg = self.mem[(self.pc.value) as usize]; - self.pc.inc(); - let val = self.read(self.pc.value).unwrap(); - self.write(reg + 32768, val); - self.pc.inc(); - }, - 2 => { //push : push onto the stack - if debug { - println!("{}: push {}", self.pc, self.mem[(self.pc.value + 1) as usize]); - } - self.pc.inc(); - let val = self.read(self.pc.value).unwrap(); - self.stack.push(val); - self.pc.inc(); - }, - 3 => { //pop : remove the top element from the stack and write it into ; empty stack = error - if debug { - println!("{}: pop {}", self.pc, self.mem[(self.pc.value + 1) as usize]); - } - self.pc.inc(); - match self.stack.pop() { - None => { - running = false; - err = 1; - }, - Some(i) => { - let addr = self.read(self.pc.value).unwrap(); - self.write(addr, i); - self.pc.inc(); - }, - } - }, - 4 => { //eq : set to 1 if is equal to ; set it to 0 otherwise - if debug { - println!("{}: eq {} {} {}", self.pc, self.mem[(self.pc.value + 1) as usize], self.mem[(self.pc.value + 2) as usize], self.mem[(self.pc.value + 3) as usize]); - } - self.pc.inc(); - let resaddr = self.read(self.pc.value).unwrap(); - self.pc.inc(); - self.alu.a.value = self.read(self.pc.value).unwrap(); - self.pc.inc(); - self.alu.b.value = self.read(self.pc.value).unwrap(); - self.alu.op = 0; //alu eq - self.alu.execute(); - let result = self.alu.c.value; - self.write(resaddr, result); - self.pc.inc(); - }, - 5 => { //gt : set to 1 if is greater than ; set it to 0 otherwise - if debug { - println!("{}: gt {} {} {}", self.pc, self.mem[(self.pc.value + 1) as usize], self.mem[(self.pc.value + 2) as usize], self.mem[(self.pc.value + 3) as usize]); - } - self.pc.inc(); - let resaddr = self.read(self.pc.value).unwrap(); - self.pc.inc(); - self.alu.a.value = self.read(self.pc.value).unwrap(); - self.pc.inc(); - self.alu.b.value = self.read(self.pc.value).unwrap(); - self.alu.op = 1; //alu gt - self.alu.execute(); - let result = self.alu.c.value; - self.write(resaddr, result); - self.pc.inc(); - }, - 6 => { //jmp : jump to - if debug { - println!("{}: jmp {}", self.pc, self.mem[(self.pc.value + 1) as usize]); - } - self.pc.inc(); - let target = self.read(self.pc.value).unwrap(); - self.jump(target); - }, - 7 => { //jt : if is nonzero, jump to - if debug { - println!("{}: jt {} {}", self.pc, self.mem[(self.pc.value + 1) as usize], self.mem[(self.pc.value + 2) as usize]); - } - self.pc.inc(); - self.alu.a.value = self.read(self.pc.value).unwrap(); - self.alu.b.value = 0; - self.alu.op = 0; //alu op: eq - self.alu.execute(); - self.pc.inc(); - let target = self.read(self.pc.value).unwrap(); - match self.alu.c.value { - 0 => {self.jump(target);}, - _ => {self.pc.inc();}, - } - }, - 8 => { //jf : if is zero, jump to - if debug { - println!("{}: jf {} {}", self.pc, self.mem[(self.pc.value + 1) as usize], self.mem[(self.pc.value + 2) as usize]); - } - self.pc.inc(); - self.alu.a.value = self.read(self.pc.value).unwrap(); - self.alu.b.value = 0; - self.alu.op = 0; //alu op: eq - self.alu.execute(); - self.pc.inc(); - let target = self.read(self.pc.value).unwrap(); - match self.alu.c.value { - 0 => {self.pc.inc();}, - _ => {self.jump(target);}, - } - }, - 9...13 => { //aluop : compute result in alu with = op - if debug { - println!("{}: aluop {} {} {}", self.pc, self.mem[(self.pc.value + 1) as usize], self.mem[(self.pc.value + 2) as usize], self.mem[(self.pc.value + 3) as usize]); - } - self.alu.op = self.read(self.pc.value).unwrap() - 7; //alu ops: 2...6 - self.pc.inc(); - let resaddr = self.read(self.pc.value).unwrap(); - self.pc.inc(); - self.alu.a.value = self.read(self.pc.value).unwrap(); - self.pc.inc(); - self.alu.b.value = self.read(self.pc.value).unwrap(); - self.alu.execute(); - let result = self.alu.c.value; - self.write(resaddr, result); - self.pc.inc(); - }, - 14 => { //not : stores 15-bit bitwise inverse of in - if debug { - println!("{}: not {} {}", self.pc, self.mem[(self.pc.value + 1) as usize], self.mem[(self.pc.value + 2) as usize]); - } - self.pc.inc(); - let resaddr = self.read(self.pc.value).unwrap(); - self.pc.inc(); - self.alu.a.value = self.read(self.pc.value).unwrap(); - self.alu.op = 7; //alu op: not - self.alu.execute(); - let result = self.alu.c.value; - self.write(resaddr, result); - self.pc.inc(); - }, - 15 => { //rmem : read memory at address and write it to - if debug { - println!("{}: rmem {} {}", self.pc, self.mem[(self.pc.value + 1) as usize], self.mem[(self.pc.value + 2) as usize]); - } - self.pc.inc(); - let resaddr = self.read(self.pc.value).unwrap(); - self.pc.inc(); - let result = self.read(self.read(self.pc.value).unwrap()).unwrap(); - self.write(resaddr, result); - self.pc.inc(); - }, - 16 => { //wmem : write the value from into memory at address - if debug { - println!("{}: wmem {} {}", self.pc, self.mem[(self.pc.value + 1) as usize], self.mem[(self.pc.value + 2) as usize]); - } - self.pc.inc(); - let resaddr = self.read(self.pc.value).unwrap(); - self.pc.inc(); - let result = self.read(self.read(self.pc.value).unwrap()).unwrap(); - self.write(resaddr, result); - self.pc.inc(); - }, - 17 => { //call : write the address of the next instruction to the stack and jump to - if debug { - println!("{}: call {}", self.pc, self.mem[(self.pc.value + 1) as usize]); - } - self.pc.inc(); - let target = self.read(self.pc.value).unwrap(); - self.pc.inc(); - self.stack.push(self.pc.value); - self.jump(target); - }, - 18 => { //ret: remove the top element from the stack and jump to it; empty stack = halt - if debug { - println!("{}: ret", self.pc); - } - match self.stack.pop() { - None => { - running = false; - }, - Some(target) => { - self.jump(target); - }, - } - }, - 19 => { //out : write the character represented by ascii code to the terminal - if debug { - println!("{}: out {}", self.pc, self.mem[(self.pc.value + 1) as usize]); - } - self.pc += Number{value: 1}; - let addr = self.read(self.pc.value).unwrap(); - let c:char = self.read(addr).unwrap() as u8 as char; - print!("{}", c); - self.pc += Number{value: 1}; - }, - 20 => { //in : read a character from the terminal and write its ascii code to ; it can be assumed that once input starts, it will continue until a newline is encountered; this means that you can safely read whole lines from the keyboard and trust that they will be fully read - if debug { - println!("{}: in {}", self.pc, self.mem[(self.pc.value + 1) as usize]); - } - running = false; - }, - 21 => { //noop: no operation - if debug { - println!("{}: noop", self.pc); - } - self.pc += Number{value: 1} - }, - _ => { //invalid - if debug { - println!("{}: invalid", self.pc); - } - err = 3; - running = false; - } - } - } - match err { - 0 => Ok("Execution successful"), - 1 => Err("Stack Empty"), - 2 => Err("No Program"), - 3 => Err("Invalid Instruction"), - _ => Err("Unknown Error"), - } - } - - fn read(&self, address: u16) -> Option { - match address { - 0...32767 => Some(self.mem[address as usize]), - 32768...32775 => Some(self.mem[(address -32768) as usize]), - _ => None - } - } - - fn write(&mut self, address: u16, val: u16) -> Result { - match address { - 0...32767 => { - self.mem[address as usize] = val; - Ok(val) - }, - 32768...32775 => { - self.mem[(address - 32768) as usize] = val; - Ok(val) - } - _ => Err("Write: Invalid address") - } - } - - fn jump(&mut self, target: u16) -> Result { - match target { - 0...32767 => { - self.pc.value = target; - Ok(target) - }, - _ => Err("Jump: Invalid address") - } - } -} - -struct Alu { - op: u16, - a: Number, - b: Number, - c: Number, -} - -impl Alu { - fn new() -> Alu { - Alu { - op: 0, - a: Number {value: 0}, - b: Number {value: 0}, - c: Number {value: 0}, - } - } - fn execute(&mut self) { - match self.op { - 0 => self.c = Number { //eq - value: match self.a.value == self.b.value { - true => 1, - false => 0, - } - }, - 1 => self.c = Number { //gt - value: match self.a.value > self.b.value { - true => 1, - false => 0, - } - }, - 2 => self.c = self.a + self.b, //add - 3 => self.c = self.a * self.b, //mult - 4 => self.c = self.a % self.b, //mod - 5 => self.c = self.a & self.b, //and - 6 => self.c = self.a | self.b, //or - 7 => self.c = !self.a, //not - _ => self.c = self.a, //other - } - } -} - -//15Bit numbers for the ALU -#[derive(Copy, Clone, Debug)] -struct Number { - value: u16, -} - -//Operator Overloading - Div not needed since it works without modification. -impl Add for Number { - type Output = Number; - fn add(self, other: Number) -> Number { - Number { - value: (self.value + other.value) % 32768, - } - } -} - -impl AddAssign for Number { - fn add_assign(&mut self, other: Number) { - self.value += other.value; - self.value %= 32768; - } -} - -impl Sub for Number { - type Output = Number; - fn sub(self, other: Number) -> Number { - Number { - value: (self.value - other.value) % 32768, - } - } -} - -impl Mul for Number { - type Output = Number; - fn mul(self, other: Number) -> Number { - Number { - value: (self.value * other.value) % 32768, - } - } -} - -impl Rem for Number { - type Output = Number; - fn rem(self, other: Number) -> Number { - Number { - value: (self.value % other.value), - } - } -} - -impl BitOr for Number { - type Output = Number; - fn bitor(self, other: Number) -> Number { - Number { - value: (self.value | other.value), - } - } -} - -impl BitAnd for Number { - type Output = Number; - fn bitand(self, other: Number) -> Number { - Number { - value: (self.value & other.value), - } - } -} - -impl Not for Number { - type Output = Number; - fn not(self) -> Number { - Number { - value: (!self.value) & 0x7FFF, - } - } -} - -impl fmt::Display for Number { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.value) - } -} - -impl Number { - //little Endian -> memory management - fn new() -> Number { - Number { - value: 0, - } - } - fn inc(&mut self) { - self.value += 1; - } -} - -#[cfg(test)] -mod tests { - use super::*; - #[test] - fn nop_out_halt() { - let mut cpu = Cpu::new(); - let program: Vec = vec![21, 21, 19, 5, 0, 'a' as u16]; - cpu.write_program(program); - let mut result = cpu.execute(); - if result.is_ok() { - println!("Execution successful!"); - } else { - println!("Err: {}", result.err().unwrap()) - } - assert!(result.is_ok()); - } -} diff --git a/src/tests.rs b/src/tests.rs new file mode 100644 index 0000000..d30d414 --- /dev/null +++ b/src/tests.rs @@ -0,0 +1,16 @@ + +use super::*; + +#[test] +fn nop_out_halt() { + let mut cpu = Cpu::new(); + let program: Vec = vec![21, 21, 19, 5, 0, 'a' as u16]; + cpu.write_program(program); + let mut result = cpu.execute(); + if result.is_ok() { + println!("Execution successful!"); + } else { + println!("Err: {}", result.err().unwrap()) + } + assert!(result.is_ok()); +}