2024-03-21 04:00:33 +00:00
|
|
|
// m68k Debugger
|
2024-03-09 03:41:36 +00:00
|
|
|
|
2024-03-21 04:00:33 +00:00
|
|
|
use core::fmt;
|
|
|
|
|
|
|
|
use emulator_hal::time;
|
|
|
|
use emulator_hal::bus::{self, BusAccess};
|
|
|
|
use emulator_hal::step::{Inspect, Debug};
|
|
|
|
|
|
|
|
use crate::{M68k, M68kError, M68kAddress, M68kCycleExecutor};
|
2021-10-02 16:35:25 +00:00
|
|
|
|
2023-03-06 04:19:49 +00:00
|
|
|
#[derive(Clone, Default)]
|
2021-10-04 18:13:10 +00:00
|
|
|
pub struct StackTracer {
|
|
|
|
pub calls: Vec<u32>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl StackTracer {
|
|
|
|
pub fn push_return(&mut self, addr: u32) {
|
|
|
|
self.calls.push(addr);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn pop_return(&mut self) {
|
|
|
|
self.calls.pop();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-21 04:00:33 +00:00
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
|
|
|
pub enum M68kInfo {
|
|
|
|
State,
|
|
|
|
}
|
|
|
|
|
2024-03-23 01:51:17 +00:00
|
|
|
impl<Bus, BusError, Instant, Writer> Inspect<M68kAddress, Bus, Writer> for M68k<Instant>
|
2024-03-21 04:00:33 +00:00
|
|
|
where
|
2024-03-23 01:51:17 +00:00
|
|
|
Bus: BusAccess<M68kAddress, Instant = Instant, Error = BusError>,
|
2024-03-21 04:00:33 +00:00
|
|
|
BusError: bus::Error,
|
|
|
|
Writer: fmt::Write,
|
|
|
|
{
|
|
|
|
type InfoType = M68kInfo;
|
|
|
|
|
|
|
|
type Error = M68kError<BusError>;
|
|
|
|
|
|
|
|
fn inspect(&mut self, info: Self::InfoType, _bus: &mut Bus, writer: &mut Writer) -> Result<(), Self::Error> {
|
|
|
|
match info {
|
|
|
|
M68kInfo::State => self
|
|
|
|
.state
|
|
|
|
.dump_state(writer)
|
|
|
|
.map_err(|_| M68kError::Other("error while formatting state".to_string())),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn brief_summary(&mut self, bus: &mut Bus, writer: &mut Writer) -> Result<(), Self::Error> {
|
|
|
|
self.inspect(M68kInfo::State, bus, writer)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn detailed_summary(&mut self, bus: &mut Bus, writer: &mut Writer) -> Result<(), Self::Error> {
|
|
|
|
self.inspect(M68kInfo::State, bus, writer)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Control the execution of a CPU device for debugging purposes
|
2024-03-23 01:51:17 +00:00
|
|
|
impl<Bus, BusError, Instant, Writer> Debug<M68kAddress, Bus, Writer> for M68k<Instant>
|
2024-03-21 04:00:33 +00:00
|
|
|
where
|
2024-03-23 01:51:17 +00:00
|
|
|
Bus: BusAccess<M68kAddress, Instant = Instant, Error = BusError>,
|
2024-03-21 04:00:33 +00:00
|
|
|
BusError: bus::Error,
|
|
|
|
Instant: time::Instant,
|
|
|
|
Writer: fmt::Write,
|
|
|
|
{
|
|
|
|
// TODO this should be a new type
|
|
|
|
type DebugError = M68kError<BusError>;
|
|
|
|
|
|
|
|
fn get_execution_address(&mut self) -> Result<M68kAddress, Self::DebugError> {
|
|
|
|
Ok(self.state.pc)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn set_execution_address(&mut self, address: M68kAddress) -> Result<(), Self::DebugError> {
|
|
|
|
self.state.pc = address;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn add_breakpoint(&mut self, address: M68kAddress) {
|
|
|
|
self.debugger.breakpoints.push(address);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn remove_breakpoint(&mut self, address: M68kAddress) {
|
|
|
|
if let Some(index) = self.debugger.breakpoints.iter().position(|a| *a == address) {
|
|
|
|
self.debugger.breakpoints.remove(index);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn clear_breakpoints(&mut self) {
|
|
|
|
self.debugger.breakpoints.clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-04 18:13:10 +00:00
|
|
|
|
2023-03-06 04:19:49 +00:00
|
|
|
#[derive(Clone, Default)]
|
2021-10-02 16:35:25 +00:00
|
|
|
pub struct M68kDebugger {
|
2023-06-10 22:28:21 +00:00
|
|
|
pub(crate) skip_breakpoint: usize,
|
|
|
|
pub(crate) breakpoints: Vec<u32>,
|
2024-03-16 06:01:41 +00:00
|
|
|
#[allow(dead_code)]
|
2023-06-10 22:28:21 +00:00
|
|
|
pub(crate) step_until_return: Option<usize>,
|
|
|
|
pub(crate) stack_tracer: StackTracer,
|
2021-10-02 16:35:25 +00:00
|
|
|
}
|
|
|
|
|
2024-03-21 04:00:33 +00:00
|
|
|
impl<'a, Bus, BusError, Instant> M68kCycleExecutor<'a, Bus, Instant>
|
2024-03-09 03:41:36 +00:00
|
|
|
where
|
2024-03-23 01:51:17 +00:00
|
|
|
Bus: BusAccess<M68kAddress, Instant = Instant, Error = BusError>,
|
2024-03-21 04:00:33 +00:00
|
|
|
Instant: Copy,
|
2024-03-09 03:41:36 +00:00
|
|
|
{
|
2024-03-14 04:49:04 +00:00
|
|
|
pub fn check_breakpoints(&mut self) -> Result<(), M68kError<BusError>> {
|
2021-11-01 23:51:45 +00:00
|
|
|
for breakpoint in &self.debugger.breakpoints {
|
|
|
|
if *breakpoint == self.state.pc {
|
2023-06-10 22:28:21 +00:00
|
|
|
if self.debugger.skip_breakpoint > 0 {
|
|
|
|
self.debugger.skip_breakpoint -= 1;
|
|
|
|
return Ok(());
|
|
|
|
} else {
|
|
|
|
self.debugger.skip_breakpoint = 1;
|
2024-03-14 04:49:04 +00:00
|
|
|
return Err(M68kError::Breakpoint);
|
2023-06-10 22:28:21 +00:00
|
|
|
}
|
2021-11-01 23:51:45 +00:00
|
|
|
}
|
|
|
|
}
|
2023-06-10 22:28:21 +00:00
|
|
|
Ok(())
|
2021-11-01 23:51:45 +00:00
|
|
|
}
|
|
|
|
}
|