;user installable disassembler and single-step run for paulmon2

.equ	locat, 0x1000		;location for these commands (usually 1000)
.equ	paulmon2, 0x0000	;location where paulmon2 is at (usually 0000)

.equ    phex1, 0x2E+paulmon2
.equ    cout, 0x30+paulmon2		;send acc to uart
.equ    cin, 0x32+paulmon2              ;getchar()
.equ    phex, 0x34+paulmon2		;print acc in hex
.equ    phex16, 0x36+paulmon2		;print dptr in hex
.equ    pstr, 0x38+paulmon2		;print string @dptr
.equ    ghex, 0x3A+paulmon2		;get two-digit hex (acc)
.equ    ghex16, 0x3C+paulmon2		;get four-digit hex (dptr)
.equ	upper, 0x40+paulmon2		;convert acc to uppercase
.equ	newline, 0x48+paulmon2
.equ	pcstr, 0x45+paulmon2
.equ	pint, 0x50+paulmon2
.equ	smart_wr, 0x56+paulmon2
.equ	cin_filter, 0x62+paulmon2
.equ	asc2hex, 0x65+paulmon2


.equ    list_key, 'L'		;list (disassemble)
.equ    step_key, 'S'		;single step run
.equ    vtedit_key, 'E'           ;memory editor

;for testing in ram
;.equ    list_key, 'K'           ;list (disassemble)
;.equ    step_key, 'W'           ;single step run
;.equ    vtedit_key, 'E'           ;memory editor



;location of two bytes used by single-step in internal ram which we
;hope the user's program won't write over while it's running.  These
;two bytes hold the address of the previous instruction, so we can
;show the last executed instruction with the current value of the
;registers, which is much more intuitive than displaying the next
;instruction by grabbing the program counter from the stack as was
;done in PAULMON1's single step.

.equ    lastpc, 0x7C		;don't forget to update the docs below



;DIS
;---------------------------------------------------------;
;                                                         ;
;                      list command                       ;
;                                                         ;
;---------------------------------------------------------;


.org	locat
.db	0xA5,0xE5,0xE0,0xA5	;signiture
.db	254,list_key,0,0		;id (254=user installed command)
.db	0,0,0,0			;prompt code vector
.dB	0,0,0,0			;reserved
.db	0,0,0,0			;reserved
.db	0,0,0,0			;reserved
.db	0,0,0,0			;user defined
.db	255,255,255,255		;length and checksum (255=unused)
.db	"List",0

newline_h:ljmp	newline

.org	locat+64                ;executable code begins here

;	disassembler register usage
;	r0 = temporary storage
;	r1 = temporart storage
;	r2 = first instruction byte
;	r3 = second instruction byte
;	r4 = third instruction byte
;	r5 = line count
;	r6 = program counter (lsb)
;	r7 = program counter (msb)

list:	acall	newline_h
	mov	r5, #20
	clr	psw.1		;use ordinary long format
list2:	acall	disasm
	djnz	r5, list2
	ajmp	newline_h

disasm:
;print out the memory location and fetch the next three bytes
	mov	a, r7
	mov	dph, a
	acall	phex_h
	mov	a, r6
	mov	dpl, a
	acall	phex_h
        clr     a
        movc    a, @a+dptr
	mov	r2, a
	inc	dptr
	clr	a
	movc	a, @a+dptr
	mov	r3, a
	inc	dptr
	clr	a
	movc	a, @a+dptr
	mov	r4, a
        mov     a, r2
	anl	a, #00001000b
	jnz	lookup2

;fetch constants for instructions not using R0-R7
lookup1:
	mov	a, r2
	rr	a
	anl	a, #01111000b	;grab upper 4 bits
	mov	r0, a		;keep in r0 for a moment
	mov	a, r2
	anl	a, #00000111b	;get lower 3 bits
	orl	a, r0		;combine in upper 4
        mov     dptr, #opot1	;opot=operand offset table
        movc    a, @a+dptr
	sjmp    unpack

;fetch constants for R0-R7 instructions
lookup2:
        mov     a, r2
        swap    a
        anl     a, #00001111b
        mov     dptr, #opot2
        movc    a, @a+dptr

;now we'll unpack the operand code (# bytes and addr mode)
unpack:	anl     a, #00000011b
	mov	r0, a

;increment the r7/r6 pointer
        add     a, r6
        mov     r6, a
        mov     a, r7
        addc    a, #0
        mov     r7, a

