; BcplGateCP.mu -- Top-level microcode source for Alto Gateway running ; Bcpl and using CommProc. ; Last modified September 23, 1978 3:58 PM #AltoConsts23.mu; ; Reset locations of the tasks to be started in the Ram (Emulator, MRT, ; CommProc, Interval Timer, and one extra Ethernet). ; Extra Ethernet is assumed to be run by task 2. !17, 20, Emulator, IntTimerTask, EREST, , , , CommProcTask, , 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 **** #CPMRT.mu; ; **** CommProc microcode **** #CommProc1.mu; #CommProc2.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 SetLineTab ; 64000 PupChecksum ; 65400 ChangeControlReg !37,40, TrapDispatch, , , , , , SilentBoot, SetLineTab, PupChecksum, , , ChangeControlReg; ; 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 ; SetLineTab subroutine: ; CallRam(#63400, lineTab) ; Specifies the address of the Line Table (LINTAB). SetLineTab: L_ AC0, TASK; LINTAB_ AC0 LINTAB_ L, :Emulator; ; ChangeControlReg subroutine: ; CallRam(#65400, lineTimes4, changeMask) ; Changes (sets or resets) bits in the control word for a line. ; The change is atomic with respect to CommProc task execution. ; lineTimes4: 4 times the line number to be affected. ; changeMask: Bits 4:15 are a mask of bits to be affected and bit 0 is ; the desired new value of those bits. ChangeControlReg: L_ AC0; lineTimes4 LINE*4_ L; T_ AC1; T_ changeMask L_ LCRetX#, :LIMCon0; L_ LIMCon0 return index LCRetX: :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