cpu.rs: Remove stack from main memory

This commit is contained in:
John 2023-04-17 06:34:48 -05:00
parent e842755d77
commit 45adf0a2b8
6 changed files with 25 additions and 37 deletions

View File

@ -129,14 +129,11 @@ impl State {
Program [0x0200..0x1000] = &read(&options.file)?, Program [0x0200..0x1000] = &read(&options.file)?,
// Create a screen // Create a screen
Screen [0x1000..0x1100], Screen [0x1000..0x1100],
// Create a stack
Stack [0x0EA0..0x0F00],
}, },
cpu: CPU::new( cpu: CPU::new(
0x1000, 0x1000,
0x50, 0x50,
0x200, 0x200,
0xefe,
Dis::default(), Dis::default(),
options.breakpoints, options.breakpoints,
Flags { Flags {

View File

@ -55,9 +55,10 @@ pub struct CPU {
// memory map info // memory map info
screen: Adr, screen: Adr,
font: Adr, font: Adr,
// memory
stack: Vec<Adr>,
// registers // registers
pc: Adr, pc: Adr,
sp: Adr,
i: Adr, i: Adr,
v: [u8; 16], v: [u8; 16],
delay: f64, delay: f64,
@ -93,7 +94,6 @@ impl CPU {
screen: Adr, screen: Adr,
font: Adr, font: Adr,
pc: Adr, pc: Adr,
sp: Adr,
disassembler: Dis, disassembler: Dis,
breakpoints: Vec<Adr>, breakpoints: Vec<Adr>,
flags: Flags, flags: Flags,
@ -103,7 +103,6 @@ impl CPU {
screen, screen,
font, font,
pc, pc,
sp,
breakpoints, breakpoints,
flags, flags,
..Default::default() ..Default::default()
@ -548,7 +547,7 @@ impl CPU {
std::println!( std::println!(
"PC: {:04x}, SP: {:04x}, I: {:04x}\n{}DLY: {}, SND: {}, CYC: {:6}", "PC: {:04x}, SP: {:04x}, I: {:04x}\n{}DLY: {}, SND: {}, CYC: {:6}",
self.pc, self.pc,
self.sp, self.stack.len(),
self.i, self.i,
self.v self.v
.into_iter() .into_iter()
@ -588,10 +587,10 @@ impl Default for CPU {
/// ``` /// ```
fn default() -> Self { fn default() -> Self {
CPU { CPU {
stack: vec![],
screen: 0xf00, screen: 0xf00,
font: 0x050, font: 0x050,
pc: 0x200, pc: 0x200,
sp: 0xefe,
i: 0, i: 0,
v: [0; 16], v: [0; 16],
delay: 0.0, delay: 0.0,

View File

@ -88,8 +88,6 @@ pub enum Region {
Program, Program,
/// Screen buffer /// Screen buffer
Screen, Screen,
/// Stack space
Stack,
#[doc(hidden)] #[doc(hidden)]
/// Total number of named regions /// Total number of named regions
Count, Count,
@ -104,7 +102,6 @@ impl Display for Region {
Region::Charset => "Charset", Region::Charset => "Charset",
Region::Program => "Program", Region::Program => "Program",
Region::Screen => "Screen", Region::Screen => "Screen",
Region::Stack => "Stack",
_ => "", _ => "",
} }
) )
@ -348,7 +345,7 @@ impl Bus {
#[cfg(feature = "drawille")] #[cfg(feature = "drawille")]
{ {
use drawille::Canvas; use drawille::Canvas;
let mut canvas = Canvas::new(dbg!(width * 8), dbg!(height)); let mut canvas = Canvas::new(width * 8, height);
let width = width * 8; let width = width * 8;
screen screen
.iter() .iter()

View File

@ -13,9 +13,9 @@ impl CPU {
match instruction { match instruction {
// Core Chip-8 instructions // Core Chip-8 instructions
Insn::cls => self.clear_screen(bus), Insn::cls => self.clear_screen(bus),
Insn::ret => self.ret(bus), Insn::ret => self.ret(),
Insn::jmp { A } => self.jump(A), Insn::jmp { A } => self.jump(A),
Insn::call { A } => self.call(A, bus), Insn::call { A } => self.call(A),
Insn::seb { x, B } => self.skip_equals_immediate(x, B), Insn::seb { x, B } => self.skip_equals_immediate(x, B),
Insn::sneb { x, B } => self.skip_not_equals_immediate(x, B), Insn::sneb { x, B } => self.skip_not_equals_immediate(x, B),
Insn::se { y, x } => self.skip_equals(x, y), Insn::se { y, x } => self.skip_equals(x, y),
@ -74,9 +74,8 @@ impl CPU {
} }
/// |`00ee`| Returns from subroutine /// |`00ee`| Returns from subroutine
#[inline(always)] #[inline(always)]
pub(super) fn ret(&mut self, bus: &impl ReadWrite<u16>) { pub(super) fn ret(&mut self) {
self.sp = self.sp.wrapping_add(2); self.pc = self.stack.pop().unwrap_or(0x200);
self.pc = bus.read(self.sp);
} }
} }
@ -97,9 +96,8 @@ impl CPU {
impl CPU { impl CPU {
/// |`2aaa`| Pushes pc onto the stack, then jumps to a /// |`2aaa`| Pushes pc onto the stack, then jumps to a
#[inline(always)] #[inline(always)]
pub(super) fn call(&mut self, a: Adr, bus: &mut impl ReadWrite<u16>) { pub(super) fn call(&mut self, a: Adr) {
bus.write(self.sp, self.pc); self.stack.push(self.pc);
self.sp = self.sp.wrapping_sub(2);
self.pc = a; self.pc = a;
} }
} }

View File

@ -106,17 +106,14 @@ mod sys {
#[test] #[test]
fn ret() { fn ret() {
let test_addr = random::<u16>() & 0x7ff; let test_addr = random::<u16>() & 0x7ff;
let (mut cpu, mut bus) = setup_environment(); let (mut cpu, _) = setup_environment();
let sp_orig = cpu.sp;
// Place the address on the stack // Place the address on the stack
bus.write(cpu.sp.wrapping_add(2), test_addr); cpu.stack.push(test_addr);
cpu.ret(&bus); cpu.ret();
// Verify the current address is the address from the stack // Verify the current address is the address from the stack
assert_eq!(test_addr, cpu.pc); assert_eq!(test_addr, cpu.pc);
// Verify the stack pointer has moved
assert!(dbg!(cpu.sp.wrapping_sub(sp_orig)) == 0x2);
} }
} }
@ -132,9 +129,9 @@ mod cf {
let (mut cpu, _) = setup_environment(); let (mut cpu, _) = setup_environment();
// Test all valid addresses // Test all valid addresses
for addr in 0x000..0xffe { for addr in 0x000..0xffe {
// Call an address // Jump to an address
cpu.jump(addr); cpu.jump(addr);
// Verify the current address is the called address // Verify the current address is the jump target address
assert_eq!(addr, cpu.pc); assert_eq!(addr, cpu.pc);
} }
} }
@ -143,15 +140,15 @@ mod cf {
#[test] #[test]
fn call() { fn call() {
let test_addr = random::<u16>(); let test_addr = random::<u16>();
let (mut cpu, mut bus) = setup_environment(); let (mut cpu, _) = setup_environment();
// Save the current address // Save the current address
let curr_addr = cpu.pc; let curr_addr = cpu.pc;
// Call an address // Call an address
cpu.call(test_addr, &mut bus); cpu.call(test_addr);
// Verify the current address is the called address // Verify the current address is the called address
assert_eq!(test_addr, cpu.pc); assert_eq!(test_addr, cpu.pc);
// Verify the previous address was stored on the stack (sp+2) // Verify the previous address was stored on the stack (sp+2)
let stack_addr: u16 = bus.read(cpu.sp.wrapping_add(2)); let stack_addr: u16 = cpu.stack.pop().expect("This should return test_addr");
assert_eq!(stack_addr, curr_addr); assert_eq!(stack_addr, curr_addr);
} }
@ -595,7 +592,7 @@ mod math {
for reg in 0..=0xff { for reg in 0..=0xff {
let (x, y) = (reg & 0xf, reg >> 4); let (x, y) = (reg & 0xf, reg >> 4);
// set the register under test to `word` // set the register under test to `word`
(cpu.v[x], cpu.v[y]) = dbg!(0, word); (cpu.v[x], cpu.v[y]) = (0, word);
cpu.shift_left(x, y); cpu.shift_left(x, y);

View File

@ -30,11 +30,11 @@ mod bus {
} }
#[test] #[test]
fn display() { fn display() {
println!("{Charset}{Program}{Screen}{Stack}{Count}"); println!("{Charset}{Program}{Screen}{Count}");
} }
#[test] #[test]
fn debug() { fn debug() {
println!("{Charset:?}{Program:?}{Screen:?}{Stack:?}{Count:?}"); println!("{Charset:?}{Program:?}{Screen:?}{Count:?}");
} }
// lmao the things you do for test coverage // lmao the things you do for test coverage
#[test] #[test]
@ -44,13 +44,13 @@ mod bus {
} }
#[test] #[test]
fn ord() { fn ord() {
assert_eq!(Stack, Charset.max(Program).max(Screen).max(Stack)); assert_eq!(Screen, Charset.max(Program).max(Screen));
assert!(Charset < Program && Program < Screen && Screen < Stack); assert!(Charset < Program && Program < Screen);
} }
#[test] #[test]
fn hash() { fn hash() {
let mut hasher = DefaultHasher::new(); let mut hasher = DefaultHasher::new();
Stack.hash(&mut hasher); Program.hash(&mut hasher);
println!("{hasher:?}"); println!("{hasher:?}");
} }
} }