; 68EC000 MONITOR Version 2.10, modified April 6, 2003.
;
; Based on Antonakos's monitor with substantial changes
; since the original version lacked many features.
; Register display, register modify, tracing and
; break-pointing were added by Sol Rosenstark (SR).
; Disassembly was added by Dave Harrison (DH).
;
; Version 2.10 contains the following modifications;
;
; (DH)  1. Modified exception ADDERR, ILEGAL, DIVZERO
;          routines to include address of exception.
;       2. Added option to change register values
;          while tracing.
;       3. Fixed unassembly of register lists for
;          MOVEM instruction.
; (SR)  1. The trap #0, trap #1 and the trap #3
;          routines no longer trash the D0 register.
;       2. The LEA disassebly now distinguishes the
;                 following:
; 00008000  4BF8 8000                 LEA.W   $8000,A5
; 00008004  4BF9 0000 D000            LEA.L   $0000D000,A5
; (SR)  3. Made the trace display correspond more closely
;          to that of EMU68K, with some improvements.
; Serial port assignments
DREG    EQU     $10000	;serial data port
CSREG   EQU     $10001	;control/status port
DAVBIT  EQU     $2	;data available bit
BFEBIT  EQU     $1	;buffer empty bit
; Ram storage assignments.
RAM     EQU     $8000   ;Change for other decoding
RAMLEN  EQU     $8000   ;$8000 for 62256
ENDRAM  EQU     RAM+RAMLEN
USTCK   EQU     ENDRAM-$150     ;user stack pointer
STACK   EQU     ENDRAM-$CA      ;system stack pointer
OLD_PC	EQU	ENDRAM-$CA	;preceding PC
UNADR   EQU     ENDRAM-$C6      ;unasm start address
UASMCMD EQU     ENDRAM-$C2      ;unasm cmd buf. 32 char
UASMOPR EQU     ENDRAM-$BA      ;******
SPARE   EQU     ENDRAM-$B9      ;spare byte for future
                                ;use
REGTYP  EQU     ENDRAM-$B8      ;information for return
                                ;from regmod cmd
PRTBUF  EQU     ENDRAM-$A0      ;16 char print buffer
INPBUF  EQU     ENDRAM-$90      ;32 char input buffer
SAVREGS EQU     ENDRAM-$70      ;D0-D7/A0-A6 storage
SAV_A7  EQU     ENDRAM-$34      ;A7 storage
SAV_PC  EQU     ENDRAM-$30      ;PC storage
SAV_SR  EQU     ENDRAM-$2C      ;SR storage
DUMPADR EQU     ENDRAM-$2A      ;dump start address
; The 2 permanent breakpoint addresses go below
BP_AD3  EQU     ENDRAM-$26
BP_AD4  EQU     ENDRAM-$22
; Temporary breakpoint addresses go below
BP_ADS1 EQU     ENDRAM-$1E
BP_ADS2 EQU     ENDRAM-$1A
BP_ADS3 EQU     ENDRAM-$16
BP_ADS4 EQU     ENDRAM-$12
; Saved breakpoint opcodes go below
OPCOD1  EQU     ENDRAM-$E
OPCOD2  EQU     ENDRAM-$C
OPCOD3  EQU     ENDRAM-$A
OPCOD4  EQU     ENDRAM-$8
;
FP_FLG  EQU     ENDRAM-$6  ;TRACE 1st pass flag
SKIPFLG EQU     ENDRAM-$5  ;Go skip 1 instruction flag
S2_FLG  EQU     ENDRAM-$4  ;LOAD S2 line flag
; miscellaneous equates
TRPTEN  EQU     $4E4A
TRPELF  EQU     $4E4B
NUMCMD  EQU     13      ;# commands checked
DUMPBYT EQU     $8F     ;# of chars in dump
CR      EQU     $D
LF      EQU     $A
; equates for RAM testing of exceptions
TRP_11  EQU     RAM     ;TRAP #11
TRP_12  EQU     RAM+4   ;TRAP #12
TRP_13  EQU     RAM+8   ;TRAP #13
TRP_14  EQU     RAM+12  ;TRAP #14
TRP_15  EQU     RAM+16  ;TRAP #15
FUTURE  EQU     RAM+20
;
	ORG     0
; The code below goes into the ROM vector table
	DC.L    STACK   ;RESET: initial SSP
	DC.L    START   ;RESET: initial PC
	DC.L    BUSERR
	DC.L    ADDERR
	DC.L    ILEGAL
	DC.L    DIVZERO
	DC.L    START   ;CHK not implemented
	DC.L    TRAP_V
	DC.L    PRIVIOL ;Privilege violation
	DC.L    TRACE
	DC.L    LINE_A
	DC.L    LINE_F
;As a precaution, skip reserved vectors
	ORG     $7C
	DC.L    LEVEL_7
	DC.L    TO_CHARIN       ;TRAP #0
	DC.L    TO_CHAROUT      ;TRAP #1
	DC.L    TO_CRLF         ;TRAP #2
	DC.L    TO_PRTMSG       ;TRAP #3
	DC.L    TO_PRT_BYT      ;TRAP #4
	DC.L    TO_PRT_WRD      ;TRAP #5
	DC.L    TO_PRT_LON      ;TRAP #6
	DC.L    TO_GET_BYT      ;TRAP #7
	DC.L    TO_GETADR       ;TRAP #8
	DC.L    TRP_9           ;TRAP #9
	DC.L    TRP_10          ;TRAP #10
	DC.L    TRP_11          ;TRAP #11
	DC.L    TRP_12          ;TRAP #12
	DC.L    TRP_13          ;TRAP #13
	DC.L    TRP_14          ;TRAP #14
	DC.L    TRP_15          ;TRAP #15
;
; The address below can be much lower if
; few interrupts are used.
	ORG     $400    ;start of monitor
;
START   BSR     NULLREG ;init user regs
	BSR     SERINI ;init ser. chip
	BSR     SIGN_ON ;greet user
;
; This point is reentered after each command
; is executed, so various things are reset. It
; then sends the prompt and calls GETLIN to
; obtain a line of KBD input terminated by
; a CR. The typed line is in the INPBUF.
GET_CMD	ANDI.W  #$7FFF,SR  ;disable tracing
	ANDI.W  #$7FFF,SAV_SR;fix the USR
	MOVEA.L #STACK,A7 ;init stack
	BSR     CRLF
	MOVE.B  #'%',D1 ;output prompt
	BSR     CHAROUT
	BSR     GETLIN ;fill INPBUF from KBD
	MOVEA.L #INPBUF,A6 ;repoint to buffer
	BSR     SKIPSP  ;skip leading SPs
;
; A6 now points to the first non SP char.
; This is put in D1, changed to UC. It will
; put the last character preceding a CR or
; SP into D2 and go on to SEARCH. Thus
; typing command ABCD is the same as D.
; This routine leaves A6 pointing one beyond
; the CR or SP which follows the principal
; command character where it stays until the
; command service routine is executed.
INCOM   MOVE.B  (A6)+,D1
	BSR     UP_CASE
	CMPI.B  #CR,D1  ;test for CR
	BEQ.S   SEARCH
	CMPI.B  #' ',D1 ;test for SP
	BEQ.S   SEARCH
	MOVE.B  D1,D2   ;insert it into D2
	BRA.S   INCOM   ;get next char
;
; Put the # of commands in D5, the command
; addresses in A1 and the command character
; addresses in A2. If the command letter is
; legit then jump to the command routine,
; else signal by typing "Bad Command."
SEARCH  MOVE.B  #NUMCMD,D5 ;# of cmds
	MOVEA.L #CMD_ADR,A1 ;A1 -> cmd addrs
	MOVEA.L #COMANDS,A2 ;A2 -> cmd chars
TSTNEXT CMP.B   (A2)+,D2        ;test again
	BEQ.S   DO_JUMP
	ADDQ.L  #4,A1   ;point to next cmd
	SUBQ.B  #1,D5   ;all cmds checked?
	BNE.S   TSTNEXT
	BRA     CMDERR  ;illegal command
DO_JUMP MOVEA.L (A1),A1 ;get command addr
	JMP     (A1)    ;and go execute it
;
; Fill memory between 2 addresses with a
; HEX value.
FILL    BSR     GETADR  ;get start addr
	MOVEA.L D2,A1
	BSR     GETADR  ;get end addr
	ADDQ.L  #1,D2   ;Needed because using (A1)+
	MOVEA.L D2,A2
	BSR     GETADR  ;get HEX byte
FILLEM  CMPA.L  A1,A2   ;at end yet?
	BEQ     GET_CMD
	MOVE.B  D2,(A1)+ ;move'em
	BRA.S   FILLEM
;
; Dumps memory. The starting address is
; fixed to end in 00. Displays in rows of
; 16 bytes. Displays ASCII equivalents too.
DUMP    CMPI.B  #CR,-1(A6);is previous CR?
	BNE.S   DUMP0   ;no, so proceed
	MOVE.L  DUMPADR,D2 ;get old starting address
	MOVEA.L D2,A4
	ADDI.L  #DUMPBYT,D2 ;get standard # of lines
	MOVEA.L D2,A5
	BRA.S   ADR_OUT ;all done, so dump
DUMP0   CMPI.B  #',',(A6);is char a comma?
	BNE.S   DUMP0A  ;no, then get new start addr
	MOVE.L  DUMPADR,D2  ;get old dump addr
	MOVEA.L D2,A5     ;into A5
	ADDQ.L  #1,A6   ;point past comma
	BRA.S   DUMP1   ;get count
DUMP0A  BSR     GETADR  ;get start address
	ANDI.B  #$F0,D2 ;zero lower nibble
	MOVEA.L D2,A4
	CMPI.B  #CR,-1(A6);is previous CR?
	BNE.S   DUMP1   ;no, so proceed
	ADDI.L  #DUMPBYT,D2
	MOVEA.L D2,A5
	BRA.S   ADR_OUT
DUMP1   BSR     GETADR  ;get # of lines to display
	SUBQ.L  #1,D2   ;reduce by 1
	LSL.L   #4,D2   ;x16 bytes per line
	MOVEA.L D2,A5
	ADDA.L  A4,A5   ;add the start address
ADR_OUT BSR     CRLF    ;new line please
	MOVE.L  A4,D2   ;print address
	BSR     PRT_SIX
	BSR     TWO_SP  ;and some spaces
BYTEOUT MOVE.B  (A4)+,D2;get a byte
	BSR     PRT_BYT ;print the byte
	BSR     SPACE
	MOVE.L  A4,D1   ;done 16 yet?
	ANDI.L  #$F,D1
	BNE.S   BYTEOUT
	SUBA.L  #16,A4  ;back up 16 bytes
	BSR     SPACE
ASC_OUT MOVE.B  (A4)+,D1;get a byte
	CMPI.B  #' ',D1 ;is it printable?
	BMI.S   UN_PRT
	CMPI.B  #$7D,D1
	BMI.S   SEND_IT
UN_PRT  MOVE.B  #'.',D1 ;unprintables -> .
SEND_IT BSR     CHAROUT ;print ASCII equiv
	MOVE.L  A4,D2   ;done 16 yet?
	ANDI.L  #$F,D2
	BNE.S   ASC_OUT
	MOVE.L  A4,DUMPADR
	BSR     INSTAT  ;key pressed?
	BEQ.S   SEND1   ;no, go on
	BSR     CHARIN  ;yes, get the char
	CMPI.B  #3,D1   ;Is it ^C?
	BEQ     GET_CMD ;If yes then quit
SEND1   CMPA.L  A4,A5   ;Is A4 > A5?
	BMI     GET_CMD ;Yes, then quit
	BRA.S   ADR_OUT
;
; Set breakpoints and transfer execution
; to the user program.
; G<ENT> starts execution at current address
; G <start> <bkpt1> <bkpt2> is obvious
; G , <bkpt1> <bkpt2> continues from current
; program counter.
GO      CMPI.B  #CR,-1(A6);is previous CR?
	BEQ.S   GO3     ;yes, so start
	CMPI.B  #',',(A6);is char a comma?
	BNE.S   GO1     ;no, then go on
	ADDQ.L  #1,A6   ;point past comma
	BRA.S   GO2     ;get breakpoints
; get execution address
GO1     BSR     GETADR
	MOVE.L  D2,SAV_PC ;save it
	CMPI.B  #CR,-1(A6);is previous CR?
	BEQ.S   GO3     ;yes, so start
; get first breakpoint address
GO2     BSR     GETADR
	MOVE.L  D2,BP_ADS1 ;save it
	CMPI.B  #CR,-1(A6);is previous CR?
	BEQ.S   GO3     ;yes, so start
; get second breakpoint address
	BSR     GETADR
	MOVE.L  D2,BP_ADS2 ;save it
; Now move-in the 2 permanent addresses
GO3     MOVE.L  BP_AD3,BP_ADS3
	MOVE.L  BP_AD4,BP_ADS4
; Duplicate breakpoints wreak havoc when set. To avoid
; these problems RID_EQ nulls duplicate entries.
	BSR     RID_EQ
; Now all breakpoints are in place. If a breakpoint
; address is 0 then it's not set. If not 0 then
; proceed to see if the address is the same as that
; at SAV_PC. If yes then execute 1 instruction and
; now proceed to set the breakpoint by saving its
; opcode and replacing it with TRAP #10. This is to
; be done but once.
	MOVEA.L #BP_ADS1,A0 ;A0 -> BP_ADS1
	MOVEA.L #OPCOD1,A1  ;A1 -> OPCOD1
	SF      D1      ;succcesive instructions flag
	MOVE.W  #3,D0 ;loop counter in D0.W
GO4     TST.L   (A0)
	BEQ.S   GO6 ;if bkpt addr is 0 then ignore
	MOVE.L  SAV_PC,D2 ;Not 0, so compare bkpt
	CMP.L   (A0),D2 ;addr. with user PC
	BNE.S   GO5     ;Go and set if not same
	TST.B   D1      ;Is this the 1st occurrence?
	BNE.S   GO5     ;No, the go set it.
	MOVEM.L D0/A0-A1,-(A7)  ;If bkpt = (SAV_PC)
	BSR     GOSKIP  ;then skip one instruction
	MOVEM.L (A7)+,D0/A0-A1
	ST      D1 ;Make sure this happens but once
; Okay, now finally set the breakpoints.
GO5     MOVEA.L (A0),A2  ;get bkpt addr
	MOVE.W  (A2),(A1) ;save and replace
	MOVE.W  #TRPTEN,(A2) ;its opcode
; Bump pointers to the next breakpoint
GO6     LEA     4(A0),A0     ;bump A0
	LEA     2(A1),A1     ;bump A1
	DBRA    D0,GO4
	BSR     REGREST ;restore user regs
	RTE     ;and go to user program
;
; This is the routine for doing a hidden
; trace tracing of a single line of code.
GOSKIP  ST      SKIPFLG ;set the flag
	SF      FP_FLG  ;clear flag
	BSR     REGREST ;restore user regs
	ORI.W   #$8000,SR   ;enable tracing
	RTE
;
; This routine nulls duplicate entries.
RID_EQ  MOVE.W  #3,D1
	MOVEA.L #BP_ADS1,A0     ;point to 1st num
RID1    MOVE.W  D1,D4
	LEA     4(A0),A1        ;point to 2nd num
RID2    MOVE.L  (A0),D2         ;put it in D2
	CMP.L   (A1),D2
	BNE.S   RID3    ;skip if not equal
	CLR.L   (A1)
RID3    ADDQ.L  #4,A1   ;point to next enty
	SUBQ.W  #1,D4   ;decrement inner loop counter
	BNE.S   RID2
	ADDQ.L  #4,A0   ;point to next enty
	SUBQ.W  #1,D1
	BNE.S   RID1
	RTS