;now print the bytes and spaces (r0 has # of bytes to print)
pbytes:	mov     a, #':'
        acall   cout_h
        acall   space_h
	jb	psw.1, pmnu		;skip bytes if running single-step
        mov     a, r2
        acall   phex_h
        acall   space_h
        cjne    r0, #1, pbytes2
        mov     r1, #11
        sjmp    pbytes4
pbytes2:mov     a, r3
        acall   phex_h
        acall   space_h
        cjne    r0, #2, pbytes3
        mov     r1, #8
        sjmp    pbytes4
pbytes3:mov     a, r4
        acall   phex_h
        mov     r1, #6
pbytes4:acall   space_h
        djnz    r1, pbytes4


;prints the mnunonic name and spaces
pmnu:   mov     a, r2
        anl     a, #00001000b
        jnz     pmnu_lookup2
pmnu_lookup1:
        mov     dptr, #mnot1    ;mnot=mnunonic offset table
        mov     a, r2
        rr      a
        anl     a, #01111000b   ;grab upper 4 bits
        mov     r0, a           ;keep in r0 for a moment
        mov     a, r2
        anl     a, #00000111b   ;get lower 3 bits
        orl     a, r0           ;combine in upper 4
        movc    a, @a+dptr
        mov     r1, a
	sjmp	pmnu0
pmnu_lookup2:
        mov     dptr, #mnot2    ;16 byte table for r0-r7 instructions
        mov     a, r2
        swap    a
        anl     a, #00001111b
        movc    a, @a+dptr
        mov     r1, a
pmnu0:	mov	dptr, #mnu_tbl
	mov     r0, #8
	clr	c
pmnu1:	mov	a, #' '
	jc	pmnu2
	mov	a, r1
	movc	a, @a+dptr
	inc	r1
	mov	c, acc.7
	anl	a, #0x7F
pmnu2:	acall	cout_h
	djnz	r0, pmnu1



;print the operands

        mov     a, #dasm2 & 255  ;(low)
        push    acc
        mov     a, #dasm2 >> 8   ;(high)
        push    acc

am_lookup0:
        mov     a, r2
        anl     a, #00001000b
        jnz     am_lookup2

;fetch constants for instructions not using R0-R7
am_lookup1:
        mov     a, r2
        rr      a
        anl     a, #01111000b   ;grab upper 4 bits
        mov     r0, a           ;keep in r0 for a moment
        mov     a, r2
        anl     a, #00000111b   ;get lower 3 bits
        orl     a, r0           ;combine in upper 4
        mov     dptr, #opot1    ;opot=operand offset table
        movc    a, @a+dptr
        sjmp    am_unpack

;fetch constants for R0-R7 instructions
am_lookup2:
        mov     a, r2
        swap    a
        anl     a, #00001111b
        mov     dptr, #opot2
        movc    a, @a+dptr

am_unpack:
        anl     a, #11111100b
        rr      a
        rr      a
        dec     a

	mov     dptr, #oprt      ;oprt=operand routine table
	rl	a
	add	a, dpl
	mov	dpl, a
	clr	a
	addc	a, dph
	mov	dph, a
	clr	a
        jmp     @a+dptr
dasm2:  
	ajmp	newline_h


oprt:   ajmp   opcd1           ;addr11
	ajmp   opcd2           ;A,Rn
	ajmp   opcd3           ;A,direct
	ajmp   opcd4           ;A,@Ri
	ajmp   opcd5           ;A,#data
	ajmp   opcd6           ;direct,A
	ajmp   opcd7           ;direct,#data
	ajmp   opcd8           ;C,bit
	ajmp   opcd9           ;C,/bit
	ajmp   opcd10          ;A,direct,rel
	ajmp   opcd11          ;A,#data,rel
	ajmp   opcd12          ;Rn,#data,rel
	ajmp   opcd13          ;@Ri,#data,rel
	ajmp   pa              ;A
	ajmp   prc             ;C
	ajmp   pbit            ;bit
	ajmp   pdirect         ;direct
	ajmp   p_reg_i         ;@Ri
	ajmp   opcd19          ;AB
	ajmp   opcd20          ;Rn,rel
	ajmp   opcd21          ;direct,rel
	ajmp   p_reg_n         ;Rn
	ajmp   pdptr           ;DPTR
	ajmp   opcd24          ;bit,rel
	ajmp   prel            ;rel
	ajmp   opcd26          ;@A+DPTR
	ajmp   opcd27          ;addr16
	ajmp   opcd28          ;Rn,A
	ajmp   opcd29          ;Rn,direct
	ajmp   opcd30          ;Rn,#data
	ajmp   opcd31          ;direct,Rn
	ajmp   opcd32          ;direct,direct
	ajmp   opcd33          ;direct,@Ri
	ajmp   opcd34          ;@Ri,A
	ajmp   opcd35          ;@Ri,direct
	ajmp   opcd36          ;@Ri,#data
	ajmp   opcd37          ;bit,C
	ajmp   opcd38          ;DPTR,#data16
	ajmp   opcd39          ;A,@A+DPTR
	ajmp   opcd40          ;A,@A+PC
	ajmp   opcd41          ;A,@DPTR
	ajmp   opcd42          ;@DPTR,A
	ret                    ; <nothing>



opcd4:                      ;A,@Ri              done
        acall   pac
p_reg_i:mov     a,#'@'
        acall   cout_h
        mov     a,#'R'
        acall   cout_h
        mov     a, r2
        anl     a,#00000001b
        ajmp    phex1_h

opcd3:                      ;A,direct           done
        acall   pac
pdirect:
        mov     a, r3
        jb      acc.7,pdir1
pdir0:  mov     a, r3
        ajmp    phex_h
pdir1:  mov     dptr,#sfrmnu
pdir2:  clr     a
        movc    a,@a+dptr
        inc     dptr
        jz      pdir0
        mov     r0,a
        clr     c
        subb    a, r3
        jnz     pdir3
pstr_h:
	ljmp	pstr

pdir3:  clr     a
        movc    a,@a+dptr
        inc     dptr
        jnb     acc.7,pdir3
        sjmp    pdir2

               
opcd9:                      ;C,/bit             done
        acall   prc
        acall   pcomma
        mov     a, #'/'
        acall   cout_h
pbit: 
        mov     a, r3
        anl     a,#01111000b
        rl      a
        swap    a
        mov     r0,a
        mov     a, r3
        anl     a,#10000000b
        jz      pbit1
        mov     dptr,#bitptr        ;it's a Special Function Reg.
        mov     a,r0
        movc    a,@a+dptr
        mov     dptr,#bitmnu
        addc    a,dpl
        mov     dpl,a
        jnc     pbit0
        inc     dph
pbit0:  acall   pstr_h
        sjmp    pbit2
pbit1:  mov     a,r0            ;it's between 20h and 2Fh
        add     a,#20h
        acall   phex_h
pbit2:  mov     a,#'.'
        acall   cout_h
        mov     a, r3
        anl     a,#00000111b
        ajmp    phex1_h


opcd10:                     ;A,direct,rel       done
        acall   pac
        acall   pdirect
opcd10a:acall   pcomma
        mov     a, r4
        mov     r3, a
prel:
        mov     a, r3
        add     a, r6
	mov	dpl, a
	mov	a, r3
	jb	acc.7, prel2
	clr	a
	sjmp	prel3
prel2:	clr	a
	cpl	a
prel3:	addc	a, r7
	mov	dph, a
	ljmp	phex16


pat:            ;prints the '@' symbol
        mov     a,#'@'
        ajmp    cout_h

pac:            ;print "A,"
        acall   pa
pcomma:         ;prints a comma
        mov     a,#','
        acall   cout_h
pspace: mov	a, #' '
	ajmp	cout_h

plb:            ;prints the '#' symbol
        mov     a,#'#'
        ajmp    cout_h


opcd6:                      ;direct,A           done
        acall   pdirect
        acall   pcomma
pa:             ;prints 'A'
        mov     a,#'A'
        ajmp    cout_h

opcd37:                     ;bit,C              done
        acall   pbit
        acall   pcomma
prc:             ;prints 'C'
        mov     a,#'C'
        ajmp    cout_h

opcd26:                     ;@A+DPTR            done
        acall   pat
        acall   pa
        mov     a,#'+'
        acall   cout_h
pdptr:          ;prints DPTR
	mov	a, #'D'
	acall	cout_h
	mov	a, #'P'
	acall	cout_h
	mov	a, #'T'
	acall	cout_h
	mov	a, #'R'
cout_h:
	ljmp	cout

opcd1:  mov     a, r7       ;addr11             done
        anl     a, #11111000b
        mov     r0, a
        mov     a, r2
        swap    a
        rr      a
        anl     a, #00000111b
        orl     a, r0
        acall   phex_h
        mov     a, r3
        ajmp    phex_h

opcd2:                      ;A,Rn               done
        acall   pac
p_reg_n:mov     a,#'R'
        acall   cout_h
        mov     a, r2
        anl     a,#00000111b
phex1_h:
	ljmp	phex1



opcd5:                      ;A,#data            done
        acall   pa
pdata:  acall   pcomma
        acall   plb
        mov     a, r3
phex_h:
	ljmp	phex

opcd7:                      ;direct,#data       done
        acall   pdirect
        mov     a, r4
        mov     r3, a
        ajmp    pdata
opcd8:                      ;C,bit              done
        acall   prc
        acall   pcomma
        ajmp    pbit

opcd11:                     ;A,#data,rel        done
        acall   pa
opcd11a:acall   pcomma
        acall   plb
        mov     a, r3
        acall   phex_h
        ajmp    opcd10a
opcd12:                     ;Rn,#data,rel       done
        acall   p_reg_n
        ajmp    opcd11a
opcd13:                     ;@Ri,#data,rel      done
        acall   p_reg_i
        ajmp    opcd11a
opcd19:                     ;AB                 done
        acall   pa
        mov     a, #'B'
        ajmp    cout_h
opcd20:                     ;Rn,rel             done
        acall   p_reg_n
        acall   pcomma
        ajmp    prel
opcd21:                     ;direct,rel         done
        acall   pdirect
        ajmp    opcd10a
opcd24:                     ;bit,rel            done
        acall   pbit
        ajmp    opcd10a
opcd28:                     ;Rn,A               done
        acall   p_reg_n
        acall   pcomma
        ajmp    pa
opcd29:                     ;Rn,direct          done
        acall   p_reg_n
        acall   pcomma          
        ajmp    pdirect
opcd30:                     ;Rn,#data           done
        acall   p_reg_n
        ajmp    pdata
opcd31:                     ;direct,Rn          done
        acall   pdirect
        acall   pcomma
        ajmp    p_reg_n
opcd32:                     ;direct,direct      done
        mov     a, r3
        push    acc
        mov     a, r4
        mov     r3, a
        acall   pdirect
        acall   pcomma
        pop     acc
        mov     r3, a
        ajmp    pdirect
opcd33:                     ;direct,@Ri         done
        acall   pdirect
        acall   pcomma
        ajmp    p_reg_i
opcd34:                     ;@Ri,A              done
        acall   p_reg_i
        acall   pcomma
        ajmp    pa
opcd35:                     ;@Ri,direct         done
        acall   p_reg_i
        acall   pcomma
        ajmp    pdirect
opcd36:                     ;@Ri,#data          done
        acall   p_reg_i
        ajmp    pdata
opcd38:                     ;DPTR,#data16       done
        acall   pdptr
        acall   pcomma
        acall   plb
opcd27: mov     a, r3  ;addr16          done
        acall   phex_h
        mov     a, r4
        ajmp    phex_h
opcd39:                     ;A,@A+DPTR          done
        acall   pac
        acall   pat
        acall   pa
        mov     a,#'+'
        acall   cout_h
        ajmp    pdptr
opcd40:                     ;A,@A+PC            done
        acall   pac
        acall   pat
        acall   pa
        mov     a,#'+'
        acall   cout_h
        mov     a,#'P'
        acall   cout_h
        ajmp    prc
opcd41:                     ;A,@DPTR            done
        acall   pac
        acall   pat
        ajmp    pdptr
opcd42:                     ;@DPTR,A            done
        acall   pat
        acall   pdptr
        acall   pcomma
        ajmp    pa





sfrmnu: .db     0xE0,"AC",'C'+128
        .db     0x81,'S','P'+128
        .db     0x82,"DP",'L'+128
        .db     0x83,"DP",'H'+128
        .db     0x80,'P','0'+128
        .db     0x90,'P','1'+128
        .db     0xA0,'P','2'+128
        .db     0xB0,'P','3'+128
        .db     0x99,"SBU",'F'+128
        .db     0xCD,"TH",'2'+128
        .db     0xC8,"T2CO",'N'+128
        .db     0xCC,"TL",'2'+128
        .db     0xCB,"RCAP2",'H'+128
        .db     0xCA,"RCAP2",'L'+128
        .db     0x8C,"TH",'0'+128
        .db     0x8A,"TL",'0'+128
        .db     0x8D,"TH",'1'+128
        .db     0x8B,"TL",'1'+128
sfr1:   .db     0xF0,'B'+128               ;5
sfr2:   .db     0xD0,"PS",'W'+128          ;7
sfr3:   .db     0xA8,'I','E'+128
sfr4:   .db     0xB8,'I','P'+128
sfr5:   .db     0x89,"TMO",'D'+128         ;8
sfr6:   .db     0x88,"TCO",'N'+128         ;8
sfr7:   .db     0x98,"SCO",'N'+128         ;8
sfr8:   .db     0x87,"PCO",'N'+128         ;8
        .db     0                       ;just in case


opot2:  .db     0x59, 0x59, 0x09, 0x09  ;inc, dec, add, addc
        .db     0x09, 0x09, 0x09, 0x7A  ;orl, anl, xrl, mov
        .db     0x7E, 0x09, 0x76, 0x33  ;mov, subb, mov, cjne
        .db     0x09, 0x52, 0x09, 0x71  ;xch, djnz, mov, mov

bitptr: .db     0x00, 0x02, 0x06, 0x08, 0x0C, 0x0E, 0x10, 0x12
        .db     0x14, 0x16, 0x1B, 0x1E, 0x20, 0x23, 0x24, 0x25


;some stuff used by single step... it's here to fill up some of
;the unused space from the end of the disassembler code and the
;beginning of the single-step header (which must begin on a 256
;byte page boundry)


wr_check:   ;write to memory and check that it worked.
	    ;acc=0 if it worked, nonzero if it didn't write
	mov	r0, a		;keep a copy of the data in r0
	movx	@dptr, a
	clr	a
	movc	a, @a+dptr
	clr	c
	subb	a, r0
	ret

;delay for approx 1 character transmit time
chardly:mov     r1, #80     
chdly2:	mov     a, th1 
        cpl     a     
        inc     a
        mov     r0, a
        djnz    r0, *
        djnz    r1, chdly2
	ret

prcolon:acall	phex_h
	mov	a, #':'
	ajmp	cout_h

phexsp:	acall	phex_h
space_h:
	mov	a, #' '
	ajmp	cout_h


;SINGLE
;---------------------------------------------------------;
;                                                         ;
;                 single step command                     ;
;                                                         ;
;---------------------------------------------------------;

.org    locat+0x400
.db     0xA5,0xE5,0xE0,0xA5     ;signiture
.db     254,step_key,0,0             ;id (254=user installed command)
.db     0,0,0,0                 ;prompt code vector
.dB     0,0,0,0                 ;reserved
.db     0,0,0,0                 ;reserved
.db     0,0,0,0                 ;reserved
.db     0,0,0,0                 ;user defined
.db     255,255,255,255         ;length and checksum (255=unused)
.db     "Single-Step",0
.org    locat+0x440             ;executable code begins here


        
ssrun:
	;first check to make sure they connect int1 low
	jnb	p3.3, ssrun2
        mov     dptr, #sserr1	;give error msg if int1 not grounded
pcstr_h:
	ljmp	pcstr

ssrun2:	;make sure there's a ljmp at the int1 vector location
	mov	dptr, #0x0013
	clr	a
	movc	a, @a+dptr
	add	a, #254
	jz	ssrun3
	mov	dptr, #sserr2	;give error that paulmon2 was not found.
	ajmp	pcstr_h
ssrun3:	;now write an ljmp to "step" in the ram and check it.
	inc	dptr
	movc	a, @a+dptr
	mov	r0, a
	clr	a
	inc	dptr
	movc	a, @a+dptr
	mov	dpl, a
	mov	dph, r0		;now data pointer points to int1 target
	mov	a, #2
	acall	wr_check
	jnz	ssrun4
	inc	dptr
	mov	a, #(step >> 8)
	acall	wr_check
	jnz	ssrun4
	inc	dptr
	mov	a, #(step & 255)
	acall	wr_check
	jz	ssrun5
ssrun4:	mov	r0, dpl
	mov	r1, dph
	mov	dptr, #sserr3	;error: couldn't write to memory @xxxx
	acall	pcstr_h
	mov	a, r1
	acall	phex_h
	mov	a, r0
	acall	phex_h
	ajmp	newline_h
ssrun5:	mov	a, ip		;set to high priority interrupt
	anl	a, #00000100b
	mov	ip, a
	;let's not beat around the bush (like paulmon1), all 
	;we need to know is where to jump into memory.
	mov	dptr, #prompt8
	acall	pcstr_h
	mov	a, r7
	acall	phex_h
	mov	a, r6
	acall	phex_h
        mov     dptr,#prompt4
        acall   pcstr_h
        lcall   ghex16		;ask for the jump location
	jb	psw.5, ssrun7
        jnc     ssrun6
        mov     dptr,#abort
        acall   pstr_h
        ajmp    newline_h
ssrun6:	mov	r6, dpl		;where we'll begin executing
	mov	r7, dph
ssrun7:	clr	tcon.2		;need low-level triggered int1
	mov     dptr,#ssmsg     ;tell 'em we're starting
	acall	pcstr_h
	mov	dptr,#ssnames
	acall	pstr_h
	clr	a
	mov	sp, #8		;just like after a reset
	push	acc		;unlike a 8051 start-up, push return addr
	push	acc		;of 0000, just in case they end w/ ret
	mov	dpl, r6		;load the program's address into dptr
	mov	dph, r7
	mov	psw, a		;and clear everything to zero
	mov	r0, a
	mov	r1, a
	mov	r2, a
	mov	r3, a
	mov	r4, a
	mov	r5, a
	mov	r6, a
	mov	r7, a
	mov	b, a
	mov	lastpc, #ssstart & 255
	mov	(lastpc+1), #ssstart >> 8
	setb	ie.2
	setb	ea		;turn on the interrupt
ssstart:jmp	@a+dptr


done:	acall	chardly
	pop	acc
	mov	r1, a
	pop	acc
	mov	r0, a
	pop	dpl
	pop	dph
	pop	psw
	pop	acc
	reti

step:    ;this is the single step interrupt service code...
	push	acc
	push	psw		;Stack Contents: (in this order)
	push	dph		;PC_L PC_H ACC PSW DPH DPL R0 R1
	push	dpl
	mov	a, r0
	push	acc
	mov	a, r1
	push	acc
	;in case the previous instruction was "clr ti", we
	;must wait for a character transmit time "in case it
	;was a move to SBUF) and then set ti so that our cout
	;doesn't hang when we transmit the first character!
	acall	chardly
	setb	ti

	;now print out a line that looks like this:
	;ACC B C DPTR  R0 R1 R2 R3 R4 R5 R6 R7  SP    PC  Instruction
	;00 00 0 3F00  00:00:00:00:00:00:00:00  00 - 0000: LJMP    0825

	acall	space_h
	acall	space_h
        mov     a, sp
        add     a, #251
        mov     r0, a           ;r0 points to user's acc on stack
        mov     a, @r0
        acall   phexsp          ;print acc
        mov     a, b
        acall   phexsp          ;print b register
	inc	r0
        mov     a, @r0
        rl      a
        anl     a, #1
        acall   phex1_h         ;print carry bit
        acall   space_h
	inc	r0
	mov	a, @r0
	acall	phex_h		;print dptr (msb)
	inc	r0
	mov	a, @r0
	acall	phexsp		;print dptr (lsb)
	acall	space_h
	inc	r0
	mov	a, @r0
	acall	prcolon		;print r0
	inc	r0
	mov	a, @r0
	acall	prcolon		;print r1
	mov	a, r2
	acall	prcolon		;print r2
	mov	a, r3
	acall	prcolon		;print r3
	mov	a, r4
	acall	prcolon		;print r4
	mov	a, r5
	acall	prcolon		;print r5
	mov	a, r6
	acall	prcolon		;print r6
	mov	a, r7
	acall	phexsp		;print r7
	acall	space_h
	mov	a, r0
	add	a, #248
	acall	phexsp		;print stack pointer
	acall	space_h
	acall	space_h
	;now the trick is to disassemble the instruction... this isn't
	;easy, since the user wants to see the last instruction that
	;just executed, but program counter on the stack points to the
	;next instruction to be executed.  The dirty trick is to grab
	;the program counter from last time where we stashed it in some
	;memory that hopefully the user's program hasn't overwritten.
	mov	a, lastpc
	mov	lastpc, r6
	mov	r6, a
	mov	a, (lastpc+1)
	mov	(lastpc+1), r7
	mov	r7, a
	mov	a, r2
	push	acc
	mov	a, r3
	push	acc
	mov	a, r4
	push	acc
	setb	psw.1		;tell it to use a compact format
	;the disassembler uses quite a bit of stack space... if the
	;user didn't leave enough room for the stack to grow with
	;all this overhead, it will likely crash somewhere in the
	;disassembler... oh well, not much I can do about it.  The
	;worst case stack usage for disasm is 9 bytes.  We just
	;pushed 5 and 6 at the beginning of step.  With the two
	;bytes for the interrupt, a total of 22 bytes of free stack
	;space must be available to use the single-step feature.
	acall	disasm
	pop	acc
	mov	r4, a
	pop	acc
	mov	r3, a
	pop	acc
	mov	r2, a
	mov	r7, (lastpc+1)
	mov	r6, lastpc
	;now grab the user's PC value to keep it for next time
        mov     a, sp
        add     a, #249
        mov     r0, a           ;r0 points to user's acc on stack
	mov	a, @r0
	mov	lastpc, a
	inc	r0
	mov	a, @r0
	mov	(lastpc+1), a

