home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
cpm
/
debug
/
wadesrc.lbr
/
MONBREAK.AZM
/
MONBREAK.ASM
Wrap
Assembly Source File
|
1988-06-19
|
16KB
|
1,013 lines
title 'Break/Trace/Display Module for Monitor'
;
; Last Edited 85-04-27 Wagner
;
; Copyright (c) 1984, 1985 by
;
; Thomas Wagner
; Patschkauer Weg 31
; 1000 Berlin 33
; West Germany
;
; Released to the public domain 1987
;
;
maclib z80
maclib monopt
;
public break
;
public display,disalt,disyvars
;
IF hilo
public dishighlow
ENDIF
;
public initbreak,unbreak,dotrace
public deletebk,definebk,addbk,resetbk,nresetbk
;
public numbreaks,breaklist
public regi,regiff,regbc,regpc,regsp,altbc,iffstr
;
extrn initcio
extrn resetrst
extrn string
;
IF extended
public cbank
extrn peek,poke,currbank,peekbuf,xltbank
ENDIF
;
extrn goto
extrn wrstr,wrchar,wrhex,wrword,space,space2,crlf,tkbint
extrn mexpression
extrn monitor,cmderr,stack
extrn disasm,analop,jumpaddr,jumpmark
extrn tracecount,trcallopt,tracejp,tracenl,traceexp,traceptr
extrn bkexpbuf,protexpbuf
extrn listaddr,restart,rstloc
extrn variables
;
IF hilo
extrn lowval
ENDIF
;
cseg
;
maxbreaks equ 8
;
;
; Display:
;
;123456789.123456789.123456789.123456789.
;F=76543210 A=xx BC=xxxx DE=xxxx HL=xxxx IX=xxxx PC=xxxx instruction
; IFF=x I=xx IY=xxxx SP=xxxx (xxxx xxxx xxxx xxxx xxxx) LD (IX+00),00
;F'=76543210 A'=xx BC'=xxxx DE'=xxxx HL'=xxxx M=xx
;
;F=76543210 A=xx BC=xxxx DE=xxxx PC=xxxx 12345678: 1234567890123456 .1234567
;IFF=x I=xx HL=xxxx IX=xxxx IY=xxxx SP=xxxx (xxxx xxxx)
;
;
; disflags: Display flag register
;
disflags:
push psw
call disregnam
pop psw
lxi h,flagnames
mvi b,8
disfll:
rlc
push psw
jrnc disfloff
mov a,m
jr disflxx
disfloff:
mvi a,'.'
disflxx:
call wrchar
inx h
pop psw
djnz disfll
jmp space
;
flagnames db 'SZxHxPNC'
;
;
;
; display: display CPU state (primary regs only)
;
display:
lxi d,reg1nam
lda regf
call disflags ; display flags
lxi h,rega
call dis8reg ; display A
;
lxi h,regbc
IF symbolic
mvi b,2
ELSE
mvi b,3
ENDIF
displ10:
call dis16reg ; display BC, DE, HL
djnz displ10
IF NOT symbolic
lxi h,regix
call dis16reg ; IX
ENDIF
;
call disregnam ; 'PC='
IF extended
lda cbank
ENDIF
lhld regpc
mvi b,0
call disasm ; disassemble at PC
shld newpc ; save next PC
call crlf
;
lxi d,reg2nam
call disregnam ; 'IFF='
lda regiff
ani 1
ori 30h
call wrchar ; display IFF
call space
lxi h,regi
call dis8reg ; display I
;
IF symbolic
lxi h,reghl
call dis16reg
lxi h,regix
call dis16reg
call dis16reg
;
ELSE
;
lxi h,regiy
call dis16reg ; IY
ENDIF
;
call disregnam ; 'SP='
lhld regsp
call wrword ; display SP
call space
IF extended
lda cbank
call peek
ENDIF
mvi a,'('
call wrchar
IF symbolic
mvi b,2
ELSE
mvi b,5 ; display 5 words at bottom of stack
ENDIF
IF extended
lxi h,peekbuf
ENDIF
displayl3:
mov e,m
inx h
mov d,m
inx h
xchg
call wrword ; display (SP)
xchg
dcr b
jrz displayend
call space
jr displayl3
;
displayend:
mvi a,')'
call wrchar
jmp crlf
;
IF symbolic
;
reg1nam db 'F=A=BC=DE=PC='
reg2nam:
iffstr db 'IFF=I=HL=IX=IY=SP='
;
ELSE
;
reg1nam db 'F= A=BC=DE=HL=IX=PC='
reg2nam db ' '
iffstr db 'IFF= I=IY=SP='
;
ENDIF
;
;
; disalt: display alternate registers
;
disalt:
lda altaf
lxi d,reganam
call disflags
lxi h,altaf+1
call dis8reg ; display A'
lxi h,altbc
mvi b,3
disaltlp:
call dis16reg ; display BF', DE', HL'
djnz disaltlp
IF extended
lxi h,cbank
call dis8reg
ENDIF
jmp crlf
;
;
reganam db 'F''=A''=BC''=DE''=HL''='
IF extended
db ' X='
ENDIF
;
; disyvars: display Y-variables
;
disyvars:
lxi h,variables
mvi b,10
mvi c,'0'
disylp:
mvi a,'Y'
call wrchar
mov a,c
call wrchar
mvi a,'='
call wrchar
call disword
call space
inr c
mov a,c
cpi '5'
cz crlf
djnz disylp
jmp crlf
;
;
IF hilo
;
; dishighlow: display High, Low and Max
;
dishighlow:
lxi d,hilostr
lxi h,lowval
mvi b,4
dishilo10:
call dis16reg
djnz dishilo10
jmp crlf
;
hilostr db 'Low= High= Max= Top='
;
ENDIF
;
dis8reg:
call disregnam
mov a,m
call wrhex
jmp space
;
;
dis16reg:
call disregnam
call disword
jmp space
;
;
disword:
push d
mov e,m
inx h
mov d,m
inx h
xchg
call wrword
xchg
pop d
ret
;
;
disregnam:
ldax d
inx d
call wrchar
cpi '='
rz
jr disregnam
;
;
;------------------------------------------------------------------------------
;
;
; Breakpoint Entry
;
;
break:
sspd savsp ; save stackpointer
lxi sp,breakstack ; register save area
push psw ; AF
ldai
push psw ; I & IFF
IF disint
DI
ENDIF
pushiy
pushix
push h ; dummy (AF)
push h ; dummy (SP)
push h ; HL
push d
push b
;
exaf
push psw ; AF'
exx
push h ; dummy (no SP')
push h ; HL'
push d ; DE'
push b ; BC'
exx
exaf ; back to old register set
lxi sp,stack ; local stack
;
xra a
sta regiff ; so peek does not enable interrupts
IF extended
call currbank
sta cbank
ENDIF
lhld savsp ; stackpointer on entry
IF extended
call peek
lxi h,peekbuf
ENDIF
mov e,m
inx h
mov d,m ; location at stackpointer = retaddr
lhld savsp
inx h
inx h ; point before retaddr on stack
xchg ; retaddr into HL
dcx h ; address at RST
IF extended
lda cbank
call peek
lda peekbuf
ELSE
mov a,m
ENDIF
push h
lxi h,restart
cmp m ; is it RST ?
pop h
jrnz break15 ; leave pc as is if not
lda breaklist
mov b,a
push d
IF extended
lda cbank
call xltbank
ENDIF
call searchbk ; is it a breakpoint ?
pop d
jrz break20 ; then reset PC to RST
break15:
inx h ; else leave PC as it is
break20:
xchg
shld regsp ; store corrected SP
lhld regpc ; this contains I & IFF
sded regpc ; set corrected PC
sded listaddr ; new default list address
shld regiff ; store iff elsewhere
lhld savaf
shld regaf ; store AF at correct place
;
lda regiff
rrc
rrc
ani 1
push psw
xra a
sta regiff
call resetbk ; reset breakpoints
pop psw
sta regiff ; shift P/V-Flag for IFF
IF disint
jrz break80 ; exit if interrupts disabled
ei ; else re-enable
ENDIF
;
break80:
call initcio
lhld regpc ; current PC
lda numbreaks
mov b,a
;
IF zeroboot
mov a,h
ora l
jz breakwarm ; jump if warmboot
ENDIF
;
IF extended
lda cbank
call xltbank
ENDIF
call searchbk ; is this a normal breakpoint ?
jrnz breaktr ; check trace if not
ldy a,3 ; conditional break ?
ani 80h
jz breakexit ; exit if not conditional
lxix bkexpbuf
call mexpression ; evaluate condition
jc breakexit ; exit if bad
mov a,h
ora l
jnz breakexit ; exit if condition met
lhld tracecount
mov a,h
ora l
jrnz breaktr ; go trace if condition false
call tkbint
jrnz breakexit
jmp gounbreak ; continue if condition not met
;
;
breaktr:
lhld tracecount ; are we tracing ?
mov a,h
ora l
jrnz breaktr10 ; then check trace conditions
lda temptrace
ora a
jnz gounbreak ; go if temporary trace
jr breakexit
;
breaktr10:
lda tracejp ; jumps only ?
ora a
jrz breaktr20 ; next if not
lhld regpc
IF extended
lda cbank
ENDIF
call analop ; analyse opcode
lda jumpmark ; jump ?
ora a
jrz brkdotr ; no list if no jump
;
breaktr20:
lda traceexp ; while/until ?
ora a
jrz break85 ; continue if not
;
; trace while/until
;
lixd traceptr ; load expression pointer
call mexpression
jrc breakexit ; exit on error
lda traceexp
rlc
jrc breakuntil
mov a,h
ora l
jrz breakexit ; trace while: exit if false
jr break85
breakuntil:
mov a,h
ora l
jrnz breakexit ; trace until: exit if true
;
break85:
lda traceexp
ora a
jrnz break91 ; no decrease if expression
lhld tracecount
dcx h ; else decrease count
shld tracecount
mov a,h
ora l
jrz breakexit ; and exit if zero
break91:
lda tracenl ; no list ?
ora a
jrz breakdis ; go if no list
brkdotr:
call tkbint ; check for int from keyboard
jrnz breakexit
jmp dotrace
;
breakdis:
call display ; display if list on
jmp dotrace ; and continue tracing
;
IF zeroboot
breakwarm:
lxi h,wbootmsg
call wrstr
ENDIF
;
breakexit:
call display ; display next opcode
jmp monitor
;
IF zeroboot
wbootmsg db 0dh,0ah,'WARM BOOT',0dh,0ah,0
ENDIF
;
;------------------------------------------------------------------------------
;
; unbreak: return from break
;
;
gounbreak:
lda numbreaks
mov b,a
unbreak:
xra a
sta temptrace
ora b
jrz untrace ; go if no breakpoints
push b
lhld regpc
IF extended
mvi a,0ffh
call xltbank
ENDIF
call searchbk ; break set at PC ?
pop b
jrnz untrace ; ok if not
mvi a,0ffh
sta temptrace ; mark temporary trace
jmp normtrace ; trace one op if break at PC
;
;
; untrace: return from break, tracing on
;
; entry: B = number of breakpoints (including temporary)
;
untrace:
IF disint
DI
ENDIF
lda regiff
push psw
xra a
sta regiff
call setbk
pop psw
sta regiff
;
lxi sp,altbc ; restore registers
exx
pop b
pop d
pop h
exx
pop psw ; i & iff
stai
exaf
pop psw
exaf
pop b
pop d
pop h
pop psw ; dummy (SP)
pop psw ; AF
popix
popiy
lxi sp,string+80
jmp goto ; go to program
;
;
;------------------------------------------------------------------------------
;
;
; setbk: set breakpoints
;
; entry: B = number of breakpoints
;
setbk:
lxix breaklist+1
stx b,-1
mov a,b
ora a
rz ; ret if no breakpoints
mvi c,5
lded regpc
setbkloop:
ldx l,0
ldx h,1
IF extended
ldx a,2
call peek
lda peekbuf
ELSE
mov a,m
ENDIF
stx a,4 ; save previous memory contents
IF extended
lda cbank
cmpx 2
jrz setbklp4 ; check pc if same bank
ldx a,2
inr a ; default bank ?
jrnz setbklp5 ; branch if different bank
ENDIF
setbklp4:
ora a
IF NOT extended
push h
dsbc d
pop h
ELSE
dsbc d
ENDIF
jrz setbklp10 ; dont set break at current PC
setbklp5:
lda restart
IF extended
sta peekbuf
call poke
ELSE
mov m,a
ENDIF
setbklp10:
mov a,b
mvi b,0
dadx b
mov b,a
djnz setbkloop
ret
;
;
; resetbk: reset breakpoints and restart location
; nresetbk: reset breakpoints only
;
resetbk:
call resetrst
nresetbk:
lxix breaklist+1
ldx b,-1
mov a,b
ora a
rz ; ret if no breakpoints
lda numbreaks
stx a,-1 ; reset number of breakpoints
lxi d,5
resbkloop:
ldx l,0
ldx h,1
IF extended
ldx a,2
call peek
lda peekbuf
lxi h,restart
cmp m
ELSE
lda restart
cmp m
ENDIF
jrnz resbk1
ldx a,4
IF extended
sta peekbuf
call poke
ELSE
mov m,a
ENDIF
resbk1:
dadx d
djnz resbkloop
ret
;
;
;------------------------------------------------------------------------------
;
; dotrace: execute one opcode, then break
;
dotrace:
xra a
sta temptrace
lxix protexpbuf ; protection
call mexpression
jrc normtrace ; ok if no protection
mov a,h
ora l
jrz normtrace ; ok if expression false
;
; protected region, set break to return address
;
call tratsp
lda numbreaks
mov b,a
mvi a,0ffh ; default bank
call addbk ; set as temp breakpoint
jmp untrace
;
; normal trace
;
normtrace:
lhld regpc
IF extended
lda cbank
ENDIF
call analop
shld newpc
lda numbreaks ; number of breakpoints
mov b,a
lda jumpmark
ora a ; jump/call/ret instruction ?
jrnz dotrjump ; then we have to set a different break
dotr10:
lhld newpc ; next location
mvi a,0ffh
call addbk ; set as temporary breakpoint
jmp untrace ; execute
;
dotrjump:
ani 070h
cpi 20h
jrc dotrjimm ; 10 is immediate
jrnz dotrjreg ; 30 is to register
call tratsp ; 20 is to stack
dotrj10:
mvi a,0ffh
call addbk ; set as temp breakpoint
lda jumpmark
ani 80h ; conditional ?
jz untrace ; go exec if not
jr dotr10 ; enter normal
;
dotrjimm:
lhld jumpaddr ; immediate
lded regpc ; same as current PC ?
ora a
dsbc d
jrnz dotrjimmok ; ok if not same
IF extended
lda peekbuf ; peekbuf contains current opcode
ELSE
ldax d
ENDIF
cpi 10h ; DJNZ ?
jnz cmderr ; abort if not
jr dotr10 ; enter normal addr instead of jumpaddr
;
dotrjimmok:
lhld jumpaddr
lda jumpmark
ani 1 ; call ?
jrz dotrj10 ; ok if not
lda trcallopt ; trace over calls ?
ora a
jrnz dotr10 ; set normal break if yes
jr dotrj10 ; else continue
;
dotrjreg:
lda jumpmark
ani 7
add a
mov e,a
mvi d,0
lxi h,regbc
dad d
mov e,m
inx h
mov d,m
xchg
jr dotrj10
;
;
tratsp:
lhld regsp ; get return address
IF extended
lda cbank
call peek
lxi h,peekbuf
ENDIF
mov e,m
inx h
mov d,m
xchg
ret
;
;------------------------------------------------------------------------------
;
; addbk: add a breakpoint to the list if not already present
;
; entry: HL = breakpoint address
; B = current number of breakpoints
; A = breakpoint bank
;
; exit: B = B + 1
;
addbk:
IF extended
cpi 0ffh
jrnz addbk1
call xltbank
ENDIF
addbk1:
call searchbk
rz ; no change if already defined
sty l,0
sty h,1
sty a,2
mviy 0,3 ; clear condition flag
inr b
ret
;
;
; searchbk: search for breakpoint
;
; entry: A/HL = address
; B = number of breakpoints
;
; exit: zero-flag set if found
; C = index if found
; IY = breaklist pointer (end of list if not found)
;
searchbk:
mov d,a
mov e,b
lxiy breaklist+1
mov a,b
ora a
jrnz searchbk10
dcr a
mov a,d
ret
searchbk10:
mvi c,0
searchbk20:
ldy a,0
cmp l
jrnz searchbk25 ; no match if not same address
ldy a,1
sub h
jrnz searchbk25
IF extended
ldy a,2
cmp d
jrnz searchbk25 ; no match if not same bank
ENDIF
mov b,e ; match, return
mov a,d
ret
;
searchbk25:
push d
lxi d,5
dady d
pop d
inr c
djnz searchbk20
ori 0ffh
mov b,e
mov a,d
ret
;
;
; delbk: delete breakpoint
;
; entry: IY = pointer to breakpoint list element
; C = index
;
delbk:
lxi h,numbreaks
dcr m
mov a,m
sta breaklist
sub c ; elements after this element
rz ; ready if nothing to move
mov c,a
delbklp:
mvi b,5
delbk10:
ldy a,5
sty a,0
inxiy
djnz delbk10
dcr c
jrnz delbklp
ret
;
;
; deletebk: delete breakpoint
;
; entry: A/HL = address
;
deletebk:
pushiy
push psw
lda numbreaks
mov b,a
pop psw
IF extended
cpi 0ffh
cz xltbank
ENDIF
call searchbk
jnz cmderr
call delbk
popiy
ret
;
;
; definebk: add breakpoint
;
;
definebk:
push b
lbcd numbreaks-1 ; get numbreaks into B
call addbk
mvi a,maxbreaks
cmp b
jc cmderr
mov a,b
pop b
sty c,3 ; set condition flag
sta numbreaks
sta breaklist
ret
;
;
; initbreak: init module variables
;
initbreak:
lxi h,vars
lxi d,vars+1
lxi b,varspace-1
mvi m,0
ldir ; clear registers & breakpoints
IF extended
call currbank
sta cbank ; init current bank
ENDIF
ldai
sta regi ; init I-reg
rpo ; leave IFF = 0 if interrupts disabled
mvi a,1
sta regiff ; init IFF
ret
;
;
dseg
;
vars:
;
altbc ds 2
altde ds 2
althl ds 2
regiff ds 2 ; no alternate SP
regi equ regiff+1
altaf ds 2
;
regbc ds 2
regde ds 2
reghl ds 2
regsp ds 2
regaf ds 2
regf equ regaf
rega equ regaf+1
regix ds 2
regiy ds 2
regpc ds 2
;
savaf ds 2
breakstack equ $
;
savsp ds 2
retloc ds 2
newpc ds 2
;
IF extended
cbank ds 1
ENDIF
;
temptrace ds 1
numbreaks ds 1
breaklist ds (maxbreaks+2)*5+1
;
; Break list format:
;
; db number of active entries
; each entry:
; dw address
; db bank (unused for non-extended version)
; db condition-flag
; db storage for original contents of location
;
varspace equ $-vars
;
end