Thursday, 3 April 2014

C65-mode ML Monitor is working

After bashing my head against various CPU speed optimisations lately, with "working" and "faster" seeming to be mutually exclusive for the moment, I turned my attention to a bug I was seeing with the machine language monitor in the C65 ROM.

On the C65, holding down the commodore key during reset or power on boots to C64 mode instead of C65 mode, similar to the C128.

Alternatively, if you hold down the run-stop key instead, it drops you into a machine language monitor, without clearing memory.  This is quite a nice feature.

However, when I had tried this with previous builds, the display of hexadecimal characters was all wrong.  There would be one hex digit, followed by a strange character.  A screen shot is below:

As you can see things are quite wrong.  The colour changes are because printing certain characters on Commodore 8 bit computers causes the drawing colour to change.

So I set about discovering where this problem was.

I knew the monitor sits in its own 8KB part of the ROM as a discrete program.  I also knew that it prints a ">" just before printing a hexadecimal value.  From experience, I also knew that the hex printing routine would likely have four LSR A instructions to shift the high nybl down. This, I figured would help me to find the exact place in the code where things were going wrong.  I hoped to then use the serial monitor debug interface to step through the code and see where it goes awol.

It didn't take too much searching to find the routine in question.  Just looking at it, I was immediately sure that it was a hex printing routine.  Apart from the four LSR's, it had the tell-tale comparison with $0A to work out whether it is printing a digit or letter.  Here is the routine:

69EB  48         PHA 
69EC  63 07 00   BSR $69F5
69EF  AA         TAX 
69F0  68         PLA 
69F1  4A         LSR A
69F2  4A         LSR A
69F3  4A         LSR A
69F4  4A         LSR A
69F5  29 0F      AND #$0F
69F7  C9 0A      CMP #$0A
69F9  90 02      BCC $69FD
69FB  69 06      ADC #$06
69FD  69 30      ADC #$30
69FF  60         RTS 

Staring at it for a few minutes I realised that the problem was the BSR instruction was not doing anything.  

BSR is a cross between JSR and the branch instructions on the 6502.  Like JSR, it pushes the return address to the stack, so you can use RTS to resume execution, but like the branch instructions, it uses relative addressing.

This struck me as odd, because I knew I had implemented that instruction.  However, I hadn't tested it, because I am still in the process of writing a comprehensive CPU test suite for the 4510.  After staring at the relevant VHDL code, I realised the logic error that was preventing the BSR instruction from ever being executed.  

Basically BSR uses 16-bit relative addressing, and before the check for the BSR instruction there is a case for all relative addressing instructions to decide whether to take the branch or not.  Basically BSR was being treated as a conditional branch with an impossible condition.  A quick bit of rearrangement, so that BSR is handled first, and suddenly hex output was working, and the monitor now seems fully functional: 

I had hoped that this would also fix the problem with C65-mode BASIC ignoring all commands, but no such luck.  There must still be at least one more CPU bug in there.  All the more reason to get that test suite written.

No comments:

Post a Comment