DataMuseum.dk

Presents historical artifacts from the history of:

RC4000/8000/9000

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about RC4000/8000/9000

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download

⟦2e75a6780⟧ TextFile

    Length: 67584 (0x10800)
    Types: TextFile
    Names: »mprocfnc1   «

Derivation

└─⟦9ccaf6601⟧ Bits:30008165 Bånd med SW8000 kildetekst/release værktøjer
    └─⟦2ba378e4a⟧ 
        └─⟦this⟧ »mprocfnc1   « 

TextFile

\f


m.                monprocfnc1 - monitor process functions, part 1 17.0 beta
;88.05.24    08.40  kak  change of cpa and address base included
;89 05 23 09.15 kak remove area changed: main address not cleared
;                                        no result inserted in buffs used by the areaprocess
;                   a new procedure: find idle area     introducted
;89 05 25 08.05 kak -  -     -     : clean area processs     -
;89 11 21 15 24 kak an error in find idle area corrected

b.i30 w.
i0=89 05 25, i1=15 21 00

; if newtime (i0,i1) > oldtime (a133,a134) then oldtime:=newtime;
c.i0-a133
  c.i0-a133-1, a133=i0, a134=i1, z.
  c.i1-a134-1,          a134=i1, z.
z.

i10=i0, i20=i1

i15=i10/100000 , i10=i10-i15*100000 , i25=i20/100000 , i20=i20-i25*100000 
i14=i10/10000  , i10=i10-i14*10000  , i24=i20/10000  , i20=i20-i24*10000 
i13=i10/1000   , i10=i10-i13*1000   , i23=i20/1000   , i20=i20-i23*1000
i12=i10/100    , i10=i10-i12*100    , i22=i20/100    , i20=i20-i22*100
i11=i10/10     , i10=i10-i11*10     , i21=i20/10     , i20=i20-i21*10

i2:  <:                              date  :>
     (:i15+48:)<16+(:i14+48:)<8+46
     (:i13+48:)<16+(:i12+48:)<8+46
     (:i11+48:)<16+(:i10+48:)<8+32

     (:i25+48:)<16+(:i24+48:)<8+46
     (:i23+48:)<16+(:i22+48:)<8+46
     (:i21+48:)<16+(:i20+48:)<8+ 0

i3:  al. w0  i2.       ; write date:
     rs  w0  x2+0      ;   first free:=start(text);
     al  w2  0         ;
     jl      x3        ;   return to slang(status ok);

     jl.     i3.       ;
e.
j.

; rc date

; rc 4000 systems tape, segment 6:  process functions.
;   leif svalgaard / jørn jensen
;   catalog administration; creation, removal, and
;   start and stop of processes.

; the code includes certain test options selected by bits in the identifier
;   a92 as follows:
;   test call included:   a92 = a92 o. 1<19
;   monitor test output:  a92 = a92 o. 1<20
;   print w, type w:      a92 = a92 o. 1<21


s.   c10, d50, e99, f100, i70, j21, l150, m280, n50, p65, r7, t40, v40


