//MDload1 -- first pass loader for Micro binaries // last edited July 5, 1980 8:35 AM get "mddecl.d" external // defined here [ Load1 // (sources, outs, tempzone, zone) ] external [ // OS Closes Puts; WriteBlock Allocate; Free MoveBlock; SetBlock; Zero Noop // Template PutTemplate // MDmain @IP @DMachine @NInstructions @IM @RM @IFUM // MDinit Version Xternal // MDerr Err ErrHeaderProc PutBlanks PutAddress PutName // MDload AllocInbuf OpenSource DoFixups Load LoadFile dataIM0; dataIM1; dataIM2 dataRM; dataIFUM; dataALUFM dataDISP; dataIMLOCK; dataIMMASK dataOther; dataSkip @mData @mWidths @mNames @mSymMax fixTab @Symbols; @SymLength // MDload0 sourceNameWidth ] structure V: // VERSION parameter [ machine byte version byte ] structure S0: // first word of symbol [ blank bit 1 char0 bit 7 blank bit 1 char1 bit 7 ] manifest [ nHash = 26 ] static [ maxMemX = 0 verMemX = -1 mCounts mSeen fixSyms nFix = 0 @fixPtr = 0 @outstrm; @outmemx = -1; @outaddr = -1 ] let Load1(sources, outs, tempzone, zone) be [ Symbols = Allocate(zone, SymLength) mNames = Allocate(zone, nMemX) mNames!IMmemx = "IM" mNames!RMmemx = "RM" mWidths = Allocate(zone, nMemX) SetBlock(mWidths, -1, nMemX) mData = Allocate(zone, nMemX) SetBlock(mData, dataOther, nMemX) mCounts = Allocate(tempzone, nMemX) Zero(IM, IMsize*lIM) Zero(RM, RMsize) mSeen = Allocate(tempzone, nMemX) SetBlock(mSeen, false, nMemX) mSymMax = Allocate(zone, nMemX) SetBlock(mSymMax, -1, nMemX) AllocInbuf(tempzone, 2000b) fixSyms = Allocate(tempzone, nHash) Load(sources, outs, tempzone, zone, LoadFile1) if verMemX ge 0 then mData!verMemX = dataSkip Version = (Version ls 0? 0, Version<>Source.pName source>>Source.niFirst = NInstructions source>>Source.niLast = NImax // in case of error outstrm = outs let load1EHP(s) be [ PutTemplate(s, "In $S:*N", sourceName) ErrHeaderProc = 0 ] ErrHeaderProc = load1EHP LoadFile(s, tempzone, zone, data1, sym1, mem1, fix1, xfix1) ErrHeaderProc = 0 Closes(s) source>>Source.niLast = NInstructions Err(PassMessage, "$S$P$6UOb instructions written $S", sourceName, PutBlanks, sourceNameWidth-sourceName>>BS.length, NInstructions-source>>Source.niFirst, source>>Source.pDate) ] and mem1(mdp, bp, zone) be [ let memx, width = mdp!1, mdp!2 if (memx le 0) % (memx ge nMemX) then Err(Fatal, "Illegal memory #$UO", memx) mWidths!memx = width let sp = mdp+3 let s = Allocate(zone, bp-sp) let n = 0 until sp>>bytes^n eq 0 do [ s>>BS.char^(n+1) = sp>>bytes^n n = n+1 ] s>>BS.length = n memname(memx, s) let imwidth = nil // width of IM in output if memx eq IMmemx then // decide which machine [ switchon width into [ case 80: // Dorado model 0 case 96: // Dorado model 1 DMachine, maxMemX = width/48, 4 // = 1 or 2 imwidth = width-32 // = 48 or 64 mWidths!IFUMmemx = 32 mWidths!ALUFMmemx = 8 memname(IFUMmemx, "IFUM") memname(ALUFMmemx, "ALUFM") mData!IFUMmemx = dataIFUM mData!ALUFMmemx = dataALUFM mData!IMmemx = (width eq 80? dataIM1, dataIM2) endcase case 84: // D0 DMachine, maxMemX = 0, 2 imwidth = 64 mData!IMmemx = dataIM0 endcase default: maxMemX = 0 // illegal ] if (Version ge 0) & (DMachine ne Version<>Sym.memx = memx sval>>Sym.addr = addr if sval>>Sym.addr ne addr then Err(NonFatal, "$S symbol $P = $UO, >7777 not allowed", mNames!memx, PutName, sp, addr) if (memx ne IMmemx) & (addr gr mSymMax!memx) then mSymMax!memx = addr ] and fix1(bp) be // Fixup for unknown memory -- just copy WriteBlock(outstrm, bp, 5) and xfix1(ap, bp, zone) be [ let memx, addr, field = ap!1, ap!2, ap!3 let sp = ap+4 let lvptr = fixSyms+(@sp rem nHash) let sym = AddSym(sp, lvptr, zone, 3) if sym!-1 ls 0 then // new entry [ sym!-3, sym!-2, sym!-1 = WNull, WNull, WNull nFix = nFix+1 ] test (memx eq IMmemx) & ((field eq W1field) % (field eq W2field)) ifso [ let ip = IP(addr) test field eq W1field ifso [ ip>>IM.W1 = sym!-1; sym!-1 = addr ] ifnot [ ip>>IM.W2 = sym!-2; sym!-2 = addr ] ] ifnot test (memx eq IFUMmemx) & (field eq IFADfield) ifso [ (IFUM+addr*lIFUM)>>IFUM.IFAD = sym!-3; sym!-3 = addr ] ifnot test memx eq IMmemx ifso Err(PassFatal, "$P....External reference to $P", PutAddress, addr, PutName, sp) ifnot Err(PassFatal, "$S $UO....External reference to $P", mNames!memx, addr, PutName, sp) ] and StringEqual(s1, s2) = valof [ let n1 = s1>>BS.length if s2>>BS.length ne n1 resultis false for i = 1 to n1 do if s1>>BS.char^i ne s2>>BS.char^i resultis false resultis true ] and ResolveSyms(proc, skipval) be // Resolve external references [ if nFix ne 0 then for i = 0 to nHash-1 do [ let lvsym = fixSyms+i while @lvsym ne 0 do [ let sym, value = @lvsym, nil let rsym = FindSym(sym+1) test rsym ne 0 ifso [ value = (rsym!-1)<>IM.W1 if value ne skipval then ip>>IM.W1 = value ] addr = sym!-2 until addr eq WNull do [ if value eq WExt then [ proc(addr+100000b, sym); fixPtr = fixPtr+2 ] let ip = IP(addr) addr = ip>>IM.W2 if value ne skipval then ip>>IM.W2 = value ] addr = sym!-3 until addr eq WNull do [ if value eq WExt then [ proc(addr+140000b, sym); fixPtr = fixPtr+2 ] let ip = IFUM+addr*lIFUM addr = ip>>IFUM.IFAD if value ne skipval then ip>>IFUM.IFAD = value ] ] and storefix(addr, sym) be @fixPtr, fixPtr!1 = addr, sym and FindSym(sp) = valof // Look up a symbol in Symbols, return 0 if missing. // The symbol is already in internal format (end marked by bit 0). [ let s0 = @sp let c0 = s0<