//D1mem.bcpl memory read/write procedures // 19 May 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 // 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 @SetALUF; @SetRSTK; @Xct; @XctR16; @XctR16C; @XctR16Link @XctL16; @XctL16C; @XctLFF; @XctL16T; @XctL16Q @SelectTask; 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) ] //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,DVX = nil,vec DMUXlen 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 //ConvertAV(..) cleared MIR, but do it directly anyway. case IMBDx: LoadDMD(IMControl+IMAddressen+ResetCBMIR) T = DMuxTab; DMuxTab = DVX ReadDMux(); MIRtoIM(DVec,DMuxTab+dIMOUT) DMuxTab = T ClearIMBDAddr(); endcase case IMx: MADDRL = LookUpAA(MADDRL,DVec) if MADDRL < 0 do //Outside VM [ Zero(DVec,3); resultis false ] case IMXx: ReadIMX(DVec,DVX); endcase 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))<>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) ] //PutMemData is called directly by MLOAD and MTEST (where speed is //important) and by some Dorado-specific actions. Other places in //machine-independent code call MPutMemData. PutMemData freely smashes //"volatile" stuff, but must be sure to leave both the hardware and //any Midas statics in good shape for the Get and MGet procedures to //deliver accurate values. MPutMemData calls PutMemData and then //restores any smashed volatile registers. and PutMemData(MemX,DVec,AVec) = valof [ let D0,D1,D2 = DVec!0,DVec!1,DVec!2 let TVec,TVec1,DVX = vec 1,vec 1,vec 10 switchon ConvertAV(AVec,MemX) into [ case ABSx: MCXct(BInt+BCStoreInc+(D0<