diff --git a/src/address.rs b/src/address.rs
index c3407b9..2e92d9b 100644
--- a/src/address.rs
+++ b/src/address.rs
@@ -2,65 +2,55 @@
pub const MEM_SIZE: u32 = 128 * 1024;
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
-pub struct Address(u32);
+pub struct Word(u32);
-impl From
for usize {
- fn from(a: Address) -> Self { (a.0 & (MEM_SIZE-1)) as usize }
-}
-
-impl From for Address {
+impl From for Word {
fn from(a: u32) -> Self { Self(a & 0xffffff) }
}
-impl Into for Address {
+impl Into for Word {
fn into(self) -> u32 { self.0 }
}
-impl std::ops::Add for Address {
- type Output = Address;
+impl std::ops::Add for Word {
+ type Output = Word;
fn add(self, rhs: i32) -> Self::Output {
- Address::from((self.0 as i32).overflowing_add(rhs).0 as u32)
+ Word::from((self.0 as i32).overflowing_add(rhs).0 as u32)
}
}
-impl std::ops::Sub for Address {
- type Output = Address;
+impl std::ops::Sub for Word {
+ type Output = Word;
fn sub(self, rhs: i32) -> Self::Output { self + -rhs }
}
-impl std::ops::SubAssign for Address {
+impl std::ops::SubAssign for Word {
fn sub_assign(&mut self, rhs: i32) { *self = *self - rhs; }
}
-impl std::ops::AddAssign for Address {
+impl std::ops::AddAssign for Word {
fn add_assign(&mut self, rhs: i32) { *self = *self + rhs; }
}
#[test]
fn test_address_truncation() {
- let a: Address = 0x11223344.into();
+ let a: Word = 0x11223344.into();
assert_eq!(a, 0x00223344.into());
}
-#[test]
-fn test_addressing_arrays() {
- let a: usize = Address::from(0xffffff).into();
- assert_eq!(a, 0x01ffff as usize);
-}
-
#[test]
fn test_address_overflows() {
- let a = Address::from(0xfffffa);
- assert_eq!(a + 10, Address(4));
+ let a = Word::from(0xfffffa);
+ assert_eq!(a + 10, Word(4));
- let b = Address::from(3);
- assert_eq!(b - 10, Address(0xfffff9));
+ let b = Word::from(3);
+ assert_eq!(b - 10, Word(0xfffff9));
- let mut c = Address::from(5);
+ let mut c = Word::from(5);
c += 3;
- assert_eq!(c, Address(8));
+ assert_eq!(c, Word(8));
- let mut d = Address::from(5);
+ let mut d = Word::from(5);
d -= 3;
- assert_eq!(d, Address(2));
+ assert_eq!(d, Word(2));
}
\ No newline at end of file
diff --git a/src/cpu.rs b/src/cpu.rs
index 5af39d8..87cf70a 100644
--- a/src/cpu.rs
+++ b/src/cpu.rs
@@ -1,16 +1,16 @@
use crate::opcodes::Opcode;
use crate::opcodes::InvalidOpcode;
use crate::memory::Memory;
-use crate::address::Address;
+use crate::address::Word;
use crate::memory::PeekPoke;
use std::convert::TryFrom;
struct CPU {
memory: Memory, // Main memory, all of it
- pc: Address, // program counter, address of the low byte of the instruction
- dp: Address, // data pointer, address of the low byte of one cell above the data stack
- sp: Address, // stack pointer, address of the low byte of the return stack
- iv: Address, // interrupt vector
+ pc: Word, // program counter, address of the low byte of the instruction
+ dp: Word, // data pointer, address of the low byte of one cell above the data stack
+ sp: Word, // stack pointer, address of the low byte of the return stack
+ iv: Word, // interrupt vector
int_enabled: bool, // interrupt enable bit
halted: bool, // Whether the CPU is halted
}
@@ -102,7 +102,7 @@ impl CPU {
}
}
- fn execute(&mut self, instruction: Instruction) -> Address {
+ fn execute(&mut self, instruction: Instruction) -> Word {
if let Some(arg) = instruction.arg {
self.push_data(arg)
}
@@ -251,7 +251,7 @@ mod tests {
impl CPU {
fn get_stack(&self) -> Vec {
let mut v = Vec::new();
- let mut curr = Address::from(256);
+ let mut curr = Word::from(256);
while curr < self.dp {
v.push(self.memory.peek24(curr));
curr += 3
@@ -261,7 +261,7 @@ mod tests {
fn get_call(&self) -> Vec {
let mut v = Vec::new();
- let mut curr = Address::from(1024);
+ let mut curr = Word::from(1024);
while curr > self.sp {
curr -= 3;
v.push(self.memory.peek24(curr));
@@ -287,7 +287,7 @@ mod tests {
})
}
- fn call_stack_opcode_test(given: Vec, given_r: Vec, opcode: Opcode, expected: Vec, expected_r: Vec, pc: Address) {
+ fn call_stack_opcode_test(given: Vec, given_r: Vec, opcode: Opcode, expected: Vec, expected_r: Vec, pc: Word) {
predicate_opcode_test(opcode, |cpu| {
for i in given.into_iter() { cpu.push_data(i) }
for i in given_r.into_iter() { cpu.push_call(i) }
@@ -298,7 +298,7 @@ mod tests {
})
}
- fn control_flow_opcode_test(given: Vec, opcode: Opcode, expected_pc: A) where A: Into {
+ fn control_flow_opcode_test(given: Vec, opcode: Opcode, expected_pc: A) where A: Into {
predicate_opcode_test(opcode, |cpu| {
for i in given.into_iter() { cpu.push_data(i) }
}, |cpu| {
@@ -311,13 +311,13 @@ mod tests {
|cpu| {
for i in given.into_iter() { cpu.push_data(i) }
for (offset, byte) in given_memory.into_iter().enumerate() {
- cpu.memory.poke(Address::from(2048 + offset as u32), byte)
+ cpu.memory.poke(Word::from(2048 + offset as u32), byte)
}
},
|cpu| {
if let Some(expected_memory) = expected_memory {
for (offset, byte) in expected_memory.into_iter().enumerate() {
- let actual = cpu.memory.peek(Address::from(2048 + offset as u32));
+ let actual = cpu.memory.peek(Word::from(2048 + offset as u32));
assert_eq!(byte, actual, "At address 2048 + {}", offset)
}
assert_eq!(cpu.get_stack(), expected)
diff --git a/src/memory.rs b/src/memory.rs
index 80da9c4..67e59a4 100644
--- a/src/memory.rs
+++ b/src/memory.rs
@@ -1,5 +1,5 @@
use rand::Rng;
-use crate::address::Address;
+use crate::address::Word;
use crate::address::MEM_SIZE;
pub struct Memory([u8; MEM_SIZE as usize]);
@@ -8,6 +8,13 @@ impl Default for Memory {
fn default() -> Self { Self([0u8; MEM_SIZE as usize]) }
}
+impl From for usize {
+ fn from(w: Word) -> Self {
+ let w: u32 = w.into();
+ (w & (MEM_SIZE-1)) as usize
+ }
+}
+
impl From for Memory {
fn from(mut rng: R) -> Self {
let mut mem = Memory::default();
@@ -18,25 +25,31 @@ impl From for Memory {
}
}
-impl std::ops::Index for Memory {
+impl std::ops::Index for Memory {
type Output = u8;
- fn index(&self, index: Address) -> &Self::Output { &self.0[usize::from(index)] }
+ fn index(&self, index: Word) -> &Self::Output {
+ &self.0[usize::from(index)]
+ }
}
-impl std::ops::IndexMut for Memory {
- fn index_mut(&mut self, index: Address) -> &mut Self::Output { &mut self.0[usize::from(index)] }
+impl std::ops::IndexMut for Memory {
+ fn index_mut(&mut self, index: Word) -> &mut Self::Output {
+ &mut self.0[usize::from(index)]
+ }
}
pub trait PeekPoke {
- fn peek>(&self, addr: A) -> u8;
- fn poke>(&mut self, addr: A, val: u8);
+ fn peek>(&self, addr: A) -> u8;
+ fn poke>(&mut self, addr: A, val: u8);
- fn peek24>(&self, addr: A) -> u32 {
+ fn peek24>(&self, addr: A) -> u32 {
let addr = addr.into();
- (self.peek(addr) as u32) | ((self.peek(addr + 1) as u32) << 8) | ((self.peek(addr + 2) as u32) << 16)
+ (self.peek(addr) as u32)
+ | ((self.peek(addr + 1) as u32) << 8)
+ | ((self.peek(addr + 2) as u32) << 16)
}
- fn poke24>(&mut self, addr: A, val: u32) {
+ fn poke24>(&mut self, addr: A, val: u32) {
let addr = addr.into();
self.poke(addr, val as u8);
self.poke(addr + 1, (val >> 8) as u8);
@@ -45,26 +58,37 @@ pub trait PeekPoke {
}
impl PeekPoke for Memory {
- fn peek>(&self, addr: A) -> u8 { self[addr.into()] }
- fn poke>(&mut self, addr: A, val: u8) { self[addr.into()] = val; }
+ fn peek>(&self, addr: A) -> u8 { self[addr.into()] }
+ fn poke>(&mut self, addr: A, val: u8) { self[addr.into()] = val; }
}
-#[test]
-fn test_mem_peek_poke() {
- let mut mem = Memory::default();
- assert_eq!(mem.peek(35), 0);
- mem.poke(35, 45);
- assert_eq!(mem.peek(35), 45);
- assert_eq!(mem.peek(36), 0);
-}
+#[cfg(test)]
+mod tests {
+ use super::*;
-#[test]
-fn test_mem_word_fns() {
- let mut mem = Memory::default();
- mem.poke24(10, 0x123456);
- assert_eq!(mem.peek(10), 0x56);
- assert_eq!(mem.peek(11), 0x34);
- assert_eq!(mem.peek(12), 0x12);
- assert_eq!(mem.peek24(10), 0x123456);
- assert_eq!(mem.peek24(11), 0x001234);
+ #[test]
+ fn test_mem_peek_poke() {
+ let mut mem = Memory::default();
+ assert_eq!(mem.peek(35), 0);
+ mem.poke(35, 45);
+ assert_eq!(mem.peek(35), 45);
+ assert_eq!(mem.peek(36), 0);
+ }
+
+ #[test]
+ fn test_mem_word_fns() {
+ let mut mem = Memory::default();
+ mem.poke24(10, 0x123456);
+ assert_eq!(mem.peek(10), 0x56);
+ assert_eq!(mem.peek(11), 0x34);
+ assert_eq!(mem.peek(12), 0x12);
+ assert_eq!(mem.peek24(10), 0x123456);
+ assert_eq!(mem.peek24(11), 0x001234);
+ }
+
+ #[test]
+ fn test_addressing_arrays() {
+ let a: usize = Word::from(0xffffff).into();
+ assert_eq!(a, 0x01ffff as usize);
+ }
}