// D0load.bcpl -- machine-dependent subroutines called by MLOAD.BCPL
// Last edited: 21 October 1981
get "mdecl.d"
get "mcommon.d"
get "d0.d"
manifest [ get "d0regmem.d" ]
external [
// OS
Zero
// MIDAS
MidasSwat; Initialized
// MASM
VUsc; StrSize
// MDATA
MCTimeOut
// MSYM
MapSymBlocks; @BHsize
// MMPRGN
UpdateMPDValues
// MCMD
DisplayError; ErrorAbort
// MGO
@CantContinue
// D0TABLES
@MEMLEN; @MEMWID
// D0MEM
readrr
// D0GO
AddBp
// D0VM
SetVirtP; LookUpAA; RetrieveBlock; VAtab; AAtab; IMstab; RMstab
// Defined here
PrepareLoad; RestoreAfterLoad; PutMDSymOnly; AddToVM; LoadCleanUp
]
static [ oldMDATAwid; TypeOfLoad ]
//Verify that the hardware is in good shape for the Ld, LdData, LdSyms,
//Cmpr, or Dump and do other setup. Call DisplayError if probably not
//ok to do the operation; if DisplayError returns (indicating user wants
//to go ahead with the operation), then do ResetsCSS().
let PrepareLoad(LoadType) be
[ if Initialized & (LoadType ne 0) do
[ CantContinue = CantContinue % didLoad
//DisplayError("Power is off", "Continue-loading")
//ResetsCSS()
Zero(MCTimeOut,6) //Zero error counters
]
TypeOfLoad = LoadType
oldMDATAwid = MEMWID!MDATAx
MEMWID!MDATAx = MDATAwid
]
and RestoreAfterLoad() = valof
[ MEMWID!MDATAx = oldMDATAwid
//2nd arg to SetVirtP causes UpdateMPDValues.
//Have to update the display even on LdSyms because virtual addresses
//may be displayed (e.g., CIA or TPC 20).
//***FormCmdMenu may be called redundantly here, once by SetVirtP and
//***once by InitLoad.
if LookUpAA(0) ge 0 then SetVirtP(true,nil)
if VUsc(MCTimeOut,table [ 0; 0; 0; 0; 0; 0 ] ,6) ne 0 then
ErrorAbort("****Communication errors occurred****")
]
//Special kludge subroutine used by MLOAD on "LdSyms" because the
//virtual to absolute correspondence table has to be loaded even though
//we are only loading symbols and we have to record the BP's in the BP
//table for the load (???)
and PutMDSymOnly(MemX,DVec,AVec) = valof
[ if MemX eq IMx do
[ if VUsc(AVec,MEMLEN+MemX+MemX,2) ge 0 then resultis false
let AA = AddToVM(AVec!1,DVec)
if AA < 0 then resultis false //AA exceeds phsyical microstore
]
resultis true
]
//Called only during Ld, LdSyms, or LdData by PutMemData or PutMDSymOnly.
//VA must be valid.
and AddToVM(VA,DVec) = valof
[ let DV3 = DVec!3
if DV3<<IMV.Undef ne 0 then resultis -1
let AA = DV3<<IMV.Addr
//Don't insert BP's on LdSyms
if TypeOfLoad eq 0 then DV3 = DV3 & #37777
//Load the VM except on LdData
if TypeOfLoad ne 1 do
[ let Block = RetrieveBlock(VAtab+(VA rshift BlockShift),VAKind,
2,0,#17777)
Block!(VA & BlockMask) = DV3
Block = RetrieveBlock(AAtab+(AA rshift BlockShift),AAKind,
2,0,#17777)
Block!(AA & BlockMask) = VA+(DV3 & not AA)
]
//Insert BP, if any, unless LdSyms
if (DV3 & #140000) ne 0 do
[ switchon AddBp(DV3<<IMV.Addr) into
[ case -1: //Inserted BP ok
case 1: endcase //Already in BP table
case 0: MidasSwat(BPTableOvf)
]
]
resultis AA
]
//Build IMstab indexed by IM address, contains BlockAddr for the symbol
//block which contains the nearest IM symbol le each IM address.
//Similarly, build RMstab indexed by RM address.
and LoadCleanUp() be
[ if not Initialized then return
MapSymBlocks(BuildAddrInvert,1)
let BestBlockAddr = 0
//Fill gaps in IMstab table
for I = 0 to (MEMLEN!(IMx+IMx+1) rshift (BlockShift+1))-1 do
[ let Block = RetrieveBlock(IMstab+I,IMKind,1)
if Block ne 0 then
BestBlockAddr = ExtendSyms(BestBlockAddr,Block,BlockSize*2)
]
ExtendSyms(0,RMstab,MEMLEN!(RMx+RMx+1))
]
and ExtendSyms(BestBlockAddr,Table,Length) = valof
[ for I = 0 to Length-1 do
[ let W = Table>>Bytes.Byte↑I
test W eq 0
ifso Table>>Bytes.Byte↑I = BestBlockAddr
ifnot BestBlockAddr = W
]
resultis BestBlockAddr
]
//Called from MapSymBlocks. Fills an IMstab entry for each IM address symbol
//with BlockAddr for the block containing the symbol; fill RMstab entry for
//each RM symbol with BlockAddr for the block containng the symbol.
and BuildAddrInvert(B,nil,nil,nil,nil) be
[ let Block,BlockAddr = B>>BT.Core,B>>BT.BlockAddr
let Blk = nil
for I = BHsize to Block>>BH.LastPntr do
[ let Sym = Block+Block!I
let Body = Sym+StrSize(Sym)
let Addr = Body>>Symb.A.A2
switchon Body!0 into
[
case (AddrSymb*#400)+IMx:
Blk = RetrieveBlock(IMstab+(Addr rshift (BlockShift+1)),
IMKind,1,Block,0)
Addr = Addr & (BlockMask+BlockMask+1); endcase
case (AddrSymb*#400)+RMx:
Blk = RMstab; endcase
default: loop
]
Blk>>Bytes.Byte↑Addr = BlockAddr
]
]