mirror of
https://github.com/transistorfet/moa.git
synced 2025-02-27 08:29:18 +00:00
Added better processing of debug commands, and timers
This commit is contained in:
parent
bc7fee5221
commit
dd21771bb3
@ -34,6 +34,7 @@ impl MC68010 {
|
||||
pub fn check_breakpoints(&mut self) {
|
||||
for breakpoint in &self.debugger.breakpoints {
|
||||
if *breakpoint == self.state.pc {
|
||||
println!("Breakpoint reached: {:08x}", *breakpoint);
|
||||
self.debugger.use_tracing = true;
|
||||
self.debugger.use_debugger = true;
|
||||
break;
|
||||
@ -43,19 +44,52 @@ impl MC68010 {
|
||||
|
||||
pub fn run_debugger(&mut self, space: &mut AddressSpace) {
|
||||
self.dump_state(space);
|
||||
let mut buffer = String::new();
|
||||
|
||||
loop {
|
||||
let mut buffer = String::new();
|
||||
std::io::stdin().read_line(&mut buffer).unwrap();
|
||||
match buffer.as_ref() {
|
||||
"dump\n" => space.dump_memory(self.state.msp as Address, (0x200000 - self.state.msp) as Address),
|
||||
"continue\n" => {
|
||||
self.debugger.use_debugger = false;
|
||||
return;
|
||||
let args: Vec<&str> = buffer.split_whitespace().collect();
|
||||
match self.run_debugger_command(space, args) {
|
||||
Ok(true) => return,
|
||||
Ok(false) => { },
|
||||
Err(err) => {
|
||||
println!("Error: {}", err.msg);
|
||||
},
|
||||
_ => { return; },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_debugger_command(&mut self, space: &mut AddressSpace, args: Vec<&str>) -> Result<bool, Error> {
|
||||
if args.len() <= 0 {
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
match args[0] {
|
||||
"b" | "break" | "breakpoint" => {
|
||||
if args.len() != 2 {
|
||||
println!("Usage: breakpoint <addr>");
|
||||
} else {
|
||||
let addr = u32::from_str_radix(args[1], 16).map_err(|_| Error::new("Unable to parse breakpoint address"))?;
|
||||
self.add_breakpoint(addr as Address);
|
||||
println!("Breakpoint set for {:08x}", addr);
|
||||
}
|
||||
},
|
||||
"d" | "dump" => {
|
||||
if args.len() > 1 {
|
||||
let addr = u32::from_str_radix(args[1], 16).map_err(|_| Error::new("Unable to parse address"))?;
|
||||
let len = if args.len() > 2 { u32::from_str_radix(args[2], 16).map_err(|_| Error::new("Unable to parse length"))? } else { 0x20 };
|
||||
space.dump_memory(addr as Address, len as Address);
|
||||
} else {
|
||||
space.dump_memory(self.state.msp as Address, 0x40 as Address);
|
||||
}
|
||||
},
|
||||
"c" | "continue" => {
|
||||
self.debugger.use_debugger = false;
|
||||
return Ok(true);
|
||||
},
|
||||
_ => { return Ok(true); },
|
||||
}
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::timers::CpuTimer;
|
||||
use crate::memory::{Address, AddressSpace};
|
||||
|
||||
use super::debugger::M68kDebugger;
|
||||
@ -81,6 +82,7 @@ pub struct MC68010 {
|
||||
pub state: MC68010State,
|
||||
pub decoder: M68kDecoder,
|
||||
pub debugger: M68kDebugger,
|
||||
pub timer: CpuTimer,
|
||||
}
|
||||
|
||||
impl MC68010 {
|
||||
@ -89,6 +91,7 @@ impl MC68010 {
|
||||
state: MC68010State::new(),
|
||||
decoder: M68kDecoder::new(0),
|
||||
debugger: M68kDebugger::new(),
|
||||
timer: CpuTimer::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -134,8 +137,15 @@ impl MC68010 {
|
||||
Status::Init => self.init(space),
|
||||
Status::Stopped => Err(Error::new("CPU stopped")),
|
||||
Status::Running => {
|
||||
let timer = self.timer.cycle.start();
|
||||
self.decode_next(space)?;
|
||||
self.execute_current(space)?;
|
||||
self.timer.cycle.end(timer);
|
||||
|
||||
if (self.timer.cycle.events % 500) == 0 {
|
||||
println!("{}", self.timer);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
},
|
||||
}
|
||||
@ -144,7 +154,9 @@ impl MC68010 {
|
||||
pub fn decode_next(&mut self, space: &mut AddressSpace) -> Result<(), Error> {
|
||||
self.check_breakpoints();
|
||||
|
||||
let timer = self.timer.decode.start();
|
||||
self.decoder = M68kDecoder::decode_at(space, self.state.pc)?;
|
||||
self.timer.decode.end(timer);
|
||||
|
||||
if self.debugger.use_tracing {
|
||||
// Print instruction bytes for debugging
|
||||
@ -164,6 +176,7 @@ impl MC68010 {
|
||||
}
|
||||
|
||||
pub fn execute_current(&mut self, space: &mut AddressSpace) -> Result<(), Error> {
|
||||
let timer = self.timer.decode.start();
|
||||
match self.decoder.instruction {
|
||||
Instruction::ADD(src, dest, size) => {
|
||||
let value = self.get_target_value(space, src, size)?;
|
||||
@ -526,6 +539,7 @@ impl MC68010 {
|
||||
_ => { return Err(Error::new("Unsupported instruction")); },
|
||||
}
|
||||
|
||||
self.timer.execute.end(timer);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
#[macro_use]
|
||||
mod error;
|
||||
mod memory;
|
||||
mod timers;
|
||||
mod cpus;
|
||||
mod devices;
|
||||
|
||||
@ -26,10 +27,10 @@ fn main() {
|
||||
space.insert(0x00700000, Box::new(serial));
|
||||
|
||||
let mut cpu = MC68010::new();
|
||||
cpu.enable_tracing();
|
||||
//cpu.enable_tracing();
|
||||
|
||||
//cpu.add_breakpoint(0x0c94);
|
||||
//cpu.add_breakpoint(0x0cf2);
|
||||
cpu.add_breakpoint(0x103220);
|
||||
|
||||
while cpu.is_running() {
|
||||
match cpu.step(&mut space) {
|
||||
|
72
src/timers.rs
Normal file
72
src/timers.rs
Normal file
@ -0,0 +1,72 @@
|
||||
|
||||
use std::fmt;
|
||||
use std::time::Instant;
|
||||
|
||||
pub struct AverageTimer {
|
||||
pub high: u32,
|
||||
pub average: f32,
|
||||
pub low: u32,
|
||||
pub events: u32,
|
||||
}
|
||||
|
||||
impl AverageTimer {
|
||||
pub fn new() -> AverageTimer {
|
||||
AverageTimer {
|
||||
high: 0,
|
||||
average: 0.0,
|
||||
low: u32::MAX,
|
||||
events: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start(&self) -> Instant {
|
||||
Instant::now()
|
||||
}
|
||||
|
||||
pub fn end(&mut self, timer: Instant) {
|
||||
let time = timer.elapsed().as_nanos() as u32;
|
||||
|
||||
self.events += 1;
|
||||
if time > self.high {
|
||||
self.high = time;
|
||||
}
|
||||
if time < self.low {
|
||||
self.low = time;
|
||||
}
|
||||
self.average = (self.average + time as f32) / 2.0;
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for AverageTimer {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "H: {:8} A: {:4} L: {:8} over {} events", self.high, self.average as u32, self.low, self.events)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub struct CpuTimer {
|
||||
pub decode: AverageTimer,
|
||||
pub execute: AverageTimer,
|
||||
pub cycle: AverageTimer,
|
||||
}
|
||||
|
||||
impl CpuTimer {
|
||||
pub fn new() -> CpuTimer {
|
||||
CpuTimer {
|
||||
decode: AverageTimer::new(),
|
||||
execute: AverageTimer::new(),
|
||||
cycle: AverageTimer::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for CpuTimer {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "Decode: {}\n", self.decode)?;
|
||||
write!(f, "Execute: {}\n", self.execute)?;
|
||||
write!(f, "Cycle: {}\n", self.cycle)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user