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

⟦af9b50d09⟧ TextFile

    Length: 49920 (0xc300)
    Types: TextFile
    Names: »tpascrun«

Derivation

└─⟦2c55ea56f⟧ Bits:30001844 SW-save af projekt 1000, Alarm-system
    └─⟦6b41451d2⟧ 
        └─⟦this⟧ »tpascrun« 

TextFile


(pascrun = slang
pascrun)
; pascal runtime system
; version 16
; date 81.05.05▶05◀

b. g3 w.
d.
p. <:fpnames:>
l.
k = h55

s. c10, d50, e30, f25, p20, r155 w.

; the first part of the variables are used
; by various library procedures

d0:  0, r.5            ; +0:  (not used)
     0, r.5            ;+10:  (not used)
     0, r.5            ;+20:  (not used)
     0, r.5            ;+30:  stack chain for output

; the following variables describe the core-layout and some
; paging-dependant variables

; description of partitioning of core:
;
;
;  low addresses
;
;         !           !
;         !  runtime  !
;         !  system   !
;         !           !
;         !-----------!
;  d1 --> !           !  first of stack
;         !           !
;         !           !
;         !-----------!
;  d2 --> !           !  stacktop
;         !           !
;         !           !
;         !-----------!
;  d6 --> !           !  first of proc nearest to stack
;         !           !
;         !           !
;         !-----------!
;  d8 --> !           !  first of last loaded proc (=top of next to load)
;         !           !
;         !           !
;         !-----------!
;  d9 --> !           !  last killed by heap-reservation
;         !           !
;         !           !
;         !-----------!
;  d10--> !           !  last used of heap
;         !           !
;         !           !
;         !-----------!
;  d11--> !           !  first of resident code
;         !           !
;         !           !
;         !-----------!
;  d12--> !           !  first of procedure table
;         !           !
;         !           !
;         !-----------!
;  d13--> !           !  first of library table
;         !           !
;         !           !
;         !-----------!
;  d14--> !           !  top of procedure table
;         !           !
;         !  fpstack  !
;         !           !
;         !           !
;
;  high addresses



d1:  0-0-0             ; first of stack
d2:  0-0-0             ; top of stack
d3:  512               ; (minimum room between (d2) and (d6))
d6:  0-0-0             ; first of proc nearest to stack
d7:  512 + 00 + 00     ; (minimum room between (d2) and (d10))
d8:  0-0-0             ; first of last loaded procedure
d9:  0-0-0             ; last killed by heap-reserve
d10: 0-0-0             ; last used of heap

d11: 0-0-0             ; first of resident procedures
d12: 0-0-0             ; first of procedure table
d13: 0-0-0             ; first of library table
d14: 0-0-0             ; top of proc table