;
; This routine saves the user registers
; after a TRAP #9 program termination,
; prints the address at which the TRAP #9
; instruction was found and puts back the
; original opcodes at all breakpoints.
TRP_9   BSR     REG_SAV
	MOVEA.L #MSG_NIN,A3;point to message
	BSR     PRTMSG
	MOVE.L  SAV_PC,D2 ;get user PC value
	SUBQ.L  #2,D2   ;adjust address
	BSR     PRT_SIX
	BSR     CRLF
	BSR     CLR_BK  ;clear the bkpts
	BRA     GET_CMD ;all done
;
; This TRAP #10 routine is executed when a
; breakpoint is encountered. It saves the
; registers and prints MSG_TEN. It then
; puts back the original opcodes at all
; breakpoints.
TRP_10  BSR     REG_SAV
	MOVEA.L #MSG_TEN,A3;point to message
	BSR     PRTMSG
	MOVE.L  SAV_PC,D2 ;get user PC value
	SUBQ.L  #2,D2   ;adjust address
	MOVE.L  D2,SAV_PC ;store adjusted PC
	BSR     PRT_SIX
	BSR     CRLF
	BSR     CLR_BK  ;clear the bkpts
	BRA     GET_CMD ;all done
;
; Removes any breakpoints that existed and
; puts back the appropriate opcodes.
; First remove bkpts set by GO command.
CLR_BK  MOVEA.L #BP_ADS1,A0 ;A0 -> BP_AD1
	MOVEA.L #OPCOD1,A1  ;A1 -> OPCOD1
	MOVEQ   #3,D0 ;loop 4 times
CLR_BK1 TST.L   (A0)
	BEQ.S   CLR_BK2 ;if 0 then ignore
	MOVEA.L (A0),A2 ;get breakpoint addr
	MOVE.W  (A1),(A2) ;restore opcode
	CLR.L   (A0)
CLR_BK2 LEA     4(A0),A0     ;bump A0
	LEA     2(A1),A1     ;bump A1
	DBRA    D0,CLR_BK1
	RTS
;
VERIFY  BSR     GETADR  ;get start addr
	MOVEA.L D2,A1   ;start addr in A1
	BSR     GETADR  ;get end addr
	MOVEA.L D2,A2   ;end addr in A2
	ADDQ.L  #1,A2   ;Needed because using (A1)+
	BSR     GETADR  ;get dest addr
	MOVEA.L D2,A3   ;dest addr in A3
VERIF1  CMPM.B  (A1)+,(A3)+ ;compare bytes
	BNE     FAIL
	CMPA.L  A1,A2   ;at end addr yet?
	BNE.S   VERIF1
	LEA     PASSMSG,A3      ;POINT TO MESSAGE
	BRA.S   QUIT
FAIL    LEA     FAILMSG,A3      ;POINT TO MESSAGE
QUIT    BSR     PRTMSG
	BRA     GET_CMD
;
MOOV    BSR     GETADR  ;get start addr
	MOVEA.L D2,A1
	BSR     GETADR  ;get end addr
	MOVEA.L D2,A2
	ADDQ.L  #1,A2   ;Needed because using (A1)+
	BSR     GETADR  ;get dest addr
	MOVEA.L D2,A3
MOOV1   MOVE.B  (A1)+,(A3)+ ;move bytes
	CMPA.L  A1,A2   ;at end addr yet?
	BNE.S   MOOV1
	BRA     GET_CMD
;
; Edit data on the screen
EDIT    BSR     GETADR  ;get start address
	MOVEA.L D2,A2   ;point A2 to memory
	BSR     CRLF    ;new line please
NEW_DAT MOVE.L  A2,D2   ;print data address
	BSR     PRT_SIX
	BSR     SPACE
	MOVE.B  (A2),D2 ;get the data stored
	BSR     PRT_BYT ;and show it
	MOVE.B  #'?',D1 ;Print change prompt
	BSR     CHAROUT
	BSR     GET_BYT ;get new data
	TST.B   D2      ;no change desired?
	BEQ.S   ENTR_IT ;jump if new data
	MOVE.B  (A2),D1 ;reget old data
ENTR_IT MOVE.B  D1,(A2)+;save data and bump
	BSR.S   NEW_DAT ;pointer
;
; Display or modify register data as
; required. SEARCH left A6 pointing one
; beyond the CR or SP which follows the
; principal command character.
; Next line added in mon209 to set where to return
REGMOD  MOVE.B #$00,REGTYP
        CMPI.B  #CR,-1(A6);is previous CR?
	BNE.S   REGMOD0 ;no, so skip
	BSR     REGPRT1
	BRA     GET_CMD
REGMOD0 BSR     SKIPSP  ;skip leading SPs
	MOVE.B  (A6)+,D1;get the next char
	BSR     UP_CASE
	MOVEA.L #SAVREGS+32,A3  ;temporary
	CMPI.B  #'A',D1
	BEQ.S   REGMOD1 ;A reg so jump
	MOVEA.L #SAVREGS,A3     ;temporary
	CMPI.B  #'D',D1
	BEQ.S   REGMOD1 ;D reg so jump
	MOVEA.L #SAV_PC,A3      ;temporary
	CMPI.B  #'P',D1
	BNE     REGME
; No command errors, so we modify the PC.
	MOVE.B  D1,D4   ;will need 'P' later
	MOVE.B  (A6)+,D1;get next char
	BSR     UP_CASE
	CMPI.B  #'C',D1 ;is it 'C'?
	BNE     REGME  ;no,so quit
	MOVE.B  D1,D3   ;will need 'C' later
	MOVE.B  (A6)+,D1;get last char
	CMPI.B  #CR,D1  ;is it CR?
	BNE     REGME  ;no,so quit
	BSR     CRLF    ;passed all tests
	MOVE.B  D4,D1   ;display the 'P'
	BSR     CHAROUT
	MOVE.B  D3,D1   ;display the 'C'
	BSR     CHAROUT
	MOVE.B  #':',D1 ;also a ':'
	BSR     CHAROUT
	BSR     SPACE   ;a ' ' looks good
	MOVE.L  (A3)+,D2;get the data in D2
	BSR     PRT_LON ;display it
	BSR     SPACE   ;another ' '
	MOVE.B  #'?',D1 ;now a '?'
	BSR     CHAROUT
	BSR     SPACE   ;one more ' '
	BSR     GETADRT ;get new data in D2
	TST.B   D6      ;check flag for CR
	BNE     REGMQ ;was FF so quit it
	MOVE.L  D2,-(A3);save it
	BRA     REGMQ ;done
;This portion modifies the A and D registers
REGMOD1 MOVE.B  D1,D4   ;save the A or D
	MOVE.B  (A6)+,D1;get register #
	CMPI.B  #'0',D1 ;within bounds?
	BMI     REGME	;< than, no good
	CMPI.B  #'7',D1
	BGT     REGME	;> than, no good
	MOVE.B  D1,D3   ;will need # later
	MOVE.B  (A6)+,D1;get last char
	CMPI.B  #CR,D1  ;is it CR?
	BNE     REGME	;no, so quit
	MOVE.B  D3,D1   ;find displacement
	ANDI.L  #$F,D1  ;remove ASCII bias
	ASL.L   #2,D1   ;multiply by 4
	ADDA.L  D1,A3   ;A3 points correctly
	MOVE.B  D4,D1   ;display 'A' or 'D'
	BSR     CHAROUT
	MOVE.B  D3,D1   ;display the #
	BSR     CHAROUT
	MOVE.B  #':',D1 ;also a ':'
	BSR     CHAROUT
	BSR     SPACE   ;a ' ' looks good
	MOVE.L  (A3)+,D2;get the data in D2
	BSR     PRT_LON ;display it
	BSR     SPACE   ;another ' '
	MOVE.B  #'?',D1 ;now a '?'
	BSR     CHAROUT
	BSR     SPACE   ;one more ' '
	BSR     GETADRT ;get new data in D2
	TST.B   D6      ;check flag for CR
	BNE     REGMQ   ;was FF so quit it
	MOVE.L  D2,-(A3);save it
;
; Added in mon209 to exit from different regmod types
REGMQ	CMPI.B	#$FF,REGTYP
	BNE	GET_CMD
	RTS
;
REGME   CMPI.B   #$FF,REGTYP
        BNE      CMDERR
	RTS
;
SERINI  MOVEA.L #CSREG,A0
	MOVE.B  #$AA,(A0)
	MOVE.B  #$40,(A0)
	MOVE.B  #$4E,(A0) ;$CE for 2 stops
	MOVE.B  #$27,(A0)
	RTS
;
; Returns Z-flag = 0 if no char.
INSTAT	MOVEM.L	D0,-(A7)
	MOVE.B  CSREG,D0   ;get status
	ANDI.B  #DAVBIT,D0 ;mask
	MOVEM.L	(A7)+,D0   ;Movem affects no flags
	RTS
;
; Returns 7-bit char in D1.B
CHARIN  BSR.S   INSTAT  ;get status
	BEQ.S   CHARIN  ;no char so loop
	MOVE.B  DREG,D1 ;get char
	ANDI.B  #$7F,D1 ;reset bit 7
	RTS
;
; Sends out char in D1.B
CHAROUT	MOVEM.L	D0,-(A7)
	MOVE.B  CSREG,D0 ;get status
	ANDI.B  #BFEBIT,D0 ;is buffer empty?
	MOVEM.L	(A7)+,D0   ;Movem affects no flags
	BEQ.S   CHAROUT ;no, so loop
	MOVE.B  D1,DREG;buffer's empty, send
	RTS
;
; This routine prints a message pointed to
; by A3. The message must end in a NULL.
PRTMSG  MOVE.B  (A3)+,D1;get a char
	BEQ.S   PRTMEX  ;quit on 0
	BSR.S   CHAROUT ;display the char
	BRA.S   PRTMSG  ;do it again
PRTMEX  RTS
;
; Inputs and echoes a character
CHARIO  BSR.S   CHARIN
	BSR.S   CHAROUT
	RTS
;
; Send out CR and LF
CRLF    MOVE.B  #CR,D1  ;send ASCII CR
	BSR.S   CHAROUT
	MOVE.B  #LF,D1  ;send ASCII LF
	BSR.S   CHAROUT
	RTS
;
; Send out a SP
SPACE   MOVE.B  #' ',D1 ;send ASCII SP
	BSR.S   CHAROUT
	RTS
;
; Send two spaces to the screen
TWO_SP  BSR.S   SPACE
	BSR.S   SPACE
	RTS
;
; Prints sign-on message
SIGN_ON MOVEA.L #HELLO,A3 ;point to 'HELLO'
	BSR.S   PRTMSG  ;send it out
	RTS
;
; Takes a byte in D2.B, converts to 2
; ASCII characters and puts them on screen.
PRT_BYT MOVE.L  D2,D1 ;init conversion reg
	ROL.B   #4,D1 ;do upper nibble first
	BSR     NUM_ASC ;convert to ASCII
	BSR.S   CHAROUT
	MOVE.L  D2,D1 ;now do lower nibble
	BSR     NUM_ASC
	BSR.S   CHAROUT ;send character
	RTS
;
; Takes a word in D2.W, converts to 4
; ASCII characters and puts them on screen.
PRT_WRD ROL.W   #8,D2   ;swap bytes in word
	BSR.S   PRT_BYT ;output MSB
	ROL.W   #8,D2   ;reswap bytes
	BSR.S   PRT_BYT ;output LSB
	RTS
;
; Takes a long word in D2.L, converts to 8
; ASCII characters and puts them on screen.
PRT_LON SWAP    D2      ;get upper 16 bits
	BSR.S   PRT_WRD ;convert 4 chars
	SWAP    D2      ;get lower 16 bits
	BSR.S   PRT_WRD
	RTS
;
; Takes a long word in D2.L, and prints the
; least significand 6 ASCII on the screen.
PRT_SIX SWAP    D2      ;get upper 16 bits
	BSR.S   PRT_BYT ;convert 4 chars
	SWAP    D2      ;get lower 16 bits
	BSR.S   PRT_WRD
	RTS
;
; Checks to see if D1.B contains a valid HEX
; digit.
VALDIG  CMPI.B  #'F',D1 ;char > 'F' ?
	BGT     DATAERR ;yes, so alert
	CMPI.B  #'0',D1 ;char < '0' ?
	BLT     DATAERR ;yes, so alert
	CMPI.B  #'9',D1 ;char < = '9'?
	BLE.S   VALDIGE ;'0' < char < '9'
	CMPI.B  #'A',D1 ;char < 'A'?
	BLT     DATAERR ;yes, so alert
VALDIGE RTS             ;'A' < char < 'F'
;
; Prints out the message "Bad Command"
; then looks for another command.
CMDERR  MOVEA.L #BADCMD,A3 ;point to message
	BRA     REPORT  ;restart monitor
;
; Prints out the message "Invalid address
; or hex data." Then it restarts monitor.
DATAERR MOVEA.L #INVDATA,A3;point to message
	BRA     REPORT  ;restart monitor
;
; Converts legit ASCII #s to BCD.
ASC_BCD SUBI.B  #$30,D1 ;remove ASCII bias
	CMPI.B  #10,D1  ;0-9?
	BMI.S   ASC_BX  ;Yes, so job's done
	SUBQ.B  #7,D1   ;remove alpha bias
ASC_BX  RTS
;
; Convert HEX digit in D1.B to ASCII
NUM_ASC ANDI.B  #$F,D1  ;reset upper nibble
	ADDI.B  #$30,D1 ;add ASCII bias
	CMPI.B  #$3A,D1 ;test if > '9'
	BMI.S   NUM_EX  ;< '9' so done
	ADDQ.B  #7,D1   ;> '9', so add 7
NUM_EX  RTS
;
; It first fills INPBUF with chars until a
; CR occurs. The chars are then examined.
; If 1st char is CR then it sets D2.B and
; quits. Else it resets D2.B and proceeds to
; change valid hex digits to ASCII numbers.
; This routine is only used by EDIT.
GET_BYT BSR     GETLIN  ;get chars from kbd
	MOVEA.L #INPBUF,A6      ;reset A6
GETB1   BSR     SKIPSP  ;get rid if spaces
	MOVE.B  (A6)+,D1;get first char
	ST      D2      ;set D2.B for now
	BSR     UP_CASE ;convert to UC
	CMPI.B  #CR,D1  ;test for CR
	BEQ.S   GETBX   ;if CR, no change
	BSR.S   VALDIG  ;valid digit?
	BSR.S   ASC_BCD ;convert into hex
	MOVE.B  D1,D2   ;save 1st digit
	MOVE.B  (A6)+,D1;get second digit
	BSR     UP_CASE
	CMPI.B  #CR,D1  ;test for CR
	BNE.S   GETB2   ;not CR, so process
	MOVE.B  D2,D1   ;reget 1st digit
	BRA.S   GETB3   ;and get out
GETB2   BSR     VALDIG  ;valid digit?
	BSR.S   ASC_BCD ;convert into hex
	ROL.B   #4,D2   ;move first digit
	ADD.B   D2,D1   ;form final result
GETB3   SF      D2      ;signal change
GETBX   RTS
;
; Gets keyboard input and transforms it into
; a longword into D2. If only a CR was typed
; then D6.B contains $FF, else it's 0.
GETADRT BSR     GETLIN  ;fill buffer
	MOVEA.L #INPBUF,A6 ;repoint A6
	ST      D6      ;set flag in D6.B
	CMPI.B  #CR,(A6) ;check 1st char
	BEQ.S   EX_ADR ;if it's CR then exit
	SF      D6  ;not CR, so reset D6.B
GETADR  BSR     SKIPSP  ;skip over SPs
	CLR.L   D1      ;init temp register
	CLR.L   D2 ;init result register
