;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<<seg>> return address to SYSCALL (after RET is executed)
;				#2	SYSCALL<<off>> 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<<seg>>
;				#16	PC<<off>>
;				#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


