Skip to content

Instantly share code, notes, and snippets.

@water111
Last active March 6, 2019 17:45
Show Gist options
  • Save water111/296b4dc0cb345f76784271529d4ac2eb to your computer and use it in GitHub Desktop.
Save water111/296b4dc0cb345f76784271529d4ac2eb to your computer and use it in GitHub Desktop.

Stop

Stops emulation before the next frame begins, using the pause system. Once the emulator reaches this point, it notifies the GUI and all debugger views update. -Pause on VBLANK -Notify GUI

Breakpoint hit

The breakpoints are checked inside of Emotion::run() and IOP::run(), after the next PC is calculated. If there is a hit, the emulator stops immediately, inside the call to do_breakpoints(), and the GUI is notified. The cpu which caused the breakpoint is considered “halted” and will not allow execution to continue until it is unhalted. The emulator thread remains in the cpu’s run() method. Even though the other CPU also stops executing, it is not “halted” and will continue running as soon as it is given the chance. The GUI switches to the processor which has hit the breakpoint and highlights the breakpoints.

  • Check debug_enable flag (only set when there is at least breakpoint for current cpu)
  • If set, check all breakpoints
  • Record all breakpoints which hit
  • If any hit, notify GUI of breakpoint hit list
  • Set halt
  • Stop executing (gets stuck locking halt mutex)

Continue

Continue will try to resume the emulation, regardless of why it has stopped. Its behavior is the same on the EE and the IOP page. After clicking continue, either the EE or the IOP may stop the emulation by hitting a breakpoint, or the user can do a Stop.

  • Unpause if paused
  • Unhalt EE if halted (releases halt mutex)
  • Unhalt IOP if halted (releases halt mutex)

Step

Step will try to make the currently selected CPU execute a single instruction. It does this by

  • Add a breakpoint for the current CPU to trigger after the next instruction
  • Unpause the emulator if it is currently paused
  • Unhalt the CPU

Note that if one CPU is halted, you can still Step the other CPU. Then, when you unhalt the first CPU, the second CPU will halt.

Note that if you Step one CPU, it is possible for the other one to Halt before the Step completes. This will switch the UI over to the other processor. From there, you can click Continue until the Step does complete, which will take you back to the processor you Stepped.

Next

Next will try to go forward one instruction. It is like step, but if the instruction is a function call, it will execute the entire function call before halting. Function calls are recognized as jal and jalr $xx ra. It is also implemented with a breakpoint, so the other CPU may halt before the Next completes.

Finish

Finish will try to finish executing the current function, and halt once control returns to the caller. This is challenging to do reliably - functions may have multiple “jr ra”, may call other functions, and might not push ra to the stack. The most compatible solution I have found is searching forward in the current function for a “jr ra”, then setting a breakpoint to trigger after that “jr ra” branches.

If you try to Finish in a weird assembly function, it may not work properly. Once the emulation stops (either because you Stop, or a CPU halts), you can remove the “finish” breakpoint from the breakpoint list.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment