{File name: Lisp11SAx000Initial.mc Lichtenberg 2-Aug-84 1:28:03 fixed obscure leader pages bug. Lichtenberg 13-Jul-84 18:15:31 uIOPage finally right this time. Purcell 13-Jul-84 18:02:02 uIOPage was incorrectly set for lisp Purcell 2-Jul-84 14:15:55 zero oldIOPage Purcell 2-Jul-84 4:44:35 set uIOPage like mesa 10 before lisp {??} Purcell 1-Jul-84 23:37:15 use newIOPage and buffer it in oldIOPage Purcell 1-Jul-84 22:25:58 Added support for Quantum Q2080 Purcell 1-Jul-84 22:25:58 Accomodate changes for Germ as a result of going over to 32-bit procedure descriptors Purcell 1-Jul-84 22:25:58 Use IOPage offsets from Dandelion.df! Purcell 14-May-84 22:03:08 Mesa 11.0 Upgrade 2080 & germ Purcell 23-Feb-84 23:23:07 detect multibanks Purcell 15-Feb-84 2:29:05 load 4mb; scrap to page 0FF Purcell February 14, 1984 8:03 PM skip "zero banks" in FPTOVP Purcell February 6, 1984 12:40 PM Lisp MCtl _ 8002h Purcell January 19, 1984 7:53 PM; MIN[topPage, AC0] removed Purcell January 18, 1984 4:14 PM; mesa: MCtl 0, MIN[topPage, AC0] Purcell January 17, 1984 11:21 AM; added NewInit section Purcell January 17, 1984; renamed from nLispSAx000Initial.mc Purcell January 16, 1984 6:34 PM; correct test of vp>2^14 Purcell December 30, 1983 3:53 PM; max real mem 3-8MB Purcell December 27, 1983 3:06 PM; max real mem 2.0MB Purcell November 26, 1983 2:25 PM; {*0} max real mem 1.5MB Purcell April 16, 1983 5:32 PM; uses password 15e3 at 17 Purcell April 16, 1983 4:22 PM; try 800h pages $$ Purcell April 16, 1983 1:16 PM; don't bother refresh Purcell April 13, 1983 10:47 AM; uLispBootMsg{0DE}=55 to boot mesa Purcell April 6, 1983 8:44 AM; skip over interface page Purcell April 1, 1983 4:53 PM; new sysout booting Purcell March 21, 1983 10:27 PM; Quantum support Purcell March 6, 1983 2:56 PM; define uLinkPtr Purcell March 6, 1983 9:45 AM; store boot disk address in IOCBs.cpr Purcell December 6, 1982 6:39 PM: map for 4MB boot file Purcell November 28, 1982 1:18 PM: LispSAx000Initial: save boot link for Lisp Purcell November 22, 1982 9:03 AM: link _ 0D for BLT Purcell November 19, 1982 4:54 PM: boot Lisp instead of diagnostics File name: [Idun]SAx000Initial.mc Description: first microcode read from the disk, gets emulator microcode into CP memory, Author: Jarvis, Created: August 25, 1980, JGS November 18, 1981 8:58 AM: move germ to mds 0. Last Edited by Neely January 14, 1982 2:40 PM - change cons. for extracting filePageHi from BootId from 7 to 7F. Last Edited by Jim Frandeen October 22, 1981 1:12 PM: If diagnostics are not installed, boot Emulator instead of crashing. Last Edited by Fasnacht June 18, 1981 10:30 AM: delete SetGerm1000 at Last Edited by DDavies February 14, 1981 4:35 PM Last Edited by Jarvis March 24, 1981 11:46 AM}jk20(0,4939)(1,5644)(2,6350)(3,7056)(4,14817) {disk definitions} {RegDef[uLispBootMsg, U, 0DE];} {also in Dandelisp.df} RegDef[uLinkPtr, U, 27{uTT}]; {uLinkPtr} RegDef[uFirstPage,U,49]; Set[hardMicrocodeFirstPage,13'd]; {null findSectorCmd for SA1000} Set[SA1000FindSectCmd, 20]; {have SA1000 reject Label and Data fields when looking for Headers} Set[SA1000HeaderLoopMsk, 43]; {control bits, low byte} {Set[stepBit, 80], Set[inBit, 40], Set[firmwareEnable, 20];} Set[SA4FindSect, 6], Set[SA1FindSect, 0]; {control bits, high byte} {Set[driveSelectBit, 4], Set[faultClearBit, 2];} {IOCB status error indicators} Set[badBits, 3F]; Set[verifyBit, 1]; {IO page offsets} {Set[diskCSB, 1];}{%} {IOCB page offsets} Set[statusAddr, 3]; {status word} {not used, used to be pointer to next IOCB, always 0} Set[seekAddr, 5]; {pointer to seek IOCB} Set[transferAddr, 6]; {pointer to transfer IOCB} Set[vrrAddr, 7]; {pointer to vrr parameter area} Set[vvrAddr, 8]; {pointer to vrr parameter area} Set[headerAddr, 9]; {header -- 2 words} Set[labelAddr, 0B]; {label -- 0A words} Set[labelPageLow, 10]; {low 16 bits of file page number} Set[miscBitsAddr, 11]; {filePageHi[0..6], unused[0..5], immutable[0], temporary[0], zeroSize[0]} Set[bootLink, 13]; {disk address of next run of pages in boot file} Set[labelSize, 0A]; {parameter area offsets} Set[sectors, 0]; {number of sectors to transfer} Set[headerLoopMsk, 6]; {specifies non-fatal errors when looking for a header} Set[dataPage, 0D]; {page number of data area in main storage} Set[haltWord, 0F]; {requires head in high 5 bits} Set[findWord, 10]; {requires head in high 5 bits} {transfer IOCB offsets} Set[parameters, 1]; {pointer to parameter area} {seek IOCB offsets} Set[cylinders, 0]; {-(number of cylinders to move heads)} Set[stepHigh, 6]; {set step level high} Set[stepLow, 8]; {set step level low} {Miscellaneous disk constants} Set[SA1000HeadCount, Sub[4,1]]; Set[SA4000HeadCount, Sub[4,1]]; Set[Q2040HeadCount, Sub[8,1]]; Set[Q2080HeadCount, Sub[7,1]]; {physical volume boot files} {useful data formats extracted from Boot.mesa BootFileType: TYPE= {hardMicrocode, softMicrocode, germ, pilot, debugger, debugee}; DiskFileID: TYPE= RECORD[fID: File.ID, firstPage: File.PageNumber, da: DiskAddress]; PVBootFiles: POINTER TO ARRAY BootFileType[hardMicrocode..pilot] OF DiskFileID= 2; After reading from the disk, PVBootFiles moved to memory location 2} Set[bootingInfo, 8]; {origin of PVBootFiles in physical volume root page} Set[DiskFileIDSize, 9]; {number of words in DiskFileID} Set[bootingInfoSize, Mul[DiskFileIDSize, 4]]; {size of PVBootFiles} {things salted away in page 0} Set[availableDevices, 0]; {devices available for booting, set up by Phase 0} Set[bootReadyFlag, 1]; {non-zero indicates boot file is ready} Set[hardFileID, 2]; {hard microcode DiskFileID, copied from physical volume root page} Set[emulatorFileID, 0B]; {emulator microcode DiskFileID, copied from physical volume root page} Set[germFileID, 14]; {germ DiskFileID, copied from physical volume root page} Set[bootFileID, 1D]; {working DiskFileID, copied from one of the above fileID's} Set[bootPage, 22]; Set[bootDiskAddr, 24]; Set[labelTemplate, 26]; {template label used by boot loading routines} {germ definitions Mesa 11} { Set[germMapOffset, 2]; Set[germPageHigh, 0]; {virtual page number of origin of germ -- 1B} Set[germPageLow, 1]; Set[sFirstGermRequestHigh, 001'b]; {start of germ request in SD - high byte} Set[sFirstGermRequestLow, 240'b]; {start of germ request in SD - low byte} } Set[sLastGermRequest, Add[sFirstGermRequestLow, 57'b]]; {end of germ request in SD} Set[RequestSize, 60'b]; {size of germ request in SD} Set[SD.Request.version, Add[sFirstGermRequestLow, 00'b]]; Set[RequestVersionHigh, 7]; Set[RequestVersionLow, 56'b]; Set[SD.Request.action, Add[sFirstGermRequestLow, 01'b]]; Set[bootPhysicalVolume, 2]; Set[SD.Request.location, Add[sFirstGermRequestLow, 02'b]]; Set[SD.Request.location.deviceType, Add[sFirstGermRequestLow, 02'b]]; Set[germPilotDisk, 64'd]; Set[SD.Request.location.deviceOrdinal, Add[sFirstGermRequestLow, 03'b]]; {germ definitions mesa10} { {Set[germPageHigh, 0]; {virtual page number of origin of germ -- 1B} Set[germPageLow, 1];} Set[sFirstGermRequest, 320'b]; {start of germ request in SD} Set[sLastGermRequest, 377'b]; {end of germ request in SD} Set[RequestSize, 60'b]; {size of germ request in SD} Set[SD.Request.version, 320'b]; { Set[RequestVersionHigh, 7]; Set[RequestVersionLow, 56'b]; }Set[SD.Request.action, 321'b]; Set[bootPhysicalVolume, 2]; Set[SD.Request.location, 322'b]; Set[SD.Request.location.deviceType, 322'b]; Set[germPilotDisk, 64'd]; Set[SD.Request.location.deviceOrdinal, 323'b]; } DoneOnceOnlyInit: {For the four disk drives, the following applies: Q2040 - ~HeadSlelect16 = ~Sector. The two pins are connected physically. Q2040 - ~Sector = TRUE. Using positive logic. SA4000- ~SA1000/SA4000 = TRUE. Positive logic. SA1000- ~SA1000/SA4000 = FALSE & ~Sector = FALSE. Also positive logic.} {First modify the IOCB for an SA1000 if necessary} Xbus _ KStatus, XwdDisp, c1; {what type of disk is this?} acR _ 0FF+1, DISP2[SetSA1IOCB, 2], c2; {Point to table of IOCBs} {there is an SA1000 drive connected. Set the LabelDataTag bit in the HeaderLoopMsk and turn off the "Wait for Sector mark" command in the FindWord} SetSA1IOCB: {Test for SA1000 or Quantum depending on bit 9 of KTest after writing to bit H16 of KCtl: KTest[9]=0 => SA1000 KTest[9]=1 => Quantum Q2040. For the Quantum Q2080 KCtl[0]=~KTest[9]} {MESA 10: Xbus _ KTest, XwdDisp, c3, at[2,4,SetSA1IOCB]; DISP2[IsSA1000orQuantum,1], c1; IsSA1000orQuantum: rB _ 7 {sa1000}, GOTO[FinishIsSA1000orQuantum], c2, at[3,4,IsSA1000orQuantum]; rB _ 3 {quantum}, GOTO[FinishIsSA1000orQuantum], c2, at[1,4,IsSA1000orQuantum]; FinishIsSA1000orQuantum: uQuantumSA1000MaxHeadNum _ rB, c3; Noop, c1; Noop, c2; acRrh _ 0, c3; }{MESA 11: } rB _ 80, c3, at[2,4,SetSA1IOCB]; KCtl _ rB LRot8, c1; {Test for an SA1000 or Quantum} Xbus _ KTest, XwdDisp, c2; DISP2[IsSA1000orQuantum,1], c3; { Xbus _ KTest, XwdDisp, c3, at[2,4,SetSA1IOCB]; DISP2[IsSA1000orQuantum,1], c1; } IsSA1000orQuantum: rB _ SA1000HeadCount {sa1000}, GOTO[FinishIsSA1000orQuantum], c1, at[1,4,IsSA1000orQuantum]; KCtl _ 0, c1, at[3,4,IsSA1000orQuantum]; {Test for a Quantum Q2040 or Q2080} Xbus _ KTest, XwdDisp, c2; DISP2[IsQ2040orQ2080,1], c3; IsQ2040orQ2080: rB _ Q2080HeadCount {Q2080}, GOTO[FinishIsSA1000orQuantum], c1, at[1,4,IsQ2040orQ2080]; rB _ Q2040HeadCount {Q2040}, GOTO[FinishIsSA1000orQuantum], c1, at[3,4,IsQ2040orQ2080]; {IsSA1000orQuantum: rB _ 7 {sa1000}, GOTO[FinishIsSA1000orQuantum], c2, at[3,4,IsSA1000orQuantum]; rB _ 3 {quantum}, GOTO[FinishIsSA1000orQuantum], c2, at[1,4,IsSA1000orQuantum];} FinishIsSA1000orQuantum: uQuantumSA1000MaxHeadNum _ rB, c2; acRrh _ 0 {Point to table of IOCBs}, c3; {JOIN} MAR _ [acRrh, vrrAddr+0], c1; {get addr of vrr parameters} rE _ SA1FindSect, c2; {prepare to set FindSectCmd} acR _ MD, c3; MAR _ [acRrh, acR+headerLoopMsk], c1; {set up new HeaderLoopMsk} MDR _ SA1000HeaderLoopMsk, LOOPHOLE[wok], CANCELBR[$,2], c2; UFindSect _ rE c3; {set FindSect mark cmd for SA1000.} MAR _ [acRrh, vvrAddr+0], c1; {get addr of vvr parameters} rE_ 0, c2; {set up source of 0 for below} acR _ MD, c3; MAR _ [acRrh, acR+headerLoopMsk], c1; {set up new HeaderLoopMsk} MDR _ SA1000HeaderLoopMsk, LOOPHOLE[wok], CANCELBR[DiskInitDone,2], c2; {Connected to an SA4000 so set the Find Sector Mark command properly} SetSA4IOCB: acR _ SA4FindSect, c3, at[3,4,SetSA1IOCB]; UFindSect _ acR, c1; rE_ 0, c2; {source of 0} DiskInitDone: germStart_ rE, c3; acRrh_ 1, c1; {set up stuff for IO page} currentCylinder_ rE, c2; acR_ badBits, c3; uBadBits_ acR, c1; acR_ driveSelectBit, c2; acR_ acR LRot8, c3; acR_ acR or firmwareEnable, c1; seekMask_ acR, {seek Mask_ drive select or firmwareEnable} c2; acR_ 4, c3; acR_ acR LRot8, c1; acR_ acR or 20, c2; haltBits_ acR, c3; {halt bits_ 420} acR_ 0F8, c1; acR_ acR LRot8, c2; headMask_ acR, c3; {headMask_ F800} acR_ 2, c1; acR_ acR LRot8, c2; uBootStart_ acR, c3; {boot file starts at 200} {*} acR_ uDiagnostic, ZeroBr, c1; {*} []_ acR{uDiagnostic} - 1, NZeroBr, BRANCH[pLispBoot, pMesaBoot], c2; pLispBoot: BRANCH[LispBoot, MesaBoot], c3; pMesaBoot: CANCELBR[MesaBoot, 1], c3; {map virtual pages 0-255 to real pages 0-255, first we must save the current mapping of the lowest virtual pages} MesaBoot2: uDiagnostic_ 0, c2; Noop, c3; MesaBoot: rB _ 0AA{Lisp}, c1; uLispBootMsg _ rB, c2; {MCtl _ 0} Noop, c3; {{topPage _ MIN[topPage, AC0]} rB_ topPage, c1; rC _ 0AC, c2; rC _ rC LRot4, c3; Ybus _ rB{topPage} - rC{AC0}, CarryBr, c1; {MCtl _ 0, }BRANCH[$, trim], c2; rC _ topPage, GOTO[mbjoin], c3; trim: topPage _ rC, GOTO[mbjoin], c3; } mbjoin: rBrh_ 1, c1; rCrh_ 1, c2; rB_ 0, c3; rC_ topPage, L0_ 4, c1; acR_ 0FF+1, CALL[BLT3], c2; {BLT3[from: 10000, to: 1topPage, cnt: 100h]} {block transfer, takes count in acR, from in rB, and to in rC, returns first word past from block in rE} acR_ present, c1, at[4, 10, subrRet]; rC_ 0FF+1, c2; rB_ 0, c3; {set up identity map for benefit of the disk microcode} identityMap: MAR_ [rBrh, rB+0], BRANCH[$, idDone], c1; MDR_ acR, rB_ rB+1, c2; acR_ acR+rC, CarryBr, GOTO[identityMap], c3; idDone: Noop, c2; Noop, GOTO[rootPage], c3; {** Lisp uses identity map for all of real memory for benefit of the disk microcode} LispBoot: rB_ 0, c1; Q _ 55{Mesa}, c2; []_ Q xor uLispBootMsg, ZeroBr, c3; acR_ 03{B}0{dirtyRef}, BRANCH[$, MesaBoot2], c1; Q{100}_ 0FF+1, c2; nextId3: rBrh_ 1, c3; {acR{dirtyRef}, rB{10000}, Q{100}, map 2^12 pages as identity} nextId: MAR_ [rBrh, rB+0], c1; MDR_ acR, acR _ acR + Q{100}, CarryBr, c2; rB_ rB+1, BRANCH[nextId, $], c3; incSeg: acR _ acR + 1, NibCarryBr{2^12 pages}, c1; rC _ topPage{virtual}, BRANCH[nextId3, Zdone], c2; Zdone: rC _ rC LRot8, c3; Ybus _ 0E - rC, PgCarryBr{if rC is low or eq}, c1; acR _ 0B0{2mb+dirty}, BRANCH[ZnextId3, doneId], c2;{%%} {acR{2mb+dirty}, rB{11000}, Q{100}, map next 2^12 pages as identity} ZnextId: MAR_ [rBrh, rB+0], c1; MDR_ acR, acR _ acR + Q{100}, CarryBr, c2; rB_ rB+1, BRANCH[ZnextId, $], c3; ZincSeg: Ybus _ acR + 1{9}, NibCarryBr{2^12{11} more pages}, c1; acR _ acR + 1, BRANCH[ZnextId3, doneId], c2; ZnextId3: Noop, GOTO[ZnextId], c3; doneId: acR{dirty;page FF}_ ~0DF, c3; rCrh_1{FirstRealPageToMapHigh}, c1; rC_ 040{FirstRealPageToMap}, c2; rC{14000} _ rC LRot8, c3; {acR{FF20}, rB{12000}, rCrh,rC{14000}, remaining vp's mapped to FF} Scrap: MAR_ [rBrh, rB+0], BRANCH[$, doneScrp], c1; Scrap2: MDR_ acR{-1}, rB_ rB+1, c2; Ybus _ rB - rC{4000}, ZeroBr, GOTO[Scrap], c3; doneScrp: Noop, c2; Noop, c3; {acR{-1}, rCrh,rC{14000}, change 65 map entries to protect the map and old iopage (as known to sysout) to point to FF{-1}} Protect65: Map{14000}_ [rCrh, rC+0], c1; MDR_ acR{-1}, rC_ rC, ZeroBr, c2; rC_ rC - 0FF - 1, BRANCH[Protect65, $], c3; {Mesa11: Real Page 20000 is IOPage for Mesa11 but stack for Lisp} {Divert the reading of page 20000 from newIOPage to oldIOPage} rCrh _ 2{IOPageHigh}, c1; acR _ 40, c2; acR _ acR LRot8, c3; Map{20000} _ [rCrh{2}, 0], c1; MDR{4031} _ acR or 31, c2; Noop, c3; {Start flailing away at the disk. First read the physical volume root page} rootPage: rBrh_ 0, c1; rCrh_ 0, c2; rDrh_ 0, c3; rErh_ 1, c1; rD_ 0FF+1, c2; {base address of IOCB page} rE_ headerAddr, c3; MAR_ [rDrh, rE+0], c1; {cylinder 0} MDR_ 0, c2; rB_ 2, c3; {read starting at page 2} MAR_ [rDrh, rE+1], c1; {head 0, sector 0} MDR_ 0, CANCELBR[$, 0], L1_ 0, c2; acR_ 1, CALL[doVrr], c3; {read 1 sector} transferRet: Ybus_ acR and uBadBits, ZeroBr, c1, at[0, 10, transferRet]; transferIOCB_ rE, BRANCH[$, here1], c2; acR_ bootDeviceError, GOTOABS[Maintenance1Loc], c3; {save the useful stuff from the physical volume root page} here1: rC_ 2, c3; {copy PVBootFiles} rB_ rC LRot8, c1; rB_ rB+bootingInfo, L0_ 0, c2; acR_ bootingInfoSize, CALL[BLT], c3; rC _ 2, c1, at[0, 10, subrRet]; rC _ rC LRot8, c2; rCrh _ 0, c3; MAR _ [rCrh, hardMicrocodeFirstPage + 0], c1; , c2; rC _ MD, c3; uFirstPage _ rC, c1; , c2; , c3; {read the emulator boot file or the hard microcode} emuHard: []_ uDiagnostic, ZeroBr, c1 ; rC_ bootFileID, BRANCH[$, emuHard0], c2; rB_ hardFileID, L0_ 8, GOTO[emuHard1], c3; emuHard0: rB_ emulatorFileID, L0_ 8, c3; emuHard1: acR_ DiskFileIDSize, CALL[BLT2], c1; acR_ 2, L2_ 0, c1, at[8, 10, subrRet]; nextPage_ acR, CALL[readBoot3], c2; rC_ uDiagnostic, ZeroBr, c1, at[0, 10, readBootRet]; acR_ nextPage, BRANCH[$, readGerm], c2; Noop, c3; Noop, c1; Ybus_ rC{uDiagnostic}-1, NZeroBr, c2; Noop, BRANCH[$, doDiag], c3; {test if we have lisp or diagnostics in real memory} rC _ 15{passH}, c1; rB _ 3, c2; rBrh{0} _ rB{300} _ rB LRot8, c3; MAR_ [rBrh, rB+0F{passA}], c1; rC{passH} _ rC LRot8, CANCELBR[$, 2], c2; rC _ MD xor rC, c3; rC _ rC xor 0E3{passL}, c1; Ybus _ rC, NZeroBr, c2; Noop, BRANCH[$, notLisp], c3; { We have Lisp; Restore the map.} {set map[0..3FFFF] to vacant and interpret FPTOVP} LispInit: rB{7FFF}_ ~1 RRot1, rBrh_ 1, c1; rB{3FFF}_ rB RShift1, c2; rC _ 60{vacant}, c3; vacLp: MAR_ [rBrh{0C1}, rB+0], ZeroBr, c1; MDR_ rC{vacant}, rB_ rB-1, NibCarryBr, BRANCH[$, vDone], c2; vac3: Noop, BRANCH[$, vacLp]{match to vacRef+1}, c3; vacRef: {Refresh,} c1; Xbus _ 1, XDisp, GOTO[vac3], c2; vDone: Noop, CANCELBR[$, 1], c3; {update Interface page and interpret FPTOVP} {Map[InterfacePageVp] _ 3} acRrh _ 26'b{INTERFACEspace}, CANCELBR[$, 1], c1; acR _ 20'b{INTERFACEbase=10000'b}, c2; acR _ acR LRot8, c3; rB _ 3{real interface page}, c1; rB{300} _ rB LRot8, c2; rBrh _ rB _ rB + 03{B}0{dirty}, c3; Map{161000} _ [acRrh,acR], c1; MDR _ rB{3B0}, c2; rC _ 0C{(NRealPages{3072})/256}, c3; MAR_ [rBrh, 15'b{MachineType} + 0], c1; MDR _ 6{\DANDELION}, c2; rC{C00} _ rC LRot8, c3; Q _ topPage{virtual}, c1; Q _ Q + 40,{ map not included} c2; Q{NRealPages} _ Q + {02}{0A8}{-56 mp301}0FF{+1}{bank 0 was not incl but}, c3; MAR_ [rBrh, 70'b{NRealPages} + 0], c1; MDR _ Q{NRealPages} {_ topPage}{rC{C00}}, c2; Noop, c3; {%% no segment crossing of FPTOVP[i-1] ptr ??? } {interpret FPTOVP setup} {for i{acR} _ 501'b to MaxRealPage{rC} } { unless FPTOVP[i-1]=none{-1} } { do MAP[FPTOVP[i-1]]:vp _ i } MAR_ [rBrh, 73'b{FPTOVPStart} + 0], c1; rBrh _ 1, c2; acR{F2Vpage} _ MD, c3; acR{F2VrealPage+1} _ acR + 2{file1=real2}{+1}, c1; acRrh _ acR _ acR LRot8, c2; acR _ acR and ~0FF, c3; acR{F2V+500b} _ acR + 40, c1; rC _ 0FF + 1, c2; rC{501b} _ rC + 41, c3; {interpret FPTOVP Loop } {acR: FPTOVP[i-1] ptr } {rB: FPTOVP[i-1]:vp } {rC: i _ 501b } {Q: NRealPages= C00 } {rBrh: 10000{Map} } {spin2: GOTO[spin2], c*;}{%%%} f2vLp: MAR_ acR _ [acRrh, acR + 0], c1; rB{7FFF} _ (rB xor ~rB) RShift1, c2; rB{vp} _ MD and rB{7FFF}, c3; Ybus _ rB + rB, NegBr, c1; rC _ rC LRot8, XRefBr, BRANCH[$, none], c2; Ybus _ rC + 0F, NibCarryBr{nondisplay bank?}, BRANCH[$, fvMod], c3; MAR_ [rBrh{1}, rB + 0], BRANCH[fvNo, $], c1; MDR _ rC{i}, GOTO[none], c2; fvNo: Noop, GOTO[none], c2; fvMod: MAR_ [rBrh{1}, rB + 0], BRANCH[fvMNo, $], c1; MDR _ rC{i} + 70{move over flags to "dp" bit}, GOTO[none], c2; fvMNo: Noop, GOTO[none], c2; none: rC _ rC LRot8, CANCELBR[$, 1], c3; rC _ rC + 1, c1; Ybus _ rC xor Q{NRealPages}, ZeroBr, c2; acR _ acR + 1, BRANCH[f2vLp, $], c3; {spin3: GOTO[spin3], c*;}{%%%} {done with interpret FPTOVP} Noop, c1; rBrh _ 1, c2; Noop, c3; rB _ 0FF, c1; rC _ 40, c2; rC{4000} _ rC LRot8, c3; {Map[IOPageVp=0FF] _ {140}500'b} MAR{100FF}_ [rBrh{1}, rB + 0], c1; MDR{4001} _ rC{4000} + 1, c2; rC{100} _ 0FF + 1, c3; rC{200} _ rC + rC, c1; rC{400} _ rC + rC, c2; uBootStart_ rC{400}, {GOTO[StartNewInit],} c3; bankTest: Q _ 0, c1; Bank _ rB _ 0, c2; btLoop: rC _ ~ PPort, BRANCH[$, {GOTO[}MultiBank], c3; btLL: rC _ (rC LRot8) xor Q, c1; Ybus _ rC and 3, NZeroBr, c2; Q _ Q + {0FF +} 1, BRANCH[$, GoNewInit{UniBank}], c3; Bank _ rB +4, c1; rB _ rB +4, NibCarryBr,{}{%} GOTO[btLoop], c2; MultiBank: rB_ 4, c1; rBrh{0} _ rB{400h}_ rB LRot8, c2; {boot file starts at 200} rC_ 3{2nd .db}, c3; MAR_ [rBrh, rC+0], c1; rC{400q}{100} _ 0FF + 1, c2; rC_ MD, c3; rC_ rC+rB, c1; uBootStart_ rC{400}, c2; Noop,GOTO[GoNewInit], c3; GoNewInit: {copy data diverted from newIOPage to oldIOPage back to newIOPage} rBrh _ 1, c1; rB _ 40, c2; rB _ rB LRot8, c3; acR _ 0FF + 1, L0_ 0D, c1; rCrh _ 2, c2; rC _ 0, GOTO[BLT], c3; {BLT cnt/acR:100 from/rB:14000 to/rC:20000} {clear oldIOPage to zeros} rBrh _ 1, c1, at[0D{free?}, 10, subrRet]; rB _ 40, c2; rB _ rB LRot8, c3; {Initialize uIOPage register} rC _ rB or 1, c1; Noop, c2; uIOPage _ rC{4001}, c3; ioclp: MAR _ [rBrh{14000}, rB+0], BRANCH[$, ioclrDone], c1; MDR _ acR and ~acR, c2; rB _ rB +1, PgCarryBr, GOTO[ioclp], c3; ioclrDone: Noop, c2; GOTO[StartNewInit], c3; BackFromNewInit: Noop, c1; TOS{8002h} _ RRot1 5, c2; MCtl _ TOS{8002h}, GOTO[exitToEmulator], c3; {hard microcode (quick exit), get diagnostic table entry from first page of boot file} doDiag: rB _ 055{Mesa}, GOTO[doDiag2], c1; notLisp: rB _ 055{Mesa}, GOTO[doDiag2], c1; doDiag2: uLispBootMsg _ rB, c2; rB_ 2, c3; {boot file starts at 200} {{topPage _ MIN[topPage, AC0]} rB_ topPage, c1; rC _ 0AC, c2; rC _ rC LRot4, c3; Ybus _ rB{topPage} - rC{AC0}, CarryBr, c1; rB_ 2, BRANCH[$, trim1], c2; {boot file starts at 200} rC _ topPage, GOTO[mbjoin1], c3; trim1: topPage _ rC, GOTO[mbjoin1], c3; } mbjoin1: rB_ rB LRot8, c1; rC_ uDiagnostic, c2; rC_ rC{uDiagnostic=1}+1, c3; MAR_ [rBrh, rC+0], c1; rC{400q}{100} _ 0FF + 1, c2; {**}{ rC{1000q}{200} _ rC+rC{rC_ MD}, c3;} rC_ MD, c3; rC_ rC+rB, c1; uBootStart_ rC{400}, c2; MCtl_ 0, GOTO[exitToEmulator], c3;{%mesa small mem} {read the germ} readGerm: germStart_ acR, c3; rB_ germFileID, c1; rC_ bootFileID, L0_ 9, c2; acR_ DiskFileIDSize, CALL[BLT], c3; L2_ 1, c1, at[9, 10, subrRet]; CALL[readBoot3], c2; { We now have the germ in real memory. Restore the map for pages 0-255. Then move the germ to MDS 0, starting at page 1. Initialize the Request in the germ's SD. } RestoreMap: rBrh_ 1, c1, at[1,10,readBootRet]; rCrh_ 1, c2; rB_ topPage, c3; rC_ 0, L0_ 5, c1; acR_ 0FF+1, CALL[BLT3], c2; {vacate the pages just used to restore the low ones} rB_ topPage, c1, at[5, 10, subrRet]; rC_ rB+1, c2; acR_ 20{0FF+1}, c3; MAR_ [rBrh, rB+0], c1; MDR_ vacant, L0_ 0B, c2; acR_ acR LRot8{acR-1}, CALL[BLT], c3; {Move germ to MDS 0, page 1} rC _ germStart, c1, at[0B, 10, subrRet]; rB _ rC LRot8, c2; rBrh _ 0, c3; rD _ nextPage, c1; rD _ rD - rC, ZeroBr, c2; transferCount _ rD, BRANCH[moveGerm1, $], c3; {number pages in germ} acR_ bootNullGerm, GOTOABS[Maintenance2Loc], c1; moveGerm1: germStart_ acR xor ~acR, c1; rFrh _ germPageHigh, rF _ 0 + germPageLow, c2; rF _ rF LRot8, c3; mg2: Map _ [rFrh, rF], c1; Noop, c2; rCrh _ rC _ MD, c3; acR _ 0FF + 1, c1; rC _ rC and ~0FF, L0 _ 0C, c2; CALL[BLT], c3; rF _ rF + 0FF + 1, c1, at[0C, 10, subrRet]; rD _ rD - 1, ZeroBr, c2; rE _ LShift1 0FF, SE _ 1, BRANCH[mg2, InitRequest], c3; {Initialize Request in germ's SD} InitRequest: {rE has 1FF = start of SD -1} rC _ sFirstGermRequestHigh, c1; rC _ rC LRot8, c2; {Constants use an 8-bit data path.} rE _ rE + rC + 1, {correct page} c3; Map _ rF _ [rFrh, rE + 0], c1; rC _ sFirstGermRequestLow, c2; rBrh _ rB _ MD, c3; {InitRequest: Map _ rF _ [rFrh, rE + 1], c1; rC _ sFirstGermRequest, c2; rBrh _ rB _ MD, c3; } ZeroReq: MAR _ [rBrh, rC+0], c1; MDR _ rD, rC _ rC + 1, PgCarryBr, c2; {rD zero from above} BRANCH[ZeroReq, $], c3; rD _ RequestVersionHigh, c1; rD _ rD LRot8, c2; rD _ rD or RequestVersionLow, c3; MAR _ [rBrh, SD.Request.version+0], c1; MDR _ rD, c2; Noop, c3; MAR _ [rBrh, SD.Request.action+0], c1; MDR _ bootPhysicalVolume, c2; Noop, c3; MAR _ [rBrh, SD.Request.location.deviceType+0], c1; MDR _ germPilotDisk, c2; doneReq: MCtl _ 0, GOTO[exitToEmulator], c3; {Read the first page of the bootFile. Calculate the proper label by reading the label from the disk and filing in the correct fileID and page number} readBoot3: Noop, c3; readBoot: rB_ bootDiskAddr, c1; rC_ rD+headerAddr, L0_ 1, c2; {disk address of boot} acR_ 2, CALL[BLT], c3; {block transfer, takes count in acR, from in rB, and to in rC, returns first word past from block in rE} {*4} rB_ bootDiskAddr, c1, at[1, 10, subrRet]; rC_ rD or 80{uLinkPtr}{+{1}headerAddr}, L0_ 0E{*free?}, c2; {save for lisp} acR_ 2, CALL[BLT], c3; rB _ 82, c1, at[0E{*free?}, 10, subrRet]; uLinkPtr _ rB, c2; rB_ bootDiskAddr, c3; {nil disk address?} MAR_ [rBrh, rB+0], c1; rB_ rB+1, c2; acR_ MD, c3; MAR_ [rBrh, rB+0], c1; Noop, c2; acR_ acR or MD, c3; []_ acR, ZeroBr, c1; BRANCH[$, nilBootFile], c2; rB_ nextPage, L1_ 1, c3; acR_ 1, CALL[doVrr2], c1; {read 1 starting at page 2} []_ acR and uBadBits, ZeroBr, c1, at[1, 10, transferRet]; rC_ rD+labelAddr, BRANCH[$, here2], c2; {write fileID into label} acR_ bootDeviceError, GOTOABS[Maintenance1Loc], c3; here2: rB_ bootFileID, L0_ 2, c3; acR_ 6, CALL[BLT2], c1; {+low 16 bits of page #} rE_ rE and 7F, c1, at[2, 10, subrRet]; rE_ rE LRot8, c2; {rE_ high bits of page#} rE_ LShift1 rE, c3; MAR_ [rCrh, rC+0], c1; acR_ 7, c2; acR_ MD and acR, c3; MAR_ [rCrh, rC+0], c1; MDR_ acR or rE, c2; rC_ rC-1, c3; MAR_ [rCrh, rC+0], c1; {read low 16 bits of page #} rB_ bootDiskAddr, c2; rC_ MD, c3; rC_ rC+1, {reading first page is a special case} c1; filePage_ rC, c2; {restore disk address} rC_ rD+headerAddr, L0_ 3, c3; acR_ 2, CALL[BLT2], c1; rB_ nextPage, L1_ 5, c1, at[3, 10, subrRet]; acR_ 1, CALL[doVvr3], c2; {read 1 starting at page 2} []_ acR and uBadBits, ZeroBr, c1, at[5, 10, transferRet]; acR_ nextPage, BRANCH[$, here3], c2; acR_ bootDeviceError, GOTOABS[Maintenance1Loc], c3; here3: acR_ acR+1, c3; nextPage_ acR, c1; {label template} acR_ labelSize, c2; rB_ rD+labelAddr, L0_ 6, c3; rC_ labelTemplate, CALL[BLT2], c1; {read the rest of the file from the Pilot Volume} readLoop: L1_ 1, c1, at[6, 10, subrRet]; CALL[pagesLeftInCylinder3], c2; transferCount_ acR, ZeroBr, c1, at[1, 10, miscRet]; L1_ 4, BRANCH[readRun, $], c2; {no pages left in cylinder, advance to next cylinder} Noop, c3; {step in one cylinder} MAR_ [rDrh, headerAddr+1], c1; MDR_ 0, CANCELBR[$, 0], c2; {start at head 0, sector 0} Noop, c3; MAR_ [rDrh, headerAddr+0], c1; Noop, c2; acR_ MD, c3; MAR_ [rDrh, headerAddr+0], L1_ 2, c1; MDR_ acR+1, CALL[pagesLeftInCylinder3], c2; Noop, c1, at[2, 10, miscRet]; transferCount_ acR, L1_ 4, c2; readRun: rB_ nextPage, CALL[doVvr], c3; rE_ acR and uBadBits, ZeroBr, c1, at[4, 10, transferRet]; rB_ transferCount, BRANCH[readBurp, $], c2; acR_ filePage, c3; acR_ acR+rB, c1; {next page in file} filePage_ acR, c2; acR_ nextPage, c3; acR_ acR+rB, c1; {next page in memory} nextPage_ acR, c2; GOTO[readLoop], c3; {burped while reading run of pages, status in acR. rB has number of sectors requested} readBurp: []_ rE and ~verifyBit, ZeroBr, c3; MAR_ [rDrh, vvrAddr+0], BRANCH[$, verifyError], c1; {get # of sectors remaining} acR_ bootDeviceError, GOTOABS[Maintenance3Loc], c2; {not a verify error} verifyError: rC_ acR LRot4, c2; {shift field bits} rE_ MD, c3; {parameter area} MAR_ [rDrh, rE+sectors], c1; rC_ rC and 0C, c2; acR_ MD, c3; {number sectors remaining} []_ rC xor 8, ZeroBr, c1; {label verify error?} acR_ rB-acR, BRANCH[$, verErr1], c2; {number sectors transferred} acR_ bootDeviceError, GOTOABS[Maintenance1Loc], c3; {not in label} verErr1: transferCount_ acR, {zero is okay} c3; rE_ filePage, c1; rE_ rE+acR+1, c2; {file page for next label} filePage_ rE, c3; rB_ nextPage, c1; rB_ rB+acR+1, c2; {next available page for vvr} nextPage_ rB, c3; rB_ rB-1, L1_ 6, c1; {page used by vrr} acR_ 1, CALL[doVrr3], c2; {transfer 1 page} []_ acR and uBadBits, ZeroBr, c1, at[6, 10, transferRet]; BRANCH[$, verErr3], c2; acR_ bootDeviceError, GOTOABS[Maintenance1Loc], c3; verErr3: Noop, c3; {Copy boot link to header, and check for end of file, FFFF in both words of boot link.} {*1,2 Check for end of file before copying boot link to header} {*0 stop reading after 768Kw max real memory} {*0} MAR_ [rDrh, labelPageLow+0], c1; Noop, c2; acR_ MD, c3; {*0} acR_ acR LRot8, c1; Ybus _ acR - 0C, {NibCarryBr{vPage> 768*4},} c2; Noop, BRANCH[$, endRead1], c3; MAR_ [rDrh, bootLink+0], c1; Noop, c2; acR_ MD, c3; {*1 MAR_ [rDrh, headerAddr+0], c1; MDR_ acR, c2; Noop, c3; *} MAR_ [rDrh, bootLink+1], c1; CANCELBR[$, 0], c2; rB_ MD, c3; {*2 MAR_ [rDrh, headerAddr+1], c1; MDR_ rB, CANCELBR[$, 0], c2; Noop, c3; *} Noop, c1; Noop, c2; []_ acR or rB, ZeroBr, c3; acR_ acR+1, BRANCH[rdBurp1, $], c1; acR_ bootBrokenChain, GOTOABS[Maintenance3Loc], c2; {boot chain link is zero} rdBurp1: rB_ rB+1, c2; []_ acR or rB, ZeroBr, c3; rC_ rD+labelAddr, BRANCH[rdBurp2, $], c1; GOTO[endRead], c2; {found end of chain, return} rdBurp2: Noop, c2; Noop, c3; {*1} MAR_ [rDrh, headerAddr+0], c1; MDR_ acR-1, c2; , c3; MAR_ [rDrh, headerAddr+1], c1; MDR_ rB-1, CANCELBR[$, 0], c2; {*2} Q_ uLinkPtr, c3; Temp _ filePage, c1; rK _ uFirstPage, c2; , c3; {*5} MAR_ [rDrh, Q{uLinkPtr}+0], c1; MDR_ Temp - rK, c2; Noop, c3; {*5} MAR_ [rDrh, Q{uLinkPtr}+1], c1; MDR_ acR-1, CANCELBR[$, 0], c2; Noop, c3; {*5} MAR_ [rDrh, Q{uLinkPtr}+2], c1; MDR_ rB - 1, CANCELBR[$, 0], c2; Q{uLinkPtr} _ Q +3, PgCarryBr, c3; acR_ labelSize, BRANCH[there1, $], c1; {Noop,} L0_ 7, GOTO[there2], c2; there1: uLinkPtr _ Q{uLinkPtr+3}, L0_ 7, c2; there2: rB_ labelTemplate, CALL[BLT], c3; MAR_ [rDrh, labelPageLow+0], c1, at[7, 10, subrRet]; MDR_ filePage, c2; GOTO[readLoop], c3; endRead: Noop, c3; endRead1:Noop, c1; pRet2, c2; RET[readBootRet], c3; {here if boot file pointer was zero} nilBootFile: []_ uDiagnostic, ZeroBr, c3; acR_ 1 {disk Boot}, BRANCH[noDiagnostics, $], c1; []_ germStart, ZeroBr, c2; BRANCH[noGerm, noEmulator], c3; noEmulator: acR_ bootNoEmulator, GOTOABS[Maintenance2Loc], c1; noGerm: acR_ bootNoGerm, GOTOABS[Maintenance2Loc], c1; {this code tries a disk boot if no hard microcode is installed} noDiagnostics: uDiagnostic_ 0, c2; bootDevice _ acR {disk Boot}, GOTO[emuHard], c3; {subroutines} doVvr3: Noop, c3; doVvr: MAR_ [rDrh, vvrAddr+0], c1; GOTO[doTransfer], c2; {does verify, read, read operation to the disk Takes number of sectors in acR, page number in rB, and disk address in header area. Returns status in acR Clobbers rE} doVrr2: Noop, c2; doVrr3: Noop, c3; doVrr: MAR_ [rDrh, vrrAddr+0], c1; {base of vrr parameters} CANCELBR[$, 0], c2; doTransfer: rE_ MD, c3; MAR_ [rDrh, rE+sectors], c1; {set up paramter area} MDR_ acR, c2; {sector count} Noop, c3; MAR_ [rDrh, rE+dataPage], c1; MDR_ rB - 1, CANCELBR[$, 0], c2; {first page in main storage} Noop, c3; MAR_ [rDrh, rD+ transferAddr], c1; {base of transferIOCB} acR_ rE, CANCELBR[$, 0], c2; {base of vrr parameter area} rE_ MD, c3; MAR_ [rDrh, rE+parameters], c1; MDR_ acR, CANCELBR[$, 0], c2; rC_ acR, c3; MAR_ [rDrh, headerAddr+1], c1; {read head} CANCELBR[$, 0], c2; acR_ MD, c3; acR_ acR LRot4, c1; acR_ acR RRot1, c2; acR_ acR and headMask, c3; acR_ acR or haltBits, c1; Noop, c2; Noop, c3; MAR_ [rDrh, rC+haltWord], c1; {write halt word} MDR_ acR, CANCELBR[$, 0], c2; acR_ acR or UFindSect, c3; MAR_ [rDrh, rC+findWord], c1; {write find word} MDR_ acR, CANCELBR[$, 0], L0_ 2, c2; rC_ rE, CALL[seek], c3; []_ acR and uBadBits, ZeroBr, L0_ 3, c1, at[2, 10, transferRet]; BRANCH[transferError, $], c2; rE_ rC, CALL[diskOp], c3; transferRet1: Noop, c1, at[3, 10, transferRet]; pRet1, c2; transferRet2: RET[transferRet], c3; transferError: GOTO[transferRet1], c3; {call with IOCB in rE, returns when disk operation complete with status in acR} {diskOp1: Noop, c1; diskOp2: Noop, c2; diskOp: acR_ IOPageLow, c3, at[2, 4]; MAR_ [acRrh, diskCSB+0], c1;}diskOp: Noop, c1; acRrh _ IOPageHigh, c2; {AEF 9/14/83 - why is this instruction at[2, 4]?} acR _ uIOPage, c3, at[2, 4]; MAR_ [acRrh, DiskCSBOffsetIOCB+0], c1; MDR_ rE, c2; {*** {*} acR_ firmwareEnable, c3; {*} {* observe segment crossings} {*} {*} MAR_ [rDrh, statusAddr+0], c1; {set invalid status} {*} MDR_ badBits, c2; {*} KCtl_ acR LRot0, c3; {start the transfer} {*} {*}transferWait: {*} acR_ ~KStatus, BRANCH[$, trRef], c1; {*}trWa2: []_ acR LRot8, XDisp, c2; {busy?} {*} Q _ Q + 1, NibCarryBr, BRANCH[trDone, transferWait, 0E], c3; {*} {*}trRef: Noop, c2; {*} Noop, c3; {*} {Refresh,} GOTO[trWa2], c1; {*} {*}trDone: MAR_ [rDrh, statusAddr+0], CANCELBR[$, 1], c1; {*} pRet0, LOOPHOLE[natc], c2; {*} acR_ MD, RET[transferRet], c3; {return status in acR} ***} Noop, c3; MAR_ [rDrh, statusAddr+0], c1; {set invalid status} MDR_ badBits, c2; acR_ firmwareEnable, c3; {start the transfer} KCtl_ acR LRot0, c1; transferWait: acR_ ~KStatus, CANCELBR[$, 0], c2, at[0F, 10, transferWait]; []_ acR LRot8, XDisp, c3; {test firmware busy} MAR_ [rDrh, statusAddr+0], BRANCH[$, transferWait], c1; pRet0, LOOPHOLE[natc], c2, at[0E, 10, transferWait]; acR_ MD, RET[transferRet], c3; {return status in acR} {call with current cylinder in currentCylinder, and desired cylinder in cylinder field of header} seek: MAR_ [rDrh, headerAddr+0], c1; rB_ currentCylinder, CANCELBR[$, 0], c2; acR_ MD, c3; {target} rB_ rB-acR, ZeroBr, c1; {delta number of cylinders} currentCylinder_ acR, BRANCH[$, noSeek], c2; []_ rB, NegBr, c3; acR_ 0, BRANCH[seekOut, $], c1; acR_ inBit, GOTO[seek1], c2; seekOut: rB_ -rB, c2; seek1: acR_ acR or seekMask, {enable firmware, drive select} c3; MAR_ [rDrh, seekAddr+0], c1; {address of seek IOCB} CANCELBR[$, 0], c2; rE_ MD, c3; MAR_ [rDrh, rE+cylinders], c1; MDR_ rB, c2; Noop, c3; MAR_ [rDrh, rE+stepHigh], c1; MDR_ acR or stepBit, CANCELBR[$, 0], c2; Noop, c3; MAR_ [rDrh, rE+stepLow], c1; MDR_ acR, CANCELBR[$, 0], c2; rE_ rE+1, GOTO[diskOp], c3; noSeek: acR_ 0, c3; Noop, c1; pRet0, GOTO[transferRet2], c2; {Be careful, these routines are device dependent! Only routines for SA1004 and SA4008 are supplied} {Uses data left in last header to compute pages left in cylinder, returns result in acR.} pagesLeftInCylinder3: Noop, c3; pagesLeftInCylinder: Noop, c1; {SA4000 or SA1000?} Xbus_ KStatus, XwdDisp, c2; BRANCH[SA1000Left, $, 2], c3; {SA4008, pages left in cylinder= (28-sector)+(8-head-1)*28} MAR_ [rDrh, headerAddr+1], c1, at[3,4,SA1000Left]; rB_ 7, CANCELBR[$, 0], c2; rE_ MD, c3; acR_ rE LRot8, c1; acR_ acR and 0FF, c2; {head} rE_ rE and 0FF, c3; {sector} acR_ rB-acR, NegBr, L0_ 0, c1; rB_ 28'd, BRANCH[multiply, $], c2; acR_ 0, c3; {off the end of the cylinder} OffEnd: rE_ 0, c1; pRet1, GOTO[pgLft1], c2; {return from multiply} divMultRet: acR_ Q+28'd, pRet1, GOTO[pgLft1], c2, at[0, 10, divMultRet]; {SA1004, pages left in cylinder= (16-sector)+(4-head-1)*16} SA1000Left: MAR_ [rDrh, headerAddr+1], c1, at[2,4,SA1000Left]; rB_ uQuantumSA1000MaxHeadNum, CANCELBR[$, 0], c2; rE_ MD, c3; acR_ rE LRot8, c1; acR_ acR and 0FF, c2; {head} rE_ rE and 0FF, c3; {sector} acR_ rB-acR, NegBr, c1; rB_ acR LRot4, BRANCH[SA1000More, $], c2; {(4-head-1)*16} acR_ 0, GOTO[OffEnd], c3; {off the end of the cylinder} SA1000More: Noop, c3; Noop, c1; acR_ rB+16'd, pRet1, c2; pgLft1: acR_ acR-rE, RET[miscRet], c3; {multiply, call with multiplier in rB, multiplicand in acR, uses rC, result left in Q timing: 45 cycles main loop is 3 cycles times 15 iterations 4 cycles last iteration 3 cycles preamble 1 cycles postamble total 53 cycles (2 MOD 3} multiply: Q_ acR, c*; acR_ 0'x, c2; rC_ 10'x, c3; mult0: []_ Q and 1, ZeroBr, c1; rC_ rC-1, ZeroBr, BRANCH[mult1, mult2], c2; mult1: acR_ DARShift1 (acR+rB), BRANCH[mult0, mult3], c3; mult2: acR_ acR DARShift1, BRANCH[mult0, mult3], c3; mult3: Q_ ~Q, pRet0, c1; RET[divMultRet], c*; {divide, call with dividend in acR, divisor in rB, uses rC, result left in Q remainder in acR timing: 64 cycles main loop is 4 cycles times 16 iterations 3 cycles preamble 2 cycles postamble total 69 cycles (0 MOD 3)} {divide: Q_ acR, c*; acR_ 0, c2; rC_ 10'x, c3; div0: acR_ acR DALShift1, Cin_ 1, c*; {shifts in a zero!!!!!} acR_ acR-rB, NegBr, c2; rC_ rC-1, ZeroBr, BRANCH[div1, div2], c3; div1: Q_ Q or 1, BRANCH[div0, div3], c1; div2: acR_ acR+rB, BRANCH[div0, div3], c1; div3: pRet0, c2; RET[divMultRet], c*;}z20320e12k40(2,14817)(3,65535)(4,65535)\302t1 1t0 127t1 1t0 133t1 1t0 57t1 1t0 14t1 1t0 71t1 1t0 44t1 1t0 43t1 1t0 48t1 1t0 51t1 1t0 39t1 1t0 320t1 1t0 128t1 1t0 61t1 1t0 49t1 1t0 75t1 1t0 67t1 1t0 56t1 1t0 38t1 1t0 444t1 1t0 368t1 1t0 261t1 1t0 3710f1 105f0 6445t2 7t0 23t2 9t0 5t2 8t0 23t2 9t0 5t2 8t0 24t2 1t0 309t2 1t0 18t2 1t0 21t2 1t0 29t2 1t0 23t2 1t0 29t2 6t0 35t2 1t0 1t2 1t0 12t2 1t0 15t2 1t0 25t2 1t0 2301f1 105f0 5426t2 12t0 58t2 13t0 46t2 6t0 2t2 10t0 7t2 12t0 11t2 8t0 32t2 8t0 11t2 4t0 33t2 79t0 4832t2 1t0 {compare two blocks of memory, takes count in acR, and addresses in rB, and rC, clobbers rE, returns count in acR where compare first lost, (acR=0)=> compare succeeded} {compare3: Noop, c3; compare: MAR_ [rBrh, rB+0], c1; []_ acR, ZeroBr, c2; rE_ MD, BRANCH[comp1, $], c3; GOTO[endBLT1], c1; comp1: MAR_ [rCrh, rC+0], c1; Noop, c2; rE_ rE xor MD, c3; Noop, c1; Noop, c2; []_ rE, ZeroBr, c3; acR_ acR-1, BRANCH[$, comp2], c1; acR_ acR+1, pRet0, GOTO[endBLT2], c2; comp2: rB_ rB+1, c2; rC_ rC+1, GOTO[compare], c3;} {increments header} {incrHdr: MAR_ [rDrh, headerAddr+1], c1; CANCELBR[$, 0], c2; rE_ MD, c3; acR_ rE and 0FF, c1; {sector} acR_ acR+1, c2; []_ acR-27'd, NegBr, c3; rE_ rE and ~0FF, BRANCH[incHd, $], c1; {head} rE_ rE or acR, c2; incHdr0: Noop, c3; incHdr1: MAR_ [rDrh, headerAddr+1], c1; MDR_ rE, pRet0, CANCELBR[$, 0], c2; RET[subrRet], c3; incHd: rE_ rE LRot8, c2; rE_ rE+1, c3; []_ rE-7, NegBr, c1; rE_ rE LRot8, BRANCH[$, incHdr0], c2; incCyl: rE_ 0, c3; MAR_ [rDrh, headerAddr+0], c1; Noop, c2; acR_ MD, c3; MAR_ [rDrh, headerAddr+0], c1; MDR_ acR+1, GOTO[incHdr0], c2;}z20320k40