DIRECTORY Basics, FS, IO, RefText USING [line, AppendChar], Rope, MDDefs, MDGlobalVars, MDOps, MDUtils; MDLoadBinImpl: CEDAR PROGRAM IMPORTS Basics, FS, IO, RefText, Rope, MDGlobalVars, MDOps, MDUtils EXPORTS MDOps = BEGIN OPEN MDDefs, MDGlobalVars, MDUtils; fixes: LIST OF Symbol; verbose: BOOL _ FALSE; LoadBinaryFiles: PUBLIC PROC[srcList: SrcFile] RETURNS[ok: BOOL] = { undefList: LIST OF Symbol _ NIL; MDOps.InitSymbolTable[]; memDescArray _ ALL[NIL]; memDescArray[IMmemx] _ NEW[MemDescObj _ [name: "IM", widthInBits: 96]]; memDescArray[RMmemx] _ NEW[MemDescObj _ [name: "RM", widthInBits: 16]]; nInstructions _ 0; nIFUInstructions _ 0; imMask _ NIL; fixes _ NIL; -- forget previous fixes IF outFile.fullName # NIL THEN outFile.strm _ FS.StreamOpen[outFile.fullName, $create]; FOR src: SrcFile _ srcList, src.next UNTIL src = NIL DO LoadOneFile[src]; src.niLast _ nInstructions; MDOps.Report[infoOnly, "%g\t%bb instructions \twritten %g\n", IO.rope[src.fullName], IO.int[src.niLast - src.niFirst], IO.time[src.createDate]]; ENDLOOP; MDOps.Report[infoOnly, "\n\tTotal of %bb instructions\n\n", IO.int[nInstructions]]; FOR i: INTEGER IN [1.. nMemX) DO memDesc: MemDescRecord = memDescArray[i]; IF memDesc = NIL OR memDesc.count = 0 THEN LOOP; MDOps.Report[infoOnly, "%bb words in %g\n", IO.int[memDesc.count], IO.rope[memDesc.name] ]; ENDLOOP; FOR fx: LIST OF Symbol _ fixes, fx.rest UNTIL fx = NIL DO symb: Symbol = fx.first; IF symb.memNum = -1 THEN undefList _ CONS[symb, undefList]; ENDLOOP; IF undefList # NIL THEN { IF external THEN MDOps.Report[infoOnly, "\n *** external symbols:\n\t"] ELSE MDOps.Report[infoOnly, "\n *** undefined symbols:\n\t"]; FOR sL: LIST OF Symbol _ undefList, sL.rest UNTIL sL = NIL DO MDOps.Report[infoOnly, " %g", IO.rope[sL.first.name]]; ENDLOOP; IF ~external THEN { MDOps.Report[infoOnly, "\n\t\t quitting\n"]; RETURN[FALSE]; }; }; FOR fx: LIST OF Symbol _ fixes, fx.rest UNTIL fx = NIL DO symb: Symbol = fx.first; FOR fr: FixupRecord _ symb.fixup, fr.next UNTIL fr = NIL DO SELECT fr.fieldDesc FROM im1Field => TRUSTED { MDUtils.IMPtr[fr.addr].wx1.W1AddrAndGroupLink _ symb.labelAddr; }; im2Field => TRUSTED { MDUtils.IMPtr[fr.addr].wx2.W2AddrAndbLink _ symb.labelAddr; }; ifField => TRUSTED { fixPtr: MDDefs.IFUMRecordPtr = MDUtils.IFUMPtr[fr.addr]; fixPtr.ifumWord0.ifad _ symb.labelAddr; }; null => ERROR; ENDCASE => ERROR; ENDLOOP; ENDLOOP; TRUSTED { FOR i: CARDINAL IN [0..nInstructions) DO imPtr: MDDefs.IMRecordPtr = MDUtils.IMPtr[i]; IF imPtr.wx1.W1AddrAndGroupLink = WNext THEN imPtr.wx1.W1AddrAndGroupLink _ i+1; IF imPtr.wx2.W2AddrAndbLink = WNext THEN imPtr.wx2.W2AddrAndbLink _ i+1; imPtr.word0 _ imPtr.wx0; imPtr.word1 _ imPtr.wx1; imPtr.word2 _ imPtr.wx2; ENDLOOP; }; RETURN[TRUE]; }; FieldDesc: TYPE = MACHINE DEPENDENT RECORD [firstBit (0: 0..7): [0..377B], encoded (0: 8..15): [0..377B] ]; -- encoded = nBits+firstBit-1 W1FieldDesc: FieldDesc = [firstBit: 4*16+4, encoded: 12+(4*16+4)-1]; W2FieldDesc: FieldDesc = [firstBit: 5*16+4, encoded: 12+(5*16+4)-1]; IFADfield: FieldDesc = [firstBit: 4, encoded: 12+4-1]; OneMinusWNull: WORD = 170001B; MDataDispArray: TYPE = ARRAY [0..nMemX) OF mDataDisp; mDataDisp: TYPE = { dataIFUM, dataALUFM, dataIM, dataRM, dataDISP, dataIMLOCK, dataSkip, dataIMMASK, dataOther }; mDataArray: MDataDispArray _ ALL[dataOther]; verMemX: INTEGER _ -1; LoadOneFile: PROC[src: SrcFile] = { inStrm: STREAM = FS.StreamFromOpenFile[src.of]; iBase: CARDINAL _ nInstructions; memNum: INTEGER _ 0; addr: CARDINAL _ 0; AdjustAddr: PROC[w: WORD] RETURNS [new: WORD] = { w1: WORD _ Basics.BITAND[w, LOOPHOLE[IMsize-1]]; IF w1 = WNull THEN new _ LOOPHOLE[addr, WORD] + OneMinusWNull + w ELSE new _ LOOPHOLE[iBase, WORD] + w; }; src.niFirst _ nInstructions; src.niLast _ NImax; -- in case of error DO blkType: INTEGER _ GetInteger[inStrm]; SELECT blkType FROM MBend => { inStrm.Close[]; -- this will close the FS.OpenFile too src.of _ FS.nullOpenFile; EXIT }; -- so can set breakppoint MBdata => { thisAddr: CARDINAL _ addr; addr _ addr + 1; [] _ GetWord[inStrm]; -- line number, ignore for all SELECT mDataArray[memNum] FROM dataOther => DataProc[inStrm, memNum, thisAddr]; dataIM => TRUSTED { -- Dorado model 1 only imPtr: IMRecordPtr = IMPtr[thisAddr]; imPtr.imw0 _ GetWord[inStrm]; imPtr.imw1 _ GetWord[inStrm]; imPtr.imw2 _ GetWord[inStrm]; imPtr.wx0 _ LOOPHOLE[GetWord[inStrm]]; imPtr.wx1 _ LOOPHOLE[GetWord[inStrm]]; imPtr.wx2 _ LOOPHOLE[GetWord[inStrm]]; imPtr.wx1 _ LOOPHOLE[AdjustAddr[LOOPHOLE[imPtr.wx1]]]; imPtr.wx2 _ LOOPHOLE[AdjustAddr[LOOPHOLE[imPtr.wx2]]]; IF nInstructions # thisAddr THEN MDOps.Report[fatalError, "%g ....Imaginary addresses not consecutive (%g follows %g)\n", IO.int[nInstructions], IO.int[thisAddr], IO.int[nInstructions-1]]; nInstructions _ thisAddr + 1; IF nInstructions > NImax THEN IMFull[]; }; dataIFUM => TRUSTED { ifum0: IFUMWord0 _ LOOPHOLE[GetWord[inStrm]]; ifumPtr: IFUMRecordPtr _ MDUtils.IFUMPtr[thisAddr]; IF ifumBits[thisAddr] THEN MDOps.Report[fatalError, "\n*** Attempt to load IFUM[%g] twice\n", IO.int[thisAddr]]; IF ifum0.ifad # WNull THEN ifum0.ifad _ ifum0.ifad+iBase; IF thisAddr >= nIFUInstructions THEN nIFUInstructions _ thisAddr + 1; ifumBits[thisAddr] _ TRUE; ifumPtr.ifumWord0 _ ifum0; ifumPtr.otherData _ GetWord[inStrm]; }; dataALUFM => TRUSTED { alufmBits[thisAddr] _ TRUE; (alufmArrayHead+thisAddr)^ _ GetWord[inStrm]; }; dataRM => TRUSTED { val: WORD = GetWord[inStrm]; IF rmBits[thisAddr] AND ((rmArrayHead+thisAddr)^ # val) THEN MDOps.Report[infoOnly, "\n*** Attempt to load RM[%g] twice\n", IO.int[thisAddr]]; (rmArrayHead+thisAddr)^ _ val; rmBits[thisAddr] _ TRUE; }; dataIMLOCK => { bits: INTEGER _ GetInteger[inStrm]; imLocked[thisAddr] _ (bits < 0); -- testing high order bit }; dataIMMASK => { msk: IMMask _ NEW[IMMaskRec _ [next: imMask, addr: thisAddr+iBase]]; msk.mask _ GetWord[inStrm]; msk.mSeq _ Basics.BITSHIFT[GetWord[inStrm], -12]; -- rshift imMask _ msk; }; dataDISP => [] _ GetWord[inStrm]; -- DISP - not defined yet dataSkip => FOR i: INTEGER IN [0..memDescArray[memNum].wordsOfData) DO [] _ GetWord[inStrm]; ENDLOOP; ENDCASE => NULL; }; MBaddress => { memNum _ GetInteger[inStrm]; IF memNum = IMmemx THEN { addr _ GetCardinal[inStrm] + iBase; IF addr > NImax THEN IMFull[]; } ELSE addr _ GetWord[inStrm]; }; MBfixup => TRUSTED { -- forward reference thisMem: INTEGER _ GetInteger[inStrm]; thisAddr: CARDINAL _ GetCardinal[inStrm]; fieldDesc: FieldDesc _ LOOPHOLE[GetWord[inStrm]]; val: WORD _ GetWord[inStrm]; SELECT thisMem FROM IMmemx => { IF fieldDesc = W1FieldDesc THEN MDUtils.IMPtr[iBase+thisAddr].wx1.W1AddrAndGroupLink _ val _ val + iBase; IF fieldDesc = W2FieldDesc THEN MDUtils.IMPtr[iBase+thisAddr].wx2.W2AddrAndbLink _ val _ val + iBase; LOOP; }; IFUMmemx => { -- check pass fixPtr: IFUMRecordPtr = MDUtils.IFUMPtr[thisAddr]; IF fieldDesc = IFADfield THEN val _ val + iBase; fixPtr.ifumWord0.ifad _ val; }; ALUFMmemx => (alufmArrayHead+thisAddr)^ _ val; RMmemx => (rmArrayHead+thisAddr)^ _ val; ENDCASE => { FixProc[thisMem, thisAddr, fieldDesc, val]; }; }; MBmemory => { memNum: INTEGER = GetInteger[inStrm]; widthInBits: INTEGER = GetInteger[inStrm]; symName: ROPE = ReadSymName[inStrm]; MemoryProc[memNum, widthInBits, symName]; }; MBsymbol => { thisMem: INTEGER = GetInteger[inStrm]; val: WORD _ GetWord[inStrm]; symName: ROPE = ReadSymName[inStrm]; symbol: Symbol; IF thisMem = IMmemx THEN val _ val + iBase; symbol _ SymbolProc[thisMem, symName, val]; IF thisMem = IMmemx THEN TRUSTED { MDUtils.IMPtr[val].symbol _ symbol }; }; MBexternalfixup => { memNum: INTEGER = GetInteger[inStrm]; loc: CARDINAL _ GetWord[inStrm]; bits: WORD _ GetWord[inStrm]; -- don't need to fix (see mdLoad.bcpl) symName: ROPE _ ReadSymName[inStrm]; IF memNum = IMmemx THEN loc _ loc + iBase; ExternalFixProc[symName, memNum, loc, bits]; }; ENDCASE => NULL; ENDLOOP; }; IMFull: PROC = { MDOps.Report[fatalError, "\n ***IM is full - quitting\n"] }; scratch: REF TEXT _ NEW[TEXT[RefText.line]]; ReadSymName: PROC[fx: STREAM] RETURNS[ROPE] = { scratch.length _ 0; DO ch: CHAR = fx.GetChar[]; IF ch = '\000 THEN EXIT; scratch _ RefText.AppendChar[scratch, ch]; ENDLOOP; IF fx.GetIndex[] MOD 2 = 1 THEN [] _ fx.GetChar[]; RETURN[Rope.FromRefText[scratch]]; }; outMemx: INTEGER _ -1; outAddr: CARDINAL _ 177777B; MachineVersion: TYPE = MACHINE DEPENDENT RECORD[ machine: [0..377B], version: [0..377B] ]; version: MachineVersion _ [377B, 377B]; DMachine: [0..377B] _ 2; -- Dorado Model 1 DataProc: PROC[inStrm: STREAM, memNum: INTEGER, addr: CARDINAL] = { IF memNum = verMemX THEN { fv: WORD = GetWord[inStrm]; fileV: MachineVersion = LOOPHOLE[fv]; IF ((version.machine < 377B) AND (version # fileV)) OR (fileV.machine # DMachine) THEN MDOps.Report[fatalError, "\n *** File says VERSION = %bB -- disagrees with IM width\n", IO.card[fv]]; version _ fileV; } ELSE { mem: MemDescRecord = memDescArray[memNum]; IF mem.seen THEN { IF (memNum # outMemx) OR (addr # outAddr+1) THEN { PutInteger[outFile.strm, MBaddress]; PutInteger[outFile.strm, memNum]; PutCardinal[outFile.strm, addr]; }; outMemx _ memNum; outAddr _ addr; PutInteger[outFile.strm, MBdata]; PutInteger[outFile.strm, memNum]; FOR i: INTEGER IN [0..mem.wordsOfData) DO PutWord[outFile.strm, GetWord[inStrm]]; ENDLOOP; mem.count _ mem.count + 1; } ELSE { IF memNum = 0 THEN MDOps.Report[fatalError, "\n *** Data word before address set\n"] ELSE MDOps.Report[fatalError, "\n *** Data for unknown memory %g", IO.int[memNum]]; }; }; }; MemoryProc: PROC[memNum, widthInBits: INTEGER, symName: ROPE] = { mem: MemDescRecord; maxMemX: INTEGER = 4; -- since we know its a dorado IF memNum <= 0 OR memNum > nMemX THEN MDOps.Report[fatalError, "\n *** Illegal memory #%g\n", IO.int[memNum]]; mem _ memDescArray[memNum]; IF mem = NIL THEN { mem _ memDescArray[memNum] _ NEW[MemDescObj]; mem.widthInBits _ widthInBits; mem.wordsOfData _ (widthInBits+15)/16; mem.name _ symName; } ELSE { -- check for idential definition IF ~symName.Equal[mem.name, FALSE] THEN MDOps.Report[fatalError, "\n *** Memory #%g (%g) redefined as %g\n", IO.int[memNum], IO.rope[mem.name], IO.rope[symName]]; IF widthInBits # mem.widthInBits THEN MDOps.Report[fatalError, "\n *** Memory #%g not valid %g\n", IO.int[memNum], IO.rope[symName]]; }; IF memNum = IMmemx THEN { other: MemDescRecord _ memDescArray[IFUMmemx]; IF other = NIL THEN { memDescArray[IFUMmemx] _ other _ NEW[MemDescObj]; other.name _ "IFUM"; other.widthInBits _ 32; }; other _ memDescArray[ALUFMmemx]; IF other = NIL THEN { memDescArray[ALUFMmemx] _ other _ NEW[MemDescObj]; other.name _ "ALUFM"; other.widthInBits _ 8; }; mDataArray[IMmemx] _ dataIM; mDataArray[RMmemx] _ dataRM; mDataArray[ALUFMmemx] _ dataALUFM; mDataArray[IFUMmemx] _ dataIFUM; }; IF memNum > maxMemX THEN -- must be unknown or fake SELECT TRUE FROM symName.Equal["DISP", FALSE] => { mDataArray[memNum] _ dataDISP; RETURN }; symName.Equal["IMLOCK", FALSE] => { mDataArray[memNum] _ dataIMLOCK; RETURN }; symName.Equal["RVREL", FALSE] => { mDataArray[memNum] _ dataSkip; RETURN }; symName.Equal["VERSION", FALSE] => { verMemX _ memNum; RETURN }; symName.Equal["IMMASK", FALSE] => { mDataArray[memNum] _ dataIMMASK; RETURN }; ENDCASE => NULL; IF mem.seen THEN RETURN; mem.seen _ TRUE; IF memNum = IMmemx THEN MDOps.WriteMemoryDef[memNum, 64, symName] ELSE MDOps.WriteMemoryDef[memNum, mem.widthInBits, symName]; }; SymbolProc: PROC[memNum: INTEGER, symName: ROPE, addr: CARDINAL] RETURNS[symbol: Symbol] = { mem: MemDescRecord = memDescArray[memNum]; symbol _ NIL; IF ~mem.seen THEN RETURN; -- skip DISP, IMLOCK, RVREL, VERSION symbol _ MDOps.AddSym[symName]; IF symbol.memNum # -1 THEN { -- check for redefn IF symbol.memNum # memNum THEN MDOps.Report[fatalError, "\n *** Symbol %g redefined from memory %g to %g\n", IO.rope[symName], IO.int[symbol.memNum], IO.int[memNum]]; IF symbol.labelAddr # addr AND verbose THEN MDOps.Report[infoOnly, "\n *** Symbol %g in memory %g redefined from addr %g to %g\n", IO.rope[symName], IO.int[symbol.memNum], IO.int[symbol.labelAddr], IO.int[addr]]; }; symbol.memNum _ memNum; symbol.labelAddr _ addr; IF (memNum # IMmemx) AND (addr > mem.symMaxAddr) THEN mem.symMaxAddr _ addr; }; FixProc: PROC[memNum: INTEGER, addr: CARDINAL, fieldDesc: FieldDesc, val: WORD] = { PutInteger[outFile.strm, MBfixup]; PutInteger[outFile.strm, memNum]; PutCardinal[outFile.strm, addr]; PutWord[outFile.strm, LOOPHOLE[fieldDesc]]; PutWord[outFile.strm, val]; }; ExternalFixProc: PROC[symName: ROPE, memNum: INTEGER, loc, bits: WORD] = { fieldDesc: FieldDesc = LOOPHOLE[bits]; which: ExtFixField _ null; symb: Symbol _ MDOps.AddSym[symName]; newFixup: FixupRecord; prev: FixupRecord; IF (memNum = IMmemx) THEN { SELECT fieldDesc FROM W1FieldDesc => which _ im1Field; W2FieldDesc => which _ im2Field; ENDCASE => MDOps.Report[fatalError, "\n *** %g....External reference to %g\n", IO.card[loc], IO.rope[symName]]; } ELSE IF (memNum = IFUMmemx) AND (fieldDesc = IFADfield) THEN which _ ifField; IF which = null THEN { mem: MemDescRecord = memDescArray[memNum]; MDOps.Report[fatalError, "\n *** %g %g ... External reference to %g", IO.rope[mem.name], IO.card[loc], IO.rope[symName]]; }; newFixup _ NEW[FixupRec _ [memNum, which, loc, prev _ symb.fixup]]; symb.fixup _ newFixup; IF prev = NIL THEN fixes _ CONS[symb, fixes]; -- first fixup for this symbol }; END. ¬MDLoadBinImpl.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Willie-Sue, September 29, 1987 4:34:19 pm PDT taken from mdload1.bcpl check for undefined sumbols make another pass over IM, changing .+1 encoding into imaginary addr the following to agree with Micro's notion of fields adjust W1 and W2 addresses Copy memory def to output Save symbols for later output Fixup for unknown memory - just copy Κ!˜šœ™Icodešœ Οmœ1™Jšœžœ˜6Jšžœ˜—šžœ ž˜Jšœ,˜,Jšžœžœ˜J˜—J˜—J˜š žœžœžœžœžœž˜9J˜šžœ'žœžœž˜;šžœž˜šœ žœ˜Jšœ?˜?J˜—šœ žœ˜Jšœ;˜;J˜—šœ žœ˜Jšœ8˜8Jšœ'˜'J˜—Jšœžœ˜Jšžœžœ˜—Jšžœ˜—Jšžœ˜—J˜JšœD™Dšžœ˜ šžœžœžœž˜(J˜-šžœ&ž˜,Jšœ$˜$—šžœ"ž˜(Jšœ ˜ —Jšœ˜Jšœ˜Jšœ˜Jšžœ˜—J˜—J˜Jšžœžœ˜ J˜—J˜šœ žœžœž œž˜*JšœA ˜^—J™Jšœ4™4JšŸ œ9˜DJšŸ œ9˜DJšŸ œ-˜6JšŸ œžœ ˜J˜Jšœžœžœ žœ ˜5šœ žœ˜JšœD˜DJšœ˜Jšœ˜—JšŸ œžœ ˜,Jšœ žœ˜J˜šŸ œžœ˜#Jšœžœžœ˜/Jšœžœ˜ Jšœžœ˜Jšœžœ˜š Ÿ œžœžœžœžœ˜1Jšœžœ žœžœ ˜0šžœ žœžœžœ˜AJšžœžœžœ˜%—J˜—Jšœ˜Jšœ ˜(J˜šž˜Jšœ žœ˜&šžœ ž˜šœ ˜ Jšœ &˜7Jšœ žœ˜Jšž˜Jšœ ˜—šœ ˜ Jšœ žœ˜Jšœ˜Jšœ ˜5šžœž˜Jšœ0˜0šœ žœ ˜+Jšœ%˜%Jšœ˜Jšœ˜Jšœ˜Jšœ žœ˜&Jšœ žœ˜&Jšœ žœ˜&Jšœ™Jšœ žœ žœ˜6Jšœ žœ žœ˜6J˜šžœž˜ šœ˜J˜?Jšžœžœžœ˜B——Jšœ˜Jšžœžœ ˜'J˜—šœ žœ˜Jšœžœ˜-Jšœ3˜3šžœž˜šœ˜Jšœ*žœ˜<——Jšžœžœ˜9Jšžœžœ!˜EJšœžœ˜Jšœ˜Jšœ$˜$J˜—šœ žœ˜Jšœžœ˜Jšœ-˜-Jšœ˜—šœ žœ˜Jšœžœ˜šžœžœ!ž˜<šœ˜Jšœ(žœ˜:——Jšœ˜Jšœžœ˜Jšœ˜—˜Jšœžœ˜#Jšœ" ˜;J˜—˜Jšœžœ3˜DJšœ˜Jšœžœ  ˜˜>—J˜Jš œ žœžœžœžœ˜,J˜š Ÿ œžœžœžœžœ˜/J˜šž˜Jšœžœ˜Jšžœ žœžœ˜Jšœ+˜+Jšžœ˜—Jšžœžœžœ˜2Jšžœ˜"J˜—J˜Jšœ žœ˜Jšœ žœ ˜š œžœžœž œžœ˜0J˜J˜J˜—Jšœ'˜'Jšœ ˜+J˜š Ÿœžœ žœ žœžœ˜Cšžœžœ˜Jšœžœ˜Jšœžœ˜%šžœžœž˜6šœž˜šœ˜Jšœ>˜>Jšžœ ˜ ———Jšœ˜J˜šžœ˜J˜*šžœ žœ˜šžœžœžœ˜2Jšœ$˜$Jšœ!˜!Jšœ ˜ J˜—Jšœ˜Jšœ˜Jšœ!˜!Jšœ!˜!šžœžœžœž˜)Jšœ'˜'Jšžœ˜—Jšœ˜—J˜šžœ˜šžœ ž˜JšœA˜Ašž˜šœ˜Jšœ%žœ˜5———J˜—J˜——J˜—J˜šŸ œžœžœ žœ˜AJšœ˜Jšœ žœ ˜4šžœ žœž˜%Jšœ8žœ˜H—Jšœ˜šžœžœžœ˜Jšœžœ ˜-Jšœ˜Jšœ&˜&Jšœ˜J˜šžœ  ˜(šžœžœž˜'šœD˜DJšžœžœžœ˜5——šžœž˜%šœ<˜