;; ShowCharMc.Mu -- Spruce inner loop ; Instruction positioning !1,2, useTest, GetChar1; !1,2, gc1, FullReturn; !1,2, GetOld, GetNew; !1,2, RangeError, notTooLow; !1,2, notTooHigh, RangeError2; !1,2, chk1, OffPage; !1,2, chk11, Double; !1,2, chk2, RangeError3; !1,2, OffPage2, chk3; !1,2, noCarry, Carry; !1,2, noCarryB, CarryB; !1,2, RecordUses, noRecord; !1,2, old, new; !1,2, OnCopy, enter1; !1,2, BufFull, GetChar; ShowChars: L←PC; savedPC←L; L←177026, TASK; PC←L; *4+entry* ;; let c=not immediate? WindowReadByte(DL), immediate>0? DL>>Bytes↑i, DL>>STR.char↑i GetChar1: L←ct-1, :gc2; [*3max* here] GetChar: L←ct-1; gc2: ct←L, SH<0; L←byteIdx+1, BUSODD, :gc1; [gc1, FullReturn*5*] ; Fetch new word or use old one gc1: byteIdx←L, :GetOld; [GetOld, GetNew] GetOld: T←377; L←T←data.T, :PlaceChar; GetNew: temp←L RSH 1; T←base; MAR←temp+T; NOP; available ;available ;available L←MD; data←L, TASK; temp←L LCY 8; *13* T←377; L←T←temp.T, :PlaceChar; ;; if c < bc % c > ec then {resultis 1} ; too high or too low PlaceChar: c←L; L←bcM1-T; L←ec-T, SH<0; ;; let icc=c+ICCOffset L←ICCOffset+T, SH<0, :RangeError; [RangeError*12*, notTooLow] ;; let p=WidthPointer+c*(size CharWidth/16) notTooLow: icc←L, L←T, :notTooHigh ; [notTooHigh, RangeError1*13*] notTooHigh: L←LASTL+T; ; next sequences makes c lsh 3 -- here, L=c lsh 1 temp←L LSH 1; ; temp=c lsh 2 L←T←temp; L←LASTL+T; ; L=c lsh 3 T←WidthPointer; L←LASTL+T, TASK; p←L; *18* ;; let b=CurB!0+p>>CharWidth.OB T←5; ; read 5, then 4 MAR←p+T; T←CurB0; ;available ;available L←MD+T; T←MD; b←L; ;; ShowChars, contd. ;; let s=CurS!0+p>>CharWidth.OS (sort of) ;; let band=s rshift 4 (sort of) ; actually, lineBand = {s, above} RROT 4 L←CurS0+T; T←LASTL; temp←L MRSH 1; L←T←temp; temp←L MRSH 1; L←T←temp; temp←L MRSH 1; L←T←temp, TASK; lineBand←L MRSH 1; *17* ;; let ds, db =p>>CharWidth.DS, p>>CharWidth.DB T←6; MAR←p+T; ;; test b < 4096 & ... T←b; L←7777-T; L←MD, SH<0; AC2←L, :chk1; [chk1, OffPage*6* ] chk1: L←MD, BUS=0, TASK; AC1←L, :chk11; *8* [chk11, Double ] ;; test db>0 & band ls nVisibleBands or resultis 2 chk11: L←AC1-1; T←7777, SH<0; L←lineBand AND T, :chk2; [chk2, RangeError3*3*] chk2: band←L; T←nVisibleBands; L←LASTL-T; ;; BandFree!0=100000b+icc //First entry MAR←BandFree, SH<0; T←100000, :OffPage2; [OffPage2*8*,chk3] band>nVisibleBands chk3: L←icc+T, TASK; MD←LASTL; *10* ;; BandFree!1=(s lshift 12)+b T←170000; MAR←BandFree+1; T←lineBand.T; L←b+T, TASK; MD←LASTL; *5* ;; DoubleAdd(CurS, lv p>>CharWidth.WS) Double: MAR←T←p+1; L←2+T; p←L; T←CurS1; L←MD+T; CurS1←L, ALUCY; T←CurS0, :noCarry; [noCarry, Carry] Carry: T←0+T+1; noCarry: L←MD+T; ;; DoubleAdd(CurB, lv p>>CharWidth.WB) MAR←p; CurS0←L; T←CurB1; ; available L←MD+T; CurB1←L, ALUCY; T←CurB0, :noCarryB; [noCarryB, CarryB] CarryB: T←0+T+1; noCarryB: L←MD+T, TASK; CurB0←L; *18* ;; ShowChars, contd. ;; if db eq 0 then goto GetChar... SINK←AC1, BUS=0; ;; if ICCUses!icc ge 0 then . . . T←icc, :useTest; [useTest, GetChar1] useTest: MAR←L←ICCUses+T; uses←L; L←2; entryLen←L; enter a 2-long value L←MD; SH<0, TASK; temp←L, :RecordUses; [RecordUses, noRecord]; *9* RecordUses: L←77, SWMODE; AC0←L, :MUL; db*ds+3*16+15 Mret: L←AC1; T←AC0; AC1← L MRSH 1, L←T; (. . .) /16 AC0← L RSH 1; L←AC1; T←AC0; AC1← L MRSH 1, L←T; AC0← L RSH 1; L←AC1; T←AC0; AC1← L MRSH 1, L←T; AC0← L RSH 1; L←AC1; T←AC0, TASK; AC1← L MRSH 1; *17* T←EvenMask; (. . .)&(177776) // even number SINK←temp, BUS=0; T←AC1.T, :old; [old, new] new: L←fspn+T; fspn←L, :sto; old: L←fspo+T; fspo←L; sto: MAR←uses; T←2; L←temp-T, TASK; MD←LASTL, :noRecord; *10* ;; BandEnter(band, size BEChar/16) -- JMPRAM 30 enters here -- ;; onlyOnCopy, band, BandTable, CopyTable , BandFree, BandAvail, entryLen set up BandEnter: L←0; ct←L; force return right away L←PC, TASK; savedPC←L; *2* noRecord: SINK←onlyOnCopy, BUS=0; T←band, :OnCopy ;[OnCopy, enter1] ; Count contributions to jump for this band OnCopy: MAR←L←CopyTable+T; temp←L; T←entryLen; ;available L←MD+T; MAR←temp; TASK; ;available MD←LASTL; *11* T←band; enter1: MAR←BandTable+T; T←entryLen+1; ; MD←BandFree; SINK←MD; L←MD; MAR←BandFree-1; temp←L; L←BandFree+T; MD←temp; BandFree←L; L←BandAvail+T; BandAvail←L, SH<0, TASK; :BufFull; [BufFull*0*,GetChar] *16max* !1, 1, CodeReturn; Kill pending branches FullReturn: L←0, TASK, :CodeReturn; [CodeReturn, CodeReturn] $MUDone $0 RangeError: L←MUCharRange, TASK, :CodeReturn; . . . RangeError2: L←MUCharRange, TASK, :CodeReturn; . . . RangeError3: L←MUCharRange, TASK, :CodeReturn; OffPage: L←MUOffPage, TASK, :CodeReturn; OffPage2: L←MUOffPage, TASK, :CodeReturn; BufFull: L←MUBufFull, TASK, :CodeReturn; CodeReturn: AC0←L; *15max* L←savedPC, TASK; PC←L, :NOVEM; *9* ; FlushChars !1,2, flDoit, flDone; !1,2, flNotCh, flCh; !1,2, flW2, flW4; !1,2, flOLp, flCant; !1,2, flGoOn, FlushLoop; FlushChars: T←177777; L←leftCt XOR T, TASK; leftCt←L; ** convert from -(# left+1) to #left FlushLoop: MAR←p-1, SINK←p, BUS=0; L←p, :flDoit; [flDoit, flDone] flDoit: pData←L; MD←0; clear pointer entry SINK←MD; switch back to original address (could use if orig. was even!) L←MD; MAR←p; p←L; ready for next time! ;available ;available L←MD, TASK; typeWd←L; *12* L←typeWd; T←37, SH<0; T←LASTL.T, :flNotCh; [flNotCh, flCh] flNotCh: L←BERectangleH-T; NOP, SH=0; flCh: L←T←3, :flW2; [flW2, flW4] flW2: L←T←ONE; flW4: numData←L; L←leftCt-T-1; SH<0, TASK; leftCt←L, :flOLp; *11max* [flOLp, flCant] flOLp: MAR←L←outAddr+1; outAddr←L; L←numData-1, BUS=0; MD←typeWd, :flGoOn; [flGoOn,FlushLoop] flGoOn: MAR←pData+1; numData←L; L←pData+1; pData←L; L←MD, TASK; typeWd←L, :flOLp; *10* !1,1,FlushReturn; ; This can almost certainly be bummed -- reverse change to leftCt (ugh!) flCant: T←numData; L←leftCt+T+1; leftCt←L; L←MUCant, TASK, :FlushReturn; flDone: L←0, TASK, :FlushReturn; MUDone ; odd-aligned to kill branches FlushReturn: AC0←L; ** T←177777; L←leftCt XOR T, TASK; leftCt←L, :NOVEM; ** convert #left to -(#left+1) ;; DCS, September 29, 1978 8:50 AM, derived from ShowCharacter in SpruceShow ;; October 2, 1978 7:20 PM, working away -- getting faster! ;; October 3, 1978 11:12 AM, define regs (used all!), last minor mods before assembly test ;; October 3, 1978 2:43 PM, repairs after deskcheck ;; October 4, 1978 10:10 AM, bugs in setup code (4, 1 a typo) ;; October 4, 1978 5:18 PM, bug in onCopy dispatch (wrong order -- a typo), and fspn/o calc (off by 2x) ;; October 5, 1978 8:30 AM, correct OrbitSizeChar computation ;; October 5, 1978 9:45 AM, ShowChars updates BandFree, BandAvail, each time out; ;; fetches same each time in ;; October 5, 1978 11:11 AM, double store must happen one cycle earlier! Good! ;; October 18, 1978 12:17 PM, remove all setup code -- use RLoad, Store instructions instead ;; October 20, 1978 11:57 AM, move defs to SpruceDefs ;; October 22, 1978 12:00 AM, add FlushChars ;; October 23, 1978 7:01 AM, complement leftCt in and out (easier than in ML code) ;; October 24, 1978 8:51 AM, update CopyTable!band if onlyOnCopy -- remove branching hair from flush ;; October 24, 1978 9:17 AM, add linkage allowing enter microcode to be used as BandEnter ;;