;************ biostrap.z8k ************************** ;* ;* Trap handlers for P-CP/M (tm) BIOS ;* ;* 821013 S. Savitzky (Zilog) -- created ;* 821123 D. Dunlop (Zilog) -- added Olivetti M20- ;* specific code to invalidate track buffer ;* contents when disk drive motor stops ;* (fixes directory-overwrite on disk change) ;* ; 01/12/83 Adapted for Z8002 (DMH) __text: .sect ;**************************************************** ;* ;* NOTE ;* Trap and interrupt handlers are started up ;* in segmented mode on the Z8001. ;* ;**************************************************** .input "biosdefs2.z8k" ;**************************************************** ;* ;* Externals ;* ;**************************************************** .global __bios ;C portion of BIOS .global memsc ;memory-management SC .global _sysseg, _usrseg, _sysstk, _psap ;**************************************************** ;* ;* Global declarations ;* ;**************************************************** .global _trapinit .global _trapvec .global _trap .global xfersc ;**************************************************** ;* ;* Trap vector table ;* ;* entries 0..31 are misc. system traps ;* entries 32..47 are system calls 0..15 ;* ;**************************************************** __bss: .sect _trapvec: .block NTRAPS*4 ; leave trap space same as for Z8001, ; for compatibility ;**************************************************** ;* ;* System Call and General Trap Handler And Dispatch ;* ;* It is assumed that the system runs ;* non-segmented on a segmented CPU. ;* ;* _trap is jumped to with the ;* following information on the stack: ;* ;* trap type: WORD ;* reason: WORD ;* fcw: WORD ;* pc: WORD ;* ;* The trap handler is called as a subroutine, ;* with all registers saved on the stack. This ;* allows the trap handler to be in another ;* segment (with some care). This is useful ;* mainly to the debugger. ;* ;* All registers except rr0 are also passed ;* intact to the handler. ;* ;**************************************************** __text: .sect sc_trap: ; system call trap server push @r15,@r15 ; duplicate type as reason _trap: ; general trap server sub r15,#FRAMESZ-8 ; push caller state ldm @r15,r0,#15 ldctl r1,NSP ex r1,nr15(r15) ; trap# now in r1 cpb rh1,#7Fh ; system call? jr ne trap_disp ; no ; yes: map it clrb rh1 add r1,#SC0TRAP ;=== need range check === trap_disp: ; dispatch sll r1,#2 ldl rr0,_trapvec(r1) testl rr0 jr z _trap_ret ; zero -- no action call @r1 ; go execute the trap _trap_ret: ;return from trap or interrupt ld r1,nr15(r15) ; pop state ldctl NSP,r1 ldm r0,@r15,#15 add r15,#FRAMESZ-6 ; re-adjust stack iret ; return from interrupt ;**************************************************** ;* ;* Assorted Trap Handlers ;* ;**************************************************** epu_trap: push @r15,#EPUTRAP jr _trap pi_trap: push @r15,#PITRAP jr _trap seg_trap: push @r15,#SEGTRAP jr _trap nmi_trap: push @r15,#NMITRAP jr _trap ;**************************************************** ;* ;* Bios system call handler ;* ;**************************************************** biossc: ; call bios ; r3 = operation code ; rr4= P1 ; rr6= P2 ; set up C stack frame ;=== pushl @r15,rr6 pushl @r15,rr4 push @r15,r3 ; call C program call __bios ; clean stack & return add r15,#10 ldl cr6+co(r15),rr6 ; with long in rr6 ret ;**************************************************** ;* ;* Context Switch System Call ;* ;* xfer(context) ;* long context; ;* ;* context is the physical (long) address of: ;* r0 ;* ... ;* r13 ;* r14 (normal r14) ;* r15 (normal r15) ;* ignored word (trap reason) ;* FCW (had better specify normal mode) ;* PC offset ;* ;* The system stack pointer is not affected. ;* ;* Control never returns to the caller. ;* ;**************************************************** xfersc: ;enter here from system call ; build frame on system stack ; when called from system call, the frame replaces ; the caller's context, which will never be resumed. inc r15,#co ; discard return addr ld r5,r15 ; move context ld r2,#FRAMESZ/2 ldir @r5,@r7,r2 dec r5,#2 ;point back to PC ldi @r5,@r7,r2 ;transfer PC jr _trap_ret ;restore context ;**************************************************** ;* ;* _trapinit -- initialize trap system ;* ;**************************************************** ;* ;* PSA (Program Status Area) structure ;* ps .equ 4 ; size of a program status entry ; --- non-segmented --- psa_epu .equ 1*ps ; EPU trap offset psa_prv .equ 2*ps ; priviledged instruction trap psa_sc .equ 3*ps ; system call trap psa_seg .equ 4*ps ; segmentation trap psa_nmi .equ 5*ps ; non-maskable interrupt psa_nvi .equ 6*ps ; non-vectored interrupt psa_vi .equ 7*ps ; vectored interrupt psa_vec .equ psa_vi+(ps/2) ; vectors _trapinit: ; initialize trap table lda r2,_trapvec ld r0,#NTRAPS subl rr4,rr4 clrtraps: ldl @r2,rr4 inc r2,#4 djnz r0,clrtraps ld r2,_sysseg lda r3,biossc ldl _trapvec+(BIOS_SC+SC0TRAP)*4,rr2 lda r3,memsc ldl _trapvec+(MEM_SC+SC0TRAP)*4,rr2 ; initialize some PSA entries. ; r0 PSA entry: FCW (ints ENABLED) ; r1 PSA entry: PC ; r5 -> PSA slot ld r5,_psap ld r0,#0D800h add r5,#ps ; skip reserved to EPU trap ld r1,#epu_trap ldm @r5,r0,#2 add r5,#ps ; Priviledged Inst ld r1,#pi_trap ldm @r5,r0,#2 add r5,#ps ; System Call ld r1,#sc_trap ldm @r5,r0,#2 add r5,#ps ; segmentation ld r1,#seg_trap ldm @r5,r0,#2 add r5,#ps ; Non-Maskable Int. ld r1,#nmi_trap ldm @r5,r0,#2 ret ;**************************************************** ;****************************************************