// MDaring -- assign a single ring
// last edited July 21, 1980  5:02 PM

	get "mddecl.d"
	get "mdadefs.d"

external [	// defined here
	AssignRing	// (tab, ring, Page) -> 0/ptr
]

external [
		// MDmain
	@IP
		// MDscan
	@PageSize; @WordMask
	@pageIfuMax
		// MDassign
	@lBT; @lPage
	@PageBase
		// MDplace
	Find1Place
	FindAlistPlace
		// OS
	MoveBlock
	SetBlock
]


let AssignRing(tab, ring, Page) = valof
// Assign instructions in table to page
// Return 0 for success, pointer to entry in tab (subpage or single
// instruction) or -1 for failure
// Don't alter any important data structures on failure
[	let BT = vec maxlBT
	test ring>>Page.slow
	 ifso
	[ if ring>>Page.global+Page>>Page.global gr pageGlobalMax resultis -1
	  if ring>>Page.IFUE+Page>>Page.IFUE gr pageIfuMax resultis -1
	  // Check absolutely assigned instructions first
	  for i = 0 to lBT-1 do
	  [ let rbits, pbits = ring>>Page.BT↑i, Page>>Page.BT↑i
	    if (rbits & pbits) ne 0 resultis -1
	    BT!i = pbits + rbits
	  ]
	]
	 ifnot
	  MoveBlock(BT, lv Page>>Page.BT, lBT)
	let AbsPage = ((Page-PageBase)/lPage)*PageSize
	let fsub = tab+lSubPageHd+@tab
	// Do subpages with +1 lists
	let sub = fsub
	until @sub eq 0 do
	[ if sub>>SubPage.alists ne 0 then
	    unless PlaceSubpage(sub, AbsPage, BT) resultis sub
	  sub = sub+lSubPageHd+sub>>SubPage.length
	]
	// Next do other subpages
	sub = fsub
	until @sub eq 0 do
	[ if sub>>SubPage.alists eq 0 then
	    unless PlaceSubpage(sub, AbsPage, BT) resultis sub
	  sub = sub+lSubPageHd+sub>>SubPage.length
	]
	// Finally do rest of ring (isolated instructions)
	for j = 0 to tab>>SubPage.length-1 do
	[ let ip = IP(tab>>SubPage.data↑j)
	  test ip>>IM.atWord
	   ifso	// absolutely placed
	  [ ip>>IM.W0 = AbsPage + (ip>>IM.W0&WordMask)
	  ]
	   ifnot
	  [ let loc = Find1Place(ip>>IM.mask, BT)
	    if loc eq -1 resultis lv tab>>SubPage.data↑j
	    ip>>IM.W0 = AbsPage + loc
	  ]
	]
	// Reflect the assignments back into the page
	Page>>Page.global = Page>>Page.global+ring>>Page.global
	Page>>Page.IFUE = Page>>Page.IFUE+ring>>Page.IFUE
	Page>>Page.used = Page>>Page.used+ring>>Page.used
	MoveBlock(lv Page>>Page.BT, BT, lBT)
	sub = tab
	[ let end = sub+lSubPageHd+sub>>SubPage.length
	  sub = sub+lSubPageHd
	  until sub eq end do
	  [ let ip = IP(@sub)
	    ip>>IM.onPage = 1
	    ip>>IM.atWord = 1
	    sub = sub+1
	  ]
	] repeatuntil @sub eq 0
	resultis 0
]

and PlaceSubpage(V, AbsPage, BT) = valof
// Returns true or false
[	let data = lv V>>SubPage.data↑0
	let end, spn = data+V>>SubPage.length, V>>SubPage.spn1-1
	let w, lw = nil, nil
	test spn eq -1
	ifso	w, lw = 0, lBT-1
	ifnot	w, lw = spn, spn
	let sBT = vec maxlBT
	SetBlock(sBT, -1, lBT)
	[ sBT!w = BT!w	// just look at subpage
	  let j = data
	  until j eq end do
	  [ let i0 = @j
	    let ip = IP(i0)
	    let j0 = j
	    if ip>>IM.aLink ne i0 then	// got a +1 list
	    [ [ j = j+1
	      ] repeatuntil IP(@j)>>IM.aLink eq i0
	    ]
	    let loc = nil
	    test ip>>IM.atWord eq 0
	     ifso	// need to find a place
	    [ loc = (j eq j0? Find1Place(ip>>IM.mask, sBT), FindAlistPlace(ip>>IM.mask, j-j0+1, sBT))
	      if loc eq -1 goto nxw
	    ]
	     ifnot	// propagate assignment through +1 list
	    [ loc = ip>>IM.W0 & WordMask
	    ]
	    for j1 = j0 to j do	// fill in assignment
	      IP(@j1)>>IM.W0 = AbsPage + loc+j1-j0
	    j = j+1
	  ]
	  BT!w = sBT!w	// success
	  resultis true
nxw:	  sBT!w = -1	// failure
	  w = w+1
	] repeatwhile w le lw
	resultis false
]