ELLIOTT 903 ALGOL OBJECT CODE
This document contains transcribed and lightly edited text taken from the Elliott 903 Algol Object Code Manual and cross referenced from the Algol Interpreter source code. The edits includes corrections for obvious spelling mistakes and handwritten notes from the original document.
To show where page breaks occur in the original document, page links are included in this document in the form [--PAGE nn--]. Clicking on these links transfers to a scanned image of the page from the original document.
N.B. Additional explanatory text, like this, that did not appear in the original document is coloured red.
Andrew Herbert April 2024
CF The intention of this is to make a partial stack entry before jumping to a procedure body. "address:= N+BA; L1: store EP at SP; store SP in Entry Pointer register; add 1 to SP; store PP at SP; add 1 to SP; PP:= address;" [CODE] [FLOWCHART] CFF This is for a call of a formal function. "Find FP using BN; address:= contents of 3n+FP; go to L1 in CF above;" [CODE] [FLOWCHART] GT An ordinary GO TO is executed by reference to two words in QACODL, of which the first contains the label address and the second the Block Number. The Block Number is needed in case a jump to an outer block is involved. "address:= N+QACODL; L2: if BN equals contents of (address + 1) then go to contents of address; L3: if contents of (EP+3) equals contents of (address + 1) then to to L4; EP:= contents of EP; go to L3; L4: if contents of (EP+2) <O then go to L5; SP:= contents of (EP+2); FP:= SP-3; go to L6; L5: SP:= EP; L6: EP:= contents of EP; BN:= contents of (EP+3); go to contents of address;" [CODE] [FLOWCHART] GTF "Find FP using BN; address: = contents of (3n+FP); go to L2 in GT above;" [CODE] [FLOWCHART] GTFS "Find FP using BN; address: = contents of (3n+FP); go to L7 in GTS below;" [CODE] [FLOWCHART] GTS "address: = N+QACODL; L7: subtract 3 from SP; get integer from stack; if integer is zero or greater than contents of address then FAIL; address: = 2 x integer -1 + address; go to L2 in GT above;" [CODE] [FLOWCHART] IFJ "subtract 3 from SP; get boolean (integer) from Stack; if zero then go to address N+BA;" [CODE] [FLOWCHART] IFUN This stacks the address of a function name if n= 0 or of a parameter if n ≠ 0, "Find FP using BN; store(3n+FP) at SP; add 1 to SP; store the constant +1 at SP; add 2 to SP;" The constant +1 indicates that the address is that of an integer or boolean variable; this is checked at a procedure entry against the parameter checking word. [CODE] [FLOWCHART] INDA The purpose of this is to place the absolute: address of an array element in the stack having been given the address of the map entry and n index values, If the array has real elements then the most significant digit of the result is a one, picked up from the array map. Next to this is placed +1 for an integer or +2 for a real array element. [CODE] [FLOWCHART] INDR As for INDA except that the value of the array element is brought to the stack and unpacked into 3 locations if real. [CODE] [FLOWCHART] INDS "address: = N+QACODL; subtract 3 from SP; get integer from stack; if integer is zero or greater than contents of address then FAIL; store 2 x integer -l +address at SP; add 3 to SP;" [CODE] [FLOWCHART] INOUT See section 9; the address part of the pord, p, determines the action in an identical way to that of the address part of a PRIM pord. [DESCRIPTION] [CODE] [FLOWCHART] MAMPS This operation is executed immediately after entry to a block in which local arrays are declared. The number of dimensions, d, and arrays, a, are packed with 6 bits each at the right hand end of the word containing MAMPS, begin real array A,B,C,D [P:Q, R:S, T:U]; is translated to TIR P TIR Q TIR R TIR S TIR T TIR U MAMPS 3,4 A: /0 0 / indicates real 3 7 3 dimensions; 7 locations onwards to map address B: /0 0 3 5 C: /0 0 3 5 D: 0 0 3 1 +0 / Map address filled in here by action of MAMPS (equal to SP). The indications "A:" etc do not mean that a global label is punched, merely that reference to array A is by specifying the address of the "array pair" marked "A:". Using the top six entries in the stack an array map is calculated and placed in the stack, advanc- ing SP appropriately, The array map fora d, dimensional array contains 2d + 2 words in all. These are arrayed as follows (for d =3):- of the word containing MAMPS. array map : DIMENSIONS TOTAL SIZE OFFSET l1 c1 l2 c2 l3 Note that there is one more lowbound value, l, than map coefficient, c, TOTAL SIZE is the number of locations occupied by the array itself, OFFSET is the number of locations between the leading element of the array and the element all of whose index values are zero; it is positive if the element with zero indices lies at a higher address than the leading element. The coefficients cl, c2 etc are calculated as follows:- c1 is the range of the first subscript multiplied by two if the array is real. c2 is the range of the second subscript multiplied by cl. The lowbound values l1, l2 etc are not necessary for the evaluation of the address of an element of the array, but are necessary for the standard procedure lowbound,. The address of the leading element of each array is filled in at A:, B: etc., the first being equal to SP, the next to SP + TOTAL SIZE etc. OFFSET is then calculated OFFSET = - 2 x P - R × c1 - T × c2 A "pointer pair" is created in QAVNDA - first pointer points to array, second to map. Finally there is a jump to execute the next pord beyond the map address. The address of element B [i,j,k] is - the contents of location B: with its "/" to indicate real plus OFFSET plus 2i + j × c1 + k × c2 [CODE] [FLOWCHART] PE This operation is at the head of a block bearing the number BN' and expecting m parameters. The action is to complete the stack entry set up by CF or by CFF, and do parameter checking (see Section 8 page 27, page 28). BN occupies 9 bits, m 4 bits. "store EP-3m at SP; add 1 to SP; store (old) BN at SP; add 1 to SP; store BN' in Block Number register; store EP-3m-3 in Formal Pointer register;" [CODE] [FLOWCHART] PEM This is placed at the head of a piece of machine code to make it look like pords when called from within the User's Algol program. Example. [ ARCTAN ] ARCTAN PEM 1 +0 for return address ... ... ... 0 ARCTAN+1 normal exit in machine /8 1 code The stack entry is completed as for a PE operation but using the current value of BN in place of BN’, There is then a call of the machine code from within the interpreter, On returning to the interpreter in the normal way for a machine code subroutine the action for RETURN (see 7.2 below) are executed. [CODE] [FLOWCHART] PRIM Enter a subroutine at address N+PBA. [DESCRIPTION] [CODE] [FLOWCHART] RFUN This stacks the address of a real type procedure or a real parameter so that an assignment can be made to it. "find FP using BN; store FP+3n + /0 0 at SP; add 1 to SP; store /0 2 at SP; add 2 to SP;" The sign bit on the address word indicates a real address, and the sign bit on the +2 indicates an unpacked quantity. The +2 indicates a real quantity for parameter checking (see page 27, page 28). [CODE] [FLOWCHART] TA "store N+BA at SP; add 3 to SP;" [CODE] [FLOWCHART] TF ) "find FP using BN; TFAI ) store contents of (3n+FP) at SP; TFAR ) store contents of (3n+FP+1) at SP+1; TFVI ) store contents of (3n+FP+2) at SP+2; TFVR ) add 3 to SP;" [CODE] [FLOWCHART] TIA "store N+QAVNDA at SP; add1 to SP; store +1 at SP; add 2 to SP;" [CODE] [FLOWCHART] TIC "store contents of (N+QACODL) at SP; add 3 to SP;" [CODE] [FLOWCHART] TICA) "store N+QACODL + the constant 8 O at SP; TLA ) add 1 to SP; store +l at SP; add 2 to SP;" The +1 written by TLA gets overwritten by +9 if a label is an actual parameter. [CODE] [FLOWCHART]TIR "store contents of (N+QAVNDA) at SP; add 3 to SP;" [CODE] [FLOWCHART] TRA "store N+QAVNDA + the constant /0 0 at SP; add 1 to SP; store +2 at SP; add 2 to SP;" [CODE] [FLOWCHART] TRC "store contents of (N+QACODL) at SP; unpack the contents of (N+1+QACODL) and store at SP+1, SP+2; add 3 to SP;" [CODE] [FLOWCHART] TRCA "store /8 0 plus N+QACODL at SP; store +2 at SP+l; add 3 to SP;" [CODE] [FLOWCHART]TRCN "Find FP using BN; address := contents of 3n+FP; store contents of address at SP; if address has sign bit =1 then begin if contents of 3n+FP+l has sign bit =l1 then transfer contents of (address +1) to SP+1 and (address +2) to SP+2 else unpack contents of (address +1) and transfer to SP+1, SP+2 end; add 3 to SP;" [CODE] [FLOWCHART]TRR "store contents of (N+QAVNDA) at SP; unpack the contents of (N+1+QAVNDA) and store at SP+1, SP+2; add 3 to SP;" [CODE] [FLOWCHART] UJ "PP: = N+BA" [CODE] [FLOWCHART] TRAP "store /8 0 plus N+BA at SP; store +2 at SP+1; add 3 to SP;" This is only for referring to real constants in hand porded programs, This function is not produced by the translator. [CODE] [FLOWCHART] CBL This has the same effect as a function CF to a point two pords on and therefore makes a partial stack entry. [CODE] [FLOWCHART] CHECK These punch "newline, asterisk" followed by a boolean, integer or real whose value is at the top of the stack or a string whose address is at the top of the stack, SP is unchanged except for CHECKS which reduces it by 3. CHECKI [CODE] [FLOWCHART] CHECKR [CODE] [FLOWCHART] CHECKB [CODE] [FLOWCHART] CHECKS [CODE] [FLOWCHART] DO This makes use of the common procedure ASSIGN (see below). "ASSIGN; store PP at EP+1; store contents of (EP+2) in Pord Pointer register;" [CODE] [FLOWCHART] STW "ASSIGN; " [CODE] [FLOWCHART] FINISH Punch 100 rows of blank tape, the word FINISH and a halt code. Then stop. [CODE] [FLOWCHART] FOR A stack entry is made. In the object program FOR is followed by three pords. PRIM FOR a address of controlled statemen BN' b address of next statement "store EP at SP; store (PP+4) at SP+1;* store a + /0 0 at SP+2; store old BN at SP+3; store b at SP+4; EP: = SP; add 5 to SP; store BN’ in Block Number register;" [CODE] [FLOWCHART] FR This ends a controlled statement. "pp; = contents of (EP+1);" [CODE] [FLOWCHART] * PP+4 points to 5 locations after PRIM FOR FSE This undoes the effect of FOR and is the last for list element. "BN: = contents of (EP+3); PP: = contents of (EP +4); SP: = EP; EP: = contents of EP;" [CODE] [FLOWCHART] DIV See arithmetic primitives. [CODE] ITOR1 Convert contents of SP-3 and SP-6 from ITOR2 integer to unpacked real respectively. ITOR1 [CODE] [FLOWCHART] ITOR2 [CODE] [FLOWCHART] NEGI Replace the contents of SP-3 by minus NEGR the contents. NEGI [CODE] [FLOWCHART] NEGR [CODE] [FLOWCHART] RETURN Used at the end of a block or procedure. "BN: = contents of (EP+3); SP: = contents of (EP+2); PP: = contents of (EP+1); EP: = contents of EP; FP: = contents of (EP+2) minus 3;" [CODE] [FLOWCHART] RTOI1 Convert contents of SP-3 from unpacked real to integer with FAIL if overflow. [CODE] [FLOWCHART] ST This makes use of the common procedure ASSIGN (see below) "ASSIGN; subtract 3 from SP;" [CODE] [FLOWCHART] STA "ASSIGN; copy the contents of SP to SP-3 (SP+1) to SP-2 (SP+2) to SP-1;" [CODE] [FLOWCHART] STEP "ASSIGN; store PP at EP+1; clear location EP+7;" [CODE] [FLOWCHART] WAIT Halt but prepare to resume after a start at 9. [CODE] [FLOWCHART] UNTIL "If the contents of (EP+7) are zero then make them non zero else add the contents of (EP+8) to the variable whose address is at EP+5; If the sign of ( the increment held at EP+8 times ( the controlled variable whose address is at EP+5 minus the final value given in (EP+11)) is greater than zero then store PP at EP+1; this corres- ponds to element exhausted; subtract 6 from SP; If the above sign is ≤ O then store the contents of (EP+2) in the pord pointer register; this causes the statement to be executed;" The type of arithmetic is determined * by the address of the controlled variable held at EP+5. * packing is determined by EP+5. [CODE] [FLOWCHART] UP This makes space in the stack for the result of a type procedure. "Add 3 to SP;" [CODE] [FLOWCHART] WHILE If the topmost value is false then the next pord is taken, but if true then a pord jump occurs to the address given in EP+2. "subtract 3 from SP; if false store PP in EP+1; if true store contents of (EP+2) in Pord Pointer register;" [CODE] [FLOWCHART] procedure ASSIGN; "subtract 3 from SP; address: = contents of (SP-3); type: = contents of (SP-2); if address has an "8 0" bit then FAIL because assignment to a constant is being attempted; store contents of SP at address; if address < O then begin, if type < O then transfer contents of (SP+1) to address+1 and contents of (SP+2) to address +2 else pack together the contents of (SP+1) and (SP+2) with round off and store at address +1 end; " PRIM28 R↑I→R [CODE] (This PRIM was omitted in the original document.) PRIM30 I+I→I [CODE] PRIM31 R+R→R [CODE] PRIM32 I-I→I [CODE] PRIM33 R-R→R [CODE] PRIM34 I×I→I [CODE] PRIM35 R×R→R [CODE] PRIM36 I/I→R [CODE] PRIM37 R/R→R [CODE] PRIM38 I↑I→I [CODE] PRIM39 I↑I→R [CODE] PRIM40 R↑R→R [CODE] PRIM41 I<I→B [CODE] PRIM42 R<R→B [CODE] PRIM43 I≤I→B [CODE] PRIM44 R≤R→B [CODE] PRIM45 I=I→B [CODE] PRIM46 R=R→B [CODE] PRIM47 I≠I→B [CODE] PRIM48 R≠R→B [CODE] PRIM49 I>I→B [CODE] PRIM50 R>R→B [CODE] PRIM51 I≥I→B [CODE] PRIM52 R≥R→B [CODE] PRIM53 B∧B→B [CODE] PRIM54 B∨B→B [CODE] PRIM55 B≡B→B [CODE] PRIM56 B⊃B→B [CODE] The primitives numbered 12 (DIV) and 30-56 have two inputs and one output. The left hand input is at SP-6, the right hand input is at SP-3. The output occupies SP-3 or, if real, the three words starting at SP-3. The nett effect of each primitive is to reduce SP by 3. PRIM57 ¬B→B [CODE] PRIM58 ABS [CODE] PRIM59 ENTIER [CODE] PRIM60 EXP [CODE] PRIM61 LN [CODE] PRIM62 SIGN [CODE] The primitives numbered 58-62 are the ones which execute the Algol procedures which are always in the store. A call of one of these procedures does not produce a PRIM UP as an ordinary procedure call would, The actions of all these primitives are:- "replace contents of (SP-3) by the function of the contents". PRIM63 | [CODE] PRIM64 | These place integer [CODE] PRIM65 | x in the stack at SP-2 [CODE] | where x runs from 3 [CODE] PRIM66 | to 10 for primitives [CODE] PRIM67 | 63-70. The purpose [CODE] PRIM68 | is for parameter [CODE] PRIM69 | checking. [CODE] PRIM70 | [CODE] The primitives numbered 63-70 serve the purpose of filling the stack with type information alongside the address of any call-by name actual parameter, This is for parameter checking.