//D1mem.bcpl memory read/write procedures 28 June 1983 get "mcommon.d" get "d1.d" manifest [ get "d1instrs.d" ] manifest [ get "d1regmem.d" ] //manifest [ get "d1dmux.d" ] "TOO MANY NAMES, SO.." manifest [ dCIAINC=#1; dCIA=#2; dTNIA=#5; dBNPC=#6; dOLDCIA=#165 dIMOUT=#172 ] external [ // OS Zero; DoubleAdd; Dvec // MINIT0 @MBlock; MStatus // MASM DoubleNeg; @OddParity // MMPRGN UpdateMPDValues // MCMD ErrorAbort // MGO @CantContinue // MLOAD DoingLoad // D1I0 @DMuxTab; @OldDMuxTab; DWrong; DChecked; DMuxSelect @DHistTab; @SaveMIR; HWStatus; SaveBR36 // D1TABLES @MEMCON // D1ASM ReadDMux; LoadDMD; LoadMIR; @DoStrobe; @SelectTask; @SetALUF; @SetRSTK @Xct; @XctR16; @XctR16C; @XctR16Link; @XctL16; @XctL16C; @XctLFF @XctL16T; @XctL16Q; ConvertAV; IMtoMIR; MIRtoIM @MCXctR; @MCXct; ReadIMX; LoadDWatch; SelFltSrn @MADDRL; @MADDRH; stUndAdr; stReadOnly // D1REG MGetChecks; MPutChecks // D1RES BR36Saved; BreakTask // D1VM LookUpVA; LookUpAA; @VirtualP // D1LOAD AddToVM // D1CONFIG CacheAMask0; CacheAMask1; log2rows; IMXmask //Defined here for use by machine-independent code GetMemData; MGetMemData; PutMemData; MPutMemData; MDATAmemx // Defined here for D1 code RdCACHEA; GetMic2; FixClock; TurnOffRefresh; ClearIMBDAddr @SaveTask; @SaveTPC; @OldTask; OldTPC; SaveALUFM0 SaveALUFM16; SaveSTKP; SaveTIOA; @SaveLINK; @SaveQ; @SaveSRN @SaveMCR; @SaveT; @SaveRBase; @SaveMBase; SaveR0 ] static [ MDATAmemx = MDATAx @SaveTask; @SaveTPC; @OldTask; OldTPC; SaveALUFM0; SaveALUFM16 @SaveLINK; @SaveQ; @SaveSRN; @SaveMCR; @SaveT; @SaveRBase @SaveMBase; @SaveBRHI; @SaveBRLO; SaveSTKP; SaveTIOA; SaveR0 ] let FixIMVA(DVec) be [ if VirtualP then DVec!0 = LookUpVA(DVec!0) ] and GetMic2(DVec) be [ DVec>>lh = MCXctR(BInt+BHoldInt+BCFetchInc) DVec>>rh = MCXctR(BInt+BHoldInt+BCFetchInc) ] and HistShift(I) = valof [ let T = nil for J = MADDRH+I to MADDRH+I+(15*3) by 3 do [ T = (T lshift 1)+((DHistTab!I rshift MADDRL) & 1) ] resultis T ] and RestoreBR36() be [ XctL16T(DisHold+DisCF+NoWake); Xct(MCRFT) XctL16T(SaveBR36!0); Xct(BRHIFT) XctL16T(SaveBR36!1); Xct(BRLOFT) ] and RestoreMemStuff() be [ XctLFF(LMB0,SaveMBase) XctL16T(SaveSRN); Xct(SRNFT) XctL16T(SaveMCR); Xct(MCRFT) XctL16T(SaveT); SelectTask(OldTask) ] and ClearIMBDAddr() be [ LoadDMD(IMAddr0); LoadDMD(IMAddr1) LoadDMD(IMAddr2+HWStatus>>HWStatus.MIRdebugging) LoadDMD(IMControl) ] and RestoreIMBD() be [ if BreakTask ne 0 then CantContinue = CantContinue % didIMBD XctL16C(LLINK,OldTPC); XctL16C(LTPC,17B); Xct(NOOP) XctL16C(LLINK,SaveLINK); SelectTask(OldTask) DoStrobe(Clock+UseCPReg+ClrReady); DoStrobe(Clock+UseCPReg) ] //Used from ConvertAV for CACHED setup and for CACHEA read and RdCACHEA(DVec) = valof [ XctL16T(dVAfVic+UseMcrV+NoWake+FDMiss+DisBR+DisHold+MADDRL) Xct(MCRFT); XctL16T(MADDRH); Xct(NOOP) //For some strange reason, it is essential to do _PIPE5 right after //DUMMYREF_ and before _PIPE0 or _PIPE1. let CE = TurnOffRefresh() Xct(DUMMYFT); Xct(NOOP) let T = XctR16C(RPIPE5,DVec) LoadDMD(CE) DVec!0 = XctR16C(RVAHI,DVec) & 7777B; XctR16C(RVALO,DVec+1) resultis T ] and FixIFUMParity(D0,D1) = (D1 & 107777B)+ (OddParity(D0 & 1400B,D1 & 40317B) & 40000B)+ (OddParity(D0 & 377B,D1 & 20000B) & 20000B)+ (OddParity(D0 & 2000B,D1 & 117460B) & 10000B) //Procedure to turn off RunRefresh. This has to be done carefully, //first turning off EnRefreshPeriod', then RunRefresh. Needed when //reading or writing cache flags. and TurnOffRefresh() = valof [ let CE = RunEnable+HWStatus>>HWStatus.RunControl LoadDMD(CE % EnRefreshPeriodx) LoadDMD(RunEnable+ECLup+IOResetx+EnRefreshPeriodx) resultis CE ] and FixClock() be [ if MStatus>>MStatus.MachRunning eq 0 then DoStrobe(Clock+UseCPReg) ] //Do manifold load of IM half-word and LoadIMData(d0,d1,dpar,lhalf) be [ LoadDMD(IMDataA+((d0 rshift 9) & 77B)) LoadDMD(IMDataB+((d0 rshift 3) & 77B)) LoadDMD(IMDataC+((d0 lshift 3) & 77B)+((d1 rshift 13) & 4)+ ((dpar rshift 6) & 2B)) let dcon = IMControl+IMAddressen+ResetCBMIR+ ((d0 rshift 14) & 2B)+lhalf LoadDMD(dcon); LoadDMD(dcon+IMWriteen); LoadDMD(dcon) ] //GetMemData is called directly by MLOAD, MTEST, and some Dorado-specific //actions. Other places in machine-dependent code call MGetMemData. //GetMemData freely smashes "volatile" stuff, but shouldn't clobber //anything that may be loaded from a .MB file. MGetMemData restores //whatever GetMemData clobbers. and GetMemData(MemX,DVec,AVec) = valof [ let T,U,DVX,DVH = nil,vec 4,nil,nil switchon ConvertAV(AVec,MemX) into [ case ABSOLx: DVec!0 = MCXctR(BInt+BHoldInt+BCFetchInc) lshift 8 MCXct(BInt+BCNoop); FixClock(); endcase case MSTATx: GetMic2(DVec); DVec = DVec+1 case ABSx: GetMic2(DVec); MCXct(BInt+BCNoop); FixClock(); endcase case TPCx: test MADDRL eq SaveTask ifso DVec!0 = SaveTPC ifnot [ XctL16C(RTPC,MADDRL); XctR16Link(RLINK,DVec) ] FixIMVA(DVec); endcase case TLINKx: SaveLINK = not XctR16Link(RLINK,DVec) DVec!0 = SaveLINK; FixIMVA(DVec); endcase case OLINKx: T = not XctR16Link(RLINK,DVec) DVec!0 = (T & 177700B)+((T-1) & 77B) FixIMVA(DVec); endcase //Use Dvec here to reduce the max. stack depth. The bad case seems to be //aborting from SimGo, when many stack words are consumed by an overlay. //During the abort, stack becomes ...MStopped, ReadAllRegs, UpdateMPDValues, //MGetMemData, GetMemData, FixIMVA, LookUpVA, RetrieveBlock, GetBlock, //ActOnDiskPages, .... Reduce GetMemData frame size by using Dvec rather //than vec. case IMBDx: DVX,DVH = DMUXlen,DHISTlen Dvec(GetMemData,lv DVX,lv DVH) T,U = DMuxTab,DHistTab; DMuxTab,DHistTab = DVX,DVH LoadDMD(IMControl+IMAddressen+ResetCBMIR) ReadDMux(); MIRtoIM(DVec,DMuxTab+dIMOUT) DMuxTab,DHistTab = T,U ClearIMBDAddr(); endcase case IMx: MADDRL = LookUpAA(MADDRL,DVec) if MADDRL < 0 do //Outside VM [ Zero(DVec,3); resultis false ] case IMXx: ReadIMX(DVec,U); endcase //U is temp storage vec case ALUFMx: test MADDRL eq 16B ifso DVec!0 = SaveALUFM16 ifnot test MADDRL eq 0 ifso DVec!0 = SaveALUFM0 ifnot [ Xct(SetALUF(TFAF0,MADDRL)); XctR16(RT,DVec) ] DVec!0 = DVec!0 lshift 8; endcase //Have Task_17, ProcSRN_1, MemBase[17]_36, virtual address from CACHEA //with word bits in BR 36, T_0, Mcr_NoWake+DisHold or NoWake+DisHold+DisCF //according to Vacant+WP in CacheA entry. case CACHEDx: //MapFaults and data errors ignored for VM. case VMx: Xct(FETCHM) case MDx: Xct(TFMD) case Tx: XctR16(RT,DVec); endcase case RBASEx: Xct(TFPTRS); DVec!0 = (XctR16(RT,DVec))<>nib0 = (RdCACHEA(DVec))<