;	FILE MESA-NOVA1.ASM
;	R. JOHNSSON
;	LAST MODIFIED March 23, 1979  11:38 AM
	.TITL MesaNova1
	.TXTM B
;
	.ENT EMLOOP
	.ENT MesaNova1
	.ENT MesaNovaSize1
	.ENT AC0Ptr
	.ENT AC1Ptr
	.ENT AbsoluteTXV
	.ENT CleanUpQueueUser
	.ENT RequeueSubUser
	.ENT WakeHeadImplementer
	.ENT STOPUser
	.ENT AdvanceTimerPtr
	.ENT processTrapPtr
	.ENT firstProcessPtr
	.ENT lastProcessPtr
	.ENT firstStateVectorPtr
;
	.SREL
EMLOOP:	EMLP-TXV	;WHERE TO START RUNNING
MesaNova1: TXV
MesaNovaSize1: END-TXV
AC0Ptr:	currentState
AC1Ptr:	WASAC1
AbsoluteTXV: X	; To check compatibility
CleanUpQueueUser: CleanUpQueue
RequeueSubUser: RequeuePtr
WakeHeadImplementer: WakeHead-TXV+X
STOPUser: pSTOP
AdvanceTimerPtr: AdvanceTimer-TXV+X
processTrapPtr: processTrap
firstProcessPtr: firstProcess
lastProcessPtr: lastProcess
firstStateVectorPtr: firstStateVector
;
	.NREL
	.GET "Mesa-NovaDefs.asm"

X = 25		; The absolute location of TXV at run time


TXV:	EMLP-TXV+X	; Microcode expects this to be in location 25
	MSTOP-TXV+X
	ME-TXV+X
	MXD-TXV+X
	MRE-TXV+X
	MXW-TXV+X
	NOTIFY-TXV+X
	BCAST-TXV+X
	REQUEUE-TXV+X
	77400
	77400

CVArray:	; This will be location 40
	0
	0
	0
	0
	0
	0
	0
	0
	0
	0
	0
	0
	0
	0
	0
	0

MSTOP:	JMP @pSTOP
pSTOP:	0


;
; Locations for saving accumulators
WASAC1:	0
trapmask: abortPending;+timeoutPending ; make timeout not trap
processTrap: 0

; Monitor ReEntry(@Monitor,cvptr)
MRE:
	sta	1 cvptr
	jsr	Enter
	mov	0 0 snc		; if failed
	  jmp	EMLP1		; then return
	lda	0 cvptr
	jsr	@CleanUpQueue
	lda	2 currentPSB
	mkzero	0 0
	sta	0 cleanUpLink,2	; cleanUpLink ← clean
	sta	0 hardMRE	; hardMRE ← FALSE
	lda	0 trapmask
	lda	1 bitsandpriority,2
	and#	0 1 snr		; if no timeout or abort
	  jmp	EnterTrue	;   then return
	lda	2 currentState	; cause a trap in the current state
	lda	1 dest,2
	sta	1 source,2	; make the dest be the source
	lda	1 @processTrap
	sta	1 dest,2	; and cause a call to SD[sProcessTrap]
	jmp	EMLP1

Enter:		;(@Monitor) returns carry=1 iff success
	mov	0,2		; copy pointer
	lda	0 lockqueue,2	; get lock and queue word
	movzl	0 0		; lock bit to carry
	movl	1 1		; store carry in low-order AC1
	movzr	0 0		; set lock bit to 0 = locked
	sta	0 lockqueue,2	; store value back
	movzr	1 1 szc		; test and remove lock bit
	  jmp 0,3		; done, carry=1
EnterFail:	
	sta	3 EXWreturn
	mov	2 1		; assumes queue=0
	lda	2 currentPSB
	lda	0 bitsandpriority,2
	movl	0 0
	movor	0 0
	sta	0 bitsandpriority,2 ; set enterfailed ← TRUE
	lda	0 pReadyList
	jsr	RequeueSub;(pReadyList,@Monitor.queue,currentPSB)
	movz	0 0		; set carry=0
	jmp	@EXWreturn

REQUEUE:	;(@from,@to,p)
	jsr	RequeueSub
	jmp	EMLP1

TabortPending: abortPending
ReSchedulePending: 0
clStateVector: lStateVector

; Monitor Exit and Depart(@Monitor)
MXD:
	jsr	Exit
	jmp	EMLP1


NoneReady:
	EIR
EMLP:	DIR
EMLP1:	LDA 1 WASAC1
	LDA 0 currentState
	LDA 2 ReSchedulePending
	SNZ 2 2
	  61010	; JMPRM
ReSchedule:
	lda	3 readyList
	snz	3 3
	  jmp	NoneReady
	sub	0 0
	sta	0 ReSchedulePending
	lda	3 link,3	; pReadyList↑↑.link
	lda	2 currentPSB
	;sne	2 3
	  ;jmp	EMLP
	sta	3 currentPSB	; store new PSB
	lda	3 currentState
	lda	0 dest,3
	sta	0 frame,2
	lda	3 currentPSB
	lda	1 bitsandpriority,3
	movzl	1 0		; carry ← enterfailed
	cycle	17
	sta	0 bitsandpriority,3 ; enterfailed ← FALSE
	lda	0 TabortPending
	and	1 0		; isolate abortPending
	lda	2 cleanUpLink,3
	add	2 0
	sta	0 hardMRE	; non zero if aborted or cleanUpLink # 0
	lda	0 mPriority
	and	0 1		; isolate priority
	lda	0 @firstStateVector
	lda	2 clStateVector
	mul			; AC1 ← priority*lStateVector+firstStateVector
	sta	1 currentState
	mov	1 2
	lda	1 frame,3
	sta	1 dest,2
	mov	0 0 snc
	  jmp	EMLP1
	jmp	EnterFalse