NEXTCHR MOVE.B  (A6)+,D1;get a char
	BSR     UP_CASE
	CMPI.B  #CR,D1  ;exit if CR
	BEQ.S   EX_ADR
	CMPI.B  #' ',D1 ;exit if SP
	BEQ.S   EX_ADR
	BSR     VALDIG  ;valid digit?
	BSR     ASC_BCD ;convert it to hex
	ROL.L   #4,D2   ;next digit in D2
	ANDI.B  #$F0,D2
	ADD.B   D1,D2   ;insert new digit
	BRA.S   NEXTCHR ;and continue
EX_ADR  RTS
;
; Changes chars in the range 'a'=<char<='z'
; to UC. Others are left unchanged.
UP_CASE CMPI.B  #'a',D1 ;out of range?
	BLT.S   NO_CHG  ;yes, skip out
	CMPI.B  #'z',D1 ;out of range?
	BGT.S   NO_CHG  ;yes, skip out
	SUBI.B  #' ',D1 ;In range so change
NO_CHG  RTS
;
; A6 is pointed to the input buffer. This
; routine fills the buffer with chars till
; a CR is encountered. D6 keeps count of
; the number of chars in the line for the
; purpose of the BK_SP routine only.
GETLIN  MOVEA.L #INPBUF,A6 ;point to buffer
	MOVEA.L A6,A5   ;save pointer
GETLIN2 MOVEA.L A5,A6   ;reget pointer
	CLR.B   D6      ;null char count
GETCHAR BSR     CHARIN  ;get char in D1
	CMPI.B  #CR,D1  ;CR ends it
	BEQ.S   GETCHX
	CMPI.B  #8,D1   ;BS key?
	BNE.S   GETCH1  ;no, so bypass
	TST.B   D6      ;If on 1st char,
	BEQ.S   GETCHAR ;ignore
	SUBQ.B  #1,D6   ;adjust count
	SUBQ.L  #1,A6   ;adjust pointer
	MOVEA.L #BSSPBS,A3 ;fix up screen
	BSR     PRTMSG
	BRA.S   GETCHAR ;continue
GETCH1  CMPI.B  #3,D1   ;^C scraps line
	BNE.S   GETCH2
	MOVEA.L #REDOMSG,A3 ;send CR, LF, %
	BSR     PRTMSG
	BRA.S   GETLIN2
GETCH2  MOVE.B  D1,(A6)+;okay, char->buffer
	ADDQ.B  #1,D6   ;update char count
	BSR     CHAROUT ;echo the char
	BRA.S   GETCHAR ;get another char
GETCHX  MOVE.B  D1,(A6) ;Place CR in buffer
	ADDQ.B  #1,D6   ;and count it
	BSR     CRLF    ;send a CR & LF
	RTS
;
; If not SP do nothing. If SP increment
; pointer A6 by one.
SKIPSP  CMPI.B  #' ',(A6)
	BNE.S   SKIPSPE
	ADDQ.L  #1,A6
	BRA.S   SKIPSP
SKIPSPE RTS
;
; Initializes the user registers to zeros.
NULLREG MOVEA.L #SAVREGS,A1
	MOVEA.L #ENDRAM,A2
NULLR1  CLR.B   (A1)+   ;clear them
	CMPA.L  A1,A2   ;done yet?
	BNE.S   NULLR1
	MOVE.L  #USTCK,SAV_A7
	CLR.L   UNADR
	RTS
;
; This routine saves the registers of the
; executed program for future display and
; future restoration.
REG_SAV MOVEM.L D0-D7/A0-A6,SAVREGS ;d0-a6
	MOVE.L  (A7)+,D0 ;pop ret address
	MOVE.W  (A7)+,SAV_SR    ;pop SR
	MOVE.L  SAV_PC,OLD_PC
	MOVE.L  (A7)+,SAV_PC    ;pop PC
	MOVE.L  D0,-(A7)  ;repush ret addr
	MOVE.L  USP,A5  ;get user's A7
	MOVE.L  A5,SAV_A7 ;save it
	RTS
;
; This routine restores the registers of a
; program whose execution terminates with
; either a trap #9 or some other trap put
; in place to breakpoint a program. Transfer
; to the user program is then accomplished
; with an RTE instruction.
REGREST MOVE.L  (A7)+,D0 ;pop ret address
	MOVEA.L SAV_A7,A5 ;get user's A7
	MOVE.L  A5,USP  ;restore it
	MOVE.L  SAV_PC,-(A7)    ;push PC
	MOVE.W  SAV_SR,-(A7)    ;push SR
	MOVE.L  D0,-(A7) ;repush ret addr
	MOVEM.L SAVREGS,D0-D7/A0-A6 ;d0-a6
	RTS
;
; This routine will diplay the register
; information saved by REG_SAV.
REG_PRT	BSR	PRTOLD	    ;Old PC with disassembly
REGPRT1	MOVEA.L #SAVREGS,A0 ;A0 -> reg. data
	MOVE.B  #'D',D7 ;print the D regs
	BSR     REGDISP
	MOVE.B  #'A',D7 ;print the A regs
	BSR     REGDISP
	BSR	PRTNEW
	BSR	PRTSR
	RTS
;
; Disassebly and display of the OPCODE at OLD_PC.
PRTOLD	MOVEA.L OLD_PC,A5   ;Disassem address in A5
	BSR     UNASMB      ;call unasm core routine
	MOVE.L  A5,D2       ;move instruction address
	BSR	PRT_SIX
	BSR     TWO_SP
	CLR.L   D3          ;blank spaces counter (BSC)
PRTOLD1 MOVE.W  (A5)+,D2    ;get word
	BSR     PRT_WRD     ;print word of hex code
	BSR     SPACE       ;space
	ADDQ.B  #2,D3       ;add 2 bytes to BSC
	SUBQ.B  #2,D6       ;reduce length counter by 2
	BNE.S   PRTOLD1     ;if more bytes print again
PRTOLD2 CMPI.B  #10,D3      ;is the string 10 bytes
	BGE.S	PRTOLD3
	BSR     TWO_SP
	BSR     TWO_SP
	BSR     SPACE
	ADDQ.B  #2,D3
	BRA.S   PRTOLD2
PRTOLD3	BSR     SPACE
	MOVEA.L #UASMCMD,A3 ;point A3 to unasm cmd buff
	BSR     PRTMSG      ;display commant text
	BSR     CRLF
	RTS
;
; Next PC is printed and disassembled.
PRTNEW	MOVEA.L	#PC_MSG,A3
	BSR     PRTMSG
	MOVE.L  SAV_PC,D2 ;get the register
	BSR	PRT_SIX
	MOVEA.L	#SP24MSG,A3
	BSR     PRTMSG
	MOVEA.L SAV_PC,A5
	BSR     UNASMB
	MOVEA.L #UASMCMD,A3 ;A3 -> to unasm cmd buffer
	BSR     PRTMSG      ;display command text
	BSR     CRLF
	RTS
;
REGDISP MOVE.B  #'0',D5 ;register # in here
REGD1   MOVE.B  D7,D1   ;print reg letter
	BSR     CHAROUT
	MOVE.B  D5,D1   ;print reg number
	BSR     CHAROUT
	BSR     COL_SP  ;print :, space
	MOVE.L  (A0)+,D2;print the register
	BSR     PRT_LON
	BSR     TWO_SP  ;print 2 spaces
	BSR	SPACE
	ADDQ.B  #1,D5
	CMPI.B  #'8',D5 ; D5 = '8' yet?
	BEQ.S   REGDFIN ; if yes then exit
	CMPI.B  #'4',D5 ; D5 = '4' yet?
	BNE.S   REGD1   ; no, then next reg
	BSR     CRLF    ; D5 = '4' send CRLF
	BRA.S   REGD1   ; and do next reg
REGDFIN BSR     CRLF
	RTS
;
; Print the USR
PRTSR	MOVEA.L	#SR_MSG,A3
	BSR     PRTMSG
	MOVE.W  SAV_SR,D2
	MOVE.W  D2,D4   ;copy SR to D4
	BSR     PRT_WRD ;print the register
	BSR     TWO_SP  ;print 2 spaces
; Print "Flags: X = " and X flag
	MOVEA.L #MESGFLG,A3
	BSR     PRTMSG
	MOVE.B  #'1',D1
	BTST.B  #4,D4
	BNE.S   REGETC1
	MOVE.B  #'0',D1
REGETC1 BSR     CHAROUT
;Print ", N = " and N flag
	MOVEA.L #MESGN,A3
	BSR     PRTMSG
	MOVE.B  #'1',D1
	BTST.B  #3,D4
	BNE.S   REGETC2
	MOVE.B  #'0',D1
REGETC2 BSR     CHAROUT
;Print ", Z = " and Z flag
	MOVEA.L #MESGZ,A3
	BSR     PRTMSG
	MOVE.B  #'1',D1
	BTST.B  #2,D4
	BNE.S   REGETC3
	MOVE.B  #'0',D1
REGETC3 BSR     CHAROUT
;Print ", V = " and V flag
	MOVEA.L #MESGV,A3
	BSR     PRTMSG
	MOVE.B  #'1',D1
	BTST.B  #1,D4
	BNE.S   REGETC4
	MOVE.B  #'0',D1
REGETC4 BSR     CHAROUT
;Print " C = " and C flag
	MOVEA.L #MESGC,A3
	BSR     PRTMSG
	MOVE.B  #'1',D1
	BTST.B  #0,D4
	BNE.S   REGETC5
	MOVE.B  #'0',D1
REGETC5 BSR     CHAROUT
	BSR     CRLF
	RTS
;
; Send : and space to the screen
COL_SP  MOVE.B  #':',D1
	BSR     CHAROUT
	MOVE.B  #' ',D1
	BSR     CHAROUT
	RTS
;
; Download a .HEX file in ASCII S-format.
; A .HEX file consists of pure ASCII chars.
; (See MacKenzie p.50.) The explanation
; below with typical file lines is perfectly
; general and applies to all files.
;
; The 1st line S00700007465737438 signifies:
; S0 = header line
; 07 = $7 bytes to load
; 0000 = address, in this case meaningless
; 74 65 73 74   = ASCII filename "TEST."
; 38 = hex check byte used as follows: 16
; bit check sum = 07+00+00+74+65+73+74+38=FF
;
; The following lines contain code and data.
; A typical line S10780003200428183 means:
; S1 = code line with 16 bit load address
; 07 = $7 bytes to load
; 8000 = start loading at this HEX address
; 32 00 42 81 = code or data to load
; 83 = hex check sum as above
;
; Another typical line S208AF800032004281D3
; signifies:
; S2 = code line with 24 bit load address
; 08 = $8 bytes to load
; AF8000 = start loading at this HEX address
; 32 00 42 81 = execution code to load
; D3 = hex check sum as always
;
; There are two kinds of footer line:
; The line S90380007C signifies:
; S9 = This line contains a 16-bit entry
; address, in this case 8000. The byte
; count is 03 and 7C is the check sum.
;
; The second kind of footer line is, e.g.
; S804AF8000CC signifies:
; S8 = This line contains a 24-bit entry
; address, in this case AF8000. The byte
; count is 04 and CC is the check sum.
;
; S5 lines exist too. They inform you of
; the number of lines of code in the file.
; Nothing will happen if we simply ignore
; these lines.
;
; The code directly below steers the
; loading.
LD_FILE MOVEA.L #0,A5   ;A5 holds offset address
	CMPI.B  #CR,-1(A6);Is previous CHAR a CR?
	BEQ.S   LD_FIL0 ;Yes so skip
	BSR     GETADR  ;get offset address
	MOVEA.L D2,A5   ;save for later
LD_FIL0 MOVEA.L #LS_MSG,A3;Tell'em to start
	BSR     PRTMSG  ;sending the file
LD_FIL1 BSR     CHARIN  ;Get first char
	CMPI.B  #3,D1   ;Is it ^C?
	BEQ     GET_CMD ;Yes, so abandon
	CMPI.B  #'S',D1 ;Is it 'S'?
	BEQ.S   IS_S    ;Yes, get next char
; The end of line CR and LF are handled here. If
; it's a CR then send a CRLF else get another char
	CMPI.B  #CR,D1  ;Is it CR?
	BNE.S   LD_FIL1 ;No, so dump LFs
	BSR     CRLF    ;If CR, then do CRLF
	BNE.S   LD_FIL1 ;get another char
IS_S    BSR     CHAROUT ;Print the 'S'
	BSR     CHARIO  ;get next char
	CMPI.B  #'0',D1 ;Is it '0'?
	BEQ.S   S0      ;if so branch
	SF      S2_FLG  ;Reset flag
	CMPI.B  #'1',D1 ;Is it '1'?
	BEQ.S   S12     ;It's '1' so process
	ST      S2_FLG  ;Set flag
	CMPI.B  #'2',D1 ;Is it '2'?
	BEQ.S   S12     ;It's '2' so process
	CMPI.B  #'5',D1 ;Is it '5'?
	BEQ.S   S5      ;Yes, go dump line
	ST      S2_FLG  ;Set flag
	CMPI.B  #'8',D1 ;Is it '8'?
	BEQ.S   S89     ;if so branch
	SF      S2_FLG  ;Reset flag
	CMPI.B  #'9',D1 ;Is it '9'?
	BEQ.S   S89     ;if so branch
	BRA     LD_ERR  ;None of above, err
;
; A line that begins with S0 is the header
; containing the name
S0      CLR.B   D4      ;Null hex check sum
	BSR     LD_NUM  ;line length in D2.B
	BSR     LD_ADR  ;discard 0000
	MOVEA.L #PRTBUF,A0
	CMPI.B  #1,D2   ;hex check byte yet?
	BEQ.S   S0B ;jump if there's no name
S0A     MOVE.L  D2,-(A7) ;push line length
	BSR     LD_NUM  ;get a name char
	MOVE.B  D2,D1
	MOVE.L  (A7)+,D2;pop line length
	BSR     UP_CASE ;change to UC
	MOVE.B  D1,(A0)+;store it
	SUBQ.B  #1,D2   ;length counter = 1?
	CMPI.B  #1,D2   ;hex check byte yet?
	BNE.S   S0A     ;if not then loop
S0B     CLR.B   (A0)    ;end name with NULL
	BSR     LD_CHK  ;branch chk
	BRA     LD_FIL1 ;Go to next line
;
; Loads an S1 or S2 line
S12     CLR.B   D4      ;Null hex check sum
	BSR     LD_NUM  ;line length in D2.B
	BSR     LD_ADR  ;line address in A4
	ADDA.L  A5,A4   ;Add offset to address
	BSR     LD_DATA ;load data
	BRA     LD_FIL1 ;Go to next line
;
; Discard all chars in the S5 line
S5      BSR     LD_NUM  ;line length in D2.B
	ADD.B   D2,D2   ;double it and add 2
	ADDQ.B  #2,D2   ;to discard the CRLF
S5A     BSR     CHARIO  ;Input and echo char
	SUBQ.B  #1,d2
	BNE.S   S5A
	BRA     LD_FIL1 ;Go to next line
;
; End of file line. Its data is used to
; change the value of the user PC. Works
; with S8 and S9 lines.
S89     CLR.B   D4      ;Null hex check sum
	BSR     LD_NUM  ;line length in D2.B
	BSR     LD_ADR  ;load address in A4
	MOVE.L  A4,SAV_PC       ;save it
	CMPA.L  #0,A4
	BEQ.S   S89A
	MOVE.L  A4,UNADR
	MOVE.L  A4,DUMPADR
S89A    BSR     LD_CHK
	BSR     CHARIO  ;read the final CR
	BSR     CHARIO  ;and LF
	BSR	CRLF
	MOVEA.L #PRTBUF,A3;print file name
	BSR     PRTMSG
	MOVEA.L #LG_MSG,A3      ;print
	BSR     PRTMSG  ;successful load
	BRA     GET_CMD ;go to prompt
