Compare commits
4 Commits
1ea7908fca
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7365bda40a | ||
|
|
c9dafbcb72 | ||
|
|
8d48c4bc89 | ||
|
|
35b0b5972f |
@@ -1,5 +1,5 @@
|
|||||||
extern crate um;
|
extern crate um;
|
||||||
use um::cpu::{Cpu};
|
use um::cpu::{Cpu,Console};
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
@@ -9,8 +9,44 @@ use clap::Parser;
|
|||||||
/// Run a um program
|
/// Run a um program
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
struct Cli {
|
struct Cli {
|
||||||
|
// debug level
|
||||||
|
#[clap(short, long, default_value_t = 0)]
|
||||||
|
debug: u32,
|
||||||
/// The path to the program to load
|
/// The path to the program to load
|
||||||
program: std::path::PathBuf,
|
program: std::path::PathBuf
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
struct IoConsole {
|
||||||
|
inptr: usize,
|
||||||
|
inbuf: String
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IoConsole {
|
||||||
|
pub fn make() -> IoConsole {
|
||||||
|
IoConsole {
|
||||||
|
inptr: 0,
|
||||||
|
inbuf: String::from("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Console for IoConsole {
|
||||||
|
fn read(&mut self) -> Option<u8> {
|
||||||
|
if self.inptr >= self.inbuf.len() {
|
||||||
|
if let Err(_) = std::io::stdin().read_line(&mut self.inbuf) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let r = self.inbuf.bytes().nth(self.inptr).unwrap();
|
||||||
|
self.inptr +=1;
|
||||||
|
Some(r)
|
||||||
|
}
|
||||||
|
fn write(&mut self, c: u8) {
|
||||||
|
let buf = [c;1];
|
||||||
|
let _ = std::io::stdout().write(&buf);
|
||||||
|
let _ = std::io::stdout().flush();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -36,21 +72,11 @@ fn main() -> io::Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut c = Cpu::new(pgm);
|
let mut c = Cpu::new(pgm);
|
||||||
cont = true;
|
c.set_debug(args.debug);
|
||||||
println!("start\n{}", c.state());
|
let mut cons = IoConsole::make();
|
||||||
while cont {
|
match c.run(&mut cons) {
|
||||||
let r = c.step();
|
Err(e) => println!("Error {:?}", e),
|
||||||
cont = match r {
|
Ok(_) => ()
|
||||||
Ok(_) => {
|
|
||||||
println!("ok\n{}", c.state());
|
|
||||||
true
|
|
||||||
},
|
|
||||||
Err(e) => {
|
|
||||||
println!("Error {:?}", e);
|
|
||||||
false
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
||||||
}
|
}
|
||||||
366
src/cpu.rs
366
src/cpu.rs
@@ -3,35 +3,32 @@ use std::vec::Vec;
|
|||||||
use crate::instruction::{Instruction, NormalInstruction, SpecialInstruction};
|
use crate::instruction::{Instruction, NormalInstruction, SpecialInstruction};
|
||||||
|
|
||||||
pub trait Console {
|
pub trait Console {
|
||||||
fn read(&self) -> Option<u8>;
|
fn read(&mut self) -> Option<u8>;
|
||||||
fn write(&mut self, c: u8);
|
fn write(&mut self, c: u8);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct NoConsole;
|
|
||||||
|
|
||||||
impl Console for NoConsole {
|
|
||||||
fn read(&self) -> Option<u8> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
fn write(&mut self, _c: u8) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum CpuError {
|
pub enum CpuError {
|
||||||
ProgramEnd,
|
ProgramEnd,
|
||||||
InvalidInstruction,
|
InvalidInstruction,
|
||||||
UnexpectedInput,
|
UnexpectedInput,
|
||||||
InvalidArray,
|
InvalidArray,
|
||||||
ArrayOutOfBounds
|
ArrayOutOfBounds,
|
||||||
|
DivideByZero,
|
||||||
|
Halt,
|
||||||
|
LargeAlloc,
|
||||||
|
InvalidOutput
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Cpu {
|
pub struct Cpu {
|
||||||
reg: [u32; 8],
|
reg: [u32; 8],
|
||||||
arr: HashMap<u32, Vec<u32>>,
|
arr: HashMap<u32, Vec<u32>>,
|
||||||
|
iarr: u32,
|
||||||
finger: u32,
|
finger: u32,
|
||||||
out: Option<u8>,
|
out: Option<u8>,
|
||||||
in_reg: Option<u8>
|
in_reg: Option<u8>,
|
||||||
|
debug: u32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -42,12 +39,17 @@ impl Cpu {
|
|||||||
Cpu {
|
Cpu {
|
||||||
reg: [0;8],
|
reg: [0;8],
|
||||||
arr: arrays,
|
arr: arrays,
|
||||||
|
iarr: 1,
|
||||||
finger: 0,
|
finger: 0,
|
||||||
in_reg: None,
|
in_reg: None,
|
||||||
out: None
|
out: None,
|
||||||
|
debug: 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_debug(&mut self, debug: u32) {
|
||||||
|
self.debug = debug;
|
||||||
|
}
|
||||||
fn gr(&self, r: u8) -> u32{
|
fn gr(&self, r: u8) -> u32{
|
||||||
self.reg[r as usize]
|
self.reg[r as usize]
|
||||||
}
|
}
|
||||||
@@ -130,7 +132,7 @@ impl Cpu {
|
|||||||
let aidx = self.gr(i.a);
|
let aidx = self.gr(i.a);
|
||||||
let aoff = self.gr(i.b) as usize;
|
let aoff = self.gr(i.b) as usize;
|
||||||
let v = self.gr(i.c);
|
let v = self.gr(i.c);
|
||||||
|
// println!("amd {}[{}]={}", aidx, aoff, v);
|
||||||
if let Some(arr) = self.arr.get_mut(&aidx){
|
if let Some(arr) = self.arr.get_mut(&aidx){
|
||||||
if arr.len() > aoff {
|
if arr.len() > aoff {
|
||||||
arr[aoff] = v;
|
arr[aoff] = v;
|
||||||
@@ -159,6 +161,85 @@ impl Cpu {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_div(&mut self, i:NormalInstruction) -> Result<(), CpuError>{
|
||||||
|
let b = self.gr(i.b);
|
||||||
|
let c = self.gr(i.c);
|
||||||
|
if c == 0 {
|
||||||
|
return Err(CpuError::DivideByZero);
|
||||||
|
}
|
||||||
|
let (a, _) = b.overflowing_div(c);
|
||||||
|
self.sr(i.a, a);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_nand(&mut self, i:NormalInstruction) -> Result<(), CpuError>{
|
||||||
|
let b = self.gr(i.b);
|
||||||
|
let c = self.gr(i.c);
|
||||||
|
let a = !(b & c);
|
||||||
|
self.sr(i.a, a);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_halt(&mut self, _i:NormalInstruction) -> Result<(), CpuError>{
|
||||||
|
Err(CpuError::Halt)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_alc(&mut self, i:NormalInstruction) -> Result<(), CpuError>{
|
||||||
|
let c = self.gr(i.c) as usize;
|
||||||
|
if c > 1048576 {
|
||||||
|
return Err(CpuError::LargeAlloc);
|
||||||
|
}
|
||||||
|
let aid = self.iarr;
|
||||||
|
self.iarr += 1;
|
||||||
|
let v = vec![0; c];
|
||||||
|
self.arr.insert(aid, v);
|
||||||
|
self.sr(i.b, aid);
|
||||||
|
//println!("alc {} -> {}", c, aid);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_abn(&mut self, i:NormalInstruction) -> Result<(), CpuError>{
|
||||||
|
let c = self.gr(i.c);
|
||||||
|
if c == 0 || ! self.arr.contains_key(&c){
|
||||||
|
return Err(CpuError::InvalidArray);
|
||||||
|
}
|
||||||
|
self.arr.remove(&c);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn handle_out(&mut self, i:NormalInstruction) -> Result<(), CpuError>{
|
||||||
|
let c = self.gr(i.c);
|
||||||
|
if c > 255 {
|
||||||
|
return Err(CpuError::InvalidOutput);
|
||||||
|
}
|
||||||
|
self.out = Some(c as u8);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_inp(&mut self, i:NormalInstruction) -> Result<(), CpuError>{
|
||||||
|
self.sr(i.c, 0xffffffff);
|
||||||
|
self.in_reg = Some(i.c);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_lod(&mut self, i:NormalInstruction) -> Result<(), CpuError>{
|
||||||
|
let aidx = self.gr(i.b);
|
||||||
|
let aoff = self.gr(i.c);
|
||||||
|
if let Some(arr) = self.arr.get(&aidx){
|
||||||
|
if arr.len() > (aoff as usize) {
|
||||||
|
if aidx > 0 {
|
||||||
|
// println!("cloning {}", aidx);
|
||||||
|
self.arr.insert(0, arr.clone());
|
||||||
|
}
|
||||||
|
self.finger = aoff;
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(CpuError::ArrayOutOfBounds)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(CpuError::InvalidArray)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn exec(&mut self, instruction: Instruction)-> Result<(), CpuError>{
|
fn exec(&mut self, instruction: Instruction)-> Result<(), CpuError>{
|
||||||
//println!("{:?}", instruction);
|
//println!("{:?}", instruction);
|
||||||
match instruction {
|
match instruction {
|
||||||
@@ -168,7 +249,15 @@ impl Cpu {
|
|||||||
Instruction::ArrayAmend(i) => self.handle_amd(i),
|
Instruction::ArrayAmend(i) => self.handle_amd(i),
|
||||||
Instruction::Add(i) => self.handle_add(i),
|
Instruction::Add(i) => self.handle_add(i),
|
||||||
Instruction::Multiply(i) => self.handle_mul(i),
|
Instruction::Multiply(i) => self.handle_mul(i),
|
||||||
_ => Err(CpuError::InvalidInstruction)
|
Instruction::Divide(i) => self.handle_div(i),
|
||||||
|
Instruction::NotAnd(i) => self.handle_nand(i),
|
||||||
|
Instruction::Halt(i) => self.handle_halt(i),
|
||||||
|
Instruction::Allocate(i) => self.handle_alc(i),
|
||||||
|
Instruction::Abandon(i) => self.handle_abn(i),
|
||||||
|
Instruction::Output(i) => self.handle_out(i),
|
||||||
|
Instruction::Input(i) => self.handle_inp(i),
|
||||||
|
Instruction::Load(i) => self.handle_lod(i),
|
||||||
|
//_ => Err(CpuError::InvalidInstruction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,14 +265,19 @@ impl Cpu {
|
|||||||
self.out = None;
|
self.out = None;
|
||||||
self.in_reg = None;
|
self.in_reg = None;
|
||||||
let i = self.ins()?;
|
let i = self.ins()?;
|
||||||
self.exec(i)?;
|
|
||||||
self.finger += 1;
|
self.finger += 1;
|
||||||
|
self.exec(i)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(&mut self, console: &mut impl Console) -> Result<(), CpuError> {
|
pub fn run(&mut self, console: &mut impl Console) -> Result<(), CpuError> {
|
||||||
let mut cont = true;
|
let mut cont = true;
|
||||||
|
|
||||||
while cont {
|
while cont {
|
||||||
|
if self.debug > 5 {
|
||||||
|
println!("{:?}", self.ins());
|
||||||
|
println!("{}", self.state());
|
||||||
|
}
|
||||||
cont = match self.step() {
|
cont = match self.step() {
|
||||||
Ok(_) => true,
|
Ok(_) => true,
|
||||||
Err(CpuError::ProgramEnd) => false,
|
Err(CpuError::ProgramEnd) => false,
|
||||||
@@ -207,6 +301,45 @@ impl Cpu {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests{
|
mod tests{
|
||||||
use super::*;
|
use super::*;
|
||||||
|
struct NoConsole;
|
||||||
|
|
||||||
|
impl Console for NoConsole {
|
||||||
|
fn read(&mut self) -> Option<u8> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
fn write(&mut self, _c: u8) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct BufConsole {
|
||||||
|
inb: Vec<u8>,
|
||||||
|
inptr: usize,
|
||||||
|
outb: Vec<u8>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BufConsole {
|
||||||
|
fn make() -> BufConsole {
|
||||||
|
BufConsole {
|
||||||
|
inb: vec![],
|
||||||
|
inptr: 0,
|
||||||
|
outb: vec![]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Console for BufConsole {
|
||||||
|
fn read(&mut self) -> Option<u8> {
|
||||||
|
if self.inptr >= self.inb.len() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let r = self.inb[self.inptr];
|
||||||
|
self.inptr += 1;
|
||||||
|
Some(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn write(&mut self, c: u8) {
|
||||||
|
self.outb.push(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn ezop(op:u32, a:u32, b:u32, c:u32) -> u32 {
|
fn ezop(op:u32, a:u32, b:u32, c:u32) -> u32 {
|
||||||
match op {
|
match op {
|
||||||
@@ -317,7 +450,7 @@ mod tests{
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_amd_nooff() -> Result<(), String> {
|
fn test_amd_nooff() -> Result<(), String> {
|
||||||
let pgm = vec!( ezop(2, 1, 2, 3) );
|
let pgm = vec!( ezop(2, 1, 2, 3) );
|
||||||
let mut c = Cpu::new(pgm);
|
let mut c = Cpu::new(pgm);
|
||||||
@@ -373,4 +506,203 @@ mod tests{
|
|||||||
assert_eq!(c.reg, exp);
|
assert_eq!(c.reg, exp);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_div() -> Result<(), CpuError> {
|
||||||
|
let pgm = vec!( ezop(5, 1, 2, 3) );
|
||||||
|
let mut c = Cpu::new(pgm);
|
||||||
|
c.reg = [0, 0, 2048, 1024, 0, 0, 0, 0];
|
||||||
|
c.run(&mut NoConsole{})?;
|
||||||
|
let exp = [0, 2, 2048, 1024, 0, 0, 0, 0];
|
||||||
|
assert_eq!(c.reg, exp);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_div_zero() -> Result<(), String> {
|
||||||
|
let pgm = vec!( ezop(5, 1, 2, 3) );
|
||||||
|
let mut c = Cpu::new(pgm);
|
||||||
|
c.reg = [0, 1338, 3, 0, 0, 0, 0, 0];
|
||||||
|
match c.run(&mut NoConsole{}) {
|
||||||
|
Err(CpuError::DivideByZero) => Ok(()),
|
||||||
|
Err(_) => Err(String::from("Invalid error")),
|
||||||
|
Ok(_) => Err(String::from("Expected err got ok"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_nand() -> Result<(), CpuError> {
|
||||||
|
let pgm = vec!( ezop(6, 1, 2, 3) );
|
||||||
|
let mut c = Cpu::new(pgm);
|
||||||
|
c.reg = [0, 0, 0xff00ff00, 0xffff0000, 0, 0, 0, 0];
|
||||||
|
c.run(&mut NoConsole{})?;
|
||||||
|
let exp = [0, 0x00ffff00, 0xff00ff00, 0xffff0000, 0, 0, 0, 0];
|
||||||
|
assert_eq!(c.reg, exp);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_halt() -> Result<(), String> {
|
||||||
|
let pgm = vec!( ezop(7, 1, 2, 3) );
|
||||||
|
let mut c = Cpu::new(pgm);
|
||||||
|
match c.run(&mut NoConsole{}) {
|
||||||
|
Err(CpuError::Halt) => Ok(()),
|
||||||
|
Err(_) => Err(String::from("Invalid error")),
|
||||||
|
Ok(_) => Err(String::from("Expected err got ok"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_alc_large() -> Result<(), String> {
|
||||||
|
let pgm = vec!( ezop(8, 1, 2, 3) );
|
||||||
|
let mut c = Cpu::new(pgm);
|
||||||
|
c.reg = [0, 1338, 33, 0xffffffff, 0, 0, 0, 0];
|
||||||
|
match c.run(&mut NoConsole{}) {
|
||||||
|
Err(CpuError::LargeAlloc) => Ok(()),
|
||||||
|
Err(_) => Err(String::from("Invalid error")),
|
||||||
|
Ok(_) => Err(String::from("Expected err got ok"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_alc() -> Result<(), CpuError> {
|
||||||
|
let pgm = vec!( ezop(8, 1, 2, 3) );
|
||||||
|
let mut c = Cpu::new(pgm);
|
||||||
|
c.reg = [0, 1338, 33, 5, 0, 0, 0, 0];
|
||||||
|
if let Err(e) = c.run(&mut NoConsole{}) {
|
||||||
|
return Err(e)
|
||||||
|
}
|
||||||
|
let exp = [0, 1338, 1, 5, 0, 0, 0, 0];
|
||||||
|
assert_eq!(c.reg, exp);
|
||||||
|
if let Some(arr) = c.arr.get(&1){
|
||||||
|
assert_eq!(arr,&vec![0,0,0,0,0] );
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(CpuError::InvalidArray)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_abn() -> Result<(), CpuError> {
|
||||||
|
let pgm = vec!( ezop(9, 1, 2, 3) );
|
||||||
|
let mut c = Cpu::new(pgm);
|
||||||
|
c.arr.insert(1338, vec![0,0,0,0]);
|
||||||
|
c.reg = [0, 0, 0, 1338, 0, 0, 0, 0];
|
||||||
|
c.run(&mut NoConsole{})?;
|
||||||
|
if c.arr.contains_key(&1338) {
|
||||||
|
Err(CpuError::InvalidArray)
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_abn_zero() -> Result<(), String> {
|
||||||
|
let pgm = vec!( ezop(9, 1, 2, 3) );
|
||||||
|
let mut c = Cpu::new(pgm);
|
||||||
|
c.reg = [0, 0, 0, 0, 0, 0, 0, 0];
|
||||||
|
match c.run(&mut NoConsole{}) {
|
||||||
|
Err(CpuError::InvalidArray) => Ok(()),
|
||||||
|
Err(_) => Err(String::from("Invalid error")),
|
||||||
|
Ok(_) => Err(String::from("Expected err got ok"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_out() -> Result<(), String> {
|
||||||
|
let pgm = vec!( ezop(10, 1, 2, 3) );
|
||||||
|
let mut c = Cpu::new(pgm);
|
||||||
|
c.reg = [0, 0, 0, 128, 0, 0, 0, 0];
|
||||||
|
let mut cons = BufConsole::make();
|
||||||
|
if let Err(e) = c.run(&mut cons) {
|
||||||
|
return Err(format!("unexpected err {:?}", e));
|
||||||
|
};
|
||||||
|
assert_eq!(cons.outb, vec!(128));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_out_inv() -> Result<(), String> {
|
||||||
|
let pgm = vec!( ezop(10, 1, 2, 3) );
|
||||||
|
let mut c = Cpu::new(pgm);
|
||||||
|
c.reg = [0, 0, 0, 1337, 0, 0, 0, 0];
|
||||||
|
let mut cons = BufConsole::make();
|
||||||
|
match c.run(&mut cons) {
|
||||||
|
Err(CpuError::InvalidOutput) => Ok(()),
|
||||||
|
Ok(_) => Err(format!("unexpected ok")),
|
||||||
|
Err(e) => Err(format!("unexpected err {:?}", e))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_inp() -> Result<(), String> {
|
||||||
|
let pgm = vec!( ezop(11, 1, 2, 3) );
|
||||||
|
let mut c = Cpu::new(pgm);
|
||||||
|
c.reg = [0, 0, 0, 0, 0, 0, 0, 0];
|
||||||
|
let mut cons = BufConsole::make();
|
||||||
|
cons.inb.push(128);
|
||||||
|
if let Err(e) = c.run(&mut cons) {
|
||||||
|
return Err(format!("unexpected err {:?}", e));
|
||||||
|
};
|
||||||
|
let exp = [0, 0, 0, 128, 0, 0, 0, 0];
|
||||||
|
assert_eq!(c.reg, exp);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_inp_fail() -> Result<(), String> {
|
||||||
|
let pgm = vec!( ezop(11, 1, 2, 3) );
|
||||||
|
let mut c = Cpu::new(pgm);
|
||||||
|
c.reg = [0, 0, 0, 0, 0, 0, 0, 0];
|
||||||
|
let mut cons = BufConsole::make();
|
||||||
|
if let Err(e) = c.run(&mut cons) {
|
||||||
|
return Err(format!("unexpected err {:?}", e));
|
||||||
|
};
|
||||||
|
let exp = [0, 0, 0, 0xffffffff, 0, 0, 0, 0];
|
||||||
|
assert_eq!(c.reg, exp);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_lod() -> Result<(), CpuError> {
|
||||||
|
let pgm = vec!( ezop(12, 1, 2, 3) );
|
||||||
|
let mut c = Cpu::new(pgm);
|
||||||
|
c.arr.insert(1338, vec![0,0,0,1339]);
|
||||||
|
c.reg = [0, 0, 1338, 3, 0, 0, 0, 0];
|
||||||
|
c.step()?;
|
||||||
|
assert_eq!(c.finger, 3);
|
||||||
|
if let Some(arr) = c.arr.get(&0){
|
||||||
|
assert_eq!(arr,&vec![0,0,0,1339] );
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(CpuError::InvalidArray)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_lod_inv() -> Result<(), String> {
|
||||||
|
let pgm = vec!( ezop(12, 1, 2, 3) );
|
||||||
|
let mut c = Cpu::new(pgm);
|
||||||
|
c.reg = [0, 0, 1338, 3, 0, 0, 0, 0];
|
||||||
|
|
||||||
|
match c.step() {
|
||||||
|
Err(CpuError::InvalidArray) => Ok(()),
|
||||||
|
Ok(_) => Err(format!("unexpected ok")),
|
||||||
|
Err(e) => Err(format!("unexpected err {:?}", e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_lod_off() -> Result<(), String> {
|
||||||
|
let pgm = vec!( ezop(12, 1, 2, 3) );
|
||||||
|
let mut c = Cpu::new(pgm);
|
||||||
|
c.reg = [0, 0, 1338, 3, 0, 0, 0, 0];
|
||||||
|
c.arr.insert(1338, vec![0]);
|
||||||
|
match c.step() {
|
||||||
|
Err(CpuError::ArrayOutOfBounds) => Ok(()),
|
||||||
|
Ok(_) => Err(format!("unexpected ok")),
|
||||||
|
Err(e) => Err(format!("unexpected err {:?}", e))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user