Files
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

357 lines
6.5 KiB
Plaintext

;************************************************
;* *
;* P-CP/M Basic Disk Operating System *
;* Exception Handling Module *
;* *
;* Version 0.0 -- July 21, 1982 *
;* Version 0.1 -- July 25, 1982 *
;* Version 0.2 -- 821014 (Zilog) *
;* Version 0.3 -- 821222 (Zilog) *
;* *
;************************************************
__text: .sect
;****************************************************
;*
;* Externals
;*
;****************************************************
.global _sysseg
.global _tpa_lp
.global _tpa_hp
;****************************************************
;*
;* Globals and Constants
;*
;****************************************************
.global _initexc
BGETSEG .equ 18 ;Bios call to get mem seg tbl
BSETEXC .equ 22 ;Bios call to set xvec
BIOS_SC .equ 3 ;Bios system call
;****************************************************
;*
;* initexc(vecarray) -- initialize exception vector
;*
;* The BDOS maintains its OWN exception vector.
;* This routine sets up the BIOS exception
;* vectors to point to handlers in this module,
;* that vector again using the BDOS vectors.
;*
;* Only vectors 2-23 and 36-38 are handled by
;* the BDOS, leaving 0-1 and 24-35 for the BIOS
;*
;****************************************************
_initexc:
;* sp -> return addr
;* +2 table addr
ld r3,#BSETEXC ; r3 = BDOS command
ldl rr4,#2 ;rr4 = exception #
ld r6,_sysseg ;rr6 -> handler
lda r7,exchndl ; (segmented)
dec r15,#10 ;space to save regs
; on stack over SC
initloop:
ldm @r15,r3,#5
sc #BIOS_SC
ldm r3,@r15,#5
inc r5,#1 ;step exception #
inc r7,#2 ;and handler addr.
cp r5,#24 ;done 23 yet?
jr ne init1 ; no
ld r5,#36 ; yes--skip to 36
inc r7,#8 ; we have entries in
; table for 32-36
; but system uses
; them. Skip.
init1: cp r5,#48 ;done all 48?
jr ne initloop ; no--loop
inc r15,#10 ;clean stack
ld r2,2(r15) ;save vector address
ld evec_adr,r2
ld r0,#18 ; 18 long entries
subl rr4,rr4
init2: ;clear vector array
; should check current entry, and keep it if
; between old TPA and current TPA limits.
; The TPA limits are flaky because we have two TPA's,
; for split and merged spaces, not to mention
; segmented programs.
; What we are going to do is clear the lot.
; Programs that want permanent traps can use the
; Bios to set the trap vector.
ldl rr6,@r2 ; rr6 = exception addr
ldl @r2,rr4
init3:
inc r2,#4
djnz r0,init2
ret ;return
;****************************************************
;*
;* Exception Handler Routine
;*
;* An exception handler is called as a subroutine
;* in segmented mode, with all registers saved
;* on the stack.
;*
;* Returning (ret) from the handler (in segmented
;* mode) will return to the state-restorer.
;*
;****************************************************
exchndl:
calr except
excrtn0:
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
except: ; general exception handler
ldctl r0,FCW ; NONSEGMENTED
res r0,#15
ldctl FCW,r0
popl rr0,@r15 ; get return address
; from above array
sub r1,#excrtn0 ; r1 now = 4*encoded
srl r2,#2 ; exception number
; r1/4 = [0..21, 22..37] represents exceptions
; [2..23, 32..47].
;
; If r1/4 is in the range [0..9, 22..29] then the
; exception may be redirected by the BDOS.
cp r1,#36
jr le chkredir
cp r1,#88
jr lt dfltexc
cp r1,#116
jr gt dfltexc
; in range of redirected exceptions
sub r1,#48 ; subtract 4*12 to normalize [0..9,22..29]
; into [0..9,10..17]
chkredir:
ld r2,evec_adr ; index into exception
; vector array
ldl rr4,r2(r1) ; rr4 -> handler
testl rr4 ; if non-zero
jr nz usrexc ; go do it
;not redirected,
; do default handler
cp r1,#40
jr lt dfltexc
add r1,#48 ; add 4*12 sub'd above
dfltexc:
srl r1,#2 ; divide r1 by 4
; r1 = [0..21,22..37]
; meaning [2..23,32..47]
add r1,#2 ;get back real except#
cp r1,#23
jr le lowexc
add r2,#12
lowexc:
push @r15,r1 ; save exception #
; print default msg
clr r6
ld r7,#excmsg1
calr print
calr prtdollar
pop r1,@r15
calr prtbyte
clr r6
ld r7,#excmsg2
calr print
calr prtdollar
popl rr0,@r15
calr prtlong
clr r6
ld r7,#excmsg3
calr print
clr r5 ; warm boot
sc #2
ret
usrexc: ; call user exception handler
; rr4 -> handler
; user exception handler called in with FCW restored
; to that at the time of the exception, with the
; stack containing a copy of the context block.
; On top of the context block will be a GARBAGE
; return address of the appropriate mode.
; Handler must exit with XFER system call.
; stack now contains:
; return address (long) to trap_ret
; normal r0..r15
; reason, fcw, PC (long)
ld r1,38(r15) ;34+4 r1 = user FCW
bit r1,#14 ;system mode?
jr nz sysexc ; yes
; no
ldl rr2,32(r15) ;28+4 rr2 = user stack
bit r1,#15 ;segmented?
jr nz segusrx ; yes
; no -- get seg
ld r2,42(r15) ;38+4
segusrx:
ldctl r0,FCW ;go segmented
set r0,#15
ldctl FCW,r0
sub r3,#44 ;copy frame to usr
; (with junk PC)
ld r0,#22
ldir @r2,@r14,r0
pushl @r14,rr4 ;go
pushl @r14,rr0
iret
sysexc: ;system mode exc.
set r1,#15 ; go segmented
ldctl FCW,r1
jp @r4 ;go
;****************************************************
;*
;* Subroutines
;*
;****************************************************
print:
ld r5,#9 ;PRINTMSG
sc #2 ;BDOS
ret
prtdollar:
ld r5,#2 ;PRINTCHAR
ldl rr6,#24h ; dollarsign
sc #2
ret
prtlong: ; print rr0 as hex long
push @r15,r1
ex r0,r1
calr prtword
pop r1,@r15
prtword: ; print r1 as hex word
push @r15,r1
ldb rl1,rh1
calr prtbyte
pop r1,@r15
prtbyte: ; Print rl1 as hex byte
push @r15,r1
srl r1,#4
calr prtnib
pop r1,@r15
prtnib:
and r1,#15
cp r1,#10
jr lt lt10
add r1,#7
lt10:
add r1,#30h
ld r7,r1
ld r5,#2 ;PRINTBYTE
sc #2 ;BDOS
ret
;****************************************************
;*
;* data
;*
;****************************************************
__data: .sect
excmsg1:
.byte 13,10,10,"Exception $"
excmsg2:
.byte " at user address $"
excmsg3:
.byte ". Aborted.$"
;****************************************************
;*
;* bss
;*
;****************************************************
__bss: .sect
evec_adr:
.block 2
.end