Contact us Heritage collections Image license terms
HOME ACL Associates Technology Literature Applications Society Software revisited
Further reading □ Contents1. Introduction2. Basic symbols and comments3. Identifiers, accumulators and cells4. Types and values5. Addresses and storage allocation6. Simple cell designation7. Assignment statements8. Integer accumulator assignments9. Real accumulator assignments10. Long accumulator assignments11. Cell assignments12. Block structure13. Procedures and labels14. Conditional and control statements15. Functions16. Cell declarations17. Synonym declarations18. Storage allocation19. Subcompilation and global storage20. Define statements, conditional compilation and include statements21. Compiler directives22. FORTRAN/PLASYD mixed programming23. ALGOL/PLASYD mixed programming24. Useful library routines25. Use of TASK macro to compile PLASYD programs26. SMO cell designation27. Compiler output28. PLAN instructions not provided for in PLASYD □ Appendices □ 1: Errors and comments2: 1900 character set3: Syntax definitions in alphabetical order4: Use of program XMED5: 1900 order code6: Code genereated for typical PLASYD statements7: A sample PLASYD program8: Less commonly used directivesReferences
ACD C&A INF CCD CISD Archives Contact us Heritage archives Image license terms

Search

   
ACLLiteratureICL 1906A manualsPLASYD
ACLLiteratureICL 1906A manualsPLASYD
ACL ACD C&A INF CCD CISD Archives
Further reading

Contents1. Introduction2. Basic symbols and comments3. Identifiers, accumulators and cells4. Types and values5. Addresses and storage allocation6. Simple cell designation7. Assignment statements8. Integer accumulator assignments9. Real accumulator assignments10. Long accumulator assignments11. Cell assignments12. Block structure13. Procedures and labels14. Conditional and control statements15. Functions16. Cell declarations17. Synonym declarations18. Storage allocation19. Subcompilation and global storage20. Define statements, conditional compilation and include statements21. Compiler directives22. FORTRAN/PLASYD mixed programming23. ALGOL/PLASYD mixed programming24. Useful library routines25. Use of TASK macro to compile PLASYD programs26. SMO cell designation27. Compiler output28. PLAN instructions not provided for in PLASYD
Appendices
1: Errors and comments2: 1900 character set3: Syntax definitions in alphabetical order4: Use of program XMED5: 1900 order code6: Code genereated for typical PLASYD statements7: A sample PLASYD program8: Less commonly used directivesReferences

22. FORTRAN/PLASYD MIXED PROGRAMMING

22.1 Introduction

One of the main uses of PLASYD will be for inserting procedures into predominantly FORTRAN programs to improve the efficiency of the total system. It will be necessary to call each language from the other and it must be possible to pass values backwards and forwards between the two languages. To do this the interface between the two languages must be defined.

Creation of mixed language programs is relatively simple using the TASK system [3] which allows users to compile and run complex binary programs in a simple and efficient manner. For example if the following files are defined:

MAINF, a FORTRAN main program
SUBRF, a FORTRAN subroutine
SUBRP, a PLASYD subroutine

then the notation:

  MAINF→SUBRP

can be used to define a program consisting of a PLASYD subroutine called by a FORTRAN main program. In its simplest form, the TASK system automatically inserts the necessary steering lines for consolidation in FORTRAN. However any PLASYD segments should contain a directive SENDTO (A.B) where both A and B are any identifiers (the TASK system will not use these names so that any unused name can be allocated). Some examples of TASK calls from a MOP console are:

(1) MAINF → SUBRF
   TASK FORTRAN,*CR MAINF,*CR SUBRF
(2) MAINF → SUBRP
   TASK PLASYD,*CR SUBRP,NOCONS,-
   TASK FORTRAN,*CR MAINF,LINK
(3) MAINF → SUBRP → SUBRF
   TASK PLASYD,*CR SUBRP,NOCONS,-
   TASK FORTRAN,*CR MAINF,*CR SUBRF,LINK
   

