Summer has been good in Sweden and besides spending time in the sun or repairing overheated RAID arrays I've had some time left over over lately to tie up the loose ends of my latest version of the MC3 monitor program. It's been a low paced on-and-off work since spring and now I've finally put together what I had and made a proper release.
Changes from version 1.3
- Streamlining of static texts and user error handling for all commands
- Added single step function
- Interrupt vectors are now properly initialized on reset
- Added ability to move stack pointer
- Added I/O access helper routines
- Added memory write function for more intuitive machine code input
Complete list of available commands.
G Go (RTI)
J Jump to address
L Load S19 from console
MC Memory change
MD Memory dump
MF Memory fill
MW Memory write
RR Print contents of stack
RC Change stack CC
RA Change stack A
RB Change stack B
RX Change stack X
RP Change stack PC
RS Change stack pointer
RM Reset stack pointer
P Select I/O page
S Single step
X Enter extended ROM
Single stepping using timed interrupts
The single step function is rather unusual. Most single step routines I've seen has been relying on replacing op-codes with SWI (software interrupt) op-codes for halting the program flow. The major problem is how to handle forks in the program flow (conditional branches etc) and to ensure that the code is not destroyed by the single step routine itself. To avoid all of this I've used the built-in timer of the 6303. This timer is clocked by the same clock as the CPU core and therefore keeping it synchronous to the code execution and it also has it's own interrupt vectors differentiating the timer interrupts from other interrupts.
Performing a single step is done by setting up the 6303 built-in timer to trigger an interrupt just after the CPU fetches the next op-code. The CPU finishes the op-code and then follows the timer interrupt vector back to the monitor where the contents of the stack is visualized and can be altered before another step can be performed. Using the timer in this way gets rid of all uncertainty of altering the code on the fly or simulating conditional branches. It also makes it possible to single step code in ROM! The single step routine can distinguish from user code and code from the monitor itself so routines in monitor ROM are simply skipped over for convenience (the monitor routines should be... ehm... thoroughly debugged anyway).
This single stepping feature as proven quite useful as I was debugging FLEX2 for the MC3. I have actually used my MC3 to run and develop
6809 code using the Micro Works 6809
emulator for 6800. That way I can run FLEX9 but still use my 6303 hardware and mass storage driver code. That emulator is some crazy stuff written in 1978 and it was easily adapted to my MC3. Nice coding Micro Works!
The goal is to get FLEX9 going on
Tom LeMense's HD6309 SBC. Tom is another devoted 68xx enthusiast with some serious skills and a more modern approach to his designs compared to my ancient VHDL-less circuits. You should really check out his
HD6309SBC project page at Hackaday!
Below is the entire single step routine as included in monitor 1.4.
***************
* DO SINGLE STEP
SSTEP JSR PCRLF
STEP LDS SP RESTORE PROGRAM STACK POINTER
LDAB #$1F
STPWAI DECB WAIT FOR EVENTUAL SCI XFER
CMPB #$00 BEFORE TIMER INIT
BNE STPWAI
LDX #STOP SET INTERRUPT VECTOR
STX TMOFVEC+1
LDX #$FFEC RESET COUNTER VALUE
STX COUNTHI
LDX TIMECON CLEAR INTERRUPT BIT IN TIMER CTRL REG
LDAA #$04 ENABLE TIMER OVERFLOW INTERRUPT
STAA TIMECON
CLI CLEAR INTERRUPT BIT IN CC
RTI
***************
* SINGLE STEP INTERRUPT ENTRY
STOP STS SP SAVE PROGRAM STACK POINTER
LDX #INTSEQ RESTORE INTERRUPT VECTOR
STX TMOFVEC+1
LDX TIMECON CLEARS INTERRUPT BIT IN TIMER CTRL REG
LDAA #$00 DISABLE TIMER INTERRUPT
STAA TIMECON
LDX SP EXTRACT PROGRAM STOP ADDRESS
LDAB #6
ABX
LDX ,X
CPX #$C000
BHI STEP NO STOP IN ROM
STX XTEMP
LDAB XTEMP
CMPB #$7F
BEQ STEP NO STOP IN PAGE $7F
LDX #STOPTX
JSR PDATA
JMP PRTREG PRINT REGS AND GO TO PROMPT
There is an extra dummy loop at the beginning since altering the timer while the serial interface is active can (and will) corrupt an ongoing transmission. The data sheet is clear about this and it is caused by the fact that some circuitry is shared between the timer and the serial interface.
I/O helper routines
Since the external memory bus of the MC3 is paged there are occasions where programs running from external memory needs to access memory or I/O devices in another page. That causes problems since swapping out a page with active code will crash the system. Therefore I have included two I/O access functions in the monitor ROM to handle this. One for reading a paged byte (
IORD) and one for writing a paged byte (
IOWR). The two functions, when called, transfers control to the monitor ROM which swaps the I/O page and accesses the byte needed and then swaps the page back again and returns to the calling program. A severe performance degradation but very simple to manage.
Source of IORD and IOWR below.
***************
* I/O READ FUNCTION
* IN: X = ADDRESS
* B = I/O PAGE
* OUT: A = DATA
IORD LDAA PIA1DAT
PSHA SAVE PAGE REG
STAB PIA1DAT SET NEW I/O PAGE
LDAA ,X ACCESS I/O PAGE
PULB
STAB PIA1DAT RESTORE PAGE REG
RTS
***************
* I/O WRITE FUNCTION
* IN: X = ADDRESS
* B = I/O PAGE
* A = DATA
IOWR PSHA SAVE DATA
LDAA PIA1DAT
PSHA SAVE PAGE REG
STAB PIA1DAT SET NEW I/O PAGE
PULB RESTORE PAGE REG VALUE
PULA RESORE DATA VALUE
STAA ,X ACCESS I/O PAGE
STAB PIA1DAT RESTORE PAGE REG
RTS
Jumptable at beginning of monitor.
RETURN EQU $C000 RETURN TO MONITOR
OUTCHAR EQU $C003 OUTPUT CHAR ON CONSOLE
INCHAR EQU $C006 INPUT CHAR FROM CONSOLE AND ECHO
PDATA EQU $C009 PRINT TEXT STRING @ X ENDED BY $04
OUTHR EQU $C00C PRINT RIGHT HEX CHAR @ X
OUTHL EQU $C00F PRINT LEFT HEX CHAR @ X
OUT2HS EQU $C012 PRINT 2 HEX CHARS @ X
OUT4HS EQU $C015 PRINT 4 HEX CHARS @ X
INHEX EQU $C018 INPUT 1 HEX CHAR TO A. CARRY SET = OK
INBYTE EQU $C01B INPUT 1 BYTE TO A. CARRY SET = OK
BADDR EQU $C01E INPUT ADDRESS TO X. CARRY SET = OK
PCRLF EQU $C021 PRINT CRLF
OUTS EQU $C024 PRINT SPACE
IORD EQU $C027 I/O READ
IOWR EQU $C02A I/O WRITE
Source
Below is the source for the new MC3 monitor.
Monitor 1.4 -
source listing s19 ($C000-$C7DC)
Quickfile 1.0 -
source listing s19 ($D000 - $DA3C)
I have included the Quickfile source as well even though it's unchanged since previous version.