; Assembly language code for non-microcoded FindPkg
; last edited October 31, 1980  6:12 PM
; Copyright Xerox Corporation 1980

; The phase argument / result below is actually
; 4000b*swap+phase, where swap=1 means even phases access odd byte.
; This peculiar convention is for microcode compatibility.
	.ent fJumpRam	; (arg, entry)
; Entry #s are:
;   0	Reset(phase)
;   2	NextEven(addr) -> (addr, -1-or-ctr-index, phase)
;   3	NextOdd(addr) -> same
	.ent fWriteReg	; (reg, value)
; Register #s are:
;  15b	phase
;  16b	-nMatch+1
	.ent fSkip, fExit, fClear, fCount
	.ent flvlvlvCtrs, fnNctrs, flvDisp

	.srel

fJumpRam:	.fJumpRam
fWriteReg:	.fWriteReg
fSkip:	.fSkip
fExit:	.fExit
fClear:	.fClear

	.zrel

fCount:	.fCount

; lvlvlvCtrs is the base of a table indexed by phase;
; lvlvCtrs points to the base of a table indexed by counter #:
;   each entry in this table points to a counter
;   the -1 entry is the same as the 0 entry
flvlvlvCtrs:	0
lvlvCtrs:	0
lvCtrs:	0	; base of counters
fnNctrs:	0	; - # of counters
nNmatch:	0	; - # of matches required +1
flvDisp:	0	; base of dispatch
daddr:	0	; pointer to data
oddByte:	0	; even if even (left) byte, odd if odd byte
fac2:	0	; save AC2 in search loop

	.nrel

link=1
temp=2
arg3=3

; Simulate WriteReg

.fWriteReg:
	sta 3 link,2
	movr# 0 0 szc
	  jmp .fSetPhase
	jmp .fInit

; Initialize with number of matches

.fInit:	adc 0 0
	add 0 1		; ac1 ← ac1-1
	sta 1 nNmatch
	lda 3 @flvlvlvCtrs
	lda 3 0,3
	sta 3 lvCtrs
	lda 3 link,2
	jmp 1,3

; Set phase

.fSetPhase:
	lda 0 m4001
	andzr 1 0 szr	; carry ← odd phase, skip if swap not set
	  movcl 0 0 skp	; odd byte flag ← not odd phase (swap set)
	  movl 0 0	; odd byte flag ← odd phase (swap not set)
	sta 0 oddByte
	inc 1 1
	lda 0 m1777
	and 0 1
	adc 0 0
	add 0 1		; mask phase
	lda 0 flvlvlvCtrs
	add 1 0
	sta 0 lvlvCtrs
	lda 3 link,2
	jmp 1,3
m4001:	4001
m1777:	1777

; Simulate JumpRam

.fJumpRam:
	sta 3 link,2
	mov# 1 1 snr
	  jmp .fReset
	sta 0 daddr
	sta 2 fac2
	lda 2 lvlvCtrs
	movr# 1 1 snc
	  jmp .fEven
	lda 1 @daddr
	jmp .fOdd

; Reset counters and phase

.fReset:
	sta 3 link,2
	lda 3 lvCtrs
	lda 1 fnNctrs
	sta 1 temp,2
	lda 1 nNmatch
.fr1:	sta 1 0,3
	inc 3 3
	isz temp,2
	  jmp .fr1
	mov 0 1
	jmp .fSetPhase

; Find next match.  Carry=oddByte, AC2=lvlvCtrs, AC1=@daddr for .fOdd

; Dispatch here for skip character

.fSkip:	mov# 0 0 szc	; carry=oddByte
	  jmp .fOdd
; Falls through to .fEven
.fEven:	isz daddr
	lda 1 @daddr
	lda 3 lcmask
	ands 1 3
	lda 0 flvDisp
	addo 0 3	; carry ← 1, odd byte next
	jmp @0,3
lcmask:	77400

; Dispatch here for a character not appearing in the pattern.
; This is exactly like an ordinary character with a null table.

.fcl0:	lda 2 flvlvlvCtrs
	lda 3 0,2
	jmp .fcl1
.fClear:
	inc 2 2
	lda 3 0,2
	mov# 3 3 snr
	  jmp .fcl0
.fcl1:	lda 0 nNmatch
	sta 0 @-1,3
	mov# 0 0 snc	; carry=oddByte
	  jmp .fEven
; Falls through to .fOdd
.fOdd:	lda 3 rcmask
	and 1 3
	lda 0 flvDisp
	addz 0 3	; carry ← 0, even byte next
	jmp @0,3
rcmask:	177

; Dispatch here for exit character

.fExit:	subcl 1 1	; ac1 ← carry
	sta 1 oddByte
	inc 2 2
	adc 1 1		; Not a real match
; Here for exit or match.  ac1=-1 or counter #
.fOut:	lda 0 0,2
	mov# 0 0 snr	; Check for wraparound
	  jmp .fx3
	sta 2 lvlvCtrs
	lda 0 flvlvlvCtrs
	sub 0 2		; Compute phase
	lda 3 m1777
	and 2 3		; Might be -1
.fx2:	lda 2 fac2	; Restore Bcpl AC2
	isz link,2	; Don't smash ac3
	lda 0 oddByte
	addr# 3 0 snc	; carry ← odd phase xor odd byte
	  jmp .fx4
	lda 0 daddr
	jmp @link,2
.fx3:	lda 3 flvlvlvCtrs
	sta 3 lvlvCtrs
	sub 3 3
	jmp .fx2
.fx4:	lda 0 swapbit
	add 0 3		; Set swap bit if phase parity # byte parity
	lda 0 daddr
	jmp @link,2
swapbit:	4000

; Dispatch here for ordinary character.  Code is
;	jsr @fCount
;	table of counter indices
;	-1

.fCount:	subcl 1 1	; ac1 ← carry
	inc 2 2
	lda 0 0,2
	mov# 0 0 snr
	  jmp .fc3	; Wrap around to phase 0
.fc0:	sta 2 lvlvCtrs
.fc1:	lda 2 0,3
	addz 0 2 szc
	  jmp .fc2	; Ran off end of table, no match
	inc 3 3
	isz @0,2
	  jmp .fc1
	sta 1 oddByte
	lda 1 0,2	; Match, return counter #
	lda 0 lvCtrs
	sub 0 1
	lda 2 lvlvCtrs
	jmp .fOut
.fc2:	lda 0 nNmatch
	sta 0 @0,2	; Reset first counter of next cycle
	lda 2 lvlvCtrs
	movr# 1 1 snc	; ac1=oddByte
	  jmp .fEven
	lda 1 @daddr
	jmp .fOdd
.fc3:	lda 2 flvlvlvCtrs
	lda 0 0,2
	jmp .fc0

	.end