In the mixed language programs, the first TASK call will compile the PLASYD subroutine leaving the semicompiled output in a workfile which is then consolidated with the FORTRAN routines by the LINK parameter. The FORTRAN library is scanned automatically so that library routines specified here will be added without any additional directives being necessary.

22.2 FORTRAN Subroutine Linkage

The method of subroutine linkage used in FORTRAN is quite similar to that defined for PLASYD in Chapter 13. Unlike PLASYD, the link accumulator must always be X1. It is always set to point to the instruction immediately following the call instruction itself. If the subroutine has no arguments then this will be the next executable instruction; otherwise it will point at the first of a set of instructions which define the arguments to be passed to the subroutine. Each argument has a single instruction associated with it which loads information about the argument into X3. This will be, in most cases, just the address of the argument. In some cases it does have certain marker bits set to differentiate between types of argument when more than one type is possible.

The simple FORTRAN subroutine call:

      CALL FRED 

is exactly equivalent to the PLASYD procedure call:

FRED;

where the procedure FRED has been declared as:

PROCEDURE FRED(X1);
.................

If the FORTRAN CALL statement has I arguments then it is important to remember that the return address should be I instructions past the address given by X1. When setting up a PLASYD subroutine to be called from FORTRAN, the simplest way to ensure that the correct return position is obtained is by including the second argument in the PLASYD procedure declaration. For example, a PLASYD procedure FRED which is to be called from FORTRAN with 3 arguments could be written:

PROCEDURE FRED (X1,3); 
BEGIN
.........
RETURN (3); 
.........
RETURN; 
.........
END;

An exit from the PLASYD procedure by either of the RETURN statements or via the final END will return control to the correct position in the FORTRAN program (see Section 13.7 for further details).

It is possible that the same PLASYD procedure may be called from a number of places in a FORTRAN program with a different number of arguments in each place. If this is the case then there must be some way of indicating to the PLASYD procedure how many arguments are present so that the correct return position can be estimated. A standard technique is to have the first argument indicating how many arguments are to follow.

As indicated above, the code generated for a FORTRAN call involving arguments such as:

      CALL FRED (J,B,E) 

will have the general form:

FRED;
An instruction setting X3 to information concerning J
An instruction setting X3 to information concerning B 
An instruction setting X3 to information concerning E 
Next executable instruction

The possible arguments appearing in the CALL statement include scalars, constants, arithmetic expressions and arrays of type REAL, INTEGER, LOGICAL, COMPLEX and DOUBLE PRECISION. In addition, labels and subroutine/ function names can be used. The standard method of getting at the information associated with an argument is to do an OBEY of the relevant instruction following the CALL statement. For example, if the routine FRED has been called, then:

OBEY (X1);   will set X3 to information concerning J, the first argument
OBEY (X1+1); will set X3 to information concerning B, the second argument
OBEY (X1+2); will set X3 to information concerning E, the third argument

In the following sections, the particular form of the information contained in X3 will be described.

The major difference between function and subroutine calls in FORTRAN is that the called routine must return a value in the case of function calls. In the 1900 compilers, this value is returned in a subset of accumulators. The particular accumulators used depends on the type of the function as follows:

TYPE OF FUNCTION              RESULT VALUE RETURNED
INTEGER                               X6
LOGICAL                               X6
REAL                                  A1
DOUBLE PRECISION                      A1 (first two words)
                                      X4, X5 (last two words)
COMPLEX                               A1 for real part
                                      X4, X5 for imaginary part

If functions are written in PLASYD which perform non-standard operations such as input/output of data then it is necessary to specify the function as ABNORMAL in the Program Description Segment.

22.3 Scalars, Constants and Arithmetic Expressions as Arguments

If the N+1 th argument of a subroutine call is either a constant, scalar or arithmetic expression then:

OBEY (X1+N);

will always set X3 to the address of the argument. The contents of this address will be the value of the argument. In the one case of a text constant, the value of X3 will be the address of the text constant, together with the #20000000 bit set.

The PLASYD equivalent of the FORTRAN subroutine:

      SUBROUTINE FRED (J,B,E)
      LOGICAL B
      J = 3+J
      B = .TRUE.
      E = E+4.0
      RETURN
      END