c.(:a399>23a.1:)-1
h.
0,r.(:(:(:(:k+2047:)/2048:)*2048:) - k:); (first address:=(first address+2047)//2048)*2048;
w.
m.                    1. address
z.

b60:                           ; start of proc func
w.b127=k, j21, k=k-2

; use of slang names:
;   a:   monitor constants, declared and defined before proc func
;   b:   monitor absolute entry addresses,  -       -     -   -
;   c:   global full word constants
;   d:   global variables, start addresses for records
;   e:   procedures, mostly called with w3 as return register
;   f:   constant names, relative addresses in records
;   g:   local labels in procedures and actions
;   i:   process functions (actions)
;   j:   global points in central administration, error exits
;
; note: in the comments to the code the notation  x.b  denotes a reference to the
;   variable  x  in the record  b.

; definition of catalog parameters:
f0  =   a88        ; size of one catalog entry:      34  bytes
f9  =   512 - 2    ; catalog buffer size - 2  :     510  bytes
f10 =   f9/f0      ; number of entries per segment:  15


;definition of results from check users and reserver

f20 = 2.000001      ; internal is user
f21 = 2.000010      ; internal is reserver
f22 = 2.000100      ; other users
f23 = 2.001000      ; another internal is reserver
f24 = 2.010000      ; internal has writeprotected
f25 = 2.100000      ; other(s) has writeprotected


; definition of proc func communications parameters

f14 =   3            ; operation  read
f15 =   5            ; operation write
f16 =  48            ; minimum value of digit in identifier
f17 =  57            ; maximum   -   -    -    -     -
f18 =  97            ; minimum   -   -  letter -     -
f19 = 125            ; maximum   -   -    -    -     -
f37 =   0            ; kind:  internal process
f38 =   4            ; kind:  area process

; definition of bits and values of process states

f40 =  1<2           ; repeat bit,  in proc state
f41 =  1<3           ; no stop bit, in proc state
f42 =  1<4           ; parent bit,  in proc state
f43 =  1<5           ; stopped bit, in proc state
f44 =  1<6           ; out of q bit,in proc state
f45 =  1<7           ; waiting bit, in proc state

; process state values

f46 = a95            ; running
f47 = a99            ; waiting start by parent
f48 = a97            ; waiting stop by parent
f49 = a100           ; waiting start by ancestor
f50 = a98            ; waiting stop by ancestor

; note: the above a-names are defined before proc func loading.
;      running:                   out of q, no stop
;      waiting start by parent    stopped, parent, no stop
;      waiting stop by parent     stopped, parent
;      waiting start by ancestor  stopped, no stop
;      waiting stop by ancestor   stopped
;      waiting events             repeat
;      waiting for proc func      repeat, out of q 
;

; definition of function keys

f71 =  1<10  ; bit 1 : aux catalog handling
f72 =  1<9   ; bit 2 : main catalog handling
f74 =  1<7   ; bit 4 : create peripheral process
f75 =  1<6   ; bit 5 : remove peripheral process
f76 =  1<5   ; bit 6 : aux entry handling
f77 =  1<4   ; bit 7 : set clock

; definition of itc-process states and mt-document states

f80 =  0             ; free
f81 =  1             ; during connect
f82 =  2             ; connected
f83 =  3             ; during disconnect
f84 =  4             ; intervention

f87 =  0             ; identified document mounted
f88 =  2             ; unidentified document mounted
f89 =  1             ; no document mounted

; definition of logical disc types

f90 =  2.00001       ; logical disc - without catalog
f91 =  2.00011       ; logical disc - with rc8000 bs catalog


; definition of chain states

t0  =  1<0           ; idle
t1  =  1<1           ; after prepare
t2  =  1<2           ; during insert
t3  =  1<3           ; ready
t4  =  1<4           ; during delete
t5  =  1<5           ; during check
t6  =  1<6           ; during aux entry manipulation

t20 =  t0            ; allowed for prepare bs
t21 =  t1+t2         ; allowed for insert entry
                     ;             insert bs
                     ;             connect main catalog
t22 =  t3            ; allowed for normal use
t23 =  t1+t2+t3+t4+t5+t6; allowed for delete bs
t24 =  t4            ; allowed for delete entries
t26 =  t1+t5         ; allowed for check aux catalog
t28 =  t1+t2+t6      ; allowed for create aux entry
t29 =  t1+t2+t3+t4+t5+t6; allowed for set bs-claims
t30 =  t1+t2+t3+t6   ; allowed for create area process


; format of catalog entry
; the formats of entries in main catalog and auxiliary catalogs are the
; same, except for a field on 4 words that
;  - in main catalog    contains document name, and
;  - in aux catalogs    contains
;        word0: entry last change (of entry), shortclock
;        word1: write access counter
;        word2: read access counter
;        word3: dummy

f4  =  0   ; byte    ; <first slice>
f3  =  1   ; byte    ; <namekey> * 8 + <perm key>
f1  =  2   ; word    ; <lower base of entry>
f2  =  4   ; word    ; <upper base of entry>
f5  =  6   ; name    ; <entry name>
f7  =  14  ; word    ; <size of entry>
f11 =  16  ; name    ; main: <document name>
f11 =  f11   ; word    ; aux:  <last change>
f12 =  f11+2 ; double  ;       <write access counter>,<read access counter>
f13 =  f12+4 ; word    ;       <last used>

f0  =  a88           ; size of catalog entry
f6  =  14            ; start of tail
f8  =  f0-f6         ; size of tail
f51 = -8             ; mask for extracting all but perm-key


; format of chainhead

f60 =  -2 - f0       ; <claims rel address in internal process>
f54 =  f4 - f0       ; <first slice of aux catalog>
f53 =  f3 - f0       ; <chain kind> * 8 + <perm key>
f55 =  f5 - f0       ; <name of aux catalog>
f56 =  f6 - f0       ;   (start of tail)
f57 =  f7 - f0       ; <size of aux catalog>
f61 =  f11- f0       ; <document name>
f62 =  f56+10 ; word ; <name table address of disc process>
f64 =  f56+12 ; word ; <slice length>
f66 =  f56+14 ; byte ; <last slice in chaintable>
f67 =  f56+15 ; byte ; <number of namekeys>
f68 =  f56+16 ; byte ; <chain state>
f69 =  f56+17 ; byte ; (not used)
f70 =  f56+18 ; word ; <name table address of aux catalog area process>
                     ; (used as segment number under include-exclude auxcat)

; each chaintable has a heading as the above given, which has the same
;   basic format as a normal catalog entry.
; it describes the aux catalog on the device.
; after the heading follows the chain-area, consisting of one byte for
;   each slice.



; record for main catalog pseudo chainhead
; (format as a normal chainhead)
d9 = k - f54         ; base of pseudo chainhead:
     0, r. f0>1      ;



; description of current catalog

c0:  0               ; size of current catalog
c1:  0               ; number of namekeys in current catalog
d7:  0, r.4          ; name of current catalog
     0               ; (name table address of current catalog area process)



; description of catalog message

d8:                  ; cat message:
f30 = k - d8, f14<12 ;   operation (initially read)
f32 = k - d8, d0     ;   first address of catalog buffer
f34 = k - d8, d18    ;   last  address of catalog buffer
f36 = k - d8, -1     ;   current cat segment  (initially not existing)


; common work variables:
     0               ;-2   work
d12: 0               ;     return



; procedure set auxcat
; call:  jl. w3  e0.
;
; procedure set maincat
; call:  jl. w3  e1.
;
;   the use of the current catalog is terminated, and the
;     new catalog is selected as curcat
;
; error return: result 2, in case of io-errors
; return: all regs undef

b. g10, h10 w.

e0:                    ; set auxcat:
     rl. w1     (h2.)    ;    catchain := curdoc;
     jl.        g1.    ;      else
e1:                    ; set maincat:
     al. w1     d9.    ;    catchain := pseudo chain for main catalog;

g1:  sn. w1    (c2.)   ;    if catchain = curcat then
     jl      x3        ;      return;

     rs. w3     h0.    ;    save(return);

; notice: be very cautious not to change curcat until all transfers are
;         terminated

     rs. w1     h1.    ;    save (catchain);

     jl. w3     e7.    ;    terminate update;
; (if io-errors the curcat is not changed yet)

     rl. w1     h1.    ;    w1 := new cur cat;
     rl  w0  x1+f57    ;    move:  catsize
     rs. w0     c0.    ;
     zl  w0  x1+f67    ;           no. of namekeys
     rs. w0     c1.    ;
     al  w0    -1      ;           dummy segment number
     rs. w0     d8.+f36;             (i.e. simulate irrell buffer contents)
     rl  w0  x1+f70    ;           name table address of catalog area process
     rx. w0     d7.+8  ;

     al  w2  x1+f55    ;           catalog name;

     rx. w1     c2.    ;    curcat := new cur cat;
     rs  w0  x1+f70    ;    save old name table address in old curcat;

     al. w1     d7.    ;
     rl. w3     h0.    ;
     jl.        e32.   ;    return;

c2:  d9                ; curcat chainhead address (initially: pseudochainhead)

h0:  0                 ; return
h1:  0                 ; new curcat
 h2: d4

e.                     ;



; procedure dump chaintable
;   writes the chaintable of current document back on the device
;
; call:  jl. w3  e2.
; error return: result 2, in case of io-errors
; return: all regs undef

b. h10 w.

e2:                    ; dump chain table:
     rs. w3     d12.   ;    save(return);
     rl. w3     (l4.)  ;    w3 := curdoc;
     al  w0  x3-f0     ;    first addr := start of head.curdoc;
     bz  w1  x3+f66    ;
     wa  w1     6      ;    last addr := start of head.curdoc
     al  w1  x1+511    ;      + last slice.curdoc + 511; (i.e. round up)
     ds. w1     h2.    ;

     al. w1     h0.    ;
     al  w3  x3+f61    ;    send message(document, output message);
     jd         1<11+16;
     al. w1     d16.   ;    wait answer;
     jd         1<11+18;
     rl. w3    (l4.)   ;    if curdoc.state = during delete then
     zl  w3  x3+f68    ;    return;
     sn  w3     t4     ;    <ignore error return when called from delete bs>
     jl.       (d12.)  ;

     rl  w1  x1        ;
     sn  w0     1      ;    if result <> ok
     se  w1     0      ;    or status <> 0 then
     jl.        j2.    ;      goto result 2;

     jl.       (d12.)  ;    return;

h0:  f15 < 12          ; output message:
     0                 ;  first address
h2:  0                 ;  last address
     0                 ;  segment number (always zero)

e.                     ;



; procedure compute namekey and segment number
;   sets segment number.work:= hash function(name.work) 
;    and namekey.work := segment mod no. of namekeys ;
;
;
;   the hash function delivers a number ranging from 0 to number of segments
;    in the catalog and is used to speed up the search for a name in the catalog.
;   when an entry is created , the segment number and the namekey is computed ,
;    and the entry is  inserted in the first free entry on "segment number" or
;    the following segments.
;    (the successor to the last segment is segment 0 ).
;
;    the search for an entry continues until segment=segment no. + no. of namekeys - 1.
;
;
;
; call:  jl. w3  e3.
; return:  w2 = namekey.work < 3 + key.work
;          other regs undef

e3:                    ; compute segment no.
     dl. w2     v13.   ;    double := name(0), name(2)
     aa. w2     v14.   ;            + name(4), name(6);
     wa  w2     2      ;    word := double(0) + double(2);
     ba  w2     4      ;    word := word + word // 4096;
     al  w1     0      ;
     wd. w2     c0.    ;    segment := word mod catsize;
     rs. w1     d28.   ;    segment no.work := segment
     al  w2  x1        ; 
     al  w1     0      ;
     wd. w2     c1.    ;    namekey.work := segment mod no. of namekeys
     ls  w1     3      ;
     al  w2    -f51-1  ;
     la. w2     v3.    ;    
     wa  w2     2      ;
     hs. w2     v3.    ;
     jl      x3        ;    return;



; the following complex of io-procedures all have a common
;   return information:
; return: w0 = namekey of next segment
;         w1 = segment number
;         w2 = absolute address of start of buffer
;         w3 = undef
;         cur cat segment defined
; error return: result 2, in case of io-errors



; "namekey of next segment" is used by the calling procedure to check wheter
; the next segment is relevant , as entries only can be saved and retreived
; from segments between segment no.work and the next segment 
; with namekey = namekey.work
;


; procedure get key segment
;   ensures that the segment given by namekey.work is present
;     in the buffer
;
; call:  jl. w3  e4.
;
;
; procedure get cat segment
;   ensures that the segment given as parameter is present
;
; call:  al  w2  <segment number>
;        jl. w3  e5.
;
;
; procedure get next segment
;   gets the next (cyclically numberred) segment into the buffer
;
; call:  jl. w3  e6.
;
;
; procedure terminate update
;   the current catalog segment is written back, in case of changes
;
; call:  jl. w3  e7.

b. g10 w.

e4:                    ; get key segment:
     rl. w2     d28.   ; segment := segment no.work
e5:                    ; get cat segment:
                       ; (w2 = segment)
     se. w2    (d8.+f36);   if segment <> current segment then
     jl.        g1.    ;      goto get segment;

g0:                    ; exit:
     al  w1  x2        ;    w1 := segment;
     al  w0     0      ;     w0:=next key
     wd. w1     c1.    ;     
     ea. w0     +1     ;     if next key := no of keys then
     sl. w0    (c1.)   ;     next key := 0
     al  w0     0      ;
     al  w1  x2        ;     restore segment
     rl. w2     d8.+f32;    w2 := abs first of buffer;
     jl      x3        ;    return;

e6:                    ; get next segment:
     am         1-0    ;    incr := 1;
e7:                    ; terminate update:
     al  w2     0      ;    incr := 0;
     wa. w2     d8.+f36;    segment := current segment + incr;

     sl. w2    (c0.)   ;    if segment outside catalog then
     al  w2     0      ;      segment := 0;

g1:                    ; get segment:
                       ; (w2 = segment, w3 = return)
     ds. w3     d12.   ;    save(segment, return);
     bz. w0     d8.+f30;
     se  w0     f15    ;    if catoperation <> output then
     jl.        g4.    ;      goto test input nescessary;
g2:                    ; after output:
     al. w3     d7.    ;    w3 := catalog name address;

     bz. w0     d8.+f30;    if catoperation = write then
     sn  w0     f15    ;
     jd         1<11+8 ;      reserve process(catalog); (i.e. after update)

     al. w1     d8.    ;
     jd         1<11+16;    send message(catalog, catmessage);

     al. w1     d16.   ;
     jd         1<11+18;    wait answer;
     zl. w2  d8.+f30     ;
     sn  w2      f15     ;
     jd          1<11+10 ;
     al  w2      f14     ;
     hs. w2  d8.+f30     ;

     al  w2    -1      ;    (prepare for io-errors)
     sn  w0     1      ;    if result <> ok
     sz  w2 (x1)       ;    or status <> 0 then
     jl.        g5.    ;      goto catalog io-error;

; a transfer has now been completed.
; if after update the transfer was an output, terminating the earlier
;   segment. in this case the new segment must be brougth into the buffer

     dl. w3     d12.   ;    restore(segment, return);

g4:                    ; test input nescessary:
     rx. w2     d8.+f36;    current segment := segment;
     se. w2    (d8.+f36);   if current segment <> segment then
     jl.        g2.    ;      goto after write;

     jl.        g0.    ;    goto exit;

g5:                    ; catalog io-error:
     rs. w2     d8.+f36;    current segment := -1;
                       ;    (i.e. undefined contents of catalog buffer)
     jl.        j2.    ;    goto result 2;

e.                     ;



; the following set of procedures are intended for updating
; and utilizing the information given in each catalog segment:
;   each segment contains a number, <entry count>, stating the
;   number of entries with a namekey corresponding to the
;   segment-number
; notice:
;         *********************************************************
;         *                                                       *
;         * in case of break-down during a multi-segment updating *
;         *   the entry count may be one (or more) too large,     *
;         *             but never too small                       *
;         *                                                       *
;         * i.e. it is actually a maximum number of entries       *
;         *                                                       *
;         * it will be reset at the first catalog search with     *
;         *      that particular namekey                          *
;         *                                                       *
;         *********************************************************

b. g30, h10 w.

; procedure prepare update and change entry count
; call:  al  w0  <change of entry count>
;        al  w2  <start of catalog buffer>
;        jl. w3  e8.
; return: all regs undef
;
;   the corresponding entry count is updated
;   and the segment is flagged for being written back

e8:                    ; change entry count and prepare update:
     wa  w0  x2+f9     ;    entry count.buffer :=
     rs  w0  x2+f9     ;      entry count.buffer + change;

; procedure prepare update
; call:  jl. w3  e9.
; return: all regs undef
;
;   the current catalog segment is flagged for being written back
;   at next catalog transfer

e9:                    ; prepare update:
     al  w0     f15    ;    catoperation := write;
     hs. w0     d8.+f30;
     jl      x3        ;    return;


; procedure search free entry
;   a new entry is to be created. the entry is given in work.
;   entry count(namekey.work) is increased, and a free entry is searched
;     for.
;   if no room, then entry count is decreased again, and error return
;
;
; call:  jl. w3  e10.
;        jl.     no room
;        jl.     ok
; error return: result 2, in case of io-error
; return: cur entry (and segment defined)

e10:                   ; search free entry:
     rs. w3     h1.    ;    save(return);
     jl. w3     e4.    ;    get key segment;
     rs. w0     h5.    ; save next key
     rs. w1     h0.    ;    save(segment number);
     al  w0     1      ;
     jl. w3     e8.    ;    increase(entry count) and prepare update;

g1:                    ; next segment:
     al  w0    -1      ;    w0 := free pattern;
     al  w3  x2+f9     ;    w3 := top of last entry;
g2:                    ; next entry:
                       ; (w0 = free pattern, w2 = entry, w3 =  top)
     sn  w0 (x2)       ;    if first word of entry <> free pattern then
     jl.        g5.    ;      begin
     al  w2  x2+f0     ;      entry := entry + entrysize;
     se  w2  x3        ;      if more entries on same segment then 
     jl.        g2.    ;        goto next entry; 


     zl. w2     v3.    ;      if key.work = next key then
     ls  w2     -3     ;       decrease entry count
     sn. w2     (h5.)  ;      else
     jl.        g10.   ;      get next segment
     jl. w3     e6.    ;
     rs. w0     h5.    ;      save next key
     jl.        g1.    ;


g5:                    ;      end;
     ds. w2     d3.    ;    save(cur entry segment, cur entry);
     am.       (h1.)   ;
     jl        +2      ;    goto ok-return;



; procedure get cur entry segment
;   ensures that the catalog buffer contains the appropriate segment
;     and that cur entry address is relevant in this buffer
;
; call: jl. w3  e11.
; error return: result 2, in case of io-error
; return: cur entry segment is in catbuffer
;         registers as get catalog segment

e11:                   ; get cur entry segment:
     rl. w2     d29.   ;    segment  := cur entry segment;
     jl.        e5.    ;    goto get catalog segment;



; procedure set cur entry
;   moves the entry in work to the catalog segment, given by cur entry
;
; call: jl. w3  e12.
; error return: result 2, in case of io-error
; return: all regs undef

e12:                   ; set cur entry:
     rs. w3     h1.    ;    save(return);
     jl. w3     e11.   ;    get cur entry segment;
     jl. w3     e9.    ;    prepare update;

     rl. w1     d3.    ;    w1 := cur entry;
     al. w2     d1.    ;    w2 := work;
     jl. w3     e33.   ;    move work to cur entry;

     jl.       (h1.)   ;



; procedure delete cur entry
;   remove the entry given by cur entry, by setting the first word
;     of the entry to -1
;   entry count(namekey.work) is decreased
;
; call: jl. w3  e13.
; error return: result 2, in case of io-error
; return: all regs undef

e13:                   ; delete cur entry:
     rs. w3     h1.    ;    save(return);
     jl. w3     e11.   ;    get cur entry segment;

     al  w0    -1      ;
     rs. w0    (d3.)   ;    first word(cur entry) := -1
     jl. w3     e9.    ;    prepare update;
                       ;    (notice: if the entry is not on the key segment
                       ;             two segments must be updated)
g10: jl. w3     e4.    ;    get key segment;

                       ; decrease entry count:
     al  w0    -1      ;
g15:                   ; update and return:
     jl. w3     e8.    ;    change entry count and prepare update;
     jl.       (h1.)   ;    return;



; procedure for all key entries do
;
;   delivers all entries, one at a time, with the namekey given
;
; call: al  w2  <segment>
;       jl. w3  e14.
;       jl.     no more
;       (maybe save w2)
;       <action for found entry>
;       (restore w2, if destroyed)
;       jl      x3
;
; error return: result 2, in case of io-errors
;
; return:  link+0: no more entries (all regs undef)
;          link+2: w0w1 = undef, w2 = entry, w3 = continue search
;                  (when continuing w2 must remain unchanged)

e14:                   ; for all key entries do:
     ds. w3     h1.    ;    save(segment, return);
     jl. w3     e5.    ;    get cat segment;
     rs. w0     h5.    ;    save next key ; key :=next key
     sn  w0      0     ;    if  key = 0 then
     rl. w0     c1.    ;     key := no. of keys.catalog
     bs. w0      1     ;    current key :=  key-1
     rs. w0     h4.    ;    save current key
     al  w3  x2+f9     ;    w3 := top of last entry;
     rs. w3     h3.    ;

     rl  w3  x2+f9     ;    remaining := entry count.key segment;
     al  w2  x2-f0     ;    (decrease(entry) ... code trick)

g21:                   ; test remaining:
     sn  w3     0      ;    if remaining = 0 then
     jl.       (h1.)   ;      return;
     rs. w3     h2.    ;

g22:                   ; next entry:
     al  w2  x2+f0     ;    increase(entry);
     sn. w2    (h3.)   ;    if out of buffer then
     jl.        g24.   ;      goto next segment;

g23:                   ; test entry:
     rl  w3  x2        ;
     se  w3    -1      ;    if entry exists then
     bz  w3  x2+f3     ;      key := key.entry;
     as  w3    -3      ;    (otherwise key = not possible)
     se. w3    (h4.)   ;    if key <> saved key then
     jl.        g22.   ;      goto next entry;

     rl. w3     h1.    ;
     jl  w3  x3+2      ;    call(found action); (w2 = entry)

     rl. w3     h2.    ;
     al  w3  x3-1      ;    decrease(remaining entries);
     jl.        g21.   ;    goto test remaining;

g24:                   ; next segment:
     rl. w0     h5.    ;    if next key = key then
     sn. w0    (h4.)   ;    
     jl.       g25.    ;    goto adjust entry count
     jl. w3     e6.    ;    else
     rs. w0     h5.    ;    get next segment
     al  w3  x2+f9     ;    save next key
     rs. w3     h3.    ;    and addres of last entry.segment
     jl.       g23.    ;

g25:                   ; adjust entry count
     rl. w2     h0.    ;
     jl. w3     e5.    ;  get entry segment

     ac. w0    (h2.)   ;    decrease entry count by remaining entries
     jl.        g15.   ;      and return;

h0:  0                 ; saved segment
h1:  0                 ; saved return
h2:  0                 ; remaining entries
h3:  0                 ; top address of last entry on segment
h4:  0                 ; key.segment
h5:  0                 ; next key

e.                     ;



; procedure compute document address
;
;   selects either the maincat document or the document
;     specified in first slice.work
;
; call:  jl. w3  e15.
; return:  w2 = doc address, other regs undef

e15:                   ; compute document address for non-area entries:
     rl  w2     b25    ;    (prepare for maincat-entry)
     bz. w1     v4.    ;    if first slice.work = 0 then
     sn  w1     0      ;      w2 := maincat document
     jl      x3        ;      and return;

     am        (b22)   ;    use the last 11 bits of first slice
     rl  w2  x1-2048   ;      to select the document;
     jl      x3        ;    return;

; procedure first proc (proc addr,new state);
;   finds the process given by name.work and checks that it is a child
;   of the sender.
;   initializes  end chain delta  and  children bits  and returns disabled
;   with w3 = proc addr  and new state = wait stop by parent.
; call:               jl. w3   e17.
; return:             disabled with
;                     w1 = sender
;                     w2 = new state
;                     w3 = proc addr
;                     w0   changed
; error:              not child: error 3;
e17: rs. w3   d12.      ; first proc: save return;
     jl. w3     e47.   ;    search best process in nametable;
       b6              ;
       b7              ;
     jl.        e26.   ;+6:   not found:  goto test found;
     al  w3  x2        ;    proc := proc found;

     rl. w1   (l2.)          ;   if parent.proc addr <> sender
     se  w1 (x3+a34)         ;   then enabled goto error 3;
     jl.      j3.            ;

     al  w2   0              ;   end chain:= children bits:= 0;
     rs. w2    d21.          ;   delta := 0;
     rs. w2   (l15.)         ;   w3:= proc addr;
b. i1 w.
     rs. w3     d14.   ;
     al  w2     a402   ; start of bit array
     al  w0     0      ;
i0:  rs. w0  x2+d13.   ; childrensbits:=0
     al  w2  x2+2      ;
     se  w2  a402+a403 ;
     jl.        i0.    ;
e.
     al  w2   f48            ;   w2:= new state:= wait stop by parent;
     jl.     (d12.)          ; disabled return;

e26: jl. w3   e24.           ; test found: test format;
     jl.      j3.            ;   goto error 3;

; procedure chain and add children;
;   connects proc addr to the the chain through wait addresses which
;   ends in end chain and exits via add children
; call:        jl. w3   e18.
; return:      w2: delta (stopcount - children)

b.   g2                           ; begin
w.                                ;
e18: dl. w2   (l15.)              ; chain and add children:
     rs  w2  x1+a40               ;   wait addr.proc addr:= end chain;
     rs. w1   (l15.)              ;   end chain:= proc addr;

; procedure add children;
;   searches through all internal processes and adds to children bits
;   the identification bit for all processes with parent = proc addr;
; call:        jl. w3   e19.
; return:      w2: delta (stopcount - children)
e19: rs. w3   d12.        ; add children:  save return;
     rl. w1     d14.     ; 
     zl  w2  x1+a12      ; delta := delta + stopcount;
     wa. w2     d21.     ;
     rs. w2     d21.     ;
     rl w3   b6          ; w3:=addr(first proc in nametable);
g0:  rl w2 x3            ; for w3 through nametable do
     rl. w1   d14.       ; w1:=proc addr;
     se  w1 (x2+a34)     ;  if parent.nametable(w3)=
     jl.        g1.      ;     procaddr then
     el  w1  x2+a14      ;    include identbit.nametable(w3)
     bz. w0  x1+d13.     ;        nametable(w3));
     lo  w0  x2+a14      ;
     hs. w0  x1+d13.     ;
     rl. w2     d21.     ;
     al  w2  x2-1        ;     delta := delta - children;
     rs. w2     d21.     ;
