; SwatSpyA.asm -- Binary Search -- Companion file is SwatSpyB.bcpl ; Copyright Xerox Corporation 1979, 1981, 1982, 1983 ; Last modified October 12, 1983 11:24 AM by Taft .titl SwatSpyA ; Ranges[0...Ncounts-1] is an ordered vector of locations ; spy will add into Counts[i] how often pc was found in ; [ Range[i]...Range[i+1] ). ; Appropriate guards are inserted by Swat code ; SwatSpyB.bcpl knows the offsets of variables in this code. .ent Mul, Div .bext spyCode, spyCodeEnd .srel spyCode: .spyCode spyCodeEnd: .spyCodeEnd Mul: .Mul Div: .Div .nrel ; *** offsets of these variables is known to SwatSpyB.bcpl *** .spyCode: bRanges: 0 ; beginning of Ranges eRanges: 0 ; end (+1) " " delta: 0 ; Counts-bRanges ipt: 1 ; interrupts per tally itnt: 1 ; ints till next tally xmEnabled: 0 ; nonzero if XM features are enabled ; *** offsets of these variables is known to SwatSpyB.bcpl *** start: dsz itnt ; tally this time? bri ; no sta 0 s0 ; save Acs and carry sta 1 s1 sta 2 s2 sta 3 s3 subcl 0 0 sta 0 sc lda 0 ipt ; restore itnt sta 0 itnt lda 0 @lvInterruptPC ; get pc lda 1 xmEnabled ; XM features enabled? mov# 1 1 snr jmp notXM ; no lda 1 lvInterruptXJmp ; yes, pointing to XM interrupt loc? se 0 1 jmp intFr0 ; no, interrupt from bank 0 lda 0 @lvInterruptXPC ; yes, get bank-relative PC lda 1 @lvInterruptXJmp ; get XJMP b instruction movr 1 1 ; get high 16 bits of 18-bit real PC movr 0 0 movr 1 1 movr 0 0 jmp notXM intFr0: movzr 0 0 ; interrupt from bank 0, just zero bank number movzr 0 0 notXM: lda 1 bRanges ; ac1 = low lda 2 eRanges ; ac2 = high = probe jmp lower ; look below probe higher: inc 2 1 ; look above probe (low = probe+1) lda 2 shigh lower: sgtu 2 1 jmp done ; if hi le low then done sta 2 shigh addzr 1 2 ; probe lda 3 0,2 sgeu 0 3 jmp lower ; missed -- look below probe lda 3 1,2 ; if key ge probe!0 then maybe found sltu 0 3 jmp higher ; missed -- look above probe lda 3 delta ; if key ls probe!1 then found add 2 3 ; ac3 ← tally location isz 0,3 ; tally pc jmp done lda 2 bRanges ; OVERFLOW of a tally (at least 20 mins.) lda 1 eRanges ; Divide all Counts by 2 lda 0 delta add 0 1 add 0 2 loop1: sltu 2 1 jmp done1 lda 0 0,2 movzr 0 0 sta 0 0,2 inc 2 2 jmp loop1 done1: lda 0 ipt ; and double movzl 0 0 ; sampling interval sta 0 ipt sta 0 itnt sub 0 0 ; set overflower movor 0 0 ; to 100000b sta 0 0,3 done: lda 0 sc ; restore carry and ACs movr 0 0 lda 0 s0 lda 1 s1 lda 2 s2 lda 3 s3 bri ; dismiss s0: 0 s1: 0 s2: 0 s3: 0 sc: 0 shigh: 0 lvInterruptPC: 500 lvInterruptXJmp: 627 ; XM: XJMP b -- interruptPC points here lvInterruptXPC: 630 ; XM: real PC (in bank b) .spyCodeEnd: 0 ; Mul(addend, multiplicand, multiplier, lvResult) ; Gives direct access to the "mul" instruction. ; Computes addend + (multiplicand*multiplier) and puts the ; 32-bit unsigned result in @lvResult .Mul: sta 3 1,2 mov 2 3 ; put stack pointer here lda 2 3,3 ; get extra args word add 3 2 ; compute absolute pointer sta 2 3,3 ; put it back lda 2 3,2 ; get third arg (multiplier) mul ; ac0 + (ac1*ac2) -> (ac0, ac1) mov 3 2 ; restore stack pointer lda 3 3,2 ; get extra args pointer lda 3 4,3 ; get lvResult sta 0 0,3 ; store result sta 1 1,3 lda 3 1,2 jmp 1,3 ; Div(lvDividend, divisor, lvRemainder) = quotient ; Gives direct access to the "div" instruction ; @lvDividend is the 32-bit unsigned dividend. ; Computes (@lvDivident)/divisor, puts the remainder in @lvRemainder ; and returns the quotient .Div: sta 3 1,2 sta 1 2,2 ; save divisor mov 0 3 ; lvDividend lda 0 0,3 ; get dividend into ac0 and ac1 lda 1 1,3 mov 2 3 ; preserve stack pointer lda 2 2,3 ; get divisor div 77400 mov 3 2 ; restore stack pointer sta 0 @3,2 ; @lvRemainder ← remainder mov 1 0 lda 3 1,2 jmp 1,3 .end