From a721a7d0b80e485e80c771e0842cbccd47aa7c91 Mon Sep 17 00:00:00 2001 From: Ross Andrews Date: Fri, 18 Feb 2022 22:32:37 -0600 Subject: [PATCH] Rename Address to Word --- src/address.rs | 48 ++++++++++++----------------- src/cpu.rs | 24 +++++++-------- src/memory.rs | 82 ++++++++++++++++++++++++++++++++------------------ 3 files changed, 84 insertions(+), 70 deletions(-) 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); + } }