;SINGLE STEP

step1:  lcall   cin_filter
        lcall   upper
step2:  cjne    a, #13, step7
        ajmp    done
step7:  cjne    a, #' ', step8    ;check space
        ajmp    done
step8:  cjne    a,#'?',step10  ;check '?'
        mov     dptr,#help5txt
        acall   pcstr_h
        ajmp    step1
step10: cjne    a,#'Q',step11  ;check 'Q'=quit and run normal
        mov     dptr, #squit
        acall   pstr_h
        clr     ie.2
	acall	chardly
	mov	8, #0		;force return to 0000
	mov	9, #0
	mov	sp, #9
	reti
step11:
	cjne    a,#'H',step12  ;check 'H'=hex dump internal ram
        ajmp    ssdmp
step12: cjne    a,#'R',step13  ;check 'R'=print out registers
        ajmp    ssreg
step13: cjne    a,#'S',step14  ;check 'S'=skip next inst
        ajmp    ssskip
step14: cjne    a,#'A',step15  ;check 'A'=change acc value
        ajmp    sschacc
step15: cjne	a,#'.',step20
	mov	dptr, #ssnames
	acall	pstr_h
	ajmp	step1

step20: ajmp    step1
 
  
pequal:        ; prints '='
        mov     a,#'='
        ajmp    cout_h

