Couple bugfixes, integration tests ported
This commit is contained in:
+33
-22
@@ -32,6 +32,12 @@ impl PeekPoke for CPU {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for CPU {
|
||||
fn default() -> Self {
|
||||
Self::new(Memory::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl CPU {
|
||||
pub fn new(memory: Memory) -> Self {
|
||||
Self {
|
||||
@@ -270,6 +276,33 @@ impl CPU {
|
||||
pub fn running(&self) -> bool {
|
||||
!self.halted
|
||||
}
|
||||
|
||||
pub fn run_to_halt(&mut self) {
|
||||
self.start();
|
||||
while !self.halted && self.pc < 1100 {
|
||||
self.tick()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_stack(&self) -> Vec<Word> {
|
||||
let mut v = Vec::new();
|
||||
let mut curr = Word::from(256);
|
||||
while curr < self.dp {
|
||||
v.push(self.memory.peek24(curr));
|
||||
curr += 3
|
||||
}
|
||||
v
|
||||
}
|
||||
|
||||
pub fn get_call(&self) -> Vec<Word> {
|
||||
let mut v = Vec::new();
|
||||
let mut curr = Word::from(1024);
|
||||
while curr > self.sp {
|
||||
curr -= 3;
|
||||
v.push(self.memory.peek24(curr));
|
||||
}
|
||||
v
|
||||
}
|
||||
}
|
||||
|
||||
impl Opcode {
|
||||
@@ -305,28 +338,6 @@ mod tests {
|
||||
use super::*;
|
||||
use Opcode::*;
|
||||
|
||||
impl CPU {
|
||||
fn get_stack(&self) -> Vec<Word> {
|
||||
let mut v = Vec::new();
|
||||
let mut curr = Word::from(256);
|
||||
while curr < self.dp {
|
||||
v.push(self.memory.peek24(curr));
|
||||
curr += 3
|
||||
}
|
||||
v
|
||||
}
|
||||
|
||||
fn get_call(&self) -> Vec<Word> {
|
||||
let mut v = Vec::new();
|
||||
let mut curr = Word::from(1024);
|
||||
while curr > self.sp {
|
||||
curr -= 3;
|
||||
v.push(self.memory.peek24(curr));
|
||||
}
|
||||
v
|
||||
}
|
||||
}
|
||||
|
||||
fn predicate_opcode_test<P, Q>(opcode: Opcode, given: P, pred: Q)
|
||||
where
|
||||
P: FnOnce(&mut CPU),
|
||||
|
||||
+5
-1
@@ -1,4 +1,8 @@
|
||||
pub mod cpu;
|
||||
pub mod memory;
|
||||
pub mod opcodes;
|
||||
pub mod word;
|
||||
pub mod word;
|
||||
|
||||
pub use cpu::CPU;
|
||||
pub use memory::Memory;
|
||||
pub use word::Word;
|
||||
|
||||
@@ -20,6 +20,26 @@ impl<R: Rng> From<R> for Memory {
|
||||
}
|
||||
}
|
||||
|
||||
impl Memory {
|
||||
/// Create a memory containing the given contents (probably code) starting at `0x400` (the
|
||||
/// starting address for code). The rest of the memory is zeroes.
|
||||
/// ```
|
||||
/// # use crate::vcore::memory::PeekPokeExt;
|
||||
/// # use crate::vcore::Word;
|
||||
/// # use crate::vcore::Memory;
|
||||
/// let mem = Memory::with_program(vec![0x02, 0x12, 0x34]);
|
||||
/// assert_eq!(mem.peek8(Word::from(0x400)), 0x02);
|
||||
/// assert_eq!(mem.peek8(Word::from(0x401)), 0x12); // etc
|
||||
/// ```
|
||||
pub fn with_program<T: IntoIterator<Item = u8>>(code: T) -> Memory {
|
||||
let mut m = Memory::default();
|
||||
for (addr, byte) in code.into_iter().enumerate() {
|
||||
m.poke8(addr + 0x400, byte)
|
||||
}
|
||||
m
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Index<Word> for Memory {
|
||||
type Output = u8;
|
||||
fn index(&self, index: Word) -> &Self::Output {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
// 128k, the amount of memory in a standard Vulcan machine
|
||||
pub const MEM_SIZE: u32 = 128 * 1024;
|
||||
|
||||
@@ -45,6 +47,11 @@ impl From<Word> for u32 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Word {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", i32::from(*self))
|
||||
}
|
||||
}
|
||||
#[test]
|
||||
fn to_from_u32() {
|
||||
assert_eq!(u32::from(Word::from(0x123456u32)), 0x123456u32);
|
||||
|
||||
Reference in New Issue
Block a user