;
; Reads and echos the two ASCII bytes repre-
; senting a number and converts them to a HEX
; number in D2.B. Thus a '2' & 'E' is conver-
; ted to $2E. Also updates checksum in D4.B
LD_NUM  BSR     CHARIO  ;get first char
	BSR     ASC_BCD ;convert it to BCD
	ROL.B   #4,D1   ;move it to MSB
	MOVE.B  D1,D2   ;copy to reg D2
	BSR     CHARIO  ;get second char
	BSR     ASC_BCD ;convert it to hex
	ADD.B   D1,D2   ;add them
	ADD.B   D2,D4   ;update check sum
	RTS
;
; Routine to extract 16 or 24 bit address
; from S-file into A4. The line count in D2.B
; represents the # of words in the S-line.
; The address info takes 2 or 3 words so the
; line count is reduced by 2 or 3 at routine's
; end. Also updates checksum in D4.B
LD_ADR  CLR.L   D3      ;D3.L = 0
	MOVE.W  #3,D5   ;Get set for 4 times
	TST.B   S2_FLG  ;See if set
	BEQ.S   LD_AD1  ;Not set, so skip
	ADDQ.W  #2,D5   ;Change to 6 times
LD_AD1  ROL.L   #4,D3   ;move it up a nibble
	BSR     CHARIO  ;Get char & convert
	BSR     ASC_BCD ;to hex in D1.B
	ADD.B   D1,D3   ;Add it to D3.B and
	DBRA    D5,LD_AD1 ;Loop 4 or 6 times
	MOVEA.L D3,A4   ;Put address in A4
	ADD.B   D3,D4   ;Update check sum
	ROL.W   #8,D3   ;for both bytes in
	ADD.B   D3,D4   ;D3.W
	SWAP    D3      ;Update 3rd byte too
	ADD.B   D3,D4   ;Checksum now in D4.B
	SUBQ.B  #2,D2   ;line counter-2
	TST.B   S2_FLG  ;If not set, skip
	BEQ.S   LD_AD2  ;Set, so do one more
	SUBQ.B  #1,D2   ;subtraction
LD_AD2  RTS
;
; Loads, into RAM, data in a HEX file whose
; line begins with S1 or S2. D2 holds the
; byte count and A4 the loading address. Also
; updates checksum which is finally checked
; by the routine that follows.
LD_DATA CMPI.B  #1,D2   ;At check byte?
	BEQ.S   LD_CHK  ;Yes, jump
	BSR     CHARIO  ;get char
	BSR     ASC_BCD ;convert to hex
	ROL.B   #4,D1   ;move it to MSB
	MOVE.B  D1,D3   ;copy to reg D3
	BSR     CHARIO  ;get second char
	BSR     ASC_BCD ;convert it to hex
	ADD.B   D1,D3   ;add them
	MOVE.B  D3,(A4)+;move to load addr
	ADD.B   D3,D4   ;update check sum
	SUBQ.B  #1,D2   ;decr. line counter
	BRA.S   LD_DATA ;Go for more
; Gets the last byte in an S line. If check
; sum is not 0FFH it flags an error.
LD_CHK  BSR     CHARIO  ;get char
	BSR     ASC_BCD ;convert it to hex
	ROL.B   #4,D1   ;move it to MSB
	MOVE.B  D1,D3   ;copy to reg D3
	BSR     CHARIO  ;get second char
	BSR     ASC_BCD ;convert it to hex
	ADD.B   D1,D3   ;add them
	ADD.B   D3,D4   ;should = 0FFH
	ADDQ.B  #1,D4   ;Should be 0
	BNE.S   LD_ERR  ;Not 0, so flag it
	RTS
;
; Flags loading error and goes to GET_CMD
LD_ERR  MOVEA.L #LE_MSG,A3 ;get message ptr
	BRA     REPORT  ;restart monitor
;
; Routine that initializes the tracing
BEG_TRC CMPI.B  #CR,-1(A6);is previous CR?
	BEQ.S   BEG1    ;yes, so start
	BSR     GETADR  ;get execution addr
	MOVE.L  D2,SAV_PC       ;save it
BEG1    BSR     REGREST ;restore user regs
	ORI.W   #$8000,SR   ;enable tracing
	RTE
;
; If the SKIPFLG is set then jump to TRACE5, else
; proceed normally. In the regular trace no tracing
; is done on the 1st pass. If a TRAP instruction is
; next then tracing is terminated. Tracing continues
; when a CR is typed. Any other chararacter causes
; termination of tracing. The FP_FLG is 0 in entry.
TRACE   BSR     REG_SAV ;save USER registers
	TST.B   FP_FLG  ;is flag = 0?
	BNE.S   TRACE0  ;no, so continue
	ST      FP_FLG  ;it was 0, so set it
	BRA.S   TRACE4  ;do nothing this time
TRACE0  TST.B   SKIPFLG ;If not 0
	BNE.S   TRACE5  ;then jump
	BSR     REG_PRT ;display them
; Check if TRAP is the next instruction.
	MOVEA.L SAV_PC,A0
	CMPI.W  #$4E4F,(A0)     ;> TRAP #15?
	BGT.S   TRACE1          ;you're okay
	CMPI.W  #$4E40,(A0)     ;< TRAP #0?
	BLT.S   TRACE1          ;okay again
	MOVEA.L #TRC_MSG,A3
	BSR     PRTMSG
	BRA.S   TRACE2
; Check for CHARIN. If CR then keep tracing.
TRACE1	MOVE.B  #'>',D1
	BSR     CHAROUT
	BSR     CHARIN
	CMPI.B  #CR,D1
	BEQ.S   TRACE3
	BSR     CHAROUT	; If R modify register
	BSR     UP_CASE	; <<<< Added in mon209 >>>>
	CMPI.B  #'R',D1	; <<<< Added in mon209 >>>>
	BEQ.S   TRACE6	; <<<< Added in mon209 >>>>
; Turn off all tracing and put out prompt.
TRACE2  ANDI.W  #$7FFF,SR  ;disable tracing
	ORI.W   #$2000,SR  ;enable supervisor
	ANDI.W  #$7FFF,SAV_SR;fix the USR
	SF      FP_FLG  ;clear flag
	BRA     GET_CMD
; Continue tracing
TRACE3  BSR     CRLF
TRACE4  ANDI.W  #$0FFF,SAV_SR;enable user
	ORI.W   #$8000,SAV_SR;enable tracing
	BSR     REGREST
	RTE
;
; TRACE saved the USER registers. This means
; that the return address of the routine
; that called GOSKIP is next on the stack.
TRACE5  ANDI.W  #$7FFF,SR  ;disable tracing
	ORI.W   #$2000,SR  ;enable supervisor
	ANDI.W  #$7FFF,SAV_SR;fix the USR
	SF      SKIPFLG ;clear flag
	SF      FP_FLG  ;clear flag
	RTS     ;pick up where you left off
;
; <<<< Added in mon209 >>>>
; Get register to be modified then
; set register value
TRACE6  BSR	GETLIN
	MOVEA.L #INPBUF,A6	;point to buffer
	MOVE.B	#$0FF,REGTYP
	BSR    REGMOD0
	BRA    TRACE1
;
; Set (at most two) permanent breakpoints.
; B<ENT> displays the current breakpoints.
; B 1 <address> sets breakpoint 1.
; B 1<ENT> clears breakpoint 1.
BREAK   CMPI.B  #CR,-1(A6);is previous CR?
	BEQ.S   DSPBRK
; get breakpoint number in D2.L
	MOVEA.L #BP_AD3,A0
	CMPI.B  #'1',(A6);is char a '1'?
	BEQ.S   BREAK1  ;no, then go on
	MOVEA.L #BP_AD4,A0
BREAK1  ADDQ.L  #1,A6   ;point past #
	CMPI.B  #CR,(A6);is it a CR?
	BNE.S   BREAK2
	CLR.L   (A0)
	BRA.S   BREAK3
BREAK2  BSR     GETADR
	MOVE.L  D2,(A0) ;save it
BREAK3  BRA     GET_CMD
;
;Deal with 1st breakpoint first.
DSPBRK  MOVEA.L #MSG_8,A3 ;breakpoint 1:
	BSR     PRTMSG
	MOVEA.L #BP_AD3,A0 ;A0 -> #BP_AD3
	TST.L   (A0)
	BNE.S   DSPBRK1
	MOVEA.L #MSG_10,A3
	BSR     PRTMSG
	BRA.S   DSPBRK2
DSPBRK1 MOVE.L  (A0),D2
	BSR     PRT_SIX
;Deal with 2nd breakpoint next.
DSPBRK2 MOVEA.L #MSG_9,A3 ;breakpoint 1:
	BSR     PRTMSG
	MOVEA.L #BP_AD4,A0 ;A0 -> #BP_AD3
	TST.L   (A0)
	BNE.S   DSPBRK3
	MOVEA.L #MSG_10,A3
	BSR     PRTMSG
	BRA.S   DSPBRK4
DSPBRK3 MOVE.L  (A0),D2
	BSR     PRT_SIX
DSPBRK4 BRA     GET_CMD
;
; Finds and prints the sum and difference
; of 2 HEX numbers
HEXCALC BSR     GETADR  ;get first number
	MOVE.L  D2,D3   ;move it to D3
	BSR     GETADR  ;get second number
	MOVE.L  D2,D4   ;make a spare in D4
	ADD.L   D3,D2   ;add them
	MOVEA.L #HS_MSG,A3
	BSR     PRTMSG  ;print sum msg
	BSR     PRT_LON ;print sum
	MOVE.L  D4,D2   ;reload original D2
	SUB.L   D2,D3   ;subtract them
	MOVE.L  D3,D2   ;move to D2 to print
	MOVEA.L #HD_MSG,A3
	BSR     PRTMSG  ;print diff msg
	BSR     PRT_LON ;print difference
	BRA     GET_CMD ;put out prompt
;
;****************************************************
;Begin Unassemble Routines
;****************************************************
;
;First get the disassembly start address and # of lines
UNASM   MOVE.B  #10,D7  ;Prepare to do 10 lines
	CMPI.B  #CR,-1(A6);is previous CR?
	BNE.S   UNASMS1   ;no, so proceed
	MOVE.L  UNADR,D2  ;get old disassebly addr
	MOVEA.L D2,A5     ;into A5
	BRA.S   UNASMS3   ;stick with 10 lines & go on
UNASMS1 CMPI.B  #',',(A6);is char a comma?
	BNE.S   USM1    ;no, then get start address
	MOVE.L  UNADR,D2  ;get old disassebly addr
	MOVEA.L D2,A5     ;into A5
	ADDQ.L  #1,A6   ;point past comma
	BRA.S   UNASMS2 ;get count
USM1    BSR     GETADR  ;get start address into D2
	MOVEA.L D2,A5   ;and put into A5
	CMPI.B  #CR,-1(A6)  ;is previous CR?
	BNE.S   UNASMS2     ;no, so proceed
	BRA.S   UNASMS3
UNASMS2 BSR     GETADR      ;get # of lines to display
	MOVE.B  D2,D7
;Command line is totally parsed, so do the disassembly
UNASMS3 BSR     UNASMB      ;call unasm core routine
	MOVE.L  A5,D2       ;move instruction address
	BSR     PRT_SIX     ;into D2 and print it
	BSR     TWO_SP      ;two space
	CLR.L   D3          ;blank spaces counter (BSC)
UNASMS4 MOVE.W  (A5)+,D2    ;get word
	BSR     PRT_WRD     ;print word of hex code
	BSR     SPACE       ;space
	ADDQ.B  #2,D3       ;add 2 bytes to BSC
	SUBQ.B  #2,D6       ;reduce length counter by 2
	BNE.S   UNASMS4     ;if more bytes print again
UNASMS5 CMPI.B  #10,D3      ;is the string 10 bytes
	BGE.S   UNASMS6
	BSR     TWO_SP
	BSR     TWO_SP
	BSR     SPACE
	ADDQ.B  #2,D3
	BRA.S   UNASMS5
UNASMS6 BSR     SPACE       ;space
	MOVEA.L #UASMCMD,A3 ;point A3 to unasm cmd buff
	BSR     PRTMSG      ;display commant text
	BSR     CRLF
	SUBQ.B  #1,D7
	BNE.S   UNASMS3
	MOVE.L  A5,UNADR
	BRA     GET_CMD
;
; 32 bytes of ram are reserved above the stacks
; for the text of the disassembled command.
; UNASMCMD points to the beginning and
; UNASMOPR points 9 characters in, so the operands
; are always evenly spaced. The text is ternminated
; with a zero and can be displayed with a call to
; PRTMSG.
;
;example
;12345678901234567890123456789012
;MOVE.B  #$01,D0
;^       ^
;|       |---UNASMOPR
;|
;|------UNASMCMD
;
; Disasemble routine. When called, A5 points to code.
; Use of Registers
; D0-Varies              A0-Varies
; D1-Varies              A1-Varies
; D2-Varies              A2-Varies
; D3-Varies              A3-Varies
; D4-cmd size (B,W,L)    A4-Instruction text buffer
; D5-instruction hex (W) A5-Ptr. to 1st byte of code
; D6-instr lngth (bytes) A6-Varies
; D7-loop count          A7-stack
;
UNASMB  MOVE.W  (A5),D5    ;D5 gets 1st byte of code
	MOVE.L  #2,D6  ;D6 will have # of bytes in code
	MOVEA.L #UASMCMD,A4 ;A4 -> to unasm cmd buff
;
	MOVE.B  #32,D1    ;Prefill UASMCMD with 32 ' 's
UNASML  MOVE.B  #' ',(A4)+
	SUBQ.B  #1,D1
	BNE.S   UNASML
;
	MOVEA.L #UASMCMD,A4 ;Repoint A4
	BSR     UNSEAR ;Returns with A3 -> matching cmd
	MOVEA.L 10(A3),A1   ;put sub-routine addr in A1
	ADDQ.L  #4,A3       ;point A3 to inst txt
UNASM1  MOVE.B  (A3)+,D1    ;get a char
	BEQ.S   UNASM2      ;stop on 0
	MOVE.B  D1,(A4)+    ;move to cmd buff
	BRA.S   UNASM1      ;do it again
UNASM2  JSR     (A1)        ;run sub-routine
	CLR.B   (A4)+       ;end cmd text with zero
	RTS
;
; This routine searches through the list of commands
; UNINSTR, comparing to the code. When a match is
; found, the routine returns with A3 pointing to it.
UNSEAR  MOVEA.L #UNINSTR,A3     ;point A3 to first cmd
UNSEAR0 MOVE.W  D5,D0   ;Get opcode into D0
	AND.W   2(A3),D0;AND opcode word with mask
	CMP.W   (A3),D0 ;CMP result with stored word
	BEQ.S   UNSEARE ;Same, so done
	ADDA.L  #14,A3  ;Test failed, so try next one
	BRA.S   UNSEAR0
UNSEARE RTS
;
; The following subroutines are for the specific
; commands. They all follow a similar format.
; First, if need be, move the length info to the end
; of the instruction, i.e. (.B, .L, .W). Next shift A4
; to UNASMOPR, then find the operands.
;
;for commands with no operands
U00     RTS
;
; ILLEGAL adds AL to end of instruction
U01     MOVE.B  #'A',(A4)+
	MOVE.B  #'L',(A4)+
	RTS
