The table has one entry of 8 words for each memory region
taking part in global memory operations.
Its bounds are given by LQMTA and LQMTE:
LQMTA start adr of the first entry
LQMTE end+1 adr of the last entry
A particular entry has this format:
LQ(L+0) division number
if zero: pseudo division
LQ(L+1) activity flag:
-1 division is empty
0 inactive
1 relocation only
2 active, eg. global shift, or MZPUSH, or MZREPL
3 garbage collection
4 wipe
LQ(L+2) NWSH, global shift of this division by NWSH words
-ve shift to low
0 no shift
+ve shift to high
LQ(L+3) start adr of the first bank
LQ(L+4) end+1 adr of the last bank
LQ(L+5) rel. adr of the first associated relocation entry
ie. LF = LQRTA + LQ(L+5), LQ(LF) is the first entry
in the link relocation table for this memory region
LQ(L+6) rel. adr of the last+1 entry, (only if LQ(L+1)=3)
= -3 if division with garbage collection reset because
of 'table full'
LQ(L+7) NFREE, number of words collected or wiped
This table contains the prescription of how any link is to be updated.
The table covers the 'total relocation interval'
(LFIXLO,LFIXHI),
links pointing outside this interval are not changed.
The area covered by the relocation interval is considered as a series of alternating 'live' and 'dead' regions, described by the link relocation table. One entry in this table specifies a particular live region and the dead region just behind it. Each region represents an integral number of live or dead banks, or alternatively a region of non-occupied store (reserve area). For the live region the table entry specifies the relocation constant, for the dead region it specifies whether a structural link pointing into this region should be bridged or not.
The table is constructed in the largest gap of the ZEBRA stores, with the following structure:
it starts at LQ(LQTA-1) holding LFIXLO
continues LQ(LQTA) first entry
LQ(LQTA+4) second entry
. . .
LQ(LQTE-4) last entry
and ends at LQ(LQTE) holding LFIXHI.
The format for entry i at L = LQTA + 4*(i-1) is:
LQ(L+0) LAi: start adr of the live area
+1) LDi: start adr of the adjacent dead area
+2) NRELi: relocation constant for the live area
+3) IFLi: bridging flag for the dead area
zero: no, 1: yes, -1: link to remain unchanged
The store from LQ(@LAi) to LQ(@LDi-1) is occupied
by live banks.
The store from LQ(@LDi) to LQ(@LAj)-1 with j=i+1
is a dead region,
containing dead banks to be bridged only if IFLi=1.
The store from LQ(@LFIXLO) to LQ(@LA1)
is a non-bridging dead region.
It is in the nature of this table that the link relocation table represents at the same time the detailed instructions for the memory move, if any.
The parameters in /MZCT/ control the relocation process.
IQFLIO flag I/O, init to zero by MZTABM
flags special treatment for IO relocation
non-zero: relocation called from FZIN (also MZCOPY)
triggers actions in MZRELB:
1) links pointing outside <LQ(LQTA),LQ(LQTE> are
simply reset to zero
2) do not go to ZFATAL for bank-chaining clobbered
but return IQFLIO = -7 to signal bad input structure
IQGAP(5,4) returns the parameters of the largest gaps found by MZFGAP
Entry 'J' in the table contains:
IQGAP(1,J) = number of words available
IQGAP(2,J) = abs. zebra adr of first word in the gap
IQGAP(3,J) = division number
IQGAP(4,J) = store number
IQGAP(5,J) user flag
Gaps J=1 and 2 are outside the moving region,
3 and 4 could be inside the moving region
IQPART partial garbage collection, init to zero by MZTABM
handle not enough space for the relocation tables
if = zero: no problem
set to =7 by MZTABH if not enough table space
set to =-7 by MZTABH if table moved into the forbidden gap
set to =1 by MZTABC if not enough space
set to =1 by MZTABR if not enough space
IQTBIT status-bit for table building, init to IQDROP by MZTABM
IQTVAL value of status-bit, init to zero by MZTABM
construct table for banks having IQTVAL in bit IQTBIT
IQTNMV init to zero by MZTABM if JQSTMV < 0 on entry
set to zero by MZGAR1, MZDIV
set to -7 by MZCOPY
used by MZTABH on first entry:
= 0: alright to move Mem.occ.table to forbidden gap
return IQPART = 7 if no gap at all
< 0: alright to move Mem.occ.table to forbidden gap
return IQPART = -7 if so done
> 0: Mem.occ.table may not go into a forbidden gap
return IQPART = 7 if no allowed gap
JQGAPM gap for Memory occupation table, init to zero by MZTABM
if non-zero: the Memory occupation table has been moved
to gap JQGAPM described by IQGAP(1/5,JQGAPM)
JQGAPR gap for the Relocation table, init to zero by MZTABM
if non-zero: the Link Relocation table has been moved
to gap JQGAPR
JQSTMV moving store, -1 if none, controlling MZFGAP
JQDVM1 first moving division
JQDVM2 last moving division
NQDVMV move divisions JQDVM1/2 by that many words, -ve: left
JQDVM1, JQDVM2, NQDVMV init to zero
by MZTABM if JQSTMV < 0 on entry
Original meaning of JQSTMV,JQDVM1,JQDVM2,NQDVMV (cf. MZTABS):
unless JQSTMV<0, the divisions JQDVM1 to JQDVM2 inclusive
of the store JQSTMV may have to be shifted by NQDVMV words,
to the left if -ve, to the right if +ve.
NQDVMV=0 means to the left by a yet unknown amount.
It follows that the gaps after divisions JDIV are not available
for the relocation table because they may be over-written
by the memory move, with:
NQDVMV 0, -ve: JDIV = <JQDVM1-1,JQDVM2-1>
+ve: JDIV = <JQDVM1, JQDVM2 >
MZFGAP is also used for I/O to find a gap where to put the
relocation table on input. In this case there is just one
gap unavailable, namely the one which will receive the data.
This is the gap before a reverse division (JQMODE=1) or after
a forward division (JQMODE=0). To block this gap one can give
JQDVM1=JQDVM2=JDIV and NQDVMV=1-2*JQMODE, setting JQSTMV also.
LQMTE end+1 adr of the Memory occupation table,
init to LQWKTB+NQWKTB-1 by MZTABM
LQMTA start adr of the Memory occupation table,
init to LQMTE-160 by MZTABM
LQMTB curr. adr of the Memory occupation table,
init to LQMTA by MZTABM
LQMTLU adr in the Mem.occ.table of the last division used
init by MZTABM to point to division 20
reset by MZTABX
LQMTBR init to zero by MZTABM
set by MZTABR to point to the current entry into
the Memory occupation table when it runs out of
table space.
The code handling this is a remenant from an
earlier approach to handle "table space full"
and has been left in MZTABR for safety.
In fact, now MZGAR1 recalls MZTABM after the first
partial garbage collection.
(The code handling LQ(LQMTB+6) = -3 is also part
of this old approach)
LQRTA start adr of the memory available to the Relocation table
init to LQWKTB by MZTABM
LQRTE end+1 adr of the memory available to the Relocation table
init to LQMTA-10 by MZTABM
both are updated by MZTABH if the tables are moved
LQTA start adr of the Link Relocation table,
init to LQRTA+1 by MZTABM
LQTE end+1 adr of the Link relocation table,
init to LQRTE by MZTABM
parameters driving MZTABC, set by MZTABR
LQMTC1 start adr of first bank
LQMTC2 end+1 adr of last bank
LQTC1 first table word available, init to LQRTA+1 by MZTABM
LQTC2 last table word available, init to LQRTE by MZTABM
MQDVGA flag word indicating the divisions with garbage collection
bit j, j=1,2,...,20 for garbage collection in division j
MQDVWI flag word indicating the divisions to be wiped
bit j, j=1,2,...,20 for wiping division j
MQDVAC flag word indicating the active divisions
constructed from MQDVGA + MQDVWI by MZTABM
and updated by MZTABS and MZTABR
seems to be used only for printing
NQDVMV move divisions JQDVM1/2 by that many words, -ve: left
init to zero by MZTABM if JQSTMV < 0 on entry
NQFREE number of words to become free, init to zero by MZTABM
NQFRTC number of words found free by MZTABC (per call)
NQGAPN number of normal gaps available in IQGAP
NQGAP number of all gaps, including forbidden, in IQGAP
NQLIVE number of live banks found by MZTABC (per call)
NQNOOP no-operation flag constructed by MZTABF
= zero normally
= -7 really no operation
= +7 only a memory shift with no garbage collection
and no links pointing into the shifted region
for example: left-shift empty division 2
usage in MZMOVE: if non-zero update the division tables
without execution of MOVE