Browse Source

self test running except instruction "in"

master
Michael Preisach 8 years ago
parent
commit
2dde5a8fca
  1. 51
      src/alu.rs
  2. 370
      src/cpu.rs
  3. 486
      src/main.rs
  4. 16
      src/tests.rs

51
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);
}
}
}

370
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<u16>,
mem: Vec<u16>,
reg: Vec<u16>,
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<u16>) {
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<u8> = 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 <a> <b>: set register <a> to the value of <b>
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 <a>: push <a> 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 <a>: remove the top element from the stack and write it into <a>; 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 <a> <b> <c>: set <a> to 1 if <b> is equal to <c>; set it to 0 otherwise
if DEBUG { //gt <a> <b> <c>: set <a> to 1 if <b> is greater than <c>; 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 <a>: jump to <a>
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 <a> <b>: if <a> is nonzero, jump to <b>
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 <a> <b>: if <a> is zero, jump to <b>
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 <a> <b> <c>: compute result in alu with <a> = <b> op <c>
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 <a> <b>: stores 15-bit bitwise inverse of <b> in <a>
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 <a> <b>: read memory at address <b> and write it to <a>
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 <a> <b>: write the value from <b> into memory at address <a>
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 <a>: write the address of the next instruction to the stack and jump to <a>
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 <a>: write the character represented by ascii code <a> 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 <a>: read a character from the terminal and write its ascii code to <a>; 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<u16> {
match val {
0...32767 => Some(val),
32768...32775 => Some(self.reg[(val - 32768) as usize]),
_ => None
}
}
fn readmem(&self, addr: u16) -> Option<u16> {
match self.read(addr) {
Some(address) => {
match address {
0...32767 => Some(self.mem[address as usize]),
_ => None
}
},
None => None
}
}
fn pop(&mut self) -> Option<u16> {
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;
}
}

486
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<u16> = 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<u16>,
mem: Vec<u16>,
reg: Vec<u16>,
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<u16>) {
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 <a> <b>: set register <a> to the value of <b>
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 <a>: push <a> 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 <a>: remove the top element from the stack and write it into <a>; 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 <a> <b> <c>: set <a> to 1 if <b> is equal to <c>; 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 <a> <b> <c>: set <a> to 1 if <b> is greater than <c>; 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 <a>: jump to <a>
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 <a> <b>: if <a> is nonzero, jump to <b>
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 <a> <b>: if <a> is zero, jump to <b>
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 <a> <b> <c>: compute result in alu with <a> = <b> op <c>
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 <a> <b>: stores 15-bit bitwise inverse of <b> in <a>
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 <a> <b>: read memory at address <b> and write it to <a>
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 <a> <b>: write the value from <b> into memory at address <a>
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 <a>: write the address of the next instruction to the stack and jump to <a>
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 <a>: write the character represented by ascii code <a> 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 <a>: read a character from the terminal and write its ascii code to <a>; 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<u16> {
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<u16, &'static str> {
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<u16, &'static str> {
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<u16> = 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());
}
}

16
src/tests.rs

@ -0,0 +1,16 @@
use super::*;
#[test]
fn nop_out_halt() {
let mut cpu = Cpu::new();
let program: Vec<u16> = 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());
}
Loading…
Cancel
Save