ssdmp:
        mov     dptr, #ssdmps1
        acall   pstr_h
        clr     a
        acall   prcolon
        acall   space_h
	mov	r0, sp
	dec	r0
        mov     a, @r0
        acall   phexsp
	inc	r0
	mov	a, @r0
        acall   phex_h
        mov     r0, #2
        mov     r1, #14
        ajmp    ssdmp2
ssdmp1: mov     a, r0
	acall	prcolon
        mov     r1, #16
ssdmp2: acall   space_h
        mov     a, @r0
        acall   phex_h
        inc     r0
        djnz    r1, ssdmp2
        acall   newline_h
        cjne    r0, #0x80, ssdmp1
        acall   newline_h
	ajmp	step1


ssreg:
	mov	dptr, #sfr2+1
	acall	pstr_h
        acall   pequal
        mov     a, sp
	add	a, #252
	mov	r0, a
        mov     a, @r0
        acall   phexsp		;print psw
        mov     dptr,#sfr3+1
        mov     r0, 0xA8
        acall   psfr		;print ie
        mov     dptr,#sfr4+1
        mov     r0, 0xB8
        acall   psfr		;print ip
        mov     dptr,#sfr5+1
        mov     r0, 0x89
        acall   psfr		;print tmod
        mov     dptr,#sfr6+1
        mov     r0, 0x88
        acall   psfr		;print tcon
        mov     dptr,#sfr7+1
        mov     r0, 0x98
        acall   psfr		;print smod
        mov     dptr,#sfr8+1
        mov     r0, 0x87
        acall   psfr		;print pcon
        mov     a, #'T'
        acall   cout_h
        mov     a, #'0'
        acall   cout_h
        acall   pequal
        mov     a, 8Ch
        acall   phex_h		;print Timer 0
        mov     a, 8Ah
        acall   phex_h
        acall   space_h
        mov     a, #'T'
        acall   cout_h
        mov     a, #'1'
        acall   cout_h
        acall   pequal
        mov     a, 8Dh		;print Timer 1
        acall   phex_h
        mov     a, 8Bh
        acall   phex_h
        acall   newline_h
        ajmp    step1