mPriority: priority
firstStateVector: 0

; Monitor Exit and Wait(@Monitor,cvptr,timeout)
MXW:
	sta	1 cvptr
	sta	2 savetimeout
	jsr	Exit
	lda	0 cvptr
	jsr	@CleanUpQueue
	lda	2 currentPSB
	lda	1 TabortPending
	lda	0 bitsandpriority,2
	and#	1 0 szr		; test abortPending
	  jmp	EMLP1		;  aborted, don't stop
	lda	3 @cvptr
	movzl	3 3 snc		; test ww bit
	  jmp	MXWq
	sta	3 @cvptr	; ww set, clear it and don't stop
	jmp	EMLP1


MXWq:	lda	1 TwaitingOnCV
	add	1 0
	sta	0 bitsandpriority,2
	lda	0 pReadyList
	lda	1 cvptr
	jsr	RequeueSub;(pReadyList,cvptr,currentPSB)
	lda	3 savetimeout
	snz	3 3
	  jmp	EMLP1
	lda	0 timer
	add	0 3 snr
	  inc	3 3		; zero means no timeout, store 1 instead
	sta	3 timeout,2	; currentPSB.timeout ← timer+timeout
	jmp	EMLP1

CleanUpQueue:	0	;(q) returns (q)

RequeueSub:	sta	2 ReSchedulePending	
	jmp	@RequeuePtr
RequeuePtr:	0	; (q1,q2,p)

EXWreturn: 0

cvptr:	0
savetimeout: 0
TwaitingOnCV: waitingOnCV
FtimeoutAllowed: 0-timeoutAllowed-1
pReadyList: readyList

; Monitor Entry(@Monitor)
ME:
	jsr	Enter
	mov	0 0 snc		; if failed
	  jmp	EMLP1	;   then reschedule
EnterTrue:
	subzl	0 0 skp
EnterFalse:
	sub	0 0
	lda	2 currentState
	sta	0 stk0,2	; store return value
	mkone	0 0
	sta	0 stkp,2	; stkp ← 1
	jmp	EMLP1

NOTIFY:		;(cvptr)
	jsr	@CleanUpQueue
	jsr	WakeHead
	jmp	EMLP1

BCAST:		;(cvptr)
	jsr	@CleanUpQueue
	sta	0 cvptr
BCASTloop:
	lda	0 cvptr
	jsr	WakeHead
	movzl#	2 2 szr		; = process notified or 0 if none; ignore ww
	  jmp	BCASTloop
	jmp	EMLP1

Exit:		;(@Monitor) returns carry=1 iff requeue was called
	sta	0 saveq
	sta	3 EXWreturn
	lda	1 @saveq
	mov	1 2 snr		; if mq↑ = NIL
	  jmp	exitstore	; low-order zero will go to carry

	lda	1 pReadyList
	; 0  correct from above
	lda	2 link,2	; p ← mq↑↑.link
	jsr	RequeueSub;(@Monitor.queue,pReadyList,Monitor.queue.link)
	lda	1 @saveq
	movol	1 1		; low-order one will go to carry
exitstore:
	movor	1 1		; set lock to 1 = unlocked
				; carry ← 1 iff requeue happened
	sta	1 @saveq
	jmp	@EXWreturn

saveq:	0

WakeHead:	;(cvptr)
	sta	3 EXWreturn
	mov	0 3
	lda	2 0,3		; cvptr↑
	movzl#	2 2 snr		; test for process = 0, ignore ww
	  jmp	@EXWreturn
	lda	2 link,2	; cvptr↑↑.link
	lda	1 bitsandpriority,2
	lda	3 FwaitingOnCV
	and	3 1
	sta	1 bitsandpriority,2
	lda	1 pReadyList
	jsr	RequeueSub;(cvptr,pReadyList,cvptr↑)
	jmp	@EXWreturn

FwaitingOnCV: 0-waitingOnCV-1

timer:	0
timeflag: -3
timeconst: -3

AdvanceTimer:
	isz	timeflag
	  bri
	lda	0 timeconst
	sta	0 timeflag
	isz	timer
	  nop
	lda	2 @firstProcess
loop:	lda	1 timeout,2
	snz	1 1
	  jmp notready
	lda	0 timer
	seq	0 1
	  jmp	notready
	lda	0 FwaitingOnCV
	lda	1 bitsandpriority,2
	and	0 1		; p.waitingOnCV ← FALSE
	sta	1 bitsandpriority,2
	sub	0 0
	lda	1 pReadyList
	jsr	RequeueSub;(NIL,pReadyList,p) -- returns p in AC2
notready:
	lda	1 @lastProcess
	sne	1 2
	  bri
	lda	1 clPSB
	add	1 2
	jmp loop

firstProcess: 0
lastProcess: 0
clPSB: lPSB

END:	jmp	TXV+200		; generate error if too big

;
;
	.END