;
; ADD, SUB, AND, EOR, OR, CMP
U02     CLR.L   D0
	MOVE.B  #7,D0
	BSR     USZ
	MOVEA.L #UASMOPR,A4
	MOVE.B  #8,D0
	BTST    D0,D5
	BEQ.S   U02_01
	MOVE.B  #'D',(A4)+
	MOVE.B  #11,D0
	BSR     UREG
	MOVE.B  #',',(A4)+
	BSR     UEA
	BRA.S   U02_02
U02_01  BSR     UEA
	MOVE.B  #',',(A4)+
	MOVE.B  #'D',(A4)+
	MOVE.B  #11,D0
	BSR     UREG
U02_02  RTS
;
; ADDA, SUBA, CMPA
U03     CLR.L   D0
	MOVE.B  #8,D0
	BTST    D0,D5
	BEQ.S   U03_01
	MOVE.B  #'.',(A4)+
	MOVE.B  #'L',(A4)+
	MOVE.B  #' ',(A4)+
	MOVE.B  #'L',D4
	BRA.S   U03_02
U03_01  MOVE.B  #'.',(A4)+
	MOVE.B  #'W',(A4)+
	MOVE.B  #' ',(A4)+
	MOVE.B  #'W',D4
U03_02  MOVEA.L #UASMOPR,A4
	BSR     UEA
	MOVE.B  #',',(A4)+
	MOVE.B  #'A',(A4)+
	MOVE.B  #11,D0
	BSR     UREG
	RTS
;
; ADDX, SUBX
U04     CLR.L   D0
	MOVE.B  #7,D0
	BSR     USZ
	MOVEA.L #UASMOPR,A4
	MOVE.B  #3,D0
	BTST    D0,D5
	BEQ.S   U04_01
	MOVE.B  #'-',(A4)+
	MOVE.B  #'(',(A4)+
	MOVE.B  #'A',(A4)+
	MOVE.B  #2,D0
	BSR     UREG
	MOVE.B  #')',(A4)+
	MOVE.B  #',',(A4)+
	MOVE.B  #'-',(A4)+
	MOVE.B  #'(',(A4)+
	MOVE.B  #'A',(A4)+
	MOVE.B  #11,D0
	BSR     UREG
	MOVE.B  #')',(A4)+
	BRA.S   U04_02
U04_01  MOVE.B  #'D',(A4)+
	MOVE.B  #2,D0
	BSR     UREG
	MOVE.B  #',',(A4)+
	MOVE.B  #'D',(A4)+
	MOVE.B  #11,D0
	BSR     UREG
U04_02  RTS
;
; CMPM
U05     CLR.L   D0
	MOVE.B  #7,D0
	BSR     USZ
	MOVEA.L #UASMOPR,A4
	MOVE.B  #'(',(A4)+
	MOVE.B  #'A',(A4)+
	MOVE.B  #02,D0
	BSR     UREG
	MOVE.B  #')',(A4)+
	MOVE.B  #'+',(A4)+
	MOVE.B  #',',(A4)+
	MOVE.B  #'(',(A4)+
	MOVE.B  #'A',(A4)+
	MOVE.B  #11,D0
	BSR     UREG
	MOVE.B  #')',(A4)+
	MOVE.B  #'+',(A4)+
	RTS
;
; DIVU, DIVS, MULU, MULS
U06     CLR.L   D0
	MOVE.B  #'W',D4
	MOVEA.L #UASMOPR,A4
	BSR     UEA
	MOVE.B  #',',(A4)+
	MOVE.B  #'D',(A4)+
	MOVE.B  #11,D0
	BSR     UREG
	RTS
;
; ASL, ASR, LSL, LSR, ROXL, ROXR, ROL, ROR
; memory shifts
U07     CLR.L   D0
	MOVE.B  #8,D0   ;check direction
	BTST    D0,D5
	BEQ.S   U07_01
	MOVE.B  #'L',(A4)+
	BRA.S   U07_02
U07_01  MOVE.B  #'R',(A4)+
U07_02  MOVE.B  #'.',(A4)+
	MOVE.B  #'W',(A4)+
	MOVE.B  #'W',D4
	MOVEA.L #UASMOPR,A4
	BSR     UEA
	RTS
;
; ASL, ASR, LSL, LSR, ROXL, ROXR, ROL, ROR
; register shifts
U08     CLR.L   D0
	MOVE.B  #8,D0   ;check direction
	BTST    D0,D5
	BEQ.S   U08_01
	MOVE.B  #'L',(A4)+
	BRA.S   U08_02
U08_01  MOVE.B  #'R',(A4)+
U08_02  MOVE.B  #7,D0
	BSR     USZ
	MOVEA.L #UASMOPR,A4
	MOVE.B  #5,D0
	BTST    D0,D5   ;i/r = 0 then count is within
	BEQ.S   U08_03  ;bits 9,10,11 so jump
	MOVE.B  #'D',(A4)+ ;i/r = 1 so count is in Dn
	MOVE.B  #11,D0
	BSR     UREG
	BRA.S   U08_08
U08_03  MOVE.B  #'#',(A4)+ ;Store a # symbol
	MOVE.W  D5,D1   ;Don't trash D5
	MOVE.L  #9,D0   ;Put shift size in D0
	LSR.W   D0,D1   ;Move shift-count bits down 9
	ANDI.B  #7,D1   ;Mask out unwanted stuff
	BNE.S   U08_06  ;If not 0 then it's ready
	MOVE.B  #8,D1   ;If 0 replace with 8
U08_06  ADDI.B  #'0',D1 ;Add the 30H to D1
	MOVE.B  D1,(A4)+        ;Store it
U08_08  MOVE.B  #',',(A4)+      ;Add a ','
	MOVE.B  #'D',(A4)+      ;Now add a 'D'
	MOVE.L  #2,D0   ;Point to register bits
	BSR     UREG
	RTS
;
; ANDI, ORI, EORI to CCR
U09     CLR.L   D0
	MOVE.B  #'.',(A4)+
	MOVE.B  #'B',(A4)+
	MOVEA.L #UASMOPR,A4
	MOVE.B  #'#',(A4)+
	MOVE.B  #'$',(A4)+
	MOVE.W  0(A5,D6.L),D1
	BSR     UGBYT
	ADDQ.B  #2,D6
	MOVE.B  #',',(A4)+
	MOVE.B  #'C',(A4)+
	MOVE.B  #'C',(A4)+
	MOVE.B  #'R',(A4)+
	RTS
;
; ANDI, ORI, EORI to SR
U10     CLR.L   D0
	MOVE.B  #'.',(A4)+
	MOVE.B  #'W',(A4)+
	MOVE.B  #'L',D4
	MOVEA.L #UASMOPR,A4
	MOVE.B  #'#',(A4)+
	MOVE.B  #'$',(A4)+
	MOVE.W  0(A5,D6.L),D1
	ROL.W   #8,D1
	BSR     UGBYT
	MOVE.W  0(A5,D6.L),D1
	BSR     UGBYT
	ADDQ.B  #2,D6
	MOVE.B  #',',(A4)+
	MOVE.B  #'S',(A4)+
	MOVE.B  #'R',(A4)+
	RTS
;
; ADDI, ANDI, ORI, EORI, SUBI, CMPI
U11     CLR.L   D0
	MOVE.B  #7,D0
	BSR     USZ
	MOVEA.L #UASMOPR,A4
	MOVE.B  #'#',(A4)+
	MOVE.B  #'$',(A4)+
	CMPI.B  #'B',D4
	BNE.S   U11_01
	MOVE.W  0(A5,D6.L),D1
	BSR     UGBYT
	ADDQ.B  #2,D6
	BRA.S   U11_03
U11_01  CMPI.B  #'W',D4
	BNE.S   U11_02
	MOVE.W  0(A5,D6.L),D1
	ROL.W   #8,D1
	BSR     UGBYT
	MOVE.W  0(A5,D6.L),D1
	BSR     UGBYT
	ADDQ.B  #2,D6
	BRA.S   U11_03
U11_02  MOVE.W  0(A5,D6.L),D1
	ROL.W   #8,D1
	BSR     UGBYT
	MOVE.W  0(A5,D6.L),D1
	BSR     UGBYT
	MOVE.W  2(A5,D6.L),D1
	ROL.W   #8,D1
	BSR     UGBYT
	MOVE.W  2(A5,D6.L),D1
	BSR     UGBYT
	ADDQ.B  #4,D6
U11_03  MOVE.B  #',',(A4)+
	BSR     UEA
	RTS
;
; BRA, BSR
U12     CLR.L   D0
	CMPI.B  #0,D5
	BEQ.S   U12_00
	MOVE.B  #'.',(A4)+
	MOVE.B  #'S',(A4)+
U12_00  MOVEA.L #UASMOPR,A4
	MOVE.B  #'$',(A4)+
	MOVE.L  A5,D1
	ADDQ.L  #2,D1
	CMPI.B  #0,D5
	BEQ.S   U12_01
	CMPI.B  #$FF,D5
	BEQ.S   U12_02
	MOVE.B  D5,D0
	ADD.B   D0,D1
	BRA.S   U12_03
U12_01  MOVE.W  0(A5,D6.L),D0
	ADD.W   D0,D1
	ADDQ.B  #2,D6
	BRA.S   U12_03
U12_02  MOVE.L  0(A5,D6.L),D0
	ADD.L   D0,D1
	ADDQ.B  #4,D6
U12_03  MOVE.B  #4,D0
U12_04  ROL.L   #8,D1
	BSR     UGBYT
	SUBQ.B  #1,D0
	BNE.S   U12_04
	RTS
;
; JMP, JSR
U13     MOVEA.L #UASMOPR,A4
	BSR     UEA
	RTS
;
; BTST, BCHG, BCLR, BSET immediate data. These don't
; need .B or .L. If the destination is a data register
; then it's automatically .L, otherwise it's always .B
U14     MOVE.B  #'B',D4
	MOVEA.L #UASMOPR,A4
	MOVE.B  #'#',(A4)+
	MOVE.B  #'$',(A4)+
	MOVE.W  0(A5,D6.L),D1
	BSR     UGBYT ;Change imm data to ASCII & store
	ADDQ.B  #2,D6
	MOVE.B  #',',(A4)+
	BSR     UEA
	RTS
;
; BTST, BCHG, BCLR, BSET
; register data
U15     CLR.L   D0
	MOVE.B  #'L',D4
	MOVEA.L #UASMOPR,A4
	MOVE.B  #'D',(A4)+
	MOVE.B  #11,D0
	BSR     UREG
	MOVE.B  #',',(A4)+
	BSR     UEA
	RTS
;
; MOVE
U16     CLR.L   D0
	MOVE.B  #13,D0
	BSR     USZM
	MOVEA.L #UASMOPR,A4
	BSR     UEA
	MOVE.B  #',',(A4)+
	MOVE.L  D5,-(A7)    ;<<< these lines
	MOVE.W  D5,D0       ;flip destination addr.
	ROL.W   #7,D5       ;RRRMMM to MMMRRR format
	AND.W   #7,D5       ;in EA location
	ROR.W   #3,D0
	ANDI.W  #$38,D0
	ADD.W   D0,D5
	BSR     UEA         ;<<<< end flip
	MOVE.L  (A7)+,D5    ;get back D5
	RTS
;
; MOVEA
U17     CLR.L   D0
	MOVE.B  #13,D0
	BSR     USZM
	MOVEA.L #UASMOPR,A4
	BSR     UEA
	MOVE.B  #',',(A4)+
	MOVE.B  #'A',(A4)+
	MOVE.B  #11,D0
	BSR     UREG
	RTS
;
; Bcc
U18     MOVE.L  #8,D0
	BSR     UCC
	BSR     U12     ;bsr routine
	RTS
;
; DBcc
U19     MOVE.L  #8,D0
	BSR     UCC
	MOVEA.L #UASMOPR,A4
	MOVE.B  #'D',(A4)+
	MOVE.B  #2,D0
	BSR     UREG
	MOVE.B  #',',(A4)+
	MOVE.B  #'$',(A4)+
	MOVE.L  A5,D1
	ADDQ.L  #2,D1
	MOVE.W  0(A5,D6.L),D0
	ADD.W   D0,D1
	ADDQ.B  #2,D6
	MOVE.B  #4,D0
U19_01  ROL.L   #8,D1
	BSR     UGBYT
	SUBQ.B  #1,D0
	BNE.S   U19_01
	RTS
;
; Scc
U20     MOVE.L  #8,D0
	BSR     UCC
	MOVE.B  #'B',D4
	MOVEA.L #UASMOPR,A4
	MOVE.B  #'B',D4
	BSR     UEA
	RTS
;
; NEGX, CLR, NEG, NOT, TST
U21     CLR.L   D0
	MOVE.B  #7,D0
	BSR     USZ
	MOVEA.L #UASMOPR,A4
	BSR     UEA
	RTS
;
; TAS
U22     CLR.L   D0
	MOVE.B  #'B',D4
	MOVEA.L #UASMOPR,A4
	BSR     UEA
	RTS
;
; SWAP
U23     CLR.L   D0
	MOVEA.L #UASMOPR,A4
	MOVE.B  #'D',(A4)+
	MOVE.B  #2,D0
	BSR     UREG
	RTS
;
; UNLK
U24     CLR.L   D0
	MOVEA.L #UASMOPR,A4
	MOVE.B  #'A',(A4)+
	MOVE.B  #2,D0
	BSR     UREG
	RTS
;
; LINK
U25     MOVEA.L #UASMOPR,A4
	MOVE.B  #'A',(A4)+
	MOVE.B  #11,D0
	BSR     UREG
	MOVE.B  #',',(A4)+
	MOVE.B  #'#',(A4)+
	MOVE.B  #'$',(A4)+
	MOVE.W  0(A5,D6.L),D1
	ADDQ.B  #2,D6
	MOVE.B  #2,D0
U25_01  ROL.W   #8,D1
	BSR     UGBYT
	SUBQ.B  #1,D0
	BNE.S   U25_01
	RTS
;
; ABCD, SBCD
U26     CLR.L   D0      ;Mnemonic is already in buffer
	MOVEA.L #UASMOPR,A4 ;A4 -> to argument storage
	BTST    #3,D5   ;D5 contains the hex opcode
	BNE.S   U26_01
	MOVEA.L #UASMOPR,A4
	MOVE.B  #'D',(A4)+
	MOVE.B  #2,D0
	BSR     UREG
	MOVE.B  #',',(A4)+
	MOVE.B  #'D',(A4)+
	MOVE.B  #11,D0
	BSR     UREG
	BRA.S   U26_02
U26_01  MOVE.B  #'-',(A4)+
	MOVE.B  #'(',(A4)+
	MOVE.B  #'A',(A4)+
	MOVE.B  #02,D0
	BSR     UREG
	MOVE.B  #')',(A4)+
	MOVE.B  #',',(A4)+
	MOVE.B  #'-',(A4)+
	MOVE.B  #'(',(A4)+
	MOVE.B  #'A',(A4)+
	MOVE.B  #11,D0
	BSR     UREG
	MOVE.B  #')',(A4)+
U26_02  RTS
;
; ADDQ, SUBQ
U27     CLR.L   D0
	MOVE.B  #7,D0
	BSR     USZ
	MOVEA.L #UASMOPR,A4
	MOVE.B  #'#',(A4)+
	MOVE.B  #'$',(A4)+
	MOVE.L  D5,-(A7)    ;get back D5
	ROL.W   #7,D5
	AND.W   #7,D5
	ADDI.B  #$30,D5
	MOVE.B  D5,(A4)+
	MOVE.L  (A7)+,D5    ;get back D5
	MOVE.B  #',',(A4)+
	BSR     UEA
	RTS
;
; CHK
U28     CLR.L   D0
	MOVE.B  #'W',D4
	MOVEA.L #UASMOPR,A4
	BSR     UEA
	MOVE.B  #',',(A4)+
	MOVE.B  #'D',(A4)+
	MOVE.B  #11,D0
	BSR     UREG
	RTS
