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