; A L T O I I C O D E 3 . M U ; Copyright Xerox Corporation 1979 ;***Derived from ALTOIICODE2.MU, as last modified by ;***Tobol, August 5, 1976 12:13 PM -- fix DIOG2 bug ;***modified by Ingalls, September 6, 1977 ; BitBLT fixed (LREG bug) and extended for new memory ;***modified by Boggs and Taft September 15, 1977 10:10 PM ; Modified MRT to refresh 16K chips and added XMSTA and XMLDA. ; Fixed two bugs in DEXCH and a bug in the interval timer. ; Moved symbol and constant definitions into AltoConsts23.mu. ; MRT split and moved into two 'get' files. ;***modified by Boggs and Taft November 21, 1977 5:10 PM ; Fixed a bug in the Ethernet input main loop. ;***modified by Boggs November 28, 1977 3:53 PM ; Mess with the information returned by VERS ;***modified by Dersch, August 26, 2015 4:04 PM ; Annotated with PROM addresses and Tasks for use in Contralto ;Get the symbol and constant definitions #AltoConsts23.mu; ;LABEL PREDEFINITIONS ;The reset locations of the tasks: !17,20,NOVEM,,,,KSEC,,,EREST,MRT,DWT,CURT,DHT,DVT,PART,KWDX,; ;Locations which may need to be accessible from the Ram, or Ram ; locations which are accessed from the Rom (TRAP1): !37,20,START,RAMRET,RAMCYCX,,,,,,,,,,,,,TRAP1; ;Macro-op dispatch table: !37,20,DOINS,DOIND,EMCYCLE,NOPAR,JSRII,U5,U6,U7,,,,,,,RAMTRAP,TRAP; ;Parameterless macro-op sub-table: !37,40,DIR,EIR,BRI,RCLK,SIO,BLT,BLKS,SIT,JMPR,RDRM,WTRM,DIRS,VERS,DREAD,DWRITE,DEXCH,MUL,DIV,DIOG1,DIOG2,BITBLT,XMLDA,XMSTA,,,,,,,,,; ;Cycle dispatch table: !37,20,L0,L1,L2,L3,L4,L5,L6,L7,L8,R7,R6,R5,R4,R3X,R2X,R1X; ;some global R-Registers $NWW $R4; State of interrupt system $R37 $R37; Used by MRT, interval timer and EIA $MTEMP $R25; Public temporary R-Register ;The Display Controller ; its R-Registers: $CBA $R22; $AECL $R23; $SLC $R24; $HTAB $R26; $YPOS $R27; $DWA $R30; $CURX $R20; $CURDATA $R21; ; its task specific functions: $EVENFIELD $L024010,000000,000000; F2 = 10 DHT DVT $SETMODE $L024011,000000,000000; F2 = 11 DHT $DDR $L026010,000000,124100; F2 = 10 DWT !1,2,DVT1,DVT11; !1,2,MOREB,NOMORE; !1,2,NORMX,HALFX; !1,2,NODD,NEVEN; !1,2,DHT0,DHT1; !1,2,NORMODE,HALFMODE; !1,2,DWTZ,DWTY; !1,2,DOTAB,NOTAB; !1,2,XNOMORE,DOMORE; ;Display Vertical Task DV0014> DVT: MAR<- L<- DASTART+1; DV0001> CBA<- L, L<- 0; DV0005> CURDATA<- L; DV0006> SLC<- L; DV0017> T<- MD; CAUSE A VERTICAL FIELD INTERRUPT DV0023> L<- NWW OR T; DV0036> MAR<- CURLOC; SET UP THE CURSOR DV0046> NWW<- L, T<- 0-1; DV0047> L<- MD XOR T; HARDWARE EXPECTS X COMPLEMENTED DV0050> T<- MD, EVENFIELD; DV0051> CURX<- L, :DVT1; DV0002> DVT1: L<- BIAS-T-1, TASK, :DVT2; BIAS THE Y COORDINATE DV0003> DVT11: L<- BIAS-T, TASK; DV0052> DVT2: YPOS<- L, :DVT; ;Display Horizontal Task. ;11 cycles if no block change, 17 if new control block. DH0013> DHT: MAR<- CBA-1; DH0053> L<- SLC -1, BUS=0; DH0054> SLC<- L, :DHT0; DH0032> DHT0: T<- 37400; MORE TO DO IN THIS BLOCK DH0055> SINK<- MD; DH0056> L<- T<- MD AND T, SETMODE; DH0057> HTAB<- L LCY 8, :NORMODE; DH0034> NORMODE:L<- T<- 377 . T; DH0070> AECL<- L, :REST; DH0035> HALFMODE: L<- T<- 377 . T; DH0071> AECL<- L, :REST, T<- 0; DH0072> REST: L<- DWA + T,TASK; INCREMENT DWA BY 0 OR NWRDS DH0073> NDNX: DWA<- L, :DHT; DH0033> DHT1: L<- T<- MD+1, BUS=0; DH0074> CBA<- L, MAR<- T, :MOREB; DH0025> NOMORE: BLOCK, :DNX; DH0024> MOREB: T<- 37400; DH0075> L<- T<- MD AND T, SETMODE; DH0127> MAR<- CBA+1, :NORMX, EVENFIELD; DH0026> NORMX: HTAB<- L LCY 8, :NODD; DH0027> HALFX: HTAB<- L LCY 8, :NEVEN; DH0030> NODD: L<-T<- 377 . T; DH0130> AECL<- L, :XREST; ODD FIELD, FULL RESOLUTION DH0031> NEVEN: L<- 377 AND T; EVEN FIELD OR HALF RESOLUTION DH0131> AECL<-L, T<-0; DH0132> XREST: L<- MD+T; DH0133> T<-MD-1; DH0134> DNX: DWA<-L, L<-T, TASK; DH0135> SLC<-L, :DHT; ;Display Word Task DW0011> DWT: T<- DWA; DW0136> T<- -3+T+1; DW0137> L<- AECL+T,BUS=0,TASK; AECL CONTAINS NWRDS AT THIS TIME DW0140> AECL<-L, :DWTZ; DW0041> DWTY: BLOCK; DW0141> TASK, :DWTF; DW0040> DWTZ: L<-HTAB-1, BUS=0,TASK; DW0142> HTAB<-L, :DOTAB; DW0042> DOTAB: DDR<-0, :DWTZ; DW0043> NOTAB: MAR<-T<-DWA; DW0143> L<-AECL-T-1; DW0144> ALUCY, L<-2+T; DW0145> DWA<-L, :XNOMORE; DW0045> DOMORE: DDR<-MD, TASK; DW0146> DDR<-MD, :NOTAB; DW0044> XNOMORE:DDR<- MD, BLOCK; DW0147> DDR<- MD, TASK; DW0150> DWTF: :DWT; ;Alto Ethernet Microcode, Version III, Boggs and Metcalfe ;4-way branches using NEXT6 and NEXT7 !17,20,EIFB00,EODOK,EOEOK,ENOCMD,EIFB01,EODPST,EOEPST,EOREST,EIFB10,EODCOL,EOECOL,EIREST,EIFB11,EODUGH,EOEUGH,ERBRES; ;2-way branches using NEXT7 ;EOCDW1, EOCDWX, and EIGO are all related. Be careful! !7,10,,EIFOK,,EOCDW1,,EIFBAD,EOCDWX,EIGO; ;Miscellaneous address constraints !7,10,,EOCDW,EODATA,EIDFUL,EIDZ4,EOCDRS,EIDATA,EPOST; !7,10,,EIDOK,,,EIDMOR,EIDPST; !1,1,EIFB1; !1,1,EIFRST; ;2-way branches using NEXT9 !1,2,EOINPR,EOINPN; !1,2,EODMOR,EODEND; !1,2,EOLDOK,EOLDBD; !1,2,EIFCHK,EIFPRM; !1,2,EOCDWT,EOCDGO; !1,2,ECNTOK,ECNTZR; !1,2,EIFIGN,EISET; !1,2,EIFNBC,EIFBC; ;R Memory Locations $ECNTR $R12; Remaining words in buffer $EPNTR $R13; points BEFORE next word in buffer ;Ethernet microcode Status codes $ESIDON $377; Input Done $ESODON $777; Output Done $ESIFUL $1377; Input Buffer full - words lost from tail of packet $ESLOAD $1777; Load location overflowed $ESCZER $2377; Zero word count for input or output command $ESABRT $2777; Abort - usually caused by reset command $ESNEVR $3377; Never Happen - Very bad if it does ;Main memory locations in page 1 reserved for Ethernet $EPLOC $600; Post location $EBLOC $601; Interrupt bit mask $EELOC $602; Ending count location $ELLOC $603; Load location $EICLOC $604; Input buffer Count $EIPLOC $605; Input buffer Pointer $EOCLOC $606; Output buffer Count $EOPLOC $607; Output buffer Pointer $EHLOC $610; Host Address ;Function Definitions $EIDFCT $L000000,014004,000100; BS = 4, Input data $EILFCT $L016013,070013,000100; F1 = 13, Input Look $EPFCT $L016014,070014,000100; F1 = 14, Post $EWFCT $L016015,000000,000000; F1 = 15, Wake-Up $EODFCT $L026010,000000,124000; F2 = 10, Output data $EOSFCT $L024011,000000,000000; F2 = 11, Start output $ERBFCT $L024012,000000,000000; F2 = 12, Rest branch $EEFCT $L024013,000000,000000; F2 = 13, End of output $EBFCT $L024014,000000,000000; F2 = 14, Branch $ECBFCT $L024015,000000,000000; F2 = 15, Countdown branch $EISFCT $L024016,000000,000000; F2 = 16, Start input ; - Whenever a label has a pending branch, the list of possible ; destination addresses is shown in brackets in the comment field. ; - Special functions are explained in a comment near their first use. ; - To avoid naming conflicts, all labels and special functions ; have "E" as the first letter. ;Top of Ethernet Task loop ;Ether Rest Branch Function - ERBFCT ;merge ICMD and OCMD Flip Flops into NEXT6 and NEXT7 ;ICMD and OCMD are set from AC0 [14:15] by the SIO instruction ; 00 neither ; 01 OCMD - Start output ; 10 ICMD - Start input ; 11 Both - Reset interface ;in preparation for a hack at EIREST, zero EPNTR EN0007> EREST: L<- 0,ERBFCT; What's happening ? EN0152> EPNTR<- L,:ENOCMD; [ENOCMD,EOREST,EIREST,ERBRES] EN0203> ENOCMD: L<- ESNEVR,:EPOST; Shouldn't happen EN0217> ERBRES: L<- ESABRT,:EPOST; Reset Command ;Post status and halt. Microcode status in L. ;Put microstatus,,hardstatus in EPLOC, merge c(EBLOC) into NWW. ;Note that we write EPLOC and read EBLOC in one operation ;Ether Post Function - EPFCT. Gate the hardware status ;(LOW TRUE) to Bus [10:15], reset interface. EN0237> EPOST: MAR<- EELOC; EN0220> EPNTR<- L,TASK; Save microcode status in EPNTR EN0222> MD<- ECNTR; Save ending count EN0224> MAR<- EPLOC; double word reference EN0230> T<- NWW; EN0240> MD<- EPNTR,EPFCT; BUS AND EPNTR with Status EN0260> L<- MD OR T,TASK; NWW OR c(EBLOC) EN0261> NWW<- L,:EREST; Done. Wait for next command ;This is a subroutine called from both input and output (EOCDGO ;and EISET). The return address is determined by testing ECBFCT, ;which will branch if the buffer has any words in it, which can ;only happen during input. EN0262> ESETUP: NOP; EN0263> L<- MD,BUS=0; check for zero length EN0264> T<- MD-1,:ECNTOK; [ECNTOK,ECNTZR] start-1 EN0253> ECNTZR: L<- ESCZER,:EPOST; Zero word count. Abort ;Ether Countdown Branch Function - ECBFCT. ;NEXT7 = Interface buffer not empty. EN0252> ECNTOK: ECNTR<- L,L<- T,ECBFCT,TASK; EN0265> EPNTR<- L,:EODATA; [EODATA,EIDATA] ;Ethernet Input ;It turns out that starting the receiver for the first time and ;restarting it after ignoring a packet do the same things. EN0213> EIREST: :EIFIGN; Hack ;Address filtering code. ;When the first word of a packet is available in the interface ;buffer, a wakeup request is generated. The microcode then ;decides whether to accept the packet. Decision must be reached ;before the buffer overflows, within about 14*5.44 usec. ;if EHLOC is zero, machine is 'promiscuous' - accept all packets ;if destination byte is zero, it is a 'broadcast' packet, accept. ;if destination byte equals EHLOC, packet is for us, accept. ;EIFRST is really a subroutine that can be called from EIREST ;or from EIGO, output countdown wait. If a packet is ignored ;and EPNTR is zero, EIFRST loops back and waits for more ;packets, else it returns to the countdown code. ;Ether Branch Function - EBFCT ;NEXT7 = IDL % OCMD % ICMD % OUTGONE % INGONE (also known as POST) ;NEXT6 = COLLision - Can't happen during input EN0153> EIFRST: MAR<- EHLOC; Get Ethernet address EN0266> T<- 377,EBFCT; What's happening? EN0267> L<- MD AND T,BUS=0,:EIFOK;[EIFOK,EIFBAD] promiscuous? EN0221> EIFOK: MTEMP<- LLCY8,:EIFCHK; [EIFCHK,EIFPRM] Data wakeup EN0225> EIFBAD: ERBFCT,TASK,:EIFB1; [EIFB1] POST wakeup; xCMD FF set? EN0151> EIFB1: :EIFB00; [EIFB00,EIFB01,EIFB10,EIFB11] EN0200> EIFB00: :EIFIGN; IDL or INGONE, restart rcvr EN0204> EIFB01: L<- ESABRT,:EPOST; OCMD, abort EN0210> EIFB10: L<- ESABRT,:EPOST; ICMD, abort EN0214> EIFB11: L<- ESABRT,:EPOST; ICMD and OCMD, abort EN0247> EIFPRM: TASK,:EIFBC; Promiscuous. Accept ;Ether Look Function - EILFCT. Gate the first word of the ;data buffer to the bus, but do not increment the read pointer. EN0246> EIFCHK: L<- T<- 177400,EILFCT; Mask off src addr byte (BUS AND) EN0270> L<- MTEMP-T,SH=0; Broadcast? EN0271> SH=0,TASK,:EIFNBC; [EIFNBC,EIFBC] Our Address? EN0256> EIFNBC: :EIFIGN; [EIFIGN,EISET] EN0257> EIFBC: :EISET; [EISET] Enter input main loop ;Ether Input Start Function - EISFCT. Start receiver. Interface ;will generate a data wakeup when the first word of the next ;packet arrives, ignoring any packet currently passing. EN0254> EIFIGN: SINK<- EPNTR,BUS=0,EPFCT;Reset; Called from output? EN0272> EISFCT,TASK,:EOCDWX; [EOCDWX,EIGO] Restart rcvr EN0226> EOCDWX: EWFCT,:EOCDWT; Return to countdown wait loop EN0255> EISET: MAR<- EICLOC,:ESETUP; Double word reference ;Input Main Loop ;Ether Input Data Function - EIDFCT. Gate a word of data to ;the bus from the interface data buffer, increment the read ptr. ; * * * * * W A R N I N G * * * * * ;The delay from decoding EIDFCT to gating data to the bus is ;marginal. Some logic in the interface detects the situation ;(which only happens occasionally) and stops SysClk for one cycle. ;Since memory data must be available during cycle 4, and SysClk ;may stop for one cycle, this means that the MD<- EIDFCT must ;happen in cycle 3. There is a bug in this logic which occasionally ;stops the clock in the instruction following the EIDFCT, so ;the EIDFCT instruction should not be the last one of the task, ;or it may screw up someone else (such as RDRAM). ;EIDOK, EIDMOR, and EIDPST must have address bits in the pattern: ;xxx1 xxx4 xxx5 ;ECBFCT is used to force an unconditional branch on NEXT7 EN0236> EIDATA: T<- ECNTR-1, BUS=0; EN0273> MAR<- L<- EPNTR+1, EBFCT; [EIDMOR,EIDPST] What's happening EN0244> EIDMOR: EPNTR<- L, L<- T, ECBFCT; [EIDOK,EIDPST] Guaranteed to branch EN0241> EIDOK: MD<- EIDFCT, TASK; [EIDZ4] Read a word from the interface EN0234> EIDZ4: ECNTR<- L, :EIDATA; ; We get to EIDPST for one of two reasons: ; (1) The buffer is full. In this case, an EBFCT (NEXT[7]) is pending. ; We want to post "full" if this is a normal data wakeup (no branch) ; but just "input done" if hardware input terminated (branch). ; (2) Hardware input terminated while the buffer was not full. ; In this case, an unconditional branch on NEXT[7] is pending, so ; we always terminate with "input done". EN0245> EIDPST: L<- ESIDON, :EIDFUL; [EIDFUL,EPOST] Presumed to be INGONE EN0233> EIDFUL: L<- ESIFUL, :EPOST; Input buffer overrun ;Ethernet output ;It is possible to get here due to a collision. If a collision ;happened, the interface was reset (EPFCT) to shut off the ;transmitter. EOSFCT is issued to guarantee more wakeups while ;generating the countdown. When this is done, the interface is ;again reset, without really doing an output. EN0207> EOREST: MAR<- ELLOC; Get load EN0274> L<- R37; Use clock as random # gen EN0275> EPNTR<- LLSH1; Use bits [2:9] EN0276> L<- MD,EOSFCT; L<- current load EN0277> SH<0,ECNTR<- L; Overflowed? EN0300> MTEMP<- LLSH1,:EOLDOK; [EOLDOK,EOLDBD] EN0243> EOLDBD: L<- ESLOAD,:EPOST; Load overlow EN0242> EOLDOK: L<- MTEMP+1; Write updated load EN0301> MAR<- ELLOC; EN0302> MTEMP<- L,TASK; EN0303> MD<- MTEMP,:EORST1; New load = (old lshift 1) + 1 EN0304> EORST1: L<- EPNTR; Continue making random # EN0305> EPNTR<- LRSH1; EN0306> T<- 377; EN0307> L<- EPNTR AND T,TASK; EN0310> EPNTR<- L,:EORST2; ;At this point, EPNTR has 0,,random number, ENCTR has old load. EN0311> EORST2: MAR<- EICLOC; Has an input buffer been set up? EN0312> T<- ECNTR; EN0313> L<- EPNTR AND T; L<- Random & Load EN0314> SINK<- MD,BUS=0; EN0315> ECNTR<- L,SH=0,EPFCT,:EOINPR;[EOINPR,EOINPN] EN0154> EOINPR: EISFCT,:EOCDWT; [EOCDWT,EOCDGO] Enable in under out EN0155> EOINPN: :EOCDWT; [EOCDWT,EOCDGO] No input. ;Countdown wait loop. MRT will generate a wakeup every ;37 usec which will decrement ECNTR. When it is zero, start ;the transmitter. ;Ether Wake Function - EWFCT. Sets a flip flop which will cause ;a wakeup to this task the next time MRT wakes up (every 37 usec). ;Wakeup is cleared when Ether task next runs. EWFCT must be ;issued in the instruction AFTER a task. EN0250> EOCDWT: L<- 177400,EBFCT; What's happening? EN0316> EPNTR<- L,ECBFCT,:EOCDW;[EOCDW,EOCDRS] Packet coming in? EN0231> EOCDW: L<- ECNTR-1,BUS=0,TASK,:EOCDW1; [EOCDW1,EIGO] EN0223> EOCDW1: ECNTR<- L,EWFCT,:EOCDWT; [EOCDWT,EOCDGO] EN0235> EOCDRS: L<- ESABRT,:EPOST; [EPOST] POST event EN0227> EIGO: :EIFRST; [EIFRST] Input under output ;Output main loop setup EN0251> EOCDGO: MAR<- EOCLOC; Double word reference EN0317> EPFCT; Reset interface EN0320> EOSFCT,:ESETUP; Start Transmitter ;Ether Output Start Function - EOSFCT. The interface will generate ;a burst of data requests until the interface buffer is full or the ;memory buffer is empty, wait for silence on the Ether, and begin ;transmitting. Thereafter it will request a word every 5.44 us. ;Ether Output Data Function - EODFCT. Copy the bus into the ;interface data buffer, increment the write pointer, clears wakeup ;request if the buffer is now nearly full (one slot available). ;Output main loop EN0232> EODATA: L<- MAR<- EPNTR+1,EBFCT; What's happening? EN0321> T<- ECNTR-1,BUS=0,:EODOK; [EODOK,EODPST,EODCOL,EODUGH] EN0201> EODOK: EPNTR<- L,L<- T,:EODMOR; [EODMOR,EODEND] EN0156> EODMOR: ECNTR<- L,TASK; EN0322> EODFCT<- MD,:EODATA; Output word to transmitter EN0205> EODPST: L<- ESABRT,:EPOST; [EPOST] POST event EN0211> EODCOL: EPFCT,:EOREST; [EOREST] Collision EN0215> EODUGH: L<- ESABRT,:EPOST; [EPOST] POST + Collision ;Ether EOT Function - EEFCT. Stop generating output data wakeups, ;the interface has all of the packet. When the data buffer runs ;dry, the interface will append the CRC and then generate an ;OUTGONE post wakeup. EN0157> EODEND: EEFCT; Disable data wakeups EN0323> TASK; Wait for EEFCT to take EN0324> :EOEOT; Wait for Outgone ;Output completion. We are waiting for the interface buffer to ;empty, and the interface to generate an OUTGONE Post wakeup. EN0325> EOEOT: EBFCT; What's happening? EN0326> :EOEOK; [EOEOK,EOEPST,EOECOL,EOEUGH] EN0202> EOEOK: L<- ESNEVR,:EPOST; Runaway Transmitter. Never Never. EN0206> EOEPST: L<- ESODON,:EPOST; POST event. Output done EN0212> EOECOL: EPFCT,:EOREST; Collision EN0216> EOEUGH: L<- ESABRT,:EPOST; POST + Collision ;Memory Refresh Task, ;Mouse Handler, ;EIA Handler, ;Interval Timer, ;Calender Clock, and ;part of the cursor. !17,20,TX0,TX6,TX3,TX2,TX8,TX5,TX1,TX7,TX4,,,,,,,; !1,2,DOTIMER,NOTIMER; !1,2,NOTIMERINT,TIMERINT; !1,2,DOCUR,NOCUR; !1,2,SHOWC,WAITC; !1,2,SPCHK,NOSPCHK; !1,2,NOCLK,CLOCK; !1,1,MRTLAST; !1,2,CNOTLAST,CLAST; $CLOCKTEMP $R11; $REFIIMSK $7777; ; * * * A T T E N T I O N * * * ;There are two versions of the Memory refresh code: ; AltoIIMRT4K.mu for refreshing 4K chips ; AltoIIMRT16K.mu for refreshing 16K chips ;You must name one or the other 'AltoIIMRT.mu'. ;I suggest the following convention for naming the resulting .MB file: ; AltoIICode3.MB for the 4K version ; AltoIICode3XM.MB for the 16K version #AltoIIMRT.mu; MR0355> CLOCK: MAR<- CLOCKLOC; R37 OVERFLOWED. MR0412> NOP; MR0413> L<- MD+1; INCREMENT CLOCK IM MEMORY MR0414> MAR<- CLOCKLOC; MR0415> MTEMP<- L, TASK; MR0416> MD<- MTEMP, :NOCLK; MR0334> DOCUR: L<- T<- YPOS; CHECK FOR VISIBLE CURSOR ON THIS SCAN MR0417> SH<0, L<- 20-T-1; ***x13 change: the constant 20 was 17 MR0420> SH<0, L<- 2+T, :SHOWC; [SHOWC,WAITC] MR0337> WAITC: YPOS<- L, L<- 0, TASK, :MRTLAST; SQUASHES PENDING BRANCH MR0336> SHOWC: MAR<- CLOCKLOC+T+1, :CNOTLAST; MR0356> CNOTLAST: T<- CURX, :CURF; MR0357> CLAST: T<- 0; MR0421> CURF: YPOS<- L, L<- T; MR0422> CURX< L; MR0423> L<- MD, TASK; MR0424> CURDATA<- L, :MRT; ;AFTER THIS DISPATCH, T WILL CONTAIN XCHANGE, L WILL CONTAIN YCHANGE-1 MR0346> TX1: L<- T<- ONE +T, :M00; Y=0, X=1 MR0343> TX2: L<- T<- ALLONES, :M00; Y=0, X=-1 MR0342> TX3: L<- T<- 0, :M00; Y=1, X=0 MR0350> TX4: L<- T<- ONE AND T, :M00; Y=1, X=1 MR0345> TX5: L<- T<- ALLONES XOR T, :M00; Y=1, X=-1 MR0341> TX6: T<- 0, :M00; Y=-1, X=0 MR0347> TX7: T<- ONE, :M00; Y=-1, X=1 MR0344> TX8: T<- ALLONES, :M00; Y=-1, X=-1 MR0425> M00: MAR<- MOUSELOC; START THE FETCH OF THE COORDINATES MR0426> MTEMP<- L; YCHANGE -1 MR0427> L<- MD+ T; X+ XCHANGE MR0430> T<- MD; Y MR0431> T<- MTEMP+ T+1; Y+ (YCHANGE-1) + 1 MR0432> MTEMP<- L, L<- T; MR0433> MAR<- MOUSELOC; NOW RESTORE THE UPDATED COORDINATES MR0434> CLOCKTEMP<- L; MR0435> MD<- MTEMP, TASK; MR0436> MD<- CLOCKTEMP, :MRTA; ;CURSOR TASK ;Cursor task specific functions $XPREG $L026010,000000,124000; F2 = 10 $CSR $L026011,000000,124000; F2 = 11 CU0012> CURT: XPREG<- CURX, TASK; CU0437> CSR<- CURDATA, :CURT; ;PREDEFINITION FOR PARITY TASK. ;THE CODE IS AT THE END OF THE FILE !17,20,PR0,,PR2,PR3,PR4,PR5,PR6,PR7,PR8,,,,,,,; ;NOVA EMULATOR $SAD $R5; $PC $R6; USED BY MEMORY INIT !7,10,Q0,Q1,Q2,Q3,Q4,Q5,Q6,Q7; !1,2,FINSTO,INCPC; !1,2,EReRead,FINJMP; ***X21 addition. !1,2,EReadDone,EContRead; ***X21 addition. !1,2,EtherBoot,DiskBoot; ***X21 addition. EM0000> NOVEM: IR<-L<-MAR<-0, :INXB,SAD<- L; LOAD SAD TO ZERO THE BUS. STORE PC AT 0 EM0460> Q0: L<- ONE, :INXA; EXECUTED TWICE EM0461> Q1: L<- TOTUWC, :INXA; EM0462> Q2: L<-402, :INXA; FIRST READ HEADER INTO 402, THEN EM0463> Q3: L<- 402, :INXA; STORE LABEL AT 402 EM0464> Q4: L<- ONE, :INXA; STORE DATA PAGE STARTING AT 1 EM0465> Q5: L<-377+1, :INXE; Store Ethernet Input Buffer Length ***X21. EM0466> Q6: L<-ONE, :INXE; Store Ethernet Input Buffer Pointer ***X21. EM0467> Q7: MAR<- DASTART; CLEAR THE DISPLAY POINTER EM0441> L<- 0; EM0451> R37<- L; EM0472> MD<- 0; EM0473> MAR<- 177034; FETCH KEYBOARD EM0474> L<- 100000; EM0475> NWW<- L, T<- 0-1; EM0476> L<- MD XOR T, BUSODD; *** X21 change. EM0477> MAR<- BDAD, :EtherBoot; [EtherBoot, DiskBoot] *** X21 change. ; BOOT DISK ADDRESS GOES IN LOCATION 12 EM0471> DiskBoot: SAD<- L, L<- 0+1; EM0500> MD<- SAD; EM0501> MAR<- KBLKADR, :FINSTO; ; Ethernet boot section added in X21. $NegBreathM1 $177175; $EthNovaGo $3; First data location of incoming packet EM0470> EtherBoot: L<-EthNovaGo, :EReRead; [EReRead, FINJMP] EM0454> EReRead:MAR<- EHLOC; Set the host address to 377 for breath packets EM0502> TASK; EM0503> MD<- 377; EM0504> MAR<- EPLOC; Zero the status word and start 'er up EM0505> SINK<- 2, STARTF; EM0506> MD <- 0; EM0457> EContRead: MAR<- EPLOC; See if status is still 0 EM0507> T<- 377; Status for correct read EM0510> L<- MD XOR T, TASK, BUS=0; EM0511> SAD<- L, :EReadDone; [EReadDone, EContRead] EM0456> EReadDone: MAR<- 2; Check the packet type EM0512> T<- NegBreathM1; -(Breath-of-life)-1 EM0513> T<-MD+T+1; EM0514> L<-SAD OR T; EM0515> SH=0, :EtherBoot; ; SUBROUTINE USED BY INITIALIZATION TO SET UP BLOCKS OF MEMORY $EIOffset $576; EM0516> INXA: T<-ONE, :INXCom; ***X21 change. EM0517> INXE: T<-EIOffset, :INXCom; ***X21 addition. EM0520> INXCom: MAR<-T<-IR<- SAD+T; *** X21 addition. EM0521> PC<- L, L<- 0+T+1; *** X21 change. EM0522> INXB: SAD<- L; **NB (JDersch 9/14 -- this is actually MD<-PC !) EM0523> SINK<- DISP, BUS,TASK; EM0524> SAD<- L, :Q0; ;REGISTERS USED BY NOVA EMULATOR $AC0 $R3; AC'S ARE BACKWARDS BECAUSE THE HARDWARE SUPPLIES THE $AC1 $R2; COMPLEMENT ADDRESS WHEN ADDRESSING FROM IR $AC2 $R1; $AC3 $R0; $XREG $R7; ;PREDEFINITIONS FOR NOVA !17,20,GETAD,G1,G2,G3,G4,G5,G6,G7,G10,G11,G12,G13,G14,G15,G16,G17; !17,20,XCTAB,XJSR,XISZ,XDSZ,XLDA,XSTA,CONVERT,,,,,,,,,; !3,4,SHIFT,SH1,SH2,SH3; !1,2,MAYBE,NOINT; !1,2,DOINT,DIS0; !1,2,SOMEACTIVE,NOACTIVE; !1,2,IEXIT,NIEXIT; !17,1,ODDCX; !1,2,EIR0,EIR1; !7,1,INTCODE; !1,2,INTSOFF,INTSON; ***X21 addition for DIRS !7,10,EMCYCRET,RAMCYCRET,CYX2,CYX3,CYX4,CONVCYCRET,,; !7,2,MOREBLT,FINBLT; !1,2,DOIT,DISABLED; ; ALL INSTRUCTIONS RETURN TO START WHEN DONE EM0020> START: T<- MAR<-PC+SKIP; EM0525> START1: L<- NWW, BUS=0; BUS# 0 MEANS DISABLED OR SOMETHING TO DO EM0576> :MAYBE, SH<0, L<- 0+T+1; SH<0 MEANS DISABLED EM0526> MAYBE: PC<- L, L<- T, :DOINT; EM0527> NOINT: PC<- L, :DIS0; EM0534> DOINT: MAR<- WWLOC, :INTCODE; TRY TO CAUSE AN INTERRUPT ;DISPATCH ON FUNCTION FIELD IF ARITHMETIC INSTRUCTION, ;OTHERWISE ON INDIRECT BIT AND INDEX FIELD EM0535> DIS0: L<- T<- IR<- MD; SKIP CLEARED HERE ;DISPATCH ON SHIFT FIELD IF ARITHMETIC INSTRUCTION, ;OTHERWISE ON THE INDIRECT BIT OR IR[3-7] EM0612> DIS1: T<- ACSOURCE, :GETAD; ;GETAD MUST BE 0 MOD 20 EM0540> GETAD: T<- 0, :DOINS; PAGE 0 EM0541> G1: T<- PC -1, :DOINS; RELATIVE EM0542> G2: T<- AC2, :DOINS; AC2 RELATIVE EM0543> G3: T<- AC3, :DOINS; AC3 RELATIVE EM0544> G4: T<- 0, :DOINS; PAGE 0 INDIRECT EM0545> G5: T<- PC -1, :DOINS; RELATIVE INDIRECT EM0546> G6: T<- AC2, :DOINS; AC2 RELATIVE INDIRECT EM0547> G7: T<- AC3, :DOINS; AC3 RELATIVE INDIRECT EM0550> G10: L<- 0-T-1, TASK, :SHIFT; COMPLEMENT EM0551> G11: L<- 0-T, TASK, :SHIFT; NEGATE EM0552> G12: L<- 0+T, TASK, :SHIFT; MOVE EM0553> G13: L<- 0+T+1, TASK, :SHIFT; INCREMENT EM0554> G14: L<- ACDEST-T-1, TASK, :SHIFT; ADD COMPLEMENT EM0555> G15: L<- ACDEST-T, TASK, :SHIFT; SUBTRACT EM0556> G16: L<- ACDEST+T, TASK, :SHIFT; ADD EM0557> G17: L<- ACDEST AND T, TASK, :SHIFT; EM0530> SHIFT: DNS<- L LCY 8, :START; SWAP BYTES EM0531> SH1: DNS<- L RSH 1, :START; RIGHT 1 EM0532> SH2: DNS<- L LSH 1, :START; LEFT 1 EM0533> SH3: DNS<- L, :START; NO SHIFT EM0060> DOINS: L<- DISP + T, TASK, :SAVAD, IDISP; DIRECT INSTRUCTIONS EM0061> DOIND: L<- MAR<- DISP+T; INDIRECT INSTRUCTIONS EM0613> XREG<- L; EM0614> L<- MD, TASK, IDISP, :SAVAD; EM0102> BRI: L<- MAR<- PCLOC ;INTERRUPT RETURN BRANCH EM0615> BRI0: T<- 77777; EM0616> L<- NWW AND T, SH < 0; EM0617> NWW<- L, :EIR0; BOTH EIR AND BRI MUST CHECK FOR INTERRUPT ; REQUESTS WHICH MAY HAVE COME IN WHILE ; INTERRUPTS WERE OFF EM0572> EIR0: L<- MD, :DOINT; EM0573> EIR1: L<- PC, :DOINT; ;***X21 addition ; DIRS - 61013 - Disable Interrupts and Skip if they were On EM0113> DIRS: T<-100000; EM0620> L<-NWW AND T; EM0621> L<-PC+1, SH=0; ; DIR - 61000 - Disable Interrupts EM0100> DIR: T<- 100000, :INTSOFF; EM0574> INTSOFF: L<- NWW OR T, TASK, :INTZ; EM0575> INTSON: PC<-L, :INTSOFF; ;EIR - 61001 - Enable Interrupts EM0101> EIR: L<- 100000, :BRI0; ;SIT - 61007 - Start Interval Timer EM0107> SIT: T<- AC0; EM0622> L<- R37 OR T, TASK; EM0623> R37<- L, :START; EM0624> FINJSR: L<- PC; EM0625> AC3<- L, L<- T, TASK; EM0455> FINJMP: PC<- L, :START; EM0626> SAVAD: SAD<- L, :XCTAB; ;JSRII - 64400 - JSR double indirect, PC relative. Must have X=1 in opcode ;JSRIS - 65000 - JSR double indirect, AC2 relative. Must have X=2 in opcode EM0064> JSRII: MAR<- DISP+T; FIRST LEVEL EM0627> IR<- JSRCX; EM0630> T<- MD, :DOIND; THE IR<- INSTRUCTION WILL NOT BRANCH ;TRAP ON UNIMPLEMENTED OPCODES. SAVES PC AT ;TRAPPC, AND DOES A JMP@ TRAPVEC ! OPCODE. EM0077> TRAP: XREG<- L LCY 8; THE INSTRUCTION EM0037> TRAP1: MAR<- TRAPPC;***X13 CHANGE: TAG 'TRAP1' ADDED EM0631> IR<- T<- 37; EM0632> MD<- PC; EM0633> T<- XREG.T; EM0634> T<- TRAPCON+T+1, :DOIND; T NOW CONTAINS 471+OPCODE ; THIS WILL DO JMP@ 530+OPCODE ;***X21 CHANGE: ADDED TAG RAMTRAP EM0076> RAMTRAP: SWMODE, :TRAP; ; Parameterless operations come here for dispatch. !1,2,NPNOTRAP,NPTRAP; EM0063> NOPAR: XREG<-L LCY 8; ***X21 change. Checks < 27. EM0635> T<-27; ***IIX3. Greatest defined op is 26. EM0640> L<-DISP-T; EM0641> ALUCY; EM0642> SINK<-DISP, SINK<-X37, BUS, TASK, :NPNOTRAP; EM0636> NPNOTRAP: :DIR; EM0637> NPTRAP: :TRAP1; ;***X21 addition for debugging w/ expanded DISP Prom EM0065> U5: :RAMTRAP; EM0066> U6: :RAMTRAP; EM0067> U7: :RAMTRAP; ;MAIN INSTRUCTION TABLE. GET HERE: ; (1) AFTER AN INDIRECTION ; (2) ON DIRECT INSTRUCTIONS EM0560> XCTAB: L<- SAD, TASK, :FINJMP; JMP EM0561> XJSR: T<- SAD, :FINJSR; JSR EM0562> XISZ: MAR<- SAD, :ISZ1; ISZ EM0563> XDSZ: MAR<- SAD, :DSZ1; DSZ EM0564> XLDA: MAR<- SAD, :FINLOAD; LDA 0-3 EM0565> XSTA: MAR<- SAD; /*NORMAL EM0643> XSTA1: L<- ACDEST, :FINSTO; /*NORMAL ; BOUNDS-CHECKING VERSION OF STORE ; SUBST ";**" TO ";**" TO ENABLE THIS CODE: ;** !1,2,XSTA1,XSTA2; ;** !1,2,DOSTA,TRAPSTA; ;**XSTA: MAR<- 10; LOCS 10,11 CONTAINS HI,LO BOUNDS ;** T<- SAD ;** L<- MD-T; HIGHBOUND-ADDR ;** T<- MD, ALUCY; ;** L<- SAD-T, :XSTA1; ADDR-LOWBOUND ;**XSTA1: TASK, :XSTA3; ;**XSTA2: ALUCY, TASK; ;**XSTA3: L<- 177, :DOSTA; ;**TRAPSTA: XREG<- L, :TRAP1; CAUSE A SWAT ;**DOSTA: MAR<- SAD; DO THE STORE NORMALLY ;** L<- ACDEST, :FINSTO; ;** EM0644> DSZ1: T<- ALLONES, :FINISZ; EM0645> ISZ1: T<- ONE, :FINISZ; EM0452> FINSTO: SAD<- L,TASK; EM0646> FINST1: MD<-SAD, :START; EM0647> FINLOAD: NOP; EM0650> LOADX: L<- MD, TASK; EM0651> LOADD: ACDEST<- L, :START; EM0652> FINISZ: L<- MD+T; EM0653> MAR<- SAD, SH=0; EM0654> SAD<- L, :FINSTO; EM0453> INCPC: MD<- SAD; EM0655> L<- PC+1, TASK; EM0656> PC<- L, :START; ;DIVIDE. THIS DIVIDE IS IDENTICAL TO THE NOVA DIVIDE EXCEPT THAT ;IF THE DIVIDE CANNOT BE DONE, THE INSTRUCTION FAILS TO SKIP, OTHERWISE ;IT DOES. CARRY IS UNDISTURBED. !1,2,DODIV,NODIV; !1,2,DIVL,ENDDIV; !1,2,NOOVF,OVF; !1,2,DX0,DX1; !1,2,NOSUB,DOSUB; EM0121> DIV: T<- AC2; EM0657> DIVX: L<- AC0 - T; DO THE DIVIDE ONLY IF AC2>AC0 EM0672> ALUCY, TASK, SAD<- L, L<- 0+1; EM0673> :DODIV, SAD<- L LSH 1; SAD<- 2. COUNT THE LOOP BY SHIFTING EM0661> NODIV: :FINBLT; ***X21 change. EM0660> DODIV: L<- AC0, :DIV1; EM0662> DIVL: L<- AC0; EM0674> DIV1: SH<0, T<- AC1; WILL THE LEFT SHIFT OF THE DIVIDEND OVERFLOW? EM0675> :NOOVF, AC0<- L MLSH 1, L<- T<- 0+T; L<- AC1, T<- 0 EM0665> OVF: AC1<- L LSH 1, L<- 0+INCT, :NOV1; L<- 1. SHIFT OVERFLOWED EM0664> NOOVF: AC1<- L LSH 1 , L<- T; L<- 0. SHIFT OK EM0676> NOV1: T<- AC2, SH=0; EM0677> L<- AC0-T, :DX0; EM0667> DX1: ALUCY; DO THE TEST ONLY IF THE SHIFT DIDN'T OVERFLOW. IF ; IT DID, L IS STILL CORRECT, BUT THE TEST WOULD GO ; THE WRONG WAY. EM0700> :NOSUB, T<- AC1; EM0666> DX0: :DOSUB, T<- AC1; EM0671> DOSUB: AC0<- L, L<- 0+INCT; DO THE SUBTRACT EM0701> AC1<- L; AND PUT A 1 IN THE QUOTIENT EM0670> NOSUB: L<- SAD, BUS=0, TASK; EM0702> SAD<- L LSH 1, :DIVL; EM0663> ENDDIV: L<- PC+1, TASK, :DOIT; ***X21 change. Skip if divide was done. ;MULTIPLY. THIS IS AN EXACT EMULATION OF NOVA HARDWARE MULTIPLY. ;AC2 IS THE MULTIPLIER, AC1 IS THE MULTIPLICAND. ;THE PRODUCT IS IN AC0 (HIGH PART), AND AC1 (LOW PART). ;PRECISELY: AC0,AC1 <- AC1*AC2 + AC0 !1,2,DOMUL,NOMUL; !1,2,MPYL,MPYA; !1,2,NOADDIER,ADDIER; !1,2,NOSPILL,SPILL; !1,2,NOADDX,ADDX; !1,2,NOSPILLX,SPILLX; EM0120> MUL: L<- AC2-1, BUS=0; EM0703> MPYX: XREG<-L,L<- 0, :DOMUL; GET HERE WITH AC2-1 IN L. DON'T MUL IF AC2=0 EM0704> DOMUL: TASK, L<- -10+1; EM0720> SAD<- L; COUNT THE LOOP IN SAD EM0706> MPYL: L<- AC1, BUSODD; EM0721> T<- AC0, :NOADDIER; EM0710> NOADDIER: AC1<- L MRSH 1, L<- T, T<- 0, :NOSPILL; EM0711> ADDIER: L<- T<- XREG+INCT; EM0722> L<- AC1, ALUCY, :NOADDIER; EM0713> SPILL: T<- ONE; EM0712> NOSPILL: AC0<- L MRSH 1; EM0723> L<- AC1, BUSODD; EM0724> T<- AC0, :NOADDX; EM0714> NOADDX: AC1<- L MRSH 1, L<- T, T<- 0, :NOSPILLX; EM0715> ADDX: L<- T<- XREG+ INCT; EM0725> L<- AC1,ALUCY, :NOADDX; EM0717> SPILLX: T<- ONE; EM0716> NOSPILLX: AC0<- L MRSH 1; EM0726> L<- SAD+1, BUS=0, TASK; EM0727> SAD<- L, :MPYL; EM0705> NOMUL: T<- AC0; EM0730> AC0<- L, L<- T, TASK; CLEAR AC0 EM0731> AC1<- L; AND REPLACE AC1 WITH AC0 EM0707> MPYA: :FINBLT; ***X21 change. ;CYCLE AC0 LEFT BY DISP MOD 20B, UNLESS DISP=0, IN WHICH ;CASE CYCLE BY AC1 MOD 20B ;LEAVES AC1=CYCLE COUNT-1 MOD 20B $CYRET $R5; Shares space with SAD. $CYCOUT $R7; Shares space with XREG. !1,2,EMCYCX,ACCYCLE; !1,1,Y1; !1,1,Y2; !1,1,Y3; !1,1,Z1; !1,1,Z2; !1,1,Z3; EM0062> EMCYCLE: L<- DISP, SINK<- X17, BUS=0; CONSTANT WITH BS=7 EM0734> CYCP: T<- AC0, :EMCYCX; EM0733> ACCYCLE: T<- AC1; EM0736> L<- 17 AND T, :CYCP; EM0732> EMCYCX: CYCOUT<-L, L<-0, :RETCYCX; EM0022> RAMCYCX: CYCOUT<-L, L<-0+1; EM0740> RETCYCX: CYRET<-L, L<-0+T; EM0742> SINK<-CYCOUT, BUS; EM0744> TASK, :L0; ;TABLE FOR CYCLE EM0174> R4: CYCOUT<- L MRSH 1; EM0741> Y3: L<- T<- CYCOUT, TASK; EM0175> R3X: CYCOUT<- L MRSH 1; EM0737> Y2: L<- T<- CYCOUT, TASK; EM0176> R2X: CYCOUT<- L MRSH 1; EM0735> Y1: L<- T<- CYCOUT, TASK; EM0177> R1X: CYCOUT<- L MRSH 1, :ENDCYCLE; EM0164> L4: CYCOUT<- L MLSH 1; EM0747> Z3: L<- T<- CYCOUT, TASK; EM0163> L3: CYCOUT<- L MLSH 1; EM0745> Z2: L<- T<- CYCOUT, TASK; EM0162> L2: CYCOUT<- L MLSH 1; EM0743> Z1: L<- T<- CYCOUT, TASK; EM0161> L1: CYCOUT<- L MLSH 1, :ENDCYCLE; EM0160> L0: CYCOUT<- L, :ENDCYCLE; EM0170> L8: CYCOUT<- L LCY 8, :ENDCYCLE; EM0167> L7: CYCOUT<- L LCY 8, :Y1; EM0166> L6: CYCOUT<- L LCY 8, :Y2; EM0165> L5: CYCOUT<- L LCY 8, :Y3; EM0171> R7: CYCOUT<- L LCY 8, :Z1; EM0172> R6: CYCOUT<- L LCY 8, :Z2; EM0173> R5: CYCOUT<- L LCY 8, :Z3; EM0746> ENDCYCLE: SINK<- CYRET, BUS, TASK; EM0750> :EMCYCRET; EM0600> EMCYCRET: L<-YCOUT, TASK, :LOADD; EM0601> RAMCYCRET: T<-PC, BUS, SWMODE, :TORAM; ; Scan convert instruction for characters. Takes DWAX (Destination ; word address)-NWRDS in AC0, and a pointer to a .AL-format font ; in AC3. AC2+displacement contains a pointer to a two-word block ; containing NWRDS and DBA (Destination Bit Address). $XH $R10; $DWAX $R35; $MASK $R36; !1,2,HDLOOP,HDEXIT; !1,2,MERGE,STORE; !1,2,NFIN,FIN; !17,2,DOBOTH,MOVELOOP; EM0566> CONVERT: MAR<-XREG+1; Got here via indirect mechanism which ; left first arg in SAD, its address in XREG. EM0751> T<-17; EM0760> L<-MD AND T; EM0761> T<-MAR<-AC3; EM0762> AC1<-L; AC1<-DBA EM0763> L<-MD+T, TASK; EM0764> AC3<-L; AC3<-Character descriptor block address(Char) EM0765> MAR<-AC3+1; EM0766> T<-177400; EM0767> IR<-L<-MD AND T; IR<-XH EM0770> XH<-L LCY 8, :ODDCX; XH register temporarily contains HD EM0577> ODDCX: L<-AC0, :HDENTER; EM0752> HDLOOP: T<-SAD; (really NWRDS) EM0771> L<-DWAX+T; EM0772> HDENTER: DWAX<-L; DWAX <- AC0+HD*NWRDS EM0773> L<-XH-1, BUS=0, TASK; EM0774> XH<-L, :HDLOOP; EM0753> HDEXIT: T<-MASKTAB; EM0775> MAR<-T<-AC1+T; Fetch the mask. EM1000> L<-DISP; EM1001> XH<-L; XH register now contains XH EM1002> L<-MD; EM1003> MASK<-L, L<-0+T+1, TASK; EM1004> AC1<-L; ***X21. AC1 <- (DBA)+1 EM1005> L<-5; ***X21. Calling conventions changed. EM1006> IR<-SAD, TASK; EM1007> CYRET<-L, :MOVELOOP; CYRET<-CALL5 EM0777> MOVELOOP: L<-T<-XH-1, BUS=0; EM1010> MAR<-AC3-T-1, :NFIN; Fetch next source word EM0756> NFIN: XH<-L; EM1011> T<-DISP; (really NWRDS) EM1012> L<-DWAX+T; Update destination address EM1013> T<-MD; EM1014> SINK<-AC1, BUS; EM1015> DWAX<-L, L<-T, TASK, :L0; Call Cycle subroutine EM0605> CONVCYCRET: MAR<-DWAX; EM1016> T<-MASK, BUS=0; EM1017> T<-CYCOUT.T, :MERGE; Data for first word. If MASK=0 ; then store the word rather than ; merging, and do not disturb the ; second word. EM0754> MERGE: L<-XREG AND NOT T; Data for second word. EM1020> T<-MD OR T; First word now merged, EM1021> XREG<-L, L<-T; EM1022> MTEMP<-L; EM1023> MAR<-DWAX; restore it. EM1024> SINK<-XREG, BUS=0, TASK; EM1025> MD<-MTEMP, :DOBOTH; XREG=0 means only one word ; is involved. EM0776> DOBOTH: MAR<-DWAX+1; EM1026> T<-XREG; EM1027> L<-MD OR T; EM1030> MAR<-DWAX+1; EM1031> XREG<-L, TASK; ***X21. TASK added. EM0755> STORE: MD<-XREG, :MOVELOOP; EM0757> FIN: L<-AC1-1; ***X21. Return AC1 to DBA. EM1032> AC1<-L; *** ... bletch ... EM1033> IR<-SH3CONST; EM1034> L<-MD, TASK, :SH1; ;RCLK - 61003 - Read the Real Time Clock into AC0,AC1 EM0103> RCLK: MAR<- CLOCKLOC; EM1035> L<- R37; EM1036> AC1<- L, :LOADX; ;SIO - 61004 - Put AC0 on the bus, issue STARTF to get device attention, ;Read Host address from Ethernet interface into AC0. EM0104> SIO: L<- AC0, STARTF; EM1037> T<- 77777; ***X21 sets AC0[0] to 0 EM1040> L<- RSNF AND T; EM1041> LTOAC0: AC0<- L, TASK, :TOSTART; ;EngNumber is a constant returned by VERS that contains a discription ;of the Alto and it's Microcode. The composition of EngNumber is: ; bits 0-3 Alto engineering number ; bits 4-7 Alto build ; bits 8-15 Version number of Microcode ;Use of the Alto Build number has been abandoned. ;the engineering number (EngNumber) is in the MRT files because it ; it different for Altos with and without Extended memory. EM0114> VERS: T<- EngNumber; ***V3 change EM1042> L<- 3+T, :LTOAC0; ***V3 change ;XMLDA - Extended Memory Load Accumulator. ; AC0 <- @AC1 in the alternate bank EM0125> XMLDA: XMAR<- AC1, :FINLOAD; ***V3 change ;XMSTA - Extended Memory Store Accumulator ; @AC1 <- AC0 in the alternate bank EM0126> XMSTA: XMAR<- AC1, :XSTA1; ***V3 change ;BLT - 61005 - Block Transfer ;BLKS - 61006 - Block Store ; Accepts in ; AC0/ BLT: Address of first word of source block-1 ; BLKS: Data to be stored ; AC1/ Address of last word of destination block ; AC3/ NEGATIVE word count ; Leaves ; AC0/ BLT: Address of last word of source block+1 ; BLKS: Unchanged ; AC1/ Unchanged ; AC2/ Unchanged ; AC3/ 0 ; These instructions are interruptable. If an interrupt occurs, ; the PC is decremented by one, and the ACs contain the intermediate ; so the instruction can be restarted when the interrupt is dismissed. !1,2,PERHAPS, NO; EM0105> BLT: L<- MAR<- AC0+1; EM1043> AC0<- L; EM1046> L<- MD, :BLKSA; EM0106> BLKS: L<- AC0; EM1047> BLKSA: T<- AC3+1, BUS=0; EM1050> MAR<- AC1+T, :MOREBLT; EM0606> MOREBLT: XREG<- L, L<- T; EM1051> AC3<- L, TASK; EM1052> MD<- XREG; STORE EM1053> L<- NWW, BUS=0; CHECK FOR INTERRUPT EM1054> SH<0, :PERHAPS, L<- PC-1; Prepare to back up PC. EM1045> NO: SINK<- DISP, SINK<- M7, BUS, :DISABLED; EM1044> PERHAPS: SINK<- DISP, SINK<- M7, BUS, :DOIT; EM0610> DOIT: PC<-L, :FINBLT; ***X21. Reset PC, terminate instruction. EM0611> DISABLED: :DIR; GOES TO BLT OR BLKS EM0607> FINBLT: T<-777; ***X21. PC in [177000-177777] means Ram return EM1055> L<-PC+T+1; EM1056> L<-PC AND T, TASK, ALUCY; EM1057> TOSTART: XREG<-L, :START; EM0021> RAMRET: T<-XREG, BUS, SWMODE; EM1060> TORAM: :NOVEM; ;PARAMETERLESS INSTRUCTIONS FOR DIDDLING THE WCS. ;JMPRAM - 61010 - JUMP TO THE RAM ADDRESS SPECIFIED BY AC1 EM0110> JMPR: T<-AC1, BUS, SWMODE, :TORAM; ;RDRAM - 61011 - READ THE RAM WORD ADDRESSED BY AC1 INTO AC0 EM0111> RDRM: T<- AC1, RDRAM; EM1061> L<- ALLONES, TASK, :LOADD; ;WRTRAM - 61012 - WRITE AC0,AC3 INTO THE RAM LOCATION ADDRESSED BY AC1 EM0112> WTRM: T<- AC1; EM1062> L<- AC0, WRTRAM; EM1063> L<- AC3, :FINBLT; ;DOUBLE WORD INSTRUCTIONS ;DREAD - 61015 ; AC0<- rv(AC3); AC1<- rv(AC3 xor 1) EM0115> DREAD: MAR<- AC3; START MEMORY CYCLE EM1064> NOP; DELAY EM1065> DREAD1: L<- MD; FIRST READ EM1066> T<-MD; SECOND READ EM1067> AC0<- L, L<-T, TASK; STORE MSW EM1070> AC1<- L, :START; STORE LSW ;DWRITE - 61016 ; rv(AC3)<- AC0; rv(AC3 xor 1)<- AC1 EM0116> DWRITE: MAR<- AC3; START MEMORY CYCLE EM1071> NOP; DELAY EM1072> MD<- AC0, TASK; FIRST WRITE EM1073> MD<- AC1, :START; SECOND WRITE ;DEXCH - 61017 ; t<- rv(AC3); rv(AC3)<- AC0; AC0<- t ; t<- rv(AC3 xor 1); rv(AC3 xor 1)<- AC1; AC1<- t EM0117> DEXCH: MAR<- AC3; START MEMORY CYCLE EM1074> NOP; DELAY EM1075> MD<- AC0; FIRST WRITE EM1076> MD<- AC1,:DREAD1; SECOND WRITE, GO TO READ ;DIOGNOSE INSTRUCTIONS ;DIOG1 - 61022 ; Hamming Code<- AC2 ; rv(AC3)<- AC0; rv(AC3 xor 1)<- AC1 EM0122> DIOG1: MAR<- ERRCTRL; START WRITE TO ERROR CONTROL EM1077> NOP; DELAY EM1100> MD<- AC2,:DWRITE; WRITE HAMMING CODE, GO TO DWRITE ;DIOG2 - 61023 ; rv(AC3)<- AC0 ; rv(AC3)<- AC0 xor AC1 EM0123> DIOG2: MAR<- AC3; START MEMORY CYCLE EM1101> T<- AC0; SETUP FOR XOR EM1102> L<- AC1 XORT; DO XOR EM1103> MD<- AC0; FIRST WRITE EM1104> MAR<- AC3; START MEMORY CYCLE EM1105> AC0<- L, TASK; STORE XOR WORD EM1106> MD<- AC0, :START; SECOND WRITE ;INTERRUPT SYSTEM. TIMING IS 0 CYCLES IF DISABLED, 18 CYCLES ;IF THE INTERRUPTING CHANEL IS INACTIVE, AND 36+6N CYCLES TO CAUSE ;AN INTERRUPT ON CHANNEL N EM0567> INTCODE:PC<- L, IR<- 0; EM1107> T<- NWW; EM1110> T<- MD OR T; EM1111> L<- MD AND T; EM1112> SAD<- L, L<- T, SH=0; SAD HAD POTENTIAL INTERRUPTS EM1113> NWW<- L, L<- 0+1, :SOMEACTIVE; NWW HAS NEW WW EM0537> NOACTIVE: MAR<- WWLOC; RESTORE WW TO CORE EM1114> L<- SAD; AND REPLACE IT WITH SAD IN NWW EM1115> MD<- NWW, TASK; EM1116> INTZ: NWW<- L, :START; EM0536> SOMEACTIVE: MAR<- PCLOC; STORE PC AND SET UP TO FIND HIGHEST PRIORITY REQUEST EM1117> XREG<- L, L<- 0; EM1120> MD<- PC, TASK; EM1121> ILPA: PC<- L; EM1122> ILP: T<- SAD; EM1123> L<- T<- XREG AND T; EM1124> SH=0, L<- T, T<- PC; EM1125> :IEXIT, XREG<- L LSH 1; EM0571> NIEXIT: L<- 0+T+1, TASK, :ILPA; EM0570> IEXIT: MAR<- PCLOC+T+1; FETCH NEW PC. T HAS CHANNEL #, L HAS MASK EM1126> XREG<- L; EM1127> T<- XREG; EM1130> L<- NWW XOR T; TURN OFF BIT IN WW FOR INTERRUPT ABOUT TO HAPPEN EM1131> T<- MD; EM1132> NWW<- L, L<- T; EM1133> PC<- L, L<- T<- 0+1, TASK; EM1134> SAD<- L MRSH 1, :NOACTIVE; SAD<- 1B5 TO DISABLE INTERRUPTS ; ; ************************ ; * BIT-BLT - 61024 * ; ************************ ; Modified September 1977 to support Alternate memory banks ; Last modified Sept 6, 1977 by Dan Ingalls ; ; /* NOVA REGS ; AC2 -> BLT DESCRIPTOR TABLE, AND IS PRESERVED ; AC1 CARRIES LINE COUNT FOR RESUMING AFTER AN ; INTERRUPT. MUST BE 0 AT INITIAL CALL ; AC0 AND AC3 ARE SMASHED TO SAVE S-REGS ; ; /* ALTO REGISTER USAGE ;DISP CARRIES: TOPLD(100), SOURCEBANK(40), DESTBANK(20), ; SOURCE(14), OP(3) $MASK1 $R0; $YMUL $R2; HAS TO BE AN R-REG FOR SHIFTS $RETN $R2; $SKEW $R3; $TEMP $R5; $WIDTH $R7; $PLIER $R7; HAS TO BE AN R-REG FOR SHIFTS $DESTY $R10; $WORD2 $R10; $STARTBITSM1 $R35; $SWA $R36; $DESTX $R36; $LREG $R40; HAS TO BE R40 (COPY OF L-REG) $NLINES $R41; $RAST1 $R42; $SRCX $R43; $SKMSK $R43; $SRCY $R44; $RAST2 $R44; $CONST $R45; $TWICE $R45; $HCNT $R46; $VINC $R46; $HINC $R47; $NWORDS $R50; $MASK2 $R51; WAS $R46; ; $LASTMASKP1 $500; MASKTABLE+021 $170000 $170000; $CALL3 $3; SUBROUTINE CALL INDICES $CALL4 $4; $DWAOFF $2; BLT TABLE OFFSETS $DXOFF $4; $DWOFF $6; $DHOFF $7; $SWAOFF $10; $SXOFF $12; $GRAYOFF $14; GRAY IN WORDS 14-17 $LASTMASK $477; MASKTABLE+020 **NOT IN EARLIER PROMS! ; BITBLT SETUP - CALCULATE RAM STATE FROM AC2'S TABLE ;---------------------------------------------------------- ; ; /* FETCH COORDINATES FROM TABLE !1,2,FDDX,BLITX; !1,2,FDBL,BBNORAM; !17,20,FDBX,,,,FDX,,FDW,,,,FSX,,,,,; FDBL RETURNS (BASED ON OFFSET) ; (0) 4 6 12 EM0124> BITBLT: L<- 0; EM1135> SINK<-LREG, BUSODD; SINK<- -1 IFF NO RAM EM1142> L<- T<- DWOFF, :FDBL; EM1141> BBNORAM: TASK, :NPTRAP; TRAP IF NO RAM ; EM1166> FDW: T<- MD; PICK UP WIDTH, HEIGHT EM1143> WIDTH<- L, L<- T, TASK, :NZWID; EM1144> NZWID: NLINES<- L; EM1145> T<- AC1; EM1146> L<- NLINES-T; EM1147> NLINES<- L, SH<0, TASK; EM1150> :FDDX; ; EM1136> FDDX: L<- T<- DXOFF, :FDBL; PICK UP DEST X AND Y EM1164> FDX: T<- MD; EM1151> DESTX<- L, L<- T, TASK; EM1152> DESTY<- L; ; EM1153> L<- T<- SXOFF, :FDBL; PICK UP SOURCE X AND Y EM1172> FSX: T<- MD; EM1154> SRCX<- L, L<- T, TASK; EM1155> SRCY<- L, :CSHI; ; ; /* FETCH DOUBLEWORD FROM TABLE (L<- T<- OFFSET, :FDBL) EM1140> FDBL: MAR<- AC2+T; EM1156> SINK<- LREG, BUS; EM1160> FDBX: L<- MD, :FDBX; ; ; /* CALCULATE SKEW AND HINC !1,2,LTOR,RTOL; EM1157> CSHI: T<- DESTX; EM1161> L<- SRCX-T-1; EM1165> T<- LREG+1, SH<0; TEST HORIZONTAL DIRECTION EM1167> L<- 17.T, :LTOR; SKEW <- (SRCX - DESTX) MOD 16 EM1163> RTOL: SKEW<- L, L<- 0-1, :AH, TASK; HINC <- -1 EM1162> LTOR: SKEW<- L, L<- 0+1, :AH, TASK; HINC <- +1 EM1170> AH: HINC<- L; ; ; CALCULATE MASK1 AND MASK2 !1,2,IFRTOL,LNWORDS; !1,2,POSWID,NEGWID; EM1171> CMASKS: T<- DESTX; EM1173> T<- 17.T; EM1200> MAR<- LASTMASKP1-T-1; EM1201> L<- 17-T; STARTBITS <- 16 - (DESTX.17) EM1202> STARTBITSM1<- L; EM1203> L<- MD, TASK; EM1204> MASK1<- L; MASK1 <- @(MASKLOC+STARTBITS) EM1205> L<- WIDTH-1; EM1206> T<- LREG-1, SH<0; EM1207> T<- DESTX+T+1, :POSWID; EM1176> POSWID: T<- 17.T; EM1210> MAR<- LASTMASK-T-1; EM1211> T<- ALLONES; MASK2 <- NOT EM1212> L<- HINC-1; EM1213> L<- MD XOR T, SH=0, TASK; @(MASKLOC+(15-((DESTX+WIDTH-1).17))) EM1214> MASK2<- L, :IFRTOL; ; /* IF RIGHT TO LEFT, ADD WIDTH TO X'S AND EXCH MASK1, MASK2 EM1174> IFRTOL: T<- WIDTH-1; WIDTH-1 EM1215> L<- SRCX+T; EM1216> SRCX<- L; SRCX <- SCRX + (WIDTH-1) EM1217> L<- DESTX+T; EM1220> DESTX<- L; DESTX <- DESTX + (WIDTH-1) EM1221> T<- DESTX; EM1222> L<- 17.T, TASK; EM1223> STARTBITSM1<- L; STARTBITS <- (DESTX.17) + 1 EM1224> T<- MASK1; EM1225> L<- MASK2; EM1226> MASK1<- L, L<- T,TASK; EXCHANGE MASK1 AND MASK2 EM1227> MASK2<-L; ; ; /* CALCULATE NWORDS !1,2,LNW1,THIN; EM1175> LNWORDS:T<- STARTBITSM1+1; EM1232> L<- WIDTH-T-1; EM1233> T<- 177760, SH<0; EM1234> T<- LREG.T, :LNW1; EM1230> LNW1: L<- CALL4; NWORDS <- (WIDTH-STARTBITS)/16 EM1235> CYRET<- L, L<- T, :R4, TASK; CYRET<-CALL4 ; **WIDTH REG NOW FREE** EM0604> CYX4: L<- CYCOUT, :LNW2; EM1231> THIN: T<- MASK1; SPECIAL CASE OF THIN SLICE EM1236> L<-MASK2.T; EM1237> MASK1<- L, L<- 0-1; MASK1 <- MASK1.MASK2, NWORDS <- -1 EM1240> LNW2: NWORDS<- L; LOAD NWORDS ; **STARTBITSM1 REG NOW FREE** ; ; /* DETERMINE VERTICAL DIRECTION !1,2,BTOT,TTOB; EM1241> T<- SRCY; EM1244> L<- DESTY-T; EM1245> T<- NLINES-1, SH<0; EM1246> L<- 0, :BTOT; VINC <- 0 IFF TOP-TO-BOTTOM EM1242> BTOT: L<- ALLONES; ELSE -1 EM1247> BTOT1: VINC<- L; EM1250> L<- SRCY+T; GOING BOTTOM TO TOP EM1251> SRCY<- L; ADD NLINES TO STARTING Y'S EM1252> L<- DESTY+T; EM1253> DESTY<- L, L<- 0+1, TASK; EM1254> TWICE<-L, :CWA; ; EM1243> TTOB: T<- AC1, :BTOT1; TOP TO BOT, ADD NDONE TO STARTING Y'S ; **AC1 REG NOW FREE**; ; ; /* CALCULATE WORD ADDRESSES - DO ONCE FOR SWA, THEN FOR DWAX EM1255> CWA: L<- SRCY; Y HAS TO GO INTO AN R-REG FOR SHIFTING EM1256> YMUL<- L; EM1257> T<- SWAOFF; FIRST TIME IS FOR SWA, SRCX EM1260> L<- SRCX; ; **SRCX, SRCY REG NOW FREE** EM1261> DOSWA: MAR<- AC2+T; FETCH BITMAP ADDR AND RASTER EM1262> XREG<- L; EM1263> L<-CALL3; EM1264> CYRET<- L; CYRET<-CALL3 EM1265> L<- MD; EM1266> T<- MD; EM1267> DWAX<- L, L<-T, TASK; EM1270> RAST2<- L; EM1271> T<- 177760; EM1272> L<- T<- XREG.T, :R4, TASK; SWA <- SWA + SRCX/16 EM0603> CYX3: T<- CYCOUT; EM1273> L<- DWAX+T; EM1274> DWAX<- L; ; !1,2,NOADD,DOADD; !1,2,MULLP,CDELT; SWA <- SWA + SRCY*RAST1 EM1275> L<- RAST2; EM1302> SINK<- YMUL, BUS=0, TASK; NO MULT IF STARTING Y=0 EM1303> PLIER<- L, :MULLP; EM1300> MULLP: L<- PLIER, BUSODD; MULTIPLY RASTER BY Y EM1304> PLIER<- L RSH 1, :NOADD; EM1276> NOADD: L<- YMUL, SH=0, TASK; TEST NO MORE MULTIPLIER BITS EM1305> SHIFTB: YMUL<- L LSH 1, :MULLP; EM1277> DOADD: T<- YMUL; EM1306> L<- DWAX+T; EM1307> DWAX<- L, L<-T, :SHIFTB, TASK; ; **PLIER, YMUL REG NOW FREE** ; !1,2,HNEG,HPOS; !1,2,VPOS,VNEG; !1,1,CD1; CALCULATE DELTAS = +-(NWORDS+2)[HINC] +-RASTER[VINC] EM1301> CDELT: L<- T<- HINC-1; (NOTE T<- -2 OR 0) EM1314> L<- T<- NWORDS-T, SH=0; (L<-NWORDS+2 OR T<-NWORDS) EM1315> CD1: SINK<- VINC, BUSODD, :HNEG; EM1310> HNEG: T<- RAST2, :VPOS; EM1311> HPOS: L<- -2-T, :CD1; (MAKES L<- -(NWORDS+2)) EM1312> VPOS: L<- LREG+T, :GDELT, TASK; BY NOW, LREG = +-(NWORDS+2) EM1313> VNEG: L<- LREG-T, :GDELT, TASK; AND T = RASTER EM1316> GDELT: RAST2<- L; ; ; /* END WORD ADDR LOOP !1,2,ONEMORE,CTOPL; EM1317> L<- TWICE-1; EM1322> TWICE<- L, SH<0; EM1323> L<- RAST2, :ONEMORE; USE RAST2 2ND TIME THRU EM1320> ONEMORE: RAST1<- L; EM1324> L<- DESTY, TASK; USE DESTY 2ND TIME THRU EM1325> YMUL<- L; EM1326> L<- DWAX; USE DWAX 2ND TIME THRU EM1327> T<- DESTX; CAREFUL - DESTX=SWA!! EM1330> SWA<- L, L<- T; USE DESTX 2ND TIME THRU EM1331> T<- DWAOFF, :DOSWA; AND DO IT AGAIN FOR DWAX, DESTX ; **TWICE, VINC REGS NOW FREE** ; ; /* CALCULATE TOPLD !1,2,CTOP1,CSKEW; !1,2,HM1,H1; !1,2,NOTOPL,TOPL; EM1321> CTOPL: L<- SKEW, BUS=0, TASK; IF SKEW=0 THEN 0, ELSE EM1340> CTX: IR<- 0, :CTOP1; EM1332> CTOP1: T<- SRCX; (SKEW GR SRCX.17) XOR (HINC EQ 0) EM1341> L<- HINC-1; EM1342> T<- 17.T, SH=0; TEST HINC EM1343> L<- SKEW-T-1, :HM1; EM1335> H1: T<- HINC, SH<0; EM1344> L<- SWA+T, :NOTOPL; EM1334> HM1: T<- LREG; IF HINC=-1, THEN FLIP EM1345> L<- 0-T-1, :H1; THE POLARITY OF THE TEST EM1336> NOTOPL: SINK<- HINC, BUSODD, TASK, :CTX; HINC FORCES BUSODD EM1337> TOPL: SWA<- L, TASK; (DISP <- 100 FOR TOPLD) EM1346> IR<- 100, :CSKEW; ; **HINC REG NOW FREE** ; ; /* CALCULATE SKEW MASK !1,2,THINC,BCOM1; !1,2,COMSK,NOCOM; EM1333> CSKEW: T<- SKEW, BUS=0; IF SKEW=0, THEN COMP EM1347> MAR<- LASTMASKP1-T-1, :THINC; EM1350> THINC: L<-HINC-1; EM1354> SH=0; IF HINC=-1, THEN COMP EM1351> BCOM1: T<- ALLONES, :COMSK; EM1352> COMSK: L<- MD XOR T, :GFN; EM1353> NOCOM: L<- MD, :GFN; ; ; /* GET FUNCTION EM1355> GFN: MAR<- AC2; EM1356> SKMSK<- L; EM1357> T- MD; EM1360> L<- DISP+T, TASK; EM1361> IR<- LREG, :BENTR; DISP <-DISP .OR. FUNCTION ; BITBLT WORK - VERT AND HORIZ LOOPS WITH 4 SOURCES, 4 FUNCTIONS ;----------------------------------------------------------------------- ; ; /* VERTICAL LOOP: UPDATE SWA, DWAX !1,2,DO0,VLOOP; EM1363> VLOOP: T<- SWA; EM1364> L<- RAST1<-T; INC SWA BY DELTA EM1365> SWA<- L; EM1366> T<- DWAX; EM1367> L<- RAST2+T, TASK; INC DWAX BY DELTA EM1370> DWAX<- L; ; ; /* TEST FOR DONE, OR NEED GRAY !1,2,MOREV,DONEV; !1,2,BMAYBE,BNOINT; !1,2,BDOINT,BDIS0; !1,2,DOGRAY,NOGRAY; EM1371> BENTR: L<- T<- NLINES-1; DECR NLINES AND CHECK IF DONE EM1402> NLINES<- L, SH<0; EM1403> L<- NWW, BUS=0, :MOREV; CHECK FOR INTERRUPTS EM1372> MOREV: L<- 3.T, :BMAYBE, SH<0; CHECK DISABLED ***V3 change EM1375> BNOINT: SINK<- DISP, SINK<- lgm10, BUS=0, :BDIS0, TASK; EM1374> BMAYBE: SINK<- DISP, SINK<- lgm10, BUS=0, :BDOINT, TASK; TEST IF NEED GRAY(FUNC=8,12) EM1377> BDIS0: CONST<- L, :DOGRAY; ***V3 change ; ; /* INTERRUPT SUSPENSION (POSSIBLY) !1,1,DOI1; MAY GET AN OR-1 EM1376> BDOINT: :DOI1; TASK HERE EM1405> DOI1: T<- AC2; EM1404> MAR<- DHOFF+T; NLINES DONE = HT-NLINES-1 EM1406> T<- NLINES; EM1407> L<- PC-1; BACK UP THE PC, SO WE GET RESTARTED EM1410> PC<- L; EM1411> L<- MD-T-1, :BLITX, TASK; ...WITH NO LINES DONE IN AC1 ; ; /* LOAD GRAY FOR THIS LINE (IF FUNCTION NEEDS IT) !1,2,PRELD,NOPLD; EM1400> DOGRAY: T<- CONST-1; EM1414> T<- GRAYOFF+T+1; EM1415> MAR<- AC2+T; EM1416> NOP; UGH EM1417> L<- MD; EM1401> NOGRAY: SINK<- DISP, SINK<- lgm100, BUS=0, TASK; TEST TOPLD EM1420> CONST<- L, :PRELD; ; ; /* NORMAL COMPLETION EM1177> NEGWID: L<- 0, :BLITX, TASK; EM1373> DONEV: L<- 0, :BLITX, TASK; MAY BE AN OR-1 HERE! EM1137> BLITX: AC1<- L, :FINBLT; ; ; /* PRELOAD OF FIRST SOURCE WORD (DEPENDING ON ALIGNMENT) !1,2,AB1,NB1; EM1412> PRELD: SINK<- DISP, SINK<- lgm40, BUS=0; WHICH BANK EM1421> T<- HINC, :AB1; EM1423> NB1: MAR<- SWA-T, :XB1; (NORMAL BANK) EM1422> AB1: XMAR<- SWA-T, :XB1; (ALTERNATE BANK) EM1424> XB1: NOP; EM1425> L<- MD, TASK; EM1426> WORD2<- L, :NOPLD; ; ; ; /* HORIZONTAL LOOP - 3 CALLS FOR 1ST, MIDDLE AND LAST WORDS !1,2,FDISPA,LASTH; %17,17,14,DON0,,DON2,DON3; CALLERS OF HORIZ LOOP ; NOTE THIS IGNORES 14-BITS, SO lgm14 WORKS LIKE L<-0 FOR RETN !14,1,LH1; IGNORE RESULTING BUS EM1413> NOPLD: L<- 3, :FDISP; CALL #3 IS FIRST WORD EM1437> DON3: L<- NWORDS; EM1427> HCNT<- L, SH<0; HCNT COUNTS WHOLE WORDS EM1434> DON0: L<- HCNT-1, :DO0; IF NEG, THEN NO MIDDLE OR LAST EM1362> DO0: HCNT<- L, SH<0; CALL #0 (OR-14!) IS MIDDLE WORDS ; UGLY HACK SQUEEZES 2 INSTRS OUT OF INNER LOOP: EM1432> L<- DISP, SINK<- lgm14, BUS, TASK, :FDISPA; (WORKS LIKE L<-0) EM1431> LASTH: :LH1; TASK AND BUS PENDING EM1435> LH1: L<- 2, :FDISP; CALL #2 IS LAST WORD EM1436> DON2: :VLOOP; ; ; ; /* HERE ARE THE SOURCE FUNCTIONS !17,20,,,,F0,,,,F1,,,,F2,,,,F3; IGNORE OP BITS IN FUNCTION CODE !17,20,,,,F0A,,,,F1A,,,,F2A,,,, ; SAME FOR WINDOW RETURNS !3,4,OP0,OP1,OP2,OP3; !1,2,AB2,NB2; EM1433> FDISP: SINK<- DISP, SINK<-lgm14, BUS, TASK; EM1430> FDISPA: RETN<- L, :F0; EM1443> F0: SINK<- DISP, SINK<- lgm40, BUS=0, :WIND; FUNC 0 - WINDOW EM1447> F1: SINK<- DISP, SINK<- lgm40, BUS=0, :WIND; FUNC 1 - NOT WINDOW EM1467> F1A: T<- CYCOUT; EM1442> L<- ALLONES XOR T, TASK, :F3A; EM1453> F2: SINK<- DISP, SINK<- lgm40, BUS=0, :WIND; FUNC 2 - WINDOW .AND. GRAY EM1473> F2A: T<- CYCOUT; EM1444> L<- ALLONES XOR T; EM1445> SINK<- DISP, SINK<- lgm20, BUS=0; WHICH BANK EM1446> TEMP<- L, :AB2; TEMP <- NOT WINDOW EM1441> NB2: MAR<- DWAX, :XB2; (NORMAL BANK) EM1440> AB2: XMAR<- DWAX, :XB2; (ALTERNATE BANK) EM1450> XB2: L<- CONST AND T; WINDOW .AND. GRAY EM1451> T<- TEMP; EM1452> T<- MD .T; DEST.AND.NOT WINDOW EM1454> L<- LREG OR T, TASK, :F3A; (TRANSPARENT) EM1457> F3: L<- CONST, TASK, :F3A; FUNC 3 - CONSTANT (COLOR) ; ; ; /* AFTER GETTING SOURCE, START MEMORY AND DISPATCH ON OP !1,2,AB3,NB3; EM1455> F3A: CYCOUT<- L; (TASK HERE) EM1463> F0A: SINK<- DISP, SINK<- lgm20, BUS=0; WHICH BANK EM1456> SINK<- DISP, SINK<- lgm3, BUS, :AB3; DISPATCH ON OP EM1461> NB3: T<- MAR<- DWAX, :OP0; (NORMAL BANK) EM1460> AB3: T<- XMAR<- DWAX, :OP0; (ALTERNATE BANK) ; ; ; /* HERE ARE THE OPERATIONS - ENTER WITH SOURCE IN CYCOUT %16,17,15,STFULL,STMSK; MASKED OR FULL STORE (LOOK AT 2-BIT) ; OP 0 - SOURCE EM1474> OP0: SINK<- RETN, BUS; TEST IF UNMASKED EM1462> OP0A: L<- HINC+T, :STFULL; ELSE :STMSK EM1475> OP1: T<- CYCOUT; OP 1 - SOURCE .OR. DEST EM1464> L<- MD OR T, :OPN; EM1476> OP2: T<- CYCOUT; OP 2 - SOURCE .XOR. DEST EM1465> L<- MD XOR T, :OPN; EM1477> OP3: T<- CYCOUT; OP 3 - (NOT SOURCE) .AND. DEST EM1466> L<- 0-T-1; EM1470> T<- LREG; EM1471> L<- MD AND T, :OPN; EM1472> OPN: SINK<- DISP, SINK<- lgm20, BUS=0, TASK; WHICH BANK EM1500> CYCOUT<- L, :AB3; ; ; ; /* STORE MASKED INTO DESTINATION !1,2,STM2,STM1; !1,2,AB4,NB4; EM1517> STMSK: L<- MD; EM1501> SINK<- RETN, BUSODD, TASK; DETERMINE MASK FROM CALL INDEX EM1506> TEMP<- L, :STM2; STACHE DEST WORD IN TEMP EM1503> STM1: T<-MASK1, :STM3; EM1502> STM2: T<-MASK2, :STM3; EM1507> STM3: L<- CYCOUT AND T; ***X24. Removed TASK clause. EM1510> CYCOUT<- L, L<- 0-T-1; AND INTO SOURCE EM1511> T<- LREG; T<- MASK COMPLEMENTED EM1512> T<- TEMP .T; AND INTO DEST EM1513> L<- CYCOUT OR T; OR TOGETHER THEN GO STORE EM1514> SINK<- DISP, SINK<- lgm20, BUS=0, TASK; WHICH BANK EM1516> CYCOUT<- L, :AB4; EM1505> NB4: T<- MAR<- DWAX, :OP0A; (NORMAL BANK) EM1504> AB4: T<- XMAR<- DWAX, :OP0A; (ALTERNATE BANK) ; ; /* STORE UNMASKED FROM CYCOUT (L=NEXT DWAX) EM1515> STFULL: MD<- CYCOUT; EM1520> STFUL1: SINK<- RETN, BUS, TASK; EM1521> DWAX<- L, :DON0; ; ; ; /* WINDOW SOURCE FUNCTION ; TASKS UPON RETURN, RESULT IN CYCOUT !1,2,DOCY,NOCY; !17,1,WIA; !1,2,NZSK,ZESK; !1,2,AB5,NB5; EM1530> WIND: L<- T<- SKMSK, :AB5; ENTER HERE (8 INST TO TASK) EM1527> NB5: MAR<- SWA, :XB5; (NORMAL BANK) EM1526> AB5: XMAR<- SWA, :XB5; (ALTERNATE BANK) EM1531> XB5: L<- WORD2.T, SH=0; EM1532> CYCOUT<- L, L<- 0-T-1, :NZSK; CYCOUT<- OLD WORD .AND. MSK EM1525> ZESK: L<- MD, TASK; ZERO SKEW BYPASSES LOTS EM1533> CYCOUT<- L, :NOCY; EM1524> NZSK: T<- MD; EM1534> L<- LREG.T; EM1535> TEMP<- L, L<-T, TASK; TEMP<- NEW WORD .AND. NOTMSK EM1536> WORD2<- L; EM1540> T<- TEMP; EM1541> L<- T<- CYCOUT OR T; OR THEM TOGETHER EM1542> CYCOUT<- L, L<- 0+1, SH=0; DONT CYCLE A ZERO ***X21. EM1543> SINK<- SKEW, BUS, :DOCY; EM1522> DOCY: CYRET<- L LSH 1, L<- T, :L0; CYCLE BY SKEW ***X21. EM1523> NOCY: T<- SWA, :WIA; (MAY HAVE OR-17 FROM BUS) EM0602> CYX2: T<- SWA; EM1537> WIA: L<- HINC+T; EM1544> SINK<- DISP, SINK<- lgm14, BUS, TASK; DISPATCH TO CALLER EM1545> SWA<- L, :F0A; ; THE DISK CONTROLLER ; ITS REGISTERS: $DCBR $R34; $KNMAR $R33; $CKSUMR $R32; $KWDCT $R31; $KNMARW $R33; $CKSUMRW $R32; $KWDCTW $R31; ; ITS TASK SPECIFIC FUNCTIONS AND BUS SOURCES: $KSTAT $L020012,014003,124100; DF1 = 12 (LHS) BS = 3 (RHS) $RWC $L024011,000000,000000; NDF2 = 11 $RECNO $L024012,000000,000000; NDF2 = 12 $INIT $L024010,000000,000000; NDF2 = 10 $CLRSTAT $L016014,000000,000000; NDF1 = 14 $KCOMM $L020015,000000,124000; DF1 = 15 (LHS only) Requires bus def $SWRNRDY $L024014,000000,000000; NDF2 = 14 $KADR $L020016,000000,124000; DF1 = 16 (LHS only) Requires bus def $KDATA $L020017,014004,124100; DF1 = 17 (LHS) BS = 4 (RHS) $STROBE $L016011,000000,000000; NDF1 = 11 $NFER $L024015,000000,000000; NDF2 = 15 $STROBON $L024016,000000,000000; NDF2 = 16 $XFRDAT $L024013,000000,000000; NDF2 = 13 $INCRECNO $L016013,000000,000000; NDF1 = 13 ; THE DISK CONTROLLER COMES IN TWO PARTS. THE SECTOR ; TASK HANDLES DEVICE CONTROL AND COMMAND UNDERSTANDING ; AND STATUS REPORTING AND THE LIKE. THE WORD TASK ONLY ; RUNS AFTER BEING ENABLED BY THE SECTOR TASK AND ; ACTUALLY MOVES DATA WORDS TO AND FRO. ; THE SECTOR TASK ; LABEL PREDEFINITIONS: !1,2,COMM,NOCOMM; !1,2,COMM2,IDLE1; !1,2,BADCOMM,COMM3; !1,2,COMM4,ILLSEC; !1,2,COMM5,WHYNRDY; !1,2,STROB,CKSECT; !1,2,STALL,CKSECT1; !1,2,KSFINI,CKSECT2; !1,2,IDLE2,TRANSFER; !1,2,STALL2,GASP; !1,2,INVERT,NOINVERT; SE0004> KSEC: MAR<- KBLKADR2; SE1574> KPOQ: CLRSTAT; RESET THE STORED DISK ADDRESS SE1575> MD<-L<-ALLONES+1, :GCOM2; ALSO CLEAR DCB POINTER SE1576> GETCOM: MAR<-KBLKADR; GET FIRST DCB POINTER SE1577> GCOM1: NOP; SE1600> L<-MD; SE1601> GCOM2: DCBR<-L,TASK; SE1602> KCOMM<-TOWTT; IDLE ALL DATA TRANSFERS SE1603> MAR<-KBLKADR3; GENERATE A SECTOR INTERRUPT SE1604> T<-NWW; SE1605> L<-MD OR T; SE1606> MAR<-KBLKADR+1; STORE THE STATUS SE1607> NWW<-L, TASK; SE1610> MD<-KSTAT; SE1611> MAR<-KBLKADR; WRITE THE CURRENT DCB POINTER SE1612> KSTAT<-5; INITIAL STATUS IS INCOMPLETE SE1613> L<-DCBR,TASK,BUS=0; SE1614> MD<-DCBR, :COMM; ; BUS=0 MAPS COMM TO NOCOMM SE1546> COMM: T<-2; GET THE DISK COMMAND SE1615> MAR<-DCBR+T; SE1616> T<-TOTUWC; SE1617> L<-MD XOR T, TASK, STROBON; SE1620> KWDCT<-L, :COMM2; ; STROBON MAPS COMM2 TO IDLE1 SE1550> COMM2: T<-10; READ NEW DISK ADDRESS SE1621> MAR<-DCBR+T+1; SE1622> T<-KWDCT; SE1623> L<-ONE AND T; SE1624> L<- -400 AND T, SH=0; SE1625> T<-MD, SH=0, :INVERT; ; SH=0 MAPS INVERT TO NOINVERT SE1572> INVERT: L<-2 XOR T, TASK, :BADCOMM; SE1573> NOINVERT: L<-T, TASK, :BADCOMM; ; SH=0 MAPS BADCOMM TO COMM3 SE1553> COMM3: KNMAR<-L; SE1626> MAR<-KBLKADR2; WRITE THE NEW DISK ADDRESS SE1627> T<-SECT2CM; CHECK FOR SECTOR > 13 SE1630> L<-T<-KDATA<-KNMAR+T; NEW DISK ADDRESS TO HARDWARE SE1631> KADR<-KWDCT,ALUCY; DISK COMMAND TO HARDWARE SE1632> L<-MD XOR T,TASK, :COMM4; COMPARE OLD AND NEW DISK ADDRESSES ; ALUCY MAPS COMM4 TO ILLSEC SE1554> COMM4: CKSUMR<-L; SE1633> MAR<-KBLKADR2; WRITE THE NEW DISK ADDRESS SE1634> T<-CADM,SWRNRDY; SEE IF DISK IS READY SE1635> L<-CKSUMR AND T, :COMM5; ; SWRNRDY MAPS COMM5 TO WHYNRDY SE1556> COMM5: MD<-KNMAR; COMPLETE THE WRITE SE1636> SH=0,TASK; SE1637> :STROB; ; SH=0 MAPS STROB TO CKSECT SE1561> CKSECT: T<-KNMAR,NFER; SE1640> L<-KSTAT XOR T, :STALL; ; NFER MAPS STALL TO CKSECT1 SE1563> CKSECT1: CKSUMR<-L,XFRDAT; SE1641> T<-CKSUMR, :KSFINI; ; XFRDAT MAPS KSFINI TO CKSECT2 SE1565> CKSECT2: L<-SECTMSK AND T; SE1642> KSLAST: BLOCK,SH=0; SE1571> GASP: TASK, :IDLE2; ; SH=0 MAPS IDLE2 TO TRANSFER SE1567> TRANSFER: KCOMM<-TOTUWC; TURN ON THE TRANSFER !1,2,ERRFND,NOERRFND; !1,2,EF1,NEF1; SE1643> DMPSTAT: T<-COMERR1; SEE IF STATUS REPRESENTS ERROR SE1650> L<-KSTAT AND T; SE1651> MAR<-DCBR+1; WRITE FINAL STATUS SE1652> KWDCT<-L,TASK,SH=0; SE1653> MD<-KSTAT,:ERRFND; ; SH=0 MAPS ERRFND TO NOERRFND SE1645> NOERRFND: T<-6; PICK UP NO-ERROR INTERRUPT WORD SE1654> INTCOM: MAR<-DCBR+T; SE1655> T<-NWW; SE1656> L<-MD OR T; SE1657> SINK<-KWDCT,BUS=0,TASK; SE1660> NWW<-L,:EF1; ; BUS=0 MAPS EF1 TO NEF1 SE1647> NEF1: MAR<-DCBR,:GCOM1; FETCH ADDRESS OF NEXT CONTROL BLOCK SE1644> ERRFND: T<-7,:INTCOM; PICK UP ERROR INTERRUPT WORD SE1646> EF1: :KSEC; SE1547> NOCOMM: L<-ALLONES,CLRSTAT,:KSLAST; SE1551> IDLE1: L<-ALLONES,:KSLAST; SE1566> IDLE2: KSTAT<-LOW14, :GETCOM; NO ACTIVITY THIS SECTOR SE1552> BADCOMM: KSTAT<-7; ILLEGAL COMMAND ONLY NOTED IN KBLK STAT SE1661> BLOCK; SE1662> TASK,:EF1; SE1557> WHYNRDY: NFER; SE1562> STALL: BLOCK, :STALL2; ; NFER MAPS STALL2 TO GASP SE1570> STALL2: TASK; SE1663> :DMPSTAT; SE1555> ILLSEC: KSTAT<-7, :STALL; ILLEGAL SECTOR SPECIFIED SE1560> STROB: CLRSTAT; SE1664> L<-ALLONES,STROBE,:CKSECT1; SE1564> KSFINI: KSTAT<-4, :STALL; COMMAND FINISHED CORRECTLY ;DISK WORD TASK ;WORD TASK PREDEFINITIONS !37,37,,,,RP0,INPREF1,CKP0,WP0,,PXFLP1,RDCK0,WRT0,REC1,,REC2,REC3,,,REC0RC,REC0W,R0,,CK0,W0,,R2,,W2,,REC0,,KWD; !1,2,RW1,RW2; !1,2,CK1,CK2; !1,2,CK3,CK4; !1,2,CKERR,CK5; !1,2,PXFLP,PXF2; !1,2,PREFDONE,INPREF; !1,2,,CK6; !1,2,CKSMERR,PXFLP0; KW1737> KWD: BLOCK,:REC0; ; SH<0 MAPS REC0 TO REC0 ; ANYTHING=INIT MAPS REC0 TO KWD KW1735> REC0: L<-2, TASK; LENGTH OF RECORD 0 (ALLOW RELEASE IF BLOCKED) KW1665> KNMARW<-L; KW1702> T<-KNMARW, BLOCK, RWC; GET ADDR OF MEMORY BLOCK TO TRANSFER KW1710> MAR<-DCBR+T+1, :REC0RC; ; WRITE MAPS REC0RC TO REC0W ; INIT MAPS REC0RC TO KWD KW1722> REC0RC: T<-MFRRDL,BLOCK, :REC12A; FIRST RECORD READ DELAY KW1723> REC0W: T<-MFR0BL,BLOCK, :REC12A; FIRST RECORD 0'S BLOCK LENGTH KW1714> REC1: L<-10, INCRECNO; LENGTH OF RECORD 1 KW1715> T<-4, :REC12; KW1716> REC2: L<-PAGE1, INCRECNO; LENGTH OF RECORD 2 KW1725> T<-5, :REC12; KW1730> REC12: MAR<-DCBR+T, RWC; MEM BLK ADDR FOR RECORD KW1732> KNMARW<-L, :RDCK0; ; RWC=WRITE MAPS RDCK0 INTO WRT0 ; RWC=INIT MAPS RDCK0 INTO KWD KW1712> RDCK0: T<-MIRRDL, :REC12A; KW1713> WRT0: T<-MIR0BL, :REC12A; KW1734> REC12A: L<-MD; KW1736> KWDCTW<-L, L<-T; KW1740> COM1: KCOMM<- STUWC, :INPREF0; KW1701> INPREF: L<-CKSUMRW+1, INIT, BLOCK; KW1741> INPREF0: CKSUMRW<-L, SH<0, TASK, :INPREF1; ; INIT MAPS INPREF1 TO KWD KW1705> INPREF1: KDATA<-0, :PREFDONE; ; SH<0 MAPS PREFDONE TO INPREF KW1700> PREFDONE: T<-KNMARW; COMPUTE TOP OF BLOCK TO TRANSFER KW0016> KWDX: L<-KWDCTW+T,RWC; (ALSO USED FOR RESET) KW1742> KNMARW<-L,BLOCK,:RP0; ; RWC=CHECK MAPS RP0 TO CKP0 ; RWC=WRITE MAPS RP0 AND CKP0 TO WP0 ; RWC=INIT MAPS RP0, CKP0, AND WP0 TO KWD KW1704> RP0: KCOMM<-STRCWFS,:WP1; KW1706> CKP0: L<-KWDCTW-1; ADJUST FINISHING CONDITION BY 1 FOR CHECKING ONLY KW1743> KWDCTW<-L,:RP0; KW1707> WP0: KDATA<-ONE; WRITE THE SYNC PATTERN KW1744> WP1: L<-KBLKADR,TASK,:RW1; INITIALIZE THE CHECKSUM AND ENTER XFER LOOP KW1745> XFLP: T<-L<-KNMARW-1; BEGINNING OF MAIN XFER LOOP KW1746> KNMARW<-L; KW1747> MAR<-KNMARW,RWC; KW1750> L<-KWDCTW-T,:R0; ; RWC=CHECK MAPS R0 TO CK0 ; RWC=WRITE MAPS R0 AND CK0 TO W0 ; RWC=INIT MAPS R0, CK0, AND W0 TO KWD KW1724> R0: T<-CKSUMRW,SH=0,BLOCK; KW1751> MD<-L<-KDATA XOR T,TASK,:RW1; ; SH=0 MAPS RW1 TO RW2 KW1666> RW1: CKSUMRW<-L,:XFLP; KW1727> W0: T<-CKSUMRW,BLOCK; KW1752> KDATA<-L<-MD XOR T,SH=0; KW1753> TASK,:RW1; ; AS ALREADY NOTED, SH=0 MAPS RW1 TO RW2 KW1726> CK0: T<-KDATA,BLOCK,SH=0; KW1754> L<-MD XOR T,BUS=0,:CK1; ; SH=0 MAPS CK1 TO CK2 KW1670> CK1: L<-CKSUMRW XOR T,SH=0,:CK3; ; BUS=0 MAPS CK3 TO CK4 KW1672> CK3: TASK,:CKERR; ; SH=0 MAPS CKERR TO CK5 KW1675> CK5: CKSUMRW<-L,:XFLP; KW1673> CK4: MAR<-KNMARW, :CK6; ; SH=0 MAPS CK6 TO CK6 KW1703> CK6: CKSUMRW<-L,L<-0+T; KW1755> MTEMP<-L,TASK; KW1756> MD<-MTEMP,:XFLP; KW1671> CK2: L<-CKSUMRW-T,:R2; ; BUS=0 MAPS R2 TO R2 KW1667> RW2: CKSUMRW<-L; KW1757> T<-KDATA<-CKSUMRW,RWC; THIS CODE HANDLES THE FINAL CHECKSUM KW1760> L<-KDATA-T,BLOCK,:R2; ; RWC=CHECK NEVER GETS HERE ; RWC=WRITE MAPS R2 TO W2 ; RWC=INIT MAPS R2 AND W2 TO KWD KW1731> R2: L<-MRPAL, SH=0; SET READ POSTAMBLE LENGTH, CHECK CKSUM KW1761> KCOMM<-TOTUWC, :CKSMERR; ; SH=0 MAPS CKSMERR TO PXFLP0 KW1733> W2: L<-MWPAL, TASK; SET WRITE POSTAMBLE LENGTH KW1762> CKSUMRW<-L, :PXFLP; KW1720> CKSMERR: KSTAT<-0,:PXFLP0; 0 MEANS CHECKSUM ERROR .. CONTINUE KW1676> PXFLP: L<-CKSUMRW+1, INIT, BLOCK; KW1721> PXFLP0: CKSUMRW<-L, TASK, SH=0, :PXFLP1; ; INIT MAPS PXFLP1 TO KWD KW1711> PXFLP1: KDATA<-0,:PXFLP; ; SH=0 MAPS PXFLP TO PXF2 KW1677> PXF2: RECNO, BLOCK; DISPATCH BASED ON RECORD NUMBER KW1763> :REC1; ; RECNO=2 MAPS REC1 INTO REC2 ; RECNO=3 MAPS REC1 INTO REC3 ; RECNO=INIT MAPS REC1 INTO KWD KW1717> REC3: KSTAT<-4,:PXFLP; 4 MEANS SUCCESS!!! KW1674> CKERR: KCOMM<-TOTUWC; TURN OFF DATA TRANSFER KW1764> L<-KSTAT<-6, :PXFLP1; SHOW CHECK ERROR AND LOOP ;The Parity Error Task ;Its label predefinition is way earlier ;It dumps the following interesting registers: ;614/ DCBR Disk control block ;615/ KNMAR Disk memory address ;616/ DWA Display memory address ;617/ CBA Display control block ;620/ PC Emulator program counter ;621/ SAD Emulator temporary register for indirection PA0015> PART: T<- 10; PA1765> L<- ALLONES; TURN OFF MEMORY INTERRUPTS PA1766> MAR<- ERRCTRL, :PX1; PA0450> PR8: L<- SAD, :PX; PA0447> PR7: L<- PC, :PX; PA0446> PR6: L<- CBA, :PX; PA0445> PR5: L<- DWA, :PX; PA0444> PR4: L<- KNMAR, :PX; PA0443> PR3: L<- DCBR, :PX; PA0442> PR2: L<- NWW OR T, TASK; T CONTAINS 1 AT THIS POINT PA0440> PR0: NWW<- L, :PART; PA1767> PX: MAR<- 612+T; PA1770> PX1: MTEMP<- L, L<- T; PA1771> MD<- MTEMP; PA1772> CURDATA<- L; THIS CLOBBERS THE CURSOR FOR ONE PA1773> T<- CURDATA-1, BUS; FRAME WHEN AN ERROR OCCURS PA1774> :PR0; AltoIIMRT4K.mu: ; ; last modified December 1, 1977 1:14 AM ; ; This is the part of the Memory Refresh Task which ; is specific to Alto IIs WITHOUT Extended memory. ; ; Copyright Xerox Corporation 1979 $EngNumber $20000; ALTO 2 WITHOUT EXTENDED MEMORY MRT: SINK_ MOUSE, BUS; MOUSE DATA IS ANDED WITH 17B MRTA: L<- T<- -2, :TX0; DISPATCH ON MOUSE CHANGE TX0: L_ T_ R37 AND NOT T; UPDATE REFRESH ADDRESS T_ 3+T+1, SH=0; L_ REFIIMSK ANDT, :DOTIMER; NOTIMER:R37_ L; STORE UPDATED REFRESH ADDRESS TIMERTN:L_ REFZERO AND T; SH=0; TEST FOR CLOCK TICK :NOCLK; NOCLK: MAR_ R37; FIRST FEFRESH CYCLE L_ CURX; T_ 2, SH=0; MAR_ R37 XORT, :DOCUR; SECOND REFRESH CYCLE NOCUR: CURDATA_ L, TASK; MRTLAST:CURDATA_ L, :MRT; DOTIMER:R37_ L; SAVE REFRESH ADDRESS MAR_EIALOC; INTERVAL TIMER/EIA INTERFACE L_2 AND T; SH=0, L_T_REFZERO.T; ***V3 CHANGE (USED TO BE BIAS) CURDATA_L, :SPCHK; CURDATA_CURRENT TIME WITHOUT CONTROL BITS SPCHK: SINK_MD, BUS=0, TASK; CHECK FOR EIA LINE SPACING SPIA: :NOTIMERINT, CLOCKTEMP_L; NOSPCHK:L_MD; CHECK FOR TIME=NOW MAR_TRAPDISP-1; CONTAINS TIME AT WHICH INTERRUPT SHOULD HAPPEN MTEMP_L; IF INTERRUPT IS CAUSED, L_ MD-T; LINE STATE WILL BE STORED SH=0, TASK, L_MTEMP, :SPIA; TIMERINT:MAR_ ITQUAN; STORE THE THING IN CLOCKTEMP AT ITQUAN L_ CURDATA; R37_ L; T_NWW; AND CAUSE AN INTERRUPT ON THE CHANNELS MD_CLOCKTEMP; SPECIFIED BY ITQUAN+1 L_MD OR T, TASK; NWW_L; NOTIMERINT: T_R37, :TIMERTN; ;The rest of MRT, starting at the label CLOCK is unchanged AltoIIMRT16K.mu: ; ; last modified December 1, 1977 1:13 AM ; ; This is the part of the Memory Refresh Task which ; is specific to Alto IIs with Extended memory. ; ; Copyright Xerox Corporation 1979 $EngNumber $30000; ALTO II WITH EXTENDED MEMORY ; ; This version assumes MRTACT is cleared by BLOCK, not MAR_ R37 ; R37 [4-13] are the low bits of the TOD clock ; R37 [8-14] are the refresh address bits ; Each time MRT runs, four refresh addresses are generated, though ; R37 is incremented only once. Sprinkled throughout the execution ; of this code are the following operations having to do with refresh: ; MAR_ R37 ; R37_ R37 +4 NOTE THAT R37 [14] DOES NOT CHANGE ; MAR_ R37 XOR 2 TOGGLES BIT 14 ; MAR_ R37 XOR 200 TOGGLES BIT 8 ; MAR_ R37 XOR 202 TOGGLES BITS 8 AND 14 MR0010> MRT: MAR<- R37; **FIRST REFRESH CYCLE** MR0351> SINK<- MOUSE, BUS; MOUSE DATA IS ANDED WITH 17B MR0360> MRTA: L<- T<- -2, :TX0; DISPATCH ON MOUSE CHANGE MR0340> TX0: L<- R37 AND NOT T, T<- R37;INCREMENT CLOCK MR0361> T<- 3+T+1, SH=0; IE. T<- T +4. IS INTV TIMER ON? MR0362> L<- REFIIMSK AND T, :DOTIMER; [DOTIMER,NOTIMER] ZERO HIGH 4 BITS MR0331> NOTIMER: R37<- L; STORE UPDATED CLOCK MR0332> NOTIMERINT: T<- 2; NO STATE AT THIS POINT IN PUBLIC REGS MR0363> MAR<- R37 XOR T,T<- R37; **SECOND REFRESH CYCLE** MR0364> L<- REFZERO AND T; ONLY THE CLOKCK BITS, PLEASE MR0365> SH=0, TASK; TEST FOR CLOCK OVERFLOW MR0366> :NOCLK; [NOCLK,CLOCK] MR0354> NOCLK: T <- 200; MR0367> MAR<- R37 XOR T; **THIRD FEFRESH CYCLE** MR0370> L<- CURX, BLOCK; CLEARS WAKEUP REQUEST FF MR0371> T<- 2 OR T, SH=0; NEED TO CHECK CURSOR? MR0372> MAR<- R37 XOR T, :DOCUR; **FOURTH REFRESH CYCLE** MR0335> NOCUR: CURDATA<- L, TASK; MR0327> MRTLAST:CURDATA<- L, :MRT; END OF MAIN LOOP MR0330> DOTIMER:R37<- L; STORE UPDATED CLOCK MR0373> MAR<- EIALOC; INTERVAL TIMER/EIA INTERFACE MR0374> L<- 2 AND T; MR0375> SH=0, L<- T<- REFZERO.T; ***V3 CHANGE (USED TO BE BIAS) MR0376> CURDATA<-L, :SPCHK; CURDATA<- CURRENT TIME WITHOUT CONTROL BITS MR0352> SPCHK: SINK<- MD, BUS=0, TASK; CHECK FOR EIA LINE SPACING MR0377> SPIA: :NOTIMERINT, CLOCKTEMP<- L; MR0353> NOSPCHK:L<-MD; CHECK FOR TIME = NOW MR0400> MAR<-TRAPDISP-1; CONTAINS TIME AT WHICH INTERRUPT SHOULD HAPPEN MR0401> MTEMP<-L; IF INTERRUPT IS CAUSED, MR0402> L<- MD-T; LINE STATE WILL BE STORED MR0403> SH=0, TASK, L<-MTEMP, :SPIA; MR0333> TIMERINT:MAR<- ITQUAN; STORE THE THING IN CLOCKTEMP AT ITQUAN MR0404> L<- CURDATA; MR0405> R37<- L; MR0406> T<-NWW; AND CAUSE AN INTERRUPT ON THE CHANNELS MR0407> MD<-CLOCKTEMP; SPECIFIED BY ITQUAN+1 MR0410> L<-MD OR T, TASK; MR0411> NWW<-L,:NOTIMERINT; ;The rest of MRT, starting at the label CLOCK is unchanged