g1:  al  w3  x3+2        ;
     se  w3    (b7)      ;
     jl.        g0.      ;
     rl. w2     d21.     ;
     jl.       (d12.)    ;  return;

e.                                ; end chain/add children;

; procedure next proc (result: proc addr, new state);
;   finds proc addr corresponding to one of the bits in children bits,
;   removes the corresponding bit in children bits, and returns disabled
;   with new state = wait stop by ancestor and proc addr defined.
; call:           jl. w3   e20.
; return:         w2 = new state
;                 w3 = proc addr
;                 w0,w1 changed.
; return 2:       no more children

b.   g5                    ; begin
w.                         ; next proc:
e20: rs. w3  d12.         ;   save(link) ;
     al  w3    -11        ;
     al  w1    a402       ; w1:=first halfword.bit array
g0:  zl. w0  x1+d13.      ; get array(w1)
     sn  w0       0       ; if no users then
     jl.        g3.       ; goto next halfword
     ns  w0      1        ; (first internal : -11 second : -12 ...)
     es  w3      1        ; w3:= -11 +no of shifts
     ls  w3      1        ; +12*halfword no(bitarray)
     am         (b6)      ; name table index:=w3*2
     rl  w3    x3         ; w3:=proc
     zl. w0  x1+d13.      ; remove children it from bit array
     lx  w0   x3+a14      ; 
     hs. w0  x1+d13.      ; 
     al  w2  f50          ; new state:=wait stop by ancestor
     rs. w3    d14.       ;
     jl.      (d12.)      ;