would be:

PROCEDURE FRED (X1,3);
BEGIN
OBEY (X1);            [sets X3 to address of J]
X0 := (X3) +3;
(X3) := X0;
OBEY (X1+1);          [sets X3 to address of B] 
X0 := 1;              [set X0 to value true]
(X3) := X0;
OBEY (X1+2);          [sets X3 to address of E]
A1 := (X3) +4.0;
(X3) := A1;
END;

The LOGICAL variable is set to 1 to indicate .TRUE. and would have been set to 0 if the value .FALSE. had been required. For each type of argument, if X3 is set to α by the OBEY instruction then the form of the argument is as follows:

TYPE         SIZE IN WORDS  ARGUMENT
REAL                2       α,α+1 contains floating point number in standard PLASYD form
INTEGER             2       α contains signed binary integer in standard PLASYD INTEGER 
                            form while α+1 is set to zero
LOGICAL             2       α contains 0 for .FALSE. and 1 for .TRUE. while α+1 is set to zero
DOUBLE PRECISION    4       α,α+1 contains floating point number in same format as for 
                            REAL while α+2,α+3 contains remaining part of mantissa. 
                            The whole is equivalent to the PLASYD LONG REAL format.
COMPLEX             4       α,α+1 contains floating point number in REAL format
                            which is the real part of the floating point number.
                            α+2,α+3 contains floating point number which is
                            the imaginary part of the complex number.

It is possible to define a compressed compilation mode for integer and logical quantities in FORTRAN. These are:

INTEGER (COMPRESS)   1      α contains integer in PLASYD form 
LOGICAL (COMPRESS)   1      form  contains 0 for .FALSE. and 1 for .TRUE.

In general this compressed mode is not used.

Arguments which are scalars may have a value passed back out of the routine as shown in the example above. If, however, the actual arguments are constant this can be quite dangerous as it will mean that the value of the constant in the calling routine has been overwritten.

22.4 Array Arguments

In a FORTRAN program, arrays are stored sequentially with the individual elements in consecutive storage locations. The number of locations required for each array element, say β, is the same as for the scalars defined above. The individual elements are stored in order such that the first subscript varies the most rapidly. For example:

      DIMENSION A(2,3) 

defines an array of SIX elements stored in the order:

A(1,1), A(2,l), A(l,2), A(2,2), A(l,3), A(2,3)

If the address of A(1,1) is α then the addresses of the other elements are α+ β, α+ 2β, α+ 3β... For example, the address of A (1,2) is α+ 2β. If A is a real array then the address is α+4 while if it is a complex array then the address is α+8.

When passing array arguments to subroutines there are basically three different situations:

(Tl) the called routine expects a scalar argument and the actual argument is an array element. For example:

      SUBROUTINE FRED (A)
      A=3.0
      RETURN
      END

with a call of form:

      CALL FRED   (B(3))

(T2) the called routine expects an array argument and the actual argument is an array name.

For example:

      SUBROUTINE FRED (A)
      DIMENSION A(20)
      A(1)=3.0
      RETURN
      END

with a call of form:

      CALL FRED (B) 

where B is an array.

(T3) the called routine expects an array argument and the actual argument is an array element.

For example the call of routine FRED in (T2) could have been:

      CALL FRED (B(3))

As the calling routine has no knowledge of the argument expected, the form of the argument passed in cases (T1) and (T3) is identical. In both cases the address of B(3) is passed with, in addition, the #40000000 bit set. As this bit defines the character position in a word, the standard operations of loading and storing the contents of the address specified by X3 can be done without removing the bit. If more complex operations are to be done then it is good practice to remove the bit first. In some of the earlier 1900 compilers, the bit #20000000 was used so that it is safer in fact always to remove the top two bits. For example a routine of type (Tl) which needs to set the real array element argument to 3.0 would be:

PROCEDURE FRED (X1,1);
BEGIN
OBEY (X1);
A1 :=3.0;
(X3) :=A1;
END;

If the top bits are to be removed, the OBEY order could be followed by:

