Skip to content

Commit

Permalink
add fin command
Browse files Browse the repository at this point in the history
  • Loading branch information
pm100 committed Jan 2, 2024
1 parent dbe264b commit 830031b
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 10 deletions.
1 change: 0 additions & 1 deletion build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ fn main() {
println!("cargo:rerun-if-changed=sim65/6502.c");
cc::Build::new()
.file("sim65/6502.c")
// .include("common")
.define("DB65", "1")
.compile("sim65");
}
10 changes: 9 additions & 1 deletion src/debugger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ pub(crate) enum FrameType {
#[derive(Debug)]
pub struct StackFrame {
pub(crate) frame_type: FrameType,
pub(crate) stop_on_pop: bool,
}
#[derive(Debug, Clone)]
pub struct BreakPoint {
Expand Down Expand Up @@ -211,7 +212,14 @@ impl Debugger {
self.execute(0) // 0 = forever
}
}

pub fn finish(&mut self) -> Result<StopReason> {
for i in (0..self.stack_frames.len()).rev() {
if let FrameType::Jsr(_) = self.stack_frames[i].frame_type {
self.stack_frames[i].stop_on_pop = true;
}
}
self.execute(0) // 0 = forever
}
pub fn next(&mut self) -> Result<StopReason> {
let next_inst = Cpu::read_byte(Cpu::read_pc());

Expand Down
38 changes: 30 additions & 8 deletions src/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub enum StopReason {
Count,
Next,
Bug(BugType),
Finish,
}
#[derive(Debug, Clone)]
pub enum BugType {
Expand All @@ -35,18 +36,17 @@ impl Debugger {

let reason = 'main_loop: loop {
let pc = Cpu::read_pc();
/*
Stack tracking code

/*==============================================================
Stack tracking code
if we hit a jsr, we push the return address and the stack pointer
onto our own tracking stack. If we hit a rts, we pop the frame
Also tracks push and pulls
===============================================================*/

Does not deal with interrupts since sim65 does not support them
Includes stack balance check logic
*/
let inst = Cpu::read_byte(pc);
let mut finish = false;
match inst {
0x20 => {
// jsr
Expand All @@ -57,13 +57,18 @@ impl Debugger {
let addr = lo as u16 | ((hi as u16) << 8);
self.stack_frames.push(StackFrame {
frame_type: FrameType::Jsr((addr, pc + 3, sp, 0)),
stop_on_pop: false,
});
}

0x60 => {
// rts
if let Some(frame) = self.stack_frames.pop() {
let sp = Cpu::read_sp();
if frame.stop_on_pop {
// defer til after we execute the rts
finish = true;
}
if self.enable_stack_check {
if let FrameType::Jsr((_addr, _ret_addr, fsp, _)) = frame.frame_type {
if sp + 2 != fsp {
Expand All @@ -88,6 +93,7 @@ impl Debugger {
let ac = Cpu::read_ac();
self.stack_frames.push(StackFrame {
frame_type: FrameType::Pha(ac),
stop_on_pop: false,
});
}

Expand All @@ -104,6 +110,7 @@ impl Debugger {
let sr = Cpu::read_sr();
self.stack_frames.push(StackFrame {
frame_type: FrameType::Php(sr),
stop_on_pop: false,
});
}
0x40 => {
Expand All @@ -115,29 +122,41 @@ impl Debugger {

// Now execute the instruction
self.ticks += Cpu::execute_insn() as usize;

// PVExit called?
if let Some(exit_code) = Cpu::exit_done() {
self.run_done = false;
break StopReason::Exit(exit_code);
}

if Cpu::was_paracall() {
// keep our stack tracker clean
// a PV call opos the stack but we do not see an rts
// so we have a dangling stack frame - pop it
self.stack_frames.pop().ok_or(anyhow!("stack underflow"))?;
}

// invalid memory read check
if self.enable_mem_check {
if let Some(addr) = Cpu::get_memcheck() {
break StopReason::Bug(BugType::Memcheck(addr));
}
}

// limited number of instructions?
if counting {
count -= 1;
if count == 0 {
break StopReason::Count;
}
}
// did we hit a breakpoint?
// did we just pop a stop_on_pop frame?
if finish {
break StopReason::Finish;
}

let pc = Cpu::read_pc();

// did we step over a function call?
if let Some(next) = self.next_bp {
// next stepping bp
if next == pc {
Expand Down Expand Up @@ -168,13 +187,16 @@ impl Debugger {
}
}
}

// did we hit a breakpoint?
if let Some(bp) = self.break_points.get(&pc) {
if bp.temp {
self.break_points.remove(&pc);
}
break StopReason::BreakPoint(pc);
}

// post instruction clean up
Cpu::post_inst_reset();
};
Cpu::post_inst_reset(); // will have been missed on a break
Expand Down
5 changes: 5 additions & 0 deletions src/shell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,10 @@ impl Shell {
self.debugger
.enable_stack_check(*args.get_one::<bool>("stackcheck").unwrap());
}
Some(("finish", _)) => {
let reason = self.debugger.finish()?;
self.stop(reason);
}
Some((name, _matches)) => unimplemented!("{name}"),
None => unreachable!("subcommand required"),
}
Expand Down Expand Up @@ -330,6 +334,7 @@ impl Shell {
let wp = self.debugger.get_watch(addr).unwrap();
println!("watch #{} 0x{:04x} ({}) ", wp.number, wp.addr, wp.symbol);
}
StopReason::Finish => {}
}
// disassemble the current instruction
let inst_addr = self.debugger.read_pc();
Expand Down
6 changes: 6 additions & 0 deletions src/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,4 +152,10 @@ pub fn syntax() -> Command {
.about("enable features")
.help_template(APPLET_TEMPLATE),
)
.subcommand(
Command::new("finish")
.alias("fin")
.about("run till current function returns")
.help_template(APPLET_TEMPLATE),
)
}

0 comments on commit 830031b

Please sign in to comment.