g3:  al  w1  x1+1         ; next halfword(bitarray)
     al  w3  x3+12        ; w3:=w3+no of internals pr halfword
     se  w1  a402+a403    ; if index > last index then
     jl.       g0.        ; return : no more children
     rl. w3    d12.       ;
     jl      x3+2         ;

e.                               ; end next proc;



; procedure create next wrk-name
;   supplies a wrk-name in name.work
;
;   a wrk-name has the format:  wrk<6 octal digits>
;
; call:  jl. w3  e23.
;
; return: name.work defined
;         all regs undef

b. g10, h10 w.

e23:                   ; test name:
     dl. w1     h0.    ;    increase(last wrkname) octal;
     aa. w1     h3.    ;
     lo. w0     h1.    ;    (notice: a carry from one character is
     la. w0     h2.    ;             propagated to next char and so on,
     lo. w1     h1.    ;             by means of the special mask)
     la. w1     h2.    ;
     ds. w1     h0.    ;

     al. w1     v5.    ;    move wrk-name
     jl. w2     e32.   ;      to name.work;
h0=k+4 ; wrk-digits    ;
     <:wrk000000:>,0   ; last wrk-name

h1:  <:000:>           ; mask to convert to digits
h2:  <:777:>           ; mask to eliminate superflouos carries
     200<16+200<8+200  ; double-mask to increase octally
h3:  200<16+200<8+200+1;    (= all ones - <:888888:> + 1)

e.                     ;



; procedure test format
;
;   test whether the format of name.work corresponds to
;     a legal identifier.
;   a legal name consists of a small letter followed by at most
;     10 small letters or digits, filled up with null-chars
;     until 4 words.
;   f16 <= value of digit        <= f17    (initially: digits 0-9)
;   f18 <= value of small letter <= f19    (initially: letters a-aa)
;
; call:  jl. w3  e24.
; error return: result 6, if nameformat illegal
; return: nameformat ok
;         all regs undef

b. g10 w.

e24:                   ; test format:
     rs. w3     d12.   ;    save(return);
     al. w2     v5.    ;    name pointer := addr of name.work;

     bz  w0  x2        ; test start of name:
     sl  w0     f18<4  ;    if first char of name < minimum letter then
     jl.        g3.    ;      goto result 6;
     jl.        j6.    ;    goto get word;

g1:                    ; test next char:
                       ;  w0 = partial word   ( <> 0 )
                       ;       (i.e. contains at least one character,
                       ;             which must be left justified)
                       ;  w1 = current word
                       ;  w2 = name pointer:  even == before null-char
                       ;                      odd  == after  null-char
                       ;  w3 = 1
     so  w2     2.1    ;    if before null-char then
     ld  w0     8      ;      char := next char from partial word + 1 shift 8;
                       ;    (partial word := partial word shift 8);
                       ;    (i.e. if after null-char then illegal name)
     sh  w3     f17+1<8;
     al  w3  x3+f18-f16;    if neither letter nor digit then
     sl  w3     f18+1<8;
     sl  w3     f19+1+1<8;
     jl.        j6.    ;      goto result 6; i.e. illegal name