;
; EXG Dn,Dm. It's always long.
U29DD   CLR.L   D0
	MOVEA.L #UASMOPR,A4
	MOVE.B  #'D',(A4)+
	MOVE.B  #11,D0
	BSR     UREG
	MOVE.B  #',',(A4)+
	MOVE.B  #'D',(A4)+
	MOVE.B  #2,D0
	BSR     UREG
	RTS
;
; EXG An,Am. It's always long.
U29AA   CLR.L   D0
	MOVEA.L #UASMOPR,A4
	MOVE.B  #'A',(A4)+
	MOVE.B  #11,D0
	BSR     UREG
	MOVE.B  #',',(A4)+
	MOVE.B  #'A',(A4)+
	MOVE.B  #2,D0
	BSR     UREG
	RTS
;
; EXG. It's always long.
U29DA   CLR.L   D0
	MOVEA.L #UASMOPR,A4
	MOVE.B  #'D',(A4)+
	MOVE.B  #11,D0
	BSR     UREG
	MOVE.B  #',',(A4)+
	MOVE.B  #'A',(A4)+
	MOVE.B  #2,D0
	BSR     UREG
	RTS
;
; EXT
U30     CLR.L   D0
	MOVE.B  #'.',(A4)+
	BTST    #6,D5
	BEQ.S   U30_01
	MOVE.B  #'L',(A4)+
	BRA.S   U30_02
U30_01  MOVE.B  #'W',(A4)+
U30_02  MOVEA.L #UASMOPR,A4
	MOVE.B  #'D',(A4)+
	MOVE.B  #2,D0
	BSR     UREG
	RTS
;
; LEA
U31     CLR.L   D0
	MOVE.B  #'.',(A4)+
; D5 contains the instruction word
	BTST    #0,D5
	BNE.S   U31A
	MOVE.B  #'W',(A4)+
	MOVE.B  #'W',D4
	BRA.S	U31B
U31A	MOVE.B  #'L',(A4)+
	MOVE.B  #'L',D4
U31B	MOVEA.L #UASMOPR,A4
	BSR     UEA
	MOVE.B  #',',(A4)+
	MOVE.B  #'A',(A4)+
	MOVE.B  #11,D0
	BSR     UREG
	RTS
;
; NBCD
U32     MOVE.B  #'B',D4
	MOVEA.L #UASMOPR,A4
	BSR     UEA
	RTS
;
; PEA
U33     MOVE.B  #'L',D4
	MOVEA.L #UASMOPR,A4
	BSR     UEA
	RTS
;
; STOP
U34     MOVEA.L #UASMOPR,A4
	MOVE.B  #'#',(A4)+
	MOVE.B  #'$',(A4)+
	MOVE.W  $00(A5,D6.L),D1
	ROL.W   #8,D1
	BSR     UGBYT
	MOVE.W  0(A5,D6.L),D1
	BSR     UGBYT
	ADDQ.B  #2,D6
	RTS
;
; TRAP
U35     MOVEA.L #UASMOPR,A4
	MOVE.B  #'#',(A4)+
	MOVE.B  #'$',(A4)+
	MOVE.B  D5,D1
	BSR     NUM_ASC
	MOVE.B  D1,(A4)+
	RTS
;
; MOVE TO CCR
U36     MOVE.B  #'.',(A4)+
	MOVE.B  #'W',(A4)+
	MOVE.B  #'W',D4
	MOVEA.L #UASMOPR,A4
	BSR     UEA
	MOVE.B  #',',(A4)+
	MOVE.B  #'C',(A4)+
	MOVE.B  #'C',(A4)+
	MOVE.B  #'R',(A4)+
	RTS
;
; MOVE from SR
U37     MOVE.B  #'.',(A4)+
	MOVE.B  #'W',(A4)+
	MOVE.B  #'W',D4
	MOVEA.L #UASMOPR,A4
	MOVE.B  #'S',(A4)+
	MOVE.B  #'R',(A4)+
	MOVE.B  #',',(A4)+
	BSR     UEA
	RTS
;
; MOVE to SR
U38     MOVE.B  #'.',(A4)+
	MOVE.B  #'W',(A4)+
	MOVE.B  #'W',D4
	MOVEA.L #UASMOPR,A4
	BSR     UEA
	MOVE.B  #',',(A4)+
	MOVE.B  #'S',(A4)+
	MOVE.B  #'R',(A4)+
	RTS
;
; MOVE An <-> USP
U39     MOVE.B  #'.',(A4)+
	MOVE.B  #'L',(A4)+
	MOVEA.L #UASMOPR,A4
	BTST    #3,D5
	BEQ.S   U39_01
	MOVE.B  #'U',(A4)+
	MOVE.B  #'S',(A4)+
	MOVE.B  #'P',(A4)+
	MOVE.B  #',',(A4)+
	MOVE.B  #'A',(A4)+
	MOVE.B  #2,D0
	BSR     UREG
	BRA.S   U39_02
U39_01  MOVE.B  #'A',(A4)+
	MOVE.B  #2,D0
	BSR     UREG
	MOVE.B  #',',(A4)+
	MOVE.B  #'U',(A4)+
	MOVE.B  #'S',(A4)+
	MOVE.B  #'P',(A4)+
U39_02  RTS
;
; MOVEQ
U40     MOVE.B  #'.',(A4)+
	MOVE.B  #'L',(A4)+
	MOVEA.L #UASMOPR,A4
	MOVE.B  #'#',(A4)+
	MOVE.B  #'$',(A4)+
	MOVE.B  D5,D1
	BSR     UGBYT
	MOVE.B  #',',(A4)+
	MOVE.B  #'D',(A4)+
	MOVE.B  #11,D0
	BSR     UREG
	RTS
;
; MOVEP
U41     BTST    #6,D5
	BEQ.S   U41_01
	MOVE.B  #'.',(A4)+
	MOVE.B  #'L',(A4)+
	BRA.S   U41_02
U41_01  MOVE.B  #'.',(A4)+
	MOVE.B  #'W',(A4)+
U41_02  MOVEA.L #UASMOPR,A4
	BTST    #7,D5
	BEQ.S   U41_03  ;If 0 then it's d(Ay),Dx
	MOVE.B  #'D',(A4)+ ;It's 1 so do Dx,d(Ay)
	MOVE.B  #11,D0  ;point to bit 11 and put in
	BSR     UREG    ;place the data register #
	MOVE.B  #',',(A4)+
	BSR     DOIT
	BRA.S   U41_04
U41_03  BSR     DOIT
	MOVE.B  #',',(A4)+
	MOVE.B  #'D',(A4)+
	MOVE.B  #11,D0
	BSR     UREG
U41_04  RTS
;
DOIT    MOVE.B  #'$',(A4)+
	MOVE.W  $00(A5,D6.L),D1
	ROL.W   #8,D1
	BSR     UGBYT
	MOVE.W  0(A5,D6.L),D1
	BSR     UGBYT
	ADDQ.B  #2,D6
	MOVE.B  #'(',(A4)+
	MOVE.B  #'A',(A4)+
	MOVEQ   #2,D0
	BSR     UREG
	MOVE.B  #')',(A4)+
	RTS
;
; MOVEM
U42     BTST    #6,D5
	BEQ.S   U42_01
	MOVE.B  #'.',(A4)+
	MOVE.B  #'L',(A4)+
	BRA.S   U42_02
U42_01  MOVE.B  #'.',(A4)+
	MOVE.B  #'W',(A4)+
U42_02  MOVEA.L #UASMOPR,A4
	MOVE.W  2(A5),D3
U42_03  BTST    #5,D5
	BEQ.S   U42_04
	BTST    #4,D5
	BNE.S   U42_04
	BTST    #3,D5
	BNE.S   U42_04
	CLR.L   D0
	CLR.L   D2
	MOVE.W  #$F,D1
U42_06  BTST    D1,D3
	BEQ.S   U42_05
	BSET    D0,D2
U42_05  ADDQ.B  #1,D0
	SUBQ.B  #1,D1
	CMPI.B  #$F,D0
	BLE.S   U42_06
	MOVE.W  D2,D3
U42_04  MOVE.B  #10,D0
	BTST    D0,D5
	BEQ.S   U42_07
	BSR     UEA
	MOVE.B  #',',(A4)+
	MOVE.B  #'D',D2
	ADDQ.B  #2,D6
	BSR     UM
	MOVE.W  D3,D1
	ROL.W   #8,D3
	CMPI.W  #$100,D1
	BLT.S   U42_10
	AND.W   #$FF,D1
	CMPI.W  #1,D1
	BLT.S   U42_10
	MOVE.B  #'/',(A4)+
U42_10  MOVE.B  #'A',D2
	BSR     UM
	BRA.S   U42_08
U42_07  MOVE.B  #'D',D2
	ADDQ.B  #2,D6
	BSR     UM
	MOVE.W  D3,D1
	ROL.W   #8,D3
	CMPI.W  #$100,D1
	BLT.S   U42_09
	AND.W   #$FF,D1
	CMPI.W  #1,D1
	BLT.S   U42_09
	MOVE.B  #'/',(A4)+
U42_09  MOVE.B  #'A',D2
	BSR     UM
	MOVE.B  #',',(A4)+
	BSR     UEA
U42_08  RTS
;
; Tests effective address field
; D0 points to first bit of <EA>
; D4.B is length of cmd  'B','W','L'
; moves result to cmd line (A4)
; <EA> format MMMRRR
UEA     CLR.L   D0
	MOVE.B  #05,D0
	BTST    D0,D5      ;check first bit XMM
	BEQ     UEA0       ;is 0MM, jmp
	SUBQ.B  #1,D0
	BTST    D0,D5      ;check second bit 1XM
	BEQ     UEA1       ;is 10M, jmp
	SUBQ.B  #1,D0
	BTST    D0,D5      ;check third bit 11X
	BEQ     UEA2       ;is 110, jmp
	SUBQ.B  #1,D0      ;<<<<<<<< 111-RRR
	BTST    D0,D5      ;test register bits
	BEQ.S   UEA7       ;is 0RR, jmp
	MOVE.B  #'#',(A4)+ ;<<<<<<<< 111-100 #<data>
	MOVE.B  #'$',(A4)+
	CMPI.B  #'B',D4
	BNE.S   UEA11
	MOVE.W  2(A5),D1
	BSR     UGBYT
	ADDQ.B  #2,D6
	BRA     UEAD    ;go to RTS
;
UEA11   CMPI.B  #'W',D4
	BNE.S   UEA12
	MOVE.W  0(A5,D6.L),D1
	ROL.W   #8,D1
	BSR     UGBYT
	MOVE.W  0(A5,D6.L),D1
	BSR     UGBYT
	ADDQ.B  #2,D6
	BRA     UEAD
UEA12   MOVE.W  $00(A5,D6.L),D1
	ROL.W   #8,D1
	BSR     UGBYT
	MOVE.W  0(A5,D6.L),D1
	BSR     UGBYT
	MOVE.W  2(A5,D6.L),D1
	ROL.W   #8,D1
	BSR     UGBYT
	MOVE.W  2(A5,D6.L),D1
	BSR     UGBYT
	ADDQ.B  #4,D6
	BRA     UEAD
;
UEA7    SUBQ.B  #1,D0
	BTST    D0,D5      ;test register bits
	BEQ     UEA8       ;is 00R, jmp
	SUBQ.B  #1,D0
	BTST    D0,D5
	BEQ.S   UEA9       ;is 010, jmp
	MOVE.B  #'$',(A4)+ ;<<<<<<<< 111-011 (d8,PC,Xn)
	MOVE.W  2(A5),D1
	BSR     UGBYT
	ADDQ.B  #2,D6
	MOVE.B  #'(',(A4)+
	MOVE.B  #'P',(A4)+
	MOVE.B  #'C',(A4)+
	MOVE.B  #',',(A4)+
	MOVE.W  2(A5),D1
	MOVE.B  #15,D0
	BTST    D0,D1
	BEQ.S   UEA17
	MOVE.B  #'A',(A4)+
	BRA.S   UEA18
UEA17   MOVE.B  #'D',(A4)+
UEA18   SUBQ.B  #1,D0
	MOVE.L  D5,D3
	MOVE.W  2(A5),D5
	BSR     UREG
	MOVE.L  D3,D5
	MOVE.B  #'.',(A4)+
	MOVE.B  #11,D0
	BTST    D0,D1
	BEQ.S   UEA19
	MOVE.B  #'L',(A4)+
	BRA.S   UEA20
UEA19   MOVE.B  #'W',(A4)+
UEA20   MOVE.B  #')',(A4)+
	BRA     UEAD    ;go to RTS
;
UEA9    MOVE.B  #'$',(A4)+ ;<<<<<<<< 111-010 (d16,PC)
	MOVE.W  0(A5,D6.L),D1
	ROL.W   #8,D1
	BSR     UGBYT
	MOVE.W  0(A5,D6.L),D1
	BSR     UGBYT
	ADDQ.B  #2,D6
	MOVE.B  #'(',(A4)+
	MOVE.B  #'P',(A4)+
	MOVE.B  #'C',(A4)+
	MOVE.B  #')',(A4)+
	BRA     UEAD    ;go to RTS
;
UEA8    SUBQ.B  #1,D0
	BTST    D0,D5
	BEQ.S   UEA10      ;is 000, jmp
	MOVE.B  #'$',(A4)+ ;<<<<<<<< 111-001 (xxx).L
	MOVE.W  $00(A5,D6.L),D1
	ROL.W   #8,D1
	BSR     UGBYT
	MOVE.W  0(A5,D6.L),D1
	BSR     UGBYT
	MOVE.W  2(A5,D6.L),D1
	ROL.W   #8,D1
	BSR     UGBYT
	MOVE.W  2(A5,D6.L),D1
	BSR     UGBYT
	ADDQ.B  #4,D6
	BRA     UEAD
;
UEA10   MOVE.B  #'$',(A4)+ ;<<<<<<<< 111-000 (xxx).W
	MOVE.W  0(A5,D6.L),D1
	ROL.W   #8,D1
	BSR     UGBYT
	MOVE.W  0(A5,D6.L),D1
	BSR     UGBYT
	ADDQ.B  #2,D6
	BRA     UEAD
UEA2    MOVE.B  #'$',(A4)+ ;<<<<<<<< 110 (d8,An,Xn)
	MOVE.W  2(A5),D1
	BSR     UGBYT
	ADDQ.B  #2,D6
	MOVE.B  #'(',(A4)+
	MOVE.B  #'A',(A4)+
	SUBQ.B  #1,D0
	BSR     UREG
	MOVE.B  #',',(A4)+
	MOVE.W  2(A5),D1
	MOVE.B  #15,D0
	BTST    D0,D1
	BEQ.S   UEA13
	MOVE.B  #'A',(A4)+
	BRA.S   UEA14
UEA13   MOVE.B  #'D',(A4)+
UEA14   SUBQ.B  #1,D0
	MOVE.L  D5,D3
	MOVE.W  2(A5),D5
	BSR     UREG
	MOVE.L  D3,D5
	MOVE.B  #'.',(A4)+
	MOVE.B  #11,D0
	BTST    D0,D1
	BEQ.S   UEA15
	MOVE.B  #'L',(A4)+
	BRA.S   UEA16
UEA15   MOVE.B  #'W',(A4)+
UEA16   MOVE.B  #')',(A4)+
	BRA     UEAD
;
UEA1    SUBQ.B  #1,D0
	BTST    D0,D5      ;check third bit 10X
	BEQ.S   UEA3       ;is 100, jmp
