// MDmain.bcpl -- main program for MicroD
// last edited February 2, 1981 3:15 PM
get "mddecl.d"
get "streams.d"
get "altofilesys.d"
get "sysdefs.d"
get "bcplfiles.d"
external [ // defined here
@IP
// statics
@DMachine
@OutputS; @MBS; @ErrDspS
@TempZone; @Zone
// Memories
@IM; @SaveW2; @IMlocked; @NInstructions; @IMMASK
@RM; @RMbits
@IFUM; @IFUMbits; @NIFUM
@ALUFM; @ALUFMbits
// for Err
End
AbortCode; NErrors; NWarnings; errMax
SourceFiles
// for MDmisc
OverlayCFA; lvOverlayLoc; lOverlaySz
]
external [
// OS
Allocate
Closes; CounterJunta; CreateDiskStream
Free
MoveBlock
Noop
Puts
ReadBlock; ReadCalendar
SetBlock; SetFilePos; ShowDisplayStream
TruncateDiskStream
Usc
WriteBlock; Ws; Wss
Zero
dsp
OsFinishSafeAdr
// EasyJunta
EasyJunta
// Template
PutTemplate
// GetSetBits
GetBits
// BcplRuntime and LoadRam
InitBcplRuntime
LoadRam
RamImage
// PrintMB
PrintMB
// MDmisc
NextOverlay
// for initialization
GetLow; PutLow
GetStorage; PutStorage
RealPutTS
// Statics
PutTS
@Storage; @EndStorage
MinSpace
RealMin
// MDerr
Err
Show
// MDinit
Init
// Statics (flags & parameters)
DebugFlag
DebugFirstLoc
DebugLastLoc
ListingLevel
ListAbs
MapChart
MapIM
MapRM
MapOccupied
ListSymbols
TraceStorage
ScratchSource
DeleteScratch
// MDload/0/1
Load; Load0; Load1
OpenSource
@Symbols; @SymLength
// MDprescan
PreScan
// MDscan
Scan
// MDlink
Link
// MDalist
BuildALists
// MDassign
Assign
WritePlaceStats
// MDcheck
Check
// MDfixup
FixupJCN
// MDDump
Dump
LinkSyms
DumpSyms
// MDlist
OpenListFile
ListIM
ListIMAbs
ListIMUsed
ListOccupied
ListIMap
ListChart
ListRM
ListNonIM
ListOtherSyms
]
manifest [
lvCodeTop = #335
StackSize = 3400b
lSysZone = lDS+10 // only needed for display stream structure
lErrStr = 120 // for errors before OutputS is opened
]
static [
DMachine = -1
AbortCode = -1; NErrors = 0; NWarnings = 0; errMax = 50
@OutputS; @MBS; @ErrDspS; @ScratchS
@TempZone; @Zone
Format
StartTime
TotalTime
saveDsp
dpasses
SourceFiles
@ErrStr; @ErrPos = 0
//
OverlayCFA
lvOverlayLoc
lOverlaySz = lKS+400b
//
IM; SaveW2; IMlocked; NInstructions; IMMASK
RM; RMbits
IFUM; IFUMbits; NIFUM
ALUFM; ALUFMbits
]
let MicroD(blv, nil, cfa) be
[ StartTime = seconds()
saveDsp = dsp
let save = vec (lCFA+lBLV)
MoveBlock(save, cfa, lCFA)
MoveBlock(save+lCFA, blv, lBLV)
EasyJunta(levStreams, microd1, save, lCFA+lBLV, lSysZone)
]
and microd1(save) be // called after Junta
[ OverlayCFA = save
lvOverlayLoc = lv (OverlayCFA+lCFA)>>BLV.overlayAddress↑0
// Initialize storage
Storage = EasyJunta
EndStorage = (lv save)-StackSize
@lvCodeTop = EndStorage
let zone = vec 2
zone!0 = GetStorage
zone!1 = PutStorage
Zone = zone
let lowzone = vec 2
lowzone!0 = GetLow
lowzone!1 = PutLow
TempZone = lowzone
PutTS = Noop
OpenListFile = 0 // for optional loading of final overlay
// Code for each phase gets returned to storage after execution
ErrStr = Allocate(zone, (lErrStr+2)/2)
let eds = vec lST
ErrDspS = eds
ErrDspS>>ST.puts = ErrPuts
let IP(i) = IM+i*lIM
compileif lIM ne 6 then [ lIMne6 = 0 ] // cause error
IP = table[ // replace by assembly code
#105120 // MOVZL 0 1
#123120 // ADDZL 1 0
0 // LDA 1 IM
#123000 // ADD 1 0
#1401 // JMP 1 3
]
IP!2 = #24000 + lv IM
SourceFiles = Init()
if TraceStorage then PutTS = RealPutTS
if LoadRam(RamImage) eq 0 then InitBcplRuntime()
if ListingLevel eq listPrintMB then // just list the input files
[ EndPass(Init)
static [ pinst = 0 ]
let listmb(source, out, nil, pzone) be
[ let s = OpenSource(source)
pinst = PrintMB(s, out, pzone, pinst)
Closes(s)
]
Load(SourceFiles, OutputS, lowzone, zone, listmb)
End()
]
EndPass(PrintMB, false)
dpasses = DebugFlag
Load0(SourceFiles, MBS, lowzone, zone)
EndPass(Load0, false)
IM = Allocate(zone, IMsize*lIM)
IMlocked = Allocate(zone, IMsize/16)
Zero(IMlocked, IMsize/16)
allocmem(lowzone)
IFUM = Allocate(lowzone, IFUMsize*lIFUM)
for i = 0 to IFUMsize-1 do
(IFUM+i*lIFUM)>>IFUM.IFAD = WNull
Load1(SourceFiles, MBS, lowzone, zone)
let format1 = ";;;!@GP;rcjf;bgk2;"
Format = format1
ScratchS = CreateDiskStream(ScratchSource>>Source.pFP, ksTypeReadWrite, wordItem, 0, 0, zone)
WriteBlock(ScratchS, IM, NInstructions*lIM)
sxfer(WriteBlock)
EndPass(Load, true)
NextOverlay()
if NIFUM ne 0 then // reload IFUM for Scan
[ SetFilePos(ScratchS, 0, NInstructions*(lIM*2)) // *2 because byte position
IFUM = Allocate(lowzone, NIFUM*lIFUM)
ReadBlock(ScratchS, IFUM, NIFUM*lIFUM)
]
Scan() // Mark IFU entries, check common errors
EndPass(Scan, false)
Link(zone) //Setup branch linkages
Format = "sa--;;;IWGP;rcjf;mgk-;"
EndPass(Link, true)
BuildALists(zone) //Form allocation lists
EndPass(BuildALists, true)
NextOverlay()
Assign(lowzone)
if TraceStorage then WritePlaceStats(OutputS)
test AbortCode ge 0
ifso // Still want storage map
[ let code = AbortCode
AbortCode = -1
EndPass(Assign, true)
NextOverlay()
ListIMUsed(OutputS, true)
doList(MapIM, lv ListIMap)
AbortCode = code
End()
]
ifnot
EndPass(Assign, true)
Err(PassMessage, "Reloading binaries...")
SetFilePos(ScratchS, 0, 0)
reloadIM(ScratchS, lowzone)
allocmem(zone)
IFUM = Allocate(zone, NIFUM*lIFUM) // Only allocate amount needed
sxfer(ReadBlock)
if DeleteScratch then
[ SetFilePos(ScratchS, 0, 0)
TruncateDiskStream(ScratchS)
]
Closes(ScratchS)
Format = format1
EndPass(0, true)
NextOverlay()
Check()
EndPass(Check, false)
FixupJCN()
Dump(MBS, lowzone)
DumpSyms(MBS, Symbols, SymLength, lowzone)
Puts(MBS, MBend)
CloseMBS()
LinkSyms(Symbols, SymLength, zone)
ListIM(OutputS, SourceFiles)
ListIMUsed(OutputS, false)
ListNonIM(OutputS, ListingLevel)
if ListSymbols then
[ if ListingLevel ls 0 then ListRM(OutputS)
ListOtherSyms(OutputS)
]
EndPass(Dump, true)
doList(ListAbs, lv ListIMAbs)
doList(MapIM, lv ListIMap)
doList(MapOccupied, lv ListOccupied)
doList(MapChart, lv ListChart)
doList(MapRM, lv ListRM)
End()
]
and doList(Source, lvProc) be
if Source ne 0 then
[ if OpenListFile eq 0 then NextOverlay() // don't load overlay until needed
let s = OpenListFile(Source, TempZone)
(@lvProc)(s, SourceFiles)
Closes(s)
]
and allocmem(z) be
[ RM = Allocate(z, RMsize)
RMbits = Allocate(z, RMsize/16)
IFUMbits = Allocate(z, IFUMsize/16)
ALUFM = Allocate(z, ALUFMsize)
ALUFMbits = Allocate(z, ALUFMsize/16)
Zero(RMbits, RMsize/16)
Zero(IFUMbits, IFUMsize/16)
Zero(ALUFMbits, ALUFMsize/16)
]
and reloadIM(S, z) be
[ let savew0 = Allocate(z, NInstructions)
for i = 0 to NInstructions-1 do savew0!i = IP(i)>>IM.W0word & W0mask
ReadBlock(S, IM, NInstructions*lIM)
for i = 0 to NInstructions-1 do
[ let ip = IP(i)
ip>>IM.W0word = (ip>>IM.W0word & not W0mask) + savew0!i
]
Free(z, savew0, NInstructions)
]
and sxfer(proc) be
[ if DMachine ne 0 then
[ proc(ScratchS, IFUM, NIFUM*lIFUM)
proc(ScratchS, IFUMbits, IFUMsize/16)
proc(ScratchS, ALUFM, ALUFMsize)
proc(ScratchS, ALUFMbits, ALUFMsize/16)
]
proc(ScratchS, RM, RMsize)
proc(ScratchS, RMbits, RMsize/16)
]
and EndPass(proc, flag) be
[ if flag then
[ if (dpasses&1) ne 0 then ShowIM()
dpasses = dpasses rshift 1
]
if AbortCode ge 0 then End()
EndP()
if Usc(proc, Err) gr 0 then // don't flush if stub!
Storage = proc
]
and EndP() be
[ if RealMin ne -1 then [ MinSpace = RealMin; RealMin = -1 ]
if TraceStorage then PutTemplate(OutputS, "$UO free, $UO min*N", EndStorage-Storage, MinSpace)
]
and ShowIM() be
[ Wss(OutputS, "IM:*N")
Show(IM, DebugFirstLoc, (DebugLastLoc ge NInstructions? NInstructions-1, DebugLastLoc), lIM, OutputS, Format)
Wss(OutputS, "*N")
]
and End() be
[ if AbortCode ge 0 then Wss(ErrDspS, "Aborted*N")
EndP()
TotalTime = seconds()-StartTime
Summary(ErrDspS)
CloseMBS()
PutTS = Noop
if OutputS ne 0 then
[ if ErrStr>>BS.length ne 0 then Wss(OutputS, ErrStr)
ErrStr>>BS.length = 0
Closes(OutputS)
]
ShowDisplayStream(dsp, DSdelete)
let AfterEnd() be
[ dsp = saveDsp
Ws("*N*N")
test ErrStr>>BS.length ne 0
ifso Ws(ErrStr) // copied to safe place below
ifnot
[ Ws(selecton AbortCode into
[ case Fatal: "Fatal error, aborted*N"
case -1: ""
default: "Aborted*N"
])
Summary(dsp)
]
finish
]
let safe = OsFinishSafeAdr-((lErrStr+2)/2)
MoveBlock(safe, ErrStr, (lErrStr+2)/2)
ErrStr = safe
CounterJunta(AfterEnd)
]
and CloseMBS() be
if MBS ne 0 then [ TruncateDiskStream(MBS); Closes(MBS); MBS = 0 ]
and Summary(S) be
PutTemplate(S, "MicroD time: $UD seconds; $D error(s), $D warning(s), $UD words free*N", TotalTime, NErrors, NWarnings, MinSpace)
and seconds() = valof
[ let t = vec 1
ReadCalendar(t)
resultis t!1
]
and ErrPuts(st, ch) be
[ test OutputS ne 0
ifso Puts(OutputS, ch)
ifnot test ErrPos ge lErrStr
ifso []
ifnot
[ ErrPos = ErrPos+1
ErrStr>>BS.char↑ErrPos = ch
if ch eq $*N then ErrStr>>BS.length = ErrPos
]
Puts(dsp, ch)
]