************************************************* * * * CP/M-68k Basic Disk Operating System * * Exception Handling Module * * * * Version 0.0 -- July 21, 1982 * * Version 0.1 -- July 25, 1982 * * Version 0.2 -- October 6, 1982 * * Version 0.3 -- December 21, 1982 * * * ************************************************* .globl _initexc .globl _tpa_lp .globl _tpa_hp bgetseg = 18 bsetexc = 22 buserr = 2 spurious = 24 trap0 = 32 trap2 = 34 trap3 = 35 endvec = 48 _initexc: * Initialize Exception Vector Handlers * It has 1 passed parameter: the address of the exception vector array move #bsetexc,d0 moveq #2,d1 move.l #exchndl,d2 init1: movem.l d0-d2,-(sp) trap #3 * BIOS call to set exception vector movem.l (sp)+,d0-d2 init2: addq #1,d1 add.l #4,d2 cmpi #spurious,d1 bne init3 move #trap0,d1 init3: cmpi #trap2,d1 beq init2 * don't init trap 2 or trap 3 cmpi #trap3,d1 beq init2 cmpi #endvec,d1 blt init1 * initialize the exception vector array moveq #bgetseg,d0 trap #3 * get the original TPA limits movea.l d0,a0 tst.w (a0)+ move.l (a0)+,d1 * d1 = original low TPA limit move.l d1,d2 add.l (a0),d2 * d2 = original high TPA limit move.l _tpa_lp,d3 * d3 = new low TPA limit move.l _tpa_hp,d4 * d4 = new high TPA limit move #17,d0 movea.l 4(sp),a0 move.l a0,evec_adr * save exception vector address init4: cmp.l (a0),d1 bhi do_init * if old exception outside orig TPA, clear it cmp.l (a0),d2 bls do_init * current exception array entry is in original TPA cmp.l (a0),d3 bhi dontinit * if old exception in old TPA but outside new cmp.l (a0),d4 * TPA, don't clear it bls dontinit do_init: clr.l (a0) dontinit: tst.l (a0)+ dbf d0,init4 rts exchndl: bsr.w except excrtn0: bsr.w except bsr.w except bsr.w except bsr.w except bsr.w except bsr.w except bsr.w except bsr.w except bsr.w except bsr.w except bsr.w except bsr.w except bsr.w except bsr.w except bsr.w except bsr.w except bsr.w except bsr.w except bsr.w except bsr.w except bsr.w except bsr.w except bsr.w except bsr.w except bsr.w except bsr.w except bsr.w except bsr.w except bsr.w except bsr.w except bsr.w except bsr.w except bsr.w except bsr.w except bsr.w except bsr.w except bsr.w except except: clr.w -(sp) movem.l a0/d0,-(sp) * 10 words now on stack in following order: * _______________________________ * |____________D0.L_______________| * |____________A0.L_______________| * |____0000______|________________ * |_______Handler Return__________| * If bus error, extra 2 longs are here * ______________ * |__Status Reg__|________________ * |_____Exception Return__________| move.l 10(sp),d0 * get return address from above array sub.l #excrtn0,d0 * d0 now has 4 * (encoded excptn nmbr), where * encoded excptn nmbr is in [0..21,22..37] * representing [2..23,32..47] cmpi #36,d0 * if d0/4 is in [0..9,22..29] then ble chkredir * the exception may be redirected cmpi #88,d0 blt dfltexc cmpi #116,d0 bgt dfltexc * in range of redirected exceptions subi #48,d0 * subtract 4*12 to normalize [0..9,22..29] * into [0..9,10..17] chkredir: movea.l evec_adr,a0 adda d0,a0 * index into exception vector array tst.l (a0) * if 00000000, then not redirected bne usrexc * not redirected, do default handler cmpi #40,d0 blt dfltexc addi #48,d0 * add 4*12 that was sub'd above dfltexc: adda #14,sp * throw away 7 words that we added to stack asr #2,d0 * divide d0 by 4 * now d0 is in [0..21,22..37] * to represent [2..23,32..47] cmpi #2,d0 * bus or address error? bge nobusexc movem.l (sp)+,a0-a1 * if yes, throw away 4 words from stack nobusexc: tst.w (sp)+ * throw away stacked SR addi #2,d0 cmpi #23,d0 * get back real excptn nmbr in [2..23,32..47] ble lowexc addi #8,d0 lowexc: move d0,-(sp) * save excptn nmbr lea excmsg1,a0 bsr print * print default exception message move (sp)+,d0 bsr prtbyte lea excmsg2, a0 bsr print move.l (sp)+,d0 bsr prtlong lea excmsg3, a0 bsr print clr.l d0 trap #2 * warm boot rte usrexc: * Call user exception handler * make sure exception information is on his stack move.l (a0),10(sp) * put user handler address on our stack move.l usp,a0 * user stack pointer to a0 cmpi #8,d0 * address or bus error? blt addrexc * if yes, skip btst #13,14(sp) * exception occured in user state? bne supstat1 * if no, go to supervisor handler move.l 16(sp),-(a0) * put exception return on user stack move.w 14(sp),-(a0) * put SR on user stack move.l a0,usp * update user stack pointer movem.l (sp)+,a0/d0 * restore regs move.l 2(sp),8(sp) * move address of user handler to excptn rtn addq #6,sp * clear junk from stack andi #$7fff,(sp) * clear trace bit rte * go to user handler addrexc: btst #13,22(sp) * exception occured in user state? bne supstat2 * if no, go to supervisor handler move.l 24(sp),-(a0) * put exception return on user stack move.w 22(sp),-(a0) * put SR on user stack move.l 18(sp),-(a0) * put extra 2 longs on user stack move.l 14(sp),-(a0) move.l a0,usp * update user stack pointer movem.l (sp)+,a0/d0 * restore regs move.l 2(sp),16(sp) * move address of user handler to excptn rtn adda #14,sp * clear junk from stack andi #$7fff,(sp) * clear trace bit rte * go to user handler supstat1: move.w 14(sp),8(sp) * move SR to our exception return bra supstat3 supstat2: move.w 22(sp),8(sp) supstat3: movem.l (sp)+,a0/d0 rte * * Subroutines * print: clr.l d1 move.b (a0)+, d1 beq prtdone move #2, d0 trap #2 bra print prtdone: rts prtlong: * Print d0.l in hex format move d0,-(sp) swap d0 bsr prtword move (sp)+,d0 prtword: * Print d0.w in hex format move d0,-(sp) lsr #8,d0 bsr prtbyte move (sp)+,d0 prtbyte: * Print d0.b in hex format move d0,-(sp) lsr #4,d0 bsr prtnib move (sp)+,d0 prtnib: andi #$f,d0 cmpi #10,d0 blt lt10 addi.b #'A'-'9'-1,d0 lt10: addi.b #'0',d0 move d0,d1 move #2,d0 trap #2 rts .data excmsg1: .dc.b 13,10,10,'Exception $',0 excmsg2: .dc.b ' at user address $',0 excmsg3: .dc.b '. Aborted.',0 .bss evec_adr: .ds.l 1 .end