UEA1A   MOVE.B  #'$',(A4)+ ;<<<<<<<< 101 (d16,An)
	MOVE.W  $00(A5,D6.L),D1
	ROL.W   #8,D1
	BSR     UGBYT
	MOVE.W  0(A5,D6.L),D1
	BSR     UGBYT
	ADDQ.B  #2,D6
	MOVE.B  #'(',(A4)+
	MOVE.B  #'A',(A4)+
	SUBQ.B  #1,D0
	BSR     UREG
	MOVE.B  #')',(A4)+
	BRA.S   UEAD
;
UEA3    MOVE.B  #'-',(A4)+ ;<<<<<<<< 100 -(An)
	MOVE.B  #'(',(A4)+
	MOVE.B  #'A',(A4)+
	SUBQ.B  #1,D0
	BSR     UREG
	MOVE.B  #')',(A4)+
	BRA.S   UEAD
;
UEA0    SUBQ.B  #1,D0
	BTST    D0,D5      ;check second bit 0XM
	BEQ.S   UEA4       ;is 00M, jmp
	SUBQ.B  #1,D0
	BTST    D0,D5      ;check third bit 01X
	BEQ.S   UEA5       ;is 010, jmp
	MOVE.B  #'(',(A4)+ ;<<<<<<<< 011 (An)+
	MOVE.B  #'A',(A4)+
	SUBQ.B  #1,D0
	BSR     UREG
	MOVE.B  #')',(A4)+
	MOVE.B  #'+',(A4)+
	BRA.S   UEAD
;
UEA5    MOVE.B  #'(',(A4)+ ;<<<<<<<< 010 (An)
	MOVE.B  #'A',(A4)+
	SUBQ.B  #1,D0
	BSR     UREG
	MOVE.B  #')',(A4)+
	BRA.S   UEAD
;
UEA4    SUBQ.B  #1,D0
	BTST    D0,D5      ;check third bit 00X
	BEQ.S   UEA6       ;is 000, jmp
	MOVE.B  #'A',(A4)+ ;<<<<<<<< 001 An
	SUBQ.B  #1,D0
	BSR     UREG
	BRA.S   UEAD
;
UEA6    MOVE.B  #'D',(A4)+ ;<<<<<<<< 000 Dn
	SUBQ.B  #1,D0
	BSR     UREG
	BRA     UEAD
UEAD    RTS
;
; Gets the register number and adds it to printout
; buffer. D0.B points to MSB of register in OPCODE.
; A4 points to next place in printout buffer.
UREG    MOVE.W  D5,D1   ;Don't trash D5
	SUBI.B  #2,D0   ;Point D0 to lowest bit
	ANDI.L  #$FF,D0 ;Reset the upper 3 bytes in D0
	BEQ.S   UREG1   ;If shift size is 0 then skip
	LSR.W   D0,D1   ;Shift down the register num
UREG1   ANDI.B  #7,D1   ;Mask out irrelevant bits
	ADDI.B  #'0',D1 ;Add 30H to convert to ASCII
	MOVE.B  D1,(A4)+        ;Store it
	RTS
;
; Converts byte in D1.B to ASCII and moves it to
; cmd line
UGBYT   MOVE.L  D1,D2 ;init conversion reg
	ROL.B   #4,D1 ;do upper nibble first
	BSR     NUM_ASC ;convert to ASCII
	MOVE.B  D1,(A4)+
	MOVE.L  D2,D1 ;now do lower nibble
	BSR     NUM_ASC
	MOVE.B  D1,(A4)+
	MOVE.L  D2,D1
	RTS
;
; cmd size. 00=byte 01=word 10=long
; moves .B, .W or .L to cmd line
; D0 points to first size bit
; also moves L or W or B to D4
USZ     BTST    D0,D5
	BEQ.S   USZ1
	MOVE.B  #'.',(A4)+
	MOVE.B  #'L',(A4)+
	MOVE.B  #'L',D4
	BRA.S   USZE
USZ1    SUBQ.B  #1,D0
	BTST    D0,D5
	BEQ.S   USZ2
	MOVE.B  #'.',(A4)+
	MOVE.B  #'W',(A4)+
	MOVE.B  #'W',D4
	BRA.S   USZE
USZ2    MOVE.B  #'.',(A4)+
	MOVE.B  #'B',(A4)+
	MOVE.B  #'B',D4
USZE    RTS
;
; cmd size for move 01=byte 11=word 10=long
; moves .B, .W or .L to cmd line
; D0 points to first size bit
; also moves L or W or B to D4
USZM    BTST    D0,D5
	BNE.S   USZM1
	MOVE.B  #'.',(A4)+
	MOVE.B  #'B',(A4)+
	MOVE.B  #'B',D4
	BRA.S   USZME
USZM1   SUBQ.B  #1,D0
	BTST    D0,D5
	BEQ.S   USZM2
	MOVE.B  #'.',(A4)+
	MOVE.B  #'W',(A4)+
	MOVE.B  #'W',D4
	BRA.S   USZME
USZM2   MOVE.B  #'.',(A4)+
	MOVE.B  #'L',(A4)+
	MOVE.B  #'L',D4
USZME   RTS
;
; Condition codes routine
; D0 contains nubmber of bits to roll
UCC     MOVE.W  D5,D1
	ROR.W   D0,D1
	AND.L   #$F,D1
	MULU.W  #2,D1
	MOVEA.L #UCCLST,A0
	MOVE.B  0(A0,D1.L),(A4)+
	MOVE.B  1(A0,D1.L),(A4)+
	RTS
;
; <<<<<< Fixed in mon209 >>>>>>
; Routine for move multiple.
; D3 contains byte in X7-X0 format
; D2 contains letter (ie A,D)
UM	CLR.L   D0
	MOVE.B  #$FF,D1
UM00	BTST.L  D0,D3
	BNE     UM01
	ADDI.B  #$01,D0
	CMPI.B  #$08,D0
	BEQ     UME
	BRA     UM00
UM01	MOVE.B  D0,D1
	BSR     UMP
	ADDI.B  #$01,D0
	CMPI.B  #$08,D0
	BEQ     UME
	BTST.L  D0,D3
	BNE     UM02
	ADDI.B  #$01,D0
	CMPI.B  #$08,D0
	BEQ     UME
	BRA     UM03
UM02	MOVE.B  D0,D1
	ADDI.B  #$01,D0
	CMPI.B  #$08,D0
	BEQ     UME
	BTST.L  D0,D3
	BNE     UM02
	MOVE.B  #'-',(A4)+
	BSR     UMP
	ADDI.B  #$01,D0
	CMPI.B  #$08,D0
	BEQ     UME
UM03	BTST.L  D0,D3
	BNE     UM04
	ADDI.B  #$01,D0
	CMPI.B  #$08,D0
	BEQ     UME
	BRA     UM03
UM04	MOVE.B  #'/',(A4)+
	BRA	  UM01
UME	CMPI.B  #$FF,D1
	BEQ	  UME0
	BSR     UMP
UME0	RTS
UMP	MOVE.B  D2,(A4)+
	ADDI.B  #$30,D1
	MOVE.B  D1,(A4)+
	MOVE.B  #$FF,D1
	RTS
;
;****************************************************
;End Unassemble Routines
;****************************************************
;
HELP    MOVEA.L #H_MSG1,A3      ;help menu
	BSR     PRTMSG  ;now the help menu
	BRA     GET_CMD
;
BUSERR  BSR     CLR_BK  ;clear the bkpts
	MOVEA.L #MSG_1,A3
	BRA	REPORT
;
; The address error exception stores more infomation
; than other exceptions. 8 additonal bytes are pushed
; to the stack before the SR and PC so a modified
; version of REG_SAV is used.
ADDERR  MOVEM.L D0-D7/A0-A6,SAVREGS ;d0-a6
	ADDA.L  #$08,A7
	MOVE.W  (A7)+,SAV_SR    ;pop SR
	MOVE.L  (A7)+,SAV_PC    ;pop PC (It points to
                                ;next instruction)
	MOVE.L  USP,A5  ;get user's A7
	MOVE.L  A5,SAV_A7 ;save it
	MOVEA.L #MSG_2,A3;point to message
	BSR     PRTMSG
	MOVE.L  SAV_PC,D2 ;get user PC value
	BSR     PRT_SIX
	BSR     CRLF
	BSR     CLR_BK  ;clear the bkpts
	BRA     GET_CMD ;all done
;
ILEGAL  BSR     REG_SAV
	MOVEA.L #MSG_3,A3;point to message
	BSR     PRTMSG
	MOVE.L  SAV_PC,D2 ;get user PC value (illegal instruction)
	BSR     PRT_SIX
	ADDQ.L	#2,D2	;skip a longword in SAV_PC
	MOVE.L  D2,SAV_PC
	SF      FP_FLG  ;clear flag
	BSR     CRLF
	BSR     CLR_BK  ;clear the bkpts
	BRA     GET_CMD ;all done
;
DIVZERO BSR     REG_SAV
	MOVEA.L #MSG_4,A3;point to message
	BSR     PRTMSG
	MOVE.L  SAV_PC,D2 ;get user PC value (next instruction)
	BSR     PRT_SIX
	BSR     CRLF
	BSR     CLR_BK  ;clear the bkpts
	BRA     GET_CMD ;all done
;
LINE_A  BSR     REG_SAV
	MOVEA.L #MSG_A,A3;point to message
	BSR     PRTMSG
	MOVE.L  SAV_PC,D2 ;get user PC value (illegal instruction)
	BSR     PRT_SIX
	ADDQ.L	#2,D2	;skip a longword in SAV_PC
	MOVE.L  D2,SAV_PC
	SF      FP_FLG  ;clear flag
	BSR     CRLF
	BSR     CLR_BK  ;clear the bkpts
	BRA     GET_CMD ;all done
;
LINE_F  BSR     REG_SAV
	MOVEA.L #MSG_F,A3;point to message
	BSR     PRTMSG
	MOVE.L  SAV_PC,D2 ;get user PC value (illegal instruction)
	BSR     PRT_SIX
	ADDQ.L	#2,D2	;skip a longword in SAV_PC
	MOVE.L  D2,SAV_PC
	BSR     CRLF
	SF      FP_FLG  ;clear flag
	BSR     CLR_BK  ;clear the bkpts
	BRA     GET_CMD ;all done
;
TRAP_V  BSR     CLR_BK  ;clear the bkpts
	MOVEA.L #MSG_5,A3
	BRA.S   REPORT
;
PRIVIOL BSR     CLR_BK  ;clear the bkpts
	MOVEA.L #MSG_6,A3
	BRA.S   REPORT
;
LEVEL_7 BSR     CLR_BK  ;clear the bkpts
	MOVEA.L #MSG_7,A3
REPORT  BSR     CRLF
	BSR     PRTMSG  ;now the help menu
	BSR     CRLF
	BRA     GET_CMD
;
TO_CHARIN       BSR     CHARIN
		RTE
;
TO_CHAROUT      BSR     CHAROUT
		RTE
;
TO_CRLF         BSR     CRLF
		RTE
;
TO_PRTMSG       BSR     PRTMSG
		RTE
;
TO_PRT_BYT      BSR     PRT_BYT
		RTE
;
TO_PRT_WRD      BSR     PRT_WRD
		RTE
;
TO_PRT_LON      BSR     PRT_LON
		RTE
;
TO_GET_BYT      BSR     GET_BYT
		RTE
;
TO_GETADR       BSR     GETADRT
		RTE