d15: 000               ; maximum page size (to be reserved above (d10)

; the next variables are used for page-transfers

d4:  <:pascallib:>,0,0 ; name of library
d5:  0, r.5            ; name of program file
d20: 0 ; zero          ; dummy name  (also used as illegal instruction by io-error)
d21: 3 < 12            ; input message
     0                 ;+2: first address
     0                 ;+4: last address (may also be top address)
     0                 ;+6: segment number
d22: 0                 ; spare message buffer
d23: 0, r.8            ; answer

; format of procedure table:
p0  = 0                ; segment number in program/library file
p2  = 2                ; if not in core:  negative size of procedure
                       ; if in core    :  top address of procedure
p4  = 4                ; if pascal procedure: size of stack-space
                       ; if library procedure: address of runtime error
p6  = 6                ; if in core    :  first address of procedure
                       ; if not in core:  zero, if never used
                       ;                  else old first address
p8  = 8                ; if pascal procedure: virtual address of first error line
                       ; if library procedure: saved stackref
p12 = 12               ; accumulated time (double word)
p14 = 14               ; number of calls
p10 =16               ; (size of entry)

; transfer
;
; call: w0 = segment number
;       w2 = return
;
; exit: return+0: transfer not ok:  w0 = logical status
;       return+2: transfer ok    :  w0 = 2

b. a10, b10 w.

b0:  0                 ; return

     am         d4-d5  ;f0-2:  w3 := library name;
f0:  al. w3     d5.    ;f0+0:  w3 := program name;
     rs. w0     d21.+6 ;   save segment number in message;

     rs. w2     b0.    ;   save(return);
     al. w1     d23.   ;   w1 := answer area;
     al  w2     0      ;
     rx. w2     d22.   ;   spare mess buf := 0;
     se  w2     0      ;   if spare mess buf was <> 0 then
     jd         1<11+18;     wait answer(spare mess buf);
                       ;   (it will only be zero just after startup,
                       ;    and in case of a break in this very procedure)

     rl. w1     d44.   ;
     al  w1  x1+1      ;   increase(blocksread);
     rs. w1     d44.   ;

a0:                    ; rep:
     al. w1     d21.   ;   w1 := message;
     jd         1<11+16;   send message(w1, w3);
     al. w1     d23.   ;   w1 := answer;
     jd         1<11+18;   w0 := wait answer(w1, w2);

     al  w2     1      ;   w2 := logical status :=
     ls  w2    (0)     ;     1 shift result
     sn  w2     1<1    ;
     lo  w2  x1        ;     + maybe status(answer);

     sn  w2     1<1    ;   if status = 2 and
     sh  w2 (x1+2)     ;      bytes transferred < 2 then
     jl.        a1.    ;
     jl.        a0.    ;     goto rep;
a1:                    ;

     sz  w2     1<1    ;   if result <> ok then
     jl.        a2.    ;     begin
     jd         1<11+52;     create area process (name);
     rs  w0  x3+8      ;     name table addr := undef;
     sn  w0     0      ;     if ok then
     jl.        a0.    ;       goto rep;
     al  w1  x3        ;     (prepare w1=name, for fp-exit)
     sn. w1     d5.    ;     if name = library name then
     jl.        h7.    ;       goto fp-end-program(name,status);
a2:                    ;     end;

     al  w0  x2        ;   w0 := logical status;

     al. w3     d20.   ;   w3 := dummy name;
     jd         1<11+16;   spare mess buf := send dummy message;
     rs. w2     d22.   ;

     rl. w2     b0.    ;
     sn  w0     1<1    ;   if transfer ok then
     jl      x2+2      ;     normal return
     jl      x2        ;   else error return;

e.                     ;


; kill
;
; call: w0 = first addr to kill
;       w1 = top addr to kill
;       w3 = return
;
; exit: w0 = unchanged
;       w1 = last addr to kill
;       w2 = unchanged
;       w3 = undef

b. a10, b10 w.

b0:  0                 ; first addr to kill
b1:  0                 ; last addr to kill
b2:  0                 ; return

f1:                    ;
     al  w1  x1-2      ;   w1 := last addr to kill;

     ds. w1     b1.    ;   save (first addr, last addr);
     rs. w3     b2.    ;   save (return);

     rl. w3     d14.   ;   entry := top of proc table;

a0:                    ; next:
     sn. w3    (d12.)  ;   if entry = first of proc table then
     jl.       (b2.)   ;     return;
     al  w3  x3-p10    ;   decrease(entry);

     sl  w1 (x3+p6)    ;   if last to kill < first (entry) or
     sl  w0 (x3+p2)    ;      first to kill >= top (entry) then
     jl.        a0.    ;     goto next;

; if 'returnaddr' is killed then
;   convert abs addr to:  abs proc table entry, rel addr
     rl. w0     d40.   ;   w0 := return addr;
     sl  w0 (x3+p6)    ;   if returnaddr inside proc (entry) then
     sl  w0 (x3+p2)    ;     <* note: can't be equal to top(proc) *>
     jl.        a5.    ;     begin

     ws  w0  x3+p6     ;     rel return addr := returnaddr - first (entry);
     ds. w0     d42.   ;     returnproc := entry;
     al. w0     f2.    ;     returnaddr :=
     rs. w0     d40.   ;       restore and return;

c. -1
m.*** begin testversion
  rs. w3  b9.
  al. w0  b10.
  rl. w3  b2.
  sh. w3  r8.    ; if not called from 'new' then
  jl. w3  h31.-2 ; outtext (warning)
  rl. w3  b9.
  jl.     a5.
b9: 0
b10: <:<10>***pascal warning: calling procedure killed<10><0>:>
m.*** end testversion
z.

a5:                    ;     end;

     rl  w0  x3+p6     ;   w0 := first (entry);

; optimize stack-reservation
     rl. w1     d6.    ;   if proc was nearest to stack then
     sl  w1 (x3+p6)    ;
     sl  w1 (x3+p2)    ;
     jl.        a6.    ;     begin
     rl  w1  x3+p2     ;
     rs. w1     d6.    ;     closest to stack := top(entry);
a6:                    ;     end;

     ws  w0  x3+p2     ;   last (entry) :=
     rs  w0  x3+p2     ;     negative size of procedure;

     dl. w1     b1.    ;   restore (first,last to kill);
     jl.        a0.    ;   goto next;

e.                     ;


; restore and return
;
; (called because returnaddr was kill'ed)
;
; call: d41, d42 = return point
;
; exit: w2 = unchanged

f2:                    ;
     jl. w1     f4.    ;   restore returnproc;
     jl        (0)     ;   return;


; get procedure and enter
;
; (called because procedure was not in core)
;
; call: w3 = rel (or abs) proc table entry
;
; exit: w1 = unchanged
;       w2 = unchanged
;      (w3 = abs proc table entry)

f3:                    ;
     al  w0  x1        ;   (save w1);
     jl. w1     f5.    ;   get procedure;
     rl  w1     0      ;   (restore w1);
     jl     (x3+p6)    ;   goto procedure;


; restore returnproc
;
; call: w1 = return
;       d41, d42 = return point
;
; exit: w0 = abs return addr
;       w2 = unchanged

b. b10 w.

b0:  0                 ;

f4:                    ;
     rs. w1     b0.    ;   (save return);
     dl. w0     d42.   ;   w0 := rel; w3 := proc table entry;
     jl. w1     f5.    ;   get procedure;
     wa  w0  x3+p6     ;   w0 := abs return := rel + first (entry);
     rs. w0     d40.   ;   returnaddr := abs return;
     jl.       (b0.)   ;   return;

e.                     ;


; get procedure
;
; call: w1 = return
;       w3 = abs proc table entry
;
; exit: w0 = unchanged
;       w1 = undef
;       w2 = unchanged
;       w3 = abs proc table entry

b. a10, b10 w.

b0:  0                 ; saved w0
b1:  0                 ; return
b2:  0                 ; saved w2
b3:  0                 ; abs proc table entry
b4:  0                 ; expected top
b5:  0                 ; calling proc

f5:                    ;

     ds. w1     b1.    ;
     ds. w3     b3.    ;

     rl  w0  x3+p2     ;   if top (entry) > 0 then
     sl  w0     0      ;     <* proc is in core *>
     jl.        a10.   ;     goto return;

     rl. w1     d43.   ;   calling proc :=
     rs. w1     b5.    ;     current pascal proc;

; w0 = negative size of procedure

; step 1: try to fit just above last loaded procedure

     wa. w0     d8.    ;   w0 := expected first addr;

a0:                    ; test against stack:

     al  w1    -1<9    ;   ps stacktop :=
     la  w1  x3+p2     ;       (rounded size of procedure
     ac  w1  x1        ;
     wa  w1  x3+p2     ;       + negative size of procedure
     wa. w1     d2.    ;       + stacktop
     wa. w1     d3.    ;       + min room between stack and code;

     sl  w0  x1        ;   if expected first >= ps stacktop then
     jl.        a2.    ;     goto found;

; step 2: try to fit just above heap

     rl  w0  x3+p2     ;   w0 := expected first addr;
     wa. w0     d10.   ;

     sh  w0  x1-2      ;   if expected first < ps stacktop then
     jl.        e1.    ;     alarm (process too small);
                       ; <* should never occur, if 'd7' is properly set *>

a2:                    ; found:

; step 3: set (first,last) in procedure table

     rs  w0  x3+p6     ;   first (entry) := expected first;
     ws  w0  x3+p2     ;   expected top := expected first
     rs. w0     b4.    ;            - negative size of procedure;

; step 4: compute first addr of transfer
;         (it has already been tested that it will
;           not interfere with the stack)

     al  w0    -1<9    ;   w0 := negative size
     la  w0  x3+p2     ;     rounded to integral number of used segments
     wa. w0     b4.    ;   + top of procedure;

     rl. w1     b4.    ;   w1 := top of procedure;
     al  w1  x1-2      ;   w1 := last of procedure;
     ds. w1     d21.+4 ;   save (first,last) in message;

; step 4a: the procedure may not cross the maxpage boundary
;          just above the heap

     rl. w3     d10.   ;   boundary := last used of heap
     ws. w3     d15.   ;             - maximum page size;

     sl  w1  x3        ;   if last of transfer >= boundary and
     sl  w0  x3        ;     first of transfer <  boundary then
     jl.        a3.    ;     begin
     al  w0  x3        ;     first := boundary;
     jl.        a5.    ;     goto set expected first;
a3:                    ;     end;

; step 5: avoid killing of calling procedure
;         (used by: call library procedure (optimization)
;                   call pascal procedure (because of string params)

     al  w3     0      ;   calling proc := 0;
     rx. w3     b5.    ;   w3 := old calling proc;
     sn  w3     0      ;   if calling proc <> 0 then
     jl.        a6.    ;     begin

     sl  w1 (x3+p6)    ;     if last of transfer >= first (proc) and
     sl  w0 (x3+p2)    ;        first of transfer < top (proc) then
     jl.        a6.    ;       begin

; the calling proc was about to get kill'ed.
; try to fit the call'ed procedure just above it.
; repeat from step 1a.

     rl  w0  x3+p6     ;       w0 := first (calling proc);
a5:                    ; set expected first:
     rl. w3     b3.    ;       (restore called proc entry);
     wa  w0  x3+p2     ;       w0 := expected first addr :=
                       ;         first(calling) + negative size(called);
     jl.        a0.    ;       goto test against stack;
a6:                    ;       end;
                       ;     end;

; step 6: kill all procedures touched by the transfer
;
; w0 = first of transfer
; w1 = last  of transfer

     al  w1  x1+2      ;   w1 := top of transfer;
     jl. w3     f1.    ;   kill;
     rl. w3     b3.    ;   (restore proc entry);
     al  w1  x1+2      ;

; step 7: compute top addr for next procedure to be loaded

     rl  w0  x3+p6     ;   w0 := first of procedure;
     rs. w0     d8.    ;   first of last loaded := first of procedure;

; step 8: optimize stack-reserve and heap-reserve

     sh. w0    (d6.)   ;   if top of next loaded <= closest to stack then
     rs. w0     d6.    ;     closest to stack := top of next loaded;

     sl. w1    (d9.)   ;   if top (entry) >= last killed by heap then
     rs. w1     d9.    ;     last killed by heap := top (entry);

; step 9: load the procedure from program- or library file

     rl  w0  x3+p0     ;   w0 := segm number (entry);
     sl. w3    (d13.)  ;   if entry >= first of library table then
     am        -2      ;     transfer from library file
     jl. w2     f0.    ;   else transfer from program file;
     jl.        e3.    ;+2:    io-error

     dl. w3     b3.    ;   restore(w2, proc table entry);
     rl. w0     b4.    ;
     rs  w0  x3+p2     ;   top(entry) := expected top;

; step 10: exit

a10:                   ; return:
     dl. w1     b1.    ;
     jl      x1        ;   return;

e.                     ;


; break routine

b. a10 w.

c0:                    ; interrupt address:
     jd         1<11+0 ;   set interrupt address;
     rs. w1     d2.    ;   top of stack := w1;
     al  w0     0      ;   w0 := procedure number of main program;
     jl  w3     (x2-2047)    ;   call pascal procedure
       0               ;+2:  occupied in stack = 0

     r. (:c0.+h76:)>1+1; (fill up to size of dumped regs)
c1:                    ; top of regdump

     dl. w3     c0.+12 ;   w3 := cause; w2 := ic;
     se  w3     0      ;   if cause = 0 and
     jl.        a2.    ;
     bl  w0  x2-2      ;     (w0 := break'ed instruction)
h.   se  w0,    ks  w. ;     instruction = 'ks' then
     jl.        a2.    ;     begin

a0:                    ; enter fp-break:
     al. w1     h10.   ;     move registers to fp;
a1:                    ;
     rl  w0  x1+c0-h10 ;
     rs  w0  x1        ;
     al  w1  x1+2      ;
     se. w1     h10.+h76;
     jl.        a1.    ;

     jl      x1        ;     goto fp-break routine;
a2:                    ;     end;

m.*** temporary: prevent calling break recursively
al  w0  2
hs. w0  a0.-1

; if break occured inside runtime system then don't destroy returnaddr
     sl. w2    (d2.)   ;   if ic >= stacktop then
     rs. w2     d40.   ;     returnaddr := ic;

     rl. w0     c0.+14 ;   w0 := effective address;
     se  w0    -2047   ;   if w0=nilvalue (e.g. after indirect)
     bs  w0  x2-1      ;   or w0 - instr.disp = nilvalue
     sn  w0    -2047   ;     (e.g. before indirect) then
     am         24-5   ;     errorcode := illegal pointer value
                       ;   else

     am         5-3    ;   errorcode := break;
e3:  am         3-1    ; ioerror:
e1:  am         1-25   ; process too small:
e25: al  w1     25     ; dispose outside heap:

; call alarm-segment and transfer the returnpoint

c2:                    ; call and enter alarm:
; call: w0 = additional error inf
;       w1 = text number
;       d39 = stackref
;       d40 = returnaddr (i.e. addr where error occured)
;      (d41,d42 = returnpoint, if returnaddr just kill'ed)

     rs. w0     d46.   ;   save (additional error inf);

     rs. w1     d38.   ;   save (text number);

     rl. w0     d40.   ;   w0 := returnaddr;
     rl. w3     d14.   ;   w3 := top of library table
a3:                    ; next:
     sn. w3    (d12.)  ;   if entry = first of proc table then
     jl.        a4.    ;     goto returnpoint set;
     al  w3  x3-p10    ;   decrease (entry);

     sh  w0 (x3+p2)    ;   if returnaddr > top (entry) or
     sh  w0 (x3+p6)    ;      returnaddr <= first (entry) then
     jl.        a3.    ;     goto next;
                       ; <* returnaddr can never be the first instruction
                       ;    in a procedure, but may well be the last *>

     ws  w0  x3+p6     ;   w0 := rel addr := returnaddr - first(entry);
     ds. w0     d42.   ;   save in return point;

a4:                    ; return point set:
; call alarm:
     rl. w3     d13.   ;
     jl. w1     f5.    ;   get procedure ( alarm segment);
     rl  w0  x3+p6     ;
     rl  w1  x3+p6     ;
     al  w1  x1+512    ;
     jl. w3     f1.    ;   kill first segment of procedure;
     ds. w1     d21.+4 ;   first,last in message := first of procedure;

     rl. w0     d12.   ;   w0 := first of procedure table;
     al. w1     c0.    ;   w1 := addr of interrupt routine;
     rl. w2     d13.   ;   w2 := first of library table;
     jl  w3 (x2+p6)    ;   enter alarm procedure;
d38: 0                 ;+0:  error number
d39:   0               ;+2:  stackref when error occured
d40:   0               ;+4:  abs returnaddr where error occured
d41:   0               ;+6:  return point:  abs proc table entry
d42:   0               ;+8:                 rel return addr
d43:   0               ;+10: current pascal procedure
       jl.   a0.       ;+12: goto enter fp-break
       jl.   f0.       ;+14: goto transfer from program file
d44:   0               ;+16: blocksread
d45:   0               ;+18: abs return addr of last library call
d46:   0               ;+20: additional error inf
 0
d47: 0   ; +22, +24:  time stamp

e.                     ;


; runtime error
;
; call: w0 = additional error inf
;       w1 = error number (0==program end)
;       w2 = stackref
;       w3 = address where error occured

r1:                    ;
     ds. w3     d40.   ;
     jl.        c2.    ;   goto call and enter alarm


; call library procedure
;
; call: w0w1 = parameters
;       w2   = stackref
;       w3   = return inf
;         x3+0:  library pageno < 12 + rel entry addr
;         x3+2:  maybe further parameters to library procedure

b. b10 w.

b0:  0                 ; saved w0
b1:  0                 ; saved w1
b10: p10               ; const: size of entry in proc tables

r3:                    ;
     ds. w3     d40.   ;   save (stackref, return);
     ds. w1     b1.    ;   save params;

     bl  w1  x3        ;
     wm. w1     b10.   ;   w0 := 0;  w1 := rel library entry;
     wa. w1     d13.   ;
     al  w3  x1        ;   w3 := abs library proctable entry;


     rs  w2  x3+p8     ;   save stackref in library proctable entry;

     sl  w0 (x3+p2)    ;   if library proc not in core then
     jl. w1     f5.    ;     get procedure;
     al  w2  x3        ;   w2 := library proc entry;

; since the library procedure may need to access parameters on
; the calling procedure page, it will be checked that the calling
; procedure is in core (but maybe at a new place)

     rl. w0     d40.   ;
     sn. w0     f2.    ;   if calling proc just kill'ed then
     jl. w1     f4.    ;     restore returnproc;

; begin test version
     rl  w1  x2+p2     ;   if library proc not in core anymore then
     sh  w1    -1      ;
     jl.        e1.    ;     alarm...
; end test version

     rl. w3     d40.   ;   w3 := abs return addr;

     rs. w3     d45.   ;   (remember return addr, in case of errors)

     bz  w0  x3+1      ;   w0 := rel entry addr
     wa  w0  x2+p6     ;       + first (library proc);
     rx. w0     b0.    ;
     rl. w1     b1.    ;   restore (params);

     jl.       (b0.)   ;   goto library proc;
; at entry to library proc:
;   w0w1 = params
;   w2   = abs addr of library proc table entry
;     x2+p8 = saved stackref
;   w3   = abs return addr

e.                     ;


; call pascal procedure
;
; call: w0 = procedure number
;       w1 = abs addr of old display
;       w2 = current stackref
;       w3 = addr of call descriptor
;        x3+0:  stack space used by calling procedure

b. a10, b10 w.

b0:  0                 ; calling proctable entry
b1:  0                 ; old display

r4:                    ;
     ds. w3    d40.    ;   save (stackref, return);
     rs. w1     b1.    ;   save (old display);

     al  w1  x2        ;   w1 := old stackref;
     wa  w2  x3+0      ;   new stackref := old stackref + used space;
     rs  w1  x2-2037   ;   activation record.dynamic list := old sref;

     al  w1     p10    ;   w1 := entry size * procedure number
     wm  w1     0      ;
     wa. w1     d12.   ;       + first of procedure table;

     al  w0  x3+2      ;   w0 := abs return address; (* i.e. skip param *)

     al  w3  x1        ;   w3 := abs addr of called proc table entry;

     rl. w1     d43.   ;   w1 := current pascal procedure;
     ws  w0  x1+p6     ;   w0 := rel return;
     ds  w1  x2-2041   ;   activation record.return point :=
                       ;     (rel return, proc table entry);

     al  w1  x2        ;   w1 := abs stacktop :=
     wa  w1  x3+p4     ;     new sref + reserve (called proc);

; test that the new stackspace can be reserved
; step 1: first test that it is possible to reserve that much stack

     rl. w0     d10.   ;   limit := last used of heap
     ws. w0     d7.    ;          - room between stack and heap;
     sh  w0  x1-2      ;   if abs stacktop > limit then
     jl.        e1.    ;     alarm(process too small);

; step 2: second, if new stacktop does not kill any pages then ok
;         (remember to leave some room between stack and program)

     rl. w0     d6.    ;   limit := first of proc nearest to stack
     ws. w0     d3.    ;          - room between stack and program;
     sl  w0  x1        ;   if abs stacktop <= limit then
     jl.        a5.    ;     goto stack reserved;

     rs. w3     b0.    ;   save (entry);
     rl. w0     d2.    ;   w0 := first to kill := old stacktop;
     rs. w1     d2.    ;   stacktop := new stacktop;
     wa. w1     d3.    ;   w1 := top to kill := new stacktop + spare room;
     sl. w1    (d6.)   ;   if top to kill >= first of proc nearest to stack then
     rs. w1     d6.    ;    first of proc nearest to stack := top to kill;
     jl. w3     f1.    ;   kill;
     rl. w3     b0.    ;   restore (entry);
     rl. w1     d2.    ;   restore (new stacktop);

a5:                    ; stack reserved:
     rs. w1     d2.    ;   stacktop := new stacktop;
     sl  w1 (x3+p2)    ;   if called proc not in core then
     jl. w1     f5.    ;     get procedure;
     rs. w3     d43.   ;   current pascal procedure := called proc;

; prepare alarm-inf, in case the procedure is breaked
; before it makes any runtime-system calls

     rl  w3  x3+p6     ;
     ds. w3     d40.   ;   save (stackref, returnaddr);

     rl. w1     b1.    ;   w1 := old display;
     jl      x3        ;   goto procedure start;
; at entry to pascal procedure:
;   w1 = abs addr of old display
;   w2 = new stackref

e.                     ;


; return from pascal procedure
;
; call: w2 = current stackref

b. a10, b10 w.

b10: p10                ; size of procedure table entry

r6:                    ;
     ds. w3     d40.   ;   save (stackref, return);

     dl  w1  x2-2041   ;   w0 := rel return; w1 := return proc entry;

     sh. w1     0      ;   if after 'goto' to surrounding block then
     jl. w3     a10.   ;     convert procedure number to abs proc table entry;

     al  w3  x1        ;   w3 := abs proc table entry;
     rl  w2  x2-2037   ;   w2 := dynamic link;

     al  w1  x2        ;   stacktop :=
     wa  w1  x3+p4     ;     stackref + reserve (return proc);
     rs. w1     d2.    ;

; prepare nice printout, in case of break before procedure is loaded

     ds. w0     d42.   ;   returnpoint := (abs proc entry, rel return);
     al. w1     f2.    ;   simulate just kill'ed;
     rs. w1     d40.   ;
     rs. w2     d39.   ;   save stackref;

     rs. w3     d43.   ;   current pascal proc := return proc;
     sl  w1 (x3+p2)    ;   if proc not in core then
     jl. w1     f5.    ;     get procedure;

     wa  w0  x3+p6     ;   abs return := rel return + first (entry);
     jl        (0)     ;   goto procedure;

a10:                   ; convert procedure number to abs proc table entry:
     wm. w1     b10.   ;   w1 := proc entry := procedure number * entry size;
     wa. w1     d12.   ;   w1 := abs procedure table entry;

     rl  w0  x2-2043   ;   (restore w0)
     jl      x3        ;   return;

e.                     ;


; value initialization
;
; call: w0 := abs address in stack
;       w1 = no of segms to read
;       w2 = stackref
;       w3 = return addr
;         x3+0: segment number in program file
; exit: w0 = undef
;       w1 = undef
;       w2 = stackref
;       w3 = undef

b. b10 w.
b0:  0
b1:  0
r7:                    ;
     ds. w3     d40.   ;   save (stackref, returnaddr);

     ls  w1     9      ;   top of transfer := segments * 512
     wa  w1     0      ;                    + first of transfer;
     ds. w1     d21.+4 ;   save (first, top) in message;
     rl  w0  x3        ;   w0 := segment number;
     al  w3  x3+2      ;   (prepare eventual kill of program-page)
     rs. w3     d40.   ;   return := after param;
     jl. w2     f0.    ;   transfer;
     jl.        e3.    ;+2:   ioerror;

; the previous transfer did'nt test for overwriting of any
; program-pages
     dl. w1     d21.+4 ;   w0w1 := first,last to kill;
     jl. w3     f1.    ;   kill;
     dl. w3     d40.   ;   restore (stackref, returnaddr);
     jl      x3        ;   return;  (notice: automatic page-recovery)
e.


; new
;
; call: w0 = number of halfwords to reserve
;       w1 = address of pointer variable
;       w2 = stackref
;       w3 = return 
;
; exit: w0 = undef
;       w1 = undef
;       w2 = stackref
;       w3 = undef

b. a10, b10 w.

b0:  0                 ; number of halfwords
b1:  0                 ; addr of pointer variable

r8:                    ;
     ds. w3     d40.   ;   save (stackref, returnaddress);
     ds. w1     b1.    ;   save (number of halfwords, addr of pointer);

; test that it is possible to allocate the wanted number of halfwords
; without having to kill any program pages

     rl. w0     d10.   ;   new last of heap := last of heap
     ws. w0     b0.    ;                     - wanted space;
     sl. w0    (d9.)   ;   if new last of heap >= last killed by heap then
     jl.        a5.    ;     goto heap reserved;

; it was nescessary to kill some pages.
; start by checking the amount to reserve

     rl. w1     d2.    ;   limit := stacktop
     wa. w1     d7.    ;        + room between stack and heap;
     sh  w0  x1-2      ;   if new last of heap < limit then
     jl.        e1.    ;     alarm(process too small);

     rs. w0     d9.    ;   last killed by heap := new last of heap;

     sh. w0    (d8.)   ;   if first to kill <= first of last loaded then
     rs. w0     d8.    ;     first of last loaded := first to kill;
     rl. w1     d10.   ;   top to kill := last of heap;
     jl. w3     f1.    ;   kill;

a5:                    ; heap reserved:
     rs. w0    (b1.)   ;   pointer variable := last of head;

a7:                    ; kill at maxpage boundary:
; w0 = new last used of heap
     rs. w0     d10.   ;   last used of heap := new last of heap;

     ws. w0     d15.   ;   boundary := last used of heap- maxpage size;
     rl  w1     0      ;   first,top to kill := boundary;
     jl. w3     f1.    ;   kill;

     jl.       (d40.)  ;   return;



; dispose
;
; call: w0 = number of halfwords to release
;       w1 = addr of pointer variable, pointing to the heap
;       w2 = stackref
;       w3 = return
;
; exit:
;       w0 = undef
;       w1 = undef
;       w2 = stackref
;       w3 = undef

r9:                    ;
     ds. w3     d40.   ;   save (stackref, returnaddress);

     wa  w0  x1        ;   w0 := new last of heap := top of record;

; test that the record really was within the heap
     rl  w3  x1        ;   w3 := first of record;
     bs. w0     1      ;   w0 := last of record;
     sl. w3    (d10.)  ;   if first of record < last of heap or
     sl. w0    (d11.)  ;      last  of record >= first of resident code then
     jl.        e25.   ;     alarm(try to release not used area);
     ba. w0     1      ;   w0 := new last used of heap := top of record;

     al  w3    -2047   ;
     rs  w3  x1        ;   pointer variable := nil;

     jl.        a7.    ;   goto kill at maxpage boundary;

e.                     ;


r15:                   ; top of resident code, if not mode listing:

; alternative call and return from procedure
; accumulate time spent in procedure, and count number of activations

b. a10, b10 w.
b0: 0    ; saved w0
b1: 0    ; saved w1

r41:
     ds. w3     d40.     ; save (stackref, return )
     ds. w1     b1.      ; save ( old display )

     dl  w1     110      ; time of day
     dl. w3     d47.     ; old time
     ds. w1     d47.     ; update old time
     ss  w1     6        ; w0 1 := time delta
     rl. w3     d43.     ; address ( proc table )
     aa  w1  x3+p12      ; add time delta
     ds  w1  x3+p12      ; restore new acc. time

     dl. w3     d40.     ; goto normal call procedure
     dl. w1     b1.
     jl.        r4.+2

e.

b.  w.

r61:
     ds. w3     d40.     ; alternative return
     dl  w1     110      ; time of day
     dl. w3     d47.     ; old time
     ds. w1     d47.     ; updated old time
     ss  w1     6        ; w0 1 := time delta
     rl. w3     d43.     ; addrss ( proc table )
     aa  w1  x3+p12      ; add time spent
     ds  w1  x3+p12      ;

     rl  w1  x3+p14      ; increment( number of calls )
     al  w1  x1+1
     rs  w1  x3+p14

     dl. w3     d40.     ; goto normal return from procedure
     jl.        r6.+2

e.
r151:                    ; top of resident code if mode listing:


 
\f


; initialization code.
; at entry the situation is as follows :
;   w0 - abs add of process start + h55
;   w1 - abs add of process start
;   w2 - abs add of first item in fp-stack
;   w3 - abs add of item containing program name
;
; the init code takes care of the following points :
;   1) test for correct program call
;   2) set interrupt address
;   3) set abs add of some runtime entries in bottom of stack
;   4) create area process to object file and pascallib
;   5) read procedure table into core from object file
;   6) initialize procedure table entries (incl. entries concerning pascallib)
;  6a) input resident procedures
;   7) input main program and jump to entry of main
;   8) global variables are initialized when the values
;      become available
;
\f


