Some System Notes for the HARTRAN implementation on the Atlas 2 at Aldermaston
The Loader Symbol Table (LST) is a computed entry list of symbols which have been met by the loader, together with information relevant to each symbol. The table has room for 2048 entries, each of two words, separated in core by 2048. The first word of an entry contains the name of a symbol as 8 characters. Empty slots in the LST are indicated by an empty first word, and deletions (caused by *RENAME, or chapter references in a chain job) by the first word having a high half of all ones (J77777777).
The table is of the computed entry type, so that a key calculated from the symbol name will tend to point to a hole which can take the entry. The key is a number in the range 0-2047 computed from the first three characters of the name as indicated in the example:
The identifier NAME-has an internal code representation 56415545. First of all add this pattern to itself shifted down circularly 6 bits (1 character):
56415545 45564155 -------- 124201722 --------- ||||
The key is the eleven bits whose least significant bit is the seventh from the right i.e. 2017.
When searching the table, and this position is found to be filled, or deleted, a further attempt is made at 2016 etc*, until a hole appears. After position 0, position 3777 is inspected, and so on until the whole table has been scanned. The search subroutine returns on different links according as to whether or not a match is obtained, and passes back the position of the match, on the first available deletion or hole for a new entry, respectively. There is no specific routine for making entries.
The function of this word differs according as to whether or not the symbol has been defined. This is indicated by the most significant bit of the high half, which is zero for defined symbols. In the rest of this section the m.s. bit is the 0 and the least significant 23.
The more significant half is defined as follows:
bits 0 zero 1 one for a routine, zero for an array 2-20 routine: relocation origin (RS7 symbols have zero.) 21 zero 22-23 mode: 0 parameter 1 public 2 global 3 block (not used on Atlas 2)
The more significant half is made up as follows:
bit 0 one 1-21 zero 22-23 mode as in 3.1
The less significant half contains a pointer to the Forward Reference Table.
Entry at A21/0 To be set on entry (and remaining on exit) B54 Name high half B55 Name low half B60 Exit 1 search for match unsuccessful B61 Exit 2 search for match successful Set on exit: B52 Computed entry position B53 Address at which an entry should be made, or is =0 if entry point is available B62 =0 if entry point is available ≠0 if LST full B63 Address of first deletion found (= 0 if no deletions) Bt =0 search successful =≠0 search unsuccessful
The Forward Reference Table (FRT) is a list of all locations in a program which are awaiting the addition of the values of symbols as yet undefined. These locations usually arise from the external reference table (ERT) of a routine (q.v.) The Loader Symbol Table entry for an undefined symbol contains a pointer to a halfword in the FRT. This halfword contains the first address listed in the ERT. The preceding halfword contains the second address listed and so on until whole list is transferred. The next halfword then oontains a negative number. If it is J4, this marks the end of the list of references. Otherwise it is the negation of the address of the first cell of a further chain of references to the same symbol.
The reverse order of entries is purely historic and dates from a time when there was no limit to the length of the FRT, and space was not re-used.
The FRTis of a finite length (3072 halfwords = 3 blocks). It is designed so that it can re-use space once occupied but now redundant because the syabol concerned has been defined. The table is set initially so that each half word, is zero. A note is kept (in B16) of the probable next available hole in the FRT. Any entry in the FRT is prefaced by a scan starting at the value in B16 and continuing until a hole is found. The last halfword is permanently zero and the position of the hole is tested against this known position to verify that the FRT not full. Once a hole is found, the list from the ERT can be copied across to the FRT, as long as there is room for a terminal marker as well as the list. If there is not room, then the ERT list will be split into two or more sections in the FRT. (This split will be reflected in printing produced under the diagnostic for missing routines).
Entry at A3/30 = A22/0 to be set on entry B16 = current pointer B56 = pointer to FRT entry B57 = value of symbol to be added B58 = return address
The subroutine works through an FRT entry adding the value into the specified locations, continuing from one part list to another. Whenever a marker other than the terminal is passed, the address of the new section is compared with the value of B16 which is reset if necessary. As each halfword in the FRT constituting the entry is dealt with, it is cleared to zero.
This area of store is used as follows:
0 working space during loading 1-11 for reading records during loading 12.31 name list during loading 32-47 LIBRTAB 48-63 .IOU 64-71 DUMPERR 72-76 not used 77-84 integer multiplication subroutine 85-87 not used 88 2.0 standardised: in octal 0022 0000 0000 0000 89 1.0 standardised: in octal 0021 0000 0000 0000 90 high half: in 4020, low half: jump address for TP error message 91-92 work space 93 (1-e) standardised in octal 0007 7777 7777 7777 94 high half setting for negative integer: in octal 0317 7777 95 high half setting for positive integers: in octal 0300 0000 96 truncating zero 0 * 826 in octal 0640 0000 0000 0000 97 integer zero 0 * 812 in octal 0300 0000 0000 0000 98 true zero i.e. octal 0000 0000 0000 0000 99 standardised zero in octal 4000 0000 0000 0000
This area is used by the magnetic tape routines in the standard transfer package, and also by the LIBRF routines. Each successive fullword is allocated to each possible tape number rom 0 to 15. The loader sets each word with low half zero and high half:
0 no tape of this number J1 there is a 1in tape of this number J2 there is a half-inch tape of this number J3 there is a disc of this number
This area is used by the input/output routines in the transfer package. The high halves represent the definition of an input stream, and the low halves that of an output stream, successive full words being allocated to each possible stream number from 0 to 15. Each halfword can be set as follows:
0 no stream of this number 0.2 this is a paper tape stream 0.4 this is a card stream 0.6 this is a printer stream (output only)
The information is derived from the job description, except for output streams 14 (presumed to have the same destination as 0) and 15 (presumed to be for the card punch). The presumption about outputs 14 and 15 are to avoid selecting these streams, for that would cause the supervisor to produce headings for these streams, even when the programmer was not using them.
This is a list of dump areas to be printed in the event of an error exit. The list is terminated by a word with high half negative. One word is used to define each area. The first gives the starting address. The second specifies a format in bits 0-2 and the finishing address in bits 3-23.The loader normally leaves bits 21-23 of each halfword zero, unless there is a forward reference to a symbol whose value is not integer. The format recognised are coded as follows:
J0 octal J1 instructions J2 floating point J3 integers J4 text
This routine handles all reading of information, from input streams, system library or private library. It also performs the writing of a private library. The subroutine has 6 entry points, which are described in detail below. In eaeh case a link is expected in B1.
This takes place if and only if the count of of the number of blocks remaining on a library is strictly greater than zero. Once the count becomes zero, no further writing takes place. A diagnostic is not issued until the *ENDLIB directive.
b18 odd: initialse for system library part 1 set position of library in A12 to G5 call supervisor document 20 b18 even: initialise for private library set position of library in A12 to G6 select tape and search for required block (A32 entry for next block) update block address Subsidiary entry A33: initialise for system library part 2 set position of library in A12 to G5 call supervisor document specified in B78
b18 zero (input stream) read record to A1/0, setting length in B41 if length < 80 cahrs, pad out with blanks, and adjust B41 write record to private library if required b18 non-zero (library) copy record to A1/0, setting length to B41 add carriage control character and adjust B41 Read next block of library if separator odd
b18 zero (input stream) read first 2 words of record to A1/0 return if next character binary. Otherwise monitor. b18 non-zero (library) copy first 2 words of record to A1/0
b18 zero (input stream) read next (b57) words to location (b54) read any remaining part of record to A1/0+2 write record to private library if required b18 non-zero (library) copy next (b57) words to location (b54) read next block of library if separator odd
b18 zero (input stream) read record to A1/0 until one begins with J16 (A normal binary card cannot begin in this way Then an entry A2 i.e. check length and write to private library b18 non-zero (library) Test each card image in turn until a symbolic one appears with first character *, reading new blocks as required then an entry A2 i.e. copy record, add carriage control, read next block
b18 zero (input stream) read remainder of record to A1/0+2 Adjust B41 by adding 2 b18 non-zero (library) Re-read record just as in A2
Single block buffers are used for both reading and writing. Double block buffering has been considered for reading but deferred. Unless lockouts (of this type whereby the supervisor releases the information after adjusting R3 and R4) can be avoided, it is doubtful if efficiency will be improved.
This note is to be read in conjunction with the document entitled "The Structure and Processing of BAS Subroutines", which describes the layout of a routine in core before it is processed, and the manual which describes card format.
First the name of the routine is read and checked to B54, B555 by subroutine NCC. It is then copied to B46, B47 where it remains during the whole of the processing of the subroutine. The next step is to decide whether or not the routine is to be loaded. A routine is loaded if there is no preceding *LIBR card, or if there is and at least one of the listed names is that of a wanted symbol. The *BAS card is printed (assuming *SUMMARY is present) only if the routine.is going to be loaded.
The routine is loaded into either the chapter or global regions. If there is a forward reference to the routine, it goes into the region of that reference. If *LIBR preceded, then if my FR was global, then the routine goes into global. If there is no *LIBR card, the main entry point is decisive, because nothing is known about the routine symbol table at this stage. B455 will contain the chosen mode, and B42 is non zero and points to the FRT if there is a forward reference. B43 is used to renumber the position in the LST for the main entry point. B15 is cleared because the next part is common to the *WRLIB scan.
Next the 4 octal numbers are read to give the main entry point (B44), the length of the routine (B48} - also used for the origin of the first card of a S3 routine - the number of RST entries (used to compute the beginning of the PUT in B49) and the length of common (B72). Next, column 50 is checked to see if a mixture of routines is being loaded. If the routine is the first one (B8), the length of the common list is now defined, and it is cleared to integer zero. Otherwise the length of common is checked to see whether it exceeds that already defined.
Finally the next available location in the appropriate region is forced to a multiple of 2 and placed in B50 as the loading origin of this routine. The length of the routine is preserved in B29 and B44, B48 and B49 now contain the absolute address of the main entry, beginning of the RST, and the beginning of the PUT respectively. Finally the area to be occupied by the routine itself is cleared to floating point zero.
Each binary card is read and relocated, checking that it is binary, that column 1 has a 7,9 punch, that the checksum checks, that S3 routines have their cards in the right order, and, that the information is not copied onto the loader. The coding is obvious considering the format of the cards. The process of relocation ceases when a card is read without a + in column 1.
Now that the routine has been successfully read to store, B15 is used to see if a return to R71 is required for *WRLIB. The next available location in the loading region is now updated. The chapter and globall next locations are stored in B20 and B21 respectively during the processing of the BAS table. At this stage the information pertinent to this routine is written to the LST if there is a forward reference to it, or if there was no *LIBR card, or if the name begins with 1 or ends with R blank.
This routine is a direct coding and will not be described.
This routine is a direct coding and will not be. described, except that array storage is not cleared yet - only B12, B13 moved.
he first part of this is a direct coding, except that entries are made in the LST if there is a forward reference, if there is no *LIBR card, or if the name begins with / or ends with R blank.
A check is now made on the next available locations in global and chapter that they do not overlap the loader as a result of arrays declared in the ERT. Then these arrays are cleared. B27 is reset to zero to indicate no *LIBR and then forward references to the main entry point are satisfied. Finally a return is made to read the next directive unless a library is being scanned or there are still forward references.
The loader uses an array /CHAIN, usually 18 words long, containing information for global and 8 chapters. If more than 8 chapters are to be used, then the *CHAIN directive must say so.
Four consecutive half-words are used for each chapter as follows:-
1st Position on tape of chapter 2nd No. of blocks - 1 in character position plus chapter origin 3rd Entry point 4th Tape number in halfword position
A library is a collection of card images representing a series of directives and routines. Each symbolic card appears with its full 80 columns, but binary card images are truncated after the last information column, thus removing the labels from binary cards. Card images are separated by a full word, of which only the high half is significant.
Bits 16-20 length of record = 10 for symbolic card = 18 for binary card The loader is coded to accept a maximum length of 31, and tom treat 0 as an error condition. Bit 0 (m.s.) is 1 if succeeding record is binary otherwise 0. Bit 23 (l.s.) used in private library only.
The system library consists of all card images end to end as described above until a *ENDLIB directive. Its length is a maximum of 5120 words for any individual part. A part other than the last indicates the supervisor document number of the succeeding part by means of an expression on the *ENDLIB directive.
A private library consists of a number of blocks on tape. Each block starts off in the way described above, and contains the images of whole cards. If there is not room at the end of a block for the whole of the next card, a few words are wasted. The end of a block is signalled by the marker halfword having its least significant bit one. The end of the library is indicated by a *ENDLIB directive as usual.
Information derived during the compile phase and output onto stream 14 is brought back during loading as input stream 0. This arrangement is particularly convenient with regard to the handling of PRELUDE data, which is thus always in stream 0. It also means that there is no need for the loader to know whether the current job is a GO or a FORGO job, indeed the loader is quite ignorant in this matter.
The table below gives details of the documents. In addition the loader has associated with it working space from location J0243 to J02717770.
Number Name Starting Address Length (Blocks) 8 Loader J0272 6 J0272 20 System Library part 1 J025 10 - 21 System Library part 2 J025 10 - 22 System Library part 3 J025 does not exist - 23 System Library part 4 J025 does not exist -
When documents 21-23 do exist, they will be of maximum length 10 blocks. They will also, unlike all other documents, be marked as self destructive, because part 1 will always be required again before these documents.
The loader, after its preliminary initialisation, gives an early call for part 1 of the system library. This early call will be repeated at the beginning of every chapter of chain jobs. Wthen it is desired to scan the library, an 1147 is given to ensure its presence, and scanning commences. If the *ENDLIB is met and routines are still wanted, then the value of the expression on the directive indicates the number of the next system document required. This is then read by means of 1147 and so on until a blank expression on a *ENDLIB occurs.
Any modification of the loader is indicated to the supervisor before the alternative is made by means of an 1146 extracode.
If an attempt is made to modify the system library, a marker is first inspected to see whether or not part 1 is in, or is expected in, core in an unmodified form. If so, an 1147 is given to ensure its presence, followed immediately by an 1146 and the document is then altered.
The Absolute Binary Card Loader is regarded as unsafe, and commences by indicating that the loader is to be mutilated, and then treats the system library in the same way as *ALTER amendments.
Termination of loading is indicated by an 1142 instruction at the end of the processing of the *ENTER directive, or alternatively upon entering the absolute binary card loader.
Private monitor is set initiallt to an internal subroutine, R55, which is capable of printing *SETDMP areas in octal. As soon, as subroutine MONITOR is loaded, this will be used in preference to R55, by means of a special forward reference table entry set initially.
As used with FORTRAN and FORGO jobs)
The Compile Master controls the whole of a FORTRAN type job, or the compilation phase of a FORGO job. A limited subset of system directives is recognised to enable Fortran subroutines to be compiled, and ASP subroutines to be assembled, possibly from more than one input stream, and finally for the processing to be terminated.
To facilitate the use of paper tape, whilst still preserving an emphasis on efficient card handling, any short (i.e. less than 80 characters) records are padded out with blanks so that they look like cards. This padding process only applies to records beginning with *. Other symbolic records are left short, even when read by the compile master itself, and will be padded out at a later stage by the loader. Note that the ASP assembler is not designed for paper tape use, and all lines must be at least 17 characters long, and the expression field must be terminated with a blank column.
The compile master treats both sorts of jobs as identical except that the former produces no output for subsequent loading, and when it reaches the end (as signalled by a directive) it will end the job. In particular the treatment of directives is identical. Note that a mispunched directive preceding a Fortran or ASP subroutine will not be diagnosed during compilation. A FORGO job will diagnose the error during loading, but in a FORTRAN job the subroutine will disappear without trace. Note too that each subroutine must be preceded by its introducer *S3 or *ASP.
Directives are divided into 4 types - compiler callers, input changes, processing terminators, and others. Any card not recognised as belonging to the first three types is assumed to be long to the last. Detailed checking of directives does not take place until the loading phase.
*S3 is a call for the S3 Fortran compiler.
*ASP is a call for the ASP assembler.
These directives are not copied in FORGO jobs.
*INPUT with an expression in columns 9-72 will change the current input to the value of the expression. The expression may be any constant acceptable to the loader, but no symbol names are allowed. In FORGO jobs this directive is not copied.
The compile phase is ended by the directive *ENTER (unless columns 9-15 contain PRELUDE) or *END ???? where ???? represents any characters other than the sequence LIB blank so that *ENDLIB is excluded. All these directives are copied. In addition, if the directive is *ENDCOMP. the currently selected input is superimposed on columns 9-16.
All other directives are copied together with any subsequent symbolic or binary cards until a symbolic card with a * in column 1 appears. In the copying process columns 73-80 of binary cards are ignored.
Output from the compile phase required during loading is put into output stream 14. This stream is quite distinct from any programmers stream 14. The complete stream, which will contain output from the S3 compiler and ASP assembler as well as other directives copied across, is given to the loader as input zero, taking precedence over any residue of the programmers stream zero.
One consequence of this arrangement is that all card output from the compiler and assembler is duplicated in output streams 14 and 15. Although this document does not say so at every opportunity, stream 14 is only produced in FORGO jobs.
The table below gives details of the various documents. In addition, the compile master has associated with it working space from location 0 to location J0201777. Note that on the supervisor library tape the S3 compiler documents are in the order 14, 13, 10, 11, 12.
Number Name Starting Address Length in Blocks Entry 5 Compile Master (FORTRAN) J0202 1 J02020001 7 Compiler Master (FORGO) J0202 1 J0202 10 S3 Compressed Dictionary J0004 4 - 11 S3 $ Declarations J004 9 - 12 S3 Stage 1 J0125 11 - 13 S3 Stage 2, 3, 4 J014 16 - 14 S3 Simulator J02 1 J02002 15 ASP 0 7 K146
The compile master begins by giving an advance request for the S3 compiler, presuming that it will subsequently be required. The compiler master uses B20 to indicate whether the job is FORTRAN (zero) or FORGO (one). B21 contains the return address when S3 or ASP is called.
First an indication is given that the ASP assembler, if present, will be overwritten. Then after the *S3 directive is printed at the head of a new page, the compiler is called into core by giving first a series of 1144 instructions, one for each part of S3, to allow the retriever to commence all its tasks in an optimum order. Then a series of 1147 instructions demanding the presence of S3 force a wait until S3 has arrived. Then S3 is entered.
First an indication is given that two parts of the S3 compiler, documents 10 and 11 will be overwritten. Then ASP is called by an 1147 and entered.
When ASP is assembling a large routine it may require backing store in the form of working tape (or disc) 13. This is not supplied automatically by the system, and must be provided by the programmer.
The compile phase is ended with either the 1117 (end program) extracode in the case of FORTRAN jobs, or an 1142 0 0 0.1 (end compile) in FORGO jobs. In either case streams 0 and 15 are terminated by a comment for example "END OF COMPILER STREAM 0".
Private Monitor is set initially so that should any monitoring occur, output streams will still have their termination comment. The mechanism is to simulate the end of *END in a FORTRAN job. Since S3 has its own private monitor, the compile master resets its own monitor immediately after each return from S3 or ASP.