home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-09-21 | 172.8 KB | 7,766 lines |
- ;-------------------------------------------------------
- ; SUPER8 Monitor Firmware, for the S8 contest board
- ; This version altered for META assembler
- ;
- ;
- ;
- ; init.s8:
- ; (1) Entry point for monitor.
- ; (2) Initialization routines for monitor.
- ; (3) Interrupt routines for Serial Input.
- ; (4) Console I/O routines
- ;
- ;
- ; 3/1/87 Start fixing things up
- ;
- ; 1) Clean up binary to ascii routines
- ; 2) Disable HOST_DELAY
- ; 3) CLean up breakpoint stuff
- ; 4) TRACE
- ; 5) Clean up op table
- ;
- ; Things that would be nice to do:
- ;
- ; a) Shift some of the montor registers & stack to RAM
- ; b) Preserve ALL user registers in monitor
- ;
- ;*****************************************************
- ;*
- ;* Constants and register usage used by
- ;* all or some of the software modules.
- ;*
- ;******************************************************;
- ; register allocation
-
- WORKREGS equ $80 ; working registers
-
- ALT_PC equ $90 ; used by TRACE
- TX_MODE equ $92 ; X_ON/X_OFF mode
- USER_RP0 equ $93 ; user RP0
- USER_RP1 equ $94 ; user RP1
- USER_FLAGS equ $95 ; user flag reg
- USER_PC equ $96 ; user PC
- USERPC_HI equ $96 ; user PC high
- USERPC_LO equ $97 ; user PC low
- REG_MODE equ $98 ; current reg disp. mode
- ERR_CODE equ $99 ; error code
- ECHO_MODE equ $9A ; echo on/off mode
- SIO_MODE equ $9B ; mode register
- CFLAG equ $9C ; CFLAG register
- OUTPTR equ $9D ; offset in output buff.
- OUTLEN equ $9E ; length of output str.
- INPTR equ $9F ; offset in input buff.
- PUTCHRPTR equ $A0 ; output offset
- GETCHRPTR equ $A1 ; output offset
- RETRY equ $A2 ; load record retries
- USER_EI equ $A3 ; user EI status
- REGBUF equ $A4 ; temp reg buffer
- ; 4 registers long
- OUT_CHR1 equ $A8 ; char output reg
- OUT_CHR2 equ $A9 ; char output reg
- D_MEMFLAG equ $AA ; data/prog. memory
- STX_ETX equ $AB ; STX_ETX mode
- HOSTGET equ $AC ; host input offset
- HOSTPUT equ $AD ; host output offset
- USER_IMR equ $AE ;
-
- ; registers used by ZAP command
- DIS_CT equ $AE ; instructon count
- BYTE_1 equ $AF ; 1st byte
- BYTE_2 equ $B0 ; 2nd byte
- BYTE_3 equ $B1 ; 3rd byte
- BYTE_4 equ $B2 ; 4th byte
- AD_IN_HI equ $B3 ; instruction addr
- AD_IN_LO equ $B4
- AD_OUT_HI equ $B5 ; output pointer
- AD_OUT_LO equ $B6
- AD_TBL_HI equ $B7 ; table pointer
- AD_TBL_LO equ $B8
- TYPE_ equ $B9 ; instruction type
- USER_SP equ $BA ; two bytes
-
- ; Monitor Ram locations
- ;
- ;relocated interrupt vectors
- INTV0: equ $E000 ; interrupt vector 0
- INTV1: equ $E003 ; interrupt vector 1
- INTV2: equ $E006 ; interrupt vector 2
- INTV3: equ $E009 ; interrupt vector 3
- INTV4: equ $E00C ; interrupt vector 4
- INTV5: equ $E00F ; interrupt vector 5
- INTV6: equ $E012 ; interrupt vector 6
- INTV7: equ $E015 ; interrupt vector 7
- INTV8: equ $E018 ; interrupt vector 8
- INTV9: equ $E01B ; interrupt vector 9
- INTV10: equ $E01E ; interrupt vector 10
- INTV11: equ $E021 ; interrupt vector 11
- INTV12: equ $E024 ; interrupt vector 12
- INTV13: equ $E027 ; interrupt vector 13
- INTV14: equ $E02A ; interrupt vector 14
- INTV15: equ $E02D ; interrupt vector 15
- ;
- ;
- USER_STACK equ $FB00 ; one is required for GO to work
- INBUF equ $FB00 ; 256 byte Serial input buffer
- HOSTBUF equ $FC00 ; 256 byte Host buffer
- CONIBF equ $FD00 ; 256 byte console input buffer
- CONOBF equ $FE00 ; 256 byte console output buffer
- T_CODE equ $FF00 ; 7 bytes used by TRACE
-
- BP1_SAVE equ $FFF0 ; 3 byte save for breakpointed inst.
- BP1_ADDR equ $FFF3 ; Addres of breakpted intruction.
- I_CODE equ $FFF5 ; I_CODE execute location (4 bytes max)
- ECHO_STAT equ $FFF6 ; 1 byte saved echo status
- REG_READ equ $FFF7 ; 1 byte pass location for register reads
- WARMSTART equ $FFF8 ; 4 byte warm start pattern location
-
-
- ; RAM CONSTANTS
- BUF_LGTH equ $46 ; ZAP output buff. size
-
- ; transmit mode
- X_ON equ $01 ; X_ON mode
- X_OFF equ $00 ; X_OFF mode
-
- ; register display mode flags
- S_FLAG equ $01 ; systems registers
- C_FLAG equ $02 ; control registers
- GEN_FLAG equ $04 ; gen. purpose registers
- ZERO_FLAG equ $08 ; bank zero flag
- ONE_FLAG equ $10 ; bank one flag
-
- ; serial line mode
- NORMAL_MODE equ $01 ; command mode
- LOAD_MODE equ $02 ; load mode
- EXT_MODE equ $80 ; load extension
- ; area
-
- ; echo mode
- ECHO_ON equ $01 ; echo on
- ECHO_OFF equ $00 ; echo off
-
-
- ; CFLAG
- LOAD_SEND equ $20 ; BIT 5 LOAD/SEND
- GETMEMFLG equ $40 ; BIT 6 GETMEMFLG
- LASTCMD equ $80 ; BIT 7 LASTCMD
- CLSTCMD equ $7F ; COMPLEMENT OF LASTCMD. FIX OF ASSEMBLER BUG
- ; error codes
- BAD_CMD equ $01 ; invalid command
- MIS_PARAM equ $02 ; missing parameter
- BAD_HEX equ $03 ; bad hex value
- BAD_OPT equ $04 ; bad option
- LOADABORT equ $05 ; load aborted by host
- ABSEND equ $06 ; load aborted by EM
- FILE_ERR equ $07 ; file error
- BAD_PARAM_VAL equ $08 ; value out of range
- BAD_EXT_ADDR equ $09 ; bad extension load addr
-
-
- ASCIICR equ $0D ; ASCII char. vlaues
- ASCIISP equ $20
- ASCIILF equ $0A
- ASCIIESC equ $1B
- ASCBKSP equ $08
- ASCIIQ equ $51
- ASCIIUP equ $5E
- ASCIIDOT equ $2E
- ASCIISTAR equ $2A
- ASCIIEQ equ $3D
- ASCIIDEL equ $7F
- ASCIITAB equ $09
- ASCIIDSH equ $2D
- ASCIICTLS equ $13
- ASCIICTLQ equ $11
- ASCIISTX equ $02
- ASCIIETX equ $03
-
- ;-----------------------------------
- ; Some constants that control things
-
- CHR_DELAY equ $25 ; character output delay variable
- ; use $0E for 12.0 MHz crystal
- ; use $05 for 7.37 MHz crystal
- CRLF_DELAY equ $08 ; initialize CRLF output delay variable
- ; use $03 for 12.0 MHz crystal
- ; use $02 for 7.37 MHz crystal
-
-
- SYS_EMT equ %00101011 ; INternal stack for monitor
- USR_EMT equ %00101011 ; external stack for user
- SYS_STACK equ $FFEF ; sys. stack base
- ;----------------------------------------------------------------------
- ;
- ; Interrupt vectors
- ;
-
-
- ORG $000
-
- dw INTV0 ;
- dw INTV1 ;
- dw INTV2 ;
- dw INTV3 ;
- dw INTV4 ;
- dw INTV5 ;
- dw INTV6 ;
- dw INTV7 ;
- dw INTV8 ;
- dw INTV9 ;
- dw INPUTINT ; Serial input interrupt routine
- dw INTV11 ;
- dw INTV12 ;
- dw INTV13 ;
- dw INTV14 ;
- dw INTV15 ;
-
-
-
- INITS8:
- ;*********************************************************
- ;*
- ;* INITS8 Initailize the monitor S8 processor and
- ;* registers
- ;*
- ;**********************************************************;
- ; org $0020
-
- EI ; enable writes to IMR
- DI ; disable interrupts
-
- ; initialize ports and control registers
-
- ld IPR,#$18 ; Priority: B>A>C
- ld IMR,#$00 ; IRQ6 (Serial input) polled mode
- ld IRQ,#$00 ; clear IRQ6
-
- ; initialize ports
-
- ld P2AM,#%10001010 ; Outputs: P31,P20,P21, INPUTS: P30
- ld P2BM,#%00000010 ; : P22 : P33,P32,P23
- ld P2CM,#%00001000 ; : P25 : P35,P34,P24
- ld P2DM,#%00000010 ; : P26 : P37,P36,P27
-
- ; Enable the address/data bus, 16 address lines & internal stack
-
- ld PM,#%00110000 ; Port 1 AD0 - AD7
- ld P0M,#%11111111 ; Port 0 A8 - A15
- ld EMT,#SYS_EMT ; Internal stack
-
- ; internal stack during initialization, self test
- ldw SP,#SYS_STACK ; Init stack to top
- SRP #$C0 ; set reg. pointer to temp value
-
- ; Set baud rate to 9600 bps
-
- sb1
- ld UMA,#%01110000 ; X16 clock, 8 bit/char, no parity
-
- ldw UBG,#7 ; set up for bit rate of
- ; 9600, continuous mode
- ; For XTAL = 12.0 MHz use 0009
- ; XTAL = 19.6 MHz use 0015
- ld UMB,#%00011110 ; P21 data, no clock out
- ; auto echo disabled, use BRG for
- ; TxC and RxC, Enable BRG
- sb0 ;
- ld UTC,#%10001000 ; P31 - TxD out, no break, 1 stop bit
- ; No wake-up, transmitter enabled
- ld URC,#%00000010 ; Enable the reciver
- ld UIE,#%00000000 ; disable all interrupts
-
- ; Clear register file (registers $00 thru $BF)
-
- ld R4,#$00 ; R4 points to $00
- ld R5,#$BF ; r5 has count
- CLEAR_VAR:
- CLR @R4 ; clear it
- INC R4 ; point to next register
- DJNZ R5,CLEAR_VAR ; Loop till done
-
- ld TX_MODE,#X_ON ; initialize transmit mode
- ld SIO_MODE,#NORMAL_MODE ; set input mode
- ld STX_ETX,#ECHO_ON ; set STX_ETX to echo
- ld ECHO_MODE,#ECHO_ON ; initialize echo mode on for terminal
- AND CFLAG,#CLSTCMD ; clear the go
-
- ; initialize the interrupt table in ram
-
- call INT_TAB_REL
-
- ; Wait for a <CR> from Host or terminal
-
- WAIT: TM URC,#%00000001 ; Wait for recieved char
- jr z,WAIT ; 1=char received
- ld r0,UIO ; Get char
- and r0,#$7F ; Mask off upper bit
- cp r0,#$0D ; Is it a <CR> ?
- jr eq,WAIT1 ; if so, continue
- cp r0,#$0A ; some systems transmit <LF>
- jr ne,WAIT ; Keep waiting if not
-
- ; Clear the screen
- WAIT1:
- call SEND_STX
- ld R8,#$20 ; clear screen
-
- CLEAR_LOOP: ; with 32 CRs
- call CRLF
- DJNZ R8,CLEAR_LOOP
- call SEND_ETX
-
- ; check for warm start
- call IS_WARM ; set C if warm start
- JR C,WARM_START ; yes
- call COLD_START ; no, cold start
-
- WARM_START:
-
- ldw rr6,#^LB BP1_ADDR ; Clear any breakpoint set
- ld r0,#$00
- ldc @rr6,r0
- incw rr6
- ldc @rr6,r0
- ldw USER_SP,#USER_STACK
-
- READ_SIZE:
- ; initialize system, control registers for monitor
- SRP #WORKREGS ; set reg. pointer
- ld FLAGS,#$00 ; clear flags
- ld IPR,#$18 ; B>A>C
- ld IMR,#$40 ; enable IRQ6 - Serial input
- ld IRQ,#$00 ; nothing pending
- ld UIE,#%00000001 ; Enable RxChar INT
-
- HDR_DISP:
- EI ; enable interrupts
-
- ;
- ;
- ; Display sign-on header message.
- ;
- ;
-
-
- ; delay and let host catch up
- call HOST_DELAY
-
- ; if echoing, request "e -0" from host
- CP ECHO_MODE,#ECHO_OFF ; echoing?
- JR EQ,MAIN ; no, skip request
- call SEND_STX ; leading STX
- ; nothing in between
- call SEND_ETX ; trailing ETX
-
- ; delay and let host catch up
- call HOST_DELAY
- call SEND_STX
- call CRLF
- call CRLF
- call CRLF
- call SEND_ETX
-
- ; delay before output of header to host
- call HOST_DELAY
-
- call SEND_STX
- LDW RR6,#STRT_MSG ; output header
- call OUTMSG
- LDW RR6,#REV_MSG
- call OUTMSG
- call SEND_ETX
- call HOST_DELAY
-
- call SEND_STX
- LDW RR6,#DATE_MSG
- call OUTMSG
- call SEND_ETX
- call HOST_DELAY
-
- ld R8,#$06 ; center header
- call SEND_STX
- CENTER_SCR:
- call CRLF
- DJNZ R8,CENTER_SCR
- call SEND_ETX
-
- ; delay and let host catch up
- call HOST_DELAY
-
- ; if echoing, request "e -0" from host
- CP ECHO_MODE,#ECHO_OFF ; echoing?
- JR EQ,MAIN ; no, skip request
- call SEND_STX ; leading STX
- ; nothing in between
- call SEND_ETX ; trailing ETX
-
- ; delay and let host catch up
- call HOST_DELAY
-
- ;------------------------------------------------------------------------------
- ; Main program loop
- ; Loop here for commands to execute
- ;
-
- MAIN:
-
- AND CFLAG,#CLSTCMD ; clear the GO flag
- call CMD_STATUS ; indicate cmd mode
- CLR D_MEMFLAG ; reset D_MEMFLAG
- call SEND_STX ; start msg
- ld R4,#'S' ; issue "S8>"
- call OUTCHR
- ld R4,#'8'
- call OUTCHR
- ld R4,#'>'
- call OUTCHR
- call SEND_ETX ; end msg
-
- GET_RESPONSE:
- ld STX_ETX,#ECHO_ON ; enable echo
- call GETLINE ; get the response
-
- PROCESS_CMD:
- CP R4,#ASCIICR ; a CR?
- JR EQ,MAIN ; yes, ignore
-
- CLR ERR_CODE
- call MATCH_CMD ; match the command
- CP ERR_CODE,#0 ; command error?
- JR EQ,CHECK_ETX ; no
- call OUT_ERROR ; yes, output message
-
- CHECK_ETX:
- CP STX_ETX,#ECHO_OFF ; invisible last cmd?
- JR NE,MAIN ; no
- JR GET_RESPONSE ; yes, no new promt
- JR MAIN ; re-enter main
-
-
- HOST_DELAY
- ;*********************************************************
- ; Delay for Host Package to catch up
- ;
- ; Deleted for CP/M
-
- ; ld R5,#$20
- ;CATCH_UP:
- ; ld R4,#$ff
- ; call DELAY
- ; DJNZ R5, CATCH_UP
- RET
-
-
- IS_WARM:
- ;***************************************************
- ;*
- ;* IS_WARM Read warm start pattern location.
- ;* If pattern is valid set carry flag.
- ;* Otherwise reset carry flag.
- ;*
- ;***************************************************;
-
- LDW RR6,#WARMSTART ; point to warm start location
-
- ; look for pattern 00 FF A5 5A
-
- LDC R4,@RR6 ; read 1st mem byte
- CP R4,#0 ; 0 ?
- JR NE,RESET_C ; no, cold start
- INCW RR6
- LDC R4,@RR6 ; read 2nd byte
- CP R4,#$FF ; $FF ?
- JR NE,RESET_C ; no, cold start
- INCW RR6
- LDC R4,@RR6 ; read 3rd byte
- CP R4,#$A5 ; $A5 ?
- JR NE,RESET_C ; no, cold start
- INCW RR6
- LDC R4,@RR6 ; read 4th byte
- CP R4,#$5A ; $5A ?
- JR NE,RESET_C ; no, cold start
- SCF ; pattern matches
- RET
-
- RESET_C:
- RCF ; no match
- RET
-
-
-
- COLD_START:
- ;***************************************************
- ;*
- ;* COLD_START Read warm start pattern location.
- ;* If pattern is valid set carry flag.
- ;* Otherwise reset carry flag.
- ;*
- ;***************************************************;
-
- ld R5,#$04
- VERIFY_DELAY:
- ld R4,#$FF
- call DELAY
- DJNZ R5,VERIFY_DELAY
-
- call VERIFY ; self test
-
- ; write out warm start pattern to memory
- LDW RR6,#WARMSTART ; point to warm start location
-
- ; write pattern 00 FF A5 5A
- ld R4,#0 ; 0
- LDC @RR6,R4 ; write 1st mem byte
- INCW RR6
- ld R4,#$FF ; $FF
- LDC @RR6,R4 ; write 2nd byte
- INCW RR6
- ld R4,#$A5 ; $A5
- LDC @RR6,R4 ; write 3rd byte
- INCW RR6
- ld R4,#$5A ; $5A
- LDC @RR6,R4 ; write 4th byte
-
- ld ECHO_MODE,#ECHO_ON ; initialize echo mode on for terminal
- LDW RR6,#ECHO_STAT ; and save in monitor RAM for warm reset read
- ld R4,#ECHO_OFF
- LDC @RR6,R4
- RET
-
-
- MATCH_CMD:
- ;********************************************************
- ;*
- ;* MATCH_COMMAND call the appropriate routine given the
- ;* first letter in the command.
- ;*
- ;* input: R4 has the first letter of the command.
- ;*
- ;********************************************************;
-
- OR R4,#$20 ; force to low case
- CP R4,#'x' ; an 'x' command?
- JR NE,GO_ON ; no
- ld D_MEMFLAG,#$FF ; yes, set flag for
- ; extern. data mem
- ld R7,INPTR ; RR6 points to input
- ld R6,#^HB CONIBF ; buffer
-
- GO_BACK:
- INC R7 ; look at next char.
- LDC R4,@RR6 ; in CONIBUF
- CP R4,#ASCIICR ; is it a CR?
- jp EQ,OUT_MATCH_CMD ; yes, no command
- CP R4,#ASCIISP ; no, is it a space?
- JR EQ,GO_BACK ; yes, ignore spaces
- OR R4,#$20 ; no, force low case
- CP R4,#'x' ; multiple 'x's ?
- JR EQ,GO_BACK ; yes, ignore them
- ld INPTR,R7 ; no, RR6 points to
- ; command letter
- ; match the command
- GO_ON:
- CP R4,#'b'
- jp EQ,BREAK ; set a breakpoint
- CP R4,#'c'
- jp EQ,COMPARE ; compare memory
- CP R4,#'d'
- jp EQ,MEMORY ; display/alter mem
- CP R4,#'e'
- jp EQ,EXTENSION ; echo off/on
- CP R4,#'f'
- jp EQ,FILL ; fill memory
- CP R4,#'g'
- jp EQ,GO ; start user execution
- CP R4,#'i'
- jp EQ,INTERRUPT_ENABLE ; user interrupts
- CP R4,#'j'
- jp EQ,PC_SET ; change user pc
- CP R4,#'k'
- jp EQ,KILL ; kill a breakpoint
- CP R4,#'l'
- jp EQ,LOAD ; load a file
- CP R4,#'m'
- jp EQ,MOVE ; move a memory block
- CP R4,#'p'
- jp EQ,PHIL_REGISTERS ; fill registers
- CP R4,#'q'
- jp EQ,QUIT ; quit host
- CP R4,#'r'
- jp EQ,REGISTERS ; register display/write
- CP R4,#'s'
- jp EQ,SET ; set memory
- CP R4,#'t'
- jp EQ,TRACE ; set memory
- CP R4,#'u'
- jp EQ,UPLOAD ; upload a file
- CP R4,#'v'
- jp EQ,VERIFY ; self test
- CP R4,#'w'
- jp EQ,WORKING_REGS ; working registers
- CP R4,#'z'
- jp EQ,ZAP ; disassembler
-
- ld ERR_CODE,#BAD_CMD ; invalid command
-
- OUT_MATCH_CMD:
- RET
-
-
-
- ZAP:
- ;************************************************************
- ;*
- ;* ZAP Prepare for and call disassembler.
- ;*
- ;************************************************************;
-
- call GETADDR ; get address parameter
- JR C,ERR3 ; an error? yes
- ld AD_IN_HI,R10 ; no, load hi address
- ld AD_IN_LO,R11 ; load low address
- call GETADDR ; count supplied?
- JR C,NO_NUM1 ; no
- ld DIS_CT,R11 ; yes, load it
- JR DIS_LOOP ; and go on
-
- ;**************************************************
- ;* NO_NUM is called by routines that need a *
- ;* single line disassembled after a halt, *
- ;* breakpoint, or single step. *
- ;**************************************************;
- NO_NUM:
-
- ld AD_IN_HI,USERPC_HI ; load saved breakpoint
- ld AD_IN_LO,USERPC_LO ; address
-
- NO_NUM1:
- ld DIS_CT,#$01 ; disassemble one inst.
- CLR ERR_CODE ; clear error flag
-
- DIS_LOOP:
- ld AD_OUT_HI,#^HB HOSTBUF ; address of output
- ld AD_OUT_LO,#^LB HOSTBUF ; buffer for inst.
- ; mnemonics.
- call DIS_ASM ; disassemble
- ld R6,#^HB HOSTBUF ; print output buffer
- ld R7,#^LB HOSTBUF
- call OUTMSG
-
- DEC DIS_CT ; repeat "DIS_CT" times
- JR NZ,DIS_LOOP
-
- ERR3:
- RET
-
-
- INPUTINT:
- ;************************************************
- ;*
- ;* INPUTINT Serial Input Interrupt handler.
- ;*
- ;***********************************************;
- PUSH R15 ; transparent
- PUSH R6 ; don't interfere
- PUSH R7 ;
-
- ld R15,UIO ; get the input
- AND R15,#$7F ; mask off high bit
-
- ; convert LINE FEED into CARRIAGE RETURN
- CP R15,#$0A
- JR NE,CHECK_ESC
- ld R15,#ASCIICR
- JR CHECK_MODE
-
- CHECK_ESC:
- ; ESC character means halt emulation, or reset monitor
- CP R15,#ASCIIESC ; ESC char?
- JR NE,CHECK_CTLS
-
- ld R4,#$FF
- call DELAY
- TM CFLAG,#LASTCMD ; are we executing?
- JR Z,RESET_MONITOR ; no, reset the monitor
- ld TX_MODE,#X_ON ; transmit on
- jp WARM_START ; Go do a warm start
-
- ; We are not executing (GO mode) so return to monitor
-
- RESET_MONITOR:
- AND CFLAG,#CLSTCMD ; clear the go
- ldw SP,#SYS_STACK ; point back on stack
- ld SIO_MODE,#NORMAL_MODE ; set mode
- ld TX_MODE,#X_ON ; transmit on
-
- ; terminate previous output
- ld R4,#ASCIICR
- call OUTCHR
-
- ; delay for CRLF output
- ld R4,#$20
- call DELAY
- call CRLF
- ld R4,#$20
- call DELAY
-
- ld FLAGS,#$00 ; clear flags
- ld IPR,#$18 ;
- ld IMR,#$40 ; enable SIO IRQ
- ld IRQ,#$00 ; nothing pending
- EI ; enable interrupts
- jp MAIN ; in monitor mode
-
- ; check for CTLQ/CTLS
- CHECK_CTLS:
- CP R15,#ASCIICTLS ; CTLS ?
- JR NE,CHECK_CTLQ ; no
- ld TX_MODE,#X_OFF
- JR XECUTE_ON
-
- CHECK_CTLQ:
- CP R15,#ASCIICTLQ ; CTLQ ?
- JR NE,CHECK_MODE ; no
- ld TX_MODE,#X_ON
- JR XECUTE_ON
-
- CHECK_MODE:
- CP SIO_MODE,#NORMAL_MODE ; which buffer?
- JR NE,HOSTINPUT
- TM CFLAG,#LASTCMD ; if 'go',can't use the
- JR Z,INTO_RAM ; (jump if not in GO mode) data bus
- ; hence can't store
- CP R15,#ASCIIESC ; ESC char is a halt
- ; JR NE,PASS_TO_USER ; not ESC char, pass interrupt to user
- JR NE,XECUTE_ON ; if not ESC just ignore it & IRET
- jp WARM_START ; Was ESC, so restart monitor
-
- INTO_RAM:
- ld R6,#^HB INBUF ; keyboard input
- ld R7,GETCHRPTR ;
- INC GETCHRPTR ; move pointer
- JR DATA_IN ;
-
- HOSTINPUT:
- ld R6,#^HB HOSTBUF ; put into buffer for host
- ld R7,HOSTGET ;
- INC HOSTGET ; update pointer
-
- DATA_IN:
- LDC @RR6,R15 ; put in I/O buffer
-
- XECUTE_ON:
- POP R7 ; restore
- POP R6 ;
- POP R15 ;
- IRET ;
-
- PASS_TO_USER:
- POP R7 ; restore registers before...
- POP R6
- POP R15
- jp INTV10 ; pass ram interrupt vector
-
-
-
- OUT_ERROR:
- ;*************************************************************
- ;*
- ;* OUT_ERROR Output error code and error message
- ;*
- ;* input: ERR_CODE has the error code.
- ;*
- ;*************************************************************;
- PUSH R5 ; save registers
- PUSH R8
- PUSH R9
-
- CP ERR_CODE,#8 ; bad error code?
- JR LE,FIND_MSG ; no
- ld ERR_CODE,#0 ; yes
-
- FIND_MSG:
- ld R5,ERR_CODE ; save error code
- ld R8,#^HB ERR_MSG_LIST
- ld R9,#^LB ERR_MSG_LIST
-
- LOOP_MSG:
- CP R5,#0 ; at the right address?
- JR EQ,AT_BEGIN ; yes
- INCW RR8 ; no, point to next
- INCW RR8
- DEC R5
- JR LOOP_MSG
-
- AT_BEGIN:
- ; RR8 now points to the address of the error message
- LDC R6,@RR8 ; load low byte of address
- INCW RR8
- LDC R7,@RR8 ; load hi byte of address
- call OUTMSG ; write the error message
-
- POP R9 ; restore registers
- POP R8
- POP R5 ; save registers
-
- RET
-
-
- BTOHEXADDR
- ;***********************************************
- ;*
- ;* BTOHEXADDR Convert an address to hex
- ;*
- ;* input: Registers R10-R11 hold address
- ;* to be converted.
- ;*
- ;* output: R6 points to next location in REGBUF
- ;* after last digit of address.
- ;* Converted address is returned in REGBUF.
- ;*
- ;***********************************************;
-
- ld R4,R10 ; convert hi byte
- call BTOHEXDAT ;
- ld R4,R11 ; convert lo byte
- ; fall through
-
-
-
- BTOHEXDAT
- ;***********************************************
- ;*
- ;* BTOHEXDAT Convert a byte to hex
- ;*
- ;* input: R4 contains byte to be converted.
- ;* R6 points to location convert
- ;* byte will go.
- ;*
- ;* output: R6 is incremented twice
- ;*
- ;***********************************************;
-
- PUSH R4 ; save
- SWAP R4 ; do up nibble
- call NIBBLE ;
- POP R4 ; fall through
- call NIBBLE
- RET
-
-
-
-
- NIBBLE
- ;***********************************************
- ;*
- ;* NIBBLE Convert a nibble to hex
- ;*
- ;* input: R4 has nibble to be converted
- ;* in the lower nibble.
- ;* R6 points to where convert goes.
- ;*
- ;* output: R6 is incremented once.
- ;*
- ;***********************************************;
-
- and R4,#$0F ; isolate nibble
- add r4,#$90
- da r4
- adc r4,#$40
- da r4
- ld @R6,R4 ; put into buffer
- inc R6 ; point to next register
- ret ;
-
-
- OUTSTR
- ;*******************************************************
- ;*
- ;* OUTSTR Write a string out to the screen
- ;*
- ;* input: RR6 points to string to be output to
- ;* to the screen. The string is terminated
- ;* with a <CR>.
- ;*
- ;* output: Each character is output to the screen.
- ;*
- ;*******************************************************;
-
- NEXT_CHR:
- LDC R4,@RR6 ; get contents
- CP R4,#ASCIICR ; stop if <CR> data
- JR EQ,DONE_STR ;
- call OUTCHR ; write the char @RR6
- INCW RR6 ; increment pointer
- JR NEXT_CHR ; but continue til then
-
- DONE_STR:
- RET
-
-
-
- OUTMSG
- ;*******************************************************
- ;*
- ;* OUTMSG Write a string out to the screen
- ;* followed by <LF> <CR>.
- ;*
- ;* input: RR6 points to string to be output to
- ;* to the screen. The string is terminated
- ;* with a <CR>.
- ;*
- ;* output: Each character is output to the screen.
- ;* Send a <CR> <LF> at the end of the string.
- ;*
- ;*******************************************************;
-
- call OUTSTR ; write string RR6
- call CRLF ; move cursor to next line
- RET
-
-
-
- OTMSG
- ;********************************************************
- ;*
- ;* OTMSG Write a string in CONOBF out to the screen.
- ;*
- ;* input: R6 is hi byte of buffer, string at beginning
- ;* of the buffer.
- ;* OUTLEN is length of string.
- ;*
- ;* output: Each character in the string is output to
- ;* the screen.
- ;*
- ;* R4,R5,R6,R7 destroyed
- ;*
- ;********************************************************;
-
- CLR R7 ; string at begin of CONOBF
- ld R5,OUTLEN ;
- OUTR5:
- LDC R4,@RR6 ; get into R4 for output
- call OUTCHR ;
- INC R7 ; move pointer
- DJNZ R5,OUTR5 ; until length
- RET ;
-
-
-
- CRLF
- ;*******************************************************
- ;*
- ;* CRLF Output a <LF> <CR>
- ;*
- ;* input: none
- ;*
- ;* output: output a <LF><CR> to the screen
- ;*
- ;*******************************************************;
-
- ld R4,#ASCIILF
- call OUTCHR
- ld R4,#ASCIICR
- call OUTCHR
- RET
-
-
- BACKSPACE
- ;*******************************************************
- ;*
- ;* BACKSPACE Process a backspace character
- ;*
- ;* input: none
- ;*
- ;* output: Write a <BKSP> <SP> <BKSP> to terminal
- ;*
- ;********************************************************;
-
- call OUTCHR ; output the backspace
- ld R4,#ASCIISP ; space
- call OUTCHR ;
- ld R4,#ASCBKSP ; backspace
- call OUTCHR ;
- RET ;
-
-
-
- GETLINE
- ;*******************************************************
- ;*
- ;* GETLINE Fill CONIBF with string in INBUF
- ;*
- ;* input: none
- ;*
- ;* output Place string terminated by <CR> in INBUF
- ;* into CONIBF.
- ;* R4 holds the first letter in the string.
- ;* INPTR is offset to first char in CONIBF.
- ;*
- ;*******************************************************;
- CLR R7 ; using R7 as ptr
- ld R6,#^HB CONIBF ;
-
- INLOOP: call GETCHR ; get from INBUF to CONIBF
- CP R4,#ASCIICR ; <CR> stops input
- JR NE,INLOOP ; end of input
-
- CLR R7 ; get pointer
- ld R6,#^HB CONIBF ;
- FIRSTCHR:
- LDC R4,@RR6 ; get first character
- CP R4,#ASCIISP ; ignore spaces
- JR NE,GOTFIRST ;
- INC R7 ; increment pointer
- JR FIRSTCHR ; wait for nonspace
-
- GOTFIRST:
- ld INPTR,R7 ;
- RET ; back with command string
-
-
-
- OUTADDR
- ;*******************************************************
- ;*
- ;* OUTADDR Convert an address to hex and display it.
- ;*
- ;* input: R10-R11 hold address to be converted
- ;* and displayed.
- ;*
- ;* output: Hex address is displayed on the screen.
- ;*
- ;*******************************************************;
-
- ld R6,#REGBUF ; converted output into REGBUF
- call BTOHEXADDR ; convert
- ld R5,#$04 ; display four bytes
- DISPLAY:
- ld R6,#REGBUF ; start at beginning
- DISP_NUM:
- ld R4,@R6 ; get character for output
- call OUTCHR ;
- INC R6 ; point to next character
- DJNZ R5,DISP_NUM ; display
-
- ld R4,#ASCIISP ; follow with a space
- call OUTCHR ;
- RET ;
-
-
-
- OUTDAT
- ;******************************************************
- ;*
- ;* OUTDAT Convert a byte to hex and display it.
- ;*
- ;* input: R4 has data to convert.
- ;*
- ;* output: Write a hex byte value to the screen
- ;* followed by a space.
- ;*
- ;******************************************************;
-
- call OUTHEX ; Print hex byte
- ld R4,#ASCIISP ; follow with a space
- call OUTCHR ;
- RET ;
-
-
- OUTHEX
- ;******************************************************
- ;*
- ;* OUTHEX Convert a byte to hex and display it.
- ;*
- ;* input: R4 has data to convert.
- ;*
- ;* output: Write a hex byte value to the screen
- ;*
- ;******************************************************;
-
- ld R6,#REGBUF ; register buffer
- call BTOHEXDAT ; convert
-
- ld R5,#$02 ; two characters
- ld R6,#REGBUF ; start at beginning
- DISP_NIB:
- ld R4,@R6 ; get character for output
- call OUTCHR ;
- INC R6 ; point to next character
- DJNZ R5,DISP_NIB ; display
- RET ;
-
-
-
- OUTCHR
- ;*****************************************************
- ;*
- ;* OUTCHR Output a character to the screen
- ;*
- ;* input: R4 contains the character to be
- ;* written.
- ;*
- ;* output: The character in R4 is written to the
- ;* screen.
- ;*
- ;*****************************************************;
- ; delay on output if not echoing
- CP ECHO_MODE,#ECHO_ON
- JR NE,OUTPUT_DEL
-
- JR CHECK_TX
-
- OUTPUT_DEL:
- ; delay
- PUSH R4 ; save R4
- ld R4,#CHR_DELAY
- call DELAY
- POP R4 ; restore R4
-
- ; check for X_OFF
- CHECK_TX:
- CP TX_MODE,#X_OFF
- JR EQ,CHECK_TX
-
- ld UIO,R4 ;
- TEST_OUT:
- TM UTC,#$02 ; wait for output finished
- JR Z,TEST_OUT ;
- RET ;
-
-
- GETCHR
- ;***************************************************
- ;*
- ;* GETCHR Get a character from INBUF and place
- ;* in CONIBF.
- ;*
- ;* input: none
- ;*
- ;* output: Process backspace and line delete.
- ;* Other characters are put into CONIBF
- ;* for parsing.
- ;*
- ;***************************************************;
- call GETDAT ;
-
- CP R4,#ASCIIDEL ; is it a line delete?
- JR NE,NOT_DEL ;
- CP R7,#$00 ; not at beginning
- JR EQ,END_GETCHR ;
-
- ld R4,#ASCBKSP ; R7 backspaces
- LINE_BACK:
- call BACKSPACE ; back to begining
- DJNZ R7,LINE_BACK ;
- JR END_GETCHR ; new input
- NOT_DEL:
- CP R4,#ASCIISP ; is it printable?
- JR C,NOT_PRINTING ;
- ECHO:
- CP R7,#$FF ; end of buffer
- JR NE,BUFOK ;
- ld R4,#ASCIICR ; insert carriage return
-
- BUFOK:
- CP ECHO_MODE,#ECHO_ON ; are we echoing ?
- JR NE,FILL_BUF ; no, no echo
-
- CP STX_ETX,#ECHO_ON ; echo enabled?
- JR NE,FILL_BUF ; no, no echo
-
- call OUTCHR ; yes, echo
-
- FILL_BUF:
- LDC @RR6,R4 ; put into CONIBF
- INC R7 ; move pointer
- JR END_GETCHR ; return
-
- NOT_PRINTING:
- CP R4,#ASCIISTX ; STX?
- JR NE,CHECK_TAB ; no
- ld STX_ETX,#ECHO_OFF ; yes
- JR END_GETCHR
-
- CHECK_TAB:
- CP R4,#ASCIITAB ; change tab to space
- JR NE,NOT_TAB ;
- ld R4,#ASCIISP ;
- JR ECHO ;
-
- NOT_TAB:
- CP R4,#ASCBKSP ; process backspace
- JR NE,NOT_BKSP ; not a backspace
- CP R7,#$00 ; forget backspace at begin
- JR EQ,END_GETCHR ;
-
- call BACKSPACE ; do the backspace
- DEC R7 ; backup pointer
- JR END_GETCHR ;
-
- NOT_BKSP:
- CP R4,#ASCIICR ; preface CR with LF
- JR NE,END_GETCHR ;
-
- CP ECHO_MODE,#ECHO_OFF ; are we echoing?
- JR EQ,FILL_BUF ; no
-
- CP STX_ETX,#ECHO_OFF ; echo enabled?
- JR EQ,FILL_BUF ; no
-
- call CRLF ;
- JR ECHO ; echo and put in CONIBF
- END_GETCHR:
- RET ;
-
-
- GETDAT
- ;****************************************************
- ;*
- ;* GETDAT Get a byte from INBUF
- ;*
- ;* input: none
- ;*
- ;* output: First byte in INBUF is placed in R4
- ;*
- ;****************************************************;
- PUSH R6 ; save
- PUSH R7 ; save
- ld R6,#^HB INBUF ; get pointer
- ld R7,PUTCHRPTR ;
-
- GETDAT1:
- CP GETCHRPTR,PUTCHRPTR ; wait for character
- JR EQ,GETDAT1 ;
-
- LDC R4,@RR6 ; get it from output
- INC PUTCHRPTR ; increment ptr
- POP R7 ;
- POP R6 ; restore
- RET ; end of input
-
-
-
- FINDNEXT
- ;*******************************************************
- ;*
- ;* FINDNEXT
- ;*
- ;* input: INPTR is offset for current character in
- ;* CONIBF.
- ;*
- ;* output: INPTR is offset again to the first character
- ;* of next token in CONIBF. on input line
- ;* R4 contains that first character.
- ;* Returns a zero if char is <CR>
- ;*
- ;*******************************************************;
-
- ld R6,#^HB CONIBF ; get pointer
- ld R7,INPTR ; into input buffer
- FINDNEXT1:
- LDC R4,@RR6 ; wait for a space
- INC R7 ; point ahead
- CP R4,#ASCIICR ; if a CR no param
- JR EQ,NO_PARAM ; no parameter
- CP R4,#ASCIISP ;
- JR NE,FINDNEXT1 ;
-
- SKPSPCE:
- LDC R4,@RR6 ; wait for nonspace
- INC R7 ;
- CP R4,#ASCIISP ;
- JR EQ,SKPSPCE ;
-
- DEC R7 ; point to first character
- CP R4,#ASCIICR ; end of line if <CR>
-
- NO_PARAM:
- ld INPTR,R7 ; update pointer
- RET ;
-
-
-
- FINDOPT
- ;*******************************************************
- ;*
- ;* FINDOPT
- ;*
- ;* input: INPTR is offset for current character in
- ;* CONIBF.
- ;*
- ;* output: Locate next token in input line. Clear R10
- ;* if token does not begin with "-". Place
- ;* first character of token in R10. Place
- ;* second character of token in R11. If token
- ;* begins with "-", remove it from input buffer
- ;* by replacing with spaces.
- ;*
- ;*******************************************************;
- CLR R10 ; clear output reg.
- CLR R11
-
- ld R6,#^HB CONIBF ; get pointer
- ld R7,INPTR ; into input buffer
-
- FINDOPT1:
- LDC R4,@RR6 ; wait for a space
- INC R7 ; point ahead
- CP R4,#ASCIICR ; if a CR no param
- JR EQ,END_FIND ; no parameter
- CP R4,#ASCIISP ;
- JR NE,FINDOPT1 ;
-
- SKIPSP:
- LDC R4,@RR6 ; wait for nonspace
- INC R7 ;
- CP R4,#ASCIISP ;
- JR EQ,SKIPSP ;
-
- CP R4,#ASCIIDSH ; is 1st char a "-" ?
- JR NE,END_FIND
-
- LDC R10,@RR6 ; load 1st char of token
- INC R7
- LDC R11,@RR6 ; load 2nd char of token
- DEC R7 ; point back to "-"
- DEC R7
-
- CLR_TOKEN:
- ld R4,#ASCIISP
- LDC @RR6,R4 ; clear token
- INC R7
- LDC R4,@RR6 ; check for token end
- CP R4,#ASCIICR
- JR EQ,END_FIND
- CP R4,#ASCIISP ; continue until we hit
- JR NE,CLR_TOKEN ; a space.
-
- END_FIND:
- RET ;
-
-
- GETADDR
- ;*******************************************************
- ;*
- ;* GETADDR Get an address value from input line
- ;*
- ;* input: INPTR is offset from CONIBF to last parameter
- ;*
- ;* output: address is stored in R10 R11
- ;*
- ;* R6,R7,R12,R4 destroyed
- ;*
- ;*******************************************************;
- CLR R10 ; clear the temp
- CLR R11 ;
-
- call FINDNEXT ; R4 has first char
- JR Z,PARA_CR ; it is a <CR>
- CON_BYTE:
-
- call CONVERT ; convert to 4 bit bin
- JR C,INV_HEX ; invalid hex
- SWAP R4 ; get into upper nibble
- ld R12,#$04 ; must SHIFT all
- ; four bits
- SHIFTIT:
- RLC R4 ; SHIFT msb into carry
- RLC R11 ; from carry to lsb low byte
- RLC R10 ; msb low byte -> lsb hi byte
- DJNZ R12,SHIFTIT ;
-
- INC R7 ; point to next digit
- LDC R4,@RR6 ; get into working register
- CP R4,#ASCIISP ; space is end
- JR EQ,LAST_NUM ;
- CP R4,#ASCIICR ; so is <CR>
- JR EQ,LAST_NUM ;
- JR CON_BYTE ; convert next digit
-
- PARA_CR:
- ld ERR_CODE,#MIS_PARAM ; type 2 error --
- ; missing param
- SCF ; set flag
- RET
-
- INV_HEX:
- ld ERR_CODE,#BAD_HEX ; type 3 error --
- ; bad hex value
- SCF ; set flag
- RET
-
- LAST_NUM:
- DEC R7 ;
- ld INPTR,R7 ; update pointer
- RCF ; reset flag
- RET
-
-
-
- CONVERT
- ;*******************************************************
- ;*
- ;* CONVERT convert ASCII char to hex
- ;*
- ;* input: ASCII char is in R4, INPTR points one
- ;* byte ahead of location where the char
- ;* was taken from.
- ;*
- ;* output: The value is returned in R4.
- ;*
- ;******************************************************;
-
- CP R4,#'0' ; less than ascii 0 is bad
- JR LT,BAD_HEX_VAL ;
-
- CP R4,#'9' ; if a numeric, mask hi nib
- JR LE,UPMASK ;
-
- CP R4,#'A' ; if > '9', be at least 'a'
- JR LT,BAD_HEX_VAL ;
-
- CP R4,#'F' ; can't be gt
- JR LE,UP_CASE ; unless it is lower case
-
- CP R4,#'a' ; lower case must be at least
- JR LT,BAD_HEX_VAL ; an 'a'
-
- CP R4,#'f' ; but no greater than an 'f'
- JR GT,BAD_HEX_VAL ;
-
- UP_CASE:
- SUB R4,#$07 ; change alpha character
- UPMASK:
- AND R4,#$0F ; mask off upper nibble
- RCF ; reset carry for good exit
- RET ;
-
- BAD_HEX_VAL:
- SCF
- RET
-
-
-
- SEND_STX
- ;********************************************************
- ;*
- ;* SEND_STX Send the character $02 (STX) to the
- ;* host. It will be ignored if an ASCII
- ;* terminal is connected.
- ;*
- ;*********************************************************;
-
-
- ld R4,#ASCIISTX ; send the STX character
- call OUTCHR
-
- ; delay on output if not echoing
- CP ECHO_MODE,#ECHO_ON ; echoing?
- JR EQ,DONE_STX ; yes
- ld R4,#CRLF_DELAY ; no, so delay
- call DELAY
-
- DONE_STX:
- RET
-
- SEND_ETX
- ;********************************************************
- ;*
- ;* SEND_ETX Send the character $03 (ETX) to the
- ;* host. It will be ignored if an ASCII
- ;* terminal is connected.
- ;*
- ;*********************************************************;
- ld R4,#ASCIIETX ; send the ETX character
- call OUTCHR
-
- ; now delay for a moment
- ld R4,#CRLF_DELAY
- call DELAY
- RET
-
- CMD_STATUS
- ;********************************************************
- ;*
- ;* CMD_STATUS Send the command status (<STX> I <ETX>)
- ;* to the host if we are not echoing characters.
- ;*
- ;*********************************************************;
- CP ECHO_MODE,#ECHO_ON ; echoing ?
- JR EQ,DONE_CMD_STAT ; yes, just ret
-
- call SEND_STX ; STX
- ld R4,#'I' ; I
- call OUTCHR
- call SEND_ETX ; ETX
-
- DONE_CMD_STAT:
- RET
-
-
-
- EDIT_STATUS
- ;********************************************************
- ;*
- ;* EDIT_STATUS Send the edit status (<STX> T <ETX>)
- ;* to the host if we are not echoing characters.
- ;*
- ;*********************************************************;
- CP ECHO_MODE,#ECHO_ON ; echoing ?
- JR EQ,DONE_EDIT_STAT ; yes, just ret
-
- call SEND_STX ; STX
- ld R4,#'T' ; T
- call OUTCHR
- call SEND_ETX ; ETX
-
- DONE_EDIT_STAT:
- RET
-
-
-
- GO
- ;*********************************************************
- ;*
- ;* GO
- ;*
- ;* syntax G [<ADDRESS>]
- ;*
- ;* defaults <ADDRESS> = current PC
- ;*
- ;*********************************************************;
-
- call PC_SET ; optional jump
- OR CFLAG,#LASTCMD ; mark user is executing
- DI ; change imr
- ld IMR,#$40 ; Enable SIO int only
- EI ;
- ; CP USER_EI,#$FF ; go with interrupts
- ; JR NE,GO_AHEAD ;
- ; call FORCE_EI ;
-
-
- GO_AHEAD:
- ld RP0,USER_RP0 ;
- ld RP1,USER_RP1 ;
- sb0
- ld EMT,#USR_EMT ; set up external stack for user
- ld FLAGS,USER_FLAGS ;
- ld IMR,USER_IMR ;
-
- ldw sp,USER_SP
- push USERPC_LO ; low byte
- push USERPC_HI ; Get high address byte
- ret ; GO !!!
- ; We will return through the
- ; SOFTWARE_BREAK routine or
- ; by a RESET only
-
-
-
- PC_SET
- ;******************************************************
- ;*
- ;* PC_SET (but don't go)
- ;*
- ;* syntax J [<ADDRESS>]
- ;*
- ;* defaults <ADDRESS> = current PC value
- ;*
- ;******************************************************;
- call GETADDR ; get go address
- JR NC,NEW_PC ; jump if new address parameter
-
- ld R10,USERPC_HI ; get user PC
- ld R11,USERPC_LO ; into RR10
- NEW_PC:
- CLR ERR_CODE ; no error
- ld USERPC_HI,R10 ; change internal copy
- ld USERPC_LO,R11 ;
- RET ; done
-
- TRACE
- ;******************************************************
- ;*
- ;* Sets breakpoint at the next op code,
- ;* then executes GO. This is smart
- ;* about program branches.
- ;*
- ;******************************************************
-
-
- ldw rr10,USER_PC
- ldci r12,@rr10 ; fetch opcode
- ldc T_CODE,r12 ; save opcode for branch handler
-
- cp r12,#$0F ; next?
- jr nz,trc_1
- ldw rr12,IP
- jr trc_x ; share some code
-
- trc_1: cp r12,#$F6 ; call #addr ?
- jr z,trc_1a
-
- cp r12,#$1F ; enter?
- jr nz,trc_2 ; if not
- trc_1a: ldw rr12,rr10
- trc_x ldci r10,@rr12 ; fetch next pc from the word list
- ldc r11,@rr12
- jp trc_0 ; go set BP
-
- trc_2: cp r12,#$2F ; Exit?
- jr nz,trc_3
- ldw rr10,sp
- ldci r12,@rr10
- ldc r13,@rr10
- jr trc_x
-
- trc_3: cp r12,#$AF ; return?
- jr nz,trc_4
- pop r10 ; get pc off stack
- pop r11
- push r11 ; restore stack
- push r10
- jp trc_0 ; go set BP
-
- trc_4: cp r12,#$F4 ; CALL @R ?
- jr z,trc_4a ; if so
-
- cp r12,#$30 ; JP @R ?
- jr nz,trc_5
-
- trc_4a: ld r14,#$C4 ; ldw opcode
- ldc T_CODE,r14
- ldci r14,@rr10 ; get des. field from opcode (@R)
- ldc T_CODE+1,r14 ; = source for LDW
- ld r14,#ALT_PC
- ldc T_CODE+2,r14 ; ldw ALT_PC,R; R is destination
- ld r14,#$AF
- ldc T_CODE+3,r14 ; ret
-
- ld FLAGS,USER_FLAGS ; we need user flags for condx. jump
- ld RP0,USER_RP0 ; user registers are needed for djnz, etc.
- ld RP1,USER_RP1
- call T_CODE ; get the destination to ALT_PC
- srp #WORKREGS ; Point to monitor reg. set
- ldw rr10,ALT_PC
- jp trc_0
- ;-----
- trc_5:
- inc r12
- ldw rr4,#OP_TAB-1 ; get starting
- nxt_2: incw rr4 ; find next
- ldc r13,@rr4 ; control byte
- TM r13,#$80 ; bit 7 set?
- jr z,nxt_2 ; loop 2 till
-
- nxt_3: djnz r12,nxt_2 ; if not there, get next
-
- swap r13
- rr r13
- and r13,#3
- add r11,r13
- adc r10,#0 ; Next addr now in rr10
- ;------------------------------------------------
- ; Now look at the opcode, & take care of branches
-
- ldw ALT_PC,rr10 ; save next intruction address
- ldw rr8,USER_PC
- ldci r14,@rr8 ; fetch opcode
- ldc T_CODE,r14 ; save opcode just in case
-
- cp r14,#$d2 ; cpijne?
- jr z,tbr4a
- cp r14,#$C2 ; cpije?
- jr z,tbr4a
-
- tbr4: cp r14,#$37 ; btjrf/t?
- jr nz,trb3
- tbr4a: ldci r14,@rr8
- ldc T_CODE+1,r14
- ld r14,#3
- ldc T_CODE+2,r14
- ldc r13,@rr8 ; get displacement to r13
- ld r12,r13
- add r12,r12 ; sign bit to carry
- clr r12
- sbc r12,#0 ; extend sign bit into r12
- add r13,r11
- adc r12,r10 ; destination to rr12
- jr tbr1b
-
- trb3: and r14,#$F
- cp r14,#$0A ; DJNZ?
- jr z,trb2 ; if so, use same code as JR
-
- cp r14,#$0B ; jump relative?
- jr nz,tbr1 ; if not
-
- trb2: ldc r13,@rr8 ; get displacement to r13
- ld r12,r13
- add r12,r12 ; sign bit to carry
- clr r12
- sbc r12,#0 ; extend sign bit into r12
- add r13,r11
- adc r12,r10 ; destination to rr12
- jr tbr1a ; go do it
-
- tbr1 cp r14,#$0D ; jump?
- jr nz,trc_0 ; if not, get out of here
- ldci r12,@rr8 ;
- ldc r13,@rr8
- ldc r14,T_CODE
- sub r14,#2 ; turn JP into JR
- ldc T_CODE,r14
-
- tbr1a: ld r14,#4 ; displacement for jr cc
- ldc T_CODE+1,r14
- ld r14,#$ff
- ldc T_CODE+2,r14 ; throw in a nop
-
- tbr1b: ldw USER_PC,rr12 ; assume a jump
- ld r14,#$C4 ; ldw opcode
- ldc T_CODE+3,r14
- ld r14,#ALT_PC ; if branch not taken,
- ldc T_CODE+4,r14 ; ALT_PC --> USER_PC
- ld r14,#USER_PC
- ldc T_CODE+5,r14 ; ldw rr12,rr10 if branch not taken
- ld r14,#$AF
- ldc T_CODE+6,r14 ; ret
-
- ld FLAGS,USER_FLAGS ; we need user flags for condx. jump
- ld RP0,USER_RP0 ; user registers are needed for djnz, etc.
- ld RP1,USER_RP1
- call T_CODE
- srp #WORKREGS ; Point to monitor reg. set
- ld R4,#'J' ; output a 'J' for jump
- jp BRK_2 ; fake a break
- .xlist
- ;-----
- trc_0: call SET_BREAK_ADDR
- jp GO
-
-
- BREAK
- ;*******************************************************
- ;*
- ;* BREAK
- ;*
- ;* syntax B display breakpoints
- ;* syntax B <ADDRESS> set one breakpoint
- ;*
- ;*******************************************************;
-
-
- call GETADDR ; check for parameters
- JR C,DISP_BRK ; jump if no parameters
- CP R10,#$80 ; Break range must be > ROM space
- JR ULT, BAD_RANGE
- jr SET_BREAK_ADDR ;
-
- ; Display the breakpoints set
-
- DISP_BRK:
- ldw rr10,#BP1_ADDR ; Point to Break point save location
- ldc r12,@rr10 ; Get high byte of breakpoint address
- cp r12,#$80 ; Check if in ROM space
- jr uge,CHK_BRK ; Jump if not
- clr ERR_CODE ; No breakpoint set
- ret
-
- CHK_BRK:
- ld r6,#^HB BRK_MES ; Print
- ld r7,#^LB BRK_MES ; breakpoint
- call OUTSTR ; header
- ldc r4,@rr10 ; Get High address byte
- call OUTHEX ; Print high byte
- incw rr10 ; Point to Low address byte
- ldc r4,@rr10 ; Get Low address byte
- call OUTHEX ; Print low byte
- call CRLF
- CLR ERR_CODE ; clear errors
- RET
-
- BAD_RANGE:
- ld ERR_CODE,#BAD_PARAM_VAL
- ret
-
-
- ; Set a breakpoint
- ; "BREAK_ADDR" can be called to set a breakpoint
- ; if RR10 has the breakpoint address
-
- SET_BREAK_ADDR:
- CLR ERR_CODE ; clear errors
-
- ; Make sure the address is not in ROM space
-
- CP R10,#$80 ; Is it in lower 16K? (ROM Space)
- JR UGE,INT_ADDR ; no
- ld ERR_CODE,#BAD_PARAM_VAL ; Opps! It is
- RET ; Send back error code
-
- ; Get the three bytes we need to replace with the call instruction
-
- INT_ADDR:
- push r0 ; save
- push r2 ; some
- push r3 ; registers
- ldw rr2,#BP1_ADDR ; pt to save address of breakaddress
- ldc @rr2,r10 ; Save High byte of break address
- incw rr2 ; Point to next location
- ldc @rr2,r11 ; Save Low byte of break address
- ldw rr2,#BP1_SAVE ; Point to save address of breakaddress
- ldc r0,@rr10 ; Get first byte
- ldc @rr2,r0 ; Save 1st byte
- ld r0,#$F6
- ldc @rr10,r0 ; Insert call opcode
- incw rr10 ; Point to next byte
- incw rr2 ; & next save location
- ldc r0,@rr10 ; Get 2nd byte
- ldc @rr2,r0 ; Save it
- ld r0,#^HB SOFTWARE_BREAK
- ldc @rr10,r0
- incw rr10 ;
- incw rr2 ;
- ldc r0,@rr10 ; Get 3rd byte
- ldc @rr2,r0 ; save it
- ld r0,#^LB SOFTWARE_BREAK ;
- ldc @rr10,r0
- pop r3
- pop r2
- pop r0
- ret
-
-
- KILL
- ;*******************************************************
- ;*
- ;* KILL
- ;*
- ;* syntax K
- ;*
- ;*******************************************************;
-
- ld ERR_CODE, #0
- ldw rr10,#BP1_ADDR ; Point to saved address
- ldci r0,@rr10 ; Load break address
- ldc r1,@rr10 ; into rr0
- clr r3
- ldw rr10,#BP1_ADDR ; Point to saved address
- ldc @rr10,r3 ; Clear break address
- incw rr10
- ldc @rr10,r3
- ldw rr10,#BP1_SAVE ; Load pointer to save area
- ldci r2,@rr10 ; Get 1st byte
- ldc @rr0,r2 ; Restore 1st byte
- incw rr0
- ldci r2,@rr10 ; get 2nd byte
- ldc @rr0,r2 ; Restore 2nd byte
- incw rr0
- ldci r2,@rr10 ; Get 3rd byte
- ldc @rr0,r2 ; Restore 3rd byte
- ret
-
-
- SOFTWARE_BREAK
- ;**********************************************************
- ;*
- ;* Software breakpoint reached
- ;*
- ;* This routine is the call location for a software
- ;* breakpoint.
- :*
- ;**********************************************************
-
- DI
- ld USER_FLAGS,FLAGS ; Save USER FLAGS
- ld USER_IMR,IMR ;
- ld USER_RP0,RP0 ; RP0
- ld USER_RP1,RP1 ; RP1
- srp #WORKREGS ; Point to correct reg set
- pop r0 ; Get USER PC
- pop r1 ; off of stack
- ldw USER_SP,SP
- decw rr0 ; Break
- decw rr0 ; address is
- decw rr0 ; 3 less
- ld USERPC_HI,r0 ; Save high address
- ld USERPC_LO,r1 ; & low address
-
- ; Restore removed instruction
-
- ldw rr10,#BP1_ADDR ; Point to saved address
- ldci r0,@rr10 ; Load break address
- ldc r1,@rr10 ; into rr0
- clr r3
- ldw rr10,#BP1_ADDR ; Point to saved address
- ldc @rr10,r3 ; Clear break address
- incw rr10
- ldc @rr10,r3
- ldw rr10,#BP1_SAVE ; Load pointer to save area
- ldci r2,@rr10 ; Get 1st byte
- ldc @rr0,r2 ; Restore 1st byte
- incw rr0
- ldci r2,@rr10 ; get 2nd byte
- ldc @rr0,r2 ; Restore 2nd byte
- incw rr0
- ldci r2,@rr10 ; Get 3rd byte
- ldc @rr0,r2 ; Restore 3rd byte
-
- ; We hit a breakpoint
-
- BREAK_1:
- ld IMR,#$40 ; Reset the IMR (Enable SIO IRQ)
- EI ; enable other interrupts
- ld R4,#'B' ; output a 'B' for break
- BRK_2: call OUTCHR ;
- ld R4,#ASCIISP ; followed by a space
- call OUTCHR ;
- call NO_NUM ; Disassemble instruction
- HALTED:
- AND CFLAG,#CLSTCMD ; clear the go
- sb0
- ld EMT,#SYS_EMT
- ldw SP,#SYS_STACK ; point back on stack
- jp MAIN ; in monitor mode
-
-
- INT_TAB_REL:
- ;************************************************************
- ;*
- ;* INTERRUPT TABLE RELOCATION ROUTINE
- ;* MOVES DUMMY INTERRUPT TABLE TO RAM LOCATION
- ;* E000H FOR USER ACCESS. ALL VECTORS POINT TO AN
- ;* INTERRUPT RETURN.
- ;*
- ;************************************************************
-
- ldw rr4,#$E000 ;beginning location of interrupt vector table
- ;in ram
- ldw rr6,#IVECT0 ;beginning location of table data in ROM
- ld r8,#IVECLEN ;get length of table
- IVLOOP: ldci r0,@rr6 ;get the byte
- ldc @rr4,r0 ;put the byte
- incw rr4 ;bump pointer
- djnz r8,IVLOOP ;loop till done
- ret
-
-
-
- ;************************************************************
- ;*
- ;* TABLES and MESSAGE STRINGS
- ;*
- ;************************************************************;
-
-
- ERR_MSG_LIST dw ERR_0_MSG, ERR_1_MSG, ERR_2_MSG, ERR_3_MSG, ERR_4_MSG
- dw ERR_5_MSG, ERR_6_MSG, ERR_7_MSG, ERR_8_MSG
-
- ERR_0_MSG .ascii '? INVALID ERROR CODE\r'
- ERR_1_MSG .ascii '? 01 INVALID COMMAND\r'
- ERR_2_MSG .ascii '? 02 MISSING PARAMETER\r'
- ERR_3_MSG .ascii '? 03 BAD HEX NUMBER\r'
- ERR_4_MSG .ascii '? 04 BAD COMMAND OPTION\r'
- ERR_5_MSG .ascii '? 05 LOAD ABORTED BY HOST\r'
- ERR_6_MSG .ascii '? 06 LOAD ABORTED BY SUPER8 MONITOR\r'
- ERR_7_MSG .ascii '? 07 FILE ERROR MESSAGE\r'
- ERR_8_MSG .ascii '? 08 PARAMETER VALUE OUT OF RANGE\r'
-
- STRT_MSG .ascii ' SUPER8 Monitor\r'
- REV_MSG .ascii ' Version 1.02.07\r'
- DATE_MSG .ascii ' March 9, 1987\r'
-
- BRK_MES .ascii 'Breakpoint set at: \r'
-
- WARM_PATTERN db $00,$FF,$A5,$5A
-
- ;
- ; interrupt handlers
- ; null return will terminate improperly initialized interrupt
- ;
- NULIRET: IRET
- ;
- ; null vector table to be relocated into ram beginning at location E000H
- ;
- IVECT0: jp NULIRET
- IVECT1: jp NULIRET
- IVECT2: jp NULIRET
- IVECT3: jp NULIRET
- IVECT4: jp NULIRET
- IVECT5: jp NULIRET
- IVECT6: jp NULIRET
- IVECT7: jp NULIRET
- IVECT8: jp NULIRET
- IVECT9: jp NULIRET
- IVECT10: jp NULIRET
- IVECT11: jp NULIRET
- IVECT12: jp NULIRET
- IVECT13: jp NULIRET
- IVECT14: jp NULIRET
- IVECT15: jp NULIRET
- IVECLEN equ $-IVECT0 ;LENGTH OF TABLE TO BE RELOCATED
-
- ;************************************************
- ;*
- ;* mem.s : all the memory command
- ;* routines except low-level routines.
- ;*
- ;* ** This version doctored for META assembler
- ;*
- ;*****************************************************
- ;*
- ;* Constants and register usage used by
- ;* all or some of the software modules.
- ;*
- ;******************************************************;
- ; register allocation
-
- FILL
- ;*****************************************************
- ;*
- ;* FILL
- ;*
- ;* syntax F <START ADDR> <LENGTH> {<DATA>}
- ;*
- ;* defaults none
- ;*
- ;* action the pattern input as {<DATA>}
- ;* is written into memory beginning
- ;* at <START ADDR> and is copied
- ;* in as many times as necessary to
- ;* fill <LENGTH> bytes of memory
- ;*
- ;*****************************************************;
- PUSH R15
-
- CALL GETADDR ; get the address
- JR C,BADHX5 ; no good
- LD R0,R10 ; use RR0
- LD R1,R11 ;
- CALL GETADDR ; get length
- JR C,BADHX5 ; no good
- LD R2,R10 ; put length into RR2
- LD R3,R11 ;
-
- CLR OUTPTR ; use the input buffer
- CLR R13 ; count # of data bytes
- ACCUM:
- CALL GETADDR ; get data
- JR C,DO_FILL ; stop input and fill
- LD R7,OUTPTR ; get pointer
- LDC @RR6,R11 ; one byte of data
- INC R13 ; keep count
- INC OUTPTR ; increment pointer
- JR ACCUM ;
- DO_FILL:
- CP R13,#$00 ; if no data,don't fill
- JR EQ,BADHX5 ; didn't get any data
-
-
- RE_PEAT:
- LD R9,R13 ; get length of pattern
- CLR R7 ; pointer not shared
- R9LOOP:
- LDC R15,@RR6 ; get data from pattern
-
- PUSH R8
- PUSH R9
- LD R8,R0
- LD R9,R1
- CALL PUTMEM ; LDE @RR8,R15
- POP R9
- POP R8
-
- INCW RR0 ; increment memory ptr
- INC R7 ; increment buffer ptr
- DECW RR2 ; decrement length of memory
- JR Z,FILL_END ;
- DJNZ R9,R9LOOP ; DJNZ R9,R9loop
- JR RE_PEAT ; repeat the pattern
- FILL_END:
-
-
- CLR ERR_CODE ; normal ending,clear error
- BADHX5:
- POP R15
-
- RET ; stop this
-
-
-
-
- MOVE
- ;******************************************************
- ;*
- ;* MOVE
- ;*
- ;* syntax M <DEST ADDR> <SOURCE ADDR> [<LENGTH>]
- ;*
- ;* defaults <LENGTH> = 1
- ;*
- ;******************************************************;
- PUSH R8
- PUSH R9
- PUSH R15
-
- CALL GETADDR ; get first address
- JR C,BADHX6 ; no good
-
- LD R2,R10 ; first address
- LD R3,R11 ; into RR2
- CALL GETADDR ; second address
- JR C,BADHX6 ; no good
-
- LD R0,R10 ; second address into
- LD R1,R11 ; RR0
- CALL GETADDR ; get move length
- JR NC,DO_MOVE ; default is 1
-
- CLR R10 ; clear high order
- LD R11,#$01 ; get default into R11
-
- DO_MOVE:
- PUSH R2 ; save from pointer
- PUSH R3 ;
- SUB R3,R1 ; subtract word
- SBC R2,R0 ; in two steps
- POP R3 ; restore pointer
- POP R2 ;
- JR C,BKWARD ; carry indicates back move
-
- FORWARD:
- LD R8,R2
- LD R9,R3
- CALL GETMEM ; LDE R15,@RR8
-
- ; data is now in R15
-
- LD R8,R0
- LD R9,R1
- CALL PUTMEM ; LDE @RR8,R15
-
- INCW RR0 ; increment pointers
- INCW RR2 ;
- DECW RR10 ; decrement count
- JR NZ,FORWARD ;
- JR END_MOVE ; stop
-
- BKWARD:
- ADD R1,R11 ; point to back end
- ADC R0,R10 ; word add
- ADD R3,R11 ; point to back end
- ADC R2,R10 ;
- BACKWD:
- DECW RR0 ; decrement pointers
- DECW RR2 ;
-
-
- LD R8,R2
- LD R9,R3
- CALL GETMEM ; LDE R15,@RR8
-
- ; data is now in R15
-
- LD R8,R0
- LD R9,R1
- CALL PUTMEM ; LDE @RR8,R15
-
- DECW RR10 ; decrement counter
- JR NZ,BACKWD ;
- END_MOVE:
- BADHX6:
- POP R15
- POP R9
- POP R8
- RET ; stop
-
-
-
-
- SET
- ;*****************************************************
- ;*
- ;* SET memory
- ;*
- ;* syntax S <ADDR> {<DATA>}
- ;*
- ;* defaults none
- ;*
- ;* Set memory at <ADDR> with <DATA> string.
- ;* Input is limited to 80 (decimal) characters
- ;* on the command line.
- ;*
- ;******************************************************;
- PUSH R15
-
- CALL GETADDR ; get the start address
- JR C,BADHX2A ; bad hex
-
- LD R8,R10 ; use reg's RR8
- LD R9,R11 ;
-
- SETVAL:
- CALL GETADDR ;
- JR C,BADHX2 ;
-
- LD R15,R11 ; data
- PUSH R8 ; hi addr
- PUSH R9 ; lo addr
- CALL PUTMEM ; LDE @RR8,R15
- POP R9 ;
- POP R8 ;
-
- INCW RR8 ;
- JR SETVAL ; get next value
- BADHX2:
- CLR ERR_CODE ; clear error
- BADHX2A:
- POP R15
- RET ;
-
-
-
-
- MEMORY
- ;*******************************************************
- ;*
- ;* MEMORY
- ;*
- ;* syntax D [<START ADDR> [<LENGTH>]]
- ;*
- ;* defaults <length> = 1,and the user is given
- ;* the opportunity to
- ;* change the contents
- ;* <start addr> = 0 (user_zero)
- ;*
- ;* action (full syntax)
- ;* memory is displayed $10 locations to
- ;* a line (unless less is specified)
- ;* each line has two addresses, the first
- ;* location displayed and the 8th location.
- ;* following each line and on the same line
- ;* is the ascii conversion when possible
- ;* and a dot when value not an ascii character.
- ;* the ascii conversion is offset by '*'
- ;*
- ;* (partial syntax)
- ;* each memory location is displayed, first
- ;* the address then the contents, and a prompt
- ;* is issued to the user for input.
- ;* possible inputs are:
- ;* [^|.|q] <cr>
- ;* or
- ;* <data> [^|.|q] <cr>
- ;* <data> replaces previous contents
- ;* <cr> causes the next location to be displayed
- ;* ^ <cr> the previous location is displayed
- ;* . <cr> the current location is displayed again
- ;* q <cr> terminates the command
- ;*
- ;*******************************************************;
- CALL GETADDR ; get first parameter
- JP C,ZERO_START ; start display from zero
-
- PUSH R10 ; save start address
- PUSH R11 ;
-
-
- CALL GETADDR ; get length parameter
- JP C,DISP_ALT ; no parameter,display + alter
-
- LD R0,R10 ; put total into RR0
- LD R1,R11 ;
- POP R11 ; recover start address
- POP R10 ;
- NEWLINE:
- PUSH R10 ;
- PUSH R11 ;
- CP R0,#$00 ; any left to display ?
- JR NZ,GO_AHEAD1 ; go ahead and display
-
- CP R1,#$00 ;
- JR Z,ALL_DONE ;
- GO_AHEAD1:
- CALL DISPMEMLINE ; display a line of memory
- POP R13 ; get start of current line
- POP R12 ; using RR12
- CALL DISPASCII ; display
- JR NEWLINE ; display next line
- ALL_DONE:
- POP R11 ; pop stack
- POP R10 ;
- ERR_EXIT:
- RET ; errors exit here
- DONE:
- CLR ERR_CODE ; no error,a token
- RET ; and exit
-
-
- ZERO_START:
- CALL EDIT_STATUS ; tell host edit mode
- CLR R10 ;
- CLR R11 ; start at user zero
-
- JR DISP_1 ; display one at a time
- DISP_ALT:
- CALL EDIT_STATUS ; tell host edit mode
- POP R11 ; recover parameter for
- POP R10 ; the start address
- DISP_1:
- CALL OUTADDR ; output the address
-
- PUSH R8
- PUSH R9
- PUSH R15
-
- LD R8,R10 ; hi addr
- LD R9,R11 ; lo addr
- CALL GETMEM ; read byte from memory
- LD R4,R15 ; get data
-
- POP R15
- POP R9
- POP R8
-
- CALL OUTDAT ;
-
- ; output prompt with leading STX and trialing ETX
- ; for host package
- LD R4,#ASCIISTX
- CALL OUTCHR
- LD R4,#'+' ; prompt for response
- CALL OUTCHR ;
- LD R4,#ASCIIETX
- CALL OUTCHR
-
- CALL GETLINE ; get the response
-
- DISP_TOKEN:
-
- CP R4,#ASCIIQ ; is it quit ?
- JR Z,DONE ;
-
- CP R4,#'q' ; is it quit ?
- JR Z,DONE ;
-
- CP R4,#ASCIIUP ; is it an up ?
- JR NZ,DOT ;
-
- DECW RR10 ;
- JR DISP_1 ;
- DOT:
- CP R4,#ASCIIDOT ; is it a dot ?
- JR Z,DISP_1 ;
-
- CP R4,#ASCIICR ; is it a <cr> ?
- JR NZ,NUMERIC ;
-
- INCW RR10 ;
- JR DISP_1 ;
- NUMERIC:
- PUSH R10 ; save
- PUSH R11 ; save
- CLR R10 ; clear
- CLR R11 ; for conversion
- CALL CON_BYTE ; entry to getaddr
- JR C,ALL_DONE ; error
-
- LD R4,R11 ; low order byte important
- POP R11 ; restore address
- POP R10 ;
-
- PUSH R8
- PUSH R9
- PUSH R15
- LD R15,R4 ; data
- LD R8,R10 ; hi addr
- LD R9,R11 ; lo addr
- CALL PUTMEM ; write byte to memory
- POP R15
- POP R9
- POP R8
-
- CALL FINDNEXT ; are there two tokens?
- JR NZ,DISP_TOKEN ;
-
- INCW RR10 ; move pointer
- JR DISP_1 ; go again
-
-
-
- COMPARE
- ;*****************************************************
- ;*
- ;* COMPARE memory
- ;*
- ;* syntax C <ADDR1> <ADDR2> [<LENGTH>]
- ;*
- ;* defaults <LENGTH> = 1
- ;*
- ;* action compares contents of addr1 with addr2
- ;* if values are unequal,the addresses
- ;* and contents are displayed on the console
- ;* <ADDR1> = <VAL1> <ADDR2> = <VAL2>
- ;* if values are equal,nothing is displayed
- ;* <ADDR1>=<ADDR2>+1 and <ADDR2>=<ADDR2>+1
- ;*
- ;*****************************************************;
- PUSH R8
- PUSH R9
-
- CALL GETADDR ; get first parameter
- JR C,BADHX3 ; bad hex
-
- LD R0,R10 ; use RR0 for first adddress
- LD R1,R11 ;
- CALL GETADDR ; get second address
- JR C,BADHX3 ;
-
- LD R2,R10 ; use RR2 for second addr
- LD R3,R11 ;
- CALL GETADDR ; get length
- JR NC,COMP ; got length in RR10
-
- CLR R10 ; no good parameter
- LD R11,#$01 ; just compare 1
- COMP:
- LD R8,R10 ; put length in RR8
- LD R9,R11 ;
- DO_COMP:
- PUSH R8
- PUSH R9
- LD R8,R0 ; hi addr
- LD R9,R1 ; lo addr
- CALL GETMEM ; LDE R15,@RR8
- LD R14,R15 ; get data
-
- LD R8,R2 ; hi addr
- LD R9,R3 ; lo addr
- CALL GETMEM ; LDE R15,@RR8
- POP R9
- POP R8
-
- ; data is in R15
-
- CP R14,R15 ; compare the values
- JR EQ,NODISPLAY ; don't display if equal
-
- CALL COMPDISP ; display
-
- NODISPLAY:
- INCW RR0 ; increment pointers
- INCW RR2 ;
- DECW RR8 ;
- JR NZ,DO_COMP ;
- BADHX3:
- POP R9
- POP R8
- RET ; finished
-
-
-
- ;**********************************************
- ;*
- ;* sup.s : low level support routines for
- ;* the various commands.
- ;*
- ;* (1) memory read/write
- ;* (2) register read/write
- ;* (3) I-CODE execution
- ;*
- ;***********************************************;
-
-
-
- READ_DIR_REG
- ;*****************************************************
- ;*
- ;* READ_DIR_REG Read register using Register
- ;* addressing mode. This will
- ;* read "set one" registers above
- ;* register address $BF
- ;*
- ;* input R9 has register number
- ;*
- ;* output R6,R7 point to reg_read,where
- ;* the register value is returned
- ;* R9 is unchanged,R4 = $00
- ;*
- ;*****************************************************;
-
- push r0
- push r4 ; Save some
- push r5 ; registers
-
- ldw rr6,#I_CODE ; Point to I_CODE buffer
- ld r0,#$48 ; 1st byte of LD R4,REG#
- ldc @rr6,r0 ; instruction
- incw rr6 ; Point to next location
- ldc @rr6,r9 ; 2nd byte is REG#
- incw rr6 ; Point to next location
- ld r0,#$AF ; Place a RET instruction
- ldc @rr6,r0 ; at the end
- call I_CODE ; Go execute the LD instruction
-
- LDW rr6,#REG_READ ; leave RR6 pointing to place
- ; where reg val is returned
- ldc @rr6,r4 ; Place value read into memory
- pop r5
- pop r4
- pop r0
- RET
-
-
-
-
- READ_IR_REG
- ;*****************************************************
- ;*
- ;* READ_IR_REG Read general purpose register
- ;* using Indirect Register addressing mode.
- ;* This will read "set two" registers above
- ;* register address $BF.
- ;*
- ;* input R9 has register number and should
- ;* be in the range $C0 - $FF
- ;*
- ;* output R6,R7 point to reg_read,where
- ;* the register value is returned
- ;* R9 is unchanged,R4 = $00
- ;*
- ;*****************************************************;
- PUSH R4
- PUSH R5
- ld r5,@r9 ; get register contents
- LDW rr6,#REG_READ ; leave RR6 pointing to
- ; place reg val returned
- ldc @RR6,r5 ; Write register value to memory
- POP R5
- POP R4
- RET ;
-
-
-
-
- WRITE_DIR_REG
- ;***************************************************
- ;*
- ;* WRITE_DIR_REG Write a value to general registers
- ;* $00 - $BF, or set one registers
- ;*
- ;* input R9 has register number
- ;* R11 has value to be written to it
- ;*
- ;* used R6,R7 used as pointers to I-CODE
- ;* R5 used to send opcode
- ;*
- ;* output R9 is unchanged,R11 = 0
- ;* R5,R6,R7 destroyed
- ;*
- ;***************************************************;
-
- LDW RR6,#I_CODE ; Point to I_CODE execution buffer
-
- LD R5,#$B9 ; 1st byte of LD REG#,R11 instruction
- LDC @RR6,R5 ; first write opcode
- INCW RR6 ;
- LDC @RR6,R9 ; 2nd byte is REG# to write
- INCW RR6 ;
- ld r5,#$AF ; 3rd byte is a RET instruction
- LDC @RR6,R5 ;
-
- CALL I_CODE ; now execute I-CODE
-
- RET ; it will happen
-
-
-
-
- WRITE_IR_REG
- ;***************************************************
- ;*
- ;* WRITE_IR_REG Write a value to a register using
- ;* Indirect Register mode. This will access
- ;* set two registers $C0 - $FF.
- ;*
- ;* input R9 has register number to be written to and
- ;* should be in the range $C0 - $FF.
- ;* R11 has value to be written to it
- ;*
- ;* output R9 is unchanged,R11 = 0
- ;*
- ;***************************************************;
-
- ld @r9,r11 ; Write register
- clr r11
- RET
-
-
-
-
- GETMEM
- ;****************************************************************
- ;*
- ;* GETMEM
- ;*
- ;* Sets GETMEMFLG bit in CFLAG and calls GETPUTMEM
- ;* checks address for internal or external memory
- ;* internal 0 through (ROM_size -1), adds offset
- ;* external >= ROM_size forces user z8 to read
- ;*
- ;* input: RR8 contains address to be read from
- ;*
- ;* output: R15 contains data read
- ;*
- ;****************************************************************;
-
- ; Read from data memory?
- CP D_MEMFLAG, #$ff ; X command ?
- JR EQ, EXT_MEM
-
- ; doing prpgram memory
- GM_INTERN:
- PUSH R6 ; save registers
- PUSH R7 ; use RR6 for LDC
- LD R6,R8 ; high address byte
- LD R7,R9 ; and low address byte
- LDC R15,@RR6 ; Read byte from program memory
- POP R7 ; restore
- POP R6 ; registers
- RET ; deliver the byte
-
- ; doing data memory
- EXT_MEM:
- PUSH R6 ; save registers
- PUSH R7 ; use RR6 for LDC
- LD R6,R8 ; high address byte
- LD R7,R9 ; and low address byte
- LDC R15,@RR6 ; Read byte from data memory
- POP R7 ; restore
- POP R6 ; registers
- RET ; deliver the byte
-
-
-
-
-
- PUTMEM
- ;***************************************************************
- ;*
- ;* PUTMEM
- ;*
- ;* resets GETMEMFLG bit in CFLAG and calls GETPUTMEM
- ;* checks address for internal or external memory
- ;* internal 0 through (ROM_size -1) , adds offset
- ;* external >= ROM_size forces user z8 to write
- ;*
- ;* input: RR8 contains address to be written to.
- ;* R15 contains data to be written.
- ;*
- ;****************************************************************;
-
- ; write to data memory ?
- CP D_MEMFLAG, #$ff ;X command ?
- JR EQ, EXT_MEM_PUT
-
- ; write to program memory
- PM_INTERN:
- PUSH R6 ; save
- PUSH R7 ; use RR6 for LDE
- LD R6,R8
- LD R7,R9
- LDC @RR6,R15 ; write byte to program memory
- POP R7 ;
- POP R6 ;
- RET ; deliver the byte
-
- ; write to data memory
- EXT_MEM_PUT:
- PUSH R6 ; save
- PUSH R7 ; use RR6 for LDE
- LD R6,R8
- LD R7,R9
- LDC @RR6,R15 ; write byte to data memory
- POP R7 ;
- POP R6 ;
- RET ; deliver the byte
-
-
-
- PUTEXT
- ;*****************************************************
- ;*
- ;* PUTEXT Store downloaded data into extension area.
- ;* Makes sure that address is valid.
- ;* Address must be in $D000 - $DFFF range.
- ;*
- ;* input R4 has byte value to be stored
- ;* RR14 has address to store value in
- ;*
- ;* output LDC @RR14,R4
- ;*
- ;*
- ;********************************************************;
-
- CP R14,#$D0 ; address below $D000?
- JR LT,BAD_ADDR ; yes
- CP R14,#$DF ; address above $DFFF?
- JR GT,BAD_ADDR ; yes
-
- LDC @RR14,R4
- JR DONE_PUTEXT
-
- BAD_ADDR:
- LD ERR_CODE,#BAD_EXT_ADDR
-
- DONE_PUTEXT:
- RET
-
-
-
- DISPMEMLINE
- ;*****************************************************
- ;*
- ;* DISPMEMLINE Display a line of memory
- ;*
- ;* input RR10 points to first address
- ;* RR0 has count of data to be displayed
- ;*
- ;* used R2 counts characters in half line segment
- ;* R3 to count half line segments
- ;* R4 to output data to console
- ;* R5,R10,R11 are used by OUTADDR
- ;*
- ;* output R2 = 0
- ;* R3 = 0
- ;* R5 = 0
- ;* RR10 = RR10 + # of locations displayed
- ;* RR0 = RR0 - # of locations displayed
- ;* R4 has last ASCII character output
- ;*
- ;*****************************************************;
-
- PUSH R8
- PUSH R9
- PUSH R15
-
- LD R3,#$02 ; disp 2 8-byte segments
- A_LINE:
- LD R2,#$08 ; assume full half lines
- CP R0,#$00 ; how much left to display?
- JR NZ,DO_LIN_SEG ; enough for a line seg
-
- CP R1,#$08 ;
- JR NC,DO_LIN_SEG ; ditto
-
- CP R1,#$00 ; any left at all
- JR Z,ALL_DISPED ; no,just exit
-
- LD R2,R1 ; display partial line seg
- DO_LIN_SEG:
- SUB R1,R2 ; adjust count
- SBC R0,#$00 ; subtract carry from hi byte
-
- HALFLINE:
- CALL OUTADDR ; line starts with address
-
- LINESEG:
- PUSH R4 ; data
- PUSH R10 ; hi addr
- PUSH R11 ; lo addr
- LD R8,R10
- LD R9,R11
- CALL GETMEM ; LDE R15,@RR8
- POP R11 ;
- POP R10 ;
- POP R4 ;
-
- LD R4,R15
- CALL OUTDAT ; display
- INCW RR10 ; move pointer
- DJNZ R2,LINESEG ; DJNZ R2,LINESEG
-
- CP R3,#2 ; are we at midpoint?
- JR NE,NOT_MID
- LD R4,#ASCIISP ; yes, output 2 spaces
- CALL OUTCHR
- CALL OUTCHR
-
- NOT_MID:
- DJNZ R3,A_LINE ; DJNZ R3,A_LINE
-
- ALL_DISPED:
- POP R15
- POP R9
- POP R8
-
- RET ; finished
-
-
-
-
- DISPASCII
- ;*****************************************************
- ;*
- ;* DISPASCII Display ASCII portion memory dump
- ;*
- ;*
- ;* input RR12 point to segment to display
- ;* RR10 point to next segment
- ;*
- ;* used R4 for character output
- ;* R5 for counter
- ;*
- ;* output RR10 saved, ASCII displayed on console
- ;* RR12 = RR10
- ;* R4 = <LF>, and R5 = 0
- ;*
- ;*****************************************************;
- PUSH R8
- PUSH R9
- PUSH R10 ; save pointer to next
- PUSH R11 ; segment in memory
- PUSH R15
-
- LD R4,#ASCIISP ; tab one space
- CALL OUTCHR
-
- SUB R11,R13 ; how many were displayed?
- CP R11,#$10 ; was it a full line ?
- JR EQ,ASCOUT ; output the ASCII
-
- CP R11,#$08 ; at least half a line ?
- JR GT,MTHALF ; yes,more than half
-
- LD R5,#$05 ; put out extra spaces
- LD R4,#ASCIISP ;
- SKIPHD:
- CALL OUTCHR ;
- DJNZ R5,SKIPHD ; DJNZ R5,SKIPHD
- MTHALF:
- PUSH R11 ; save numberr displayed
- COM R11 ; get complement
- AND R11,#$0F ; mask off upper nibble
- INC R11 ; increment for correct count
- ; now have # not displayed
- LD R4,#ASCIISP ; put out 3 spaces for each
- OUT3SP:
- LD R5,#$03 ; location in a line not displayed
- SPACE_3:
- CALL OUTCHR ;
-
- DJNZ R5,SPACE_3 ; DJNZ R5,SPACE_3
-
- DJNZ R11,OUT3SP ; DJNZ R11,OUT3SP
-
- POP R11 ; get back number displayed
- ASCOUT:
- LD R4,#ASCIISTAR ; start displayed with a star
- CALL OUTCHR ;
- PRINT_IT:
- PUSH R4 ; data
- PUSH R12 ; hi addr
- PUSH R13 ; lo addr
- LD R8,R12
- LD R9,R13
- CALL GETMEM ; LDE R15,@RR8
- POP R13 ;
- POP R12 ;
- POP R4 ;
-
- ; data is in R15
- LD R4,R15
- CP R4,#ASCIISP ; is it printable?
- JR GE,MAY_PRINT ; maybe
- UN_PRINT:
- LD R4,#ASCIIDOT ; output a dot if not
- JR CAN_PRINT ; a printable character
- MAY_PRINT:
- CP R4,#$7F ; it could be too large
- JR GE,UN_PRINT ; so can't print it
- CAN_PRINT:
- CALL OUTCHR ; output the character
- ; be it a dot or ASCII
- INCW RR12 ; increment pointer
-
- DJNZ R11,PRINT_IT ; DJNZ R11,PRINT_IT
-
- LD R4,#ASCIISTAR ; final star
- CALL OUTCHR ;
- CALL CRLF ; end of line
- POP R15 ;
- POP R11 ; restore pointer to nxt
- POP R10 ; segment of memory
- POP R9
- POP R8
- RET ;
-
-
-
-
- COMPDISP
- ;*******************************************************
- ;*
- ;* COMPDISP
- ;*
- ;* input RR0 point to addr1
- ;* RR2 point to addr2
- ;* R14 has contents of RR0
- ;* R15 has contents of RR2
- ;*
- ;* used R8 (saved first) to point to R14,R15
- ;* R4 for character output
- ;* R5,R10,R11 for address output
- ;* R12 to point to registers RR0,RR2
- ;* R13 to count to 2
- ;*
- ;* output R8 preserved
- ;* R13 = 0
- ;* R5 = 0
- ;* R4 = <LF>
- ;* R12 points to R4
- ;* R10,R11 destroyed
- ;* RR0,RR2,R14,R15 unchanged
- ;*
- ;*****************************************************;
- PUSH R8 ; used in calling routine
-
- LD R12,RP0 ; point to R0 with R12
- LD R8,R12 ; make R8 point to R14
- ADD R8,#14 ; to get the values
- LD R13,#$02 ; two values to display
-
- DISP_COMP:
- LD R10,@R12 ; display address
- INC R12 ;
- LD R11,@R12 ;
- INC R12 ;
-
- CALL OUTADDR ; line starts with address
-
- LD R4,#ASCIIEQ ; connect with an equals
- CALL OUTCHR ;
- LD R4,#ASCIISP ; and space
- CALL OUTCHR ;
-
- LD R4,@R8 ; get contents into R4
- INC R8 ;
- CALL OUTDAT ;
-
- DJNZ R13,DISP_COMP ; DJNZ R13,disp_comp
-
- CALL CRLF ; new line
- POP R8 ; restore
- RET
-
-
-
- DELAY
- ;*******************************************************
- ;*
- ;* DELAY kill time routine.
- ;*
- ;* input R4 has delay variable
- ;*
- ;*******************************************************;
- PUSH R5
-
- DELAY_LOOP:
- LD R5,#$40
- DELAY_R5:
- DJNZ R5,DELAY_R5
- DJNZ R4,DELAY_LOOP
-
- POP R5
- RET
-
-
- ;**********************************************
- ;*
- ;* reg.s : Register display and edit
- ;* routines.
- ;*
- ;**********************************************;
-
-
-
- CONSTANT
- RW equ $00 ; read/write register
- WO equ $01 ; write only register
- RO equ $02 ; read only register
- UI equ $04 ; unimplemented register
-
-
- REGISTERS
- ;******************************************************
- ;*
- ;* REGISTER display and alter
- ;*
- ;* syntax R [-S|C|SC] [<REG NUMBER> [<REG VALUE>]]
- ;*
- ;* defaults *
- ;******************************************************;
- CLR REG_MODE
-
- ; look for SC option in command line
- ; GET_SC_OPT sets REG_MODE accordingly
-
- CALL GET_SC_OPT ; look for SC options
- CP ERR_CODE,#BAD_OPT
- JR EQ,DONE_REGISTER
-
- CALL GETADDR ; are there parameters?
- JR C,DISP_REGS ; no, display all
- PUSH R11 ; save register number
- CALL GETADDR ; is it a single command?
- JP C,EDIT_REG ; no,scroll thru registers
- POP R9 ; get the reg number into R9
-
- CALL WRITE_1_REG ; write value in R11 into
- ; reg pointed to by R9
- RET
-
- DISP_REGS
- CP ERR_CODE,#BAD_HEX ; was there a bad reg# ?
- JR EQ,DONE_REGISTER
-
- ; Display system registers
- TM REG_MODE,#S_FLAG ; display sys regs?
- JR Z,CNTRL_MODE ; no
- CALL SYS_REG ; yes
- TM REG_MODE,#C_FLAG ; displaying control
- JR Z,DONE_REGISTER ; also? no
- CALL CRLF ; yes, so put an extra CR
-
- ; Display control registers
- CNTRL_MODE
- TM REG_MODE,#C_FLAG ; display ctl regs?
- JR Z,GEN_MODE ; no
- CALL CNTR_REG ; yes
-
- ; Display general purpose registers
- GEN_MODE
- TM REG_MODE,#S_FLAG+C_FLAG ; display gen. regs?
- JR NZ,DONE_REGISTER ; no
- CALL GEN_PURPOSE ; yes
-
- RET
-
- EDIT_REG
- CALL EDIT_STATUS ; indicate to host edit mode
-
- POP R9 ; get the reg number into R9
- CP ERR_CODE,#BAD_HEX ; was there a bad reg value?
- JR EQ,DONE_REGISTER ; yes
-
- TM REG_MODE,#S_FLAG ; edit sys regs?
- JP NZ,EDIT_SYS ; yes, JP to edit
- ; sys regs procedure
-
- TM REG_MODE,#C_FLAG ; edit ctl regs?
- JP NZ,EDIT_CTL ; yes, JP to edit
- ; ctl reg procedure
-
- ; edit gen. regs?
- TM REG_MODE,#S_FLAG+C_FLAG
- JR NZ,DONE_REGISTER ; no
- CALL EDIT_GEN ; yes
-
- DONE_REGISTER
- RET ; stop the command
-
-
-
-
- WRITE_1_REG
- ;*****************************************************************
- ;*
- ;* WRITE_1_REG Write the value in R11 into the user
- ;* register pointed to by R9.
- ;*
- ;* input: R9 has the user register number to be written to.
- ;* R11 has the value to be written.
- ;* REG_MODE has the appropriate flags set for the
- ;* '-S' and '-C' options.
- ;*
- ;* output: If no errors are found, the value is written to
- ;* the user register.
- ;*
- ;*******************************************************************;
- TM REG_MODE,#C_FLAG+S_FLAG
- ; is it a sys or ctl register?
- JR NZ,WRITE_SC ; yes
-
- ; it's a general purpose register
- CP R9,#$C0 ; is register < $C0 ?
- JR ULT,WRITE_R ; yes, write direct
- JR WRITE_IR ; no, write indirect
-
- WRITE_SC
- CP R9,#$C0 ; is it < $C0 ?
- JR ULT,ERR_WR1 ; yes, error
- CP R9,#$CF ; is it > $CF ?
- JR UGT,WRITE_R ; yes, write it
-
- ; it's a "set one" Cx register
- LD D_MEMFLAG,#$FF ; indicate a write
- CALL RD_WR_CX ; to a Cx register
- CLR D_MEMFLAG
- JR DONE_WR_1
-
- WRITE_IR
- CALL WRITE_IR_REG ; write indirect
- JR DONE_WR_1
-
- WRITE_R
- ; check for control register
- CP R9,#$E0 ; is it >= $E0?
- JR ULT,NO_BANK ; no, a sys register
-
- ; check for bank 0
- TM REG_MODE,#ZERO_FLAG ; bank zero ?
- JR Z,CHECK_BANK1 ; no
-
- ; its a bank 0 register write
- PUSH R2 ; save R2
- CLR R2 ; a bank 0 register
- LD D_MEMFLAG,#$FF ; a write
- CALL RD_WR_BANK ; write it
- POP R2 ; restore R2
- CLR D_MEMFLAG
- JR DONE_WR_1
-
- CHECK_BANK1
- ; check for bank 1
- TM REG_MODE,#ONE_FLAG ; bank ONE ?
- JR Z,NO_BANK ; no
-
- ; its a bank 1 register write
- PUSH R2 ; save R2
- LD R2,#1 ; a bank 1 register
- LD D_MEMFLAG,#$FF ; a write
- CALL RD_WR_BANK ; write it
- POP R2 ; restore R2
- CLR D_MEMFLAG
- JR DONE_WR_1
-
-
- NO_BANK
- CALL WRITE_DIR_REG ; write direct
-
- DONE_WR_1
- RET
-
- ERR_WR1
- LD ERR_CODE,#BAD_PARAM_VAL
- JR DONE_WR_1
-
-
-
- GET_SC_OPT
- ;***********************************************************
- ;*
- ;* GET_SC_OPT Look at the command line for the
- ;* [-S | -C | -SC | -C0 | -C1] options. Set
- ;* REG_MODE with the appropriate flags.
- ;*
- ;************************************************************;
-
- AND REG_MODE,#GEN_FLAG ; assume no option
- CALL FINDOPT ; look for option in command
- CP R10,#0 ; is there no option
- JR EQ,DONE_SC
-
- CP R10,#ASCIISP ; just a " " following "-" ?
- JR EQ,SC_ERROR
-
- CP R10,#ASCIICR ; just a <CR> following "-" ?
- JR EQ,SC_ERROR
-
- ; check for option in R10
- CP R10,#'s' ; check R10 for 's' opt
- JR NE,R10_NOT_S
- OR REG_MODE,#S_FLAG
- JR CHECK_R11
-
- R10_NOT_S
- CP R10,#'c' ; if its not a 'c' and
- JR NE,SC_ERROR ; not an 's', its an error
- OR REG_MODE,#C_FLAG
-
- CHECK_R11
- ; check for option in R10
- CP R11,#ASCIISP ; check for a space
- JR EQ,DONE_SC
- CP R11,#ASCIICR ; check for a CR
- JR EQ,DONE_SC
-
- CP R11,#'s' ; check R11 for 's' opt
- JR NE,R11_NOT_S
- OR REG_MODE,#S_FLAG
- JR DONE_SC
-
- R11_NOT_S
- CP R11,#'c' ; check for 'c' option
- JR NE,R11_NOT_C ; not an 's'
- OR REG_MODE,#C_FLAG
- JR DONE_SC
-
- R11_NOT_C
- CP R11,#'0' ; a 0 ?
- JR NE,R11_NOT_0 ; not a '0'
- CP R10,#'c' ; was 1st opt a 'c'?
- JR NE,SC_ERROR ; no, error
- OR REG_MODE,#ZERO_FLAG ; yes, set flag
- JR DONE_SC
-
- R11_NOT_0
- CP R11,#'1' ; a 1 ?
- JR NE,SC_ERROR ; not a '1'
- CP R10,#'c' ; was 1st opt a 'c'?
- JR NE,SC_ERROR ; no, error
- OR REG_MODE,#ONE_FLAG ; yes, set flag
-
- DONE_SC
- RET
-
- SC_ERROR
- CLR REG_MODE
- LD ERR_CODE,#BAD_OPT
- JR DONE_SC
-
-
-
-
- EDIT_GEN
- ;*************************************************************
- ;*
- ;* EDIT_GEN Edit the general purpose registers
- ;*
- ;* input: starting register number is in R9
- ;*
- ;*
- ;***************************************************************;
- CLR ERR_CODE ; NOT AN ERROR
-
- DISP_1_REG
- LD R4,R9 ; display the register value
- CALL OUTDAT ;
-
- PUSH R9 ; save reg number
- CP R9,#$C0 ; set two register?
- JR UGE,IR_READ ; yes
-
- CALL READ_DIR_REG ; read reg. number R9
- JR READ_RESULT
-
- IR_READ
- CALL READ_IR_REG ; read set two reg. number R9
-
- READ_RESULT
- LDC R4,@RR6 ; display the register contents
- CALL OUTDAT ;
- POP R9 ; restore reg number
-
- ; prompt for a new value, package STX and ETX around
- ; prompt for the host package
- LD R4,#ASCIISTX
- CALL OUTCHR
- LD R4,#'+' ; prompt for a new value
- CALL OUTCHR ;
- LD R4,#ASCIIETX
- CALL OUTCHR
-
- CALL GETLINE ; input response up to <CR>
-
- REG_TOKEN
- CP R4,#ASCIIQ ; is it a quit?
- JR Z,END_REG ; stop the command sequence
-
- CP R4,#'q' ; is it a quit?
- JR Z,END_REG ; stop the command sequence
-
- CP R4,#ASCIIUP ; is it an ^
- JR NZ,REG_DOT ; if not check for dot
- DEC R9 ; it is a ^,do previous
- JR DISP_1_REG ; display previous register
- REG_DOT
- CP R4,#ASCIIDOT ; dot displays same
- JR Z,DISP_1_REG ;
-
- CP R4,#ASCIICR ; just display next?
- JR NZ,NEW_REG_VAL ; no, convert the number
- JR MORE_REG ;
-
- NEW_REG_VAL
- CLR R10 ;
- CLR R11 ;
- CALL CON_BYTE ; convert
- JR C,END_REG ; error
-
- CP R9,#$C0 ; a set two register?
- JR UGE,WRITE_IND ; yes
-
- CALL WRITE_DIR_REG ; no, write R11 into R9
- JR WROTE_REG
-
- WRITE_IND
- CALL WRITE_IR_REG ; write R11 into R9
- ; (set two)
-
- WROTE_REG
- CALL FINDNEXT ; is there a token also?
- JR NZ,REG_TOKEN ; yes,there is more on the line
- MORE_REG
- INC R9 ; increment register pointer
- JP DISP_1_REG ; display the nest register
-
- END_REG
- RET ; stop the command
-
-
-
- EDIT_SYS
- ;*************************************************************
- ;*
- ;* EDIT_SYS Edit the system registers
- ;*
- ;*
- ;* input: starting register number is in R9
- ;*
- ;***************************************************************;
- CLR ERR_CODE ; NOT AN ERROR
-
- CP R9,#$D0 ; too low for a sys reg.?
- JR UGE,CHK_SYS_HI ; no
- LD ERR_CODE,#BAD_PARAM_VAL ; yes
- JR END_SYS_ED
-
- CHK_SYS_HI
- CP R9,#$DE ; too high for a sys reg.?
- JR ULE,DISP_1_SYS ; no
- LD ERR_CODE,#BAD_PARAM_VAL ; yes
- JR END_SYS_ED
-
- DISP_1_SYS
- LD R4,R9 ; display the register value
- CALL OUTDAT ;
-
- CALL READ_DIR_REG ; read reg pointed to by R9
-
- LDC R4,@RR6 ; display the register contents
- CALL OUTDAT ;
-
- ; prompt for a new value, package STX and ETX around
- ; prompt for the host package
- LD R4,#ASCIISTX
- CALL OUTCHR
- LD R4,#'+' ; prompt for a new value
- CALL OUTCHR ;
- LD R4,#ASCIIETX
- CALL OUTCHR
-
- CALL GETLINE ; input response up to <CR>
-
-
- SYS_TOKEN
- CP R4,#ASCIIQ ; is it a quit?
- JR Z,END_SYS_ED ; stop the command sequence
-
- CP R4,#'q' ; is it a quit?
- JR Z,END_SYS_ED ; stop the command sequence
-
- CP R4,#ASCIIUP ; is it an ^
- JR NZ,SYS_DOT ; if not check for dot
- DEC R9 ; it is a ^,do previous
- CP R9,#$CF ; at boundry?
- JR UGT,DISP_1_SYS ; no
- LD R9,#$DE ; yew
- JR DISP_1_SYS ; display previous register
- SYS_DOT
- CP R4,#ASCIIDOT ; dot displays same
- JR Z,DISP_1_SYS ;
-
- CP R4,#ASCIICR ; just display next?
- JR NZ,NEW_SYS_VAL ; no, convert the number
- JR MORE_SYS ;
- NEW_SYS_VAL
- CLR R10 ;
- CLR R11 ;
- CALL CON_BYTE ; convert
- JR C,END_SYS_ED ; error
- CALL WRITE_DIR_REG ; write R11 into R9
- CALL FINDNEXT ; is there a token also
- JR NZ,SYS_TOKEN ; yes,there is more on the line
- MORE_SYS
- INC R9 ; indrement pointer to reg
- CP R9,#$DF ; at boundry ?
- JP ULT,DISP_1_SYS ; no
- LD R9,#$D0 ; yes
- JP DISP_1_SYS ; display the next register
-
- END_SYS_ED
- RET ; stop the command
-
-
-
-
- EDIT_CTL
- ;*************************************************************
- ;*
- ;* EDIT_CTL Edit the control registers
- ;*
- ;*
- ;* input: starting register number is in R9
- ;*
- ;***************************************************************;
- PUSH R2
-
- ; check for start bank
- TM REG_MODE,#ONE_FLAG ; bank one?
- JR Z,ITS_BANK2 ; no
- LD R2,#1 ; yes, set number
- JR CLEAR_ERR
-
- ITS_BANK2
- CLR R2 ; bank number starts with 0
-
- CLEAR_ERR
- CLR ERR_CODE ; not an error
-
- ; check for reg number between $C0 and $CF
- CP R9,#$C0 ; reg number < $C0 ?
- JP ULT,CTL_BAD_PARAM ; yes
- CP R9,#$CF ; reg number <= $CF ?
- JR ULE,DISP_1_CTL ; yes
-
- ; check for reg number between $E0 and $CF
- CP R9,#$E0 ; reg number < $E0 ?
- JP ULT,CTL_BAD_PARAM ; yes
-
- DISP_1_CTL
- LD R4,R9 ; display the register number
- CALL OUTHEX ;
-
- ; display the bank number if in range $E0 - $FF
- CP R9,#$CF ; a control register?
- JR ULE,CX_REG ; no, a Cx register
-
- LD R4,#'/' ; display bank number
- CALL OUTCHR
- LD R4,R2 ; save bank # in R4
- LD R6,#REGBUF
- CALL BTOHEXDAT ; convert to ASCII
- LD R4,REGBUF+1 ; get least sig. digit
- CALL OUTCHR ; print it
- LD R4,#ASCIISP
- CALL OUTCHR
-
- CLR D_MEMFLAG ; indicate a read
- CALL RD_WR_BANK ; read reg pointed to by R9
- LD R4,R10 ; R10 has the value
-
- JR OUT_REG
-
- CX_REG
- LD R4,#ASCIISP ; write out a space
- CALL OUTCHR
-
- CALL RD_WR_CX ; Cx reg pointed to by
- ; R9 and load its value
- ; into R4
-
- OUT_REG
- CALL OUTDAT ; display register vlaue
-
- ; prompt for a new value, package STX and ETX around
- ; prompt for the host package
- LD R4,#ASCIISTX
- CALL OUTCHR
- LD R4,#'+' ; prompt for a new value
- CALL OUTCHR ;
- LD R4,#ASCIIETX
- CALL OUTCHR
-
- CALL GETLINE ; input response up to <CR>
-
- CTL_TOKEN
- CP R4,#ASCIIQ ; is it a quit?
- JP Z,END_CTL_ED ; stop the command sequence
-
- CP R4,#'q' ; is it a quit?
- JP Z,END_CTL_ED ; stop the command sequence
-
- CP R4,#ASCIIUP ; is it an ^
- JR NZ,CTL_DOT ; if not check for dot
- DEC R9 ; it is a ^,do previous
- CP R9,#$DF ; past $E0 boundry?
- JR EQ,TO_CF ; yes, skip to $CF
- CP R9,#$BF ; past $C0 boundry?
- JP NE,DISP_1_CTL ; no, display previous
-
- ; wrap around and change bank numbers
- LD R9,#$FF ; start at $FF again
- CP R2,#0 ; bank 0?
- JR EQ,TO_BANK1 ; yes
- LD R2,#0 ; no, set to 0
- JP DISP_1_CTL
-
- TO_BANK1
- LD R2,#1 ; set to 1
- JP DISP_1_CTL
-
- TO_CF
- LD R9,#$CF ; start at $CF
- JP DISP_1_CTL
-
- CTL_DOT
- CP R4,#ASCIIDOT ; dot displays same
- JP Z,DISP_1_CTL ;
-
- CP R4,#ASCIICR ; just display next?
- JR NZ,NEW_CTL_VAL ; no, convert the number
- JR MORE_CTL ;
- NEW_CTL_VAL
- CLR R10 ;
- CLR R11 ;
- CALL CON_BYTE ; convert
- JR C,END_CTL_ED ; error
-
- ; write value in R11 into register pointed to by R9
- CP R9,#$CF ; a Cx register?
- JR ULE,WR_CX_REG ; yes
-
- LD D_MEMFLAG,#$FF ; indicate a write
- CALL RD_WR_BANK ; no, normal write
- CLR D_MEMFLAG
- JR NEXT_FIND
-
- WR_CX_REG
- LD D_MEMFLAG,#$FF ; indicate a write
- CALL RD_WR_CX ; to a Cx reg.
- CLR D_MEMFLAG
-
- NEXT_FIND
- CALL FINDNEXT ; is there a token also
- JR NZ,CTL_TOKEN ; yes,there's more on the line
- MORE_CTL
- CP R9,#$CF ; at $CF boundry ?
- JR EQ,TO_E0 ; yes, next is $E0
-
- CP R9,#$FF ; at $FF boundry ?
- JR ULT,INC_CTL_ED ; no
-
- ; wrap around and change bank number
- LD R9,#$C0 ; yes, prepare for $C0
- CP R2,#1 ; bank 1?
- JR EQ,TO_BANK0 ; yes
- LD R2,#1 ; no, set to 1
- JP DISP_1_CTL
-
- TO_BANK0
- LD R2,#0 ; set to 0
- JP DISP_1_CTL
-
- INC_CTL_ED
- INC R9 ; indrement register pointer
- JP DISP_1_CTL ; display the next register
-
- TO_E0
- LD R9,#$E0 ; new register is $E0
- JP DISP_1_CTL
-
- END_CTL_ED
- ; restore user flag register
- PUSH R9
- PUSH R11
- LD R9,#$D5 ; flag reg number
- LD R11,USER_FLAGS ; flag reg value
- CALL WRITE_DIR_REG ; write it
- POP R11
- POP R9
-
- POP R2
- RET
-
- CTL_BAD_PARAM
- LD ERR_CODE,#BAD_PARAM_VAL
- JR END_CTL_ED
-
-
-
- RD_WR_CX
- ;*************************************************************
- ;*
- ;* RD_WR_CX Read/write a "set one" register in the
- ;* range $C0 - $CF.
- ;*
- ;* input: R9 has the register number to be read.
- ;* D_MEMFLAG is 0 for a read and $FF for a write.
- ;* R11 has the value to be written for a write.
- ;*
- ;* output: R4 has the register value for a read.
- ;*
- ;*************************************************************;
-
- PUSH R9 ; save reg number
- PUSH R11 ; save value
-
- ; read RP0 and RP1 and save them
- LD R9,#$D6 ; RP0
- CALL READ_DIR_REG ; read it
- LDC R4,@RR6
- LD USER_RP0,R4 ; save it
-
- LD R9,#$D7 ; RP1
- CALL READ_DIR_REG ; read it
- LDC R4,@RR6
- LD USER_RP1,R4 ; save it
-
- ; write $C0 and $C8 to RP0 and RP1
- LD R9,#$D6 ; RP0
- LD R11,#$C0 ; gets $C0
- CALL WRITE_DIR_REG ; write it
- LD R9,#$D7 ; RP1
- LD R11,#$C8 ; gets $C8
- CALL WRITE_DIR_REG ; write it
-
-
- ; now read/write the register
- POP R11 ; restore reg value
- POP R9 ; restore reg number
-
- CP D_MEMFLAG,#0 ; is it a read?
- JR EQ,READ_CX ; yes
-
- CALL WRITE_DIR_REG ; write it
- JR RESTORE_CX
-
- READ_CX
- CALL READ_DIR_REG ; read it
- LDC R4,@RR6 ; save it
-
- ; restore RP0 and RP1
- RESTORE_CX
- PUSH R9 ; save reg number
- PUSH R11 ; save value
- LD R9,#$D6 ; RP0
- LD R11,USER_RP0
- CALL WRITE_DIR_REG ; write it
-
- LD R9,#$D7 ; RP1
- LD R11,USER_RP1
- CALL WRITE_DIR_REG ; write it
- POP R11 ; restore reg value
- POP R9 ; restore reg number
-
- RET
-
-
-
- SYS_REG
- ;*************************************************************
- ;*
- ;* SYS_REG Display all system registers
- ;*
- ;***************************************************************;
-
- CLR ERR_CODE ; clear errors
-
- ; display 1st row of PC and system registers
- LD R6,#^HB SYS1_H_REG ; print 1st nmemonic
- LD R7,#^LB SYS1_H_REG ; header for system
- CALL OUTMSG ; registers
-
- LD R6,#^HB SYS1_N_REG ; print the register
- LD R7,#^LB SYS1_N_REG ; numbers
- CALL OUTMSG ;
-
- ld r10,USERPC_HI ; Print
- ld r11,USERPC_LO ; user
- call OUTADDR ; PC
- LD R4,#ASCIISP ; tab 1 space
- CALL OUTCHR
-
- LD R9,#$D0 ; display start
- LD R10,#$D6 ; display end
- CALL SYS_OUT ; display the regs
- CALL CRLF ;
- CALL CRLF ; one blank line
-
- ; display 2nd row of system registers
- LD R6,#^HB SYS2_H_REG ; print 2nd nmemonic
- LD R7,#^LB SYS2_H_REG ; header for system
- CALL OUTMSG ; registers
- LD R6,#^HB SYS2_N_REG ; print the register
- LD R7,#^LB SYS2_N_REG ; numbers
- CALL OUTMSG ; for input
-
- LD R9,#$D7 ; display start
- LD R10,#$DE ; display end
- CALL SYS_OUT ; display the regs
- CALL CRLF ;
- RET
-
-
- GEN_PURPOSE
- ;*************************************************************
- ;*
- ;* GEN_PURPOSE Display all general purpose registers
- ;*
- ;***************************************************************;
- PUSH R6
- PUSH R7
- PUSH R9
- PUSH R10
- PUSH R11
- PUSH R12
-
- ; R12 has the leading character, a 'R' (working register)
- ; or ' '. Space is the default
-
- LD R12,#' '
- CLR R9 ; register counter
- LD R6,#^HB GEN_REG_H ; print the register
- LD R7,#^LB GEN_REG_H ; numbers header
- CALL OUTMSG ; for input
-
- GEN_LOOP
-
- PUSH R9 ; save reg number
- CP R9,#$C0 ; set two register?
- JR UGE,GEN_READ_IR ; yes
-
- CALL READ_DIR_REG ; read (direct) reg. number R9
- JR GEN_GET_RESULT
-
- GEN_READ_IR
- CALL READ_IR_REG ; read set two (indirect) reg. number R9
-
- GEN_GET_RESULT
- ; RR6 now points to result register
- LDC R10,@RR6 ; save register value
- ; in R10
- POP R9 ; restore reg number
-
- TM R9,#$0F ; R9 = x0 ?
- JR NZ,CHECK_RP ; no
-
- ; write out high nibble for row
- CALL CRLF
- LD R4,#'r' ; write 'r'
- CALL OUTCHR
-
- LD R6,#OUT_CHR1 ; destination of NIBBLE
- LD R4,R9 ; load reg number
- SWAP R4 ; put upper nibble in lower
- CALL NIBBLE ; convert to ASCII
- LD R4,OUT_CHR1 ; write it
- CALL OUTCHR
-
- LD R4,#'x' ; write 'x'
- CALL OUTCHR
- LD R4,#ASCIISP ; write ' '
- CALL OUTCHR
- CALL OUTCHR
- CALL OUTCHR ; 3 times
-
- CHECK_RP
- TM R9,#$07 ; are we at an 8th reg?
- JR NZ,WRITE_IT ; no
-
- CP R9,USER_RP0 ; equal to RP0 ?
- JR NE,CHECK_RP1 ; no, check RP1
-
- CP R9, #$C0 ; are we still in register area?
- JR UGE, CHECK_RP1
-
- LD R12,#'R' ; yes, output leading 'R'
- JR WRITE_IT
-
- CHECK_RP1
- CP R9,USER_RP1 ; equal to RP1 ?
- JR NE, NOT_RP ; no
-
- CP R9, #$C0 ; are we still in register area?
- JR UGE, NOT_RP
-
- LD R12,#'R' ; yes, output leading 'R'
- JR WRITE_IT
-
- NOT_RP
- LD R12,#' ' ; yes, output leading 'R'
-
- WRITE_IT
- LD R4,R12 ; output a leading
- CALL OUTCHR ; 'R' or ' '
- LD R4,R10 ; register value in R4
- LD R6,#OUT_CHR1 ; dest of BTOHEXDAT
- CALL BTOHEXDAT
-
- LD R4,OUT_CHR1 ; print high nibble
- CALL OUTCHR
- LD R4,OUT_CHR2 ; print low nibble
- CALL OUTCHR
-
- LD R4,#ASCIISP ; a trailing ' '
- CALL OUTCHR
-
- INC R9 ; next register
- CP R9,#0 ; are we done?
- JR EQ,DONE_GEN ; yes
- JP GEN_LOOP ; no, continue
-
- DONE_GEN
- CALL CRLF
- CLR ERR_CODE
- POP R12
- POP R11
- POP R10
- POP R9
- POP R7
- POP R6
- RET
-
-
- CNTR_REG
- ;*************************************************************
- ;*
- ;* CNTR_REG Display all control and mode registers
- ;*
- ;***************************************************************;
-
- CLR ERR_CODE ; clear errors
-
- AND CFLAG,#$F8 ; clear errors
-
- ; display 1st row of control and mode registers
-
- LD R6,#^HB CTL1_H_REG ; print 1st nmemonic
- LD R7,#^LB CTL1_H_REG ; header for control
- CALL OUTMSG ; registers
-
- LD R6,#^HB CTL1_N_REG ; print the register
- LD R7,#^LB CTL1_N_REG ; numbers
- CALL OUTMSG ;
-
- LD R9,#$E0 ; display start
- LD R10,#$F0 ; display end
- LD R11,#0 ; bank 0
- CALL CNTRL_OUT ; display the regs
- CALL CRLF
- CALL CRLF ; one blank line
-
- ; display 2nd row of control and mode registers
-
- LD R6,#^HB CTL2_H_REG ; print 2nd nmemonic
- LD R7,#^LB CTL2_H_REG ; header for control
- CALL OUTMSG ; registers
-
- LD R6,#^HB CTL2_N_REG ; print the register
- LD R7,#^LB CTL2_N_REG ; numbers
- CALL OUTMSG ;
-
- LD R9,#$F6 ; display start
- LD R10,#$FF ; display end
- LD R11,#0 ; bank 0
- CALL CNTRL_OUT ; display the regs
-
- ; last 4 regs of row 2 are bank 1 registers
-
- LD R9,#$E0 ; display start
- LD R10,#$E3 ; display end
- LD R11,#1 ; bank 1
- CALL CNTRL_OUT ; display the regs
-
- CALL CRLF
- CALL CRLF ; one blank line
-
- ; display 3rd row of control and mode registers
-
- LD R6,#^HB CTL3_H_REG ; print 3rd nmemonic
- LD R7,#^LB CTL3_H_REG ; header for control
- CALL OUTMSG ; registers
-
- LD R6,#^HB CTL3_N_REG ; print the register
- LD R7,#^LB CTL3_N_REG ; numbers
- CALL OUTMSG ;
-
- LD R9,#$E4 ; display start
- LD R10,#$FF ; display end
- LD R11,#1 ; bank 1
- CALL CNTRL_OUT ; display the regs
-
- CALL CRLF
- CALL CRLF ; one blank line
-
- ; display 4th row (Cx) registers
-
- LD R6,#^HB CTL4_N_REG ; print 3rd register
- LD R7,#^LB CTL4_N_REG ; numbers
- CALL OUTMSG ;
-
- LD R9,#$C0 ; display start
- LD R10,#$CF ; display end
- CALL SYS_OUT ; display the regs
- CALL CRLF
-
- RET
-
-
-
- SYS_OUT
- ;*******************************************************
- ;*
- ;* SYS_OUT Print out system or Cx registers.
- ;*
- ;* input R9 contains 1st register to be displayed.
- ;* R10 contains last register to be displayed.
- ;* R9 and R10 are in the range $C0 to $DE.
- ;* R9 <= R10.
- ;*
- ;*************************************************************;
-
- SYS_LOOP
- CALL READ_DIR_REG ; read S8 reg. @R9
- ; RR6 now points to result register
- LDC R4,@RR6 ; save the value
-
- LD R6,#OUT_CHR1 ; dest of BTOHEXDAT
- CALL BTOHEXDAT
-
- LD R4,OUT_CHR1 ; print high nibble
- CALL OUTCHR
- LD R4,OUT_CHR2 ; print low nibble
- CALL OUTCHR
-
- LD R4,#ASCIISP ; 2 trailing ' 's
- CALL OUTCHR ; for rCx regs.
- CALL OUTCHR
- CP R9,#$D0 ; rCx registers?
- JR LT,CHECK_DONE ; yes
-
- CALL OUTCHR ; 4 trailing ' 's
- CALL OUTCHR ; for sys regs.
-
- CHECK_DONE
- CP R9,R10 ; are we through
- JR EQ,SYS_DONE
-
- INC R9 ; next register
- JR SYS_LOOP
-
- SYS_DONE
- RET
-
-
-
- CNTRL_OUT
- ;*******************************************************
- ;*
- ;* CNTRL_OUT Print out control registers.
- ;* Skip over unimplemented or
- ;* write only registers.
- ;*
- ;* input R9 contains 1st register to be displayed.
- ;* R10 contains last register to be displayed.
- ;* R9 and R10 are in the range $E0 to $FF.
- ;* R9 <= R10.
- ;* R11 contains bank number to be displayed.
- ;*
- ;*************************************************************;
- PUSH R8
- PUSH R12
- PUSH R13
-
- LD R8,R9 ; save start reg.
-
- ; Now, do we want Bank 0 or 1 registers ?
-
- CP R11,#0
- JR NE,BANK_1
-
- ; Bank 0
- LD R12,#^HB BANK_0_TAB ; point to proper table
- LD R13,#^LB BANK_0_TAB
- JR FIND_ENTRY
-
- ; Bank 1
- BANK_1
- LD R12,#^HB BANK_1_TAB ; point to proper table
- LD R13,#^LB BANK_1_TAB
-
- ; Find correct location in lookup table for first register requested
-
- FIND_ENTRY
- SUB R8,#$E0 ; find offset from $E0
- LOOP_FIND
- CP R8,#0 ; are we through ?
- JR EQ,CNTRL_LOOP ; yes
- DEC R8 ; decrement counter
- INCW RR12 ; point to next byte in table
- JR LOOP_FIND
-
- ; check for unimplemented or write-only
- ; control registers
- CNTRL_LOOP
- LDC R4,@RR12 ; get value from table
- CP R4,#UI
- JR EQ,NEXT_CNTRL
- CP R4,#WO
- JR EQ,NEXT_CNTRL
-
- START_READ
-
- ; Fisrt save the current user flag register
- ; so we know which bank (0 or 1) to return to
-
- push FLAGS ; save it
-
- ; set correct bank number
-
- CP R11,#0 ; bank 0 ?
- JR NE,SET_BANK_1 ; no
- sb0
- JR WRITE_FLAG
-
- SET_BANK_1
- sb1
-
- WRITE_FLAG
-
- ; now read the correct control register
- CALL READ_DIR_REG ; read S8 reg. @R9
-
- ; Restore flag register so we back to the correct bank (0 or 1)
- pop FLAGS
-
- ; RR6 now points to result register
- LDC R4,@RR6 ; save the value
-
- LD R6,#OUT_CHR1 ; dest of BTOHEXDAT
- CALL BTOHEXDAT
-
- LD R4,OUT_CHR1 ; print high nibble
- CALL OUTCHR
- LD R4,OUT_CHR2 ; print low nibble
- CALL OUTCHR
-
- LD R4,#ASCIISP ; 4 trailing ' 's
- CALL OUTCHR
- CALL OUTCHR
- CALL OUTCHR
- CALL OUTCHR
-
-
- NEXT_CNTRL
- CP R9,R10 ; are we through ?
- JR GE,DONE_CNTRL
- INC R9 ; next register
- INCW RR12
- JR CNTRL_LOOP
-
- DONE_CNTRL
-
- POP R13
- POP R12
- POP R8
- RET
-
-
-
- RD_WR_BANK
- ;*******************************************************
- ;*
- ;* BANK_REG Read/write the correct control register
- ;* value for the given bank0/bank1 register.
- ;*
- ;* input R9 contains register number and must be
- ;* in the range $E0 through $FF.
- ;* R2 contains bank number.
- ;* R11 contains the value to be written.
- ;*
- ;* output R10 has the register value read.
- ;*
- ;*
- ;*******************************************************;
- PUSH R4
- PUSH R9 ; save reg number
- LD R9,#$D5 ; read flag register
- CALL READ_DIR_REG
- LDC R4,@RR6
- LD USER_FLAGS,R4
- POP R9
-
- ; determine bank, R4 has bank value
- CP R2,#0 ; bank 0 ?
- JR EQ,SET_BANK0
- OR R4,#$01 ; bank 1
- JR WRITE_BANK
-
- SET_BANK0
- AND R4,#$FE ; bank 0
-
- WRITE_BANK
- PUSH R9 ; save used regs
- PUSH R11
- LD R11,R4
- LD R9,#$D5 ; read flag register
- CALL WRITE_DIR_REG
- POP R11
- POP R9
-
- ; check for a read or write
- CP D_MEMFLAG,#0 ; a read?
- JR NE,WR_BANK_REG
-
- ; now read the register, R9 has reg number
- CALL READ_DIR_REG
- LDC R10,@RR6 ; save in output reg
- JR RESTOR_FLAG
-
- WR_BANK_REG
- CALL WRITE_DIR_REG
-
- RESTOR_FLAG
- ; restore user flag register
- PUSH R9 ; save used regs
- PUSH R11
- LD R9,#$D5 ; flag reg number
- LD R11,USER_FLAGS ; flag reg value
- CALL WRITE_DIR_REG ; write it
- POP R11
- POP R9
- POP R4
- RET
-
-
- ;*********************************************
- ;*
- ;* new.s : Misc. commands
- ;*
- ;* (1) Phill (fill) registers
- ;* (2) Interrupt enable/disable
- ;* (3) Working register display
- ;* (4) Echo on/off
- ;* (5) Verify (self test)
- ;*
- ;**********************************************;
-
-
- PHIL_REGISTERS
- ;************************************************
- ;*
- ;* PHILL fill general registers just as memory
- ;* is filled.
- ;*
- ;* syntax P <REG NUM> <NUM OF REGS> {<DATA>}
- ;*
- ;************************************************;
-
- CALL GETADDR ; get first reg num
- JR C,BADHX_ ; no good
- LD R9,R11 ; first register
- CALL GETADDR ; number of registers
- JR C,BADHX_ ; no good
- LD R2,R11 ; put length in R2
-
- CLR OUTPTR ; use input buffer to
- CLR R13 ; store converted pattern
- ACCUM_
- CALL GETADDR ; get value
- JR C,DO_FILL_ ; stop input and fill regs
- LD R7,OUTPTR ;
- LDC @RR6,R11 ; one byte of data
- INC R13 ; keep count
- INC OUTPTR ;
- JR ACCUM_ ; get next data byte
-
- DO_FILL_
- CP R13,#$00 ; if no data, don't fill
- JR EQ,BADHX_ ;
- LD R0,R6 ; use RR0 to access pattern
-
- RE_PEAT_
- LD R8,R13 ; save pattern length
- CLR R1 ; and start at begin of pattern
- R8LOOP_
- LDC R11,@RR0 ; get byte
-
- CP R9,#$C0 ; set two register?
- JR UGE,WRITE_IR1 ; yes
-
- CALL WRITE_DIR_REG ; no, write R11 into @R9
- JR WROTE_IT
-
- WRITE_IR1
- CALL WRITE_IR_REG ; write R11 into @R9
- ; (set two)
-
- WROTE_IT
- INC R9 ;
- INC R1 ;
- DEC R2 ; number of registers
- JR Z,PHIL_END ; done
- DJNZ R8,R8LOOP_ ;
- JR RE_PEAT_ ;
- PHIL_END
- CLR ERR_CODE ; no errors
- BADHX_
- RET ;
-
-
-
-
- INTERRUPT_ENABLE
- ;************************************************
- ;*
- ;* ENABLE USER INTERRUPTS in next 'go'
- ;*
- ;* syntax I [E|D]
- ;*
- ;* default E
- ;*
- ;************************************************;
- DI ; must DI to change IMR
- CALL FINDNEXT ; parameter?
- JR C,DEFAULT_I ; allow interrupts
- OR R4,#$20 ; upper or lower case
- CP R4,#'e' ; enable is default
- JR EQ,DEFAULT_I ;
- CP R4,#'d' ; disable
- JR NE,IN_ERROR ; invalid parameter
- CLR USER_EI
- JR ENABLE_GLOBAL ;
- DEFAULT_I
- CLR ERR_CODE ;
- LD USER_EI,#$FF ; go with interrupts
- JR ENABLE_GLOBAL ;
- IN_ERROR
- LD ERR_CODE,#BAD_OPT ; invalid parameter
- ENABLE_GLOBAL
- EI ;
- RET ;
-
-
-
-
- WORKING_REGS
- ;*************************************************
- ;*
- ;* WORKING register display/modify routine
- ;*
- ;* syntax W
- ;*
- ;*************************************************;
-
- CALL GETADDR ; Check for register number
- JP C,DISP_WREGS ; Jump if none found
-
- PUSH R10 ; save
- PUSH R11 ; it
-
- CALL GETADDR ; Check for a new value?
- JP C,EDIT_WREGS ; Jump if no value found to edit mode
-
- ; Write new value to working register
-
- POP R13 ;
-
- CP R13,#$a ;
- JR LT,GET_WREG ;
- SUB R13,#$6 ;
-
- GET_WREG
- POP R12 ; get register
- CP R13,#$f ; valid register
- JR GT,BADREG ;
-
- LD R9,#$D6 ; get rp0
- LD R12,R13 ;
-
- CP R13,#8 ; which RP
- JR LT,GET_RP
- INC R9
- SUB R12,#8
-
- GET_RP
- CALL READ_DIR_REG
- LDC R9,@RR6
- AND R9,#$F8
-
- ADD R9,R12 ; R9 is register, R11 value
- CALL WRITE_DIR_REG
- CLR ERR_CODE
- RET
-
- BADREG
- LD ERR_CODE,#BAD_PARAM_VAL
- RET
-
- ; Edit working register set
-
- EDIT_WREGS
- CLR ERR_CODE
- CALL EDIT_STATUS
-
- POP R11
- POP R10
-
- CP R11,#$15
- JR GT,BADREG
-
- CP R11,#10 ; convert hex to decimal
- JR LT,LOOP
- SUB R11,#6
-
- LOOP ; here we go editing
- CALL SEND_STX
- LD R4,#'R'
- CALL OUTCHR
-
- LD R4,R11 ; print register number
- CP R4,#10
- JR LT,LP1
- ADD R4,#6
- LP1
- CALL OUTHEX
-
- LD R4,#' '
- CALL OUTCHR
-
- LD R9,#$D6 ; get register pointers
- LD R10,R11
-
- CP R11,#8
- JR LT,LP2
- INC R9
- SUB R10,#8
- LP2
- CALL READ_DIR_REG
- LDC R9,@RR6
- AND R9,#$F8
- ; get old value
- ADD R9,R10
- PUSH R9 ; save register
- CALL READ_DIR_REG
-
- LDC R4,@RR6
- CALL OUTHEX
-
- LD R4,#'+'
- CALL OUTCHR
- CALL SEND_ETX
-
- CALL GETLINE
- POP R13 ; register number
-
- REG_TOKEN1
- CP R4,#'Q' ; do we quit
- JP EQ,ENDWEDIT
- CP R4,#'q'
- JP EQ,ENDWEDIT
-
- CP R4,#ASCIIUP
- JR NZ,REG_DOT1 ; ^ go back
- DEC R11
- CP R11,#0
- JP GE,LOOP
- LD R11,#$f ; wrap around
- JP LOOP
-
- REG_DOT1
- CP R4,#'.'
- JP EQ,LOOP ; same reg again
-
- CP R4,#ASCIICR
- JR EQ,MORE_REG1
-
- NEW_REG_VALUE
- ; R13 should have register number
- PUSH R11
- CALL CON_BYTE ; convert byte
- ; R11 = byte
- LD R9,R13 ; R9 = register
- CALL WRITE_DIR_REG
- POP R11
-
- CALL FINDNEXT
- JR NZ,REG_TOKEN1
-
- MORE_REG1
- INC R11 ; next register
- CP R11,#16
- JP LT,LOOP
- LD R11,#0
- JP LOOP
-
- ENDWEDIT
- RET
-
-
- ; ----- Display the working register set ------------------
-
- DISP_WREGS
-
- ; Start by displaying the working register header, numbers are
- ; in decimal
-
- LD R0,#0 ; counter
- DISP_HDR
- LD R4,#'R' ; Put a 'R'
- CALL OUTCHR ; in front of each #
-
- ; print tens digit
-
- LD R1,R0 ; save reg number
- CP R0,#9 ; is R0 > 9 ?
- JR GT,GT_9 ; yes
- LD R4,#'0' ; no, print '0'
- CALL OUTCHR
- JR DIGIT_2
-
- GT_9
- LD R4,#'1' ; print '1'
- CALL OUTCHR
- SUB R1,#10 ; R1 has ones digit
-
- DIGIT_2
- ADD R1,#$30 ; make it ascii
- LD R4,R1
- CALL OUTCHR
- CP R0,#$0F ; are we through?
- JR EQ,DISP_WORKS ; yes
- LD R4,#' ' ; no, print 2 spaces
- CALL OUTCHR ;
- CALL OUTCHR ;
- INC R0 ; inc counter
- JR DISP_HDR ; and repeat
-
- ; ------ Okay we finished with the header now move on ------------
- ; to displaying the working registers values
-
- DISP_WORKS
- CALL CRLF
- LD R9,USER_RP0 ; get USER's RP0
- and r9,#$F8 ; Mask off don't care bits
- PUSH R9 ; save RP0
- CALL DISP_REG ; Display the RP0 register set
-
- GET_RP1
- LD R9,USER_RP1 ; get USER_RP1
- AND R9,#$F8 ; mask off don't cares
- PUSH R9 ; save RP1
- CALL DISP_REG ; Display the RP1 register set
-
- ; ------- Now print the reister pointer values themselves ----------
-
- POP R11 ; Get the RP1
- POP R10 ; and RP0 values off of stack
- CALL CRLF
- LD R4, #'R'
- CALL OUTCHR
- LD R4, #'P'
- CALL OUTCHR
- LD R4, #'0'
- CALL OUTCHR
- LD R4, #'='
- CALL OUTCHR
- LD R4,R10 ; print the RP0 value
- CALL OUTHEX
- LD R4, #' '
- CALL OUTCHR
-
- LD R4, #'R'
- CALL OUTCHR
- LD R4, #'P'
- CALL OUTCHR
- LD R4, #'1'
- CALL OUTCHR
- LD R4, #'='
- CALL OUTCHR
- LD R4,R11 ; print the RP1 value
- CALL OUTHEX
- LD R4, #' '
- CALL OUTCHR
-
- LD R4, #'S'
- CALL OUTCHR
- LD R4, #'P'
- CALL OUTCHR
- LD R4, #'='
- CALL OUTCHR
- ldw rr10,USER_SP ; Print SP
- call OUTADDR
-
- DISP_DONE
- CALL CRLF
- CLR ERR_CODE
- RET ;
-
-
-
- ; ------ Display eight register set ------------------------
- ;
- ; Enter: R9 points to 8 register set
-
- DISP_REG
- LD R10, R9 ; get base register pointer
- ADD R10, #7 ; set end pointer for displaying 8 registers
-
- SYS_LOOP1
- LD R4,#ASCIISP ; 1 leading ' '
- CALL OUTCHR ; for rCx regs.
- CALL READ_DIR_REG ; read S8 reg. @R9
- ; RR6 now points to result register
- LDC R4,@RR6 ; save the value
- CALL OUTDAT
- LD R4,#ASCIISP ; 1 trailing ' '
- CALL OUTCHR ; for rCx regs.
-
- CP R9,R10 ; are we through
- JR EQ,SYS_DONE1
- INC R9 ; next register
- JR SYS_LOOP1
- SYS_DONE1
- RET
-
-
-
- EXTENSION
- ;************************************************************
- ;*
- ;* Echo command: E -O|1|0
- ;*
- ;* Options have the following meanings:
- ;*
- ;* O Toggle the "ECHO ON/ECHO OFF" mode.
- ;* 1 Turn echo on.
- ;* 0 Turn echo off.
- ;*
- ;*
- ;**************************************************************;
- CALL FINDOPT ; look for the option
- CP R10,#'o' ; is it an 'o'
- JR NE,CHECK_0 ; no
-
- ; toggle the echo mode
- CP ECHO_MODE,#ECHO_ON ; are we echoing?
- JR EQ,RESET_ECHO ; yes, so stop echo
- JR SET_ECHO ; no, start echo
-
- CHECK_0
- CP R10,#'0' ; '0' option ?
- JR NE,CHECK_1 ; no
- JR RESET_ECHO ; yes, turn echo off
-
- CHECK_1
- CP R10,#'1' ; '1' option ?
- JR NE,NOT_VALID ; no, illegal option
- JR SET_ECHO ; yes, turn echo o n
-
-
- SET_ECHO
- LD ECHO_MODE,#ECHO_ON ; no, start echoing
- JR DONE_EXT
-
- RESET_ECHO
- LD ECHO_MODE,#ECHO_OFF ; stop echoing
- JR DONE_EXT
-
- NOT_VALID
- LD ERR_CODE,#BAD_OPT
-
- DONE_EXT
- ; save echo status in monitor RAM
- LDW RR6,#ECHO_STAT ; point to echo save
- LD R4,ECHO_MODE
- LDC @RR6, R4 ; save the status
-
- RET
-
-
-
-
- VERIFY
- ;********************************************************
- ;*
- ;*
- ;* VERIFY Self test of S8 EM board
- ;*
- ;* tests:
- ;* (1) Performs checksum on Monitor
- ;*
- ;* (2) Performs simple test of Super8
- ;* registers & , User Internal, and Breakpoint RAM
- ;* by writing and reading 0 and 1 at each bit
- ;* location.
- ;*
- ;* (2) I-Code register interface by writing and
- ;* reading a SUPER8 register.
- ;*
- ;* (3) Emulation interface by the folowing steps:
- ;*
- ;* A. write a value to a SUPER8 register.
- ;*
- ;* B. put instructions into SUPER8 memory
- ;* to increment that register.
- ;*
- ;* c. set a breakpoint at the end of those
- ;* instructions.
- ;*
- ;* d. start emulation
- ;*
- ;* e. read the SUPER8 register after the break
- ;* occurs to verify execution.
- ;;*
- ;**********************************************************;
-
- CLR ERR_CODE
- CALL HOST_DELAY ; Wait for Host to catch up
- CALL SEND_STX
- LDW RR6,#TEST_MSG ; test message
- CALL OUTMSG
- CALL SEND_ETX
-
- CALL HOST_DELAY ; Wait for host to catch up
- CALL SEND_STX ; start message
- CALL MON_RAM_TEST ; test monitor RAM
- CP ERR_CODE,#$FF ; RAM test error ?
- JR EQ,TEST_ICODE ; yes
-
- LDW RR6,#RAM_OK_STR ; print RAM_OK message
- CALL OUTMSG
- CALL SEND_ETX ; end message
-
- CALL HOST_DELAY ; Wait for host to catch up
-
- TEST_ICODE
- CLR ERR_CODE
- RET
-
-
-
- MON_RAM_TEST
- ;********************************************************
- ;*
- ;* MON_RAM_TEST Test monitor RAM with 1's and 0's
- ;* to all locations.
- ;*
- ;* Performs a non-destructive read/write test
- ;*********************************************************;
-
- push r3
- push r4
- push r5
- push r12
- push r13
-
- ; First check if we have a 8K or 32K RAM out there
-
- ld r4,#$AA ; Load test pattern
- ld r12,#$80 ; Point to
- ld r13,#$00 ; test location
- ldc r3,@rr12 ; Save byte thats there
- ldc @rr12,r4 ; Write test pattern to RAM
- ldc r5,@rr12 ; Read back test pattern
- ldc @rr12,r3 ; Restore byte that was there
- cp r4,r5 ; Compare value read with test pattern
- jr ne,RAM_8K ; If not equal must be 8K RAM
-
- ; Print test message
-
- ld r6,#^HB RAM_MESS1
- ld r7,#^LB RAM_MESS1
- call OUTMSG
-
- ; Write a 1 to all locations for 32K RAM
-
- LD R12,#$80 ; high byte of start address
- LD R14,#$F0 ; high byte of end address
- LD R15,#$FF ; write all 1's
- CALL MEM_WRITE_READ
-
- ; Now write a 0 to all locations for 32K RAM
-
- LD R12,#$80 ; high byte of start address
- LD R14,#$F0 ; high byte of end address
- LD R15,#$00 ; write all 0's
- CALL MEM_WRITE_READ
- jr RAM_EXIT
-
- ; Print test message
-
- RAM_8K: ldw rr6,#RAM_MESS2
- call OUTMSG
-
- ; Write a 1 to all locations for 8K RAM
-
- LD R12,#$E0 ; high byte of start address
- LD R14,#$F0 ; high byte of end address
- LD R15,#$FF ; write all 1's
- CALL MEM_WRITE_READ
-
- ; Now write a 0 to all locations for 8K RAM
-
- LD R12,#$E0 ; high byte of start address
- LD R14,#$F0 ; high byte of end address
- LD R15,#$00 ; write all 0's
- CALL MEM_WRITE_READ
-
-
- RAM_EXIT:
- pop r13
- pop r12
- pop r5
- pop r4
- pop r3
- RET
-
-
- MEM_WRITE_READ
- ;*************************************************
- ;*
- ;* Write a value to memory on the SUPER8 EM
- ;* board and read it back.
- ;* If error, print out message. Repeat for
- ;* specified range of memory.
- ;*
- ;* input: R12 -- hi byte of starting address
- ;* R14 -- hi byte of end address + 1
- ;* R15 -- data to be written and read
- ;*
- ;* Performs a non-destructive read/write test
- ;*************************************************;
- PUSH R3 ; save used registers
- PUSH R4
- PUSH R5
- PUSH R6
- PUSH R7
- PUSH R10
- PUSH R11
- PUSH R15
-
- CLR R13
- ; main write - read loop
- WRITE_READ_LOOP
- LDC R3,@RR12 ; save value at location
- ; to be tested
- LDC @RR12,R15 ; write data in R15
- LDC R5,@RR12 ; read it back into R5
-
- LDC @RR12,R3 ; restore original value
-
- CP D_MEMFLAG,#0 ; is it BREAK memory?
- JR EQ,NOT_BREAK ; no
- AND R5,#$01 ; yes, only LSB is valid
-
- NOT_BREAK
- CP R5,R15 ; are values and equal ?
- JR NE,NOT_EQUAL
-
- NEXT_LOC
- INCW RR12 ; inc. mem pointer
- CP R12,R14 ; are we through?
- JR ULT,WRITE_READ_LOOP ; no
- JR DONE_WRITE_READ ; yes
-
- NOT_EQUAL
- PUSH R5 ; save data values
- PUSH R15
-
- LD R4,#$10
- CALL DELAY
-
- LDW RR6,#RAM_ERROR ; 'RAM FAILURE AT '
- CALL OUTSTR
-
- LD R4,#$10
- CALL DELAY
-
- LD R10,R12 ; put bad address in
- LD R11,R13 ; RR10 for OUTADDR
- CALL OUTADDR ; <ADDRESS>
-
- LD R4,#$10
- CALL DELAY
-
- LD R6,#^HB WROTE_STR ; ' WROTE '
- LD R7,#^LB WROTE_STR
- CALL OUTSTR
-
- LD R4,#$10
- CALL DELAY
-
- POP R15 ; <write value>
- LD R4,R15
- CALL OUTDAT
-
- LD R4,#$10
- CALL DELAY
-
- LD R6,#^HB READ_STR ; ' READ '
- LD R7,#^LB READ_STR
- CALL OUTSTR
-
- LD R4,#$10
- CALL DELAY
-
- POP R5
- LD R4,R5 ; <read value>
- CALL OUTDAT
-
- LD R4,#$10
- CALL DELAY
-
- LD ERR_CODE,#$FF ; set error flag
-
- CALL CRLF
- ; exit after first error
-
- DONE_WRITE_READ
- POP R15 ; restore used registers
- POP R11
- POP R10
- POP R7
- POP R6
- POP R5
- POP R4
- POP R3
- RET
-
-
- QUIT
- ;****************************************************
- ;*
- ;* QUIT Send message to host to quit to MSDOS.
- ;*
- ;* SYNTAX: Q
- ;*
- ;****************************************************;
-
- CP ECHO_MODE,#ECHO_ON ; are we echoing?
- JR NE,SEND_QUIT ; no, send quit msg
-
- ; we are echoing, don't send message and flag error
- LD ERR_CODE,#BAD_CMD ; bad command
- RET
-
- ; send quit message: "<STX> Q <ETX>"
- SEND_QUIT
- CALL SEND_STX ; STX
- LD R4,#'Q'
- CALL OUTCHR ; 'Q'
- CALL SEND_ETX ; ETX
- RET
-
-
- TEST_MSG .ascii 'Executing SELF TEST...\r'
- RAM_MESS1 .ascii 'Testing 32K RAM at location 8000 - FFFF\r'
- RAM_MESS2 .ascii 'Testing 8K RAM at location E000 - FFFF\r'
- RAM_ERROR .ascii 'RAM Failure at \r'
- WROTE_STR .ascii ' wrote \r'
- READ_STR .ascii ' read \r'
- RAM_OK_STR .ascii 'RAM test OK\r'
-
-
- ; mnemonic PC and register header for first row of system regs
- SYS1_H_REG .ascii 'PC P0 P1 P2 P3 P4 FLAGS RP0\r'
-
-
- ; register numbers for first row of system regs
- SYS1_N_REG .ascii ' rD0 rD1 rD2 rD3 rD4 rD5 rD6\r'
-
-
- ; mnemonic register header for second row of system regs
- SYS2_H_REG .ascii 'RP1 SPH SPL IPH IPL IRQ IMR SYM\r'
-
-
- ; register numbers for second row of system regs
- SYS2_N_REG .ascii 'rD7 rD8 rD9 rDA rDB rDC rDD rDE\r'
-
-
- ; mnemonic register header for first row of control/mode regs
- CTL1_H_REG .ascii 'C0CT C1CT C0CH C0CL C1CH C1CL UTC URC UIE UIO P0M\r'
-
- ; register numbers for first row of control/mode regs
- CTL1_N_REG .ascii 'rE0/0 rE1/0 rE2/0 rE3/0 rE4/0 rE5/0 rEB/0 rEC/0 rED/0 rEF/0 rF0/0\r'
-
- ; mnemonic register header for second row of control/mode regs
- CTL2_H_REG .ascii 'P4D P4OD P2AIP P2BIP EMT IPR C0M C1M C0CTH C0CTL\r'
-
- ; register numbers for second row of control/mode regs
- CTL2_N_REG .ascii 'rF6/0 rF7/0 rFC/0 rFD/0 rFE/0 rFF/0 rE0/1 rE1/1 rE2/1 rE3/1\r'
-
- ; mnemonic register header for third row of control/mode regs
- CTL3_H_REG .ascii 'C1TCH C1TCL DCH DCL UBGH UBGL UMA UMB WUMCH WUMSK\r'
-
- ; register numbers for third row of control/mode regs
- CTL3_N_REG .ascii 'rE4/1 rE5/1 rF0/1 rF1/1 rF8/1 rF9/1 rFA/1 rFB/1 rFE/1 rFF/1\r'
-
- ; register numbers for fourth row of control/mode regs
- CTL4_N_REG .ascii 'rC0 rC1 rC2 rC3 rC4 rC5 rC6 rC7 rC8 rC9 rCA rCB rCC rCD rCE rCF\r'
-
-
- ; map of bank 0 control/mode registers:
- ; read/write(RW), write only(WO), read only(RO), unimplemented(UI)
- BANK_0_TAB:
-
- ; E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- db RW, RW, RW, RW, RW, RW, UI, UI, UI, UI, UI, RW, RW, RW, UI, RW
-
- ; F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
- db RW, WO, UI, UI, WO, WO, RW, RW, WO, WO, WO, WO, RW, RW, RW, RW
-
-
- ; map of bank 1 control/mode registers:
- ; read/write(RW), write only(WO), read only(RO), unimplemented(UI)
- BANK_1_TAB:
-
- ; E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- db RW, RW, RW, RW, RW, RW, UI, UI, UI, UI, UI, UI, UI, UI, UI, UI
-
- ; F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
- db RW, RW, UI, UI, UI, UI, UI, UI, RW, RW, RW, RW, UI, UI, RW, RW
-
-
- ; general register display header
- GEN_REG_H .ascii ' x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF\r'
-
-
- ;************************************************
- ;*
- ;* load.s : Download and Upload functions
- ;*
- ;************************************************;
- ;*
- ;* Constants and register usage used by
- ;* all or some of the software modules.
- ;*
- ;******************************************************;
- ; register allocation
-
-
-
- LOAD
- ;**************************************************
- ;*
- ;* LOAD Download a program
- ;*
- ;* syntax L [-E] <filename>
- ;*
- ;****************************************************;
- LD SIO_MODE,#LOAD_MODE ; load input mode
-
- CALL FINDOPT ; look for an option
- CP R10,#0 ; an option?
- JR EQ,LOADUP ; no
-
- CP R10,'e' ; yes, is it an 'e'?
- JR EQ,E_OPTION ; yes
- LD ERR_CODE,#BAD_OPT ; no, bad option
- LD SIO_MODE,#NORMAL_MODE
- RET
-
- E_OPTION:
- LD SIO_MODE,#EXT_MODE
-
-
- LOADUP:
- OR SIO_MODE,#LOAD_MODE
-
- CALL LODCMD ; do the load
-
- LD SIO_MODE,#NORMAL_MODE
- RET
-
-
-
- UPLOAD
- ;***************************************************
- ;*
- ;* UPLOAD Upload a program image
- ;*
- ;* syntax U <FILENAME> <ADDRESS> <N>
- ;*
- ;*****************************************************;
- LD SIO_MODE,#LOAD_MODE
-
- CALL SEND ; send the records
-
- LD SIO_MODE,#NORMAL_MODE
- RET
-
-
-
- LODCMD
- ;**************************************************
- ;*
- ;* load command expects records of data (ascii chars)
- ;* in the following tek hhex format:
- ;* <address(4)> <count(2)> <cksum1(2)> <data(2)> <data(2)>
- ;* <data(2)> ... <data(2)> <cksum2(2)>
- ;*
- ;* the two checksum values are verified before the data
- ;* is stored in memory (specified by <address>)
- ;* <cksum1> is the checksum for <address> & <count>
- ;* <cksum2> is the checksum for the data portion
- ;*
- ;* if the record is recieved with <count> = 0, this is
- ;* the end of the load data
- ;*
- ;* after each data record is recieved, either and acknowledge
- ;* (ascii 0 followed by cr) or a non-acknowledge (ascii 7
- ;* followed by a cr) will be sent.
- ;*
- ;* if the recieved record begins with //, the character string
- ;* will be sent instead to the terminal and the command aborted.
- ;*
- ;*************************************************************;
-
-
- ; send command to host to download file
- GOTFILE:
- OR CFLAG,#LOAD_SEND ; set bit for load
- ;***** JR NZ,NXXTR ***** all ok
- ;***** RET ***** ret z
-
- NXXTR:
- CALL LODREC ; fetch record in CONIBF
- LD R6,#^HB CONIBF ;
- CLR R7 ; pointing to CONIBF with RR6
- LDC R0,@RR6 ; check for error (//)
- CP R0,#'/' ;
- JR NZ,RECOK ; the record is ok
-
- OR CFLAG,#LOADABORT ; send error message
- RET ; and forget characters
-
- RECOK:
- CALL REKCKS ; verify checksums
- JR NC,LODOK ; good checksums
-
- CALL BADCKS ; bad checksums send non-ack
- JR NXXTR ; try again
-
- ; check if this is the last record (count = 0)
-
- LODOK:
- CP R5,#$00 ; data count in R5
- JR NZ,STRED ; not 0, put data into memory
- CALL GODCKS ; send acknowledge
- RET ; back to main
-
- STRED:
- CALL GODCKS ; send acknowledge
- CALL STREC ; store data in memory
- JR NXXTR ; get next record
-
-
-
-
- SEND
- ;***************************************************************
- ;*
- ;* send transfers data in memory to host system.
- ;* all data is converted to ascii characters before
- ;* they are sent. maximum is 30 bytes of data in one
- ;* record in the following format:
- ;*
- ;* /<address> <count> <cksum1> <data> <data> ... <data>
- ;* <cksum2> cr
- ;* where
- ;* <address> - the address of the first byte of data
- ;* <count> - # bytes of data in that record
- ;* <cksum1> - cksum of <address> & <count>
- ;* <data> - data byte of specified memory
- ;* <cksum2> - checksum of the data bytes
- ;*
- ;* after all data is sent, a record in the following format will
- ;* be sent at the end:
- ;*
- ;* /<entry address> 00 <cksum> cr
- ;* where cksum is the checksum of <entry address>
- ;*
- ;* send command will retry 10 times if a non-acknowledge is received.
- ;* then it will send //error cr to abort command.
- ;*
- ;*
- ;***************************************************************;
-
- ; reset host input buffer pointer, insure filename exists
-
- CALL CKFNAM
- JR Z,SENDER ; no parameter, filename
-
- PUSH INPTR ; save pointer at filename
-
- CALL GETADDR ; get start address
- JR C,SENDER_POP ; error, send message
- LD R14,R10 ; save start address
- LD R15,R11 ; in RR12
-
- CALL GETADDR ; get length
- JR C,SENDER_POP ; error, send message
- LD R8,R10 ; save length
- LD R9,R11 ; in RR8
-
- POP INPTR ; pointer at filename
-
- AND CFLAG,#^C LOAD_SEND ; for send process
-
- JR OPOK
-
- ; send command to host upload data
- ;**** JR NZ,OPOK **** send was loaded
- SENDER:
- RET ; not loaded
- SENDER_POP:
- POP INPTR ; syntax error,must
- RET ; pop ptr to filename
-
-
- OPOK:
- NXTR:
- LD RETRY,#10 ; retry 10 times max
- CP R8,#$00 ; see if length < 30
- JR NE,SET30 ; not if R8 > 0
- CP R9,#30 ; check lower byte
- JR NC,SET30 ; send 30
-
- LD R0,R9 ; use R9 for count
- CLR R9 ; clear the count to 0
- JR COTT ;
- SET30:
- LD R0,#30 ; send 30 bytes each time
- RCF ; clear carry for 2 reg sub
- SUB R9,#30 ; RR8 has length,must sub 30
- SBC R8,#$00 ; only subtract carry from R8
-
- COTT:
- LD R11,R0 ; save count for possible resend
-
- ; format address, checksum & data in record &
- ; send to host ;
- RESEND:
-
- ; delay so that host can set up
- PUSH R3
- PUSH R4
- LD R3,#$04
-
- REC_DELAY:
- LD R4,#$FF
- CALL DELAY
- DJNZ R3,REC_DELAY
-
- POP R4
- POP R3
-
- CALL RECSND ; send data record to host
- JR Z,LREC ; was last record
-
- CALL WATACK ;
- JR NZ,RECE79 ; got a 7 or 9 from host
- JR NXTR ; z means ok, sendnext record
-
- RECE79:
- JR C,ABTS ; '9' means abort
-
- ; recieve non-acknowledge, resend same record
-
- SUB R15,R11 ; set back address
- SBC R14,#$00 ;
- LD R0,R11 ; get back count
- DEC RETRY ; 1 of 10 chances
- JR Z,SNDABT ; that was last chance
-
- JR RESEND ;
-
- ; send last record /<entry addr> 00 <cksum> cr
-
- LREC:
- CALL LASREC ; send last record
-
- CALL WATACK ; wait for acknowledge
- JR NZ,C2 ; not done
- RET ; done
- C2: JR NC,RESD ; nz,nc recieve 7,resend
- ABTS: OR CFLAG,#ABSEND ; 9 is file error
- RET ;
-
- ; got a '7', so send same data if not the 10th time
-
- RESD: DEC RETRY ; try counter
- JR NZ,RESEND ;
-
- SNDABT:
- CALL SNDERR ; format an error record for host
- OR CFLAG,#ABSEND ; abort
- RET ; with an error message
-
-
-
-
- RECSND
- ;*********************************************************
- ;*
- ;* recsnd formats address, count, checksums & data in
- ;* tektronix format. it sends the data to the host
- ;* system or the terminal.
- ;* if the count = 0, just store '/' in buffer & don't
- ;* format the data
- ;*
- ;* input: R0 has count, RR12 has start address
- ;* output: RR14 increased by count (R0)
- ;* return z for last record
- ;* return nz when record is sent and
- ;* ready for acknowledge.
- ;*
- ;************************************************************;
- LD R6,#^HB CONOBF ; pt to output buffer
- CLR R7 ; with RR0
- LD R4,#'/' ; first character
- LDC @RR6,R4 ;
- INCW RR6 ;
- CP R0,#$00 ; any data ?
- JR NE,SENDDATA ; yes
- RET ; no data
- SENDDATA:
- CLR R3 ; checksum accumualtor
- LD R5,R14 ; format address
- CALL PUT1 ; and put into buffer
- LD R5,R15 ;
- CALL PUT1 ;
- LD R5,R0 ; and count
- CALL PUT1 ;
- LD R5,R3 ; then checksum1
- CALL PUT1 ;
- ; format <data> <data> ... <data> <checksum2>
- CLR R3 ; clear checksum accumulator
- MDATA:
- PUSH R8
- PUSH R9
- PUSH R14 ; hi addr
- PUSH R15 ; lo addr
- LD R8,R14
- LD R9,R15
- CALL GETMEM ; lde R5,@RR14
- LD R5,R15 ; data
- POP R15 ;
- POP R14 ;
- POP R9 ;
- POP R8 ;
- CALL PUT1 ; add to checksum
- INCW RR14 ; next data byte
- DJNZ R0,MDATA ; until all data converted
-
- LD R5,R3 ; and checksum
- CALL PUT1 ;
-
- LD R4,#ASCIILF ; end with a <LF>
- LDC @RR6,R4 ;
- INC R7 ; send <LF> also
- LD OUTLEN,R7 ; into outlen
- CALL OTMSG ; to send to host
- INC R6 ; reset z flag
-
- RET ;
-
-
-
- LASREC
- ;*******************************************************
- ;* lasrec formats entry address with 0 count and
- ;* checksum in tektronix format for the last record
- ;* and sends it to the host
- ;*
- ;* input RR10 is entry address
- ;*
- ;*******************************************************;
- CLR R3 ; clear accumulator
-
- LD R5,#$00 ; address
- CALL PUT1 ; put into buffer
- LD R5,#$0C ; low byte
- CALL PUT1 ;
-
- CLR R5 ; 0 byte count
- CALL PUT1 ;
- LD R5,R3 ; the checksum
- CALL PUT1 ;
- LD R4,#ASCIILF ; read ascii on host side
- LDC @RR6,R4 ;
- INC R7 ; send <LF> also
- LD OUTLEN,R7 ; into outlen
- CALL OTMSG ; output to host
- RET
-
-
-
-
- PUT1
- ;*******************************************************
- ;* add each nibble of R5 to the checksum accumulator R3
- ;* convert contents of R5 to 2 ascii characters
- ;* enter characters into buffer pointed to by RR6
- ;* RR6 gets incremented in 'nibble'
- ;********************************************************;
- LD R4,R5 ; do high byte first
- SWAP R4 ;
- AND R4,#$0F ; isolate nibble
- ADD R3,R4 ; checksum
- CALL NOOBLE ; puts it into buffer
- ; increments pointer ;
-
- LD R4,R5 ; low nibble
- AND R4,#$0F ; isolate nibble
- ADD R3,R4 ; checksum
- CALL NOOBLE ; into buffer
- RET ;
-
-
-
- NOOBLE
- ;***********************************************************
- ;*
- ;* convert hex to ASCII and put into memory @RR6
- ;*
- ;* input: R4 has hex value in lower nibble
- ;*
- ;************************************************************;
- and R4,#$0F ; isolate lower nibble
- add r4,#$90
- da r4
- adc r4,#$40
- da r4
- LDC @RR6,R4 ; put into buffer
- inc r7 ; point to next location
- ret
-
-
- CKFNAM
- ;**************************************************************
- ;*
- ;* ckfname resets two pointers of the ram buffer before
- ;* starting the upload/download procedure. also checks
- ;* that the filename is included in the command.
- ;*
- ;* z flag on => no filename
- ;* z flag off => filename present
- ;*
- ;**************************************************************;
-
- CLR HOSTGET ; these are offsets
- CLR HOSTPUT ; not pointers
- CALL FINDNEXT ; get the filename
- JR NZ,GOTIT ; filename present
- OR CFLAG,#$02 ; missing filename
- GOTIT:
- RET ; there is a filename
-
-
-
-
- LODREC
- ;************************************************************
- ;*
- ;* lodrec reads in an input line into conibf from the host
- ;* and starts storing data once a '/' is recieved.
- ;* the input line is terminated by a carriage return.
- ;* it will read in a maximum of 80 characters (ascii)
- ;* and ignore the rest until a carriage return is recieved.
- ;* all control characters are skipped ( <20h)
- ;*
- ;* output: data in conibf
- ;***********************************************************;
- CALL HOSTINP ; get the character
- CP R4,#'/' ; wait for '/'
- JR NZ,LODREC ;
-
- LD R2,#^HB CONIBF ; start at beginning of conibf
- CLR R3 ; use RR6
- LD R8,#80 ; maximum character count
-
- ; start storing characters , ignore control characters
- ; also check for carriage return for end of record ;
- LODRC0:
- CALL HOSTINP ; get next character
- LDC @RR2,R4 ; put into conibf
- CP R4,#ASCIICR ; end of record?
- JR EQ,DONE_LODREC
- CP R4,#ASCIILF ; end of record?
- JR EQ,DONE_LODREC
-
- CKCT:
- CP R4,#ASCIISP ; ignore control characters
- JR C,LODRC0 ; was a control char
-
- INCW RR2 ; increment pointer
- DJNZ R8,LODRC0 ; next character
-
- ; have received 80 characters, skip over all characters
- ; until carriage return ;
- LODRC2:
- CALL HOSTINP ; ignore all but <CR>
- CP R4,#ASCIICR ;
- JR EQ,TERM_REC
- CP R4,#ASCIILF ; and <LF>
- JR EQ,TERM_REC
-
- JR LODRC2 ;
-
- TERM_REC:
- LD R3,#80 ; put terminator here
- LDC @RR2,R4 ; get <CR> into buffer
- ; returns z flag on
-
- DONE_LODREC:
- RET
-
-
-
-
- REKCKS
- ;************************************************************
- ;*
- ;* rekcks verifies two checksums values in a record
- ;* stored in conibf. all ascii characters in conibf are
- ;* converted to 4-bit hex value to obtain checksum
- ;* which is the sum of all these 4 bit hex values.
- ;*
- ;* the format of the record is as follows:
- ;* <address(4)> <count(2)> <cksum1(2)> <data(2)>
- ;* ... <data(2)> <cksum2(2)> <CR>
- ;*
- ;* input: record in conibf
- ;* RR6 pointing to conibf
- ;*
- ;* output: R5 has count in byte value
- ;*
- ;* return c if checksum bad
- ;* return c if non-ascii found in conibf
- ;* return nc if ok
- ;*
- ;*************************************************************;
- LD R5,#$03 ; chksum is for 3 pairs
- CALL CHKCKS ; verify first checksum
- JR C,REKCKS_END ; bad checksum
-
- CP R5,#$00 ; this is the count
- JR Z,REKCKS_END ; no data if count 0
-
- PUSH R5 ; save count
- CALL CHKCKS ; verify second check sum
-
- POP R5 ; get count back
- REKCKS_END:
- RET ; all exits here
-
-
-
-
- CHKCKS
- ;************************************************************
- ;*
- ;* chkcks verifies the checksum in the record. converts
- ;* each ascii character in the record to the hex value
- ;* and accumulates their values to obtain the checksum.
- ;* the checksum is then compared with the check sum in the
- ;* record following the character string. all characters
- ;* including the checksum are ascii characters
- ;*
- ;* input: RR6 pointer to the ascii string
- ;* R5 # of char pairs in this chksum calculation
- ;*
- ;* output: R5 count value of the record
- ;* R2 calculated checksum
- ;* R4 checksum in the record
- ;*
- ;* return c if cksum bad
- ;* return c if found non-ascii character
- ;* return nc if chksum is correct
- ;*
- ;***********************************************************;
- ; init cksum accumulator (R2), convert the
- ; next pair of characters to hex and sum their
- ;hex values. ;
- CLR R2 ; checksum accumulator
- CHKSM2:
- CALL LODBYL ; convert next two characters
- ; to hex & add to chksm accum
- JR C,CHKCKS_END ; bad ascii
- DJNZ R5,CHKSM2 ; R3 is number of pairs
-
- ; save 8 bit hex value of last two characters
- ;(count of the data in the record). save calculated
- ;cksum then convert next two chars to get chksm in
- ;the record and compare the two chksum ;
-
- LD R5,R4 ; get count into R5
- PUSH R5 ; save count
- PUSH R2 ; and checksum
-
- CALL LODBYL ; convert next two characters
-
- POP R2 ; get record checksum in R4
- POP R5 ;
- JR C,CHKCKS_END ; bad ascii
-
- CP R4,R2 ; return nc if match
- JR Z,CHKCKS_END ;
- SCF ; return carry if no match
- CHKCKS_END:
- RET ; common exit
-
-
-
-
- LODBYL
- ;*********************************************************
- ;*
- ;* convert two ascii characters to two 4-bit hex
- ;* and add the two hex values to an accumulator
- ;*
- ;* input: RR6 points to first ascii character
- ;* R2 is the accumulator
- ;*
- ;* output: RR6 updated
- ;* R2 updated
- ;* R4 8 bit hex result of conversion
- ;*
- ;* return c if any characters non-ascii
- ;* return nc if ok
- ;*
- ;********************************************************;
- CALL HEXDCD ; convert char ptd by RR6
- JR C,LODBYL_END ; bad ascii
-
- ADD R2,R4 ; add to accumulator
- LD R1,R4 ; save value in R1
- SWAP R1 ; put in upper nibble
-
- CALL HEXDCD ; convert next 4 bits
- JR C,LODBYL_END ; common exit
-
- ADD R2,R4 ; add to accumulator
- OR R4,R1 ; 8 bit value in R4
- RCF ; reset carry
- LODBYL_END:
- RET ; common exit
-
-
-
-
- HEXDCD
- ;********************************************************
- ;*
- ;* convert ascii character pointed to by RR6 to
- ;* the 4 bit hex value. increment RR6 by one.
- ;*
- ;* input: RR6 pointer to ascii character
- ;*
- ;* output: RR6 advanced by one
- ;* R4 4-bit value of ascii char
- ;*
- ;* return c if character is non-ascii
- ;* return nc if ok
- ;*
- ;******************************************************;
-
- LDC R4,@RR6 ; get the character
- INCW RR6 ;
- JP CONVERT ; convert to hex
-
-
-
-
- STREC
- ;**********************************************************
- ;*
- ;* strec unpacks data in record & stores them into
- ;* memory location specified by address in record
- ;*
- ;* input: record in conibf
- ;* R5 # of bytes of data in record
- ;*
- ;************************************************************;
-
- LD R8,R5 ; use R8 to count down data
-
- ; convert <address> & <count> to hex value.
- ;store byte data in memory. the number of bytes
- ;is specified by <count> ;
- CALL RECADR ; calculate record address
- LD R7,#$08 ; skip count and checksum
-
- LODFR3:
- CALL LODBYL ; convert next two char
- PUSH R4 ;
- PUSH R8 ;
- PUSH R9 ;
- PUSH R14 ;
- PUSH R15 ;
-
- LD R8,R14 ; save address
- LD R9,R15
- LD R15,R4 ; save data
-
- TM SIO_MODE,#EXT_MODE ; extension load?
- JR Z,NO_EXT ; no
- CALL PUTEXT ; yes, store it
- JR CLEAN_UP
-
- NO_EXT:
- CALL PUTMEM ; lde @RR8,R15
-
- CLEAN_UP:
- POP R15 ;
- POP R14 ;
- POP R9 ;
- POP R8 ;
- POP R4 ;
- INCW RR14 ; increment memory pointer
- DJNZ R8,LODFR3 ; next byte
- RET ; done
-
-
-
- RECADR
- ;***********************************************************
- ;*
- ;* convert the starting address in load record to
- ;* the hex value and put into RR0
- ;*
- ;***********************************************************;
- LD R6,#^HB CONIBF ; point to begin of rec
- CLR R7 ;
- CALL LODBYL ; get first byte of address
- LD R14,R4 ;
- CALL LODBYL ; get lo byte of address
- LD R15,R4 ;
- RET ; got it
-
-
-
-
- BADCKS
- ;************************************************************
- ;*
- ;* badcks sends non-acknowledge (ascii 7 (37h) & <CR> )
- ;* for receiving a non-ascii character or if the checksum
- ;* is incorrect.
- ;*
- ;* godcks sends an acknowledge (ascii 0 (30h) & <CR> ) for
- ;* valid record of data
- ;*
- ;*************************************************************;
- LD R4,#'7' ; output to host
- JR MSEND ;
-
- GODCKS:
- LD R4,#'0' ; output to host
- MSEND:
-
- ; delay so that host has time to set up
- PUSH R4
- LD R4,#$80
- CALL DELAY
- POP R4
-
- CALL OUTCHR ; output
-
- ; delay so that host has time to set up
- LD R4,#$80
- CALL DELAY
-
- LD R4,#ASCIICR ; read ascii of rio
- CALL OUTCHR ;
- RET ;
-
-
-
- WATACK
- ;**************************************************************
- ;* expects either acknowledge (ascii 0) or non-acknowledge
- ;* (ascii 7) from serial line. ignore other characters
- ;*
- ;* good-ack from host returns z, nc
- ;* non-ack from host returns nz,nc
- ;* abort-ack from host returns nz,c
- ;*
- ;***************************************************************;
- CALL MCHAR ; get character
- CP R4,#'0' ; good ack?
- JR NZ,CK79 ; check for 7 or 9
- CALL SKIP_EOL ; skip to end of line
- RCF ; reset carry flag
- XOR R4,R4 ; set z flag
- JR END_ACK ; z,nc is good ack
- CK79:
- CP R4,#'7' ; check for non-ack
- JR NZ,CK9 ; no
- CALL SKIP_EOL ; skip to end of line
- INC R4 ; reset the z flag
- RCF ; reset the carry flag
- JR END_ACK ; nz,nc is non-ack
- CK9:
- CP R4,#'9' ; check for abort acknowledge
- JR Z,MATC ; yes
- CALL HOSTINP ; advance pointer to get next
- JR WATACK ; ignore character
- MATC:
- CALL SKIP_EOL ; skip to end of line
- INC R4 ; reset the z flag
- SCF ; set carry flag
-
- END_ACK:
- RET ; return nz,c for abort
-
-
-
- SNDERR
- ;***********************************************************
- ;*
- ;* formats an error record to send to host
- ;*
- ;* error record is '//<CR>'
- ;*
- ;* this is an abort initiated by the 'send' command
- ;*
- ;* because of too many checksum errors detected by
- ;*
- ;* the host system on a single record
- ;*
- ;**********************************************************;
- LD R6,#^HB CONIBF ; point to record buffer
- CLR R7 ;
- LD R4,#'/' ; put two '/'s in the buffer
- LDC @RR6,R4 ;
- INCW RR6 ;
- LDC @RR6,R4 ;
- INCW RR6 ;
- LD R4,#ASCIICR ; and follow with a <CR>
- LDC @RR6,R4 ;
- INC R7 ; get count
- LD OUTLEN,R7 ; and send over serial
- JP OTMSG ; channel to host
-
-
-
- SKIP_EOL
- ;************************************************************
- ;*
- ;* skip over input line until <CR> is recieved from host.
- ;*
- ;*************************************************************;
- CALL HOSTINP ; input from the host
- CP R4,#ASCIICR ; until <CR>
- JR NE,SKIP_EOL ;
-
- RET
-
-
-
- HOSTINP
- ;************************************************************
- ;*
- ;* gets a character from the host input interrupt buffer.
- ;* if no character is in the buffer, it waits...
- ;*
- ;* hostput updated to point to next character
- ;* character returned in R4
- ;*
- ;*************************************************************;
- CALL MCHAR ;
- INC HOSTPUT ;
- RET ;
-
-
-
- MCHAR
- ;***********************************************************
- ;*
- ;* same as hostinp except don't update pointer
- ;*
- ;***********************************************************;
- CP HOSTGET,HOSTPUT ; got a character
- JR EQ,MCHAR ;
-
- PUSH R6 ;
- PUSH R7 ;
- LD R6,#^HB HOSTBUF ; get full pointer
- LD R7,HOSTPUT ;
- LDC R4,@RR6 ;
- POP R7 ;
- POP R6 ;
- RET ;
-
- ;********************************************************
- ;*
- ;* dasm.s : Super8 disassembler
- ;*
- ;* This version doctored for the META assembler
- ;*
- ;*********************************************************;
-
- ONE_BYTE: equ $00 ; one-byte inst.
- TWO_BYTES: equ $20 ; two-byte inst.
- THREE_BYTES: equ $40 ; three-byte inst.
- FOUR_BYTES: equ $60 ; four-byte inst.
- HI_BIT: equ $80 ; most sig. bit
- ONE_M: equ $00+$80 ; one-byte inst.
- TWO_M: equ $20+$80 ; two-byte inst.
- THREE_M: equ $40+$80 ; three-byte inst.
- FOUR_M: equ $60+$80 ; four-byte inst.
- COMMA: equ $2C ; ASCII comma
- VARY_MNE: equ $00 ; var. mnemonics glag
- AD_TYPE_0: equ $00 ; address mode types
- AD_TYPE_1: equ $01
- AD_TYPE_2: equ $02
- AD_TYPE_3: equ $03
- AD_TYPE_4: equ $04
- AD_TYPE_5: equ $05
- AD_TYPE_6: equ $06
- AD_TYPE_7: equ $07
- AD_TYPE_8: equ $08
- AD_TYPE_9: equ $09
- AD_TYPE_A: equ $0A
- AD_TYPE_B: equ $0B
- AD_TYPE_C: equ $0C
- AD_TYPE_D: equ $0D
- AD_TYPE_E: equ $0E
- AD_TYPE_F: equ $0F
- AD_TYPE_10: equ $10
- AD_TYPE_11: equ $11
- AD_TYPE_12: equ $12
- AD_TYPE_13: equ $13
- AD_TYPE_14: equ $14
- AD_TYPE_15: equ $15
- AD_TYPE_16: equ $16
- AD_TYPE_17: equ $17
- AD_TYPE_18: equ $18
- AD_TYPE_19: equ $19
- AD_TYPE_1A: equ $1A
- AD_TYPE_1B: equ $1B
- AD_TYPE_1C: equ $1C
-
-
- DIS_ASM
- ;**********************************************************
- ;*
- ;* ZAP disassemble SUPER8 instructions
- ;*
- ;* syntax Z <address> [<n>]
- ;*
- ;* defaults <n> = 1
- ;*
- ;* Disassemble <n> instructions starting at <address>
- ;* Maximum value for <n> = $FF
- ;*
- ;* input: AD_IN_HI,AD_IN_LO point to memory location to be
- ;* disassembled.
- ;* AD_OUT_HI,AD_OUT_LO point to output buffer
- ;*
- ;* output: The output buffer is filled with the disassembled
- ;* instruction.
- ;*
- ;**************************************************************;
-
- PUSH R0 ; save all regs
- PUSH R1 ; except R6,R7
- PUSH R2
- PUSH R3
- PUSH R4
- PUSH R5
- PUSH R8
- PUSH R9
- PUSH R10
- PUSH R11
- PUSH R12
- PUSH R13
- PUSH R14
- PUSH R15
-
-
- ; write output buffer with 70 spaces
-
- LD R10,#BUF_LGTH ; loop of 70
- LD R11,#' ' ; ASCII space
- LD R12,AD_OUT_HI ; output buffer
- LD R13,AD_OUT_LO ; address
- LP1A:
- LDC @RR12,R11 ; write one space
- INCW RR12 ; points to next
- DJNZ R10,LP1A ; loop 80. times
- LD R11,#$0D ; carrage return
- LDC @RR12,R11 ; output
-
- ; initialize output buffer pointer
- LD R2,AD_OUT_HI ; output buffer
- LD R3,AD_OUT_LO ; address
-
- ; initialize memory pointer
- LD R0,AD_IN_HI ; memory address
- LD R1,AD_IN_LO ;
-
- ; tab in 4 spaces before writing
- LD R15,#$04 ; tab 4 spaces
- CALL TAB_SP
-
- ; write address in output buffer
- LD R10,AD_IN_HI ; first hi addr
- CALL HEX_ASCII ; inti buffer
- LD R10,AD_IN_LO ; then lo addr
- CALL HEX_ASCII ; into buffer
- LD R15,#$04 ; tab 4 spaces
- CALL TAB_SP
-
- ; get opcode and write first byte in out buf
- CALL RD_MEM ; read first byte into R10
- INCW RR0 ; point to next
- LD R12,R10 ; save opcode
- LD BYTE_1,R10 ; save first byte
- CALL HEX_ASCII ; write out buffer
-
- ; find table entry that = hex mnemonic
- LD R4,#^HB OP_TAB ; get starting
- LD R5,#^LB OP_TAB ; addr of table
- LDC R10,@RR4 ; read first control
- AGN3:
- CP R12,#$00 ; there yet ?
- JR Z,DONE1 ; if zero yes
-
- AGN2: INCW RR4 ; find next
- LDC R10,@RR4 ; control byte
- TM R10,#$80 ; bit 7 set
- JR Z,AGN2 ; loop 2 till
- DEC R12 ; bit 7 set
- JR AGN3 ;test for zero
-
- DONE1:
- LD R8,R10 ; save control in R8
-
- ; get type of instruction from control byte
- LD R11,R8 ; save control
- AND R11,#$1F ;isolate least sig. 5 bits
- LD TYPE_,R11 ; save in type_
-
- ; test for quantity of bytes in instruction
- ; encoded as (n - 1) in bits 5 and 6 of control byte
- LD R9,R8 ; save size in R9
- AND R9,#FOUR_BYTES ;isolate bits 5,6
-
- CP R9,#ONE_BYTE ; test for one byte
- JR NZ, BY_2 ; no - at least two
-
- ; one byte instruction -- pad with spaces
- LD R15,#$12 ; tab 18. spaces
- CALL TAB_SP
- JR MNE ; ASCII mnemonic
-
- BY_2:
- INCW RR2 ; tab two spaces
- INCW RR2
- CALL RD_MEM ; read second byte
- INCW RR0 ; point to third
- LD BYTE_2,R10 ; save byte 2
- CALL HEX_ASCII ; write to buffer
-
- CP R9,#TWO_BYTES ; test for two bytes
- JR NZ, BY_3 ; no - at least three
-
- ; two byte instruction -- pad with spaces
- LD R15,#$0E ; tab 14. spaces
- CALL TAB_SP
- JR MNE ; ASCII mnemonic
-
- BY_3:
- INCW RR2 ; tab two spaces
- INCW RR2
- CALL RD_MEM ; read third byte
- INCW RR0 ; point to fourth
- LD BYTE_3,R10 ; save byte 3
- CALL HEX_ASCII ; write to buffer
-
- CP R9,#THREE_BYTES ; test for three bytes
- JR NZ, BY_4 ; no - four bytes
-
- ; three byte instruction -- pad with spaces
- LD R15,#$0A ; tab 10. spaces
- CALL TAB_SP
- JR MNE ; ASCII mnemonic
-
- BY_4:
- INCW RR2 ; tab two spaces
- INCW RR2
- CALL RD_MEM ; read fourth byte
- INCW RR0 ; point to next
- LD BYTE_4,R10 ; save byte 4
- CALL HEX_ASCII ; write to buffer
- LD R15,#$06 ; tab 6. spaces
- CALL TAB_SP
-
- ; output mnemonic to buffer
- MNE:
- INCW RR4 ; first ASCII
- LD R11,#$09 ; 6 ch +3 spaces
-
- LDC R10,@RR4 ; read letter
- LD R8,R10 ; check for varying
- TM R8,#$F0 ; mnemonics
- JR NZ,AGN4 ; not varying
- CALL CHK_MNE ; varies
-
- AGN4: ; letter of mnemonic
- LDC R10,@RR4 ; read letter
-
- TM R10,#$80 ; test next byte
- JR NZ,SK_SP ; for control byte
-
- LDC @RR2,R10 ; write letter
- INCW RR2 ; point next wr
- INCW RR4 ; point next rd
- DEC R11
- JR AGN4 ; do 2 to 6 times
-
- SK_SP:
- LD R15,R11 ; add remaining spaces
- CALL TAB_SP
-
-
- ; call routine 0 through 15 as function type
-
- CP TYPE_,#AD_TYPE_0
- JP EQ, DONE_DASM
- CP TYPE_,#AD_TYPE_1
- JP EQ, TYPE_01
- CP TYPE_,#AD_TYPE_2
- JP EQ, TYPE_02
- CP TYPE_,#AD_TYPE_3
- JP EQ, TYPE_03
- CP TYPE_,#AD_TYPE_4
- JP EQ,TYPE_04
- CP TYPE_,#AD_TYPE_5
- JP EQ,TYPE_05
- CP TYPE_,#AD_TYPE_6
- JP EQ,TYPE_06
- CP TYPE_,#AD_TYPE_7
- JP EQ,TYPE_07
- CP TYPE_,#AD_TYPE_8
- JP EQ,TYPE_08
- CP TYPE_,#AD_TYPE_9
- JP EQ,TYPE_09
- CP TYPE_,#AD_TYPE_A
- JP EQ,TYPE_0A
- CP TYPE_,#AD_TYPE_B
- JP EQ,TYPE_0B
- CP TYPE_,#AD_TYPE_C
- JP EQ,TYPE_0C
- CP TYPE_,#AD_TYPE_D
- JP EQ,TYPE_0D
- CP TYPE_,#AD_TYPE_E
- JP EQ,TYPE_0E
- CP TYPE_,#AD_TYPE_F
- JP EQ,TYPE_0F
-
- CP TYPE_,#AD_TYPE_10
- JP EQ,TYPE_10
- CP TYPE_,#AD_TYPE_11
- JP EQ,TYPE_11
- CP TYPE_,#AD_TYPE_12
- JP EQ,TYPE_12
- CP TYPE_,#AD_TYPE_13
- JP EQ,TYPE_13
- CP TYPE_,#AD_TYPE_14
- JP EQ,TYPE_14
- CP TYPE_,#AD_TYPE_15
- JP EQ,TYPE_15
- CP TYPE_,#AD_TYPE_16
- JP EQ,TYPE_16
- CP TYPE_,#AD_TYPE_17
- JP EQ,TYPE_17
- CP TYPE_,#AD_TYPE_18
- JP EQ,TYPE_18
- CP TYPE_,#AD_TYPE_19
- JP EQ,TYPE_19
- CP TYPE_,#AD_TYPE_1A
- JP EQ,TYPE_1A
- CP TYPE_,#AD_TYPE_1B
- JP EQ,TYPE_1B
- CP TYPE_,#AD_TYPE_1C
- JP EQ,TYPE_1C
-
- ; common exit point from disassembler
- DONE_DASM:
- ; update memory pointer
- LD AD_IN_HI,R0 ; output buffer
- LD AD_IN_LO,R1 ; address
-
- POP R15 ; restore all regs
- POP R14 ; except R6,R7
- POP R13
- POP R12
- POP R11
- POP R10
- POP R9
- POP R8
- POP R5
- POP R4
- POP R3
- POP R2
- POP R1
- POP R0
-
- RET
-
-
-
- TYPE_01
- ;*******************************************************
- ;*
- ;* Process and output operands for addressing mode:
- ;*
- ;* opcode r
- ;*
- ;*********************************************************;
-
- L_TYPE_01:
- LD R8,BYTE_1 ; get reg #
- AND R8,#$F0 ; in hi nibble
- SWAP R8 ; put in lo nibble
- OR R8,#$C0 ; a working reg
- CALL WR_REG
-
- JP DONE_DASM ; done
-
- TYPE_02
- ;*********************************************************
- ;*
- ;* Process and output operands for addressing modes:
- ;*
- ;* opcode R
- ;* opcode IR
- ;*
- ;***********************************************************;
-
- L_TYPE_02:
- ; get mode from byte #1
- TM BYTE_1,#$01 ; even = direct addr
- JR Z,DIR ; odd = indirect add
- LD R10,#'@' ; indirect mode
- CALL OUT_BUF ; put @ in out buf
- DIR:
- ; test for working reg from byte #2
- LD R10,BYTE_2 ; c0 to ef =
- AND R10,#$F0
- CP R10,#$C0
- JR NE,END_EXC ; working regs
- LD R10,#'R' ; yes working reg
- CALL OUT_BUF
- AND BYTE_2,#$0F ; delete c from wr
- ; two exceptions are 80 and a0 mnenomics
- ; which are word format not byte
- CP BYTE_1,#$80 ; test for inst 80
- JR NE,NO_EXC ; test next inst
- EXCT:
- LD R10,#'R' ; put r in out buf
- CALL OUT_BUF
- JR END_EXC ; done
- NO_EXC:
- CP BYTE_1,#$A0 ; test for inst a0
- JR NE,END_EXC ; done
- JR EXCT ; yes a0 out r
- END_EXC:
- LD R10,BYTE_2
- CALL HEX_D_ASCII ; put reg # in out buf
-
- JP DONE_DASM ; done
-
-
- TYPE_03
- ;*********************************************************
- ;*
- ;* Process and output operands for addressing modes:
- ;*
- ;* opcode IRR
- ;* opcode IR
- ;*
- ;***********************************************************;
-
- L_TYPE_03:
- LD R10,#'@' ;put @ in out buffer
- CALL OUT_BUF
- ; test for working regs in byte #2
- LD R8,BYTE_2
- CALL WR_REG_PAIR
-
- JP DONE_DASM ; done
-
- TYPE_04
- ;*********************************************************
- ;*
- ;* Process and output operands for addressing modes:
- ;*
- ;* opcode IM
- ;*
- ;***********************************************************;
-
- LD R10,#'#' ; put # in out buffer
- CALL OUT_BUF
- LD R10,BYTE_2 ; save im value
- AND R10,#$FC ; mask bank mode in
- ; bits 0-1
- CALL HEX_D_ASCII
-
- JP DONE_DASM ; done
-
-
- TYPE_05
- ;*********************************************************
- ;*
- ;* Process and output operands for addressing modes:
- ;*
- ;* opcode r,r
- ;* opcode r,Ir
- ;*
- ;***********************************************************;
-
-
- ; write dst operand
- LD R8,BYTE_2 ; save dst in R8
- SWAP R8 ; put in lo nibble
- AND R8,#$0F ; isolate
- OR R8,#$C0 ; make working reg
- CALL WR_REG ; write it
- CALL SEP_OPRNDS
-
- ; write src operand
- ; test for indirect
- LD R10,BYTE_1 ; save opcode
- TM R10,#$01 ; test: even = direct
- JR Z, DIRRECT
- ; odd = indirect
- LD R10,#'@' ; put @ in out buffer
- CALL OUT_BUF
- DIRRECT:
- LD R8,BYTE_2 ; save src in R8
- AND R8,#$0F ; isolate
- OR R8,#$C0 ; make working reg
- CALL WR_REG ; write it
-
- JP DONE_DASM ; done
-
-
- TYPE_06
- ;*********************************************************
- ;*
- ;* Process and output operands for addressing modes:
- ;*
- ;* opcode r,Irr
- ;* opcode Ir,Ir
- ;*
- ;***********************************************************;
-
- ; get mode from byte #1
- TM BYTE_1,#$10 ; even = direct
- JR NZ,IDIR ; odd = indirect
-
- N_OPC:
- LD R8,BYTE_2 ; save reg# in high
- AND R8,#$F0 ; nibble -- put in
- SWAP R8 ; low nibble
- OR R8,#$C0 ; a working reg
- CALL WR_REG ; write it
- CALL SEP_OPRNDS
-
- LD R10,#'@' ;put '@' in out buffer
- CALL OUT_BUF
-
- LD R8,BYTE_2 ; save reg# in low
- AND R8,#$0F ; nibble
- OR R8,#$C0 ; a working reg
- CALL WR_REG_PAIR ; write it
-
- JP DONE_DASM ; done
-
- IDIR:
- LD R10,#'@' ;put @RR in out buffer
- CALL OUT_BUF
-
- LD R8,BYTE_2 ; save reg# in low
- AND R8,#$0F ; nibble
- OR R8,#$C0 ; a working reg
- CALL WR_REG_PAIR ; write it
- CALL SEP_OPRNDS
-
- DIR2:
- LD R8,BYTE_2 ; save reg# in high
- AND R8,#$F0 ; nibble -- put in
- SWAP R8 ; low nibble
- OR R8,#$C0 ; a working reg
- CALL WR_REG ; write it
-
- JP DONE_DASM ; done
-
-
- TYPE_07
- ;*********************************************************
- ;*
- ;* Process and output operands for addressing modes:
- ;*
- ;* opcode r,R
- ;*
- ;***********************************************************;
-
- LD R10,BYTE_1 ; opcode x8 or x9
- TM R10,#$01
- JR NZ,X9_
-
- LD R10,#'R' ; opcode = x8
- CALL OUT_BUF ; put r in out buffer
- LD R10,BYTE_1 ; put reg# in out buf
- AND R10,#$F0
- SWAP R10
- CALL HEX_D_ASCII
- CALL SEP_OPRNDS
-
- LD R8,BYTE_2
- CALL WR_REG ; write working reg
-
- JP DONE_DASM ; done
-
- X9_:
- ; opcode = x9
- LD R8,BYTE_2
- CALL WR_REG ; write working reg
- CALL SEP_OPRNDS
-
- LD R10,#'R' ; put r in out buffer
- CALL OUT_BUF
- LD R10,BYTE_1 ;put reg# in out buf
- AND R10,#$F0
- SWAP R10
- CALL HEX_D_ASCII
-
- JP DONE_DASM ; done
-
- TYPE_08
- ;*********************************************************
- ;*
- ;* Process and output operands for addressing modes:
- ;*
- ;* opcode r,IM
- ;*
- ;***********************************************************;
-
- LD R10,#'R' ; put r in out buffer
- CALL OUT_BUF
- LD R10,BYTE_1 ; put reg# in out buf
- AND R10,#$F0
- SWAP R10
- CALL HEX_D_ASCII
- CALL SEP_OPRNDS
-
- LD R10,#'#' ; put # in out buffer
- CALL OUT_BUF
- LD R10,BYTE_2 ; put reg# in out buf
- CALL HEX_D_ASCII
-
- JP DONE_DASM ; done
-
-
- TYPE_09
- ;*********************************************************
- ;*
- ;* Process and output operands for addressing modes:
- ;*
- ;* opcode r,RA
- ;* opcode cc,RA
- ;*
- ;***********************************************************;
-
- LD R10,BYTE_1 ; opcode xa or xb ?
- TM R10,#$01
- JR NZ,XB_
- LD R10,#'R' ; opcode = xa
- CALL OUT_BUF ; put r in out buffer
- LD R10,BYTE_1 ; put reg# in out buf
- AND R10,#$F0
- SWAP R10
- CALL HEX_D_ASCII
- CALL SEP_OPRNDS
- JR COMM ; same as opc xb
- XB_:
- LD R10,BYTE_1 ; get condition code
- AND R10,#$F0
- SWAP R10
- LD R12,#^HB CC_TAB ; cc table addr
- LD R13,#^LB CC_TAB
- LUPE2:
- LDC R11,@RR12 ; read cc table
- CP R10,#$00 ; test for done
- JR Z,COMP2
- LLUP2:
- INCW RR12 ; find next table flag
- LDC R11,@RR12
- TM R11,#$80
- JR Z,LLUP2
- INCW RR12 ; found flag
- DEC R10 ; point to valid data
- JR LUPE2
- COMP2:
- LD R10,R11 ; put cc in out buffer
- AGNI2:
- CALL OUT_BUF
- INCW RR12
- LDC R10,@RR12
- TM R10,#$80
- JR Z,AGNI2
- COMM:
- LD R10,#$25 ; put $ in out buf
- CALL OUT_BUF
- CLR R10 ; calculate address
- TM BYTE_2,#$80 ; test for minus
- JR Z,SKFF
- LD R10,#$FF
- SKFF:
- LD R12,R1 ; lo input addr
- ADD R12,BYTE_2 ; add relative addr
- JR NC,SKK1
- INC R10
- SKK1:
- ADD R10,R0
- CALL HEX_ASCII ;put addr in out buf
- LD R10,R12
- CALL HEX_ASCII
-
- JP DONE_DASM ; done
-
-
- TYPE_0A
- ;*********************************************************
- ;*
- ;* Process and output operands for addressing modes:
- ;*
- ;* opcode R,R
- ;* opcode IR,R
- ;*
- ;***********************************************************;
-
- LD R8,BYTE_3
- CALL WR_REG ; write working reg
- CALL SEP_OPRNDS
-
- ; test mode from byte #1
- LD R10,BYTE_1 ; even = direct
- TM R10,#$01 ; odd = indirect
- JR Z,DIRR
- LD R10,#'@' ; indirect mode
- CALL OUT_BUF ; put @ in out buffer
- DIRR:
- LD R8,BYTE_2
- CALL WR_REG ; write working reg
-
- JP DONE_DASM ; done
-
- TYPE_0B
- ;*********************************************************
- ;*
- ;* Process and output operands for addressing modes:
- ;*
- ;* opcode R,IM
- ;* opcode IR,IM
- ;*
- ;***********************************************************;
-
- ; check for ir,im
- LD R10,BYTE_1 ; check for opcode
- CP R10,#$D6 ; d6 -- indirect
- JR NE,DIRR_
- LD R10,#'@' ; indirect mode
- CALL OUT_BUF ; put @ in out buffer
- DIRR_:
- LD R8,BYTE_2
- CALL WR_REG ; write working reg
- CALL SEP_OPRNDS
-
- LD R10,#'#' ; put # in out buffer
- CALL OUT_BUF
- LD R10,BYTE_3 ; put reg# in out buf
- CALL HEX_D_ASCII
-
- JP DONE_DASM ; done
-
- TYPE_0C
- ;*********************************************************
- ;*
- ;* Process and output operands for addressing modes:
- ;*
- ;* opcode R,IR
- ;*
- ;***********************************************************;
-
- LD R10,#'@' ; put @ in out buffer
- CALL OUT_BUF
- LD R8,BYTE_3
- CALL WR_REG ; write working reg
- CALL SEP_OPRNDS
-
- LD R8,BYTE_2
- CALL WR_REG ; write working reg
-
- JP DONE_DASM ; done
-
-
- TYPE_0D
- ;*********************************************************
- ;*
- ;* Process and output operands for addressing modes:
- ;*
- ;* opcode r,x,R
- ;*
- ;***********************************************************;
-
- LD R10,BYTE_1 ; test opcode for
- CP R10,#$87 ; 87 or 97
- JR EQ,OPC_87
-
- LD R10,BYTE_3 ; opcode = 97
- CALL HEX_D_ASCII ; put reg# in out buf
- LD R10,#$28 ; put (r in out buf
- CALL OUT_BUF
- LD R10,#'R'
- CALL OUT_BUF
- LD R10,BYTE_2 ; put reg# in out buf
- AND R10,#$0F
- CALL HEX_D_ASCII
- LD R10,#$29 ; put ) in out buffer
- CALL OUT_BUF
- CALL SEP_OPRNDS
-
- LD R10,#'R' ; put r in out buffer
- CALL OUT_BUF
- LD R10,BYTE_2 ; put reg# in out buf
- AND R10,#$F0
- SWAP R10
- CALL HEX_D_ASCII
-
- JP DONE_DASM ; done
-
- OPC_87:
- LD R10,#'R' ; put r in out buffer
- CALL OUT_BUF
- LD R10,BYTE_2 ; put reg# in out buf
- AND R10,#$F0
- SWAP R10
- CALL HEX_D_ASCII
- CALL SEP_OPRNDS
-
- LD R10,BYTE_3 ; put reg# in out buf
- CALL HEX_D_ASCII
- LD R10,#$28 ; put (r in out buf
- CALL OUT_BUF
- LD R10,#'R'
- CALL OUT_BUF
- LD R10,BYTE_2 ; put reg# in out buf
- AND R10,#$0F
- CALL HEX_D_ASCII
- LD R10,#$29 ; put ) in out buffer
- CALL OUT_BUF
-
- JP DONE_DASM ; done
-
-
- TYPE_0E
- ;*********************************************************
- ;*
- ;* Process and output operands for addressing modes:
- ;*
- ;* opcode cc,DA
- ;*
- ;***********************************************************;
-
- LD R10,BYTE_1 ; get condition code
- AND R10,#$F0
- SWAP R10
- LD R12,#^HB CC_TAB ; cc table address
- LD R13,#^LB CC_TAB
- LUPE1:
- LDC R11,@RR12 ; read table
- CP R10,#$00
- JR Z,COMP1 ; find table entry
- LLUP1:
- INCW RR12 ; find next table flag
- LDC R11,@RR12
- TM R11,#$80
- JR Z,LLUP1
- INCW RR12 ; point to next entry
- DEC R10
- JR LUPE1
- COMP1:
- LD R10,R11 ; put cc in out buffer
- AGNI1:
- CALL OUT_BUF
- INCW RR12
- LDC R10,@RR12
- TM R10,#$80
- JR Z,AGNI1
-
- LD R10,#$25 ; put $ in out buffer
- CALL OUT_BUF
- LD R10,BYTE_2 ; put addr in out buf
- CALL HEX_ASCII
- LD R10,BYTE_3
- CALL HEX_ASCII
-
- JP DONE_DASM ; done
-
- TYPE_0F
- ;*********************************************************
- ;*
- ;* Process and output operands for addressing modes:
- ;*
- ;* opcode DA
- ;*
- ;***********************************************************;
-
- LD R10,#$25 ; put $ in out buffer
- CALL OUT_BUF
- LD R10,BYTE_2 ; put addr in out buf
- CALL HEX_ASCII
- LD R10,BYTE_3
- CALL HEX_ASCII
-
- JP DONE_DASM ; done
-
- TYPE_10
- ;*********************************************************
- ;*
- ;* Process and output operands for addressing modes:
- ;*
- ;* opcode r,b
- ;* opcode r,b,R
- ;*
- ;***********************************************************;
-
- LD R9,BYTE_2 ; save bit number in R8
- RR R9 ; bits 0-2
- AND R9,#$07
-
- LD R10,BYTE_2 ; find mode
- TM R10,#$01 ; even: dst(0) or src(b)
- JR Z,DST0_ ; odd: dst(b) or src(0)
-
- DSTb_: ; write out dst operand
- LD R8,BYTE_3
- CALL WR_REG ; write working reg
- CALL SEP_OPRNDS
-
- ; write out bit number
- LD R10,#'#' ; put '#' in out buffer
- CALL OUT_BUF
- LD R10,R9 ; put bit# in out buf
- CALL HEX_D_ASCII
- CALL SEP_OPRNDS
-
- ; write out src operand
- LD R8,BYTE_2 ; save reg#
- SWAP R8 ; put reg# in lo nibble
- AND R8,#$0F ; clear upper nibble
- OR R8,#$C0 ; working register
- CALL WR_REG ; write src operand
-
- JP DONE_DASM ; done
-
- DST0_: ; write out dst operand
- LD R8,BYTE_2 ; save reg#
- SWAP R8 ; put reg# in lo nibble
- AND R8,#$0F ; clear upper nibble
- OR R8,#$C0 ; working register
- CALL WR_REG ; write src operand
- CALL SEP_OPRNDS
-
- ; write out src operand
- LD R8,BYTE_3
- CALL WR_REG ; write working reg
- CALL SEP_OPRNDS
-
- ; write out bit number
- LD R10,#'#' ; put '#' in out buffer
- CALL OUT_BUF
- LD R10,R9 ; put bit# in out buf
- CALL HEX_D_ASCII
-
- JP DONE_DASM ; done
-
- TYPE_11
- ;*********************************************************
- ;*
- ;* Process and output operands for addressing modes:
- ;*
- ;* opcode IR,R
- ;* opcode R,IR
- ;*
- ;***********************************************************;
- ; check for IR,R
- LD R10,BYTE_1 ; save opcode
- TM R10,#$10 ; test bit 4
- JR Z, IR_R ; even = IR,R
- R_IR: ; odd = R,IR
- ; write dst operand
- LD R8,BYTE_3 ; save reg
- CALL WR_REG ; write it
- CALL SEP_OPRNDS
-
- ; write src operand
- LD R10,#'@' ; write '@'
- CALL OUT_BUF
- LD R8,BYTE_2 ; save reg
- CALL WR_REG ; write it
-
- JP DONE_DASM ; done
-
- IR_R:
- ; write dst operand
- LD R10,#'@' ; write '@'
- CALL OUT_BUF
- LD R8,BYTE_2 ; save reg
- CALL WR_REG ; write it
- CALL SEP_OPRNDS
-
- ; write src operand
- LD R8,BYTE_3 ; save reg
- CALL WR_REG ; write it
-
- JP DONE_DASM ; done
-
-
- TYPE_12 ; r,b,ra
- ;*********************************************************
- ;*
- ;* Process and output operands for addressing modes:
- ;*
- ;* opcode r,b,RA
- ;*
- ;***********************************************************;
- LD R9,BYTE_2 ; save bit number in R8
- RR R9 ; bits 0-2
- AND R9,#$07
-
- ; write out relative address operand
- LD R10,#$25 ; put $ in out buf
- CALL OUT_BUF
- CLR R10 ; calculate address
- TM BYTE_3,#$80 ; test for minus
- JR Z,SK12FF
- LD R10,#$FF
- SK12FF:
- LD R12,R1 ; lo input addr
- ADD R12,BYTE_3 ; add relative addr
- JR NC,SK12K1
- INC R10
- SK12K1:
- ADD R10,R0
- CALL HEX_ASCII ;put addr in out buf
- LD R10,R12
- CALL HEX_ASCII
- CALL SEP_OPRNDS
-
- ; write out src register
- LD R8,BYTE_2 ; save reg#
- SWAP R8 ; put reg# in lo nibble
- AND R8,#$0F ; clear upper nibble
- OR R8,#$C0 ; working register
- CALL WR_REG ; write src operand
- CALL SEP_OPRNDS
-
- ; write out bit#
- LD R10,#'#' ; put '#' in out buffer
- CALL OUT_BUF
- LD R10,R9 ; put bit# in out buf
- CALL HEX_D_ASCII
-
- JP DONE_DASM ; done
-
- TYPE_13 ; r,b
- ;*********************************************************
- ;*
- ;* Process and output operands for addressing modes:
- ;*
- ;* opcode r,b
- ;*
- ;***********************************************************;
- LD R9,BYTE_2 ; save bit number in R8
- RR R9 ; bits 0-2
- AND R9,#$07
-
- ; write out dst register
- LD R8,BYTE_2 ; save reg#
- SWAP R8 ; put reg# in lo nibble
- AND R8,#$0F ; clear upper nibble
- OR R8,#$C0 ; working register
- CALL WR_REG ; write src operand
- CALL SEP_OPRNDS
-
- ; write out bit#
- LD R10,#'#' ; put '#' in out buffer
- CALL OUT_BUF
- LD R10,R9 ; put bit# in out buf
- CALL HEX_D_ASCII
-
- JP DONE_DASM ; done
-
- TYPE_14
- ;*********************************************************
- ;*
- ;* Process and output operands for addressing modes:
- ;*
- ;* opcode R,RR
- ;* opcode IR,RR
- ;*
- ;***********************************************************;
- ; write out dst operand
- LD R8,BYTE_3
- CALL WR_REG_PAIR
- CALL SEP_OPRNDS
-
- ; write out src operand
- LD R10,BYTE_1 ; even = direct
- TM R10,#$01 ; odd = indirect
- JR Z,DIRR14
- LD R10,#'@' ; indirect mode
- CALL OUT_BUF ; put @ in out buffer
- DIRR14:
- LD R8,BYTE_2
- CALL WR_REG ; write out reg#
-
- JP DONE_DASM ; done
-
- TYPE_15
- ;*********************************************************
- ;*
- ;* Process and output operands for addressing modes:
- ;*
- ;* opcode IM,RR
- ;*
- ;***********************************************************;
-
- ; write out dst operand
- LD R8,BYTE_3
- CALL WR_REG_PAIR
- CALL SEP_OPRNDS
-
- ; write out src operand
- LD R10,#'#' ; put # in out buffer
- CALL OUT_BUF
- LD R10,BYTE_2 ; put reg# in out buf
- CALL HEX_D_ASCII
-
- JP DONE_DASM ; done
-
- TYPE_16
- ;*********************************************************
- ;*
- ;* Process and output operands for addressing modes:
- ;*
- ;* opcode IR,r,RA
- ;*
- ;***********************************************************;
- ; write out dst operand
- LD R8,BYTE_2
- AND R8,#$0F
- OR R8,#$C0
- CALL WR_REG
- CALL SEP_OPRNDS
-
- ; write out src operand
- LD R10,#'@' ; write '@'
- CALL OUT_BUF
- LD R8,BYTE_2 ; save src
- SWAP R8 ; put reg# in lo nibble
- AND R8,#$0F ; clear upper nibble
- OR R8,#$C0 ; working register
- CALL WR_REG ; write it
- CALL SEP_OPRNDS
-
- ; write out relative address operand
- LD R10,#$25 ; put '$' in out buf
- CALL OUT_BUF
- CLR R10 ; calculate address
- TM BYTE_3,#$80 ; test for minus
- JR Z,SK16FF
- LD R10,#$FF
- SK16FF:
- LD R12,R1 ; lo input addr
- ADD R12,BYTE_3 ; add relative addr
- JR NC,SK16K1
- INC R10
- SK16K1:
- ADD R10,R0
- CALL HEX_ASCII ;put addr in out buf
- LD R10,R12
- CALL HEX_ASCII
-
- JP DONE_DASM ; done
-
- TYPE_17
- ;*********************************************************
- ;*
- ;* Process and output operands for addressing modes:
- ;*
- ;* opcode RR,RR
- ;*
- ;***********************************************************;
- ; write out dst operand
- LD R8,BYTE_3
- CALL WR_REG_PAIR
- CALL SEP_OPRNDS
-
- ; write out src operand
- LD R8,BYTE_2
- CALL WR_REG_PAIR
-
- JP DONE_DASM ; done
-
- TYPE_18
- ;*********************************************************
- ;*
- ;* Process and output operands for addressing modes:
- ;*
- ;* opcode RR,IML
- ;*
- ;***********************************************************;
- ; write out dst operand
- LD R8,BYTE_2
- CALL WR_REG_PAIR
- CALL SEP_OPRNDS
-
- ; write out src operand
- LD R10,#'#' ; put # in out buffer
- CALL OUT_BUF
- LD R10,#$25 ; put $ in out buffer
- CALL OUT_BUF
- LD R10,BYTE_3 ; put addr in out buf
- CALL HEX_ASCII
- LD R10,BYTE_4
- CALL HEX_ASCII
-
- JP DONE_DASM ; done
-
- TYPE_19
- ;*********************************************************
- ;*
- ;* Process and output operands for addressing modes:
- ;*
- ;* opcode IA
- ;*
- ;***********************************************************;
- ; write out dst operand
- LD R10,#$23 ; put # in out buffer
- CALL OUT_BUF
- LD R10,#$25 ; put $ in out buffer
- CALL OUT_BUF
- LD R10,BYTE_2 ; put addr in out buf
- CALL HEX_ASCII
-
- JP DONE_DASM ; done
-
- TYPE_1A
- ;*********************************************************
- ;*
- ;* Process and output operands for addressing modes:
- ;*
- ;* opcode r,x(rr)
- ;* opcode x(rr),r
- ;*
- ;***********************************************************;
- ; determine mode - test bit 4
- LD R10,BYTE_1
- TM R10,#$10 ; if cleared then
- JR Z, R_X ; r,x(irr) mode
-
- X_R: ; otherwise x(irr),r
- ; write indexed (short or long) dst operand
- LD R10,#$25 ; put $ in out buffer
- CALL OUT_BUF
-
- LD R10,BYTE_1 ; test for long offset
- TM R10,#$40 ; bit 6 in opcode
- JR NZ, NLX_R ; not long if cleared
- LX_R:
- LD R10,BYTE_4 ; output (hi) offset
- CALL HEX_ASCII
-
- NLX_R:
- LD R10,BYTE_3 ; output (lo) offset
- CALL HEX_ASCII
- LD R10,#'(' ; output '('
- CALL OUT_BUF
-
- LD R8,BYTE_2 ; save reg #
- AND R8,#$0F ; in lo nibble
- OR R8,#$C0 ; make work reg
- CALL WR_REG_PAIR ; write pair
-
- LD R10,#')' ; output ')'
- CALL OUT_BUF
- CALL SEP_OPRNDS
-
- ; write src operand
- LD R8,BYTE_2 ; save src
- SWAP R8 ; put src in lo nibble
- AND R8,#$0F ; isolate src reg
- OR R8,#$C0 ; make work reg
- CALL WR_REG ; write it
-
- JP DONE_DASM ; done
-
- R_X:
- ; write dst operand
- LD R8,BYTE_2 ; save src
- SWAP R8 ; put src in lo nibble
- AND R8,#$0F ; isolate src reg
- OR R8,#$C0 ; make work reg
- CALL WR_REG ; write it
- CALL SEP_OPRNDS
-
- ; write indexed (short or long) src operand
- LD R10,#$25 ; put $ in out buffer
- CALL OUT_BUF
-
- LD R10,BYTE_1 ; test for long offset
- TM R10,#$40 ; bit 6 in opcode
- JR NZ, NLR_X ; not long if cleared
- LR_X:
- LD R10,BYTE_4 ; output (hi) offset
- CALL HEX_ASCII
- NLR_X:
- LD R10,BYTE_3 ; output (lo) offset
- CALL HEX_ASCII
- LD R10,#'(' ; output '('
- CALL OUT_BUF
-
- LD R8,BYTE_2 ; save reg #
- AND R8,#$0F ; in lo nibble
- OR R8,#$C0 ; make work reg
- CALL WR_REG_PAIR ; write pair
-
- LD R10,#')' ; output ')'
- CALL OUT_BUF
-
- JP DONE_DASM ; done
-
- TYPE_1B
- ;*********************************************************
- ;*
- ;* Process and output operands for addressing modes:
- ;*
- ;* opcode r,DA
- ;* opcode DA,r
- ;*
- ;***********************************************************;
-
- ; test for indexed mode
- LD R10,BYTE_2 ; test bits 1-3
- TM R10,#$0E ; if nz then indexed
- JP NZ,TYPE_1A ; mode
-
- ; test for order of operands
- LD R10,BYTE_1 ; test opcode bit 1
- TM R10,#$10 ; if cleared then
- JR Z, r_DA ; r, da mode
- DA_r: ; otherwise da,r
- ; write address operand
- LD R10,#$25 ; output '$'
- CALL OUT_BUF
- LD R10,BYTE_4 ; output hi
- CALL HEX_ASCII ; address byte
- LD R10,BYTE_3 ; output lo
- CALL HEX_ASCII ; address byte
- CALL SEP_OPRNDS
-
- ; write src operand
- LD R8,BYTE_2 ; save src
- SWAP R8 ; put src in lo nibble
- AND R8,#$0F ; isolate src reg
- OR R8,#$C0 ; make work reg
- CALL WR_REG ; write it
-
- JP DONE_DASM ; done
-
- r_DA:
- ; write dst operand
- LD R8,BYTE_2 ; save src
- SWAP R8 ; put src in lo nibble
- AND R8,#$0F ; isolate src reg
- OR R8,#$C0 ; make work reg
- CALL WR_REG ; write it
- CALL SEP_OPRNDS
-
- ; write address operand
- LD R10,#$25 ; output '$'
- CALL OUT_BUF
- LD R10,BYTE_4 ; output hi
- CALL HEX_ASCII ; address byte
- LD R10,BYTE_3 ; output lo
- CALL HEX_ASCII ; address byte
-
- JP DONE_DASM ; done
-
- TYPE_1C
- ;*********************************************************
- ;*
- ;* Process and output operands for addressing modes:
- ;*
- ;* opcode Ir,r
- ;*
- ;***********************************************************;
-
- ; write dst operand
- LD R10,#'@' ; put @ in out buffer
- CALL OUT_BUF
- LD R8,BYTE_2 ; save dst in R8
- SWAP R8 ; put in lo nibble
- AND R8,#$0F ; isolate
- OR R8,#$C0 ; make working reg
- CALL WR_REG ; write it
- CALL SEP_OPRNDS
-
-
- ; write src operand
- LD R8,BYTE_2 ; save src in R8
- AND R8,#$0F ; isolate
- OR R8,#$C0 ; make working reg
- CALL WR_REG ; write it
- CALL SEP_OPRNDS
-
- JP DONE_DASM ; done
-
- CHK_MNE
- ;***************************************************************
- ;*
- ;* CHK_MNE Check for opcode mnemonics that vary.
- ;*
- ;* input RR4 points to current main table entry.
- ;* Lo nibble of R10 contains entry# for alternate
- ;* table. Use alternate table if bit 0 of byte_2
- ;* is cleared.
- ;*
- ;* output If bit 0 of byte_2 is cleared, then RR4 points
- ;* to the correct entry in the alternate table.
- ;*
- ;***************************************************************;
- ; check for opcode mnemonics that vary
- ; RR4 points to current table entry
- ; lo nibble of R10 contains entry# for alt. table
- ; use alt. table if bit 0 of byte_2 is cleared
-
-
-
- LD R8,BYTE_2 ; save mode
- TM R8,#$01 ; test bit 1
- JR Z, VRY_TAB ; use other table
- ; if cleared
-
- SAME_TAB:
- ; use the same table -- just inc pointer
- INCW RR4
- JR DONE_CHK
-
- VRY_TAB:
- ; check for special case of srp
- CP BYTE_1,#$31 ; test for srp
- JR NE,NOT_SRP0 ; opcode
-
- TM BYTE_2,#$02 ; test bit 1
- JR Z,NOT_SRP0 ; for srp0
-
- LD R10,#$08 ; load alt table
- ; index for srp0
-
- NOT_SRP0:
- ; point RR4 to correct pos. in alt. table
- LD R8,R10 ; save entry #
- AND R8,#$0F ; isolate entry #
-
- LD R4,#^HB ALT_TAB ; point RR4 to
- LD R5,#^LB ALT_TAB ; alt table
-
- ENTRY_LP:
- CP R8,#$00 ; are we at right
- JR EQ, AT_ENTRY ; entry ?
-
- CHAR_LP: ; increment RR4 until we get to control byte
- INCW RR4 ; get next char.
- LDC R9,@RR4
- TM R9,#$80 ; control byte?
- JR Z,CHAR_LP ; no
-
- DEC R8 ; yes
- JR ENTRY_LP
-
- AT_ENTRY:
- INCW RR4 ; point RR4 to letter
-
- DONE_CHK:
- ; if instruction is ldc/lde type,
- ; clear lsb of byte_2
- LDC R10,@RR4 ; put letter in R10
- CP R10,#'L' ; load inst. ?
- JR NE,RET_CHK ; no
-
- AND BYTE_2,#$FE ; yes -- clear bit
-
- RET_CHK:
- RET
-
-
-
-
-
- HEX_ASCII
- ;**********************************************************
- ;*
- ;* HEX_ASCII Convert hex byte to ASCII char and output.
- ;*
- ;* input R10 has hex byte.
- ;* RR2 points to the current output buffer pos.
- ;*
- ;* output The byte value is converted to ASCII
- ;* and placed in the output buffer.
- ;*
- ;************************************************************;
-
- LD R11,R10 ; save R10
- AND R10,#$F0 ; isolate hi nibble
- SWAP R10 ; first
- add r10,#$90
- da r10
- adc r10,#$40
- da r10
- LDC @RR2,R10 ; write hi nibble
- INCW RR2 ; into out buffer
- AND R11,#$0F ; now lo nibble
- add r11,#$90
- da r11
- adc r11,#$40
- da r11
- LDC @RR2,R11 ; write lo nibble
- INCW RR2 ; into out buffer
- RET
-
-
-
- RD_MEM
- ;**********************************************************
- ;*
- ;* RD_MEM Read a byte of memory
- ;*
- ;* input: RR0 is the memory read address
- ;*
- ;* output: R10 contains the value read from
- ;* the address
- ;*
- ;**********************************************************;
- PUSH R8
- PUSH R9
- PUSH R15
-
- LD R8,R0
- LD R9,R1
- CALL GETMEM
- LD R10,R15
-
- POP R15
- POP R9
- POP R8
-
- RET
-
-
- OUT_BUF
- ;*****************************************************
- ;*
- ;* OUT_BUF Put a character into the output buffer.
- ;*
- ;* input: R10 has the character
- ;*
- ;*******************************************************;
- LDC @RR2,R10
- INCW RR2
- RET
-
-
- HEX_D_ASCII
- ;**********************************************************
- ;*
- ;* HEX_D_ASCII Convert hex to decimal and put in
- ;* output buffer.
- ;*
- ;* input: R10 has the value to be converted
- ;*
- ;**********************************************************;
- ; first convert hex to decimal ff to 255
- CLR R15 ;unit decimal #
- CLR R14 ;tens decimal #
- CLR R13 ;hundreds dec #
- LUP:
- CP R10,#$00 ; test for done
- JR EQ,ASCI ; yes then to sacii
- DEC R10 ; decrement hex
- INC R15 ; increment dec
- CP R15,#$0A ; check for dec carry
- JR NE,LUP ; no do again
- CLR R15 ; yes carry to tens
- INC R14 ; zero units
- CP R14,#$0A ; check for dec carry
- JR NE,LUP ; no do again
- CLR R14 ; yes carry to hundreds
- INC R13 ; clear tens
- JR LUP ; do again
- ; now convert decimal to ASCII
- ; and delete leading zeros
- ASCI:
- CP R13,#$00 ; first hundreds
- JR EQ,TENS_
- ADD R13,#$30 ; add 30
- LDC @RR2,R13 ; put in out buf
- INCW RR2
- JR SK8 ; no delete tens
- TENS_:
- CP R14,#$00 ; next tens
- JR EQ,UNITS_
- SK8:
- ADD R14,#$30 ; add 30
- LDC @RR2,R14 ; put in out buf
- INCW RR2
- UNITS_:
- ADD R15,#$30 ; next units
- LDC @RR2,R15 ; put in out buf
- INCW RR2
- RET
-
-
- TAB_SP
- ;***********************************************************
- ;*
- ;* TAB_SP Tab over some spaces in the output buffer
- ;*
- ;* input: R15 has the number of spaces to tab.
- ;*
- ;***********************************************************;
- ADD R3,R15
- JR NC,SKP
- INC R2
- SKP:
- RET
-
-
- WR_REG
- ;*******************************************************
- ;*
- ;* WR_REG Write a register operand into the output
- ;* buffer.
- ;*
- ;* input: R8 has the register number.
- ;*
- ;*******************************************************;
- ; R8 must contain the register number
-
- ; test for working reg in R8
- LD R10,R8
- AND R10,#$F0 ; hi nibble =c wregs
- CP R10,#$C0
- JR NE,NWR
- LD R10,#'R' ;put r in out buf
- CALL OUT_BUF
- AND R8,#$0F ; delete c
- NWR:
- LD R10,R8 ; put reg# in out buf
- CALL HEX_D_ASCII
-
- RET
-
-
-
- WR_REG_PAIR
- ;*******************************************************
- ;*
- ;* WR_REG Write a register pair operand into the
- ;* output buffer.
- ;*
- ;* input: R8 has the register number.
- ;*
- ;*******************************************************;
-
- ; test for working reg in R8
- LD R10,R8
- AND R10,#$F0 ; hi nibble =c wregs
- CP R10,#$C0
- JR NE,NWR_PAIR
- LD R10,#'R' ;put r in out buf
- CALL OUT_BUF
- CALL OUT_BUF
- AND R8,#$0F ; delete c
- NWR_PAIR:
- LD R10,R8 ; put reg# in out buf
- CALL HEX_D_ASCII
-
- RET
-
-
-
- SEP_OPRNDS
- ;******************************************************
- ;*
- ;* SEP_OPRNDS Write a ", " into the output buffer
- ;* to separate the operands.
- ;*
- ;******************************************************;
- LD R10,#',' ; write out ", " to
- CALL OUT_BUF ; separate operands
- LD R10,#' '
- CALL OUT_BUF
- RET
-
-
-
-
- ; opcode table: each entry has a control byte followed by 2-6 characters
- ; of opcode mnemonics.
- ; control byte format:
- ; bit 7 : set to indicate control byte
- ; bit 5-6 : instruction size encoded as (n - 1)
- ; bit 0-4 : instruction type for operad mnemonics
-
-
- OP_TAB:
-
- ; opcodes 0x
- db TWO_M+AD_TYPE_2, 'DEC'
- db TWO_M+AD_TYPE_2, 'DEC'
- db TWO_M+AD_TYPE_5, 'ADD'
- db TWO_M+AD_TYPE_5, 'ADD'
- db THREE_M+AD_TYPE_A, 'ADD'
- db THREE_M+AD_TYPE_A, 'ADD'
- db THREE_M+AD_TYPE_B, 'ADD'
- db THREE_M+AD_TYPE_10, 'BOR'
- db TWO_M+AD_TYPE_7, 'LD'
- db TWO_M+AD_TYPE_7, 'LD'
- db TWO_M+AD_TYPE_9, 'DJNZ'
- db TWO_M+AD_TYPE_9, 'JR'
- db TWO_M+AD_TYPE_8, 'LD'
- db THREE_M+AD_TYPE_E, 'JP'
- db ONE_M+AD_TYPE_1, 'INC'
- db ONE_M+AD_TYPE_0, 'NEXT'
-
- ; opcodes 1x
- db TWO_M+AD_TYPE_2, 'RLC'
- db TWO_M+AD_TYPE_2, 'RLC'
- db TWO_M+AD_TYPE_5, 'ADC'
- db TWO_M+AD_TYPE_5, 'ADC'
- db THREE_M+AD_TYPE_A, 'ADC'
- db THREE_M+AD_TYPE_A, 'ADC'
- db THREE_M+AD_TYPE_B, 'ADC'
- db THREE_M+AD_TYPE_10, 'BCP'
- db TWO_M+AD_TYPE_7, 'LD'
- db TWO_M+AD_TYPE_7, 'LD'
- db TWO_M+AD_TYPE_9, 'DJNZ'
- db TWO_M+AD_TYPE_9, 'JR'
- db TWO_M+AD_TYPE_8, 'LD'
- db THREE_M+AD_TYPE_E, 'JP'
- db ONE_M+AD_TYPE_1, 'INC'
- db ONE_M+AD_TYPE_0, 'ENTER'
-
- ; opcodes 2x
-
- db TWO_M+AD_TYPE_2, 'INC'
- db TWO_M+AD_TYPE_2, 'INC'
- db TWO_M+AD_TYPE_5, 'SUB'
- db TWO_M+AD_TYPE_5, 'SUB'
- db THREE_M+AD_TYPE_A, 'SUB'
- db THREE_M+AD_TYPE_A, 'SUB'
- db THREE_M+AD_TYPE_B, 'SUB'
- db THREE_M+AD_TYPE_10, 'BXOR'
- db TWO_M+AD_TYPE_7, 'LD'
- db TWO_M+AD_TYPE_7, 'LD'
- db TWO_M+AD_TYPE_9, 'DJNZ'
- db TWO_M+AD_TYPE_9, 'JR'
- db TWO_M+AD_TYPE_8, 'LD'
- db THREE_M+AD_TYPE_E, 'JP'
- db ONE_M+AD_TYPE_1, 'INC'
- db ONE_M+AD_TYPE_0, 'EXIT'
-
- ; opcodes 3x
- db TWO_M+AD_TYPE_3, 'JP'
- db TWO_M+AD_TYPE_4, VARY_MNE+7, 'SRP1'
- db TWO_M+AD_TYPE_5, 'SBC'
- db TWO_M+AD_TYPE_5, 'SBC'
- db THREE_M+AD_TYPE_A, 'SBC'
- db THREE_M+AD_TYPE_A, 'SBC'
- db THREE_M+AD_TYPE_B, 'SBC'
- db THREE_M+AD_TYPE_12, VARY_MNE+6, 'BTJRT'
- db TWO_M+AD_TYPE_7, 'LD'
- db TWO_M+AD_TYPE_7, 'LD'
- db TWO_M+AD_TYPE_9, 'DJNZ'
- db TWO_M+AD_TYPE_9, 'JR'
- db TWO_M+AD_TYPE_8, 'LD'
- db THREE_M+AD_TYPE_E, 'JP'
- db ONE_M+AD_TYPE_1, 'INC'
- db ONE_M+AD_TYPE_0, 'WFI'
-
- ; opcodes 4x
- db TWO_M+AD_TYPE_2, 'DA'
- db TWO_M+AD_TYPE_2, 'DA'
- db TWO_M+AD_TYPE_5, 'OR'
- db TWO_M+AD_TYPE_5, 'OR'
- db THREE_M+AD_TYPE_A, 'OR'
- db THREE_M+AD_TYPE_A, 'OR'
- db THREE_M+AD_TYPE_B, 'OR'
- db THREE_M+AD_TYPE_10, 'LDB'
- db TWO_M+AD_TYPE_7, 'LD'
- db TWO_M+AD_TYPE_7, 'LD'
- db TWO_M+AD_TYPE_9, 'DJNZ'
- db TWO_M+AD_TYPE_9, 'JR'
- db TWO_M+AD_TYPE_8, 'LD'
- db THREE_M+AD_TYPE_E, 'JP'
- db ONE_M+AD_TYPE_1, 'INC'
- db ONE_M+AD_TYPE_0, 'SB0'
-
- ; opcodes 5x
- db TWO_M+AD_TYPE_2, 'POP'
- db TWO_M+AD_TYPE_2, 'POP'
- db TWO_M+AD_TYPE_5, 'AND'
- db TWO_M+AD_TYPE_5, 'AND'
- db THREE_M+AD_TYPE_A, 'AND'
- db THREE_M+AD_TYPE_A, 'AND'
- db THREE_M+AD_TYPE_B, 'AND'
- db TWO_M+AD_TYPE_13, 'BITC'
- db TWO_M+AD_TYPE_7, 'LD'
- db TWO_M+AD_TYPE_7, 'LD'
- db TWO_M+AD_TYPE_9, 'DJNZ'
- db TWO_M+AD_TYPE_9, 'JR'
- db TWO_M+AD_TYPE_8, 'LD'
- db THREE_M+AD_TYPE_E, 'JP'
- db ONE_M+AD_TYPE_1, 'INC'
- db ONE_M+AD_TYPE_0, 'SB1'
-
- ; opcodes 6x
- db TWO_M+AD_TYPE_2, 'COM'
- db TWO_M+AD_TYPE_2, 'COM'
- db TWO_M+AD_TYPE_5, 'TCM'
- db TWO_M+AD_TYPE_5, 'TCM'
- db THREE_M+AD_TYPE_A, 'TCM'
- db THREE_M+AD_TYPE_A, 'TCM'
- db THREE_M+AD_TYPE_B, 'TCM'
- db THREE_M+AD_TYPE_10, 'BAND'
- db TWO_M+AD_TYPE_7, 'LD'
- db TWO_M+AD_TYPE_7, 'LD'
- db TWO_M+AD_TYPE_9, 'DJNZ'
- db TWO_M+AD_TYPE_9, 'JR'
- db TWO_M+AD_TYPE_8, 'LD'
- db THREE_M+AD_TYPE_E, 'JP'
- db ONE_M+AD_TYPE_1, 'INC'
- db ONE_M+AD_TYPE_0, '**'
-
- ; opcodes 7x
- db TWO_M+AD_TYPE_2, 'PUSH'
- db TWO_M+AD_TYPE_2, 'PUSH'
- db TWO_M+AD_TYPE_5, 'TM'
- db TWO_M+AD_TYPE_5, 'TM'
- db THREE_M+AD_TYPE_A, 'TM'
- db THREE_M+AD_TYPE_A, 'TM'
- db THREE_M+AD_TYPE_B, 'TM'
- db TWO_M+AD_TYPE_13, VARY_MNE+5,'BITS'
- db TWO_M+AD_TYPE_7, 'LD'
- db TWO_M+AD_TYPE_7, 'LD'
- db TWO_M+AD_TYPE_9, 'DJNZ'
- db TWO_M+AD_TYPE_9, 'JR'
- db TWO_M+AD_TYPE_8, 'LD'
- db THREE_M+AD_TYPE_E, 'JP'
- db ONE_M+AD_TYPE_1, 'INC'
- db ONE_M+AD_TYPE_0, '**'
-
- ; opcodes 8x
- db TWO_M+AD_TYPE_2, 'DECW'
- db TWO_M+AD_TYPE_2, 'DECW'
- db THREE_M+AD_TYPE_11, 'PUSHUD'
- db THREE_M+AD_TYPE_11, 'PUSHUI'
- db THREE_M+AD_TYPE_14, 'MULT'
- db THREE_M+AD_TYPE_14, 'MULT'
- db THREE_M+AD_TYPE_15, 'MULT'
- db THREE_M+AD_TYPE_D, 'LD'
- db TWO_M+AD_TYPE_7, 'LD'
- db TWO_M+AD_TYPE_7, 'LD'
- db TWO_M+AD_TYPE_9, 'DJNZ'
- db TWO_M+AD_TYPE_9, 'JR'
- db TWO_M+AD_TYPE_8, 'LD'
- db THREE_M+AD_TYPE_E, 'JP'
- db ONE_M+AD_TYPE_1, 'INC'
- db ONE_M+AD_TYPE_0, 'DI'
-
- ; opcodes 9x
- db TWO_M+AD_TYPE_2, 'RL'
- db TWO_M+AD_TYPE_2, 'RL'
- db THREE_M+AD_TYPE_11, 'POPUD'
- db THREE_M+AD_TYPE_11, 'POPUI'
- db THREE_M+AD_TYPE_14, 'DIV'
- db THREE_M+AD_TYPE_14, 'DIV'
- db THREE_M+AD_TYPE_15, 'DIV'
- db THREE_M+AD_TYPE_D, 'LD'
- db TWO_M+AD_TYPE_7, 'LD'
- db TWO_M+AD_TYPE_7, 'LD'
- db TWO_M+AD_TYPE_9, 'DJNZ'
- db TWO_M+AD_TYPE_9, 'JR'
- db TWO_M+AD_TYPE_8, 'LD'
- db THREE_M+AD_TYPE_E, 'JP'
- db ONE_M+AD_TYPE_1, 'INC'
- db ONE_M+AD_TYPE_0, 'EI'
-
- ; opcodes ax
- db TWO_M+AD_TYPE_2, 'INCW'
- db TWO_M+AD_TYPE_2, 'INCW'
- db TWO_M+AD_TYPE_5, 'CP'
- db TWO_M+AD_TYPE_5, 'CP'
- db THREE_M+AD_TYPE_A, 'CP'
- db THREE_M+AD_TYPE_A, 'CP'
- db THREE_M+AD_TYPE_B, 'CP'
- db FOUR_M+AD_TYPE_1B, VARY_MNE+0,'LDE'
- db TWO_M+AD_TYPE_7, 'LD'
- db TWO_M+AD_TYPE_7, 'LD'
- db TWO_M+AD_TYPE_9, 'DJNZ'
- db TWO_M+AD_TYPE_9, 'JR'
- db TWO_M+AD_TYPE_8, 'LD'
- db THREE_M+AD_TYPE_E, 'JP'
- db ONE_M+AD_TYPE_1, 'INC'
- db ONE_M+AD_TYPE_0, 'RET'
-
- ; opcodes bx
- db TWO_M+AD_TYPE_2, 'CLR'
- db TWO_M+AD_TYPE_2, 'CLR'
- db TWO_M+AD_TYPE_5, 'XOR'
- db TWO_M+AD_TYPE_5, 'XOR'
- db THREE_M+AD_TYPE_A, 'XOR'
- db THREE_M+AD_TYPE_A, 'XOR'
- db THREE_M+AD_TYPE_B, 'XOR'
- db FOUR_M+AD_TYPE_1B, VARY_MNE+0,'LDE'
- db TWO_M+AD_TYPE_7, 'LD'
- db TWO_M+AD_TYPE_7, 'LD'
- db TWO_M+AD_TYPE_9, 'DJNZ'
- db TWO_M+AD_TYPE_9, 'JR'
- db TWO_M+AD_TYPE_8, 'LD'
- db THREE_M+AD_TYPE_E, 'JP'
- db ONE_M+AD_TYPE_1, 'INC'
- db ONE_M+AD_TYPE_0, 'IRET'
-
- ; opcodes cx
- db TWO_M+AD_TYPE_2, 'RRC'
- db TWO_M+AD_TYPE_2, 'RRC'
- db THREE_M+AD_TYPE_16, 'CPIJE'
- db TWO_M+AD_TYPE_6, VARY_MNE+0,'LDE'
- db THREE_M+AD_TYPE_17, 'LDW'
- db THREE_M+AD_TYPE_14, 'LDW'
- db FOUR_M+AD_TYPE_18, 'LDW'
- db TWO_M+AD_TYPE_5, 'LD'
- db TWO_M+AD_TYPE_7, 'LD'
- db TWO_M+AD_TYPE_7, 'LD'
- db TWO_M+AD_TYPE_9, 'DJNZ'
- db TWO_M+AD_TYPE_9, 'JR'
- db TWO_M+AD_TYPE_8, 'LD'
- db THREE_M+AD_TYPE_E, 'JP'
- db ONE_M+AD_TYPE_1, 'INC'
- db ONE_M+AD_TYPE_0, 'RCF'
-
- ; opcodes dx
- db TWO_M+AD_TYPE_2, 'SRA'
- db TWO_M+AD_TYPE_2, 'SRA'
- db THREE_M+AD_TYPE_16, 'CPIJNE'
- db TWO_M+AD_TYPE_6, VARY_MNE+0,'LDE'
- db TWO_M+AD_TYPE_19, 'CALL'
- db ONE_M+AD_TYPE_0, '**'
- db THREE_M+AD_TYPE_B, 'LD'
- db TWO_M+AD_TYPE_1C, 'LD'
- db TWO_M+AD_TYPE_7, 'LD'
- db TWO_M+AD_TYPE_7, 'LD'
- db TWO_M+AD_TYPE_9, 'DJNZ'
- db TWO_M+AD_TYPE_9, 'JR'
- db TWO_M+AD_TYPE_8, 'LD'
- db THREE_M+AD_TYPE_E, 'JP'
- db ONE_M+AD_TYPE_1, 'INC'
- db ONE_M+AD_TYPE_0, 'SCF'
-
- ; opcodes ex
- db TWO_M+AD_TYPE_2, 'RR'
- db TWO_M+AD_TYPE_2, 'RR'
- db TWO_M+AD_TYPE_6, VARY_MNE+1,'LDED'
- db TWO_M+AD_TYPE_6, VARY_MNE+2,'LDEI'
- db THREE_M+AD_TYPE_A, 'LD'
- db THREE_M+AD_TYPE_A, 'LD'
- db THREE_M+AD_TYPE_B, 'LD'
- db THREE_M+AD_TYPE_1A, VARY_MNE+0,'LDE'
- db TWO_M+AD_TYPE_7, 'LD'
- db TWO_M+AD_TYPE_7, 'LD'
- db TWO_M+AD_TYPE_9, 'DJNZ'
- db TWO_M+AD_TYPE_9, 'JR'
- db TWO_M+AD_TYPE_8, 'LD'
- db THREE_M+AD_TYPE_E, 'JP'
- db ONE_M+AD_TYPE_1, 'INC'
- db ONE_M+AD_TYPE_0, 'CCF'
-
- ; opcodes fx
- db TWO_M+AD_TYPE_2, 'SWAP'
- db TWO_M+AD_TYPE_2, 'SWAP'
- db TWO_M+AD_TYPE_6, VARY_MNE+3,'LDEPD'
- db TWO_M+AD_TYPE_6, VARY_MNE+4,'LDEPI'
- db TWO_M+AD_TYPE_3, 'CALL'
- db THREE_M+AD_TYPE_C, 'LD'
- db THREE_M+AD_TYPE_F, 'CALL'
- db THREE_M+AD_TYPE_1A, VARY_MNE+0,'LDE'
- db TWO_M+AD_TYPE_7, 'LD'
- db TWO_M+AD_TYPE_7, 'LD'
- db TWO_M+AD_TYPE_9, 'DJNZ'
- db TWO_M+AD_TYPE_9, 'JR'
- db TWO_M+AD_TYPE_8, 'LD'
- db THREE_M+AD_TYPE_E, 'JP'
- db ONE_M+AD_TYPE_1, 'INC'
- db ONE_M+AD_TYPE_0, 'NOP'
- db HI_BIT
-
- ; mnenmonics that vary
- ALT_TAB:
- db HI_BIT, 'LDC'
- db HI_BIT, 'LDCD'
- db HI_BIT, 'LDCI'
- db HI_BIT, 'LDCPD'
- db HI_BIT, 'LDCPI'
- db HI_BIT, 'BITR'
- db HI_BIT, 'BTJRF'
- db HI_BIT, 'SRP'
- db HI_BIT, 'SRP0'
- db HI_BIT
-
- ; condition code mnemonics
- CC_TAB:
- db 'F',COMMA,' ',$80
- db 'LT',COMMA,' ',$80
- db 'LE',COMMA,' ',$80
- db 'ULE',COMMA,' ',$80
- db 'OV',COMMA,' ',$80
- db 'MI',COMMA,' ',$80
- db 'Z/EQ',COMMA,' ',$80
- db 'C/ULT',COMMA,' ',$80
- db ' ',$80
- db 'GE',COMMA,' ',$80
- db 'GT',COMMA,' ',$80
- db 'UGT',COMMA,' ',$80
- db 'NOV',COMMA,' ',$80
- db 'PL',COMMA,' ',$80
- db 'NZ/NE',COMMA,' ',$80
- db 'NC/UGE',COMMA,' ',$80
-
- END
-