g2:                    ; test rest of partial word:
     al  w3     1      ;    (prepare for next char and for making nameptr odd)
     se  w0     0      ;    if partial word <> 0 then
     jl.        g1.    ;      goto test next char;

     sz  w1     255    ;    if last char in current word = null then
     sz  w2     2.1    ;      after null-char := true;
     lo  w2     6      ;    (i.e. make name pointer odd)

     al  w2  x2+2      ;    increase(name pointer);

g3:                    ; get word:
     rl  w1  x2        ;    current word := name (name pointer);
     al  w0  x1        ;    partial word := current word;
     sh. w2     v15.   ;    if name pointer < last addr of name.word then
     jl.        g2.    ;      goto test rest of partial word;

     sz  w2     2.1    ;    if after null-char then
     jl.       (d12.)  ;      return;
     jl.        j6.    ;    goto result 6; (i.e. more than 11 chars)

e.                     ;


; procedure remove area (intproc,areaproc);
; intproc is removed as user and as reserver of area proc.
; call:   w1= intproc,   w2=area proc
;         disabled call with link in w3

b.g30,h7 w.              ; begin
                         ; remove area:

h0:  0                   ; save w1: init proc
h1:  0                   ; save w2: area
h2:  0                   ; save w3: link
h3:  0                   ; result from check user-reserver
     0                   ; write access counter
h6:  0                   ; read access counter
     0                   ; lower base.proc
h7:  0                   ; upper base.proc
e25: rs. w3  h2.         ; save return
     jl. w3  e64.        ;
     rs. w3  h3.         ;
     so  w3  f20         ; if proc not user  then
     jl.     (h2.)       ; enable return;
     jl. w3  e56.        ; exclude proc as user(and reserver)
     rl. w3  h3.         ; if proc has writeprotected then
     sz  w3  f24         ;
     jl. w3  e53.        ;    remove writeprotect(proc, area);
     al  w3  1           ;
     ba  w3  x1+a20      ; increase area claim
     hs  w3  x1+a20      ;
     rl. w0  h3.         ; if other users then
     sz  w0  f22         ; 
     jl.     (h2.)       ; enable return
     al  w0  0           ;
     sn  w0 (x2+a411)    ;   w0=0 used below....
     se  w0 (x2+a412)    ;   if access counters<>0,0 then
     jl.     g1.         ;     name(0).area:=0;
     jl. w3  e67.        ;     clean area process;
     jl.     (h2.)       ; enable return
; save statistical information in auxiliary catalog.
g1:  ds. w2  h0.+2       ;   save init proc, link;
     dl  w1  x2+a49      ;  
     ds. w1  v2.         ;   base.work:=base.proc
     ds. w1  h7.         ;   save base.proc
     dl  w1  x2+a62+2    ;   move docname.area to docname.work
     ds. w1  v30.        ;  
     dl  w1  x2+a62+6    ;  
     ds. w1  v31.        ;  
     dl  w1  x2+a11+2    ;   move name.area to name.work
     ds. w1  v13.        ;  
     dl  w1  x2+a11+6    ;  
     ds. w1  v14.        ;  
     jl. w3     e67.     ;   clean area process
     rl. w1  h0.         ;   w1:= initproc
     dl  w0  x2+a412     ;
     ds. w0  h6.         ;   access counters:=access counters.area;
     jl. w3  e45.        ;   enable, find chain(docname.work)
             v11         ;  
     jl.     g2.         ;   NOT FOUND:  result 3

     rs. w2  d4.        ; curdoc:= chain;
     jl. w3  e0.         ;   set aux cat
     jl. w3  e46.        ;   search best entry
     jl.     g2.         ;   NOT FOUND: enable return
     sn. w0 (h7.-2)      ;   if base.entry<> base.proc 
     se. w1 (h7.)        ;   then enable return
     jl.     g2.         ;   (area describes a temp entry on curdoc)
     dl  w1  b13+2       ;
     ld  w1  5           ;
     dl. w2  h6.         ;
     se  w1  0           ;   if write access counter<>0 then
     rs. w0  v11.        ;     last change.work:=short clock;
     sn  w1  0           ;   if write access counter<>0 or
     se  w2  0           ;   if read access counter<>0 then
     rs. w0  v8.         ;     last used.work := short clock
     wa. w1  v12.        ;
     wa. w2  v32.        ;
     ds. w2  v32.        ;   update access counters;
     jl. w3  e12.        ;   set curr entry;
g2:  jl. w3  e1.         ; maincat: set main catalog;


     rl. w1  h0.         ;   w1:=init proc;
     jl.    (h2.)        ; exit: enable, return;
e.                       ;



; the following complex of procedures take care of moves
;   in general the call must be like this:
; call:  al  w0  <bytes to move>   (must be even)
;        al. w1  <to-address>
;        al. w2  <from-address>
;        jl. w3  move
; return: all regs undef
;
; procedure move entry
; procedure move name
; procedure move
;

b. g10, h10 w.

e33: am         f0-8   ; move entry: bytes = size of catalog entry
e32: al  w0     8      ; move name:  bytes = size of name
e31:                   ; move:
     rs. w3     h0.    ;    save(return);
     gg  w3     b100   ;    if mp-cpu then
     sh  w3     55     ;    begin
     jl.        g0.    ;
     mh  w2    (0)     ;      move halfwords(size, destination, source);
     jl.       (h0.)   ;      return;
                       ;    end;

g0:  ac  w3    (0)     ;    remaining := - bytes;
     sz  w3     1<1    ;    if odd number of words to move then
     jl.        g5.    ;      goto move single word;

g1:                    ; move double words:
     rs. w3     h1.    ;    save(remaining);
     sl  w3     h5     ;    if remaining does no exceed size of move-table
     jl.     x3+h4.    ;      then switch out through table;
                       ;    (otherwise move a whole portion)
h3:                    ; start of move-table:
     dl  w0  x2+30     ;
     ds  w0  x1+30     ;
     dl  w0  x2+26     ;
     ds  w0  x1+26     ;
     dl  w0  x2+22     ;
     ds  w0  x1+22     ;
     dl  w0  x2+18     ;
     ds  w0  x1+18     ;
     dl  w0  x2+14     ;
     ds  w0  x1+14     ;
     dl  w0  x2+10     ;
     ds  w0  x1+10     ;
     dl  w0  x2+6      ;
     ds  w0  x1+6      ;
     dl  w0  x2+2      ;
     ds  w0  x1+2      ;
h4:                    ; top of move-table:
h5 = h3 - h4           ; size of move-table (notice: negative)

     al  w1  x1-h5     ;    increase(to-address);
     al  w2  x2-h5     ;    increase(from-address);
     rl. w3     h1.    ;    restore(remaining);
     al  w3  x3-h5     ;    decrease(remaining);  (remember: negative)
     sh  w3    -1      ;    if not all moved yet then
     jl.        g1.    ;      goto move double words;

     jl.       (h0.)   ;    return;

g5:                    ; move single word:
     rl  w0  x2+0      ;
     rs  w0  x1+0      ;
     al  w1  x1+2      ;    increase(to-address);
     al  w2  x2+2      ;    increase(from-address);
     al  w3  x3+2      ;    decrease(remaining);  (remember: negative)
     jl.        g1.    ;    goto move double words;

h0:  0                 ; saved return
h1:  0                 ; remaining bytes (negative, multiplum of 4 bytes)
e.                     ;

; procedure find idle area  or pseudo;
;
; reg     call            return
; w0                        0
; w1                        unchanged
; w2                        proc
; w3      link              proc
;
b. h5,g5 w.
e40: rs. w3     h3.    ; begin
     al  w0     0      ;
     rl  w2     b5     ;
     al  w2  x2-2      ;
g0:  al  w2  x2+2      ;   repeat
     sn  w2     (b6)   ;     if end_of_name_table.area then
     jl.        j1.    ;        result 1;
     rl  w3  x2        ;     proc:=next;
     sn  w0  (x3+a11)  ;     test idle;
     se  w0  (x3+a50)  ;
     jl.        g0.    ;   until proc is idle;
                       ;
     rs. w2     d11.   ; found: set name table entry;
     rl  w2  x2        ;
     jl.        (h3.)  ;
h3:  0                 ; saved return;
e.