; the object file contains the following :
;  - code for each procedure
;  - value blocks to value initialization
;  - procedure table
;  - information segment (heapsize,noofproc * 10 etc)
;  - line error table
;
; each of these types of items occupies an integral
; number of bs-segments. this means that a new item always
; starts on a bs-segment boundary.
; the segment number of the information segment is found in
; the catalog tail for the object file.
; the catalog entry tail contains in +17 cont key<12 + segmno of inf
;
; the information segment contains :
;  +0 heapsize
;  +2 no of procedures
;  +4 segment no of procedure table
;  +6 segment no of line error table
;  +8 proc number of first resident procedure
; +10  -     -    -  second    -       -
;   .
;   .
;  +n -1  (end of resident procedures)

b. a40, b20 w.

b0 = 8                 ; size of proc table entry in inf segment

b1:  4<12 + 10         ; spacename
b3:  0, r.10           ; tail for lookup entry
b4:  0                 ; first of process
b5:  0, r.256          ; buffer for init-segment
b7:                    ; list of library procedure sizes
     1536  ;  page 0
     512   ;  page 1
     512   ;  page 2
     512   ;  page 3
     1024  ;  page 4
     1024  ;  page 5
     1024  ;  page 6
     512   ;  page 7
b8:  (: k - b7 :) / 2 * p10 ; size of library proc table
b9:  0                 ; proc table entry
b10: 0                 ; size of proc
b11: 0                 ; pointer variable

