;************************************************ ;* * ;* 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