; procedure compare names
;
;   the names at name.work and name.param are compared
;
; call: w2 = chain addr, w3 = link
; exit: w0w1 = undef, w2w3 = unchanged
;
; return: link+0: not same name
;         link+2: the names are equal

e41:                   ; compare names:
     dl. w1     v13.   ;
     sn  w0 (x2+f55+0) ;    if first part of name.work <>
     se  w1 (x2+f55+2) ;       first part of name.chain then
     jl      x3        ;      return not same;

     dl. w1     v14.   ;    if second part of name.work <>
     sn  w0 (x2+f55+4) ;
     se  w1 (x2+f55+6) ;       second part of name.chain then
     jl      x3        ;      return not same;

     jl      x3+2      ;    return same;



; procedure for all named entries in cat do
;
;   the namekey.work is computed, and the current catalog is searched for
;     entries with name = name.work.
;   for each such entry the found-action is called
;
; call:  jl. w3  e42.
;        jl.     no more
;        <action for found entry>
;           w0w1 = base.entry, w2 = entry
;        (maybe save w2)
;        ...
;        (maybe restore w2, if changed)
;        jl      x3
;
; error return: result 2, in case of io-error
;
; return: link+0: no more entries (all regs undef)
;         link+2: w0w1 = base.entry, w2 = entry, w3 = continue search

b. h0 w.

e42:                   ; for all named entries in cat do:
     rs. w3     h0.    ;
     jl. w3     e3.    ;    compute namekey.work;
     rl. w2    d28.    ;    segment := segment.work

     jl. w3     e14.   ;    for all key entries do
     jl.       (h0.)   ;+2:   no more: goto no-more action;

; for each entry the name must be tested:
     dl. w1     v13.   ;
     sn  w0 (x2+f5+0)  ;
     se  w1 (x2+f5+2)  ;    if name.entry <> name.work then
     jl      x3        ;      return;

     dl. w1     v14.   ;
     sn  w0 (x2+f5+4)  ;
     se  w1 (x2+f5+6)  ;
     jl      x3        ;

; the name.entry was correct, now exit to check the base.entry
     dl  w1  x2+f2     ;    w0w1 := base.entry;
     am.       (h0.)   ;
     jl        +2      ;    call found-action and return;

h0:  0                 ; saved return;

e.                     ;



; procedure for all named procs in part of nametable do
;
;   the specified part of nametable is scanned for processes with
;     name.proc = name.work
;   for each process the found-action is called
;
; call:  jl. w3  e43.
;          <first>    ; e.g. b5 (=first area process in nametable)
;          <top>      ; e.g. b6 (=top   area process in nametable)
;        jl.     no more
;        <action for found process>
;           w2 = nametable address
;        (maybe save w2)
;        ...
;        (maybe restore w2)
;        jl      x3
;
; return: link+4: no more processes (all regs undef)
;         link+6: w0w1 = base.process, w2 = nametable address, w3 = continue

b. g10, h10 w.

e43:                   ; for all processes in part of nametable do:
     rl  w2 (x3+0)     ;    get first nametable address;
     rl  w0 (x3+2)     ;    get top   nametable address;
     al  w3  x3+6      ;
     ds. w0     h1.    ;    save(found-action address, top nametable address);

     al  w2  x2-2      ;
g1:                    ; next process:
     dl. w1     v13.   ;
g2:                    ;
     al  w2  x2+2      ;    increase(nametable address);
     sn. w2    (h1.)   ;    if nametable address = top name table address then
     jl.        g10.   ;      goto no-more action;

     rl  w3  x2+0      ;    proc := word(nametable address);

     sn  w0 (x3+a11+0) ;
     se  w1 (x3+a11+2) ;    if name.proc <> name.work then
     jl.        g2.    ;      goto next process;

     dl. w1     v14.   ;
     sn  w0 (x3+a11+4) ;
     se  w1 (x3+a11+6) ;
     jl.        g1.    ;

; the process-name was correct, now exit to check the base.process
     dl  w1  x3+a49    ;    w0w1 := base.process;
     al. w3     g1.    ;    return := next process;
     jl.       (h0.)   ;    call found-action;

g10: am.       (h0.)   ; no-more action:
     jl        -2      ;    goto no-more;

h0:  0                 ; return to found-action
h1:  0                 ; top name table address

e.                     ;



; procedure find idle process in part of nametable
;
;   the specified part of nametable is scanned until an idle process is found
;   (notice: it must exist)
;
; call:  jl. w3  e44.
;        <first>     ; e.g. b5 (= first area process in name table)
;
; return: cur proc nametable address is defined
;         w0 = 0, w1 = unchanged, w2 = proc, w3 = undef

b. g10 w.

e44:                   ; find idle process in part of nametable:
     al  w0     0      ;
     rl  w2 (x3)       ;    nametable address := param;
     se  w2    (b6)    ;    (if internal processes then skip procfunc itself)
     al  w2  x2-2      ;
g1:                    ; next process:
     al  w2  x2+2      ;    increase(nametable address);
     am     (x2)       ;    if name.process(nametable address) <> 0 then
     se  w0   (+a11)   ;
     jl.        g1.    ;      goto next process;

     rs. w2     d11.   ;    save(cur proc nametable addr);
     rl  w2  x2        ;    w2 := proc;
     jl      x3+2      ;    return;

e.                     ;



; procedure find chain
;
;   searches the chaintables in order to find a chainhead with
;     docname.chain = name
;
; call:  jl. w3  e45.
;        <name address>
;
; error return:  result 6, if name(0) = 0
;
; return: link+2: chain not found   (all regs undef)
;         link+4: chain found
;                   w2 = chain
;                   other regs undef

b. g10, h10 w.

e45:                   ; find chain:
     rl  w1  x3        ;    w1 := start of name;
     al  w1  x1+2      ;
     al  w2  x1+4      ;
     ds. w2     h2.    ;    save (first double, last double);

     al  w3  x3+2      ;
     rs. w3     h0.    ;    save (error return address);

     rl  w3     b22    ;    entry := first drumchain in name table;
     al  w3  x3-2      ;

g1:                    ; next chain:
     dl. w1    (h2.)   ;    w0w1 := last double word of name;
g2:                    ;
     al  w3  x3+2      ;    increase (entry);
     sn  w3    (b24)   ;    if all chains tested then
     jl.       (h0.)   ;      error return;

     rl  w2  x3        ;    chain := name table(entry);
     sn  w0 (x2+f61+4) ;
     se  w1 (x2+f61+6) ;    if name.chain <> name then
     jl.        g2.    ;      goto next chain;

     dl. w1    (h1.)   ;
     sn  w0 (x2+f61+0) ;
     se  w1 (x2+f61+2) ;
     jl.        g1.    ;

; a chain was found, with docname.chain = name
; check that the chain is not empty

     sn  w0     0      ;    if name(0) = 0 then
     jl.        j6.    ;      result 6;  i.e. nameformat illegal;

     am.       (h0.)   ;
     jl        +2      ;    return ok;

h0:  0                 ; return
h1:  0                 ; address of first double word of name
h2:  0                 ; address of last  double word of name

e.                     ;



; procedure search best entry in catalog
;
;   searches the current catalog for an entry with name.entry = name.work
;     and with the narrowest interval containing base.work
;   the entry is moved to work
;
; call:  jl. w3  e46.
;        jl.     not found
;        jl.     found
;
; error return: result 2, in case of io-error
;               result 6, in case of nameformat illegal
;
; return: link+0: no entry with name.entry = name.work was found
;                   with an interval containing base.work
;                 (all regs undef)
;         link+2: an entry was found:
;                   w0w1 = base.entry
;                   cur entry (and -segment) is defined
;                   entry is moved to work
;                 (all regs undef)

b. g20, h10 w.

e46:                   ; search best entry in catalog:
     rs. w3     h0.    ;    save(return);

     dl  w1     b40    ;    best base := system base;
     ds. w1     h2.    ;
     al  w0     0      ;    cur entry := 0;
     rs. w0     d3.    ;

     jl. w3     e42.   ;    for all named entries in catalog do
     jl.        g5.    ;+2:   no more: goto test any found;

; w0w1 = base.entry, w2 = entry, w3 = continue search
     sh. w0    (v1.)   ;    if base.entry does not contain base.work
     sh. w0    (h1.)   ;    or base.entry is not better than best base then
     jl      x3        ;      continue search;

     sl. w1    (v2.)   ;
     sl. w1    (h2.)   ;
     jl      x3        ;

; a better entry was found: save new base as best base
     bs. w0     1      ;    (code trick)
     al  w1  x1+1      ;    (code trick)
     ds. w1     h2.    ;    best base := base.entry;

; procedure save position
;
; call:  w2 = entry
;        jl. w3  e48.
; exit:  w2,w3 = unchanged

