;; 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
;;