; BcplEmuEIA.mu -- Top-level microcode source for Alto EIA driver-- ; this version does EIA processing in the Emulator task ; Last modified September 23, 1978 4:18 PM #AltoConsts23.mu; ; Reset locations of the tasks to be started in the Ram (Emulator, MRT, ; and one extra Ethernet). Extra Ethernet is assumed to be run by task 2. !17, 20, Emulator, , EREST, , , , , , MRT; ; Ram entry point for fielding undefined opcodes. !37, 1, TRAP1; ; Reserve 774-1003 for Ram Utility Area. %7, 1777, 774, RU774, RU775, RU776, RU777, RU1000, RU1001, RU1002, RU1003; ; For the moment, just throw these locations away. This is done only ; to squelch the "unused predef" warnings that would otherwise occur. ; If we ever run short of Ram, assign these to real instructions somewhere ; in microcode executed only by the Emulator. RU774: NOP; RU775: NOP; RU776: NOP; RU777: NOP; RU1000: NOP; RU1001: NOP; RU1002: NOP; RU1003: NOP; ; **** Modified Memory Refresh Task **** #EmuEIAMRT.mu; ; **** EIA microcode **** #AltoEIA1.mu; #AltoEIA2.mu; ; **** Extra Ethernet microcode **** $ECNTR $R11; Same as CLOCKTEMP, which has been abolished $EPNTR $R14; Not used by Nova emulator #ExtraEther1.mu; ; Nova emulator conventions $START $L 4020, 0, 0; Emulator entry point $AC0 $R3; $AC1 $R2; $AC2 $R1; $AC3 $R0; $XREG $R7; ; **** Emulator Task **** ; Degenerate -- just returns control to emulator in Rom0 (for silent boot). Emulator: SWMODE; Switch to Rom1 :START; Nova emulator entry point ; Trap handler and dispatcher for instructions that trap into ; the RAM. In the following predefinition, the tags correspond ; to opcodes 60000, 60400, 61000, 61400, ... 77400. ; Note that opcodes 60000, 60400, 61000, 64400, 65000, 67000, and 77400 ; cannot be used since control never gets to the RAM for these. ; 61400, 62000, and 62400 are reserved for the Bcpl Runtime package, ; should it ever be included. ; 63000 SilentBoot ; 63400 EnableEIA ; 64000 PupChecksum ; 65400 ProcessEIA !37,40, TrapDispatch, , , , , , SilentBoot, EnableEIA, PupChecksum, , , ProcessEIA; ; Control comes here with the instruction LCY 8 in XREG TRAP1: T_ 37; L_ XREG AND T; TrapDispatch: SINK_ M, BUS, TASK; :TrapDispatch; ; Microcode subroutines are defined and called from Bcpl programs ; by loading arguments into AC0, AC1, and AC3 and executing the ; appropriate trap opcode. The return value, if any, is in AC0. ; A Bcpl-callable subroutine is available to do this (in CallRam.asm): ; result = CallRam(opcode, ac0, ac1, ac3) ; SilentBoot subroutine: ; CallRam(#63000, bootLocusVector) ; Sets the Boot Locus Vector and does a silent boot. SilentBoot: RMR_ AC0; Set BLV from arg SINK_ 100000, STARTF, :Emulator; Boot the machine, resume emulator ; EnableEIA subroutine: ; CallRam(#63400, lineTab) ; If lineTab is nonzero, specifies the address of the Line Table (LINTAB) ; and enables the EIA microcode. ; If lineTab is zero, disables the EIA microcode. !1, 2, EIAOn, EIAOff; EnableEIA: L_ AC0; Get arg LINTAB_ L, SH=0; Set LINTAB, test for zero EIAExit: T_ 1, :EIAOn; [EIAOn, EIAOff] EIAOn: L_ R37 OR T, TASK, :UpdR37; Nonzero, turn on R37[15] EIAOff: L_ R37 AND NOT T, TASK; Zero, turn off R37[15] UpdR37: R37_ L, :Emulator; Update R37, resume emulator ; PupChecksum subroutine: ; result = CallRam(#64000, 0, address, count) ; AC0: 0 initially ; AC1: address of block ; AC3: length of block (words) ; Computes the ones-complement add-and-cycle checksum over the block. ; This instruction is interruptible. If an interrupt occurs, intermediate ; state is stored in the ACs and the PC is backed up so the instruction will ; start over when the interrupt is dismissed. ; Timing: 9 cycles/word ; 2484 cycles (= 422 microseconds) per maximum-length Pup $AC3 $R0; $AC1 $R2; $AC0 $R3; $NWW $R4; $PC $R6; !1,2,PCMayI,PCNoI; !1,2,PCDoI,PCDisI; !1,2,PCNoCy,PCCy; !1,2,PCLoop,PCDone; !1,2,PCNoMZ,PCMinZ; PupChecksum: MAR_ L_ AC1, :PCLp1; Start fetch of first word ; Top of main loop PCLoop: MAR_ L_ AC1+1; Start fetch of next word PCLp1: AC1_ L; Update pointer L_ NWW, BUS=0; Test for interrupts T_ AC0, SH<0, :PCMayI; [PCMayI, PCNoI] Get partial sum PCNoI: L_ MD+T, :PCDisI; Add new word PCDisI: T_ M, ALUCY; Test for carry out L_ AC3-1, :PCNoCy; [PCNoCy, PCCy] Decrement count PCNoCy: AC3_ L, L_ T, SH=0, TASK, :PCLast; No carry PCCy: AC3_ L, L_ T_ 0+T+1, SH=0, TASK; Do end-around carry PCLast: AC0_ L MLSH 1, :PCLoop; [PCLoop, PCDone] Left cycle 1 ; Here when done PCDone: L_ AC0+1; Test for minus zero (ones-complement) L_ PC, SH=0; PCDn1: PC_ L, L_ 0, TASK, :PCNoMZ; [PCNoMZ, PCMinZ] PCNoMZ: :Emulator; PCMinZ: AC0_ L, :Emulator; Minus zero, change to plus zero ; Here when have potential interrupt; branch pending on disable bit. PCMayI: L_ MD+T, :PCDoI; [PCDoI, PCDisI] PCDoI: L_ PC-1, :PCDn1; Back up PC ; ProcessEIA instruction. ; Executed as the only instruction of the interrupt routine invoked ; by MRT when it finds that EIA processing is required. ProcessEIA: L_ R37, :CheckEIA; CheckEIA does R37_ L ; CheckEIA goes to EIAExit (above) when done. ; EIAExit turns MRT polling back on.