e48:                    ; save position:
     rl. w1     d8.+f36;    cur entry segment := current segment;
     ds. w2     d3.    ;    cur entry := entry;
     jl      x3        ;    return;;

g5:                    ; test any found:
     rl. w2     d3.    ;    if cur entry = 0 then
     sn  w2     0      ;      goto test format;
     jl.        g10.   ;    (i.e. no entries was found, maybe illegal name)

     jl. w3     e11.   ;    get current entry segment;
     al. w1     d1.    ;
     rl. w2     d3.    ;
     jl. w3     e33.   ;    move entry to work;

     dl. w1     v2.    ;    w0w1 := base.work;
     am.       (h0.)   ;    ok return;
     jl        +2      ;

g10:                   ; test format:
     jl. w3     e24.   ;    test format;
     jl.       (h0.)   ;    not-found return;

h0:  0                 ; saved return
h1:  0                 ; lower best interval - 1
h2:  0                 ; upper best interval + 1




; procedure search best process in nametable
;
;   searches the nametable for a process with name.process = name.work
;     and with the narrowest interval containing base.work
;
; call:  jl. w3  e47.
;          <first>    ; e.g. b5 (=first area process in nametable)
;          <top>      ; e.g. b6 (=top   area process in nametable)
;        jl.     not found
;        jl.     found
;
; return: link+4: no process with name.process = name.work was found
;                 (all regs undef)
;         link+6: a process was found:
;                   cur process nametable address is defined
;                   w0w1 = base.process, w2 = process
;                 (other regs undef)


e47:                   ; search best process in nametable:
     rs. w3     h0.    ;    save(return);

     dl  w1  x3+2      ;    get search limits;
     ds. w1     h5.    ;

     dl  w1     b40    ;    best base := system base;
     ds. w1     h2.    ;
     al  w0     0      ;    cur proc nametable address := 0;
     rs. w0     d11.   ;

     jl. w3     e43.   ;    for all named processes in part of nametable do
       0 ; e.g. b3     ; (start limit)
h5:    0 ; e.g. b7     ; (top limit)
     jl.        g20.   ;+6:   no more: goto test any found;

; w0w1 = base.process, w2 = nametable address, w3 = continue address
     sh. w0    (v1.)   ;    if base.process does not contain base.work
     sh. w0    (h1.)   ;    or base.process in not better than best base then
     jl      x3        ;      continue search;

     sl. w1    (v2.)   ;
     sl. w1    (h2.)   ;
     jl      x3        ;

; a better process was found, save new base and nametable address
     bs. w0     1      ;    (code trick)
     al  w1  x1+1      ;    (code trick)
     ds. w1     h2.    ;    best base := base.process;

     rs. w2     d11.   ;    cur process nametable address := nametable address
     jl      x3        ;    continue search;

g20:                   ; test any found:
     rl. w2     d11.   ;
     rl. w3     h0.    ;
     sn  w2     0      ;    if cur proc nametable address = 0 then
     jl      x3+4      ;      not-found return;

     rl  w2  x2        ;    proc := nametable (name table address);
     dl  w1  x2+a49    ;    w0w1 := base.proc;
     jl      x3+6      ;    ok-return;

e.                     ;


; insert statinf.
; this procedure moves the contents of the statarea of
; the work area to the current entry (docname area).
;
; call:  jl. w3  e49.
;
; return: all registers destroyed

e49: rl. w1  d3.       ; insert statinf;
     al  w1  x1+f11    ;
     al. w2  d30.      ;
     jl.     e32.      ;   goto move name;


; get statinf.
; this procedure moves the contents of the statarea in current entry
; to the work area.
;
; call:  jl. w3  e50.
;
; return:  all registers destroyed

e50: al. w1  d30.      ; get statinf:
     rl. w2  d3.       ;
     al  w2  x2+f11    ;
     jl.     e32.      ;   goto move name;

; lock and call monitor subprocedures.
; note: when called the used tabel-element will contain the return address,
;       but at return, the original content of the element is restored.

b.  i4  h.
                       ; monitor call table: <subprocedure address>,<tabel index>
i0:  b33,  k-i0-1      ;    remove writeprotect
     b35,  k-i0-1      ;    remove element
     b36,  k-i0-1      ;    link   element
     b37,  k-i0-1      ;    remove user
     b39,  k-i0-1      ;    insert reserver
     b46,  k-i0-1      ;    insert user
     b48,  k-i0-1      ;    check  user and reserver
w.                     ; table end;
i1:  0                 ; monitor entry
i2:  0                 ; tabel index
i3:  0                 ; saved w3 from monitor call
                       ;
e64: am         2      ;    check user and reserver
e58: am         2      ;    insert user
e57: am         2      ;    insert reserver
e56: am         2      ;    remove user
e55: am         2      ;    link element
e54: am         2      ;    remove element
e53:                   ;    remove writeprotect
     rx. w3     i0.    ; begin
     rs. w3     i1.    ;   monitor entry, index := monitor call(subroutine);
     hs. w3     i2.+1  ;   tabel index := monitor call;
     jl. w3     e65.   ;   lock monitor;
     zl. w3     i1.    ;
     jl  w3  x3        ;   call monitor subprocedure(monitor entry);
     rs. w3     i3.    ;   save w3
     jl. w3     e66.   ;   unlock monitor;
     rl. w3     i1.    ;   monitor call(tabel index):= monitor entry, index;
     am.       (i2.)   ;
     rx. w3     i0.    ;
     rx. w3     i3.    ;   restore w3 , save return
     jl.       (i3.)   ;   return
                       ; end;
                       ;
;
; lock and check user
;
e59:                   ; lock and check user
     rs. w3     i4.    ; begin
     jl. w3     e65.   ;   lock monitor;
     jl  w3     b47    ;   call check user;
     am        -2      ;   +0: not user
     al  w3     0      ;   +2: user
     wa. w3     i4.    ;
     al  w3  x3+2      ;   return addr := return addr + result;
     jl.        e66.   ;   unlock monitor and return;
                       ;
i4:  0                 ;
e.                     ; end;





; the following set of procedures handles the conversion of
;   logical sender-addresses (in case of rc8000)
;
; they all have a common call- and return-sequence:
;
; call:  jl. w2  e<number>
; return: w2 = abs address
;         w0, w1, w3 unchanged

b. g10, h10 w.

e60:                   ; get w1-abs:
     rs. w2     h0.    ;
     al  w2     a29    ;    w2 := rel of save w1;
     jl.        g0.    ;    goto get abs;

e61:                   ; get w2-abs:
     rs. w2     h0.    ;
     al  w2     a30    ;    w2 := rel of save w2;
     jl.        g0.    ;    goto get abs;

e62:                   ; get w3-abs:
     rs. w2     h0.    ;
     al  w2     a31    ;    w2 := rel of save w3;

g0:                    ; get abs:
     am.       (d2.)   ;
     rl  w2  x2        ;    w2 := saved wreg.sender (logical address);

g1:                    ; convert to abs:
c. 8000                ;    if rc8000 then
     am.       (d2.)   ;
     wa  w2    +a182   ;      w2 := logical address + base.sender;
z.                     ;
     jl.       (h0.)   ;    return;

h0:  0                 ; saved return


; procedure get abs address
;
; call:  al  w2  <logical addr>
;        jl. w3  e63.
;
; return: w2 = abs address
;         w0, w1, w3 unchanged

e63:                   ; get abs address
     rs. w3     h0.    ;
     jl.        g1.    ;    goto convert to abs;

e.                     ;


; lock monitor
; if mpu the monitor lock is locked else the interrupt disable limit is selected
;

b.  h1  w.
                       ; lock monitor
e65:                   ; begin
     am        (b9)    ;
h0=k                   ;   if mpu then
     jl.        0      ;   lock(monitor lock);
     lk         b51    ;
c.(:h0+a8-k-1:)        ;
     am         0      ;
r.(:h0+a8+2-k:)>1      ;   fill up;
z.                     ;
     jd      x3        ;   return disabled;
e.                     ; end;

; unlock monitor
; if mpu the monitor is released else the interrupt enable limit is selected

b.  h1  w.
                       ; unlock monitor
e66:                   ; begin
     am        (b9)    ;
h0=k                   ;   if mpu then
     jl.        0      ;   unlock(monitor lock);
     ul         b51    ;
c.(:h0+a8-k-1:)        ;
     am         0      ;
r.(:h0+a8+2-k:)>1      ;   fill up;
z.                     ;
     je      x3        ;   return enabled;
e.                     ; end;