psfr:   acall   pstr_h
        acall   pequal
        mov     a, r0
        ajmp    phexsp



;skip the next instruction
ssskip:
	mov	r0, #23
ssskip2:acall	space_h
	djnz	r0, ssskip2
        mov     dptr,#sskip1
        acall   pstr_h
	mov	a, sp
	add	a, #249
	mov	r0, a		;set r0 to point to pc on stack
	mov	a, @r0
	mov	lastpc, r6	;keep r6/r7 safe in lastpc
	mov	r6, a		;put user's pc into r6/r7
	inc	r0
	mov	a, @r0
	mov	(lastpc+1), r7
	mov	r7, a
	mov	a, r2
	push	acc
	mov	a, r3
	push	acc
	mov	a, r4
	push	acc
        setb    psw.1           ;tell it to use a compact format
        acall   disasm		;run disasm to show 'em what was skipped
	pop	acc
	mov	r4, a
	pop	acc
	mov	r3, a
	pop	acc
	mov	r2, a
        mov     a, sp
        add     a, #249
        mov     r0, a           ;set r0 to point to pc on stack
	mov	a, r6
        mov     r6, lastpc	;restore r6/r7
	mov	lastpc, a	;update lastpc with next inst addr
	mov	@r0, a		;also update user's pc!!
	inc	r0
	mov	a, r7
	mov	r7, (lastpc+1)
	mov	(lastpc+1), a
	mov	@r0, a
	ajmp	step1

