sy2002 / QNICE-FPGA

QNICE-FPGA is a 16-bit computer system for recreational programming built as a fully-fledged System-on-a-Chip in portable VHDL.
http://qnice-fpga.com
Other
69 stars 15 forks source link

(Feature Request) Emulator debugger with "step over" capability #194

Closed sy2002 closed 3 years ago

sy2002 commented 3 years ago

In the light of vaxman's even more limited time than mine: Assigning this one to vaxman and myself so that there is not so much pressure on one person to do this one here - might be some nice excercise "over Chrismas" also for me :-)

Today we have the step feature which can be used to perform single step debugging. It always follows a "step into" semantic, i.e. in this code snippet, all the RSUB paths will be taken:

                MOVE    @R8, R8                 ; output amount of changed..      
                MOVE    INPUTSCRATCH, R9        ; palette entries
                RSUB    WORD2HEXSTR, 1
                MOVE    R9, R8
                RSUB    UART_PUTS, 1
                MOVE    STR_LS_NEWLINE, R8
                RSUB    UART_PUTS, 1

                MOVE    @R1++, R3               ; R3: amount of changes

If one would prefer to step over these RSUBs, then you need to change your breakpoint manually to the next comand.

This is very cumbersome, particularly when debugging a bit larger programs.

Since our "real" debugging capabilities will probably and realistically take same more years to unfold, it might be a nice pain relief to have at least this "step over" capability.

The comand might be named stepover (new comand) - or - the existing step comand receives some more parameters.

Sidenote (which might be done while implementing this issue): Also it might be helpful to have a parameter for step and stepover that immediatelly shows a regdump after stepping. Something like step [address] [into|over] [showregs]. Since we are having a command history in the meantime, one could just press (repeatedly) UP ARROW walk through the command history and repeat the old command(s), so it does not matter, if the paramter names are a bit more verbose such as step into showregs and step over showregs.

bernd-ulmann commented 3 years ago

Would a variant of the step command suffice which just runs without stepping/stopping until it encounters a MOVE @R13++, R15 i.e. a RET-instruction?

sy2002 commented 3 years ago

If this very MOVE @r13++, R15 would then also be executed, then this would be rather close to a step-over semantics albeit not exactly it. Yet - for sure better than nothing ;-)

MJoergen commented 3 years ago

What if the RSUB jumps into a subroutine with another RSUB, i.e. nested subroutines? Then we would need to maintain state information of the nesting level, i.e. count the number of RSUB's and RET's.

bernd-ulmann commented 3 years ago

The emulator could keep a global nesting counter which is incremented by each RSUB/ASUB and decremented by each MOVE @R13++, R15. An so (step-over) command would the run the machine as long until this global nesting counter reaches its previous level again.

bernd-ulmann commented 3 years ago

The emulator now has a new global variable gbl$nesting_depth that counts the overall depth of nested subroutine calls. This value is als printed when rdump is executed. This may be a first step towards the desired step over functionality. :-)

bernd-ulmann commented 3 years ago

The emulator now support a new command: so (short for step-over). Its behaviour is best explained with this short test program:

000603                                                .ORG 0x8000
000604  8000  0FB4  FF00                              MOVE 0xFF00, R13
000605  8002  FF90  8005                              ASUB L1, 1
000606  8004  E000                                    HALT
000607                    ;
000608  8005  0F84  0001  L1                          MOVE 0x0001, R1
000609  8007  FFB0  0001                              RSUB L2, 1
000610  8009  0DBC                                    MOVE @R13++, R15
000611  800A  0F88  0002  L2                          MOVE 0x0002, R2
000612  800C  0DBC                                    MOVE @R13++, R15

Starting it with

step $8000

executes the first instruction and stops at address $8002. Typing

so

now causes run to run until the subroutine nesting depth is increased by at least one with respect to the current nesting depth and then drops back to the value it had when the so command was invoked:

[0000] Q> step $8000
[8002] Q> so
[8004] Q> step
HALT instruction executed at address 8004.

I hope I did not break anything but my quick test looked quite promising. :-) Good night!

sy2002 commented 3 years ago

🚀 This sounds exactly like what is needed 😃 I will work with it on "Nerd Saturday" and report back.

bernd-ulmann commented 3 years ago

I just made a small change to the emulator. The "so" command will now also halt when the current nesting depth falls below the depth saved when so was issued. Thus so can also be used within (and not at the point of calling it) a subroutine and will stop at the final RET.

So "so" can now be used as follows:

sy2002 commented 3 years ago

Sounds great! 👍

sy2002 commented 3 years ago

Tested it: Works like a charm. Closing.