; procedure clean area process(proc);
; reg    call       return
; w0                  0
; w1                unchanged
; w2     proc           -
; w3     link       number of oustanding buffers
;
b. h3  w.
e67: rs. w3     h3.    ; save return
     al  w0     0      ;
     rs  w0  x2+a11    ; name(0).area:=0;
     zl  w3  x2+a57    ;
     sn  w3     0      ; if number of outstanding buffers=0 then
     rs  w0  x2+a50    ; clear main;
     jl.        (h3.)  ;
h3:  0                 ; saved return;
e.



; the following set of procedures take care of all moves between
;   sender-process and procfunc.
;
; they all have a common call- and return-sequence:
;
; call:  jl. w3  e<number>
; return: all regs undef

b. h10 w.

;    size       procfunc addres

h1:  8   ,      v5     ; name.work
h2:  8   ,      v11    ; docname.work
h3:  f8  ,      v6     ; tail.work
h4:                    ; (chainhead)
h5:  f0  ,      d1     ; entry.work
h6:  12  ,      v6     ; registers to tail.work
h7:  18  ,      v6     ; internal params to tail.work
h8:  10  ,      v5     ; name + nametable addr
h9:  4*a110+4 , d16    ; bs-claims to bs-params

; moves from senders w1-area:
e76: am         h7-h9  ; internal params to tail.work:
e75: am         h9-h6  ; bs-claims to bs-params:
e74: am         h6-h5  ; registers to tail.work:
e73: am         h5-h3  ; complete entry to work:
e72: am         h3-h2  ; tail to tail.work:
e71: am         h2-h1  ; name to docname.work:
e70: dl. w1     h1.+2  ; name to name.work:
     jl. w2     e60.   ;    w2 := abs address of w1-area;
     jl.        e31.   ;    goto move;

; moves to senders w1-area:
e82: am         h1-h5  ; name.work to name:
e81: am         h5-h3  ; work to complete entry:
e80: dl. w1     h3.+2  ; tail.work to tail:
e83:                   ; bs-claims.cur.proc to sender area
     jl. w2     e60.   ;    w2 := abs address of w1-area;
     rx  w2     2      ;    exchange ..to.. and ..from..;
     jl.        e31.   ;    goto move;

; moves from senders w2-area:
e85: dl. w1     h2.+2  ; name to docname.work:
     jl. w2     e61.   ;    w2 := abs address of w2-area;
     jl.        e31.   ;    goto move;

; moves from senders w3-area:
e92: am         h4-h2  ; chainhead to work:
e91: am         h2-h1  ; name to docname.work:
e90: dl. w1     h1.+2  ; name to name.work:
     jl. w2     e62.   ;    w2 := abs address of w3-area;
     jl.        e31.   ;    goto move;

; moves to senders w3-area:
e96: am         h8-h1  ; name and nametable addr to name etc.:
e95: dl. w1     h1.+2  ; name.work to name:
     jl. w2     e62.   ;    w2 := abs address of w3-area;
     rx  w2     2      ;    exchange ..to.. and ..from..;
     jl.        e31.   ;    goto move;

e.                     ;



; the following set of procedures handles the interpretation
;   of the function-tables.
;
; most of the entries leave w0 and w2 unchanged

b. g20, h10 w.

h0 = 1                 ; size of instructions (in bytes)

h1:  0                 ; current instruction pointer
                       ;    (points at instruction being interpreted)
h2:  0                 ; first free in stack
h3:  0, r.3            ; stack

c.(:a92>22a.1:)-1
m.                test buffer pointers (first, last, next)
h4:  d49               ; first of test buffer
h5:  d50               ; top   of test buffer
h6:  d49               ; current  test address
z.


n2:  am         h0     ; skip 2 instructions:
n1:  am         h0     ; skip 1 instruction:
n0:  al  w3     h0     ; next instruction:
g0:  wa. w3     h1.    ;    w3 := abs addr of next instruction byte;
g1:  rs. w3     h1.    ;    save (cur instruction ptr);

; test start:
c.(:a92>22a.1:)-1
     rs. w3    (h6.)   ;    save (cur instr ptr) in test buffer;
     rl. w3     h6.    ;
     al  w3  x3+2      ;    increase (test buffer ptr);
     sl. w3    (h5.)   ;    (unless outside buffer);
     rl. w3     h4.    ;
     rs. w3     h6.    ;
     rl. w3     h1.    ;    (restore (cur instr ptr) )
z.
; test end

     bz  w3  x3        ;    w3 := instruction byte (positive integer);
; when the function is entered, w0, w1 and w2 are unchanged from last
;   function call.
; w3 = return to next instruction
     jl. w3  x3+n50.   ;    goto function (w3);
     jl.        n0.    ;    (if it was a procedure then goto next instruction)

n6:  am         h0     ; goto-action 2:  goto second param;
n5:  al  w3     h0     ; goto-action 1:  goto first param;
     wa. w3     h1.    ;    w3 := abs address of param byte;
     ba  w3  x3        ;    w3 := abs addr of next instruction;
     jl.        g1.    ;    goto save cur instruction address;

; procedure next param
;
; call: jl. w3  n10.
; return: w0 = next param (signed integer)

n10: al  w0     h0     ; next param:
     wa. w0     h1.    ;    w0 := abs addr of param byte;
     rs. w0     h1.    ;    save (cur instruction ptr);
     bl  w0    (0)     ;    w0 := param (cur instr ptr);
     jl      x3        ;    return;


; procedure call table program
;
; call: al  w3  <abs address of start of program>
;       jl.     n20.

n20: rl. w1     h1.    ; call table program:
     rs. w1    (h2.)   ;    stack (cur instr ptr);
     rl. w1     h2.    ;
     al  w1  x1+2      ;    increase (stack ptr);
g10: rs. w1     h2.    ;
     jl.        g1.    ;    goto save abs instr ptr;

n33: am         n5-n1  ; return to program and goto:
n31: am         n1-n0  ; return to program and skip:
n30: al. w3     n0.    ; return to program:
     rl. w1     h2.    ;
     al  w1  x1-2      ;    decrease (stack ptr);
     rs. w1     h2.    ;
     rl  w1  x1        ;    unstack (cur instr ptr);
     rs. w1     h1.    ;
     jl      x3        ;    goto next or skip or goto-action;


; subroutine call following program and return later to function
;
; call: jl. w3  n25.

n25: rl. w1     h2.    ; call from function:
     rs  w3  x1        ;    stack (return to function);
     rl. w3     h1.    ;
     rs  w3  x1+2      ;    stack (cur instr ptr);
     al  w1  x1+4      ;    increase (stack ptr);
     al  w3  x3+h0+h0  ;    w3 := abs addr of second byte;
     jl.        g10.   ;    goto save stackptr and cur instr ptr;

n35: rl. w1     h2.    ; return from program to function:
     al  w1  x1-4      ;
     rs. w1     h2.    ;    decrease (stack ptr);
     rl  w3  x1+2      ;    unstack (cur instr ptr);
     rs. w3     h1.    ;
     jl     (x1)       ;    return to unstack (function);



n50:                   ; base of interpretation addresses:



; start interpretation
;
;   the previous procfunc call is answerred and the next is awaited
;   the differrent pointers are initialized

j7:  am         7-6    ; result 7:
j6:  am         6-5    ; result 6:
j5:  am         5-4    ; result 5:
j4:  am         4-3    ; result 4:
j3:  am         3-2    ; result 3:
j2:  am         2-1    ; result 2:
j1:  am         1-0    ; result 1:
j0:  al  w0     0      ; result 0:
     jl. w3     e66.    ; unlock(monitor)
     rl. w1     d2.    ;    w1 := sender;
     rs  w0  x1+a28    ;    w0.sender := result;
     jl. w3     e1.    ;    set maincat;
     jl. w3     e7.    ;    terminate update;

j10: jd         1<11+2 ; waiting instruction:
     rl  w1     (b6)   ;    w1 := procfunc;
     rl  w1  x1+a15    ;    sender := next (messq (procfunc) ) - a16;
     al  w1  x1-a16    ;
     rs. w1     d2.    ;    save (sender);

     rl  w3  x1+a176   ;    w3 := monitor call number;
     ws. w3     h9.    ;    ( = word (ic.sender - 2) - jd 1<11+40 )

; w1 = sender
; w3 = monitor call number

     al. w2     h3.    ;
     rs. w2     h2.    ;    stack ptr := start of stack;
     ls  w3    -1      ;
     wa. w3     h10.   ;    cur instruction ptr := start table (monitor call);
     ba  w3  x3        ;
     jl.        g1.    ;    goto next instruction;
h9:  40                ; first procfunc monitor call
h10: n49               ; start of table


; redefinition of d-names

l2 : d2
l4 : d4
l14: d14
l15: d15

e.                     ;
▶EOF◀