sschacc:
        mov     a, sp
	add	a, #251
	mov	r0, a		;r0 points to acc on stack
        mov     dptr, #chaccs1
        acall   pstr_h
        lcall   ghex
        jc      chacc2
	jb	psw.5, chacc2
        mov     @r0, a
        acall   newline_h
        ajmp    step1
chacc2: mov     dptr, #abort
        acall   pstr_h
        ajmp    step1




;stuff some of the disassembler tables, strings, etc since we have a
;bit of space before the beginning of the editor command code


       ;opcode offset table (gives #bytes for the instruction
       ;and the number of the routine to print the operands)

opot1:  .db     0xAD, 0x06, 0x6F, 0x39, 0x39, 0x46, 0x49, 0x49 ;0
        .db     0x63, 0x06, 0x6F, 0x39, 0x39, 0x46, 0x49, 0x49 ;1
        .db     0x63, 0x06, 0xAD, 0x39, 0x16, 0x0E, 0x11, 0x11 ;2
        .db     0x63, 0x06, 0xAD, 0x39, 0x16, 0x0E, 0x11, 0x11 ;3
        .db     0x66, 0x06, 0x1A, 0x1F, 0x16, 0x0E, 0x11, 0x11 ;4
        .db     0x66, 0x06, 0x1A, 0x1F, 0x16, 0x0E, 0x11, 0x11 ;5
        .db     0x66, 0x06, 0x1A, 0x1F, 0x16, 0x0E, 0x11, 0x11 ;6
        .db     0x66, 0x06, 0x22, 0x69, 0x16, 0x1F, 0x92, 0x92 ;7
        .db     0x66, 0x06, 0x22, 0xA1, 0x4D, 0x83, 0x86, 0x86 ;8
        .db     0x9B, 0x06, 0x96, 0x9D, 0x16, 0x0E, 0x11, 0x11 ;9
        .db     0x26, 0x06, 0x22, 0x5D, 0x4D, 0xAD, 0x8E, 0x8E ;A
        .db     0x26, 0x06, 0x42, 0x3D, 0x2F, 0x2B, 0x37, 0x37 ;B
        .db     0x46, 0x06, 0x42, 0x3D, 0x39, 0x0E, 0x11, 0x11 ;C
        .db     0x46, 0x06, 0x42, 0x3D, 0x39, 0x57, 0x11, 0x11 ;D
        .db     0xA5, 0x06, 0x11, 0x11, 0x39, 0x0E, 0x11, 0x11 ;E
        .db     0xA9, 0x06, 0x89, 0x89, 0x39, 0x1A, 0x89, 0x89 ;F

mnot1:  ;mnunonic offset table (gives offset into above table)

        .db     0x5A, 0x0E, 0x48, 0x73  ;nop, ajmp, ljmp, rr
        .db     0x2B, 0x2B, 0x2B, 0x2B  ;inc, inc, inc, inc
        .db     0x30, 0x00, 0x43, 0x75  ;jbc, acall, lcall rrc
        .db     0x21, 0x21, 0x21, 0x21  ;

        .db     0x2E, 0x0E, 0x67, 0x6E  ; etc...
        .db     0x06, 0x06, 0x06, 0x06  ;
        .db     0x38, 0x00, 0x6A, 0x70  ;
        .db     0x0A, 0x0A, 0x0A, 0x0A  ;

        .db     0x33, 0x0E, 0x5D, 0x5D  ;
        .db     0x5D, 0x5D, 0x5D, 0x5D  ;
        .db     0x3B, 0x00, 0x12, 0x12  ;
        .db     0x12, 0x12, 0x12, 0x12  ;

        .db     0x41, 0x0E, 0x8F, 0x8F  ;
        .db     0x8F, 0x8F, 0x8F, 0x8F  ;
        .db     0x3E, 0x00, 0x5D, 0x35  ;
        .db     0x4C, 0x4C, 0x4C, 0x4C  ;

        .db     0x7C, 0x0E, 0x12, 0x4F  ;
        .db     0x24, 0x4C, 0x4C, 0x4C  ;
        .db     0x4C, 0x00, 0x4C, 0x4F  ;
        .db     0x80, 0x80, 0x80, 0x80  ;

        .db     0x5D, 0x0E, 0x4C, 0x2B  ;
        .db     0x57, 0x92, 0x4C, 0x4C  ;
        .db     0x12, 0x00, 0x1C, 0x1C  ;
        .db     0x15, 0x15, 0x15, 0x15  ;

        .db     0x63, 0x0E, 0x19, 0x19  ;
        .db     0x84, 0x88, 0x88, 0x88  ;
        .db     0x60, 0x00, 0x78, 0x78  ;
        .db     0x1F, 0x27, 0x8B, 0x8B  ;

        .db     0x53, 0x0E, 0x53, 0x53  ;
        .db     0x19, 0x4C, 0x4C, 0x4C  ;
        .db     0x53, 0x00, 0x53, 0x53  ;
        .db     0x1C, 0x4C, 0x4C, 0x4C  ;