X3 :=X3 AND #17777777;

In cases (T2) and (T3), if the routine FRED called is in PLASYD, the most likely information required is the address of the first element. In case (T2) this is the address of the first element of B while in case (T3) it is the address of B(3) in the examples given above. In the case (T2) the information passed to X3 by the OBEY order is the address of the array header. This contains information such as the dimensionality of the array and the limits of each subscript. The PLASYD routine can therefore differentiate between the two types (T2) and (T3) by checking for the top two bits being set. If either is set then X3 contains the address of the first element; otherwise the value of X3 is the address of the array header. Array headers may have a variety of forms. However, in all cases the first location of the array is stored in the second word of the array header. A PLASYD routine equivalent to the example in (T2) would therefore be:

PROCEDURE FRED (X1,1);
BEGIN
OBEY (X1);
X2 := X3 AND #60000000;
IF X2=0 THEN X3 := (X3+1);
A1 := 3.0;
(X3) := A1;
END;

If the PLASYD routine needs to access more information about the array in calls of type (T2), then this can be obtained from the array header using the routine GETAH in the FORTRAN and PLAN libraries. The routine GETAH requires two arguments. The first argument must be the address of an area of store in the PLASYD procedure into which the information is to be put. For an N-dimensional array, the length of this area must be N+4 locations. The procedure FRED above, assuming it is only used with one and two dimensional array names as arguments, might have the form:

PROCEDURE FRED (X1,1);
BEGIN
EXTERNAL GETAH   (X1);
LOWER
INTEGER AHDR, INFOBLK(6);
LOWEND;
OBEY (X1);
AHDR := X3;
GETAH;
X3 := AHDR;
X3 := @INFOBLK;
.......

This procedure would set the array INFOBLK as follows:

INFOBLK(0) = the number of dimensions of the array
INFOBLK(1) = the number of words, β, per any element
INFOBLK(2) - the base address of the array, ie address of B(0,0)
INFOBLK(3) = the address of the first element of the array
INFOBLK(4) = the address of the first word past the end of the array
INFOBLK(5) = the first partial product P(1) = D(1)

where D(I) is the number of elements in the Ith dimension.

If the procedure had been called with an N-dimensional array name as argument then:

INFOBLK(6) = the second partial product P(2) = D(1)*D(2)
...........
INFOBLK(N+3) = the last partial product P(N-1) = D(1)*D(2)*......*D(N-1)

the address of the arbitrary array element B(I1, I2,....IN) can be culated from the above information by:

INFOBLK(2) + I1+ I2*P(1) + I3*P(2) + ... + IN*P(N-1)

The library containing GETAH is automatically scanned by the TASK system so that there is no need to specify it explicitly.

22.5 Subroutine and Function Names as Arguments

It is possible to have, in FORTRAN, a CALL of the form:

      CALL FRED (JBC)

where JBC is the name of either a function or subroutine. For example the subroutine FRED might be:

      SUBROUTINE FRED (XYZ) 
      CALL XYZ
      RETURN 
      END

The call of FRED is therefore equivalent to calling JBC in the example above. The argument to the routine call in this case is an instruction which sets X3 to an instruction containing a jump to the routine JBC. Assuming the subroutine FRED above is replaced by a PLASYD procedure then this would have the form:

PROCEDURE FRED (X1,1); 
BEGIN
LOWER
INTEGER LINK; 
LOWEND;
LINK := X1;
OBEY (X1);      [set X3 to address of jump instruction]
X1 := @RET;     [set X1 to correct return address]
OBEY (3);       [executes jump to subroutine]
RET;
LINK := X1;
END;

If the routine called has arguments then a set of instructions following the label RET must be added which sets X3 to the required information for each.

22.6 Labels as Arguments

It is possible to define labels as arguments to FORTRAN subroutines in the 1900 dialect. For example:

      SUBROUTINE FRED (*,*,X,Y,Z,*) 
      .......
      RETURN 1
      .......
      RETURN 2 
      ........
      RETURN 3
      ........
      RETURN 
      END

