;MONITOR.S ;Z8000 assembler source file (Zilog syntax) ; ;******************************************************************************** ;* Adapted and documented version of Rolf-Dieter Klein's z8000 (z8002) Monitor * ;* originally published in: * ;* Basic-Interpreter; Funktionsweise und Implementierung in 8080/z80-Computern, * ;* ISBN 3-7723-6942-1 (2nd edition, 1982) * ;******************************************************************************** ; ;Run at DOS command line: Z8000.BAT MONITOR ;Author: Jurjen Kranenborg, okt. 2003 (www.kranenborg.org) ;Note 1: ZASM syntax slightly different from PLZ/ASM ;Note 2: Code developed for Z8001 CPU ;################################################################################ ;# ZASM Assembly starts HERE # ;################################################################################ ;Assembler: Definition of main constants CONSTANT ; NOTE: this keyword MUST be non-indented! ;================================================================================ ;Startup; PSA Area; initialization of z8001 ;Note: all handlers will start in segmented mode (because the handlers are assumed to leave ; with IRET which requires segmented mode) except for the start vector (PSA_reset) ; because this is a jump. PSA_AREA: ; PSA_Area starts at <0>,0000 (=Addr_PSA), for z8001 always in segmented format PSA_reset: ; Reset area .word %0000 ; 1st: unused .word %4000 ; 2nd: FCW set: Nonsegmented, System Mode, Int's disabled .long START1 ; 3rd and 4th: Jump to START1 (begin of monitor program) PSA_extended_instr: ; Program Status for Extended Intruction Trap handler .word %0000 .word %C000 .long TRAP_extended_instr PSA_privileged_instr: ; Program Status for Privileged instructions handler .word %0000 .word %C000 .long TRAP_privileged_instr PSA_SYSCALL: ; Program Status for SYSTEM CALL Trap handler .word %0000 .word %C000 .long SYSCALL PSA_SEGT: ; Program Status for Segmentation Fault Trap Handler .word %0000 .word %C000 .long TRAP_SEGT PSA_NMI: ; Program Status for NMI (Non-maskable Interrupt) Handler .word %0000 .word %C000 .long TRAP_NMI PSA_NVI: ; Program Status for NVI (Non-vectored Interrupt) Handler .word %0000 .word %C000 .long TRAP_NVI PSA_VI_FCW: ; Reserved word and FCW for Vectored Interrupt handlers .word %0000 .word %C000 PSA_VI_0: ; Vectored interrupt handler addresses .long TRAP_VI_0 PSA_VI_2: .long TRAP_VI_2 PSA_VI_4: .long TRAP_VI_4 PSA_VI_6: .long TRAP_VI_6 PSA_VI_8: .long TRAP_VI_8 PSA_VI_10: .long TRAP_VI_10 PSA_VI_12: .long TRAP_VI_12 PSA_VI_14: .long TRAP_VI_14 ;=================================================================================== SCn_TABLE: .long SC0_handler .long SC1_handler .long SC2_handler ;---------------------------------------------------------------- ;SCn_handler: Handler subroutines for SC, #n System Call instructions (separate subroutines for each #n) ; See SYSCALL routine for explanation SC0_handler: RET SC1_handler: RET SC2_handler: RET ;*********************************************************************************** ;START1: Start of monitor program after power-up or RESET ; System Mode ; Segmented mode (to properly initialize stacks and PSA) .seg START1: ; Firstly, initialize the stacks and the PSA LDA RR14, Addr_System_Stack LDA RR12, Addr_Normal_Stack LDA RR10, PSA_AREA LDCTL PSAPSEG, R10 LDCTL PSAPOFF, R11 LDCTL NSPSEG, R12 LDCTL NSPOFF, R13 ; Change to nonsegmented mode for normal conditions (only traps/interrupts use segt code) LDCTL R12, FCW RES R12, #15 ; reset SEG bit LDCTL FCW, R12 .nonseg ; Now initialize the peripherals CALR SUB_INIT_Peripherals ; Finally, enable all interrupts: we're ready for action EI vi, nvi ;========================================================================== ;TRAP_HANDLERS: Area for handling interrupts and software traps. ;Important note: All trap handlers are executed in segmented mode ; as IRET must be handled in segmented mode as well. .seg TRAP_HANDLERS: TRAP_extended_instr: IRET TRAP_privileged_instr: IRET ;-------------------------------------------------------------------------- ;SYSCALL: ; System Call Trap handler, characteristics: ; - Executes in segmented, system mode ; - Is treated as a normal interrupt handling routine, i.e.: ; - Executes with VI, NVI disabled (may be changed however by SCn_handler routines below) ; - SYSCALL returns to calling program with IRET ; - Calls a separate handling procedure SCn_handler for each identifier n in sc #n command ; - SCn_handler must end with RET command, not IRET, in order to return to main SYSCALL handler ; - SCn_handler is executed in segmented, system mode: ; - must finally return to SYSCALL also in segmented, system mode, ; - however may switch to nonsegmented mode before return. ; - SCn_handler may change FCW flags of SC caller program ; - Program Status is saved on stack, all SCn_handler routines deal with the following System Stack: ; ; SP-> #0 SYSCALL<> return address to SYSCALL (after RET is executed) ; #2 SYSCALL<> return address to SYSCALL ( ,, ,, ,, ) ; #4 - Saved R1 (pushed by SYSCALL for workspace) ; #6 - Saved R2 (pushed by SYSCALL ,, ,, ) ; #8 - Saved R3 (pushed by SYSCALL ,, ,, ) ; #10 SC #n instruction (PROGRAM STATUS of SC invoker, used by IRET) ; #12 FCW (PROGRAM STATUS of SC invoker, used by IRET) ; #14 PC<> ; #16 PC<> ; #18 *** (Top of System Stack just before SC #n instruction was executed) ; ; - SCn_handler routines may take VIE, NVIE settings from caller's FCW (#12) to prevent unhandled interrupts ; - SCn_handlers are called using address table SCn_TABLE containing segmented address entries SYSCALL: DEC R15, #6 ;Save workspace registers R1, RR2 LDM @RR14, R1, #3 ; ,, ,, ,, LD R1,RR14(#6) ;Get SC #n instruction CLRB RH1 ;Prepare index for SCn_TABLE (containing subroutine call addrrs for each #n) SLL R1, #4 ; - table contains longword addresses LDL RR2, SCn_TABLE(R1) ;Get #n-th entry (stored in Table SCn_TABLE) and load it in RR2 CALL @RR2 ;Call of SCn_handler nr #n using handler address in RR2 LDM R1, @RR14, #3 ;Workspace not needed anymore, restore registers INC R15, #6 ; ,, ,, ,, ,, IRET TRAP_SEGT: IRET TRAP_NMI: IRET TRAP_NVI: IRET TRAP_VI_0: IRET TRAP_VI_2: IRET TRAP_VI_4: IRET TRAP_VI_6: IRET TRAP_VI_8: IRET TRAP_VI_10: IRET TRAP_VI_12: IRET TRAP_VI_14: IRET ;================================================== ;SUB_INIT_Peripherals: Subroutine to initialize peripherals SUB_INIT_Peripherals: RET ;************************************************** ;************************************************** ;* START of TINY BASIC * ;************************************************** ;************************************************** .nonseg BASIC_START: JP START CI11: SC #1 RET CO11: SC #2 RET CSTS: SC #3 RET START: LDA R15,Addr_Normal_Stack LDB RL1,#%FF INIT: LDB OCSW,RL1 CALR CRLF CRLF: LDB RL1,#%0D OUTC: PUSH @R15, R6 PUSH @R15, R1 LDB RL1, OCSW ORB RL1, RL1 OC2: JR NZ, OC3 POP R1, @R15 POP R6, @R15 RET OC3: POP R1, @R15 PUSH @R15, R1 LDB RL6, RL1 LPT: CPB RL6, #%0D JR Z, LINEF H1: LDB RL1, RL6 CALR CO11 POP R1, @R15 POP R6, @R15 RET LINEF: LDB RL1, #%0D CALR CO11 LDB RL6, #%0A JR H1 ;************************************************** ;Storage memory OCSW: .word(1) Addr_System_Stack: Addr_Normal_Stack: .end