mnot2:  .db     0x2B, 0x21, 0x06, 0x0A  ;inc, dec, add, addc
        .db     0x5D, 0x12, 0x8F, 0x4C  ;orl, anl, xlr, mov
        .db     0x4C, 0x80, 0x4C, 0x15  ;mov, subb, mov, cjne
        .db     0x88, 0x27, 0x4C, 0x4C  ;xch, djnz, mov, mov

;---------------------------------------------------------;
;                                                         ;
;                  About PAULMON2                    ;
;                                                         ;
;---------------------------------------------------------;

;register usage:
; R4,    Flags:
;         bit0: 0=display CODE memory, 1=display DATA memory
;         bit1: 0=editing disabled, 1=editing enabled
;         bit2: 0=editing in hex, 1=editing in ascii
;         bit3: 0=normal, 1=in middle of hex entry (value in r5)
; R6/R7, current memory location
;

.org    locat+0x800
.db     0xA5,0xE5,0xE0,0xA5     ;signiture
.db     254,'A',0,0      ;id (254=user installed command)
.db     0,0,0,0                 ;prompt code vector
.dB     0,0,0,0                 ;reserved
.db     0,0,0,0                 ;reserved
.db     0,0,0,0                 ;reserved
.db     0,0,0,0                 ;user defined
.db     255,255,255,255         ;length and checksum (255=unused)
.db     "About PAULMON2",0

.org    locat+0x0840            ;executable code begins here
        mov dptr,#about
        lcall pstr
        ljmp  newline_h

about: .db 13,10," PAULMON2 by Paul Stoffregen paul@ece.orst.edu"
       .db 13,10," modified by Wichit Sirichote July 25,'99" 
       .db 13,10," * add return path to monitor & print ACC & PSW"
       .db 13,10," * use 9600 fixed baud rate",13,10,0


; change Fix_baud to 9600
;this little program is an example of how to use the "init" type
;of startup program to initialize the baud rate and the other
;related memory locations, so that PAULMON2 will *not* attempt
;to do automatic baud rate detection, even if it configured to
;do automatic baud rate detection by default.  For boards with
;flash rom, this allows the board to used for a dedicated purpose
;without having to do automatic baud rate detection every time
;the power is cycled.  Startup programs other than hardware
;initialization should usually used type 253 instead of 249.

;.equ    baud_const, 255         ;57600 baud w/ 11.0592 MHz
;.equ   baud_const, 253         ;19200 baud w/ 11.0592 MHz
;.equ   baud_const, 252         ;19200 baud w/ 14.7456 MHz
;.equ   baud_const, 243         ;4808 baud w/ 12 MHz
.equ    baud_const, 250         ; 9600 baud w/11.0592 MHz

.org    locat+0x900             ; i.e., 1900h

.db	0xA5,0xE5,0xE0,0xA5	;signiture bytes
.db	249,255,0,0		;id (35=prog, 249=init, 253=startup, 254=cmd)
.db	0,0,0,0			;prompt code vector
.db	0,0,0,0			;reserved
.db	0,0,0,0			;reserved
.db	0,0,0,0			;reserved
.db	0,0,0,0			;user defined
.db	255,255,255,255		;length and checksum (255=unused)
.db	"Fixed Baud Rate",0
.org    locat+0x940             ;executable code begins here

	mov	a, #baud_const
	mov     0x7B, a
        mov     0x7A, a         ;store the baud rate for next warm boot.
        mov     0x79, a
        mov     0x78, a
        xrl     0x7A, #01010101b
        xrl     0x79, #11001100b
        xrl     0x78, #00011101b
	ret

;------------------------- my code ------------------------------
; back to monitor program path with printout accumulator and
; psw's content
; W.Sirichote 25 July 1999

monitor:
        push psw
        push acc

        lcall newline
        mov  dptr, #accumulator
        lcall pstr
        pop  acc
        lcall phex

        lcall newline
        mov dptr, #PSW_REG
        lcall pstr
        pop psw
        mov a,psw
        lcall phex
        lcall newline

        ljmp  0         ; go to reset condition

accumulator: .db "Accumulator = ",0
PSW_REG:     .db "PSW = ",0

;----------------------------------------------------------
; getnum() and _atoi()
; W.Sirichote 16 August 1999

; 16 bit multiply of AB by R3-4, result in AB
;

mul16:    MOV     R6,A           ; Save LO1
        MOV     A,R3           ; Get LO2
        MUL     AB             ;   Multiply HI1 * LO2
        MOV     R5,A           ; Save partial product
        MOV     B,R6           ; Get LO1
        MOV     A,R4           ; Get HI2
        MUL     AB             ;   Multiply LO1 * HI2
        MOV     R4,A           ; Save partial product
        MOV     A,R3           ; Get LO2
        MOV     B,R6           ; Get LO1
        MUL     AB             ;   Multiply LO2 * LO1
        XCH     A,B            ; Save low & get high
        ADD     A,R4           ; Add in carry from LO1 * HI2
        ADD     A,R5           ; Add in carry from HI1 * LO2
        XCH     A,B            ; Restore proper order
	RET

; Convert ASCII string to number: int _atoi(string)
; r1 string pointer