defines a subroutine with three label arguments. Statements of the form RETURN i will return control to the ith label in the argument list. In the actual call to the subroutine FRED, labels are indicated by preceding them with an & symbol. For example:

      CALL FRED (&100, &2, X, U, V, &30)

indicates that control may return to labels 100, 2 and 30 as well as the instruction immediately following the CALL statement. Thus:

      RETURN 3 

will return control to label 30 in the example.

The method of compilation adopted on the 1900 is that the CALL statement itself is equivalent to:

      CALL FRED (X, U, V)

and it is followed by the equivalent of:

      GOTO (1, 100, 2, 30), X6
 1    CONTINUE

where X6 is the integer accumulator. Before returning to the calling routine, the subroutine must set X6 to 0 for the normal return or 1,2,3 for the first, second or third label respectively.

For example, the FORTRAN subroutine:

      SUBROUTINE JBE (*,I,J,*,*) 
      IF (I .EQ. 0) RETURN
      IF (J) 1, 2, 3
 1    RETURN 1
 2    RETURN 2
 3    RETURN 3 
      END

would be written in PLASYD as:

PROCEDURE JBE (X1,2);
BEGIN
OBEY   (X1);
X0 :=   (X3);
X6 := 0;
IF X0=0 THEN RETURN;
OBEY   (X1+1);
X0 :=  (X3);
X6 := 3;
IF X0 < 0 THEN X6 := 1;
IF X0 = 0  THEN X6 := 2;
RETURN;
END;

22.7 Passing Arguments via COMMON

A second method of passing arguments between one routine and another is using COMMON storage in FORTRAN. There is a direct equivalence between FORTRAN named common areas and PLASYD global areas (see Section 19.5). For example a FORTRAN routine having the declaration:

      LOGICAL B 
      COMMON/XYZ/A,B,I,C(5),J(7,5)

defines an area of storage called XYZ consisting of 86 locations. The integer and logical quantities in FORTRAN are normally allocated two words of storage with the second not being used. A PLASYD procedure could communicate with this FORTRAN routine by defining a GLOBAL area as follows:

GLOBAL XYZ;
REAL A;
INTEGER B, BRUBBISH, I, IRUBBISH;
REAL C(5);
INTEGER J(70);
GLOBEND;

The fact that two words of storage are allocated for integer and logical variables in FORTRAN does mean that the equivalences are not immediately obvious. For example, the array element J(1,1) in FORTRAN is equivalent to both J(0) and J(1) in PLASYD where the actual integer value will be put in J(0) and J(1) will be set to zero. Similarly J(2,1) is equivalent to J(2) and J(3). and so on. It should also be noted that whereas the FORTRAN declaration for C defines elements C(1) to C(5), the PLASYD declaration defines variables C(0) to C(4).

Unlabelled FORTRAN COMMON is equivalent to a PLASYD global area with the name %. Thus the following two declarations are equivalent:

      COMMON A 
GLOBAL %: REAL A; GLOBEND;

It may be necessary in some instances to provide communication between PLASYD procedures which is distinct from any named common areas defined in the FORTRAN part of the program (this is likely for library systems defined in PLASYD). In order to avoid name clashes, the PLASYD global areas should be given with the % symbol somewhere in the middle of the name. This will ensure that no clashes occur.

To generate more efficient code in the PLASYD procedures, it may be desirable to have the global area defined as lower storage. If this is done in the PLASYD procedure, then it will force the equivalent FORTRAN COMMON area to reside in lower to preserve the equivalence. Although the code in the FORTRAN routines will not take advantage of this, it may well be worth doing if the PLASYD procedures are heavily used.

If the user requires one COMMON area to be of undefined SIZE then this can be allowed by defining the equivalent PLASYD global area as TOPGLOBAL. Under GEORGE 3 this will ensure that this particular COMMON area is loaded last so that it can overrun its upper bound without overwriting other areas. The same effect is achieved under GEORGE 4 by placing the COMMON area at a high virtual store address for sparse programs.

22.8 Calling FORTRAN routines from PLASYD