g3:                    ; start of initialization:
     rs. w1     b4.    ;   save (first of process);
     rs. w2     d14.   ;   top of proc table := first of command;

     rl. w0     d5.    ;   if program file name already set then
     se  w0     0      ;
     jl.        a2.    ;     goto program file name found;

     rs. w3     d14.   ;   save (addr of program name item, i.e. 'pascrun')

a0:                    ; get program file name:
     ba  w3  x3+1      ;   w3 := first parameter;
     rl  w0  x3        ;   if separator <> spacename then
     se. w0    (b1.)   ;
     jl.        a20.   ;     init error (error in call);

     dl  w1  x3+4      ;   w0w1 := first part of program file name;
     se  w0     0      ;   if first part = 0 then
     jl.        a1.    ;     begin <* after replace *>
     am.       (b4.)   ;
     rs  w1     h51    ;     fp-modebits := second word;
     jl.        a0.    ;     goto get program file name;
a1:                    ;     end;
     ds. w1     d5.+2  ;
     dl  w1  x3+8      ;   move param to program file name;
     ds. w1     d5.+6  ;

; remove the 'pascrun'-name from the command stack
;   (this will make it easier for 'system'...)

     rl. w2     d14.   ;   w2 := addr of program name item;

     bl  w0  x2+0      ;   w0 := preceding separator;
     se  w0     6      ;   if separator = 'equal' then
     jl.        a3.    ;     begin
     dl  w1  x2-0      ;     move lefthand side up in
     ds  w1  x3-0      ;       front of file name;
     dl  w1  x2-4      ;
     ds  w1  x3-4      ;
     dl  w1  x2-8      ;     (don't forget the '=' item...)
     ds  w1  x3-8      ;
     al  w3  x3-10     ;     first of command := addr of lefthand item;
a3:                    ;     end;
     rs. w3     d14.   ;   top of proc table := first of command;
     rl. w2     b4.    ;
     rs  w3  x2+h8     ;   current command := first of command;

a2:                    ; program file name found:
     al. w1     b3.    ;
     al. w3     d5.    ;
     jd         1<11+42;   lookup entry (file name);
     se  w0     0      ;   if not ok then
     jl.        a21.   ;     init error (object file not ok);
     sh  w0  (x1)      ; if size < 0 then
     jl.        a4.    ; begin
     dl. w1   b3.+4    ;   move docname( entry ) to filename
     ds  w1   x3+2     ;
     dl. w1   b3.+8    ;
     ds  w1   x3+6     ;
     al. w1   b3.      ;
     jd       1<11+42  ;   lookup entry (file name)
     se  w0   0        ;   if not ok then
     jl.      a21.     ;     init error (object file not ok);
a4:                    ; end;
     jd         1<11+52;   create area process (file name);
     se  w0     0      ;   if not ok then
     jl.        a22.   ;     init error (area process not created);

     al. w3     d4.    ;
     jd         1<11+52;   create area process(library file);
     se  w0     0      ;   if not ok then
     jl.        a22.   ;     init error (area process not created);

; prepare initialization of primary input/output
     rl. w1     b4.    ;

     al. w0     d20.   ;
     rs  w0  x1+h20+h2+2;   primary input.giveup action := 'dummy name';
     rs  w0  x1+h21+h2+2;   primary output.giveup action:= 'dummy name';

     al  w0     0      ;
     al  w2     1      ;
     al  w3     10     ;

; initialize primary input
     hs  w0  x1+h20+h4+0;   primary input.eof := false;
     hs  w2  x1+h20+h4+1;   primary input.eoln := true;
     rs  w3  x1+h20+h4+4;   primary input.filebuf := newline char;
     hs  w2  x1+h20+h2+6;   primary input.zonestate := after read char;
     hs  w2  x1+h20+h2+7;   primary input.kind := textfile;

; initialize primary output
     hs  w2  x1+h21+h4+0;   primary output.eof := true;
     hs  w2  x1+h21+h2+7;   primary output.kind := textfile;
     al  w2     3      ;
     hs  w2  x1+h21+h2+6;   primary output.zonestate := after write char;

; step 2: get inf segment
     al. w3     b5.    ;
     al  w0  x3+510    ;
     ds. w0     d21.+4 ;   save (first,last) in message;
     rl. w2     b3.+0  ;   w2 := entry size;
     al  w0  x2-1      ;   w0 := segment number := size - 1;
     jl. w2     f0.    ;   transfer from program file;
     jl.        a23.   ;+2:   io-error

; step 3: initialize pointers
     rl. w3     d14.   ;   w3 := top := top of procedure table;

     ws. w3     b8.    ;   top := top - size of library table;
     rs. w3     d13.   ;   first of library table := top;

     al  w1     p10    ;   size of procedure table :=
     wm. w1     b5.+2  ;     entry size * number of procedures;

     ws  w3     2      ;   top := top - size of procedure table;
     rs. w3     d12.   ;   first of procedure table := top;

     rs. w3     d11.   ;   first of resident := top;
     rs. w3     d10.   ;   last used of heap := top;
     rs. w3     d9.    ;   last killed by heap := top;
     rs. w3     d8.    ;   first of last loaded := top;
     rs. w3     d6.    ;   first of proc nearest to stack := top;

; step 4: read procedure table into core

     al  w3     b0     ;   w3 := size of entry in inf segment
     wm. w3     b5.+2  ;       * number of procedures
     al  w3  x3+511    ;
     ls  w3    -9      ;
     ls  w3     9      ;      rounded up to size of used segments;

     al. w3  x3+b6.    ;   w3 := last of transfer;
     al  w3  x3-2      ;
     sl. w3    (d12.)  ;   if last of transfer >= first of procedure table then
     jl.        a24.   ;     init error(process too small);

     al. w2     b6.    ;   w2 := first of transfer;
     ds. w3     d21.+4 ;
     rl. w0     b5.+4  ;   w0 := segment number of procedure table;
     jl. w2     f0.    ;   transfer from program file;
     jl.        a23.   ;+2:   ioerror

; step 5: initialize procedure table

     al. w2     b6.    ;   w2 := first of procedure table buffer;
     rl. w3     d12.   ;   w3 := first of procedure table;
     rs. w3     d43.
     dl  w1     110
     ds. w1     d47.


a10:                   ; next:
     rl  w0  x2+0      ;   move segment number;
     rs  w0  x3+p0     ;
     ac  w0 (x2+2)     ;   move negative size of procedure;
     rs  w0  x3+p2     ;
     rl  w0  x2+4      ;   move number of halfwords on stack;
     rs  w0  x3+p4     ;
     al  w0     0
     rs  w0  x3+p12-2    ; accumulated time := 0
     rs  w0  x3+p12
     rs  w0  x3+p14      ; number of calls := 0
     rs  w3  x3+p6       ; first addr := 'greater than runtime syst'

     rl. w1     b5.+6  ;   move (abs) virtual address of first line error entry;
     ls  w1     9      ;
     wa  w1  x2+6      ;
     wa  w1  x2+6      ;     (it was a word number)
     rs  w1  x3+p8     ;

     al  w2  x2+b0     ;   increase pointers;
     al  w3  x3+p10    ;
     se. w3    (d13.)  ;   if not all procedures initialized then
     jl.        a10.   ;     goto next;

; step 6: initialize library procedure table

     al. w2     b7.    ;   w2 := first of library procedure sizes;
     al  w0     0      ;   w0 := current segment := 0;

a15:                   ; next:
     rs  w0  x3+p0     ;   segm := current segment;
     ac  w1 (x2+0)     ;   move negative size of procedure;
     rs  w1  x3+p2     ;
     as  w1    -9      ;   current segment := current segment
     ws  w0     2      ;     + segments used by this procedure;
     al. w1     r1.    ;   initialize addr of runtime error;
     rs  w1  x3+p4     ;
     al  w1     0      ;   first addr := 0;
     rs  w1  x3+p6     ;

     al  w2  x2+2      ;   increase pointers;
     al  w3  x3+p10    ;
     se. w3    (d14.)  ;   if not all library procedures initialized then
     jl.        a15.   ;     goto next;

     rl. w3     d13.   ;   first proc := first of library proc table;
     jl. w2     f20.   ;   set maxsize;

; step 7: get resident procedures to core

     al. w3     b6.    ;   safety limit := top of init code;
     rs. w3     d1.    ;   first of stack := safety limit;
     rs. w3     d2.    ;   stacktop := safety limit;

     jl. w3     f21.   ;   test room;

     al. w2     b5.+8  ;   w2 := first of resident list;
a18:                   ; next resident:
     al  w1     p10    ;   proc entry := proc table entry size
     wm  w1  x2        ;     * procedure number (entry);

     sh  w1    -1      ;   if procedure number >= 0 then
     jl.        a25.   ;     begin

     al  w3  x1        ;     w3 := abs proc table entry;
     wa. w3     d12.   ;


     ac  w0 (x3+p2)    ;     w0 := positive size of procedure;
     ds. w0     b10.   ;     save (proc table entry, proc size);
; check room for resident procedure, by means of calls of: 'new' and 'dispose'
     al. w1     b11.   ;     w1 := address of working cell;
     jl. w3     r8.    ;     allocate on heap;
     rl. w0     b10.   ;     w0 := size of procedure;
     al. w1     b11.   ;     w1 := working cell;
     jl. w3     r9.    ;     release heap;
; there was room enough, therefore load it
     rl. w3     b9.    ;     w3 := proc entry;
     rl. w1     d10.   ;
     rs. w1     d8.    ;     first of last loaded := last used of heap;
     jl. w1     f5.    ;     get procedure;
     rl  w1  x3+p6     ;
     rs. w1     d11.   ;     first of resident := first(proc);
     rs. w1     d10.   ;     last used of heap := first(proc);
     rs. w1     d9.    ;     last killed by heap reserve := first(proc);
     al  w2  x2+2      ;     increase(entry);
     jl.        a18.   ;     goto next resident;
a25:                   ;     end;

; step 8: compute max size of nonresident procedures

     rl. w3     d12.   ;   first proc := first of procedure table;
     jl. w2     f20.   ;   set maxsize;

; step 9: pre-reserve the heap (but don't check yet)

     rl. w1     d10.   ;   limit := last used of heap
     ws. w1     b5.    ;          - std heap size;

     rs. w1     d9.    ;   last killed by heap := limit;
     rs. w1     d8.    ;   first of last loaded procedure := limit;
     rs. w1     d6.    ;   first of proc nearest to stack := limit;


; step 11: set correct first of stack, and check heapsize

     al. w1     r15.   ;
     am.         (b4.)    ; get fp-mode bits
     rl  w3     h51
     sz  w3     1<8       ; if mode listing
     al. w1     r151.     ;   then top of rs := r151
     rs. w1     d1.    ;   first of stack := top of runtime system;

     jl. w3     f21.   ;   test room;

; step 12: initialize stackref and entry-addresses to runtime system

     am.        (b4.)     ; get mode bits
     rl  w3     h51

     al  w2  x1+2047   ;   w2 := stackref;
     al  w2  x2+1      ;
     sz  w3     1<8
     am         r41-r4 ; alternative call procedure

     al. w0     r4.    ;   init: call pascal procedure
     rs  w0  x2-2047   ;
     sz  w3     1<8
     am         r61-r6 ; alternative return from procedure
     al. w0     r6.    ;         return from pascal procedure
     rs  w0  x2-2045   ;
     al. w0     r3.    ;         call library procedure
     rs  w0  x2-2035   ;
     al. w0     r1.    ;         runtime error
     rs  w0  x2-2033   ;
     al. w0     r7.    ;         value initialization
     rs  w0  x2-2031   ;
     al. w0     r8.    ;         new
     rs  w0  x2-2029   ;
     al. w0     r9.    ;         dispose
     rs  w0  x2-2027   ;
     al  w0    -15     ;        (old versions: start of proctable)
     rs  w0  x2-2025   ;
     al  w0    -2      ;        (old versions: get procedure)
     rs  w0  x2-2023   ;

; step 13: prepare call of set interrupt, and start main program

     al  w0     0      ;   interrupt mask := 0;
     al. w3     c0.    ;   interrupt address := break-routine;

; w0 = interrupt mask
; w1 = stacktop
; w2 = stackref
; w3 = interrupt address

     jl.        c0.    ;   goto init-code;


; set maxsize
;
; call: w2 = return
;       w3 = first proc

b. a10 w.

f20:                   ;
     al  w0     0      ;   w0 := maxsize := 0;  <*notice: negative values *>
a0:                    ; rep:
     sn. w3    (d14.)  ;   if entry = top of procedure table then
     jl.        a1.    ;     goto set max;
     sl  w0 (x3+p2)    ;   if maxsize >= size of procedure then
     rl  w0  x3+p2     ;     maxsize := negative size of procedure;
     al  w3  x3+p10    ;   increase(entry);
     jl.        a0.    ;   goto rep;
a1:                    ; set max:
; w0 = largest (negative) procedure size
     ls  w0    -9      ;
     ls  w0     9      ;
     ac  w0    (0)     ;   max := - maxsize rounded up;

     rs. w0     d15.   ;   maximum page size above 'd10' := max;

     ls  w0     1      ;
     wa. w0     d3.    ;   minimum room between stack and heap :=
     rs. w0     d7.    ;     2 * max + min room between stack and code;

     jl      x2        ;   return;

e.                     ;


; test room
;
; call: w3 = return

f21:                   ;
     rl. w0     d10.   ;   room := last used of heap
     ws. w0     d7.    ;         - room between stack and heap
     ws. w0     d1.    ;         - first of stack;
     sh  w0    -1      ;   if room < 0 then
     jl.        a24.   ;     init error (process too small);
     jl      x3        ;   return;
\f


; errorreturn :
 
b. c10, e2 w.
e1:  0                   ;
     0                   ;
 
c0: <:<10><10> *** pascal init trouble <10> w0=:>;
c1: <: error in program call<0> :>;
c2: <: cannot create area process<0> :>;
c3: <: wrong answer<0> :>;
c4: <: process too small<0> :>;
c5: <: cannot transfer procedure table<0> :>;
 
 
a20: am         c1.-c2.;   error in program call
a22: am         c2.-c3.;   cannot create area process
a23:                   ;   ioerror:
a21: am         c3.-c4.;   object file not ok
a24: am         c4.-c5.;   program too big
a5:  al. w1     c5.    ;   transfer proc table
     ds. w1     e1.+2  ;
     rl. w2     b4.    ;
     al. w0     c0.    ;
     jl  w3  x2+h31-2  ;   outtext(init trouble)
     rl. w0     e1.    ;
     jl  w3  x2+h32-2  ;   outinteger(w0)
     1<23 + 32<12 + 3  ;
     rl. w0     e1.+2  ;
     jl  w3  x2+h31-2  ;   outtext(cause)
     rl. w1     b4.    ;
     al  w2     10     ;
     jl  w3  x1+h26-2  ;   outchar(nl)
   
     al  w2     1      ;   terminate program(not ok)
     rl. w1     b4.    ;
     jl      x1+h7     ;   goto fp-end program
e.
\f


; dump procedure
; call :
;  w1 - lower bound
;  w2 - upper bound
;  w3 - return
b. a3 w.
a1: 0,r.4
f22: ds. w1     a1.+2
     ds. w3     a1.+6
a3:  rl. w2     b4.
     rl. w0     a1.+2  ;
     jl  w3  x2+h32-2  ;   outinteger(addr);
       32<12 + 6       ;
     rl. w1     b4.    ;
     al  w2     58     ;
     jl  w3  x1+h26-2  ;   outchar(colon);
     rl. w2     b4.    ;
     rl. w0    (a1.+2)
     jl  w3  x2+h32-2
     1<23+32<12+9
     al  w2     10
     rl. w1     b4.
     jl  w3  x1+h26-2
     rl. w1     a1.+2
     al  w1  x1+2
     rs. w1     a1.+2 
     sh. w1    (a1.+4)
     jl.        a3.
     dl. w1     a1.+2
     dl. w3     a1.+6
     jl      x3
e.

b6:                    ; top of init code:
e.                     ; end initialization block;
e.                     ; end segment
 
g2=k-h55
; the runtime system is generated by a job like
; the following :
;  job bbj 3 1 time 30 size 25000 perm disc1 40 1
;  clear user pascrun
;  pascrun=set 40 disc1
;  (pascrun=slang tpascrun entry.no proc.fpnames proc.insertproc
;  pascrun)
;  scope user pascrun
;  finis
;
;  the job looks like this because the catalog entry
;  is set by insertproc, which requires the name of the
;  entry to appear right after the translation. the 
;  parenthesis is present to ensure that the name is
;  read at the same time as the call of the slang-
;  assembler.
 
g0:
g1:  (:g2+511:)>9       ;   segments
     0,r.4              ;   document
     s2                 ;   short clock
     0                  ;   file
     0                  ;   block
     2<12+g3-h55        ;   contents key <12 + entry point
     g2                 ;   load length
d.
p.<:insertproc:>
▶EOF◀