*----------------------------------------------------------- Title[InitMem.mc...June 27, 1985 12:36 PM...Rumph]; * Memory system initialization for all emulators. *----------------------------------------------------------- % Entry points: InitMap Cold start: map and main storage initialization (name is an historical artifact). InitMapWarm Warm start: map initialization only; doesn't disturb main storage (Alto mode only). After initialization, InitMap branches to the external label StartEmulator, and InitMapWarm branches to ResumeEmulator. InitMap code assumes that CacheA, CacheD, and the map automata have already been put into a good state (by bootstrap initialization), but assumes nothing about the contents of the map or main storage. It zeroes all real storage in order to clear out any lurking bad parity. It maps virtual addresses to real storage such that all real storage is compacted in VM (usually at the bottom), and marks all other VM vacant. As a side-effect, it computes VirtualBanks and RealPages, for the benefit of emulators. If no real storage is present, it breaks at NoStorage. InitMapWarm assumes that map and main storage are already in a reasonable state for running the Alto emulator, and in particular that the first 64K of REAL memory contains simulated Alto memory. It sets up the map as appropriate for the new emulator (note that different emulators keep the simulated Alto memory in different parts of VIRTUAL memory), so that execution within the simulated Alto memory can continue. For Alto mode only, this code depends on there being an external, emulator-specific subroutine GetEmulatorMapParams, which returns the following in T: T[0] = 1 to write-protect page 377, for XM Alto emulation; 0 to emulate a non-XM Alto. T[4:15] = the VA[4:15] to be used to define the main "bank" (64K memory region) for Alto emulation. Should be 0 in all emulators except Lisp. This version of the code assumes 256-word pages, but can cope with any map and main storage configuration. % Set[logWordsPerPage, 10]; TopLevel; Set[XTask, IP[EMU]]; * Register usage -- bank shared with Ethernet output registers SetRMRegion[EORegs]; * Reserve[xx]; * Registers defined in RegisterDefs.mc * RVN[VirtualBanks]; * RVN[RealPages]; Reserve[Add[And[IP[RealPages], 17], 1]]; RVN[PgsPerMod]; * Pages per storage module RVN[ModMask]; * Mask of modules present RVN[ITemp0]; * Temporaries RVN[ITemp1]; RVN[ITemp2]; Reserve[1]; * Ensure there is at least one register left RVRel[ITemp17, 17]; :If[AltoMode]; ********** Alto version ********** *----------------------------------------------------------- * Warm start initialization. *----------------------------------------------------------- InitMapWarm: RBase_ RBase[ITemp0], Call[GetMemConfig]; RealPages_ (RealPages)+1, * Set flag to note this is a warm start Branch[CacheFlush]; :EndIf; ********************************** *----------------------------------------------------------- * Cold start initialization. * Initially started here by "Initial" (second-stage bootstrap). * Restarted here by Baseboard on 2-button boot. *----------------------------------------------------------- InitMap: At[InitMapLoc], Call[TasksOff]; * Do an I/O Reset RBase_ RBase[ITemp0]; B_ FaultInfo'; * clear faults T_ mcr.noWake; * disable fault task wakeups LoadMCR[T, T]; Call[WaitForMapBuf]; * Set TestSyndrome register to normal state (error correction on) MemBase_ IOBR, T_ A0; BrHi_ T; BrLo_ T; Fetch_ T; * need to be sure store will hit T_ MD, Store_ T, DBuf_ tsyn.ecOn; * DBuf_ data LoadTestSyndrome; * TestSyn_ DBuf Call[WaitForMapBuf]; TaskingOn; *----------------------------------------------------------- * Map pre-initialization for cold start. * Set the map one-to-one with real storage (without regard to the * real storage configuration), in preparation for flushing the cache. *----------------------------------------------------------- Call[GetMemConfig]; ITemp1_ T_ A0, Call[BeginEnumerateMap]; Map1to1Loop: ITemp0_ A0, Call[IWriteMap]; * Dirty=0, WP=0, RP = VPage mod 2^16 SCall[NextMapEntry]; ITemp1_ (ITemp1)+1, Branch[Map1to1Loop]; *----------------------------------------------------------- * Cache flush and map clear. * During a warm start, the data in the cache is flushed to wherever it * belongs. During a cold start, it is flushed to memory arbitrarily. * This may result in flushing into nonexistent storage, but no matter. *----------------------------------------------------------- CacheFlush: ITemp1_ T_ A0, Call[BeginEnumerateMap]; CacheFlushLoop: * Flush all munches in this page ITemp0_ A0, Cnt_ 17S; ITemp0_ Flush_ ITemp0, Carry20, Branch[., Cnt#0&-1]; * Set the map entry to vacant Nop; ITemp0_ T-T-1, Call[IWriteMap]; * Dirty = 1, WP = 1, RP = 0 SCall[NextMapEntry]; Branch[CacheFlushLoop]; *----------------------------------------------------------- * Map and storage initialization. * Map virtual addresses into real storage, starting with the virtual address * defined by the BRHi value for MDS (emulator specific), and wrapping around * the end of the virtual address space if necessary (Lisp requires this). * Zero storage if cold start is in progress. * Note: this code assumes that the virtual address space is at least as large as * the real address space. *----------------------------------------------------------- :If[AltoMode]; ********** Alto version ********** ITemp1_ A0, * Init real page # Call[GetEmulatorMapParams]; * Get emulator-specific information :Else; ******** PrincOps version ******** ITemp1_ T_ A0; * Init real page #, virtual bank # :EndIf; ********************************** ITemp2_ A0, Branch[BeginMapInit]; * No pages left in current module * Register usage at top of loop: * ITemp1 = real page number * ITemp2 = -(remaining pages in current module)-1 MapInitLoop: ITemp1_ (ITemp1)+1, * Increment real page number SCall[NextMapEntry]; * Increment virtual page number ITemp2_ (ITemp2)+1, * +1 return; decrement (negative) page count DblBranch[MapModuleCont, FindModule, R<0]; * Get here initially with T = bank for emulated Alto memory. * If we go past the end of VM, we get here due to NextMapEntry returning to * caller+2; T = 0 in this case, so we will wrap around to the beginning of VM. BeginMapInit: T_ T AND (7777C), Call[BeginEnumerateMap]; ITemp2_ (ITemp2)+1, DblBranch[MapModuleCont, FindModule, R<0]; * Current module exhausted, find the next one. FindModule: ModMask_ (ModMask) LSH 1, Branch[MapModule, R<0]; T_ PgsPerMod, Branch[EndOfStorage, ALU=0]; ITemp1_ (ITemp1)+T, Branch[FindModule]; * Skip nonexistent real pages MapModule: T_ (1S)-(PgsPerMod); * Init page count in module ITemp2_ T; * Continue mapping virtual pages into the current module. MapModuleCont: ITemp0_ A0, Call[IWriteMap]; * Write map entry; WP and Dirty = 0 T_ 377C, RealPages, Branch[MapInitLoop, R odd]; * Branch if warm start T_ ITemp0_ A0, Cnt_ T; * Zero out the page ITemp0_ (Store_ ITemp0)+1, DBuf_ T, Branch[., Cnt#0&-1]; Branch[MapInitLoop]; *----------------------------------------------------------- * Finish setting up the high part of MDS. * Then, if XM Alto emulation is desired, write-protect page 377 of * the 64K space for Alto emulation (MDS). *----------------------------------------------------------- EndOfStorage: ; :If[AltoMode]; ********** Alto version ********** Call[GetEmulatorMapParams]; ITemp0_ T; T_ T AND (7777C); EmuXMBRHiReg_ T; * For XM, start with alternate=normal EmuBRHiReg_ T; BRHi_ T, ITemp0, Branch[InitMemDone, R>=0]; * Test XM flag * Make page 377B be write-protected. * First, flush the page, then set WP in map entry. T_ 177400C; ITemp0_ A0, BRLo_ T; Cnt_ 17S; ITemp0_ (Flush_ ITemp0), Carry20, Branch[., Cnt#0&-1]; ITemp0_ TIOAwProtect, Call[IWriteMapFlags]; :EndIf; ********************************** *----------------------------------------------------------- * Now enable fault reporting and go run the emulator! * For now, do not enable fault reporting of Single Errors. *----------------------------------------------------------- InitMemDone: B_ FaultInfo'; * Clear faults T_ mcr.noReportSE; * Normal MCR value LoadMCR[T, T]; Call[WaitForMapBuf]; :If[AltoMode]; ********** Alto version ********** RealPages_ (RealPages) AND (177776C), Branch[.+2, R even]; Branch[ResumeEmulator]; :EndIf; ********************************** Branch[StartEmulator]; *----------------------------------------------------------- GetMemConfig: * Read the map and storage configuration, and set these registers: * VirtualBanks = size of virtual memory, in units of 64K words * RealPages = size of real memory, in pages * PgsPerMod = number of pages per module * ModMask = bit mask of modules present (B0=1 => module 0 present, etc.) * Breakpoints at NoStorage if no storage modules are present. * Clobbers T, ITemp0, ITemp1, ITemp17 *----------------------------------------------------------- Subroutine; ITemp0_ Link; TopLevel; T_ 1400C; T_ ITemp1_ T OR (112C); Call[SetDMuxAddress]; * Read DMux[1512] = MapIs256K ITemp17, Branch[MapIs256K, R<0]; VirtualBanks_ 400C; T_ (ITemp1)-1, Call[SetDMuxAddress]; * Read DMux[1511] = MapIs64K ITemp17, Branch[GotMapConfig, R<0]; VirtualBanks_ 100C, Branch[GotMapConfig]; * Assume MapIs16K MapIs256K: VirtualBanks_ 2000C; GotMapConfig: ModMask_ NOT (Config'); T_ LDF[ModMask, 2, 2]; * Storage chip size = 2^(12 + 2*T) T_ DPF[T, 2, 11]; * ShC count _ 2*T RealPages_ A0, ShC_ T; ModMask_ LSH[ModMask, 10]; * Left-justify the module-present bits ModMask_ T_ (ModMask) AND (170000C); ITemp1_ T, Branch[NoStorage, ALU=0]; PgsPerMod_ 400C; * 4K chips give 400B pages/module PgsPerMod_ T_ ShiftNoMask[PgsPerMod]; * LCY[R, R, 2*n] ITemp1_ (ITemp1)+(ITemp1), Branch[.+2, R>=0]; * Count the modules RealPages_ (RealPages)+T, FreezeBC; Link_ ITemp0, Branch[.-2, ALU#0]; Subroutine; PD_ ModMask, Return; *----------------------------------------------------------- * No storage modules are present. *----------------------------------------------------------- NoStorage: Branch[.], Breakpoint; *----------------------------------------------------------- * EnumerateMap: Perform operation on every entry in the map * Calling sequence: * * T_ , Call[BeginEnumerateMap]; * Loop: ; * SCall[NextMapEntry]; * Branch[Loop]; * ; * * Enter: MemBase = BR to use for enumeration * VirtualBanks set up * Exit: BR addresses word 0 of page corresponding to map entry * T = 0 * Clobbers T, ITemp17 *----------------------------------------------------------- Subroutine; BeginEnumerateMap: ITemp17_ A0, Branch[NextMap1]; NextMapEntry: T_ LShift[1, logWordsPerPage]C; * Let the memory system do the add! DummyRef_ T, T_ MD; ITemp17_ VALo; T_ VAHi; NextMap1: BRLo_ ITemp17; PD_ (BRHi_ T)-(VirtualBanks); T_ A0, Return[ALU=0]; *----------------------------------------------------------- IWriteMapFlags: * Write map flags without disturbing real page * Enter: ITemp0 = WP and Dirty bits * Current BR contains VA for map entry to be written * Clobbers ITemp1, Q. *----------------------------------------------------------- Subroutine; ITemp1_ A0, Q_ Link; TopLevel; RMap_ ITemp1, Call[WaitForMapBuf]; * Read current map entry ITemp1_ NOT (Map'), Branch[IWriteMap1]; *----------------------------------------------------------- IWriteMap: * Write map entry * Enter: ITemp0 = WP and Dirty bits * ITemp1 = real page number * Current BR contains VA for map entry to be written * Clobbers Q. *----------------------------------------------------------- Subroutine; Q_ Link; TopLevel; IWriteMap1: TIOA_ ITemp0, Call[WaitForMapBuf]; Map_ 0S, MapBuf_ ITemp1; Link_ Q, Branch[WaitForMapBuf]; *----------------------------------------------------------- WaitForMapBuf: * Wait for map operation to complete * Clobbers nothing *----------------------------------------------------------- Subroutine; PD_ T-T-1; PD_ PRef, Branch[., ALU<0]; * MapBufBusy is sign bit Return; e6(1552)