_atoi:  
        CLR     A              ; Get ZERO
        MOV     R3,A           ; Set LOW
        MOV     R4,A           ; Set HIGH
        MOV     R7,A           ; Assume positive
A1:     MOV     A,@R1          ; Get char
        INC     R1             ; Advance
        CJNE    A,#'-',A3      ; Not minus
        INC     R7             ; Set negative flag
A2:      MOV     A,@R1          ; Get char
        INC     R1             ; Advance
A3:      CLR     C              ; Insure no carry
        SUBB    A,#'0'         ; Convert to binary
        CJNE    A,#10,*+3      ; Non-destructive compare
        JNC     A4             ; End of number
        MOV     R2,A           ; Save for later
        MOV     A,#10          ; *10
        MOV     B,#0           ; Zero high
        LCALL   mul16           ; Multiply result
        ADD     A,R2           ; Include digit
        MOV     R3,A           ; Save LOW
        MOV     A,B            ; Swap
        ADDC    A,#0           ; Insure high incs
        MOV     R4,A           ; Save high
        SJMP    A2             ; And go again
A4:      MOV     A,R3           ; Get LOW result
        MOV     B,R4           ; Get HIGH result
        DJNZ    R7,A5          ; Negative sign?
      ;  LJMP    neg           ; Yes, convert
A5:      RET

; int getnum() return integer in BA
; get decimal string then convert to int
; use 6-byte RAM at f0h-f5h, eg. '65535' 0

_getnum: mov  r1,#0xf0
_getnum2:
         lcall cin
         cjne a,#0dh,check_BS
         mov  @r1,#0            ; put terminator
         mov  r1,#0xf0
         lcall _atoi
         ret                    ; return BA as an integer

check_BS: cjne a,#8,check_FF
          lcall cout
          dec  r1
          sjmp  _getnum2

check_FF: cjne a,#0x0c,save_char
          lcall cout
          inc r1
          sjmp _getnum2

save_char: lcall cout
           mov @r1,a
           inc r1
           sjmp _getnum2





;---------------------------------------------------------;
;                                                         ;
;                    single step strings                  ;
;                                                         ;
;---------------------------------------------------------;


           
prompt4:.db     "), or <ESC> to exit: ",0 
prompt8:.db     13,31,136,128,131,129," (",0 
abort:  .db     " Command Aborted.",13,10,0


sserr1: .db     13,161,197," connect INT1 (pin 13) low"
        .db     128,186,207,204,13,0
sserr2:	.db	148,"2",179,199,174,129," 0013",13,0
sserr3:	.db	31,184,179,255,165," vector",174," ",0
ssmsg:  .db     13,"Now",134,"ning",166,207,204," mode:  "
        .db     "<RET>=",204,", ?= Help",13,13,0

sskip1: .db     "Skipping Instruction-> ",0
ssdmps1:.db     13,10,"Loc:  Int RAM Memory Contents",13,10,0
chaccs1:.db     "New Acc Value: ",0

help5txt:.db	13
        .db     31,207,31,204,31,158,":",13
        .db     "<RET> ",134,212,246,13
        .db     " <SP> ",134,212,246,13
        .db     " '?'  ",255,142,215,13
	.db	" '.'  ",255,196,253,"s",13
        .db     " 'R'  ",255," special function",196,"s",13
        .db     " 'H'  ",132,219,192,146,13
        .db     " 'S'  ",252,212,246,13
        .db     " 'A'  ",240,162," Acc value",13
	.db     " 'Q'  ",200,207,204,13,14

squit:	.db	"Quit",13,10,0

ssnames:.db	"  ACC B C DPTR  R0 R1 R2 R3 R4 R5 R6 R7  SP"
	.db	"   Addr  Instruction",13,10,0


;---------------------------------------------------------;
;                                                         ;
;                    disassembler data                    ;
;                                                         ;
;---------------------------------------------------------;



mnu_tbl:.db     "ACAL",'L'+128
        .db     0
        .db     "AD",'D'+128
        .db     0
        .db     "ADD",'C'+128
        .db     "AJM",'P'+128
        .db     "AN",'L'+128
        .db     "CJN",'E'+128
        .db     "CL",'R'+128
        .db     "CP",'L'+128
        .db     "D",'A'+128 
        .db     "DE",'C'+128
        .db     "DI",'V'+128
        .db     "DJN",'Z'+128
        .db     "IN",'C'+128
        .db     "J",'B'+128
        .db     "JB",'C'+128
        .db     "J",'C'+128
        .db     "JM",'P'+128
        .db     "JN",'B'+128
        .db     "JN",'C'+128
        .db     "JN",'Z'+128
        .db     "J",'Z'+128
        .db     "LCAL",'L'+128
        .db     "LJM",'P'+128
        .db     "MO",'V'+128
        .db     "MOV",'C'+128
        .db     "MOV",'X'+128
        .db     "MU",'L'+128
        .db     "NO",'P'+128
        .db     "OR",'L'+128
        .db     "PO",'P'+128
        .db     "PUS",'H'+128
        .db     "RE",'T'+128
        .db     "RET",'I'+128
        .db     "R",'L'+128
        .db     "RL",'C'+128
        .db     "R",'R'+128
        .db     "RR",'C'+128
        .db     "SET",'B'+128
        .db     "SJM",'P'+128
        .db     "SUB",'B'+128
        .db     "SWA",'P'+128
        .db     "XC",'H'+128
        .db     "XCH",'D'+128
        .db     "XR",'L'+128
        .db     "??",'?'+128



bitmnu: .db     'P','0'+128
        .db     "TCO",'N'+128
        .db     'P','1'+128
        .db     "SCO",'N'+128
        .db     'P','2'+128
        .db     'I','E'+128
        .db     'P','3'+128
        .db     'I','P'+128
        .db     'C','0'+128
        .db     "T2CO",'N'+128
        .db     "PS",'W'+128
        .db     'D','8'+128
        .db     "AC",'C'+128
        .db     'E'+'8'+128
        .db     'B'+128
        .db     'F'+'8'+128


