tests: Update tests to match current behavior.
This commit is contained in:
parent
a4c548d0ec
commit
f27537b3b8
20
src/cpu.rs
20
src/cpu.rs
@ -522,6 +522,11 @@ impl CPU {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Executes a single instruction
|
/// Executes a single instruction
|
||||||
|
///
|
||||||
|
/// Returns [Error::BreakpointHit] if a breakpoint was hit after the instruction executed.
|
||||||
|
/// This result contains information about the breakpoint, but can be safely ignored.
|
||||||
|
///
|
||||||
|
/// Returns [Error::UnimplementedInstruction] if the instruction at `pc` is unimplemented.
|
||||||
/// # Examples
|
/// # Examples
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use chirp::*;
|
/// # use chirp::*;
|
||||||
@ -552,11 +557,8 @@ impl CPU {
|
|||||||
/// ],
|
/// ],
|
||||||
/// Screen [0x0f00..0x1000],
|
/// Screen [0x0f00..0x1000],
|
||||||
/// };
|
/// };
|
||||||
/// match cpu.tick(&mut bus) {
|
/// dbg!(cpu.tick(&mut bus))
|
||||||
/// Err(Error::UnimplementedInstruction {word})
|
/// .expect_err("Should return Error::InvalidInstruction { 0xffff }");
|
||||||
/// => assert_eq!(0xffff, word),
|
|
||||||
/// _ => panic!(),
|
|
||||||
/// }
|
|
||||||
/// ```
|
/// ```
|
||||||
pub fn tick(&mut self, bus: &mut Bus) -> Result<&mut Self> {
|
pub fn tick(&mut self, bus: &mut Bus) -> Result<&mut Self> {
|
||||||
// Do nothing if paused
|
// Do nothing if paused
|
||||||
@ -571,7 +573,9 @@ impl CPU {
|
|||||||
// fetch opcode
|
// fetch opcode
|
||||||
let opcode: &[u8; 2] = if let Some(slice) = bus.get(self.pc as usize..self.pc as usize + 2)
|
let opcode: &[u8; 2] = if let Some(slice) = bus.get(self.pc as usize..self.pc as usize + 2)
|
||||||
{
|
{
|
||||||
slice.try_into()?
|
slice
|
||||||
|
.try_into()
|
||||||
|
.expect("`slice` should be exactly 2 bytes.")
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::InvalidBusRange {
|
return Err(Error::InvalidBusRange {
|
||||||
range: self.pc as usize..self.pc as usize + 2,
|
range: self.pc as usize..self.pc as usize + 2,
|
||||||
@ -603,6 +607,10 @@ impl CPU {
|
|||||||
// process breakpoints
|
// process breakpoints
|
||||||
if !self.breakpoints.is_empty() && self.breakpoints.contains(&self.pc) {
|
if !self.breakpoints.is_empty() && self.breakpoints.contains(&self.pc) {
|
||||||
self.flags.pause = true;
|
self.flags.pause = true;
|
||||||
|
return Err(Error::BreakpointHit {
|
||||||
|
addr: self.pc,
|
||||||
|
next: bus.read(self.pc),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
@ -939,6 +939,7 @@ mod io {
|
|||||||
output: &'static [u8],
|
output: &'static [u8],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Verify the character sprite addresses with the data they should return
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
const TESTS: [SpriteTest; 16] = [
|
const TESTS: [SpriteTest; 16] = [
|
||||||
SpriteTest { input: 0x0, output: &[0xf0, 0x90, 0x90, 0x90, 0xf0] },
|
SpriteTest { input: 0x0, output: &[0xf0, 0x90, 0x90, 0x90, 0xf0] },
|
||||||
@ -1121,15 +1122,51 @@ mod behavior {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mod breakpoint {
|
mod breakpoint {
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
#[test]
|
#[test]
|
||||||
|
#[cfg_attr(feature = "unstable", no_coverage)]
|
||||||
fn hit_break() {
|
fn hit_break() {
|
||||||
let (mut cpu, mut bus) = setup_environment();
|
let (mut cpu, mut bus) = setup_environment();
|
||||||
cpu.set_break(0x202);
|
cpu.set_break(0x202);
|
||||||
cpu.multistep(&mut bus, 10)
|
match cpu.multistep(&mut bus, 10) {
|
||||||
.expect("Running valid instructions should always succeed");
|
Err(crate::error::Error::BreakpointHit { addr, next }) => {
|
||||||
|
assert_eq!(0x202, addr); // current address is 202
|
||||||
|
assert_eq!(0x1204, next); // next insn is `jmp 204`
|
||||||
|
}
|
||||||
|
other => unreachable!("{:?}", other),
|
||||||
|
}
|
||||||
|
assert!(cpu.flags.pause);
|
||||||
|
assert_eq!(0x202, cpu.pc);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
#[cfg_attr(feature = "unstable", no_coverage)]
|
||||||
|
fn hit_break_singlestep() {
|
||||||
|
let (mut cpu, mut bus) = setup_environment();
|
||||||
|
cpu.set_break(0x202);
|
||||||
|
match cpu.singlestep(&mut bus) {
|
||||||
|
Err(crate::error::Error::BreakpointHit { addr, next }) => {
|
||||||
|
assert_eq!(0x202, addr); // current address is 202
|
||||||
|
assert_eq!(0x1204, next); // next insn is `jmp 204`
|
||||||
|
}
|
||||||
|
other => unreachable!("{:?}", other),
|
||||||
|
}
|
||||||
assert!(cpu.flags.pause);
|
assert!(cpu.flags.pause);
|
||||||
assert_eq!(0x202, cpu.pc);
|
assert_eq!(0x202, cpu.pc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg_attr(feature = "unstable", no_coverage)]
|
||||||
|
fn invalid_pc() {
|
||||||
|
let (mut cpu, mut bus) = setup_environment();
|
||||||
|
// The bus extends from 0x0..0x1000
|
||||||
|
cpu.pc = 0xfff;
|
||||||
|
match cpu.tick(&mut bus) {
|
||||||
|
Err(Error::InvalidBusRange { range }) => {
|
||||||
|
eprintln!("InvalidBusRange {{ {range:04x?} }}")
|
||||||
|
}
|
||||||
|
other => unreachable!("{other:04x?}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,14 @@ pub type Result<T> = std::result::Result<T, Error>;
|
|||||||
/// Error type for Chirp.
|
/// Error type for Chirp.
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
/// Represents a breakpoint being hit
|
||||||
|
#[error("Breakpoint hit: {addr:03x} ({next:04x})")]
|
||||||
|
BreakpointHit {
|
||||||
|
/// The address of the breakpoint
|
||||||
|
addr: u16,
|
||||||
|
/// The instruction after the breakpoint
|
||||||
|
next: u16,
|
||||||
|
},
|
||||||
/// Represents an unimplemented operation
|
/// Represents an unimplemented operation
|
||||||
#[error("Unrecognized opcode: {word:04x}")]
|
#[error("Unrecognized opcode: {word:04x}")]
|
||||||
UnimplementedInstruction {
|
UnimplementedInstruction {
|
||||||
|
Loading…
Reference in New Issue
Block a user