* 6809 Debug monitor for use with NOICE09
|
* 6809 Debug monitor for use with NOICE09
|
*
|
*
|
* Copyright (c) 1992-2006 by John Hartman
|
* Copyright (c) 1992-2006 by John Hartman
|
*
|
*
|
* Modification History:
|
* Modification History:
|
* 14-Jun-93 JLH release version
|
* 14-Jun-93 JLH release version
|
* 24-Aug-93 JLH bad constant for COMBUF length compare
|
* 24-Aug-93 JLH bad constant for COMBUF length compare
|
* 25-Feb-98 JLH assemble with either Motorola or Dunfield
|
* 25-Feb-98 JLH assemble with either Motorola or Dunfield
|
* 1-May-06 JLH slight cleanup
|
* 1-May-06 JLH slight cleanup
|
* 4-Jul-06 JEK Modified for System09 ACIA at $E000/$E001
|
* 4-Jul-06 JEK Modified for System09 ACIA at $E000/$E001
|
* 2K monitor RAM at $F000 - $F7FF
|
* 2K monitor RAM at $F000 - $F7FF
|
* Allocated 1536 bytes ($600) for user stack.
|
* Allocated 1536 bytes ($600) for user stack.
|
* disables watchdog timer
|
* disables watchdog timer
|
*
|
*
|
*============================================================================
|
*============================================================================
|
*
|
*
|
* To customize for a given target, you must change code in the
|
* To customize for a given target, you must change code in the
|
* hardware equates, the string TSTG, and the routines RESET and REWDT.
|
* hardware equates, the string TSTG, and the routines RESET and REWDT.
|
* You may or may not need to change GETCHAR, PUTCHAR, depending on
|
* You may or may not need to change GETCHAR, PUTCHAR, depending on
|
* how peculiar your UART is.
|
* how peculiar your UART is.
|
*
|
*
|
* This file has been assembled with the Motorola Freeware assembler
|
* This file has been assembled with the Motorola Freeware assembler
|
* available from the Motorola Freeware BBS and elsewhere.
|
* available from the Motorola Freeware BBS and elsewhere.
|
* BUT: you must first "comment out" the conditionals as required,
|
* BUT: you must first "comment out" the conditionals as required,
|
* because the Motorola assemblers do not have any IFEQ/ELSE/ENDIF
|
* because the Motorola assemblers do not have any IFEQ/ELSE/ENDIF
|
*
|
*
|
* This file may also be assembled with the Dunfield assembler
|
* This file may also be assembled with the Dunfield assembler
|
*
|
*
|
* To add mapped memory support:
|
* To add mapped memory support:
|
* 1) Define map port MAPREG here
|
* 1) Define map port MAPREG here
|
* 2) Define or import map port RAM image MAPIMG here if MAPREG is
|
* 2) Define or import map port RAM image MAPIMG here if MAPREG is
|
* write only. (The application code must update MAPIMG before
|
* write only. (The application code must update MAPIMG before
|
* outputing to MAPREG)
|
* outputing to MAPREG)
|
* 3) Search for and modify MAPREG, MAPIMG, and REG_PAGE usage below
|
* 3) Search for and modify MAPREG, MAPIMG, and REG_PAGE usage below
|
* 4) In TSTG below edit "LOW AND HIGH LIMIT OF MAPPED MEM"
|
* 4) In TSTG below edit "LOW AND HIGH LIMIT OF MAPPED MEM"
|
* to appropriate range (typically 4000H to 07FFFH for two-bit MMU)
|
* to appropriate range (typically 4000H to 07FFFH for two-bit MMU)
|
*
|
*
|
*============================================================================
|
*============================================================================
|
*
|
*
|
* I/O equates for Heng's ROM emulator (set true if used)
|
* I/O equates for Heng's ROM emulator (set true if used)
|
***ROMEM SET 1
|
***ROMEM SET 1
|
*
|
*
|
*============================================================================
|
*============================================================================
|
* HARDWARE PLATFORM CUSTOMIZATIONS
|
* HARDWARE PLATFORM CUSTOMIZATIONS
|
*
|
*
|
*RAM_START EQU $D800 START OF MONITOR RAM
|
*RAM_START EQU $D800 START OF MONITOR RAM
|
RAM_START EQU $F000 START OF MONITOR RAM
|
RAM_START EQU $F000 START OF MONITOR RAM
|
ROM_START EQU $FC00 START OF MONITOR CODE
|
ROM_START EQU $FC00 START OF MONITOR CODE
|
HARD_VECT EQU $FFF0 START OF HARDWARE VECTORS
|
HARD_VECT EQU $FFF0 START OF HARDWARE VECTORS
|
|
|
*============================================================================
|
*============================================================================
|
* Equates for memory mapped 16450 serial port on Heng's ROM emulator board
|
* Equates for memory mapped 16450 serial port on Heng's ROM emulator board
|
*;* IFEQ ROMEM,1
|
*;* IFEQ ROMEM,1
|
*
|
*
|
*S16450 equ $A000 base of 16450 UART
|
*S16450 equ $A000 base of 16450 UART
|
*RXR equ 0 Receiver buffer register
|
*RXR equ 0 Receiver buffer register
|
*TXR equ 0 Transmitter buffer register
|
*TXR equ 0 Transmitter buffer register
|
*IER equ 1 Interrupt enable register
|
*IER equ 1 Interrupt enable register
|
*LCR equ 3 Line control register
|
*LCR equ 3 Line control register
|
*MCR equ 4 Modem control register
|
*MCR equ 4 Modem control register
|
*DTR equ 1 Bit equate used to control status LED
|
*DTR equ 1 Bit equate used to control status LED
|
*LSR equ 5 Line status register
|
*LSR equ 5 Line status register
|
*
|
*
|
* Define monitor serial port
|
* Define monitor serial port
|
*SER_STATUS EQU S16450+LSR
|
*SER_STATUS EQU S16450+LSR
|
*SER_RXDATA EQU S16450+RXR
|
*SER_RXDATA EQU S16450+RXR
|
*SER_TXDATA EQU S16450+TXR
|
*SER_TXDATA EQU S16450+TXR
|
*RXRDY EQU $01 BIT MASK FOR RX BUFFER FULL
|
*RXRDY EQU $01 BIT MASK FOR RX BUFFER FULL
|
*TXRDY EQU $20 BIT MASK FOR TX BUFFER EMPTY
|
*TXRDY EQU $20 BIT MASK FOR TX BUFFER EMPTY
|
*;* ELSE
|
*;* ELSE
|
*
|
*
|
* Put you UART equates here
|
* Put you UART equates here
|
SER_STATUS EQU $E000
|
SER_STATUS EQU $E000
|
SER_RXDATA EQU $E001
|
SER_RXDATA EQU $E001
|
SER_TXDATA EQU $E001
|
SER_TXDATA EQU $E001
|
RXRDY EQU $01
|
RXRDY EQU $01
|
TXRDY EQU $02
|
TXRDY EQU $02
|
*
|
*
|
*;* ENDIF
|
*;* ENDIF
|
*
|
*
|
* Watchdog timer (if any) See REWDT for use
|
* Watchdog timer (if any) See REWDT for use
|
*WDT EQU $207
|
*WDT EQU $207
|
*
|
*
|
* Condition code bits
|
* Condition code bits
|
C EQU 1
|
C EQU 1
|
I EQU 10H
|
I EQU 10H
|
F EQU 40H
|
F EQU 40H
|
E EQU 80H
|
E EQU 80H
|
*
|
*
|
*============================================================================
|
*============================================================================
|
* RAM definitions:
|
* RAM definitions:
|
ORG RAM_START
|
ORG RAM_START
|
*
|
*
|
* RAM interrupt vectors (first in SEG for easy addressing, else move to
|
* RAM interrupt vectors (first in SEG for easy addressing, else move to
|
* their own SEG)
|
* their own SEG)
|
NVEC EQU 8 number of vectors
|
NVEC EQU 8 number of vectors
|
RAMVEC RMB 2*NVEC
|
RAMVEC RMB 2*NVEC
|
*
|
*
|
* Initial user stack
|
* Initial user stack
|
* (Size and location is user option)
|
* (Size and location is user option)
|
* RMB 64
|
* RMB 64
|
RMB $600
|
RMB $600
|
INITSTACK
|
INITSTACK
|
*
|
*
|
* Monitor stack
|
* Monitor stack
|
* (Calculated use is at most 7 bytes. Leave plenty of spare)
|
* (Calculated use is at most 7 bytes. Leave plenty of spare)
|
RMB 16
|
RMB 16
|
MONSTACK
|
MONSTACK
|
*
|
*
|
* Target registers: order must match that in TRGHC11.C
|
* Target registers: order must match that in TRGHC11.C
|
TASK_REGS
|
TASK_REGS
|
REG_STATE RMB 1
|
REG_STATE RMB 1
|
REG_PAGE RMB 1
|
REG_PAGE RMB 1
|
REG_SP RMB 2
|
REG_SP RMB 2
|
REG_U RMB 2
|
REG_U RMB 2
|
REG_Y RMB 2
|
REG_Y RMB 2
|
REG_X RMB 2
|
REG_X RMB 2
|
REG_B RMB 1 B BEFORE A, SO D IS LEAST SIG. FIRST
|
REG_B RMB 1 B BEFORE A, SO D IS LEAST SIG. FIRST
|
REG_A RMB 1
|
REG_A RMB 1
|
REG_DP RMB 1
|
REG_DP RMB 1
|
REG_CC RMB 1
|
REG_CC RMB 1
|
REG_PC RMB 2
|
REG_PC RMB 2
|
TASK_REG_SZ EQU *-TASK_REGS
|
TASK_REG_SZ EQU *-TASK_REGS
|
*
|
*
|
* Communications buffer
|
* Communications buffer
|
* (Must be at least as long as TASK_REG_SZ. At least 19 bytes recommended.
|
* (Must be at least as long as TASK_REG_SZ. At least 19 bytes recommended.
|
* Larger values may improve speed of NoICE memory move commands.)
|
* Larger values may improve speed of NoICE memory move commands.)
|
COMBUF_SIZE EQU 128 DATA SIZE FOR COMM BUFFER
|
COMBUF_SIZE EQU 128 DATA SIZE FOR COMM BUFFER
|
COMBUF RMB 2+COMBUF_SIZE+1 BUFFER ALSO HAS FN, LEN, AND CHECK
|
COMBUF RMB 2+COMBUF_SIZE+1 BUFFER ALSO HAS FN, LEN, AND CHECK
|
*
|
*
|
RAM_END EQU * ADDRESS OF TOP+1 OF RAM
|
RAM_END EQU * ADDRESS OF TOP+1 OF RAM
|
*
|
*
|
*===========================================================================
|
*===========================================================================
|
ORG ROM_START
|
ORG ROM_START
|
*
|
*
|
* Power on reset
|
* Power on reset
|
RESET
|
RESET
|
*
|
*
|
* Set CPU mode to safe state
|
* Set CPU mode to safe state
|
ORCC #I+F INTERRUPTS OFF
|
ORCC #I+F INTERRUPTS OFF
|
LDS #MONSTACK CLEAN STACK IS HAPPY STACK
|
LDS #MONSTACK CLEAN STACK IS HAPPY STACK
|
*
|
*
|
*----------------------------------------------------------------------------
|
*----------------------------------------------------------------------------
|
*;* IFEQ ROMEM,1
|
*;* IFEQ ROMEM,1
|
*
|
*
|
* Initialize S16450 UART on ROM emulator
|
* Initialize S16450 UART on ROM emulator
|
*
|
*
|
* Delay here in case the UART has not come out of reset yet.
|
* Delay here in case the UART has not come out of reset yet.
|
LDX #0
|
LDX #0
|
LOP LEAX -1,X DELAY FOR SLOW RESETTING UART
|
LOP LEAX -1,X DELAY FOR SLOW RESETTING UART
|
NOP
|
NOP
|
NOP
|
NOP
|
BNE LOP
|
BNE LOP
|
*
|
*
|
* access baud generator, no parity, 1 stop bit, 8 data bits
|
* access baud generator, no parity, 1 stop bit, 8 data bits
|
* LDA #$83
|
* LDA #$83
|
* STA S16450+LCR
|
* STA S16450+LCR
|
*
|
*
|
* fixed baud rate of 19200: crystal is 3.686400 Mhz.
|
* fixed baud rate of 19200: crystal is 3.686400 Mhz.
|
* Divisor is 3,686400/(16*baud)
|
* Divisor is 3,686400/(16*baud)
|
* LDA #12 fix at 19.2 kbaud
|
* LDA #12 fix at 19.2 kbaud
|
* STA S16450+RXR lsb
|
* STA S16450+RXR lsb
|
* LDA #0
|
* LDA #0
|
* STA S16450+RXR+1 msb=0
|
* STA S16450+RXR+1 msb=0
|
*
|
*
|
* access data registers, no parity, 1 stop bits, 8 data bits
|
* access data registers, no parity, 1 stop bits, 8 data bits
|
* LDA #$03
|
* LDA #$03
|
* STA S16450+LCR
|
* STA S16450+LCR
|
*
|
*
|
* no loopback, OUT2 on, OUT1 on, RTS on, DTR (LED) on
|
* no loopback, OUT2 on, OUT1 on, RTS on, DTR (LED) on
|
* LDA #$0F
|
* LDA #$0F
|
* STA S16450+MCR
|
* STA S16450+MCR
|
*
|
*
|
* disable all interrupts: modem, receive error, transmit, and receive
|
* disable all interrupts: modem, receive error, transmit, and receive
|
* LDA #$00
|
* LDA #$00
|
* STA S16450+IER
|
* STA S16450+IER
|
*
|
*
|
*;* ELSE
|
*;* ELSE
|
*
|
*
|
* Initialize your UART here
|
* Initialize your UART here
|
LDA #$03 Reset ACIA
|
LDA #$03 Reset ACIA
|
STA SER_STATUS
|
STA SER_STATUS
|
LDA #$11 8 data 2 stop no parity
|
LDA #$11 8 data 2 stop no parity
|
STA SER_STATUS
|
STA SER_STATUS
|
TST SER_RXDATA
|
TST SER_RXDATA
|
*;* ENDIF
|
*;* ENDIF
|
*
|
*
|
*----------------------------------------------------------------------------
|
*----------------------------------------------------------------------------
|
*
|
*
|
* Initialize RAM interrupt vectors
|
* Initialize RAM interrupt vectors
|
LDY #INT_ENTRY ADDRESS OF DEFAULT HANDLER
|
LDY #INT_ENTRY ADDRESS OF DEFAULT HANDLER
|
LDX #RAMVEC POINTER TO RAM VECTORS
|
LDX #RAMVEC POINTER TO RAM VECTORS
|
LDB #NVEC NUMBER OF VECTORS
|
LDB #NVEC NUMBER OF VECTORS
|
RES10 STY ,X++ SET VECTOR
|
RES10 STY ,X++ SET VECTOR
|
DECB
|
DECB
|
BNE RES10
|
BNE RES10
|
*
|
*
|
* Initialize user registers
|
* Initialize user registers
|
LDD #INITSTACK
|
LDD #INITSTACK
|
STA REG_SP+1 INIT USER'S STACK POINTER MSB
|
STA REG_SP+1 INIT USER'S STACK POINTER MSB
|
STB REG_SP LSB
|
STB REG_SP LSB
|
*
|
*
|
LDD #0
|
LDD #0
|
STD REG_PC
|
STD REG_PC
|
STA REG_A
|
STA REG_A
|
STA REG_B
|
STA REG_B
|
STA REG_DP
|
STA REG_DP
|
STD REG_X
|
STD REG_X
|
STD REG_Y
|
STD REG_Y
|
STD REG_U
|
STD REG_U
|
STA REG_STATE initial state is "RESET"
|
STA REG_STATE initial state is "RESET"
|
*
|
*
|
* Initialize memory paging variables and hardware (if any)
|
* Initialize memory paging variables and hardware (if any)
|
STA REG_PAGE initial page is zero
|
STA REG_PAGE initial page is zero
|
*;;; STA MAPIMG
|
*;;; STA MAPIMG
|
*;;; STA MAPREG set hardware map
|
*;;; STA MAPREG set hardware map
|
*
|
*
|
LDA #E+I+F state "all regs pushed", no ints
|
LDA #E+I+F state "all regs pushed", no ints
|
STA REG_CC
|
STA REG_CC
|
*
|
*
|
* Set function code for "GO". Then if we reset after being told to
|
* Set function code for "GO". Then if we reset after being told to
|
* GO, we will come back with registers so user can see the crash
|
* GO, we will come back with registers so user can see the crash
|
LDA #FN_RUN_TARG
|
LDA #FN_RUN_TARG
|
STA COMBUF
|
STA COMBUF
|
JMP RETURN_REGS DUMP REGS, ENTER MONITOR
|
JMP RETURN_REGS DUMP REGS, ENTER MONITOR
|
*
|
*
|
*===========================================================================
|
*===========================================================================
|
* Get a character to A
|
* Get a character to A
|
*
|
*
|
* Return A=char, CY=0 if data received
|
* Return A=char, CY=0 if data received
|
* CY=1 if timeout (0.5 seconds)
|
* CY=1 if timeout (0.5 seconds)
|
*
|
*
|
* Uses 6 bytes of stack including return address
|
* Uses 6 bytes of stack including return address
|
*
|
*
|
GETCHAR
|
GETCHAR
|
PSHS X
|
PSHS X
|
LDX #0 LONG TIMEOUT
|
LDX #0 LONG TIMEOUT
|
GC10 JSR REWDT PREVENT WATCHDOG TIMEOUT
|
GC10 JSR REWDT PREVENT WATCHDOG TIMEOUT
|
LEAX -1,X
|
LEAX -1,X
|
BEQ GC90 EXIT IF TIMEOUT
|
BEQ GC90 EXIT IF TIMEOUT
|
LDA SER_STATUS READ DEVICE STATUS
|
LDA SER_STATUS READ DEVICE STATUS
|
ANDA #RXRDY
|
ANDA #RXRDY
|
BEQ GC10 NOT READY YET.
|
BEQ GC10 NOT READY YET.
|
*
|
*
|
* Data received: return CY=0. data in A
|
* Data received: return CY=0. data in A
|
CLRA CY=0
|
CLRA CY=0
|
LDA SER_RXDATA READ DATA
|
LDA SER_RXDATA READ DATA
|
PULS X,PC
|
PULS X,PC
|
*
|
*
|
* Timeout: return CY=1
|
* Timeout: return CY=1
|
GC90 ORCC #C CY=1
|
GC90 ORCC #C CY=1
|
PULS X,PC
|
PULS X,PC
|
*
|
*
|
*===========================================================================
|
*===========================================================================
|
* Output character in A
|
* Output character in A
|
*
|
*
|
* Uses 5 bytes of stack including return address
|
* Uses 5 bytes of stack including return address
|
*
|
*
|
PUTCHAR
|
PUTCHAR
|
PSHS A
|
PSHS A
|
PC10 JSR REWDT PREVENT WATCHDOG TIMEOUT
|
PC10 JSR REWDT PREVENT WATCHDOG TIMEOUT
|
LDA SER_STATUS CHECK TX STATUS
|
LDA SER_STATUS CHECK TX STATUS
|
ANDA #TXRDY RX READY ?
|
ANDA #TXRDY RX READY ?
|
BEQ PC10
|
BEQ PC10
|
PULS A
|
PULS A
|
STA SER_TXDATA TRANSMIT CHAR.
|
STA SER_TXDATA TRANSMIT CHAR.
|
RTS
|
RTS
|
*
|
*
|
*======================================================================
|
*======================================================================
|
*
|
*
|
* RESET WATCHDOG TIMER. MUST BE CALLED AT LEAST ONCE EVERY LITTLE WHILE
|
* RESET WATCHDOG TIMER. MUST BE CALLED AT LEAST ONCE EVERY LITTLE WHILE
|
* OR COP INTERRUPT WILL OCCUR
|
* OR COP INTERRUPT WILL OCCUR
|
*
|
*
|
* Uses 2 bytes of stack including return address
|
* Uses 2 bytes of stack including return address
|
*
|
*
|
REWDT CLRA
|
REWDT CLRA
|
* STA WDT
|
* STA WDT
|
INCA
|
INCA
|
* STA WDT CU-style WDT: must leave bit high
|
* STA WDT CU-style WDT: must leave bit high
|
RTS
|
RTS
|
*
|
*
|
*======================================================================
|
*======================================================================
|
* Response string for GET TARGET STATUS request
|
* Response string for GET TARGET STATUS request
|
* Reply describes target:
|
* Reply describes target:
|
TSTG FCB 5 2: PROCESSOR TYPE = 6809
|
TSTG FCB 5 2: PROCESSOR TYPE = 6809
|
FCB COMBUF_SIZE 3: SIZE OF COMMUNICATIONS BUFFER
|
FCB COMBUF_SIZE 3: SIZE OF COMMUNICATIONS BUFFER
|
FCB 0 4: NO TASKING SUPPORT
|
FCB 0 4: NO TASKING SUPPORT
|
FDB 0,0 5-8: LOW AND HIGH LIMIT OF MAPPED MEM (NONE)
|
FDB 0,0 5-8: LOW AND HIGH LIMIT OF MAPPED MEM (NONE)
|
FCB B1-B0 9: BREAKPOINT INSTR LENGTH
|
FCB B1-B0 9: BREAKPOINT INSTR LENGTH
|
B0 SWI 10: BREAKPOINT INSTRUCTION
|
B0 SWI 10: BREAKPOINT INSTRUCTION
|
B1 FCC '6809 monitor V1.0' DESCRIPTION, ZERO
|
B1 FCC '6809 monitor V1.0' DESCRIPTION, ZERO
|
FCB 0
|
FCB 0
|
TSTG_SIZE EQU *-TSTG SIZE OF STRING
|
TSTG_SIZE EQU *-TSTG SIZE OF STRING
|
*
|
*
|
*======================================================================
|
*======================================================================
|
* HARDWARE PLATFORM INDEPENDENT EQUATES AND CODE
|
* HARDWARE PLATFORM INDEPENDENT EQUATES AND CODE
|
*
|
*
|
* Communications function codes.
|
* Communications function codes.
|
FN_GET_STAT EQU $FF reply with device info
|
FN_GET_STAT EQU $FF reply with device info
|
FN_READ_MEM EQU $FE reply with data
|
FN_READ_MEM EQU $FE reply with data
|
FN_WRITE_M EQU $FD reply with status (+/-)
|
FN_WRITE_M EQU $FD reply with status (+/-)
|
FN_READ_RG EQU $FC reply with registers
|
FN_READ_RG EQU $FC reply with registers
|
FN_WRITE_RG EQU $FB reply with status
|
FN_WRITE_RG EQU $FB reply with status
|
FN_RUN_TARG EQU $FA reply (delayed) with registers
|
FN_RUN_TARG EQU $FA reply (delayed) with registers
|
FN_SET_BYTE EQU $F9 reply with data (truncate if error)
|
FN_SET_BYTE EQU $F9 reply with data (truncate if error)
|
FN_IN EQU $F8 input from port
|
FN_IN EQU $F8 input from port
|
FN_OUT EQU $F7 output to port
|
FN_OUT EQU $F7 output to port
|
*
|
*
|
FN_MIN EQU $F7 MINIMUM RECOGNIZED FUNCTION CODE
|
FN_MIN EQU $F7 MINIMUM RECOGNIZED FUNCTION CODE
|
FN_ERROR EQU $F0 error reply to unknown op-code
|
FN_ERROR EQU $F0 error reply to unknown op-code
|
*
|
*
|
*===========================================================================
|
*===========================================================================
|
* Common handler for default interrupt handlers
|
* Common handler for default interrupt handlers
|
* Enter with A=interrupt code = processor state
|
* Enter with A=interrupt code = processor state
|
* All registers stacked, PC=next instruction
|
* All registers stacked, PC=next instruction
|
INT_ENTRY
|
INT_ENTRY
|
STA REG_STATE SAVE STATE
|
STA REG_STATE SAVE STATE
|
*
|
*
|
* Save registers from stack to reg block for return to master
|
* Save registers from stack to reg block for return to master
|
* Host wants least significant bytes first, so flip as necessary
|
* Host wants least significant bytes first, so flip as necessary
|
PULS A
|
PULS A
|
STA REG_CC CONDITION CODES
|
STA REG_CC CONDITION CODES
|
PULS A
|
PULS A
|
STA REG_A A
|
STA REG_A A
|
PULS A
|
PULS A
|
STA REG_B B
|
STA REG_B B
|
PULS A
|
PULS A
|
STA REG_DP DP
|
STA REG_DP DP
|
PULS D
|
PULS D
|
STA REG_X+1 MSB X
|
STA REG_X+1 MSB X
|
STB REG_X LSB X
|
STB REG_X LSB X
|
PULS D
|
PULS D
|
STA REG_Y+1 MSB Y
|
STA REG_Y+1 MSB Y
|
STB REG_Y LSB Y
|
STB REG_Y LSB Y
|
PULS D
|
PULS D
|
STA REG_U+1 MSB U
|
STA REG_U+1 MSB U
|
STB REG_U LSB U
|
STB REG_U LSB U
|
*
|
*
|
* If this is a breakpoint (state = 1), then back up PC to point at SWI
|
* If this is a breakpoint (state = 1), then back up PC to point at SWI
|
PULS X PC AFTER INTERRUPT
|
PULS X PC AFTER INTERRUPT
|
LDA REG_STATE
|
LDA REG_STATE
|
CMPA #1
|
CMPA #1
|
BNE NOTBP BR IF NOT A BREAKPOINT
|
BNE NOTBP BR IF NOT A BREAKPOINT
|
LEAX -1,X ELSE BACK UP TO POINT AT SWI LOCATION
|
LEAX -1,X ELSE BACK UP TO POINT AT SWI LOCATION
|
NOTBP TFR X,D TRANSFER PC TO D
|
NOTBP TFR X,D TRANSFER PC TO D
|
STA REG_PC+1 MSB
|
STA REG_PC+1 MSB
|
STB REG_PC LSB
|
STB REG_PC LSB
|
JMP ENTER_MON REG_PC POINTS AT POST-INTERRUPT OPCODE
|
JMP ENTER_MON REG_PC POINTS AT POST-INTERRUPT OPCODE
|
*
|
*
|
*===========================================================================
|
*===========================================================================
|
* Main loop wait for command frame from master
|
* Main loop wait for command frame from master
|
*
|
*
|
* Uses 6 bytes of stack including return address
|
* Uses 6 bytes of stack including return address
|
*
|
*
|
MAIN LDS #MONSTACK CLEAN STACK IS HAPPY STACK
|
MAIN LDS #MONSTACK CLEAN STACK IS HAPPY STACK
|
LDX #COMBUF BUILD MESSAGE HERE
|
LDX #COMBUF BUILD MESSAGE HERE
|
*
|
*
|
* First byte is a function code
|
* First byte is a function code
|
JSR GETCHAR GET A FUNCTION (6 bytes of stack)
|
JSR GETCHAR GET A FUNCTION (6 bytes of stack)
|
BCS MAIN JIF TIMEOUT: RESYNC
|
BCS MAIN JIF TIMEOUT: RESYNC
|
CMPA #FN_MIN
|
CMPA #FN_MIN
|
BLO MAIN JIF BELOW MIN: ILLEGAL FUNCTION
|
BLO MAIN JIF BELOW MIN: ILLEGAL FUNCTION
|
STA ,X+ SAVE FUNCTION CODE
|
STA ,X+ SAVE FUNCTION CODE
|
*
|
*
|
* Second byte is data byte count (may be zero)
|
* Second byte is data byte count (may be zero)
|
JSR GETCHAR GET A LENGTH BYTE
|
JSR GETCHAR GET A LENGTH BYTE
|
BCS MAIN JIF TIMEOUT: RESYNC
|
BCS MAIN JIF TIMEOUT: RESYNC
|
CMPA #COMBUF_SIZE
|
CMPA #COMBUF_SIZE
|
BHI MAIN JIF TOO LONG: ILLEGAL LENGTH
|
BHI MAIN JIF TOO LONG: ILLEGAL LENGTH
|
STA ,X+ SAVE LENGTH
|
STA ,X+ SAVE LENGTH
|
CMPA #0
|
CMPA #0
|
BEQ MA80 SKIP DATA LOOP IF LENGTH = 0
|
BEQ MA80 SKIP DATA LOOP IF LENGTH = 0
|
*
|
*
|
* Loop for data
|
* Loop for data
|
TFR A,B SAVE LENGTH FOR LOOP
|
TFR A,B SAVE LENGTH FOR LOOP
|
MA10 JSR GETCHAR GET A DATA BYTE
|
MA10 JSR GETCHAR GET A DATA BYTE
|
BCS MAIN JIF TIMEOUT: RESYNC
|
BCS MAIN JIF TIMEOUT: RESYNC
|
STA ,X+ SAVE DATA BYTE
|
STA ,X+ SAVE DATA BYTE
|
DECB
|
DECB
|
BNE MA10
|
BNE MA10
|
*
|
*
|
* Get the checksum
|
* Get the checksum
|
MA80 JSR GETCHAR GET THE CHECKSUM
|
MA80 JSR GETCHAR GET THE CHECKSUM
|
BCS MAIN JIF TIMEOUT: RESYNC
|
BCS MAIN JIF TIMEOUT: RESYNC
|
PSHS A SAVE CHECKSUM
|
PSHS A SAVE CHECKSUM
|
*
|
*
|
* Compare received checksum to that calculated on received buffer
|
* Compare received checksum to that calculated on received buffer
|
* (Sum should be 0)
|
* (Sum should be 0)
|
JSR CHECKSUM
|
JSR CHECKSUM
|
ADDA ,S+ ADD SAVED CHECKSUM TO COMPUTED
|
ADDA ,S+ ADD SAVED CHECKSUM TO COMPUTED
|
BNE MAIN JIF BAD CHECKSUM
|
BNE MAIN JIF BAD CHECKSUM
|
*
|
*
|
* Process the message.
|
* Process the message.
|
LDX #COMBUF
|
LDX #COMBUF
|
LDA ,X+ GET THE FUNCTION CODE
|
LDA ,X+ GET THE FUNCTION CODE
|
LDB ,X+ GET THE LENGTH
|
LDB ,X+ GET THE LENGTH
|
CMPA #FN_GET_STAT
|
CMPA #FN_GET_STAT
|
BEQ TARGET_STAT
|
BEQ TARGET_STAT
|
CMPA #FN_READ_MEM
|
CMPA #FN_READ_MEM
|
BEQ JREAD_MEM
|
BEQ JREAD_MEM
|
CMPA #FN_WRITE_M
|
CMPA #FN_WRITE_M
|
BEQ JWRITE_MEM
|
BEQ JWRITE_MEM
|
CMPA #FN_READ_RG
|
CMPA #FN_READ_RG
|
BEQ JREAD_REGS
|
BEQ JREAD_REGS
|
CMPA #FN_WRITE_RG
|
CMPA #FN_WRITE_RG
|
BEQ JWRITE_REGS
|
BEQ JWRITE_REGS
|
CMPA #FN_RUN_TARG
|
CMPA #FN_RUN_TARG
|
BEQ JRUN_TARGET
|
BEQ JRUN_TARGET
|
CMPA #FN_SET_BYTE
|
CMPA #FN_SET_BYTE
|
BEQ JSET_BYTES
|
BEQ JSET_BYTES
|
CMPA #FN_IN
|
CMPA #FN_IN
|
BEQ JIN_PORT
|
BEQ JIN_PORT
|
CMPA #FN_OUT
|
CMPA #FN_OUT
|
BEQ JOUT_PORT
|
BEQ JOUT_PORT
|
*
|
*
|
* Error: unknown function. Complain
|
* Error: unknown function. Complain
|
LDA #FN_ERROR
|
LDA #FN_ERROR
|
STA COMBUF SET FUNCTION AS "ERROR"
|
STA COMBUF SET FUNCTION AS "ERROR"
|
LDA #1
|
LDA #1
|
JMP SEND_STATUS VALUE IS "ERROR"
|
JMP SEND_STATUS VALUE IS "ERROR"
|
*
|
*
|
* long jumps to handlers
|
* long jumps to handlers
|
JREAD_MEM JMP READ_MEM
|
JREAD_MEM JMP READ_MEM
|
JWRITE_MEM JMP WRITE_MEM
|
JWRITE_MEM JMP WRITE_MEM
|
JREAD_REGS JMP READ_REGS
|
JREAD_REGS JMP READ_REGS
|
JWRITE_REGS JMP WRITE_REGS
|
JWRITE_REGS JMP WRITE_REGS
|
JRUN_TARGET JMP RUN_TARGET
|
JRUN_TARGET JMP RUN_TARGET
|
JSET_BYTES JMP SET_BYTES
|
JSET_BYTES JMP SET_BYTES
|
JIN_PORT JMP IN_PORT
|
JIN_PORT JMP IN_PORT
|
JOUT_PORT JMP OUT_PORT
|
JOUT_PORT JMP OUT_PORT
|
|
|
*===========================================================================
|
*===========================================================================
|
*
|
*
|
* Target Status: FN, len
|
* Target Status: FN, len
|
*
|
*
|
* Entry with A=function code, B=data size, X=COMBUF+2
|
* Entry with A=function code, B=data size, X=COMBUF+2
|
*
|
*
|
TARGET_STAT
|
TARGET_STAT
|
LDX #TSTG DATA FOR REPLY
|
LDX #TSTG DATA FOR REPLY
|
LDY #COMBUF+1 POINTER TO RETURN BUFFER
|
LDY #COMBUF+1 POINTER TO RETURN BUFFER
|
LDB #TSTG_SIZE LENGTH OF REPLY
|
LDB #TSTG_SIZE LENGTH OF REPLY
|
STB ,Y+ SET SIZE IN REPLY BUFFER
|
STB ,Y+ SET SIZE IN REPLY BUFFER
|
TS10 LDA ,X+ MOVE REPLY DATA TO BUFFER
|
TS10 LDA ,X+ MOVE REPLY DATA TO BUFFER
|
STA ,Y+
|
STA ,Y+
|
DECB
|
DECB
|
BNE TS10
|
BNE TS10
|
*
|
*
|
* Compute checksum on buffer, and send to master, then return
|
* Compute checksum on buffer, and send to master, then return
|
JMP SEND
|
JMP SEND
|
|
|
*===========================================================================
|
*===========================================================================
|
*
|
*
|
* Read Memory: FN, len, page, Alo, Ahi, Nbytes
|
* Read Memory: FN, len, page, Alo, Ahi, Nbytes
|
*
|
*
|
* Entry with A=function code, B=data size, X=COMBUF+2
|
* Entry with A=function code, B=data size, X=COMBUF+2
|
*
|
*
|
READ_MEM
|
READ_MEM
|
*
|
*
|
* Set map
|
* Set map
|
*;;; LDA 0,X
|
*;;; LDA 0,X
|
*;;; STA MAPIMG
|
*;;; STA MAPIMG
|
*;;; STA MAPREG
|
*;;; STA MAPREG
|
*
|
*
|
* Get address
|
* Get address
|
LDA 2,X MSB OF ADDRESS IN A
|
LDA 2,X MSB OF ADDRESS IN A
|
LDB 1,X LSB OF ADDRESS IN B
|
LDB 1,X LSB OF ADDRESS IN B
|
TFR D,Y ADDRESS IN Y
|
TFR D,Y ADDRESS IN Y
|
*
|
*
|
* Prepare return buffer: FN (unchanged), LEN, DATA
|
* Prepare return buffer: FN (unchanged), LEN, DATA
|
LDB 3,X NUMBER OF BYTES TO RETURN
|
LDB 3,X NUMBER OF BYTES TO RETURN
|
STB COMBUF+1 RETURN LENGTH = REQUESTED DATA
|
STB COMBUF+1 RETURN LENGTH = REQUESTED DATA
|
BEQ GLP90 JIF NO BYTES TO GET
|
BEQ GLP90 JIF NO BYTES TO GET
|
*
|
*
|
* Read the requested bytes from local memory
|
* Read the requested bytes from local memory
|
GLP LDA ,Y+ GET BYTE
|
GLP LDA ,Y+ GET BYTE
|
STA ,X+ STORE TO RETURN BUFFER
|
STA ,X+ STORE TO RETURN BUFFER
|
DECB
|
DECB
|
BNE GLP
|
BNE GLP
|
*
|
*
|
* Compute checksum on buffer, and send to master, then return
|
* Compute checksum on buffer, and send to master, then return
|
GLP90 JMP SEND
|
GLP90 JMP SEND
|
|
|
*===========================================================================
|
*===========================================================================
|
*
|
*
|
* Write Memory: FN, len, page, Alo, Ahi, (len-3 bytes of Data)
|
* Write Memory: FN, len, page, Alo, Ahi, (len-3 bytes of Data)
|
*
|
*
|
* Entry with A=function code, B=data size, X=COMBUF+2
|
* Entry with A=function code, B=data size, X=COMBUF+2
|
*
|
*
|
* Uses 6 bytes of stack
|
* Uses 6 bytes of stack
|
*
|
*
|
WRITE_MEM
|
WRITE_MEM
|
*
|
*
|
* Set map
|
* Set map
|
LDA ,X+
|
LDA ,X+
|
*;;; STA MAPIMG
|
*;;; STA MAPIMG
|
*;;; STA MAPREG
|
*;;; STA MAPREG
|
*
|
*
|
* Get address
|
* Get address
|
LDB ,X+ LSB OF ADDRESS IN B
|
LDB ,X+ LSB OF ADDRESS IN B
|
LDA ,X+ MSB OF ADDRESS IN A
|
LDA ,X+ MSB OF ADDRESS IN A
|
TFR D,Y ADDRESS IN Y
|
TFR D,Y ADDRESS IN Y
|
*
|
*
|
* Compute number of bytes to write
|
* Compute number of bytes to write
|
LDB COMBUF+1 NUMBER OF BYTES TO RETURN
|
LDB COMBUF+1 NUMBER OF BYTES TO RETURN
|
SUBB #3 MINUS PAGE AND ADDRESS
|
SUBB #3 MINUS PAGE AND ADDRESS
|
BEQ WLP50 JIF NO BYTES TO PUT
|
BEQ WLP50 JIF NO BYTES TO PUT
|
*
|
*
|
* Write the specified bytes to local memory
|
* Write the specified bytes to local memory
|
PSHS B,X,Y
|
PSHS B,X,Y
|
WLP LDA ,X+ GET BYTE TO WRITE
|
WLP LDA ,X+ GET BYTE TO WRITE
|
STA ,Y+ STORE THE BYTE AT ,Y
|
STA ,Y+ STORE THE BYTE AT ,Y
|
DECB
|
DECB
|
BNE WLP
|
BNE WLP
|
*
|
*
|
* Compare to see if the write worked
|
* Compare to see if the write worked
|
PULS B,X,Y
|
PULS B,X,Y
|
WLP20 LDA ,X+ GET BYTE JUST WRITTEN
|
WLP20 LDA ,X+ GET BYTE JUST WRITTEN
|
CMPA ,Y+
|
CMPA ,Y+
|
BNE WLP80 BR IF WRITE FAILED
|
BNE WLP80 BR IF WRITE FAILED
|
DECB
|
DECB
|
BNE WLP20
|
BNE WLP20
|
*
|
*
|
* Write succeeded: return status = 0
|
* Write succeeded: return status = 0
|
WLP50 LDA #0 RETURN STATUS = 0
|
WLP50 LDA #0 RETURN STATUS = 0
|
BRA WLP90
|
BRA WLP90
|
*
|
*
|
* Write failed: return status = 1
|
* Write failed: return status = 1
|
WLP80 LDA #1
|
WLP80 LDA #1
|
|
|
* Return OK status
|
* Return OK status
|
WLP90 JMP SEND_STATUS
|
WLP90 JMP SEND_STATUS
|
|
|
*===========================================================================
|
*===========================================================================
|
*
|
*
|
* Read registers: FN, len=0
|
* Read registers: FN, len=0
|
*
|
*
|
* Entry with A=function code, B=data size, X=COMBUF+2
|
* Entry with A=function code, B=data size, X=COMBUF+2
|
*
|
*
|
READ_REGS
|
READ_REGS
|
*
|
*
|
* Enter here from SWI after "RUN" and "STEP" to return task registers
|
* Enter here from SWI after "RUN" and "STEP" to return task registers
|
RETURN_REGS
|
RETURN_REGS
|
LDY #TASK_REGS POINTER TO REGISTERS
|
LDY #TASK_REGS POINTER TO REGISTERS
|
LDB #TASK_REG_SZ NUMBER OF BYTES
|
LDB #TASK_REG_SZ NUMBER OF BYTES
|
LDX #COMBUF+1 POINTER TO RETURN BUFFER
|
LDX #COMBUF+1 POINTER TO RETURN BUFFER
|
STB ,X+ SAVE RETURN DATA LENGTH
|
STB ,X+ SAVE RETURN DATA LENGTH
|
*
|
*
|
* Copy the registers
|
* Copy the registers
|
GRLP LDA ,Y+ GET BYTE TO A
|
GRLP LDA ,Y+ GET BYTE TO A
|
STA ,X+ STORE TO RETURN BUFFER
|
STA ,X+ STORE TO RETURN BUFFER
|
DECB
|
DECB
|
BNE GRLP
|
BNE GRLP
|
*
|
*
|
* Compute checksum on buffer, and send to master, then return
|
* Compute checksum on buffer, and send to master, then return
|
JMP SEND
|
JMP SEND
|
|
|
*===========================================================================
|
*===========================================================================
|
*
|
*
|
* Write registers: FN, len, (register image)
|
* Write registers: FN, len, (register image)
|
*
|
*
|
* Entry with A=function code, B=data size, X=COMBUF+2
|
* Entry with A=function code, B=data size, X=COMBUF+2
|
*
|
*
|
WRITE_REGS
|
WRITE_REGS
|
*
|
*
|
TSTB NUMBER OF BYTES
|
TSTB NUMBER OF BYTES
|
BEQ WRR80 JIF NO REGISTERS
|
BEQ WRR80 JIF NO REGISTERS
|
*
|
*
|
* Copy the registers
|
* Copy the registers
|
LDY #TASK_REGS POINTER TO REGISTERS
|
LDY #TASK_REGS POINTER TO REGISTERS
|
WRRLP LDA ,X+ GET BYTE TO A
|
WRRLP LDA ,X+ GET BYTE TO A
|
STA ,Y+ STORE TO REGISTER RAM
|
STA ,Y+ STORE TO REGISTER RAM
|
DECB
|
DECB
|
BNE WRRLP
|
BNE WRRLP
|
*
|
*
|
* Return OK status
|
* Return OK status
|
WRR80 CLRA
|
WRR80 CLRA
|
JMP SEND_STATUS
|
JMP SEND_STATUS
|
|
|
*===========================================================================
|
*===========================================================================
|
*
|
*
|
* Run Target: FN, len
|
* Run Target: FN, len
|
*
|
*
|
* Entry with A=function code, B=data size, X=COMBUF+2
|
* Entry with A=function code, B=data size, X=COMBUF+2
|
*
|
*
|
RUN_TARGET
|
RUN_TARGET
|
*
|
*
|
* Restore user's map
|
* Restore user's map
|
** LDA REG_PAGE USER'S PAGE
|
** LDA REG_PAGE USER'S PAGE
|
** STA MAPIMG SET IMAGE
|
** STA MAPIMG SET IMAGE
|
** STA MAPREG SET MAPPING REGISTER
|
** STA MAPREG SET MAPPING REGISTER
|
*
|
*
|
* Switch to user stack
|
* Switch to user stack
|
LDA REG_SP+1 BACK TO USER STACK
|
LDA REG_SP+1 BACK TO USER STACK
|
LDB REG_SP
|
LDB REG_SP
|
TFR D,S TO S
|
TFR D,S TO S
|
*
|
*
|
* Restore registers
|
* Restore registers
|
LDA REG_PC+1 MS USER PC FOR RTI
|
LDA REG_PC+1 MS USER PC FOR RTI
|
LDB REG_PC LS USER PC FOR RTI
|
LDB REG_PC LS USER PC FOR RTI
|
PSHS D
|
PSHS D
|
*
|
*
|
LDA REG_U+1
|
LDA REG_U+1
|
LDB REG_U
|
LDB REG_U
|
PSHS D
|
PSHS D
|
*
|
*
|
LDA REG_Y+1
|
LDA REG_Y+1
|
LDB REG_Y
|
LDB REG_Y
|
PSHS D
|
PSHS D
|
*
|
*
|
LDA REG_X+1
|
LDA REG_X+1
|
LDB REG_X
|
LDB REG_X
|
PSHS D
|
PSHS D
|
*
|
*
|
LDA REG_DP
|
LDA REG_DP
|
PSHS A
|
PSHS A
|
*
|
*
|
LDA REG_B
|
LDA REG_B
|
PSHS A
|
PSHS A
|
*
|
*
|
LDA REG_A
|
LDA REG_A
|
PSHS A
|
PSHS A
|
*
|
*
|
LDA REG_CC SAVE USER CONDITION CODES FOR RTI
|
LDA REG_CC SAVE USER CONDITION CODES FOR RTI
|
ORA #E _MUST_ BE "ALL REGS PUSHED"
|
ORA #E _MUST_ BE "ALL REGS PUSHED"
|
PSHS A
|
PSHS A
|
*
|
*
|
* Return to user
|
* Return to user
|
RTI
|
RTI
|
*
|
*
|
*===========================================================================
|
*===========================================================================
|
*
|
*
|
* Common continue point for all monitor entrances
|
* Common continue point for all monitor entrances
|
* SP = user stack
|
* SP = user stack
|
ENTER_MON
|
ENTER_MON
|
TFR S,D USER STACK POINTER
|
TFR S,D USER STACK POINTER
|
STA REG_SP+1 SAVE USER'S STACK POINTER (MSB)
|
STA REG_SP+1 SAVE USER'S STACK POINTER (MSB)
|
STB REG_SP LSB
|
STB REG_SP LSB
|
*
|
*
|
* Change to our own stack
|
* Change to our own stack
|
LDS #MONSTACK AND USE OURS INSTEAD
|
LDS #MONSTACK AND USE OURS INSTEAD
|
*
|
*
|
* Operating system variables
|
* Operating system variables
|
** LDA MAPIMG GET CURRENT USER MAP
|
** LDA MAPIMG GET CURRENT USER MAP
|
LDA #0 ... OR ZERO IF UNMAPPED TARGET
|
LDA #0 ... OR ZERO IF UNMAPPED TARGET
|
STA REG_PAGE SAVE USER'S PAGE
|
STA REG_PAGE SAVE USER'S PAGE
|
*
|
*
|
* Return registers to master
|
* Return registers to master
|
JMP RETURN_REGS
|
JMP RETURN_REGS
|
|
|
*===========================================================================
|
*===========================================================================
|
*
|
*
|
* Set target byte(s): FN, len { (page, alow, ahigh, data), (...)... }
|
* Set target byte(s): FN, len { (page, alow, ahigh, data), (...)... }
|
*
|
*
|
* Entry with A=function code, B=data size, X=COMBUF+2
|
* Entry with A=function code, B=data size, X=COMBUF+2
|
*
|
*
|
* Return has FN, len, (data from memory locations)
|
* Return has FN, len, (data from memory locations)
|
*
|
*
|
* If error in insert (memory not writable), abort to return short data
|
* If error in insert (memory not writable), abort to return short data
|
*
|
*
|
* This function is used primarily to set and clear breakpoints
|
* This function is used primarily to set and clear breakpoints
|
*
|
*
|
* Uses 1 byte of stack
|
* Uses 1 byte of stack
|
*
|
*
|
SET_BYTES
|
SET_BYTES
|
LDU #COMBUF+1 POINTER TO RETURN BUFFER
|
LDU #COMBUF+1 POINTER TO RETURN BUFFER
|
LDA #0
|
LDA #0
|
STA ,U+ SET RETURN COUNT AS ZERO
|
STA ,U+ SET RETURN COUNT AS ZERO
|
LSRB
|
LSRB
|
LSRB LEN/4 = NUMBER OF BYTES TO SET
|
LSRB LEN/4 = NUMBER OF BYTES TO SET
|
BEQ SB99 JIF NO BYTES (COMBUF+1 = 0)
|
BEQ SB99 JIF NO BYTES (COMBUF+1 = 0)
|
*
|
*
|
* Loop on inserting bytes
|
* Loop on inserting bytes
|
SB10 PSHS B SAVE LOOP COUNTER
|
SB10 PSHS B SAVE LOOP COUNTER
|
*
|
*
|
* Set map
|
* Set map
|
*;;; LDA 0,X
|
*;;; LDA 0,X
|
*;;; STA MAPIMG
|
*;;; STA MAPIMG
|
*;;; STA MAPREG
|
*;;; STA MAPREG
|
*
|
*
|
* Get address
|
* Get address
|
LDA 2,X MSB OF ADDRESS IN A
|
LDA 2,X MSB OF ADDRESS IN A
|
LDB 1,X LSB OF ADDRESS IN B
|
LDB 1,X LSB OF ADDRESS IN B
|
TFR D,Y MEMORY ADDRESS IN Y
|
TFR D,Y MEMORY ADDRESS IN Y
|
*
|
*
|
* Read current data at byte location
|
* Read current data at byte location
|
LDA 0,Y
|
LDA 0,Y
|
*
|
*
|
* Insert new data at byte location
|
* Insert new data at byte location
|
LDB 3,X GET BYTE TO STORE
|
LDB 3,X GET BYTE TO STORE
|
STB 0,Y WRITE TARGET MEMORY
|
STB 0,Y WRITE TARGET MEMORY
|
*
|
*
|
* Verify write
|
* Verify write
|
CMPB 0,Y READ TARGET MEMORY
|
CMPB 0,Y READ TARGET MEMORY
|
PULS B RESTORE LOOP COUNT, CC'S INTACT
|
PULS B RESTORE LOOP COUNT, CC'S INTACT
|
BNE SB90 BR IF INSERT FAILED: ABORT
|
BNE SB90 BR IF INSERT FAILED: ABORT
|
*
|
*
|
* Save target byte in return buffer
|
* Save target byte in return buffer
|
STA ,U+
|
STA ,U+
|
INC COMBUF+1 COUNT ONE RETURN BYTE
|
INC COMBUF+1 COUNT ONE RETURN BYTE
|
*
|
*
|
* Loop for next byte
|
* Loop for next byte
|
LEAX 4,X STEP TO NEXT BYTE SPECIFIER
|
LEAX 4,X STEP TO NEXT BYTE SPECIFIER
|
CMPB COMBUF+1
|
CMPB COMBUF+1
|
BNE SB10 *LOOP FOR ALL BYTES
|
BNE SB10 *LOOP FOR ALL BYTES
|
*
|
*
|
* Return buffer with data from byte locations
|
* Return buffer with data from byte locations
|
SB90
|
SB90
|
*
|
*
|
* Compute checksum on buffer, and send to master, then return
|
* Compute checksum on buffer, and send to master, then return
|
SB99 JMP SEND
|
SB99 JMP SEND
|
|
|
*===========================================================================
|
*===========================================================================
|
*
|
*
|
* Input from port: FN, len, PortAddressLo, PAhi (=0)
|
* Input from port: FN, len, PortAddressLo, PAhi (=0)
|
*
|
*
|
* While the 6809 has no input or output instructions, we retain these
|
* While the 6809 has no input or output instructions, we retain these
|
* to allow write-without-verify
|
* to allow write-without-verify
|
*
|
*
|
* Entry with A=function code, B=data size, X=COMBUF+2
|
* Entry with A=function code, B=data size, X=COMBUF+2
|
*
|
*
|
IN_PORT
|
IN_PORT
|
*
|
*
|
* Get port address
|
* Get port address
|
LDA 1,X MSB OF ADDRESS IN A
|
LDA 1,X MSB OF ADDRESS IN A
|
LDB 0,X LSB OF ADDRESS IN B
|
LDB 0,X LSB OF ADDRESS IN B
|
TFR D,Y MEMORY ADDRESS IN Y
|
TFR D,Y MEMORY ADDRESS IN Y
|
*
|
*
|
* Read the requested byte from local memory
|
* Read the requested byte from local memory
|
LDA 0,Y
|
LDA 0,Y
|
*
|
*
|
* Return byte read as "status"
|
* Return byte read as "status"
|
JMP SEND_STATUS
|
JMP SEND_STATUS
|
|
|
*===========================================================================
|
*===========================================================================
|
*
|
*
|
* Output to port FN, len, PortAddressLo, PAhi (=0), data
|
* Output to port FN, len, PortAddressLo, PAhi (=0), data
|
*
|
*
|
* Entry with A=function code, B=data size, X=COMBUF+2
|
* Entry with A=function code, B=data size, X=COMBUF+2
|
*
|
*
|
OUT_PORT
|
OUT_PORT
|
*
|
*
|
* Get port address
|
* Get port address
|
LDA 1,X MSB OF ADDRESS IN A
|
LDA 1,X MSB OF ADDRESS IN A
|
LDB 0,X LSB OF ADDRESS IN B
|
LDB 0,X LSB OF ADDRESS IN B
|
TFR D,Y MEMORY ADDRESS IN Y
|
TFR D,Y MEMORY ADDRESS IN Y
|
*
|
*
|
* Get data
|
* Get data
|
LDA 2,X
|
LDA 2,X
|
*
|
*
|
* Write value to port
|
* Write value to port
|
STA 0,Y
|
STA 0,Y
|
*
|
*
|
* Do not read port to verify (some I/O devices don't like it)
|
* Do not read port to verify (some I/O devices don't like it)
|
*
|
*
|
* Return status of OK
|
* Return status of OK
|
CLRA
|
CLRA
|
JMP SEND_STATUS
|
JMP SEND_STATUS
|
|
|
*===========================================================================
|
*===========================================================================
|
* Build status return with value from "A"
|
* Build status return with value from "A"
|
*
|
*
|
SEND_STATUS
|
SEND_STATUS
|
STA COMBUF+2 SET STATUS
|
STA COMBUF+2 SET STATUS
|
LDA #1
|
LDA #1
|
STA COMBUF+1 SET LENGTH
|
STA COMBUF+1 SET LENGTH
|
BRA SEND
|
BRA SEND
|
|
|
*===========================================================================
|
*===========================================================================
|
* Append checksum to COMBUF and send to master
|
* Append checksum to COMBUF and send to master
|
*
|
*
|
SEND JSR CHECKSUM GET A=CHECKSUM, X->checksum location
|
SEND JSR CHECKSUM GET A=CHECKSUM, X->checksum location
|
NEGA
|
NEGA
|
STA 0,X STORE NEGATIVE OF CHECKSUM
|
STA 0,X STORE NEGATIVE OF CHECKSUM
|
*
|
*
|
* Send buffer to master
|
* Send buffer to master
|
LDX #COMBUF POINTER TO DATA
|
LDX #COMBUF POINTER TO DATA
|
LDB 1,X LENGTH OF DATA
|
LDB 1,X LENGTH OF DATA
|
ADDB #3 PLUS FUNCTION, LENGTH, CHECKSUM
|
ADDB #3 PLUS FUNCTION, LENGTH, CHECKSUM
|
SND10 LDA ,X+
|
SND10 LDA ,X+
|
JSR PUTCHAR SEND A BYTE
|
JSR PUTCHAR SEND A BYTE
|
DECB
|
DECB
|
BNE SND10
|
BNE SND10
|
JMP MAIN BACK TO MAIN LOOP
|
JMP MAIN BACK TO MAIN LOOP
|
|
|
*===========================================================================
|
*===========================================================================
|
* Compute checksum on COMBUF. COMBUF+1 has length of data,
|
* Compute checksum on COMBUF. COMBUF+1 has length of data,
|
* Also include function byte and length byte
|
* Also include function byte and length byte
|
*
|
*
|
* Returns:
|
* Returns:
|
* A = checksum
|
* A = checksum
|
* X = pointer to next byte in buffer (checksum location)
|
* X = pointer to next byte in buffer (checksum location)
|
* B is scratched
|
* B is scratched
|
*
|
*
|
CHECKSUM
|
CHECKSUM
|
LDX #COMBUF pointer to buffer
|
LDX #COMBUF pointer to buffer
|
LDB 1,X length of message
|
LDB 1,X length of message
|
ADDB #2 plus function, length
|
ADDB #2 plus function, length
|
LDA #0 init checksum to 0
|
LDA #0 init checksum to 0
|
CHK10 ADDA ,X+
|
CHK10 ADDA ,X+
|
DECB
|
DECB
|
BNE CHK10 loop for all
|
BNE CHK10 loop for all
|
RTS return with checksum in A
|
RTS return with checksum in A
|
|
|
***********************************************************************
|
***********************************************************************
|
*
|
*
|
* Interrupt handlers to catch unused interrupts and traps
|
* Interrupt handlers to catch unused interrupts and traps
|
* Registers are stacked. Jump through RAM vector using X, type in A
|
* Registers are stacked. Jump through RAM vector using X, type in A
|
*
|
*
|
* This will affect only interrupt routines looking for register values!
|
* This will affect only interrupt routines looking for register values!
|
*
|
*
|
* Our default handler uses the code in "A" as the processor state to be
|
* Our default handler uses the code in "A" as the processor state to be
|
* passed back to the host.
|
* passed back to the host.
|
*
|
*
|
RES_ENT LDA #7
|
RES_ENT LDA #7
|
LDX RAMVEC+0
|
LDX RAMVEC+0
|
JMP 0,X
|
JMP 0,X
|
*
|
*
|
SWI3_ENT LDA #6
|
SWI3_ENT LDA #6
|
LDX RAMVEC+2
|
LDX RAMVEC+2
|
JMP 0,X
|
JMP 0,X
|
*
|
*
|
SWI2_ENT LDA #5
|
SWI2_ENT LDA #5
|
LDX RAMVEC+4
|
LDX RAMVEC+4
|
JMP 0,X
|
JMP 0,X
|
*
|
*
|
* May have only PC and CC's pushed (unless we were waiting for an interrupt)
|
* May have only PC and CC's pushed (unless we were waiting for an interrupt)
|
* Push all registers here for common entry (else we can't use our RAM vector)
|
* Push all registers here for common entry (else we can't use our RAM vector)
|
FIRQ_ENT STA REG_A SAVE A REG
|
FIRQ_ENT STA REG_A SAVE A REG
|
PULS A GET CC'S FROM STACK
|
PULS A GET CC'S FROM STACK
|
BITA #E
|
BITA #E
|
BNE FIRQ9 BR IF ALL REGISTERS PUSHED ALREADY
|
BNE FIRQ9 BR IF ALL REGISTERS PUSHED ALREADY
|
PSHS U,Y,X,DP,B ELSE PUSH THEM NOW
|
PSHS U,Y,X,DP,B ELSE PUSH THEM NOW
|
LDB REG_A
|
LDB REG_A
|
PSHS B
|
PSHS B
|
ORA #E SET AS "ALL REGS PUSHED"
|
ORA #E SET AS "ALL REGS PUSHED"
|
FIRQ9 PSHS A REPLACE CC'S
|
FIRQ9 PSHS A REPLACE CC'S
|
LDA #4
|
LDA #4
|
LDX RAMVEC+6
|
LDX RAMVEC+6
|
JMP 0,X
|
JMP 0,X
|
*
|
*
|
IRQ_ENT LDA #3
|
IRQ_ENT LDA #3
|
LDX RAMVEC+8
|
LDX RAMVEC+8
|
JMP 0,X
|
JMP 0,X
|
*
|
*
|
NMI_ENT LDA #2
|
NMI_ENT LDA #2
|
LDX RAMVEC+12
|
LDX RAMVEC+12
|
JMP 0,X
|
JMP 0,X
|
*
|
*
|
SWI_ENT LDA #1
|
SWI_ENT LDA #1
|
JMP INT_ENTRY
|
JMP INT_ENTRY
|
*
|
*
|
*============================================================================
|
*============================================================================
|
* VECTORS THROUGH RAM
|
* VECTORS THROUGH RAM
|
ORG HARD_VECT
|
ORG HARD_VECT
|
|
|
FDB RES_ENT fff0 (reserved)
|
FDB RES_ENT fff0 (reserved)
|
FDB SWI3_ENT fff2 (SWI3)
|
FDB SWI3_ENT fff2 (SWI3)
|
FDB SWI2_ENT fff4 (SWI2)
|
FDB SWI2_ENT fff4 (SWI2)
|
FDB FIRQ_ENT fff6 (FIRQ)
|
FDB FIRQ_ENT fff6 (FIRQ)
|
FDB IRQ_ENT fff8 (IRQ)
|
FDB IRQ_ENT fff8 (IRQ)
|
FDB SWI_ENT fffa (SWI/breakpoint)
|
FDB SWI_ENT fffa (SWI/breakpoint)
|
FDB NMI_ENT fffc (NMI)
|
FDB NMI_ENT fffc (NMI)
|
FDB RESET fffe reset
|
FDB RESET fffe reset
|
*
|
*
|
END RESET
|
END RESET
|
|
|