;
;******************************************************
; Begin Unassemble of Instructions. Each entry is in
; the following format: The 1st word is the opcode
; with all variable bits made 0. The 2nd word is
; the mask consisting of all 1's in the bit positions
; in which the instruction is fully defined and 0's
; in the positions in which the bits can change. Next
; are 6 ASCII bytes of null-padded instruction text.
; Next is one long word pointing to the subroutine
; that handles the disassembly of the opcode.
; The order of the commands is extremely important.
; The most specific commands, those that have more
; ones bits in their mask, must come first. With each
; instruction you'll find the bit count of its mask.
;
; HEX opcode examples
;-----------------------------------------------------
; NOP This instruction is fully defined
; BITS (X's for variable bits)         0100111001110001
; 1st word (X bits converted to 0)     0100111001110001
; 2nd word (The mask, see CMPA below)  1111111111111111
; Mask bit count of ones = 16
;
; CMPA
; BITS (X's for variable bits)         1011XXXX11XXXXXX
; 1st word (X bits converted to 0)     1011000011000000
; 2nd word (Defined bits = 1, X = 0)   1111000011000000
; Mask bit count of ones = 6
;
;******************************************************
UNINSTR
; Instructions with 1st nibble = 0000.
; ORI to CCR. Number of bits in mask = (16)
	DC.W    $3C,$FFFF
	DC.B    'ORI',0,0,0
	DC.L    U09
; ORI to SR (16)
	DC.W    $7C,$FFFF
	DC.B    'ORI',0,0,0
	DC.L    U10
; ANDI to CCR (16)
	DC.W    $23C,$FFFF
	DC.B    'ANDI',0,0
	DC.L    U09
; ANDI to SR (16)
	DC.W    $27C,$FFFF
	DC.B    'ANDI',0,0
	DC.L    U10
; EORI to CCR (16)
	DC.W    $A3C,$FFFF
	DC.B    'EORI',0,0
	DC.L    U09
; EORI to SR (16)
	DC.W    $A7C,$FFFF
	DC.B    'EORI',0,0
	DC.L    U10
; BTST (10)
	DC.W    $800,$FFC0
	DC.B    'BTST',0,0
	DC.L    U14
; BCHG (10)
	DC.W    $840,$FFC0
	DC.B    'BCHG',0,0
	DC.L    U14
; BCLR (10)
	DC.W    $880,$FFC0
	DC.B    'BCLR',0,0
	DC.L    U14
; BSET (10)
	DC.W    $8C0,$FFC0
	DC.B    'BSET',0,0
	DC.L    U14
; Ordinary ORI (8)
	DC.W    $0,$FF00
	DC.B    'ORI',0,0,0
	DC.L    U11
; Ordinary ANDI (8)
	DC.W    $200,$FF00
	DC.B    'ANDI',0,0
	DC.L    U11
; SUBI (8)
	DC.W    $400,$FF00
	DC.B    'SUBI',0,0
	DC.L    U11
; ADDI (8)
	DC.W    $600,$FF00
	DC.B    'ADDI',0,0
	DC.L    U11
; Ordinary EORI (8)
	DC.W    $A00,$FF00
	DC.B    'EORI',0,0
	DC.L    U11
; CMPI (8)
	DC.W    $C00,$FF00
	DC.B    'CMPI',0,0
	DC.L    U11
; MOVEP (8)
	DC.W    $108,$F138
	DC.B    'MOVEP',0
	DC.L    U41
; BTST (7)
	DC.W    $100,$F1C0
	DC.B    'BTST',0,0
	DC.L    U15
; BCHG (7)
	DC.W    $140,$F1C0
	DC.B    'BCHG',0,0
	DC.L    U15
; BCLR (7)
	DC.W    $180,$F1C0
	DC.B    'BCLR',0,0
	DC.L    U15
; BSET (7)
	DC.W    $1C0,$F1C0
	DC.B    'BSET',0,0
	DC.L    U15
; MOVEA (5)
	DC.W    $40,$C1C0
	DC.B    'MOVEA',0
	DC.L    U17
; MOVE (2)
	DC.W    $0,$C000
	DC.B    'MOVE',0,0
	DC.L    U16
; Instructions with 1st nibble = 0100
; ILLEGAL (16)
	DC.W    $4AFC,$FFFF
	DC.B    'ILLEG',0
	DC.L    U01
; RESET (16)
	DC.W    $4E70,$FFFF
	DC.B    'RESET',0
	DC.L    U00
; NOP (16)
	DC.W    $4E71,$FFFF
	DC.B    'NOP',0,0,0
	DC.L    U00
; STOP (16)
	DC.W    $4E72,$FFFF
	DC.B    'STOP',0,0
	DC.L    U34
; RTE (16)
	DC.W    $4E73,$FFFF
	DC.B    'RTE',0,0,0
	DC.L    U00
; RTS (16)
	DC.W    $4E75,$FFFF
	DC.B    'RTS',0,0,0
	DC.L    U00
; TRAPV (16)
	DC.W    $4E76,$FFFF
	DC.B    'TRAPV',0
	DC.L    U00
; RTR (16)
	DC.W    $4E77,$FFFF
	DC.B    'RTR',0,0,0
	DC.L    U00
; SWAP (13)
	DC.W    $4840,$FFF8
	DC.B    'SWAP',0,0
	DC.L    U23
; LINK (13)
	DC.W    $4E50,$FFF8
	DC.B    'LINK',0,0
	DC.L    U25
; UNLK (13)
	DC.W    $4E58,$FFF8
	DC.B    'UNLK',0,0
	DC.L    U24
; MOVE An <-> USP (12)
	DC.W    $4E60,$FFF0
	DC.B    'MOVE',0,0
	DC.L    U39
; TRAP (12)
	DC.W    $4E40,$FFF0
	DC.B    'TRAP',0,0
	DC.L    U35
; JSR (12)
	DC.W    $4E80,$FFC0
	DC.B    'JSR',0,0,0
	DC.L    U13
; JMP (12)
	DC.W    $4EC0,$FFC0
	DC.B    'JMP',0,0,0
	DC.L    U13
; EXT (11)
	DC.W    $4880,$FEB8
	DC.B    'EXT',0,0,0
	DC.L    U30
; MOVE from SR (10)
	DC.W    $40C0,$FFC0
	DC.B    'MOVE',0,0
	DC.L    U37
; MOVE to CCR (10)
	DC.W    $44C0,$FFC0
	DC.B    'MOVE',0,0
	DC.L    U36
; MOVE to SR (10)
	DC.W    $46C0,$FFC0
	DC.B    'MOVE',0,0
	DC.L    U38
; NBCD (10)
	DC.W    $4800,$FFC0
	DC.B    'NBCD',0,0
	DC.L    U32
; PEA (10)
	DC.W    $4840,$FFC0
	DC.B    'PEA',0,0,0
	DC.L    U33
; TAS (10)
	DC.W    $4AC0,$FFC0
	DC.B    'TAS',0,0,0
	DC.L    U22
; NEGX (8)
	DC.W    $4000,$FF00
	DC.B    'NEGX',0,0
	DC.L    U21
; CLR (8)
	DC.W    $4200,$FF00
	DC.B    'CLR',0,0,0
	DC.L    U21
; NEG (8)
	DC.W    $4400,$FF00
	DC.B    'NEG',0,0,0
	DC.L    U21
; NOT (8)
	DC.W    $4600,$FF00
	DC.B    'NOT',0,0,0
	DC.L    U21
; TST (8)
	DC.W    $4A00,$FF00
	DC.B    'TST',0,0,0
	DC.L    U21
; MOVEM (8)
	DC.W    $4880,$FB80
	DC.B    'MOVEM',0
	DC.L    U42
; LEA (7)
	DC.W    $41C0,$F1C0
	DC.B    'LEA',0,0,0
	DC.L    U31
; CHK (5)
	DC.W    $4000,$F040
	DC.B    'CHK',0,0,0
	DC.L    U28
; Instructions with 1st nibble = 0101
; DBcc (9)
	DC.W    $50C8,$F0F8
	DC.B    'DB',0,0,0,0
	DC.L    U19
; Scc (6)
	DC.W    $50C0,$F0C0
	DC.B    'S',0,0,0,0,0
	DC.L    U20
; ADDQ (5)
	DC.W    $5000,$F100
	DC.B    'ADDQ',0,0
	DC.L    U27
; SUBQ (5)
	DC.W    $5100,$F100
	DC.B    'SUBQ',0,0
	DC.L    U27
; Instructions with 1st nibble = 0110
; BRA (8)
	DC.W    $6000,$FF00
	DC.B    'BRA',0,0,0
	DC.L    U12
; BSR (8)
	DC.W    $6100,$FF00
	DC.B    'BSR',0,0,0
	DC.L    U12
; Bcc (4)
	DC.W    $6000,$F000
	DC.B    'B',0,0,0,0,0
	DC.L    U18
; Instructions with 1st nibble = 0111
; MOVEQ (5)
	DC.W    $7000,$F100
	DC.B    'MOVEQ',0
	DC.L    U40
; Instructions with 1st nibble = 1000
; SBCD (9)
	DC.W    $8100,$F1F0
	DC.B    'SBCD',0,0
	DC.L    U26
; DIVU (7)
	DC.W    $80C0,$F1C0
	DC.B    'DIVU',0,0
	DC.L    U06
; DIVS (7)
	DC.W    $81C0,$F1C0
	DC.B    'DIVS',0,0
	DC.L    U06
; OR (4)
	DC.W    $8000,$F000
	DC.B    'OR',0,0,0,0
	DC.L    U02
; Instructions with 1st nibble = 1001
; SUBX (7)
	DC.W    $9100,$F130
	DC.B    'SUBX',0,0
	DC.L    U04
; SUBA (6)
	DC.W    $90C0,$F0C0
	DC.B    'SUBA',0,0
	DC.L    U03
; SUB (4)
	DC.W    $9000,$F000
	DC.B    'SUB',0,0,0
	DC.L    U02
; Instructions with 1st nibble = 1011
; CMPM (8)
	DC.W    $B108,$F138
	DC.B    'CMPM',0,0
	DC.L    U05
; CMPA (6)
	DC.W    $B0C0,$F0C0
	DC.B    'CMPA',0,0
	DC.L    U03
; EOR (5)
	DC.W    $B100,$F100
	DC.B    'EOR',0,0,0
	DC.L    U02
; CMP (4)
	DC.W    $B000,$F000
	DC.B    'CMP',0,0,0
	DC.L    U02
; Instructions with 1st nibble = 1100
; EXG  Dn,Dm. (10)
	DC.W    $C140,$F1F8
	DC.B    'EXG',0,0,0
	DC.L    U29DD
; EXG  An,Am. (10)
	DC.W    $C148,$F1F8
	DC.B    'EXG',0,0,0
	DC.L    U29AA
; EXG  Dn,An. (10)
	DC.W    $C188,$F1F8
	DC.B    'EXG',0,0,0
	DC.L    U29DA
; ABCD (9)
	DC.W    $C100,$F1F0
	DC.B    'ABCD',0,0
	DC.L    U26
; MULS (7)
	DC.W    $C1C0,$F1C0
	DC.B    'MULS',0,0
	DC.L    U06
; MULU (7)
	DC.W    $C0C0,$F1C0
	DC.B    'MULU',0,0
	DC.L    U06
; AND (4)
	DC.W    $C000,$F000
	DC.B    'AND',0,0,0
	DC.L    U02
; Instructions with 1st nibble = 1101
; ADDX (7)
	DC.W    $D100,$F130
	DC.B    'ADDX',0,0
	DC.L    U04
; ADDA (6)
	DC.W    $D0C0,$F0C0
	DC.B    'ADDA',0,0
	DC.L    U03
; ADD (4)
	DC.W    $D000,$F000
	DC.B    'ADD',0,0,0
	DC.L    U02
; Instructions with 1st nibble = 1110
; ASL and ASR mem shifts (9)
	DC.W    $E0C0,$FEC0
	DC.B    'AS',0,0,0,0
	DC.L    U07
; LSL and LSR mem shifts (9)
	DC.W    $E2C0,$FEC0
	DC.B    'LS',0,0,0,0
	DC.L    U07
; ROXL and ROXR mem shifts (9)
	DC.W    $E4C0,$FEC0
	DC.B    'ROX',0,0,0
	DC.L    U07
; ROL and ROR mem shifts (9)
	DC.W    $E6C0,$FEC0
	DC.B    'RO',0,0,0,0
	DC.L    U07
; ASL and ASR reg shifts (6)
	DC.W    $E000,$F018
	DC.B    'AS',0,0,0,0
	DC.L    U08
; LSL and LSR reg shifts (6)
	DC.W    $E008,$F018
	DC.B    'LS',0,0,0,0
	DC.L    U08
; ROXL and ROXR reg shifts (6)
	DC.W    $E010,$F018
	DC.B    'ROX',0,0,0
	DC.L    U08
; ROL and ROR reg shifts (6)
	DC.W    $E018,$F018
	DC.B    'RO',0,0,0,0
	DC.L    U08
; This is the 'I have no idea' entry.
	DC.W    0,0
	DC.B    '?????',0
	DC.L    U00
;
UCCLST  DC.B    'T '
	DC.B    'F '
	DC.B    'HI'
	DC.B    'LS'
	DC.B    'CC'
	DC.B    'CS'
	DC.B    'NE'
	DC.B    'EQ'
	DC.B    'VC'
	DC.B    'VS'
	DC.B    'PL'
	DC.B    'MI'
	DC.B    'GE'
	DC.B    'LT'
	DC.B    'GT'
	DC.B    'LE'
;
;***************************************************
;End Unassemble Instructions
;***************************************************
;
; Vectors to the command line routines
CMD_ADR DC.L    DUMP ;DUMP execution address
	DC.L    GO
	DC.L    EDIT
	DC.L    MOOV
	DC.L    HELP
	DC.L    LD_FILE
	DC.L    FILL
	DC.L    HEXCALC
	DC.L    REGMOD
	DC.L    BEG_TRC ;tracing
	DC.L    BREAK
	DC.L    UNASM
	DC.L    VERIFY
; The next command is for future command
; development in the RAM of the SBC
;       DC.L    FUTURE
;
COMANDS DC.B    'D'
	DC.B    'G'
	DC.B    'E'
	DC.B    'M'
	DC.B    '?'
	DC.B    'L'
	DC.B    'F'
	DC.B    'H'
	DC.B    'R'
	DC.B    'T'
	DC.B    'B'
	DC.B    'U'
	DC.B    'C'
; The next command is for future command
; development in the RAM of the SBC
;       DC.B    'X'
;
; Messages go at end so that code word
; alignment won't get derailed
mesgflg dc.b    ' Flags: X = ',0
mesgn   dc.b    ', N = ',0
mesgz   dc.b    ', Z = ',0
mesgv   dc.b    ', V = ',0
mesgc   dc.b    ', C = ',0
;
MSG_1   DC.B    'Bus Error',0
MSG_2   DC.B    'Address Error before ',0
MSG_3   DC.B    'Illegal Instruction Error at '
	DC.B    0
MSG_4   DC.B    'Divide by Zero Error before ',0
MSG_5   DC.B    'TRAPV Overflow',0
MSG_6   DC.B    'Privilege Violation',0
MSG_7   DC.B    'Level-7 Interrupt',0
MSG_8   DC.B    CR,LF,'Breakpoint 1: ',0
MSG_9   DC.B    CR,LF,'Breakpoint 2: ',0
MSG_10  DC.B    'Inactive',0
MSG_A	DC.B	'Line 1010 emulator instruction encountered at ',0
MSG_F	DC.B	'Line 1111 emulator instruction encountered at ',0
;
; Help menu in response to typing a ?
H_MSG1  DC.B    CR,LF
	DC.B    '*** 68EC000 CPU-based '
	DC.B    'Single Board Computer '
	DC.B    '*** Monitor Version 2.10',CR,LF
	DC.B    '===================================='
	DC.B    '================================'
	DC.B    CR,LF
	DC.B    'B <1 or 2> <bkpt>            '
	DC.B    'Set permanent breakpoint '
	DC.B    '1 or 2.',CR,LF
	DC.B    'B <1 or 2><ENT>              '
	DC.B    'Clear breakpoint 1 or 2.',CR,LF
	DC.B    'B<ENT>                       '
	DC.B    'Display permanent breakpoints.',CR,LF
	DC.B    'C <start> <end> <destin>     '
	DC.B    'Compare Memory',CR,LF
	DC.B    'D <start> <#$ of lines>      '
	DC.B    'Dump Memory with optional '
	DC.B    'parameters. ^C to quit.',CR,LF
	DC.B    'D , <#$ of lines>            As '
	DC.B    'above, but start at current address.'
	DC.B    CR,LF
	DC.B    'E <address>                  '
	DC.B    'Edit Memory',CR,LF
	DC.B    'F <start> <end> <data>       '
	DC.B    'Fill Memory',CR,LF
	DC.B    'G <start> <bkpt1> <bkpt2>    '
	DC.B    'Go to USER program with op'
	DC.B    'tional breakpoints.',CR,LF
	DC.B    'G , <bkpt1> <bkpt2>          '
	DC.B    'As above but start at '
	DC.B    'current program counter.'
	DC.B    CR,LF
	DC.B    'G<ENT>                       '
	DC.B    'Start at current program '
	DC.B    'counter, no breakpoints.'
	DC.B    CR,LF
	DC.B    'H <data1> <data2>            '
	DC.B    'Hex sum & difference',CR,LF
	DC.B    'L <optional offset address>  '
	DC.B    'Load S-FILE Program. ^C to abandon.'
	DC.B    CR,LF
	DC.B    'M <start> <end> <destin>     '
	DC.B    'Move Memory',CR,LF
	DC.B    'R                            '
	DC.B    'Register Dump',CR,LF
	DC.B    'R D7                         '
	DC.B    'Register Modify D7',CR,LF
	DC.B    'T <optional start address>   '
	DC.B	'Trace. >R Dn <ENT> to modify any '
	DC.B	'register while ',CR,LF
	DC.B    '                             '
	DC.B    'tracing. Type <ENT> to continue '
	DC.B	'tracing.',CR,LF
	DC.B    'U <start> <#$ of lines>      '
	DC.B    'Unassemble memory with optional '
	DC.B    'parameters.',CR,LF
	DC.B    'U , <#$ of lines>            As '
	DC.B    'above, but start at current address.'
	DC.B    CR,LF
	DC.B    '?                            '
	DC.B    'This Screen',0
;
BADCMD  DC.B    'Bad Command.',0
INVDATA DC.B    'Invalid address or hex '
	DC.B    'data.',0
HELLO   DC.B    CR,LF,'68EC000 Monitor, '
	DC.B    'version 2.10',CR,LF,LF
	DC.B    'Type ? for help menu.'
	DC.B    CR,LF,0
; Load file error message
LE_MSG  DC.B    'There was an error '
	DC.B    'loading the file.',0
LG_MSG  DC.B    '.HEX loaded successfully.'
	DC.B    CR,LF,0
LS_MSG  DC.B    CR,LF
	DC.B    'Start sending the file, '
	DC.B    '^C to abandon.'
	DC.B    CR,LF,0
LF_MSG  DC.B    'Loading file named ',0
HS_MSG  DC.B    CR,LF,'Sum  = ',0
HD_MSG  DC.B    CR,LF,'Diff = ',0
BSSPBS  dc.b    8,' ',8,0
REDOMSG DC.B    CR,LF,'%',0
MSG_NIN DC.B    CR,LF
	DC.B    'TRAP #9 encountered at '
	DC.B    'address ',0
MSG_TEN DC.B    CR,LF
	DC.B    'Breakpoint encountered at '
	DC.B    'address ',0
TRC_MSG DC.B    'TRAP instruction is next. '
	DC.B    'Trace terminated.',0
PASSMSG DC.B    CR,LF,'Comparison successful.',CR,LF,0
FAILMSG DC.B    CR,LF,'Comparison failed.',CR,LF,0
SP24MSG	DC.B	'                      ',0
PC_MSG	DC.B	'PC:   ',0
SR_MSG	DC.B	'SR:     ',0
;
ZEND    DC.B    0
;
	END      START
