{File name: StartCedar0.mc Description: Cedar Emulator initialization, Last Edited: Sturgis: 16-Sep-83 10:47:37: add a patch to zero uStickyReg for Floating point, a Kludge added because rollBack dosn't do it. Once rollback zeros the register, all is well and this patch can be removed. Fiala 11-Jun-86 15:40:48: Prepare for Initial changes by inserting init for u200 and uSDAddr; remove def'n for uStickyRegx. Fiala 23-Jul-86 15:36:19 Insert changes for alternate configurations from 12.0 product microcode; do not assume that uIOPage contains bank number in rh; SAx000 code gets new init of PCtl. Fiala 25-Jul-86 9:47:58 Removed uStickyReg and uSDAddr init to InitDLion.mc. Fiala 30-Jul-86 10:29:20 Cosmetic. Fiala 9-Sep-86 15:13:40 Move Display IOPage defn's to Dandelion.dfn. Fiala 18-Nov-86 14:01:33 Add assembly config switch for Dicentra. Fiala 30-Jan-87 17:35:57 Removed useless rhTT ←; cosmetic edits to make keys up init like Pilot 12.2. Fiala 6-Mar-87 10:54:48 Move this module from Bank 1 to Bank 0 for new booting procedure. Move Kernel & multi-bank reserves here from CedarB0.mc. Changed multi-bank reserve to be [1, 7F] and [800, 801] instead of [1, 0FF]. Changed exit to do bank cross to B1EFCHaveLink. Put code to show 799 in MP in as a comment. Trow 20-Oct-87 22:09:46 Remove initialization of DCtl, PCtl, KCtl, IOPCtl. Fix bank cross. Trow 22-Oct-87 23:13:05 Add Cedar Emulator register (constants) initialization. Trow 27-Oct-87 19:09:32 Convert to StartCedar.mc. Trow 28-Oct-87 1:06:47 Split into StartCedar0.mc and StartCedar1.mc. Trow 30-Oct-87 23:10:08 Change starting point. Trow 31-Oct-87 1:39:03 Remove Reserve clauses in favor of Extensions.dfn. Trow 2-Nov-87 17:19:03 Combine SwapGerm.mc into StartCedar0.mc. Trow 3-Nov-87 16:16:13 Add StartHere. bj 4-Nov-87 2:11:57 Change to use boot slot 23. Trow 9-Nov-87 20:27:24 Initialize uPSB. bj 8-Mar-88 1:34:14 read the length of the Germ out of its own image. bj 8-Mar-88 22:22:22 Add Disk booting via setBootRequestDisk. } {db ***** Reserve[0F6F]; Reserve[0F78]; Reserve[0F7F,0FFF]; {Kernel/Bermuda} Reserve[1, 7F]; {ExtraBanksKernel & IOPBoot} Reserve[800, 801]; {Don't know why this is reserved} ***** db} {** this stuff is specific to PrincOps version! **} Set[mapRealAddrHigh, 4]; Set[mapRealAddrLow, 0]; Set[germPageHigh, 0]; Set[germPageLow, 0]; Set[cedarGermPageHigh, 3E]; Set[cedarGermPageLow, 2]; Set[globalFrameTableHigh, 2]; Set[globalFrameTableLow, 0]; Set[germPageCount, 40]; {value to use if we find silly GermCount(=0)} Set[topPageHighByte, 1B]; {should get last real page # [1B80] from Opie} Set[topPageLowByte, 80]; MacroDef[RtnBLT, at[#1,10,subrRet]]; Set[L0.gftExch, 0]; Set[L0.germExch, 1]; Set[L0.vswap, 2]; Set[germRequest, 0F0]; {360'b offset from germ start} Set[cedar.Request.Action, Add[germRequest, 0]]; Set[cedar.Request.deviceType, Add[germRequest, 1]]; Set[cedar.Request.devOrd, Add[germRequest, 2]]; Set[cedar.Request.BootFileNumber, Add[germRequest, 3]]; Set[cedar.Request.NetworkNumber, Add[germRequest, 4]]; Set[cedar.Request.HostNumber, Add[germRequest, 5]]; Set[cedarGermSAx000, 3]; Set[cedarGermEthernet, 5]; Set[cedarGermAnyPilotDisk, 100'b]; Set[inLoad, 0]; Set[bootPhysicalVolume, 2]; Set[diskDeviceOrdinal, 0]; Set[ethernetDeviceOrdinal, 0]; {InitDaybreak is now an initialization routine which ends by looping at addrLinkage. The emulator resumes at this address in any cycle; the following code synchronizes the cycle and transfers control to boot Cedar. Note that InitDaybreak has set up parameters and loaded the germ for booting Mesa/Pilot.} Linkage: [] ← L {=0} + PC16, NZeroBr, BRANCH[Linkage, LinkageEntry], c*, at[addrLinkage]; LinkageEntry: Xbus ← 0, XC2npcDisp, BRANCH[LinkageEntry, ReadGermLength, 5], c*; StartHere: [] ← 1, ZeroBr, GOTO[Linkage], c1; {++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Well, We've got a problem here. PrincOps 3.0 expects the germ at .mv 3E0200 and PrincOps 4.0 expects the germ at .mv 100. We can move the germ in virtual space by moving map entries; we don't have to move anything in physical address space. transferCount contains the number of virtual pages we have to move from .map 1 to .map 3E02 CoreInitial sets up map and leaves next available virtual page in topPage. Since everybody's been nice enough so far to move things around and play the game according the the PrincOps 4.0 rules (like Bermuda), how about if we just swap the approprite map entries and leave everything as it already is? Well, that leaves a funny hole in VM at .mv 100, So... So we do an even cuter swap put the germ where it belongs: .mv 3E0200 <==> .mv 100 move some real pages back under .vm 100 to be *nice* .map topPage-transferCount <==> .map 1 On top of that, MDS relief required moving one other page in the germ that we have to fix up to get the global frame table back in the right place. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ } { Read the size of the Germ Image from the SD (last word of the first page) } ReadGermLength: rErh ← globalFrameTableHigh, CANCELBR[$, 0F], c1; rE ← globalFrameTableLow, c2; rE ← rE LRot8, c3; Map ← [rErh, rE], c1; Q ← 0FF, c2; rErh ← rE ← MD, c3; MAR ← [rErh, Q + 0], c1; Noop, c2; rB ← MD, c3; Noop, c1; rB ← rB, ZeroBr, c2; BRANCH[setSwapConstants, guessSize], c3; guessSize: rB ← germPageCount, c1; Noop, c2; Noop, c3; setSwapConstants: {rB ← germPageCount,} CANCELBR[$, 0F], c1; transferCount ← rB, c2; rE ← topPageHighByte, c3; rE ← rE LRot8, c1; rE ← rE or topPageLowByte, c2; topPage ← rE, c3; { Bermuda can break here to modify topPage or transferCount. } constantsOK: rC ← transferCount, {number of pages in germ} c1; rErh ← mapRealAddrHigh, c2; rBrh ← mapRealAddrHigh, c3; { Swap the gft (at .map 200) back where it belongs (.map 0) } swapGft: rB ← germPageHigh, c1; rB ← rB LRot8, c2; rB ← rB or germPageLow, {vp of 4.0 germ} c3; rE ← globalFrameTableHigh, c1; rE ← rE LRot8, c2; rE ← rE or globalFrameTableLow, c3; Noop, c1; L0 ← L0.gftExch, c2; CALL[memSwap], c3; rE ← cedarGermPageHigh, c1, RtnBLT[L0.gftExch]; rE ← rE LRot8, c2; rE ← rE or cedarGermPageLow, {vp of 3.0 germ} c3; { Swap map entries at .map 0 (Pilot germ location) with those vacant entries at .map 3E02 (Cedar germ location). } looper: Noop, c1; L0 ← L0.germExch, c2; CALL[memSwap], c3; rB ← rB + 1, c1, RtnBLT[L0.germExch]; rC ← rC - 1, ZeroBr, c2; rE ← rE + 1, BRANCH[looper, swipe], c3; { Now swap the map entries for the last physical memory pages *present* in vm with those at .map 0 to fill in the hole in vm. } swipe: rB ← germPageHigh, c1; rB ← rB LRot8, c2; rB ← rB or germPageLow, {vp of 4.0 germ} c3; rC ← transferCount, {number of pages in germ} c1; rE ← topPage, c2; rE ← rE - rC, {vp of real memory block} c3; looper2: Noop, c1; L0 ← L0.vswap, c2; CALL[memSwap], c3; rB ← rB + 1, c1, RtnBLT[L0.vswap]; rC ← rC - 1, ZeroBr, c2; rE ← rE + 1, BRANCH[looper2, setBootRequestDisk], c3; setBootRequestEther: rBrh ← cedarGermPageHigh, c1; rB ← cedarGermPageLow, c2; rB ← rB LRot8, c3; Map ← [rBrh, rB], c1; Q ← cedar.Request.deviceType, c2; rErh ← rE ← MD, c3; MAR ← [rErh, Q + 0], c1; MDR ← 5, {anyEthernet} c2; Q ← cedar.Request.BootFileNumber, c3; acR ← 0A, c1; acR ← acR LRot8, c2; acR ← acR or 83, c3; MAR ← [rErh, Q + 0], c1; MDR ← acR {A83}, {BasicCedarDLion23.pb} c2; GOTO[Germ], c3; setBootRequestDisk: rBrh ← cedarGermPageHigh, c1; rB ← cedarGermPageLow, c2; rB ← rB LRot8, c3; Map ← [rBrh, rB], c1; {Noop}, c2; rErh ← rE ← MD, c3; MAR ← [rErh, cedar.Request.Action+0] ,c1; MDR ← bootPhysicalVolume ,c2; {Noop} ,c3; MAR ← [rErh, cedar.Request.deviceType+0] ,c1; MDR ← cedarGermAnyPilotDisk ,c2; {Noop} ,c3; MAR ← [rErh, cedar.Request.devOrd+0] ,c1; MDR ← diskDeviceOrdinal ,c2; GOTO[Germ], c3; { Swaps two locations in memory, takes addresses in $rE and $rB, clobbers acR and rD. } memSwap: MAR ← [rErh, rE+0], c1; Noop, c2; acR ← MD, c3; MAR ← [rBrh, rB+0], c1; Noop, c2; rD ← MD, c3; MAR ← [rErh, rE+0], c1; MDR ← rD, c2; Noop, c3; MAR ← [rBrh, rB+0], c1; MDR ← acR, pRet0, c2; RET[subrRet], c3; Germ: TOS ← 3E, rhMDS ← 3E, CANCELBR[SetMDS,0F], c1, at[0, 2, Germ]; Go: TOS ← 2, rhMDS ← 2, CANCELBR[SetMDS,0F], c1, at[1, 2, Germ]; SetMDS: UvMDS ← TOS, c2; Noop, c3; uXTS ← stackP ← 0, c1; UvG ← 0, c2; UBrkByte ← 0, c3; T ← 2, c1; T {200} ← T LRot8, c2; u200 {200} ← T, {uAVAddr = u200} c3; T {240} ← T + 40, c1; uSDAddr {240} ← T, c2; Noop, c3; T {1FF} ← LShift1 0FF, SE ← 1, c1; T {3FF} ← LShift1 T, SE ← 1, c2; T {7FF} ← T LShift1, SE ← 1, c3; u7FF {7FF} ← T, T {FFF} ← T LShift1, SE ← 1, c1; T {1FFF} ← T LShift1, SE ← 1, c2; u1FFF {1FFF} ← T, T {3FFF} ← T LShift1, SE ← 1, c3; u3FFF {3FFF} ← T, c1; T {8000} ← RShift1 0, SE ← 1, c2; u8000 {8000} ← T, c3; T ← 0F, c1; T {0F00} ← T LRot8, c2; T {0FFC} ← T or 0FC, c3; uPMask {0FFC} ← T, c1; uPMask2 {0FFC} ← T, c2; Noop, c3; T ← 7, c1; T {7000} ← T LRot12, c2; uPPMask {7000} ← T, c3; uPCCross ← 0, c1; uPCValid ← 0, c2; PC ← 1, c3; uWDC ← PC, ClrIntErr, c1; uWP ← 0, c2; uStickyReg ← 0, c3; { initialize uPSB so we can debug before we start ProcessImpl } T ← 10, c1; uPSB ← T, c2; Noop, c3; Bank ← MSBank1, c1; GOTOABS[BxMP799], c2; GOTOABS[B1MP799], c3, at[BxMP799];