From the previous sections it can be seen that the FORTRAN calling sequence is similar to the PLASYD one. The main point to remember is that the procedure call must be followed by the set of argument instructions which are single orders setting X3 basically to the address of the argument. There may be certain marker bits added in the case of text constants and array elements. Due to the complexity of the array headers, it is recommended that passage of an array to a FORTRAN routine is achieved by specifying an array element (type T3 of Section 22.4) rather than the array name itself.

The individual instructions setting X3 should not depend on them being executed in a standard order nor should they assume that the instruction is only OBEYed once. It is usual for the instruction to be OBEYed twice by the FORTRAN routine. Although it is usual for the instructions setting X3 to be of the simple form:

X3 := @A;

where A is the argument, there is no necessity for this. For example, the instruction could be a subroutine call as long as any links are stored and restored correctly. A call of the FORTRAN subroutine FRED could be:

FRED; 
GET1; 
GET2; 
GET3;

The routine FRED expects three arguments and the addresses of these are calculated by the subroutines GET1, GET2 and GET3 respectively.

As the FORTRAN subroutine will be compiled separately, there is a need to have an external declaration of the form:

EXTERNAL FRED (X1);

to ensure that the correct link, X1, is used.

22.9 Tracing

So far it has been assumed that the user is not interested in the fact that the PLASYD procedure has been entered for tracing purposes. It is as though the PLASYD procedure is part of the FORTRAN subroutine that called it. In order to provide a correct tracing information it is necessary to call a library procedure FPROLOG at the start of the PLASYD procedure and FEPILOG at the end. As well as setting up the correct tracing information, these routines also pass arguments from the FORTRAN routine to the PLASYD procedure and check for overflow. For example, a PLASYD procedure might have the form:

PROCEDURE FRED (X1;);
BEGIN
INTEGER TRC(4);
FPROLOG;
DATA ("FREDPLAS",3,@TRC);
........
FEPILOG; 
DATA(@TRC); 
END;

The arguments following the call to FPROLOG consist of an 8-character text string defining the TRACE name of the procedure, the number of arguments and the address of an array into which the arguments may be transferred. The example call given above expects the procedure FRED to be called with 3 arguments. The array TRC will be set as follows:

TRC(0) contains link information to be used by FEPILOG
TRC(1) contains address of first argument
TRC(2) contains address of second argument
TRC(3) contains address of third argument

The bits of the word not used in the address may or may not be zero. The routine will also handle a variable number of arguments if, in place of the second argument, a negative value is given. In this case the number given defines the maximum number of arguments excluding the first that can be passed. The first argument must define how many arguments are to follow. For example if FRED is called by:

      CALL FRED (2, A, B)

where 2 indicates that two arguments are to follow, and if it assumed that no call of FRED will take place with more than 5 arguments other than the first then the form of the prologue will be:

PROCEDURE FRED (X1);
BEGIN
INTEGER TRC(7);
FPROLOG;
DATA ("FREDPLAS", -5, @TRC);

In this case the array TRC is set as follows:

TRC(0) contains link information to be used by FEPILOG
TRC(1) contains the first argument, i.e. the number of arguments following
TRC(2) contains address of first argument
TRC(3) contains address of second argument

Note that in both cases the array TRC must be one greater than the maximum number of arguments expected including the count if it appears.

The routines FPROLOG and FEPILOG use X3 as a link accumulator. Both routines check for overflow and will give FORTRAN execution error 50. The call of FPROLOG should be the first instruction obeyed in the procedure so that correct tracing is given on such errors.

22.10 Peripheral Usage

One of the main uses of a PLASYD procedure may be to handle non-standard input/output requests. The user should remember that input/output operations for disc and tape will be buffered in FORTRAN and it is therefore dangerous to mix requests for the same stream from PLASYD and FORTRAN. In the case of cards and lineprinter output, there should not be any trouble in mixing, for example, reads from the same stream by routines in both languages.

⇑ Top of page
© Chilton Computing and UKRI Science and Technology Facilities Council webmaster@chilton-computing.org.uk
Our thanks to UKRI Science and Technology Facilities Council for hosting this site