home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / EFFO / pd0.lzh / DOC / rtfman.txt
Text File  |  1991-02-10  |  227KB  |  53 lines

  1.                                                                 12 Mar.87                                                                   HvdS                                 R T F / 6 8 K                                 =============                    Real-Time Fortran-77 for 68K Processors                    =======================================                    Manual of Compiler and Run-Time Library                    ---------------------------------------                                (Version  2.13)                               H.von der Schmitt                            Physikalisches Institut                            Universitaet Heidelberg                                March 12, 1986                          =========================                          DRAFT - not yet completed                          =========================
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.  
  13.  
  14.  
  15.  
  16.  
  17.  
  18.  
  19.  
  20.  
  21.      RECORD OF CHANGES      Release  Version Changes to former version     --------- ------- -------------------------     25 Oct 83   1.0     20 Dec 83   1.6   Last update of versions 1.x     30 Aug 84   2.0   Versions 2.x start with full F-77, NS16081                       support, IEEE 32-bit FP numbers, position                       independent option, dynamic linkage                       capability.     10 Dec 84   2.1   In-line subroutines and functions added:                       _MOVs, _CMPs, OWNER.     01 Mar 85   2.2   Preparation for 68020 with 68881 FPCP.                       Optimizations in register save/restore; the                       syntax of the KEEP statement has changed                       accordingly.                       Pointer-based COMMON blocks added.                       Support for a FASTBUS coprocessor added.     25 Mar 85   2.3   Optimizations in array index and statement                       function evaluation.                       Corrections to CHARACTER handling.                       Dynamic storage allocation implemented.     16 Jul 85   2.4   Changed address alignment for 1-byte items.                       Options SAVE and INTSIZE added.                       Unified version of runtime library:                       unformatted, block-oriented I/O and                       REWIND, BACKSPACE, ENDFILE added.                       CACHECONTROL statement for 68020 added.                       RECORD declaration added.                       Names may contain $ now.                       In-line routines _SETs added.     27 Sep 85   2.5   Updates in documentation.                       Residual position-dependence in software                       floating point emulation of runtime                       library removed.                       Native (68000) implementation compatible                       with APPLE Macintosh.                       Initialization routine _SYI now returns                       via A0 instead of via stack.                       Changes to compiler and library towards                       zero-length character strings.                       Format descriptor Iw.n added.                       Absolute address of COMMON block can be                       PARAMETER now.                       NORD style octal constants no longer                       supported.     20 Oct 85   2.6   Generalizations in pointer-based COMMON                       blocks.     22 Dec 85   2.7   Run-time variable formats implemented.                       EQUIVALENCE with status register provided.                       Improvements in EQUIVALENCE and DATA .     19 Jun 86   2.8   Bugs removed in IAND etc. generic functions.                       Manual updated. New options CODE=AZTEC and                       NUMPAR=OFF added. Option CHECK=ON also checks                       stack limit now at routine entry. CPU=68020                       generates position independent code also in                       the case SIZE=LONG. Bug removed in indexing                       variable-sized arrays.     11 Oct 86   2.9   Full compatibility with VERSADOS assembler.                       Improvements in memory indirect addressing                       for the 68020. Output of version number.                       Bug removed in Integer*2 Multiply/Divide                       and string concatenation on the 68020.                       EXTERNAL now also applicable for variables                       and Common blocks. Multi-level indirection                       for RECORDS and pointer-based COMMONs                       possible now. Integer expressions get definite                       type when used as actual arguments.     20 Nov 86   2.10  Code generation option for OS9 systems.                       Cross compiler available now on IBM VM/CMS.                       Some minor compiler bugs fixed.                       Static formats checking eliminated.     16 Jan 87   2.11  Changed calling sequence for CHARACTER funct-                       ions. For OS9, calling sequences compatible                       with C language. Bug fixed in KEEP statement.                       RETURN/STOP eliminated before END. EVENTFLAG                       directive added. Extra OS9 option to switch                       off C compatibility. ASSIGN statement also                       usable for dynamic equivalence. Bug fixed in                       using MOV_s with RECORD arrays.     11 Mar 87   2.12  Effect of EVENTFLAG changed for OS9. New                       Fastbus hardware subroutines implemented.     12 Mar 87   2.13  Looping mode primitives extended to 32-bit                       loop count. New option REGUSE introduced to                       use less address registers within routines.
  22.  
  23.  
  24.  
  25.         ACKNOWLEDGEMENT        ---------------        RTF/68K emerged almost entirely from applications in various physics     experiments. Most features (adaptation to run-time environment, code     efficiency, portability of the compiler, extensions of the language) are     due to the suggestions of various collaborators in these experiments, as     well as to efforts of people working with 68K processors in other fields;     namely           V.Mertens, L.Nellen                 from TASSO at DESY/Bonn           W.Jank, S.Cittolin, M.Demoulin,           R.Wilcke, D.Samyn, P.Giacomelli,           K.Bos, J.Dorenbosch, B. Haynes,           J.-P.Porte                          from UA1 at CERN           K.Einsweiler                        from UA2 at CERN           M.LeVine, C.Watson                  from E802 at BNL           E.Elsen, G.Eckerlin, P.v.Walter     from JADE at DESY/Heidelberg           A.Lacourt, S.Marchioro, W.v.Ruden   from ALEPH at CERN           Y.Bertsch                           from L3 at CERN/LAPP Annecy           E.Lesquoy                           from OPAL at CERN           J.Hooper                            from DELPHI at CERN/Copenhagen           M.Freisberg                         from ELTEC Elektronik/Mainz           J.Schanzenbach                      from Univ. Kaiserslautern.        The most painful contributions of the people mentioned above and many     others had to go into testing RTF/68K.        The author is very grateful for all these contributions and, last     but not least, for the possibility to start this project (which is     rather unusual in the context of a physics institute). This is due     to E.Hilger from the Physikalisches Institut Universitaet Bonn.        CONTENTS:        ---------          1. RTF/68K AT A GLANCE   .  .  .  .  .  .  .  .  .    ok            1. Implementation and availability .  .  .  .  .    ok            2. Syntax  .  .  .  .  .  .  .  .  .  .  .  .  .    ok            3. Why Fortran with memory-mapped I/O .  .  .  .    ok          2. THE COMPILER .  .  .  .  .  .  .  .  .  .  .  .            1. Source format .  .  .  .  .  .  .  .  .  .  .    ok            2. Constants  .  .  .  .  .  .  .  .  .  .  .  .    ok            3. Data types .  .  .  .  .  .  .  .  .  .  .  .    ok            4. Declarations  .  .  .  .  .  .  .  .  .  .  .    ok              1. Global and local declarations .  .  .  .  .    ok              2. PARAMETER declarations  .  .  .  .  .  .  .    ok              3. Data type declarations  .  .  .  .  .  .  .    ok              4. DIMENSION declarations  .  .  .  .  .  .  .    ok              5. COMMON declarations  .  .  .  .  .  .  .  .    ok              6. SAVE declarations .  .  .  .  .  .  .  .  .    ok              7. EQUIVALENCE declarations   .  .  .  .  .  .    ok              8. EXTERNAL declarations   .  .  .  .  .  .  .    ok              9. DATA statements   .  .  .  .  .  .  .  .  .    ok             10. INCLUDE directive .  .  .  .  .  .  .  .  .    ok             11. Pointers .  .  .  .  .  .  .  .  .  .  .  .    ok             12. RECORD declarations  .  .  .  .  .  .  .  .    ok            5. Subroutines and functions .  .  .  .  .  .  .    ok              1. General overview  .  .  .  .  .  .  .  .  .    ok              2. Stack assignment during calls .  .  .  .  .    ok              3. ENTRY specification  .  .  .  .  .  .  .  .    ok              4. ASSEMBLER entry specification .  .  .  .  .    ok              5. Statement functions  .  .  .  .  .  .  .  .    ok              6. Intrinsic functions and subroutines .  .  .    ok              7. Obtaining the actual number of arguments  .    ok              8. KEEP directive .  .  .  .  .  .  .  .  .  .    ok              9. INTERRUPT and EVENTFLAG directives  .  .  .    ok             10. CPU time required for subroutine calls .  .    ok             11. Type conversions for integer arguments .  .    ok            6. Other language elements   .  .  .  .  .  .  .              1. Arithmetic, logical, and                 character string expressions  .  .  .  .  .              2. Assignment statements   .  .  .  .  .  .  .              3. Label and variable ASSIGN statements   .  .    ok              4. DO loops .  .  .  .  .  .  .  .  .  .  .  .    ok              5. IF statements  .  .  .  .  .  .  .  .  .  .    ok              6. GOTO statements   .  .  .  .  .  .  .  .  .    ok              7. Input/output statements .  .  .  .  .  .  .    ok              8. PRIORITY statement   .  .  .  .  .  .  .  .    ok              9. CACHECONTROL statement  .  .  .  .  .  .  .    ok            7. Use of pointers  .  .  .  .  .  .  .  .  .  .              1. Subroutine arguments as an example  .  .  .              2. Obtaining and changing addresses .  .  .  .              3. RECORDs and pointer-based COMMON blocks   .              4. Dynamic storage allocation .  .  .  .  .  .              5. Autoincrement/decrement addressing  .  .  .              6. EQUIVALENCE with formal arguments   .  .  .              7. Dynamic equivalence with ASSIGN  .  .  .  .            8. Registers and absolute addresses   .  .  .  .              1. Fields of application   .  .  .  .  .  .  .              2. How to use registers .  .  .  .  .  .  .  .              3. Saving/restoring registers .  .  .  .  .  .              4. How to use absolute addresses .  .  .  .  .            9. Output from the compiler  .  .  .  .  .  .  .    ok           10. Compiler directives .  .  .  .  .  .  .  .  .    ok           11. Compilation error messages and warnings  .  .    ok          3. THE RUN-TIME LIBRARY  .  .  .  .  .  .  .  .  .            1. Main features    .  .  .  .  .  .  .  .  .  .            2. Details of specific routines    .  .  .  .  .              1. Floating point arithmetic  .  .  .  .  .  .                1. Software emulation .  .  .  .  .  .  .  .    ok                2. Code generated for the 68881 FPCP .  .  .                3. Code generated for NS16081 FPP .  .  .  .              2. Input/output package .  .  .  .  .  .  .  .              3. Dynamic interrupt handling .  .  .  .  .  .              4. CAMAC support  .  .  .  .  .  .  .  .  .  .              5. FASTBUS coprocessor support   .  .  .  .  .              6. Connection to operating system services   .          4. IMPLEMENTATION DETAILS   .  .  .  .  .  .  .  .              1. The compiler entry points JFOR/CONFOR  .  .              2. Interactive compiling   .  .  .  .  .  .  .              3. Representation of data in memory .  .  .  .              4. Initialization at start of program  .  .  .              5. Mechanism for dynamic linking .  .  .  .  .          5. USING RTF/68K ON SOME HOST AND NATIVE SYSTEMS .            1. Description of RTF/68K distribution media   .              1. Cross-software package  .  .  .  .  .  .  .              2. Native software package .  .  .  .  .  .  .            2. Installation and execution on VAX/VMS .  .  .            3. Installation and execution on CP/M-68K   .  .            4. Installation and execution on OS9-68K .  .  .            5. Flow of information .  .  .  .  .  .  .  .  .          A. APPENDIX  .  .  .  .  .  .  .  .  .  .  .  .  .            1. Syntax charts of RTF/68K  .  .  .  .  .  .  .            2. Current developments   .  .  .  .  .  .  .  .            3. Associated documentation  .  .  .  .  .  .  .
  26.  
  27.  
  28.  
  29.  
  30.  
  31.  
  32.  
  33.  
  34.  
  35.  
  36.  
  37.  
  38.  
  39.  
  40.  
  41.  
  42.  
  43.  
  44.  
  45.      1. RTF/68K AT A GLANCE     ======================         RTF/68K means 'Real-Time Fortran 77 for 68K Processors' and     consists of a compiler and a run-time library. It provides full     (almost full as of today) Fortran 77 for 68K series microprocessors     while fulfilling some additional demands, namely:             o  compatibility with VAX-11 Fortran (which is a                superset of the standard ANSI X3.9-1978),             o  very good overall run-time efficiency,             o  easy and efficient applicability to real-time                and system implementation problems.         The entire 68K processor family is supported: 68000/08/10/12     and 68020. While the latter is object-code compatible with the     former group, the compiler optionally produces code which utilizes     the additional features of the 68020.         A variety of floating point options is covered: the MC68881     FP coprocessor, the often-used NS16081 FP peripheral processor,     as well as FP software emulation - always obeying IEEE data format.     1.1 Implementation and availability     -----------------------------------         RTF/68K is, for the purpose of easy adaptability, written in     a comprehensive 'very-high-level' language (4000 lines of source     code for the compiler). Nevertheless, the compiler is portable     because a translator generates Fortran code out of this source.     Thus, the compiler is also available in Fortran form (the same     is true for the translator). RTF/68K runs on VAX and NORD as a     cross-compiler and on 68K as a native compiler.         RTF/68K produces an intermediate assembly code as output.     This is then further processed by one of the available assemblers,     e.g. AS68 of CP/M or M68MIL. The connection to linkers, e.g. CUFOM,     is thus obtained automatically.         Calling sequences and debug information generated by RTF/68K     conform to the CERN standard for 68K processors.         The RTF/68K run-time library is to 95% written in RTF/68K     (2000 lines). The small rest, which provides the interfacing     to the environment (hardware setup and operating system, if any)     is assembler. Thus, RTF/68K is essentially self-contained and     easily adapted to any software environment.         The RTF/68K package is available free on distribution tape or     Floppy disk - ready to be used with VAX computers running VMS and/or     the ELTEC E-3 processor running CP/M-68K (see section 5.). Compiler     and run-time system can be adapted to other 32-bit systems with     little effort.         Note that the CERN products M68MIL and CUFOM are not contained     in the RTF/68K package. They can be obtained through CERN, Div. DD     (free of charge for non-profit organizations).         The following table shows the various 68k and other computer     systems RTF runs on. 'Compile' means that the compiler itself runs     on the system to generate code for either the same system and/or     as a host for other systems. 'Exec' means that code generated by     RTF can be executed on the system. - Maybe RTF has been transported     to additional systems unknown to the author.            Computer   Operating system   Compile   Execute            --------   ----------------   -------   -------            VAX        VMS                   X            NORD       SINTRAN               X            IBM        VM                    X            PCS        MUNIX                 X            CSEE       UNIX                  X         X            ELTEC      CP/M                  X         X              "        OS9                   X         X            MicroSys   CP/M                  X         X               "       OS9                   X         X            Macintosh  MacSys                X         X                "      Aztec-C               X         X            Motorola   VersaDOS              X         X            Aleph EVB  OS9                   X         X            Eltec              E3       -none-                          X              SAC      -none-                          X            MicroSys              CPU06    -none-                          X              CPU07    -none-                          X            DataSud              CPUA1    -none-                          X            Motorola              MVME130  -none-                          X            XYCOM              IPROTO   -none-                          X            Aleph              EVB      -none-                          X            Amsterdam              FAMP     -none-                          X            Robcon              CPU020   -none-                          X     1.2 Syntax     ----------         Since VAX computers are widely used in fields where 16/32-bit     micros might also find their place, and since VAX-11 Fortran is     friendly in that it digests virtually every Fortran, the RTF/68K     syntax has been made as similar as possible to VAX-11 Fortran.     RTF/68K is best described by stating the omissions and extensions     as compared to VAX-11 Fortran.         The formal syntax description is found in the appendix which is     a copy of the syntax charts given in the ANSI X3.9-1978 standard.     Omissions are indicated by blobs which close the 'railroads' for the     non-implemented constructs. Extensions are extra rails drawn as fat     lines.     Omissions:  -  The input/output statements are not yet fully                    implemented; namely, direct-access read/write                    and INQUIRE are missing.                 -  The EQUIVALENCE statement does not automatically                    increase storage allocation in case of size                    incompatibility. Moreover, only pairs of two variable                    names are accepted.                 -  DATA statements may contain only one variable per                    constants list.                 -  COMPLEX data are not supported, and REAL is                    restricted to single precision (32-bit IEEE format).                 -  Arrays may have up to five indices only.         Some important VAX-11 Fortran features are explicitly implemented,     e.g. the syntax of hexadecimal and octal numbers; INCLUDE statements;     short (one and two byte) data types; and end-of-line comments.     Extensions: +  Pointer-based variables are available.                 +  Explicit access to the processor (and co-processor)                    registers is possible under Fortran variable names.                 +  Explicit access to absolute addresses is possible                    under Fortran names, allowing easy and efficient                    memory-mapped I/O.                 +  EQUIVALENCE is allowed with pointers and thus also                    with formal arguments.                 +  Entire COMMON blocks may be based on pointers and                    can thus be assigned to memory dynamically. This                    offers almost everything that is available with                    'structs' or 'records' in other languages. For                    convenience such COMMON blocks may be called                    RECORDs.                 +  Entire COMMONs may also be placed at absolute                    addresses, e.g. for memory-mapped I/O to 'structured'                    sets of hardware registers.                 +  Arguments may be passed by value as well as by                    reference.                 +  Global variables are possible; e.g., all COMMON                    blocks could be stated once at the beginning of                    a file and are then valid for all routines that                    follow.                 +  The data types INTEGER*1,*2 are supported. These                    are useful for accessing some hardware devices, and                    may as well serve for saving the famous factor of                    two or four, e.g. in big pattern recognition tasks.                 +  'Strong typing' may be forced by IMPLICIT NONE.                    This is highly recommended as a big step towards                    writing correct programs. In any case, warnings                    are given by the compiler if undeclared variables                    are definitely read-accessed. Misspelt names on the                    left hand side in assignment statements, however,                    require IMPLICIT NONE to be detected.                 +  Besides DO index=.. ENDDO and DO WHILE, DO UNTIL and                    DO FOREVER are available.                 +  The number of routine arguments may vary and can                    be obtained inside the routine by CALL NUMPAR(num).                    If this statement is omitted, however, and the                    actual number of arguments differs from the declared                    one, a run-time message is issued.                 +  The generated code is position-independent.                 +  All routines are re-entrant. Recursive calls are                    possible. Libraries are sharable.                 +  Subroutines can serve as interrupt handlers without                    any software overhead between interrupt vector                    and routine entry. Also, they may be used as event                    flag handlers known under some operating systems.                 +  Integer constants may be written in decimal, hexadecimal,                    octal, binary, and ASCII form.                 +  Dynamic storage allocation is provided with the                    ALLOCATE ... ENDBLOCK construct.                 +  All the ISA bit-handling functions are implemented                    with fast in-line code.                 +  Special in-line subroutines and functions provide                    for efficient block-moves, bit handling, and semaphore                    control for system implementation.                 +  Embedded assembly code is possible.                 +  'Hardware subroutines' (implemented as special                    coprocessors) are supported with generation of fast                    in-line code.         Since some of these concepts are unusual in Fortran (but look     a bit like Pascal or C), a few examples might illustrate their use.     Remember that without the additional features used here you would     have to write it in assembler or use external assembler routines     (the calling of which costs extra time). Note that some of the     examples below are intentionally quite tricky.           equivalence (VIOR,'FFF980'X)     ! this states the address of           integer*2 VIOR                   ! .. the hardware register           VIOR=0                           ! issue command           STATUS=VIOR                      ! .. to read hardware status           integer function FAK(N)          ! this is the most obsolete           if(N.le.1) then                  ! .. example of recursion             FAK=1           else             FAK=N*FAK(N-1)           endif           end           subroutine TERMIO                ! this routine is activated           implicit integer*1 (a-z)           parameter (RxD_ready=3)           equivalence (STAT,'FF2000'X),          *            (DATA,'FF2001'X)     ! .. whenever interrupt with           interrupt 122                    ! .. vector #122 occurs           if(btest(STAT,RxD_ready)) then             I=I+1             BUF(I)=DATA                    ! .. and then reads some hardware             ...           logical function THERE(ADDR)     ! tests if address ADDR is there           integer*2 ADDR,JUNK,SSAVE,S      ! (in supervisor mode)           integer*4 IVEC(0:255),IVECSAV           equivalence (IVEC,0),(S,SR)           IVECSAV=IVEC(2)                  ! save old vector contents           SSAVE=S                          ! .. and status register           assign 1000 to IVEC(2)           ! link bus errors to label           JUNK=ADDR                        ! test if address responds           THERE=.true.           goto 1      1000 THERE=.false.                    ! go here if bus error         1 IVEC(2)=IVECSAV           S=SSAVE                          ! the UNLK instruction will           end                              ! .. clean up the stack           program Dyn_Storage           real @FIELD(0:3,N,N)             ! dynamic storage allocation           accept *,N           ...           allocate 4*4*N**2 for FIELD      ! allocate proper number            FIELD(0,2,3)=PHI                ! of bytes for FIELD            ...           endblock           allocate * for FIELD             ! exactly the same as above            FIELD(0,2,3)=PHI                ! * allocates amount stated            ...                             ! in declaration           end block         The next example shows how a pointer-based COMMON or RECORD may be     used to describe data structures which don't have a fixed location in     memory. In this example, the entire structure is even a formal subroutine     argument.           subroutine ANALYZE(EVENT,...)           record /EVENT/ TOF(32),CALO(128),PAT,CNT(6)       --or--           common /@EVENT/ TOF(32),CALO(128),PAT,CNT(6)           integer TOF,CALO,PAT,CNT           ...           if(iand(PAT,'11'O) .ne. 0 .and. CALO(2).ge.MIN) ...         This is an example where a COMMON block is bound to a fixed absolute     address:           common/'100000'X/ VMX_SPACE(0:'3FFFF'X),EXTRA_VMX('40000'X)         RTF/68K has been used to implement a wide range of different     applications, such as the FASTBUS routine package, Mini-GD3, CAMAC     readout tasks, a complex VME multiprocessor system for driftchamber     readout and on-line analysis, the RTF/68K runtime library, and last     but not least the RTF/68K compiler itself systems.     1.3. Why Fortran with memory-mapped I/O     ---------------------------------------         Given that RTF/68K is made primarily for real-time applications     of moderately to very complex microprocessor systems with close     connections to hardware ('embedded systems'), it may be worthwile to     summarize the arguments for specific extensions offered by RTF/68K.     The most crucial and least usual extension is the provsion for memory     mapped I/O, and the arguments for this are as follows.       a) In the environment of physics experiments, the problem-oriented          part of the application (e.g. analysis algorithms) usually will          be, or is already, programmed in Fortran.       b) One of the essentials of microprocessors with big address space          is the simplicity and efficiency of memory-mapped I/O.       c) The access to the hardware is only in simplistic cases a small          subset of the whole application. Instead, a proven way to keep          the hardware simple is by interaction with a programmable device          like a microprocessor - hence the name 'embedded system'. The          processors (and their programs) act as an interface with one leg          deep inside the hardware.       d) Complete hardware-independence of the application program is an          illusion for this reason. There is no argument why only programs          that are anyway unreadable (assembler) should be allowed to be          hardware-dependent, unless one wants to maintain admired 'experts'          and grateful 'users' that are supposed to understand nothing and          hence are not allowed to really exploit the system.       e) The access to static absolute addresses is very simple to understand          for normal (not 'real-time') Fortran users because Fortran          always had a 'hardware-dependent' component - the possible knowledge          of how variables are arranged in memory. This access fits          directly into the ordinary Fortran syntax. The extension to dynamic          addressing by pointers is well known from other high-level languages.          Both concepts are straightforward to implement into Fortran.       f) A memory-mapped software interface to the hardware is by orders of          magnitude faster than even the optimally coded usual subroutine/call          interface - just because the processor hardware is able to do it          directly in one instruction.       g) In summary, Fortran with extensions like in RTF/68K is suited for          problem and system programming. It allows to write the entire          application in a single high-level language. Non-experts find an easy          way to system programming.         In fact, at least one very complex readout and analysis system with     34 tightly coupled (shared memory) VME processors has been written in     RTF/68K. It was not necessary to use assembler statements. None of the     participants started as an expert in this project, and yet is was finished     in a very short time.
  46.  
  47.  
  48.  
  49.  
  50.  
  51.  
  52.  
  53.      2. THE COMPILER     ---------------         This section gives a brief description of the RTF/68K syntax.     Mainly the deviations (extensions and omissions) from standard Fortran-77     are reported here. As a reference we take the VAX-11 Fortran     which is available on VAX systems and is an extension to standard     Fortran-77 insofar as it supports DO-ENDDO, DO WHILE, IMPLICIT NONE     etc. as well as compatibility with old Fortran (Hollerith, hexadecimal     and octal constants). The reason is that VAX computers will very     often act as hosts for, or will be used in close collaboration with,     68K microprocessor systems.         The complete definition of the syntax of RTF/68K may be found in     the appendix. The deviations from the ANSI standard X3.9-1978 (extensions     and omissions) are obvious from the syntax charts reproduced     there.     2.1. Source format     ------------------         The RTF/68K source code is essentially free-format. Some formatting     is required, however, in order to be compatible with the Fortran     conventions. The following are extensions to the standard:       a) Source lines may start in any column except column six (conflict          with marker for continuation lines). They should also          not start in column one (possible confusion with comment line          marker).       b) Continuation lines are marked in column six with a non-blank          and non-zero character as usual. However, this mark may also          be omitted (continuation is always obvious from context).       c) Comment lines are marked by a "*" or "C" or "c" in column 1.          "D" and "d" also denote comment lines unless the DEBUG=ON          option is selected; then they are proper code lines.       d) More than one statement may be given per source line. They          must be separated by blank(s), or optionally by ";" for          better readability.       e) End-of-line comments may be given. They must be preceded by "!".       f) Source lines may be up to 132 characters long. Thus, source          line numbering in columns 73-80 is not available unless the          compilation option LENGTH=72 is chosen.       g) Lowercase letters are accepted and shifted to uppercase before          interpretation unless they occur within strings.       h) Variable names may contain the special characters underline "_"          and '$'. Thus, e.g. Start_Time and SYS$SYSTEM are legal names.          For determining the implicit data type, the first alphabetic          character is taken.       i) Names may have any length. All characters are relevant to the          compiler. For names belonging to external objects (COMMON blocks,          subroutines, functions), length restrictions might arise from          the subsequent assembler and linker steps.       j) Lines beginning with a "+" in column one are transferred to the          output without changes (just stripping off the "+"), thus allowing          for embedded assembly statements.         The following remarks also refer to the source format, but deal     with deviations from the standard, rather than extensions.       a) Blanks are meaningful in RTF/68K. For example, DO100 will not          be recognized correctly because a blank is required between          keyword and label. GO TO and GOTO, END DO and ENDDO, etc. are          however explicitly considered.       b) The first TAB character met in a source line, if it is within          the first eight columns, steps to column 10. Later TABs are          converted to blank.         The purpose of handling blanks in the described way is to eliminate     some of the huge redundancy of the Fortran language; namely, the     kind of redundancy which gives a very wrong semantic meaning to statements     with small misprints which are yet formally correct. Maybe you     know the example of the Mariner mission which failed due to the Fortran     statement                             DO 10 I=1.3                             ....     where of course a loop was the programmer's intention. But "DO 10 I"     is a valid variable name in the standard and was interpreted in that     way (because of the "."). - It is invalid and would have been flagged     as an error in RTF/68K.     2.2. Constants     --------------         According to the data types discussed in the next chapter, there     are four types of constants:            Integer, Floating Point, Boolean, and Character String.     Constants may be placed directly in the code, or they can be accessed     by names assigned to them with PARAMETER statements (see 2.4.2.). Not     much needs to be said about the latter three types of constants;     examples are:           Floating Point:                 123.456                 0.00000123456E8                 123456e-3           Boolean:                 .TRUE.                 .true.                 .FALSE.                 .False.           Character String:                 'this is the same thing'                 22Hthis is the same thing     !..but not recommended                 'THIS IS not THE SAME THING'     Integer constants may be decimal, bit-pattern, or ASCII oriented:                 1             decimal; value fits into one byte                 -128                 256                 -330                      (two bytes)                 -32768                 65535                 2000000000                (four bytes)                 'FFFF'X       hexadecimal (two bytes)                 '1000'X                 'ABCDEF'X                 (four bytes)                 '377777'O     octal       (four bytes)                 '111'O                    (two bytes)                 '101010'B     binary      (one byte)                 '1000110001'B             (two bytes)                 'ADAM'A       right-justfied ASCII (four bytes)                 '0'A                      (one byte)     Integer constants in a context where Floating Point is required     are converted at compile-time. Use of integer constants requiring     more bytes than are available in the context is flagged as an error;     e.g. I1=1000 where I1 is an INTEGER*1 variable. Note that the types                    Arithmetic (i.e. Integer or Floating Point)                    Boolean                    Character string     must not be intermixed, as opposed to VAX Fortran where Integer     and Boolean may be mixed. RTF/68K would flag this as an error.     Integer, floating point, and logical constants used as subroutine     arguments are passed as 4-byte entities, unless word-size modifier     intrinsic functions or the option INTSIZE=2 are used (see 2.5.6.     and 2.10.).     2.3. Data Types     ---------------         The following data types are available in RTF/68K.     a) Integer data types:          INTEGER             denotes 4-byte signed integer values                                             by default                                   or 2-byte signed integer values                                             with option INTSIZE=2          INTEGER*1           denotes 1-byte signed integer values          INTEGER*2              "    2-byte   "       "      "          INTEGER*4              "    4-byte   "       "      "          DOUBLE INTEGER         "    4-byte   "       "      "          BYTE                   "    1-byte   "       "      "     NOTE that the integer data types denote always signed values. In     operations with operands of different length (e.g. addition of a     INTEGER*4 value and an INTEGER*2 value), the shorter lenghts are     sign-extended to the longest length occuring. This may cause     undesired effects in non-arithmetic operations sensitive to bit     patterns (e.g. IOR, IAND etc.).     b) Floating point data types:          REAL                denotes 4-byte IEEE floating point values          REAL*4                 "    4-byte  "      "       "     "       ** REAL*8                 "    8-byte  "      "       "     "       ** DOUBLE PRECISION       "    8-byte  "      "       "     "       ** DOUBLE REAL            "    8-byte  "      "       "     "     NOTE that the 8-byte values are not yet included in RTF/68K. They     are treated as 4-byte values and a warning is given.     c) Boolean data types:          LOGICAL             denotes 4-byte boolean values                                             by default                                   or 2-byte boolean values                                             with option INTSIZE=2          LOGICAL*1           denotes 1-byte boolean values          LOGICAL*2              "    2-byte    "      "          LOGICAL*4              "    4-byte    "      "     Boolean data are determined in any case by one byte only; the most     significant byte in memory or the least significant byte in registers,     resp. An all-zero byte means .FALSE., any other value, preferrably all     ones, means .TRUE. This is in accordance with the "set according to     condition" instructions of the 68K family.     d) Complex data types:       ** COMPLEX             denotes a pair of 4-byte IEEE FP values       ** COMPLEX*8              "       "   "  4-byte  "   "    "     NOTE that complex data are not yet included in RTF/68K.     e) Character string data types:          CHARACTER           denotes 1-byte ASCII character values          CHARACTER*n            "    n-byte   "       "       "          CHARACTER*(*)          "    m-byte   "       "       "                              where m is determined by the calling                              routine for formal arguments; else                              m=256 by default.     Character variables are represented in memory just as the ASCII     characters, without any additional information. Thus EQUIVALENCE     of character and other variables is possible. Whenever a character     variable is accessed, however, a descriptor containing the     necessary extra information is formed. Note that character constants,     other than variables, are represented as null-terminated     strings.         Details on the memory representation of the various data types     may be found in chapter 4.4.     2.4. Declarations     -----------------         Declarations are the field where most of the deviations - extensions     and omissions - between RTF/68K and the standard show up. The reason     is that on one hand, the aim was to introduce the extensions as far     as possible by means of declarations, rather than by modifications in     the executable statements. This is a rather obvious method and offers     a way to enhance existing programs mainly by adding declarations.         On the other hand, the most irregular structures of Fortran are     found among the declarations. Some of these structures, e.g. recursion     of EQUIVALENCE statements, have been omitted because of their     irregularity. Other omissions (lack of some data types) are intended to     keep the entire RTF/68K system small, with the on-line applications     in mind.     2.4.1.  Global and local declarations     - - - - - - - - - - - - - - - - - - -         A nice way to repeat a common set of declarations (e.g. COMMONs)     in many subroutines is with INCLUDE files. Apart from the fact that     this is not standard Fortran, the widely used implementations support it.     RTF/68K also does.         The other way to introduce globally valid declarations is normally     offered by block-structured languages like Pascal etc. Fortran     knows one level of declarations: the subroutine level. Subroutines     have no block level above them (apart from the semantic binding of     COMMONs which is recognized only during linking time) nor below     them (apart from statement functions). The advantage is that subroutines     can be compiled separately. Disadvantages are that conflicting     declarations cannot be recognized by the compiler, and that     identical declarations have to be repeated in different subroutines     as mentioned above. Block structured languages allow for several,     nested block levels. The scope of validity of a declaration is the     block where the declaration is made and all lower-level blocks     contained in it. If a variable already declared is re-declared on     a lower block level, the latter declaration is valid within the     lower block.         RTF/68K ranges between Fortran and block-structured languages:       1) It accepts usual Fortran. The declarations made within subroutines          are called 'local declarations' in what follows.       2) It allows for one level above the subroutine level: the 'global          declarations'. These are usual Fortran declaration statements          which are written once in front of a set of subroutines in a          file. The global declarations are valid within all of these          subroutines.       3) In order to exclude an obvious source of errors, it is not allowed          to re-declare global variables locally.       4) In order that the compiler can recognize global declarations and          distinguish them from local declarations within a main program,          the PROGRAM statement is mandatory.       5) There is also one extra level of declarations below the subroutine          level which allows for dynamic storage allocation (see 2.7.4.          for the ALLOCATE-ENDBLOCK construct).         Some examples might illustrate the use of global declarations.     (a)  'Standard' example. Without use of global declarations, a set of          routines would look like:            PROGRAM P          \            INCLUDE 'I.FOR'    |            INTEGER II,JJ      |  Main program            REAL ...           |            ...                |            END                /            SUBROUTINE S       \            INCLUDE 'I.FOR'    |            DATA A /1.0/       |  Routine 1            ...                |            END                /            FUNCTION F(X)      \            INCLUDE 'I.FOR'    |  Routine 2            ...                |            END                /          where the INCLUDE file contains e.g.            COMMON /A/ A,B,C            COMMON /S/ I,J,K            PARAMETER (PI=3.14)          Using global declarations, one can write it as follows:            INCLUDE 'I.FOR'       Global declarations            PROGRAM P          \            INTEGER II,JJ      |            REAL ...           |  Main program            ...                |            END                /            SUBROUTINE S       \            DATA A /1.0/       |  Routine 1            ...                |            END                /            FUNCTION F(X)      \            ...                |  Routine 2            END                /          Notes:  1) The PROGRAM statement is required in RTF68K.                     Without it, the local declarations of P would                     be taken as global, and the first executable                     statement of P would be flagged as an error.                  2) Local declarations stay within each routine.                  3) Global declarations of course need not be                     contained in INCLUDE files. The contents of                     I.FOR could be given in place of the INCLUDE                     statements in the example above.                  4) The global variable A has been preset with                     DATA locally. This is possible but bad style.                     The preferred method would be to give the DATA                     statement globally.     (b)  In the above example, A is a global variable. Redeclaration          of A like (referring to the example above)            FUNCTION F(X)            DIMENSION A(100)            ...            END          is illegal and flagged as an error.     (c)  Global variables should be normally in COMMON blocks, but this          is not necessary in principle. Consider, again referring to the          example (a), the following contents of I.FOR:            REAL A,B,C            INTEGER I,J,K            PARAMETER (PI=3.14)          Still, the variables A,B,C,I,J,K and the constant named PI          are globally defined. However, the variables reside now not          in the memory for COMMON blocks, but in the space drawn from          the stack when the program is initialized. Thus, the connection          to separately compiled files which are linked with the          example file is no longer as obvious as would be the case for          COMMON blocks. In fact, non-COMMON global variables from separate          files will normally overlap in memory, unless special          care is taken (see chapter 4.4.).          The use of such global variables should thus be restricted to          system libraries.     (d)  Also other kinds of declarations may be written in the global          declarations part, e.g. the special ones            EQUIVALENCE (ILOOP,D7)            KEEP D7          The effect is that ILOOP is now a globally declared variable          which resides in register D7 for speed, and is saved/restored          on each routine's entry/return (see chapter 2.5.8.).         Apart from the scope of a declaration, the scope of validity of     the value carried by a declared variable has to be considered. The     former has to do with the static nesting of blocks as written down     in the program source, the latter deals with the dynamic nesting of     blocks during execution. Fortran usually disallows recursivity, i.e.     a subroutine cannot call itself (neither directly or indirectly     through another routine). At least, results of such calls are     inpredictable. On the other hand, the standard says that the values of     local variables of a subroutine are lost when you leave the routine     and enter it again, unless the variables are in COMMON or SAVE.     Nevertheless, many Fortran implementations leave those values unchanged.     RTF/68K offers an option (SAVE=ALL) to guarantee this, too.         Now note the following: recursivity has the consequence that the     values of local variables must be lost when leaving the routine.     Re-entrancy, which is a requirement in interrupt-driven real-time     environments, is a more general case of recursivity. Thus, if you     want to use RTF/68K in the field it was made for, the values of local     variables are for sure lost when leaving a routine (COMMON or SAVE     variables must be used with great care in cases where re-entrancy is     required). The reason is of course that space for local variables has     to be allocated on the stack, and this space is re-used for other     variables after leaving the routine.         One further consequence is on DATA statements: variables which     are preset with DATA cannot be on the stack. They must be SAVEd or in     COMMON. Routines which alter the values of DATA variables are not     reentrant. If the values are not altered, the variables are constants     and should better be declared with PARAMETER.     2.4.2. PARAMETER declarations     - - - - - - - - - - - - - - -         PARAMETER declarations assign names to arithmetic, logical, or     character string constants. These names can be used in place of the     constant, e.g. also as array bounds in DIMENSION declarations. They     offer the possibility to define a constant, which is used in many     places within a program, in one central place only. Whenever a value     is really constant during program execution, PARAMETER is very much     preferred over DATA statements.         PARAMETER statements may be given globally or locally. Like on the     VAX, PARAMETER statements may be written with (standard) or without     parentheses, e.g.:             PARAMETER (pi=3.14159,max=500,assert='YES')         or             PARAMETER pi=3.14159,max=500,assert='YES'     The data type associated with the name is always the data type of the     constant, e.g. REAL for pi, CHARACTER*3 for assert in the example above.     Please refer to  2.2. for the various forms of integer constants.     One may also state the data type in addition with a type declaration,     but only before the PARAMETER statement. The type declaration, if given,     must agree completely with the constant used in the PARAMETER statement.     E.g.,             REAL pi; INTEGER max; CHARACTER*3 assert             PARAMETER (pi=3.14159,max=500,assert='YES')     is legal, while             REAL pi,amax; CHARACTER*5 assert             PARAMETER (pi=3.14159,amax=500,assert='YES')     contains two errors.     2.4.3. Data type declarations     - - - - - - - - - - - - - - -         The data types available have already been listed in 2.3.     above. Consider <type> to be one of      INTEGER, INTEGER*1, INTEGER*2, INTEGER*4, DOUBLE INTEGER, BYTE      REAL, REAL*4, REAL*8, DOUBLE PRECISION, DOUBLE REAL      LOGICAL, LOGICAL*1, LOGICAL*2, LOGICAL*4      COMPLEX, COMPLEX*8      CHARACTER, CHARACTER*n, CHARACTER*(*).     Then a data type declaration has the form ([..] denotes     optional syntax elements):         <type> <dcl>[,<dcl>...]     where <dcl> is one of:         <name>  [<arraybounds>]      or         @<name> [<arraybounds>]  .     The former is the standard Fortran-77 variable or array     declaration, while the latter declares a pointer-based     variable or array (@ is the symbol for 'pointer to' or     'address of').     <name> is a usual Fortran name of any length and may,     apart from uppercase letters and digits, also contain     lowercase letters, underline, and dollar characters.         Pointer-based variables have their address assigned     or changed during execution of the program; please refer     to 2.4.11. and 2.7. for further explanation. Note here     that in case of pointer variables or arrays of any data     type, four bytes are always reserved for the address of     the variable. No space is allocated for the values. The     data type, and accordingly the word size, is an attribute     of the value of a variable and has nothing to do with     its address.     2.4.4. DIMENSION declarations     - - - - - - - - - - - - - - -         This declaration is in principle redundant in Fortran     because array bounds may also be given together with other     declarations, e.g. of data type. The syntax is:         DIMENSION <vdcl>[,<vdcl>...]     where <vdcl> is one of         <name>  <arraybounds>    or         @<name> <arraybounds>  .     The former is the standard Fortran-77 array declaration,     while the latter declares a pointer-based array.     The array bounds have the usual form:         (<bounds>[,<bounds>...])     with the following choices for <bounds>:         <integer constant>                   or         <integer constant:integer constant>  or         <integer variable>  .     In RTF/68K, up to five <bounds> are permitted; i.e.     tensors of rank five can be handled.     The third of the above forms of <bounds> provides     variable array bounds. While normally restricted to     formal arguments of routines, RTF/68K allows variable     bounds also for pointer-based arrays; see the example     of chapter 1.1. above. The mechanism is clear: bounds     may be variable because in both cases memory is not     allocated during compilation, but only during program     execution.     2.4.5.  COMMON declarations     - - - - - - - - - - - - - -         As in the standard, COMMON declarations serve are     used to make storage blocks accessible globally for     several routines. Storage allocation is usually performed     by the linker. In addition, RTF allows to allocate storage     under the programmer's control: either to a fixed address     known when writing the program or to a variable address     known only during execution. For the latter, see also the     RECORD declaration below.        The syntax of COMMON declarations is on of         COMMON          <dcl>[,<dcl>...]         COMMON    //    <dcl>[,<dcl>...]         COMMON /<base>/ <dcl>[,<dcl>...]  .        See 2.4.3. above for <dcl>.        The first and second forms both denote 'blank COMMON'.     The latter form denotes 'named COMMON' as usual, but in     RTF is also used for 'absolute COMMON' and 'pointer-based     COMMON', depending on the from of <base> which is one of:         <name>                   or         <integer constant>       or         @<name>               .        The first form results in standard 'named COMMON' and     space is allocated by the linker which will normally give     an absolute base address to the COMMON block at link-time.     If the option COMMON=INDIRECT is chosen, the <name> form     has the same effect as the @<name> form (see below). Still,     the operating system takes care of space allocation, but     this can then be delayed until load-time (necessary e.g.     on the MacIntosh).        The second form results in 'absolute COMMON'. Here, the     programmer determines the base address of the COMMON block     at programming time. The block can by this means placed into     special hardware, e.g. an extra fast memory module. The     integer constant may also be a PARAMETER declared before     the COMMON declaration, e.g.          Parameter (VectorBase='100000'X)          Common /VectorBase/ IVector(0:255)       or just          Common /'100000'X/ IVector(0:255)  .      The system gets no notice about absolute COMMONs.         The third form denotes 'pointer-based COMMON'. Here,     the allocation of space for the COMMON block can be made     more dynamically - at load-time or at run-time, depending     on how the pointer is declared.         If @<name> is not declared explicitely somewhere, then     the system will take care of space allocation at load-time.     For the user, this looks much like ordinary named COMMON,     apart from the fact that the base address can still be     modified at run-time. The <name> form with option COMMON=     INDIRECT has the same effect as the @<name> form without     explicit pointer declaration. In both cases, the base address     is held in a storage word addressed relative to the program     counter at the end of a program module. Thus, care must be     taken when changing this storage word: the base address will     be altered only in this program module. Other, separately     compiled modules will not be affected (an appropriate waring     is given by the compiler). Briefly speaking, @<name> without     explicit pointer declaration is meant for load-time     allocation of space as required by some operating systems,     and not primarily for run-time allocation under the user's     control.         If, however, the pointer is declared explicitely before     the COMMON declaration, the operating system does not get     notice of the COMMON block, and the user has to allocate     space at run-time. This is done with an assignment statement     for the pointer, e.g.:            Integer @Struct,CpuIndex,CpuBase            Common /@Struct/ Xlow(1000),Xup(1000)            ...            @Struct=CpuIndex*'800000'X+CpuBase            Xup(I)=XLow(I)+123.4     This can be applied for shifting data structures around in     memory. The purpose of the RECORD statement (see below) is     exactly the same. The 'scope' of the space allocation is     the same as the scope of the declaration of the pointer;     i.e. if @Struct in the above example is a local variable     of a routine, the entire pointer-based COMMON is defined     only in this routine. On the other extreme, if @Struct is     itself in an ordinary COMMON block, then the definition     is global - i.e., the effect of the @Struct=... statement     is global.     2.4.6.  SAVE declarations     - - - - - - - - - - - - -         According to the standard, the SAVE declaration is used     to maintain the values of variables when leaving and reentering     routines. For many Fortran implementations, this is achieved     even without SAVE. In RTF, however, and in full accordance with     the standard, SAVE is required if values of local variables of     a routine are to be maintained during leave from that routine.     Without SAVE, those variables would reside on the stack for     re-entrancy and hence their values are lost on exit from the     routine. COMMON variables are always maintained.         The syntax of the SAVE declaration is:         SAVE  <dcl>[,<dcl>...]       or         SAVE  /<name>/            .     Note that local variables can be preset with DATA statements     in RTF only if they appear in a SAVE declaration. There are no     such restrictions for COMMON variables.         A global SAVE for all local variables can be enforced with     the option SAVE=ALL. This may be useful when porting programs     from the usual (but non-reentrant) Fortran environments to RTF.     2.4.7. EQUIVALENCE declarations     - - - - - - - - - - - - - - - -         EQUIVALENCE declarations are the Fortran programmer's way     to control storage allocation of variables. In the standard,     they can be used to control memory addresses of variables     relative to each other; e.g. variables of different data types     and formats can share the same storage. As such, EQUIVALENCE     is considered bad practice. In RTF, EQUIVALENCE can (and is     meant to) be used to control the absolute positions rather than     the relative positions of variables, although the latter is     also possible.         The syntax of EQUIVALENCE in RTF is:         EQUIVALENCE (<name>,<base>)     or         EQUIVALENCE (@<name>,<base>)         where <name> is the name of a variable to which storage     is not allocated by other means than the EQUIVALENCE statement     (e.g., COMMON variables not allowed here). <base> may be one of         <variable ref>                  or         <integer constant>              or         <register name>                 or         @<name>                       .     <variable ref> is the name of a simple variable, array, or an     array element reference. This form is used for the standard     EQUIVALENCE statements. Note that only pairs of arguments may     appear in RTF.     <integer constant> is used to give a fixed absolute address to     a variable. This is useful for accessing special hardware     locations easily, e.g.:                    Integer*1 IOReg                    Equivalence (IOReg,'FF0021'X)                    ...                    IOReg=15   .     <register name> is used to force a variable in a register of     the CPU or a coprocessor. The following symbols are reserved     words when appearing as the second argument of EQUIVALENCE:         D0, D1, D2, D3, D4, D5, D6, D7                for the data registers of the 68K processor         A0, A1, A2, A3, A4, A5, A6, A7 or SP                for the address registers of the 68K processor         F0, F1, F2, F3, F4, F5, F6, F7                for the floating point registers - valid for                the MC68881 coprocessor, the NS16081 processor,                and software emulation         SR     for the status register of the 68K processor.     Variables of any data type (1, 2, or 4 bytes long) except     CHARACTER, as well as pointers, may reside in the data or     address registers. Typically, values should be kept in data     registers, and pointers in address registers.     The floating point registers are useful only for variables     of type REAL.     Variables EQUIVALENCEd with the status register must be     declared INTEGER*2.         The purpose of putting values or pointers in registers     is twofold:       1. a considerable gain in speed for frequently used          variables or pointers,       2. a way of interfacing e.g. with operating systems          that expect or deliver parameters in registers.     Note that registers used by the programmer via EQUIVALENCE,     unlike registers allocated automatically by the compiler,     are not saved on entry and restored on exit from the routine     that uses them. The KEEP directive (see below) has to     be used for this purpose if it is desired to keep register     contents unaltered for the outside world. This is a must     for interrupt service routines and normally true also for     usual routines.        @<name> is used for EQUIVALENCEing with pointers. This is     useful e.g. when making an equivalence with a formal argument     which is passed by reference. Note that whenever variables are     pointer-based, only their pointer may be used in EQUIVALENCE     because the allocation of variables are not known at compile     time.     Examples of EQUIVALENCE:      1 ...the standard way:         INTEGER*1 I1(4); INTEGER*4 I4         COMMON /XX/ I4         EQUIVALENCE (I1,I4)      2 ...with an absolute address:         INTEGER*2 RegisterFile(0:15)         EQUIVALENCE (RegisterFile,'3400006'O)         ...         RegisterFile(0)=1      3 ...with data registers:         Function Dot(N,A,B)         Integer A(N),B(N),N,I,S         Equivalence (I,D7),(S,D6)         Keep D7,D6         S=0         Do I=1,N           S=S+A(I)*B(I)         EndDo         Dot=S         End      4 ...with address registers in addition:         Function Dot(N,A,B)         Integer A(N),B(N),N,I,S,AA(N),BB(N)         Equivalence (I,d7),(S,d6),(@AA,a4),(@BB,a3)         Keep a3,a4,d6,d7         @AA=@A         @BB=@B         S=0         Do I=1,N           S=S+AA(+)*BB(+)         EndDo         Dot=S         End         Note the special array indexing used in the formula.         Writing S=S+AA(I)*BB(I) or S=S+A(I)*B(I) would both         give exactly the same result, but the 'autoincrement'         form chosen is by far the fastest. It is only available         if the pointer to the array resides in an address register.         The compiler generates the post-increment mode         of addressing of the 68K processor for it. The code         generated from S=S+AA(+)*BB(+) is (option CPU=68020):               MOVE.L  (A4)+,D2               MULS.L  (A3)+,D2               ADD.L   D2,D7      .         Using as an array reference e.g. BB(-) results in the         pre-decrement addressing mode.         In the above example, it is in principle not necessary         to copy the pointer of array A into an address register.         The first two formal arguments of routines are copied         to address registers automatically by the compiler in         order to have fast access to them (unless option REGUSE=         OFF is used). Thus also the special addressing mode is         available for A. But beware: the pointer is of course         changed by using the special addressing mode! This does         no harm in the example because the pointer is no longer         used afterwards.      5 ...with floating point registers:         Equivalence (X,F7),(X2,F6)         Keep F6,F7         ...         X2=X**2         V=exp(X2-sin(X2)*cos(X)+sinh(X))         The code generated for the above formula is in the case         of the 68881 coprocessor (option FLOAT=HARD):                FMOVE.X FP6,FP0                FSIN.X FP6,FP1                FCOS.X FP7,FP2                FMUL.X FP2,FP1                FSUB.X FP1,FP0                FSINH.X FP7,FP1                FADD.X FP1,FP0                FETOX.X FP0,FP1                FMOVE.S FP1,<V>         The advantage is obvious from this code: the coprocessor         is utilized optimally. Apart from fetching the result,         no operand moving between CPU and coprocessor takes place.      6 ...with the status register:         Equivalence (CpuStatus,SR)         Integer*2 CpuStatus         ...         If(CpuStatus.lt.0) ...   ! check if in TRACE mode         Note that access to the status register is only allowed         in supervisor mode. The PRIORITY=... statement (see         below) can be used if only the priority part of the         status word should be affected.         Also note that there is no KEEP for the SR. Explicit         save/restore to e.g. a local variable must be used for         temporary changes to the status register. In interrupt         service routines, the status before interrupt occurance         is restored automatically on routine exit.      7 ... with formal arguments:         Subroutine S(X)         Real X(100)         Integer IX(100)         Equivalence (@IX,@X)         ...         Subroutine T(%VAL(Y))         Real Y         Integer IY         Equivalence (IY,Y)         ...         Note that Equivalence (IX,X) which semantically looks the         same would not be accepted by the compiler. Only items         which occupy memory with addresses known at compile time         can be equivalenced; in the first example above, those items         are the pointers to X and IX, while in the second example,         the values of Y and IY.         As can be seen from the examples above, registers used     by the programmer with EQUIVALENCE should be allocated starting     from the upper end of the available sets of registers, i.e.     starting with D7, D6... for the data registers, A4, A3... for     the address registers, and F7, F6... for the floating point     registers. A7, A6, and A5 are reserved for use by the system     (thus there is often a shortage of address registers). The     compiler starts allocating registers from the lower ends of     the sets. If a clash between user's and compiler's allocation     occurs, a warning is given.     The restrictions in the standard use of EQUIVALENCE will be     removed in a later release of RTF.     2.4.8.  EXTERNAL declarations     - - - - - - - - - - - - - - -         EXTERNAL declarations are normally used to state that a     name refers to a subroutine or function in cases where this     is not obvious from the context, i.e. when such names are used     as actual arguments of routines. This is also the case in RTF.         In addition to that, also variables and even entire COMMON     blocks can be made to refer to external objects (e.g., data which     are located at an entry point of an assembler routine). This     corresponds to the IMPORT and EXPORT variables known in Pascal.     In order to distinguish those variables from standard EXTERNALs     and to provide an access method by the standard linkers, they     have to be pointer-based, i.e. their names have to be preceded     by '@' in the EXTERNAL declaration.         Examples:         External @Iarr         Integer Iarr(20,20)         ...         Iarr(5,5)=0         External @Com,@I         Common /@Com/ X,Y,Iz(100)         ...         X=Y+Iz(I)         In these examples, the addresses of the external variables     (Iarr and X,Y,Iz,I) are equated by the linker to entry points     in other code modules.     2.4.9.  DATA statements     - - - - - - - - - - - -         DATA statements belong to the declarations part of a     routine and are used to preset variables with values once     prior to execution of the user's code. Values may be changed     afterwards; if not, i.e. if the variables are in fact     constants, PARAMETER declarations should be used whenever     possible (e.g. not for arrays). DATA statements result either     in blocks of data put into the appropriate storage location     by the loader, or in pieces of code executed after loading     and before the user's program is entered, depending on the     operating environment.         DATA statements must be put between the last of the     other declarations and the first executable statement,     statement function definition, or INTERRUPT attribute of     a routine.         In RTF, DATA statements have no purpose in addition to     the standard one. Instead, there are some restrictions for     the variable list. The syntax in RTF is:         DATA <var>/<const list>/[[,]<var>/<const list>...] .     <var> stands for a simple variable, an array name, an array     element reference, or a pointer. Note that only one item, not     a list, is allowed for <var>. Implied-Do lists are not allowed.     Moreover, <var> must be declared SAVE if it is a local variable.     Only global, COMMON, or SAVE variables can be preset with DATA.         Example:         Subroutine Junk         Logical FirstTime         Integer Arr(0:9,2)         Save FirstTime, Arr         Data FirstTime/.true./, Arr/10*0,10*1/         ...         is legal in RTF, while omission of the SAVE or writing         Data FirstTime,Arr/.true.,10*0,10*1/ are not.     The restrictions will be removed in a later release of RTF.     2.4.10. INCLUDE directive     - - - - - - - - - - - - -         The INCLUDE directive is an extension to the standard present     in most Fortran implementations. It is useful for inserting a     piece of source text from a different file, especially one which     contains all COMMON declarations used by a set of subroutines.         The syntax in RTF is:         INCLUDE  '<filename>'      (VAX style)  or         $INCLUDE  <filename>       (NORD style).     The syntax and interpretation of <filename> depends on the operating     system under which RTF is executed. E.g., under CP/M, the drive     identifier of the main source file is prefixed to the file name of     the INCLUDE file as the default drive.     2.4.11.  Pointers     - - - - - - - - -         Pointers contain the addresses of variables rather than the     values, which are carried by the variables themselves. The concept     of accessing values indirectly through pointers is not unknown to     Fortran users; it is used all the time when replacing the formal     arguments of a subroutine definition with the actual arguments of     a subroutine call. By means of the subroutine call, the programmer     determines the addresses of the formal arguments. This is the only     occurence of pointers in Fortran.         The additional feature available with pointer variables as in     RTF (or C, Pascal) is that the programmer has full control on the     addresses of variables, not only of formal arguments. Many illustrations     for pointers were used already on the previous pages; in     summary, pointers are adequate for variables or data structures     whose position in the 68K's address space is determined only at     run-time. Paragraph 2.7. is devoted to the use of pointers. Only     one important rule that must be obeyed for declaring pointer     variables is stated here:         If the address of a variable is to be changed in the         executable part of a routine, the variable must either         be declared as a pointer variable, or not declared at         all. Examples:                Integer @ITDC                @ITDC=ICamAd(B,C,N,A,F,T)                JTDC=ITDC         or                @ITDC=ICamAd(B,C,N,A,F,T)                JTDC=ITDC         are both correct and give the same result. It is not         correct to declare ITDC without the pointer mark '@':                Integer ITDC                @ITDC=ICamAd(B,C,N,A,F,T)                JTDC=ITDC         The compiler gives an error message in this case for         the second statement which tries to modify the address         of a variable which is not pointer-based, but has a         fixed address assigned by the compiler.     (Semantic meaning: in the above examples it is assumed     that the CPU has memory-mapped access to a CAMAC system,     and that the function ICamAd returns the address of a     CAMAC object with given branch B, crate C, station N,     subaddress A, function F, and wordsize T. Once the address     is assigned to the pointer variable ITDC, the access to     it, i.e. the I/O to the CAMAC system, is as simple and     as fast as the access to a normal variable in memory.)         Note also that there exists in RTF an extension to the     ASSIGN statement which is normally used to handle addresses     of statement labels. Here it can be used for addresses of     variables or array elements as well. This provides the func-     tionality of the 'abbreviations' known from the transputer     language OCCAM. For example,                ASSIGN A(I,J,K) to B(0)                B(0)=B(1)-B(-1)     has the effect that a linear array B is defined which has     the same data type as A and where the element B(0) has the     same address as the element A(I,J). B can the be used as a     shorthand form for A(I,J,K), B(1) for A(I+1,J,K), etc. This     speeds up access very much in cases where A(I,J,K) and elements     with constant offset relative to A(I,J,K) are accessed frequ-     ently - especially if @B is EQUIVALENCEd with an address     register.     2.4.12. RECORD declarations     - - - - - - - - - - - - - -         The pointer-based COMMON blocks have been described     already in paragraph 2.4.5.; a RECORD is exactly the same     as a pointer-based COMMON whose pointer is explicitely     declared. Syntax:         RECORD /<name>/ <dcl>[,<dcl>...]     <name> is the name of a variable not declared so far, or     declared as a pointer variable. Included in the latter     case are formal arguments of routines. As mentioned earlier,     the purpose of RECORDs is to have data structures that can     be imposed on any block of storage, just by setting the     address of the RECORD properly. Examples:      1 ...the pointer is not declared elsewhere, hence it is         allocated on the stack (local variable):         Subroutine Junk         Record /D/ Flags,X,Y,Z         Integer Flags; Real X,Y,Z         @D=...                    ! set base address of RECORD         If(Btest(Flags,0)) X=...      2 ...the pointer is declared as a COMMON variable:         Subroutine Junk         Common /Bases/ @D         ! assume @D is set elsewhere         Record /D/ Flags,X,Y,Z         Integer Flags; Real X,Y,Z         If(Btest(Flags,0)) X=...      3 ...the pointer is declared as a formal argument:         Subroutine Junk(D)        ! @D supplied by subroutine call         Record /D/ Flags,X,Y,Z         Integer Flags; Real X,Y,Z         If(Btest(Flags,0)) X=...     In the second example, it would be illegal to omit the '@' in     the COMMON declaration.     2.5. Subroutines and Functions     ------------------------------         This chapter is intended to provide details of the implementation     with respect to subroutine and function definitions and calls rather     than the language-guide type of information on this topic. Also, the     extensions available for interrupt handling etc. are described.     2.5.1. General overview     - - - - - - - - - - - -         Passing of arguments from the calling program to a subroutine or     function can be done in RTF by three different means:                by VALUE      - the value of a variable, constant, or                                expression is passed;                by REFERENCE  - the address of a variable, array, or                                auxiliary variable containing the value                                of a constant or expression is passed;                by DESCRIPTOR - the address of a descriptor block which                                contains further information is passed                                (details are found below).         The default method is passing by reference for all objects except     for character variables or character expressions which are passed by     descriptor. Arguments optionally may be passed by value. In the call     as well as in the subroutine/function declaration, they have to be     prefixed by a "#" for this purpose. This calling method is restricted     to simple variables and constants. It is slightly faster than call by     reference and may be necessary for compatibility with routines written     in other languages calling or called by RTF routines.         Trailing actual arguments may be omitted (short parameter list) if     precautions in the called routine are taken.         All arguments are transferred via the stack. Arguments are pushed     on the stack before the call and removed from the stack after the call     by the calling program.         The first two arguments (i.e., their addresses when called by     reference) are copied to address registers inside of the called routine     in order to have fast access to them. With the option REGUSE=OFF, this     optimization is switched off. This may be useful in cases where the     compiler runs out of address registers within subroutines.         Function results are returned via the register D0 if the value     of the result fits into 32 bits (so far, everything except type     CHARACTER). Otherwise, the stckframe contains an address, provided     by the caller, which points to where the value has to go.         When passed by reference, actual arguments may be simple variables,     expressions, arrays (those three not of type CHARACTER), EXTERNALs, and     constants (including string constants). Formal arguments may be simple     variables, arrays (both not of type CHARACTER), or formal subroutines     or functions. Passing by descriptor applies for actual arguments which     are simple variables or expressions of type CHARACTER, and any formal     arguments of type CHARACTER. When passed by value (i.e. with the '#'     in front) actual arguments may be simple variables, constants, or     expressions. Formal arguments may then only be simple variables. Type     CHARACTER is not allowed for call by value.         Side exits from subroutines are denoted in the standard way by "$"     or "*".         Secondary entry points are defined by ENTRY as usual. In addition,     entry points coded with embedded assembler statements (and thus     invisible to the compiler) can be declared with the "ASSEMBLER name"     statement (see below).         If inside of a function definition its declared name appears     with an argument list, e.g in expressions, this results in a (legal)     recursive call of the function. Occurence of the function name inside     the function without an argument list is handled in the standard way,     i.e. as the present value of the function identifier.         All registers explicitely used by the compiler are saved during     subroutine calls. This is required for reentrancy. The registers     referenced by the user with EQUIVALENCE (variable,register) are,     however, not automatically saved. The KEEP statement must be used     to save these registers unless the routine is intended to change one     or all of these registers.         Subroutines may be statically designated to handle certain     interrupts. This is requested with the "INTERRUPT vectornumber" statement     which has to follow immediately all declaration statements of the     subroutine. The specific meanings of vectornumber values is hardware     dependent. The effect is to modify the appropriate interrupt vector     cell during initialisation such that it points to the routine.         The current priority of a task may be changed with the statement     PRIORITY=prio, where prio is a constant between 0 and 7. The user     should be aware of the effects resulting from priority changing. In     routines serving interrupts, the priority is automatically reset to     its value prior to the interrupt when returning from the routine.         The code generated by RTF for subroutine definitions and calls     is compatible with the 'CERN calling conventions for 68k processors'     with the exception that registers are saved by default inside of     the called routine instead of by the caller. This scheme is necessary     for direct interrupt server routines. A compilation option, REGSAVE=     OUTSIDE, forces RTF to stick to the CERN scheme also for register     saving. In addition to, but compatible with the CERN scheme, the     actual number of arguments is passed to the called routine via D0     to be able to handle short argument lists. For the option CODE=OS9,     register assignments stick to OS9 rules instead of CERN conventions;     the actual number of arguments may then be passed via the condition     code register, CCR.     2.5.2.  Stack Assignment during Calls     - - - - - - - - - - - - - - - - - - -         In the following, AG denotes the base register for the global/     static variables, and AL denotes the base register for local variables.     For all options but OS9, AG is A5 and AL is A6. For OS9, ist is just     the other way around: AG is A6 and AL is A5.         Actual parameters (addresses, 32-bit values) are pushed on the     stack by the calling program in the reverse order of the argument     list. Note that pushing uses pre-decrement addressing mode which     lowers the stack pointer. After that, the call (with assembler     instruction JSR) pushes the return address on the stack. In the     called routine, the LINK instruction saves the address register AL     on the stack and reserves space for local variables. Local variables     are addressed relative to AL, i.e., with the d(AL) mode. Then, the     entry address to the routine and an all-zero word are written to     locations -4(AL) and -12(AL) (-8(AL) is unused), resp., providing     information for the symbolic debugger and traceback. This is done     only if the option DEBUG=ON is chosen. Following these words, the     contents of the necessary data-, address-, and floating point     registers are saved within the local space. Local program variables     are allocated from -204(AL) downwards.         It is normally the calling program's responsibility to remove     the arguments from the stack after return from the call, by moving     the stack pointer with an LEA d(A7),A7 instruction. If the called     routine takes a side exit, i.e. it does not return into the proper     point of the calling sequence, it removes the arguments itself. In     this case, short argument lists are not allowed, because the number     of arguments stated in the routine declaration is removed.         If the called routine is a function, it returns its result via     D0. If the result occupies 4 bytes or less, the value is returned     directly in D0. If the result occupies more than 4 bytes, the value     is returned to the memory location pointed to by D0. This is the case     for type CHARACTER functions only. Note that those functions are thus     not able to obtain the actual number of arguments in D0.         The stack layout after entry into the called routine (more precisely,     after registers are saved and debug information is stored) is shown in     the figure below. If you require access to the stackframe from Fortran,     use the predeclared INTEGER*4 array STACKFRAME with indices given as     below; e.g., STACKFRAME(21) contains the return address.     For non-OS9:                      |                           |                      |     stack before call     |                      |                           |                      |---------------------------|             +(n+1)*4 |        parameter n        |   STACKFRAME(n+21)                      |- - - - - - - - - - - - - -|                      :                           :                      |- - - - - - - - - - - - - -|                +8    |        parameter 1        |   STACKFRAME(22)                      |---------------------------|                +4    |      return address       |   STACKFRAME(21)                      |---------------------------|               A6 --> |      link location        |   STACKFRAME(20)                      |---------------------------|                -4    |      entry address        |   STACKFRAME(19)                      |---------------------------|                -8    |       (undefined)         |                      |---------------------------|                -12   |          (zero)           |   STACKFRAME(17)                      |---------------------------|                -16   | A7   (if requested)       |                      : .   data and address      :                      : .  register save area     :                      : .   4 bytes/register      :                -76   | D0   (always saved)       |   STACKFRAME(1)                      |---------------------------|                -80   | FP7  (if required)        |                      : .    floating point       :                      : .  register save area     :                      : .   12 bytes/register     :                -172  | FP0  (if required)        |                      |---------------------------|                -176  |                           |                      :        (reserved)         :                -200  |                           |                      |---------------------------|                -204  |                           |                      : space for local variables :               A7 --> |                           |                      |---------------------------|                      |                           |                      |   free stack after call   |                      |                           |     For OS9:                      |                           |                      |     stack before call     |                      |                           |                      |---------------------------|                    \             +(n-1)*4 |        parameter n        |   STACKFRAME(n+19) | only                      |- - - - - - - - - - - - - -|                    |                      :                           :                    |  if                      |- - - - - - - - - - - - - -|                    |                +8    |        parameter 3        |   STACKFRAME(22)   | n>=3                      |---------------------------|                    /                       .... parameter 2 in D1 .....                       .... parameter 1 in D0 .....                +4    |      return address       |   STACKFRAME(21)                      |---------------------------|               A5 --> |      link location        |   STACKFRAME(20)                      |---------------------------|                -4    |      entry address        |   STACKFRAME(19)                      |---------------------------|                -8    |       (undefined)         |                      |---------------------------|                -12   |          (zero)           |   STACKFRAME(17)                      |---------------------------|                -16   | A7   (if requested)       |                      : .   data and address      :                      : .  register save area     :                      : .   4 bytes/register      :                -76   | D0   (always saved)       |   STACKFRAME(1)                      |---------------------------|                -80   | FP7  (if required)        |                      : .    floating point       :                      : .  register save area     :                      : .   12 bytes/register     :                -172  | FP0  (if required)        |                      |---------------------------|                -176  |                           |                      :        (reserved)         :                -200  |                           |                      |---------------------------|                -204  |                           |                      : space for local variables :               A7 --> |                           |                      |---------------------------|                      |                           |                      |   free stack after call   |                      |                           |     Summary of register usage in connection with calls:       D0:   scratch register; on entry, contains number of actual arguments,             or address of first parameter if OS9.             On exit, contains result if function call, else the value on entry.       D1:   \       ..    | working registers. For OS9, D1 contains address of 2nd parameter.       D7:   /       A0:   address of first actual argument (if >= 1 formal arg. present and                                               REGUSE=ON; else work register).       A1:   address of second  "       "     (if >= 2 formal args. present and                                               REGUSE=ON; else work register).       A2:   \       A3:   | working registers.       A4:   /       AG:   global space pointer (global user variables and system variables,                                   d(AG) ).       AL:   local space pointer  (local user variables inside routine ,d(AL)                                   with negative offset).       A7:   stack pointer.     Format of character string descriptors:       Whenever a character VARIABLE is referenced, a descriptor of this     variable is set up in the following format (3 longwords occupied):         < - - - - 32 bits - - - - ->         +--------------------------+         |address of first character|    Regardless of substring indices         |------------+-------------|         |lower index |  upper index|    These are the substring indices         |------------+-------------|         |pointer to next descriptor|    Zero if nothing concatenated.         +--------------------------+       For example, assume CHARACTER*10 A,B. Then the descriptors look     as follows for various character expressions:         +--------------------------+         |    address of A(1:1)     |    for A         |------------+-------------|         |      1     |     10      |         |------------+-------------|         |            0             |         +--------------------------+         +--------------------------+         |    address of B(1:1)     |    for B(2:5)         |------------+-------------|         |      2     |      5      |         |------------+-------------|         |            0             |         +--------------------------+         +--------------------------+         |    address of A(1:1)     |    for A(1:5)//B(6:10)         |------------+-------------|         |      1     |      5      |         |------------+-------------|         |    address of descr.2    |--         +--------------------------+ |       -- - - - - - - < - - - - - - - -       | +--------------------------+       ->|    address of B(1:1)     |         |------------+-------------|         |      6     |     10      |         |------------+-------------|         |            0             |         +--------------------------+       In calls, the address of the descriptor of character variables or     expressions is given, with the sign bit of this address set to 1.     This allows to distinguish between descriptors and normal addresses.     For character CONSTANTS, the address of the first character is given,     with the sign bit cleared as usual. Character constants are null     terminated. As soon as an expression is formed with constants, e.g.     'ABC'//'DEF', however, a descriptor is set up.     2.5.3.  ENTRY specification     - - - - - - - - - - - - - -         The ENTRY specification is used to provide alternative entry     points into subroutines and functions; the same is true for RTF.         The formal arguments of an ENTRY can differ from those of the     main entry point in number, names, and order. In RTF, when a formal     argument has the same name as one of the main entry or a previous     ENTRY, a warning is given. After the ENTRY, the ordering of     arguments stated there is maintained statically.         Example:         Subroutine Alfa(A,X,Y)         Real A,B,X,Y         A=X-Y         Entry Beta(B,Y,X)        ! CAUTION X and Y change roles         B=X-Y         End         In this odd example, the following happens when entry Alfa     is called with CALL ALFA(O,P,Q). First, O is assigned the value     P minus Q. Then (after skipping the non-executable ENTRY     specification) O is assigned the value Q minus P. That is of course     not what you want - so be aware of this implicit EQUIVALENCE scheme     when using ENTRY!     2.5.4.  ASSEMBLER entry specification     - - - - - - - - - - - - - - - - - - -         This extension to Fortran is provided for pieces of code     written in embedded assembly code. Other than writing the entry     point declaration also in embedded assembly, the RTF ASSEMBLER     entry specification makes it an 'official' entry point which     fully sticks to the rules imposed by the interactive linker,     symbolic debugger, and traceback. Formal arguments are not     allowed at ASSEMBLER entry points.         Example:         Subroutine Dummy         Assembler Kill     +   ILLEGAL         Assembler Fiddle     +   MOVE.L #4711,A7     +   RTS         End     2.5.5.  Statement functions     - - - - - - - - - - - - - -         Statement functions conform to the standard. They are implemented     not like macros which are inserted at every call point, but     are entered with JSR and left with RTS much like external functions.     Only the way of argument passing is faster: the arguments of a     statement function as well as its value are local variables of     the program unit containing the statement function. In effect,     arguments are passed by value. Also, time for saving and restoring     registers is minimized.     2.5.6.  Intrinsic functions and subroutines     - - - - - - - - - - - - - - - - - - - - - -         The following paragraph describes the functions and subroutines     which are recognized by the compiler as non-external and are handled     in a special way. The purpose is twofold: a) run-time efficiency,     and b) special handling of involved data types (generic functions).     2.5.6.1.  Intrinsic functions         Note that the routine names specified in this chapter cannot act     as substitutions for dummy routines in subroutine or function calls;     i.e. they cannot be declared EXTERNAL. For example,                    CALL SUB(X,ABS)     is NOT allowed.     They may, of course, be used in expressions which are used as actual     arguments:                    CALL SUB(ABS(X))    is allowed.     The reason is that fast in-line code is generated for the routines     described in this chapter rather than subroutine/function calls. For     some of the routines, this is only true if certain compiler options     are chosen.     2.5.6.1.1. Bit manipulation functions        i = IAND(j,k) or       I is the bit-by-bit product of j and k.        i = AND (j,k)          Both must be INTEGER (any size), as is the                               result.                               Example: MANTISSA=AND(IREAL,'7FFFFF'X).        i = IOR (j,k) or       I is the bit-by-bit sum of j and k.        i = OR  (j,k)          Both must be INTEGER (any size), as is the                               result.                               Example: PATTERN=IOR(PATTERN,ENDFLAG).        i = IEOR(j,k) or       I is the bit-by-bit difference of j and k.            EOR (j,k) or       Both must be INTEGER (any size), as is the            IXOR(j,k) or       result.            XOR (j,k)                               Example: ITOGGLE=EOR(ITOGGLE,1).        i = INOT(j)   or       I is the bit-by-bit inverse of j.        i = NOT (j)            The data type of the result is that of j.                               Example: ZERO=IAND(MASK,NOT(MASK)).        i = IBSET(j,k)         I is the same as j but the k-th bit set.                               The data type of the result is that of j.                               The data type of k must be INTEGER (any size).                               K is evaluated modulo 32.                               Example: REALMINUS=IBSET(REAL,31).        i = IBCLR(j,k)         I is the same as j but the k-th bit cleared.                               The data type of the result is that of j.                               The data type of k must be INTEGER (any size).                               K is evaluated modulo 32.                               Example: REALABS=IBCLR(REAL,31).        i = IBCHG(j,k)         I is the same as j but the k-th bit inverted.                               The data type of the result is that of j.                               The data type of k must be INTEGER (any size).                               K is evaluated modulo 32.                               Example: REALINV=IBCHG(REAL,31).        i = ISHFT(j,k)         I is j shifted by abs(k) places to the left                               (if k positive) or right (if k negative).                               The bits shifted out are lost and zeros are                               filled in. The data type of the result is                               that of j. The data type of k must be INTEGER                               (any size). K is evaluated modulo 32.                               Example: IEXPO=ISHFT(IREAL,-23).        if (BTEST(j,k)) ...    BTEST is a logical function which is TRUE                               if the k-th bit of j is set. The data type of                               k must be integer (any size). K is evaluated                               modulo 32.                               Example: IF(BTEST(STATUS,12)) CALL ALARM.     2.5.6.1.2. Other functions that produce in-line code        i = MOD(j,k)           I is j modulo k. If k is a power of two,                               a AND is carried out, otherwise a divide.                               J and k must both be INTEGER (any size),                               as is the result.                               Example: IAND255=MOD(I,256).        i = IABS(j)            I is the absolute value of j. J must be                               INTEGER (any size), as is the result.        r = ABS (s)            R is the absolute value of s. S may be of                               type INTEGER (any size) or REAL. The data                               type of the result is REAL.        i = IFIX(j)            I is j, converted to INTEGER by truncating                               to the nearest integer closer to zero. J                               must have INTEGER (any size) or REAL data                               type. The type of the result is INTEGER.                               Example: TRUNC=IFIX(REAL).        r = FLOAT(s)           I is s, converted to REAL. S must have                               INTEGER (any size) or REAL data type. The                               type of the result is REAL.                               Example: ISAME=FLOAT(I).        i = ICHAR(c)           I is the binary representation of the first                               ASCII character of the string c. The result                               is type INTEGER. C must have type CHARACTER.                               Example: LOWERA=ICHAR('a').        c = CHAR (j)           C is the ASCII string representation of the                               binary value j. J must have type INTEGER (any                               size). The result is type CHARACTER*1.                               Example: CHARSET(I:I)=CHAR(I).        if (Lcc(c,d)) ...      Lcc is a logical value stating the result of                               lexical comparison of two CHARACTER strings                               c and d. cc may be one of LE, GE, NE, LT, GT,                               or EQ.                               Example: IF(LEQ(INPUT,'EXIT')) STOP.        Note: Lcc(c,d) generates the same code as c.cc.d .        if (OWNER(sema))...    OWNER is a access control primitive which uses                               the TAS instruction of the processor to test                               and set a semaphore. It is a logical function                               which is .TRUE. if the semaphore was free, i.e.                               the calling program owns it after the call.                               Sema must be variable (not expression) of any                               data type; only its first byte is accessed.                               A natural choice would be INTEGER*1. Releasing                               the resource then works with sema=0.                               Example: DO WHILE(.NOT.OWNER(BRANCH))                                          CALL WAIT                                        ENDDO                                        ...                                        CALL ACCESS                                        ...                                        BRANCH=0     2.5.6.1.3. Standard functions        r = func(s)            Func is the value of the standard function                               acting on the argument s. S must have                               INTEGER (any size) or REAL data type. Func                               has data type REAL. Func stands for:                               SQRT,                               SIN, COS, TAN, ASIN, ACOS, ATAN,                               EXP, EXP10, ALOG, ALOG10,                               SINH, COSH, TANH, ATANH.        r = RNDM(j)            RNDM is a high-quality random generator with                               uniform distribution in (0,1). J must be                               declared as INTEGER*4 J(2). The two values should                               be initialized and are updated in each RNDM                               call. They can be saved as a starting point                               for later use. The type of the result is REAL.                               RNDM provides a period length of 2**64.        r = RNORM(j)           RNORM generates random numbers with normal                               distribution (derived from 12 calls to RNDM).                               Call similar to RNDM.        i = LEN(j)             LEN calculates the number of characters in the                               character string expression j.                               Example: CHARACTER*128 CH                                        ...                                        NONBL=LEN(CH(1:-1)) ! length without                                        ...                 ! trailing blanks        i=INDEX(j1,j2)         INDEX calculates the character index in the                               character string expression where the character                               string expression j2 starts. Zero is returned                               if j2 is not found in j1.                               Example: I=INDEX(FILE,'.')                                        IF(I.NE.0) THEN                                          FILE1=FILE(:I)//'FOR'                                        ELSE                                          FILE2=FILE//'.FOR'                                        ENDIF        i = INT(x)             I is x, truncated to the nearest integer                               closer to zero. X must have REAL data type,                               the type of the result is INTEGER. Same as                               IFIX above, but not a generic function.        i = NINT(x)            I is x, rounded to the nearest integer. X                               must be type REAL. The type of the result                               is INTEGER. Not a generic function.                               Example: IROUND=NINT(R).        i = INCHR(lu)          Single character input without wait. Lu is                               the logical unit (INTEGER*4). I (INTEGER*4)                               is zero if no character is present; else                               it has the integer value of the ASCII                               character entered.                               Example: do forever                                          i=inchr(1)                                          if(i.ne.0) then                                            call action(i)                                          else                                            call background                                          ...     2.5.6.1.4. Word size modifiers          These serve as a shorthand alternative for mixtures of data type     and EQUIVALENCE statements (especially when accessing the same hardware     in different modes). Note that, if used on the left side of assignments,     they are outside the Fortran standard.        i = BYTE(j)            Regardless of the data type specification        BYTE(j) = i            of j, only its first data byte is read or                               written, resp.; i.e., the result is as if                               j were declared as INTEGER*1. If BYTE is                               used for reading (on the right hand side                               or in arithmetic expressions), its argument                               may be a constant.        i = WORD(j)            The same for the first 2 bytes (word) of        WORD(j) = i            j; like INTEGER*2 declaration.        i = LONG(j)            The same for the first 4 bytes (longword)        LONG(j) = i            of j; like INTEGER*4 declaration.         CAUTION: note the quite different (peek/poke type) meaning of the     above intrinsic names in ABSOFT Fortran. Use EQUIVALENCE with absolute     addresses or pointer variables if the effect of the ABSOFT BYTE, WORD,     or LONG is desired.     2.5.6.2.  Intrinsic subroutines         Some in-line procedures have been added which are invoked with     CALL statements. They perform simple, often-used operations at maximum     speed without any subroutine call overhead. - In particular, one class     uses instruction sequences which have 'looping capability' on the 68010,     acting on blocks of data. - Other classes act as 'hardware subroutines'     by activating peripheral processors or 68020 co-processors.     2.5.6.2.1. Looping mode routines        Note: Due to the nature of the DBcc instruction of the 68K processor     the block length l is evaluated modulo 2**16; i.e., the values 1 to 65536     are possible. Also note that the word sizes may apply for various data     types; e.g. _MOVL may be used for INTEGER*4, LOGICAL*4, and REAL*4 data,     _CMPB may be used for INTEGER*1 and LOGICAL*1, etc.        call _MOVL(s,d,l)      Moves a block of l words (size L or 4 bytes,        call _MOVW(s,d,l)      W or 2 bytes, B or one byte each) from s        call _MOVB(s,d,l)      to d, starting from the low addresses.                               Example: CALL _MOVB(ARRY(1),ARRY(1001),1000).        call _SETL(v,d,l)      Writes the value v (word size as above) into        call _SETW(v,d,l)      all l components of the block d.        call _SETB(v,d,l)                               Example: CALL _SETL(3.14,PIARR,LPIA)        call _CMPL(s1,s2,l)    Compares two blocks of l words each (word size        call _CMPW(s1,s2,l)    as above), s1 and s2. Comparison starts from        call _CMPB(s1,s2,l)    the low addresses and terminates when either                               two words are not equal or all l words are                               done. The result appears in the condition code                               register of the processor and can be checked                               subsequently.                               Example: CALL _CMPW(A,B,10000)                                        IF(.EQ.) THEN                                          CALL IDENTICAL                                        ELSE IF(.LT.) THEN  ! i.e. A < B                                           ...        As an alternate notation, one can also use the following aliases:        MOV_L, MOV_W, MOV_B                           _MOVL, _MOVW, _MOVB        SET_L, SET_W, SET_B      instead of, resp.    _SETL, _SETW, _SETB        CMP_L, CMP_W, CMP_B                           _CMPL, _CMPW, _CMPB.     2.5.6.2.2. Hardware subroutines       a) FASTBUS. A subset of the standard Fastbus routines is implemented     as a 68020 coprocessor. They are enabled by the option FB=HARD (see     above). Then statements of the following form result in generating     essentially one F-line coprocessor instruction instead of a subroutine     call:        call FBxx(p1,p2,...)   Please refer to Ref.2 for a complete list                               of FB hardware subroutines.                               Example: CALL FBBRD(PRIMA,SECA,DEST,LENGTH)       b) As the source of the compiler is easy to modify, more sets of special     hardware routines can be made available for Fortran use without runtime     overhead.     2.5.7. Obtaining the actual number of arguments     - - - - - - - - - - - - - - - - - - - - - - - -         As inidcated above, the caller passes the number of actual arguments     to the called routines if both          - the calling routine is compiled with option NUMPAR=ON            (this is the default)   and          - the called routine is not a type CHARACTER function.     Then the number of arguments is in register D0.L after entering the     called routine. The called routine may transfer the number of arguments     to a variable by using                 CALL NUMPAR(var)   or                 CALL NOARG(var)     as the first executable statement. The compiler then generates inline     code for that of the kind                 MOVE.L D0,var .     If the call is made without parameters, i.e.                 CALL NUMPAR()   or                 CALL NOARG()     no code is generated.     If the call is completely left out, however, RTF generates code to     check if the actual number of arguments is the same as the formal     number of arguments:                 CMP.W #formal,D0                 BEQ *+4                 JSR _BADPAR  .     This check may be suppressed with the option CHECK=OFF, or with a call     to NUMPAR/NOARG without arguments as described above.         Calling NUMPAR or NOARG other than in the first executable statement     results in a normal subroutine call to a user-supplied routine.     2.5.8. KEEP directive     - - - - - - - - - - -         The KEEP directive should accompany EQUIVALENCE with registers.     Other than registers which are allocated by the compiler itself,     the user-declared registers are not automatically saved at entry and     restored at exit of the routine using them. If the contents of user     declared registers is to be preserved for the outside world (which     is normally the case, and is a must for interrupt handler routines),     the names of those registers have to appear in the KEEP directive.     Otherwise, the routine exits with the value of the register(s) altered     - maybe useful only as an odd way of passing results.         Also when modifying registers in embedded assembly code parts,     these registers should appear in KEEP.         The registers accessible to the user by this means are the processor     data registers D0-D7, the processor address registers A0-A7,     and the floating point coprocessor data registers F0-F7. The processor     status register SR, which is accessible with EQUIVALENCE, cannot     appear in KEEP, however.         Example:         Function ISum(IA)         Integer*2 I,IA(100); Integer ISum,IS         Equivalence (I,d7),(IS,d6)         Keep D7,d6         IS=0         Do I=1,100           IS=IS+IA(+)         EndDo         ISum=IS         End         If one omits the KEEP in this example, the function should     be better called ITrouble - because it will affect the caller's     registers D6 and D7 in an uncontrolled manner!     2.5.9. INTERRUPT and EVENTFLAG directives     - - - - - - - - - - - - - - - - - - - - -         As mentioned previously, RTF subroutines can be used as interrupt     handlers without any operating system overhead. For this purpose, the     entry address of the subroutine is written into the appropriate longword     of the CPU's interrupt vector. On occurance of the interrupt     signal (an external hardware signal or software trap), the CPU's     firmware saves the current CPU status word and program counter (or     more for some special interrupts) on the stack and jumps directly     to the subroutine's entry point. The saving of the rest of the CPU's     current context (registers) is done by the subroutine internally.     Thus, it takes typically only 20 usec on a 10 MHz 68000 from the     interrupt to the first useful instruction of the subroutine (i.e.,     after the register saving).         The exit from an interrupt routine is special as compared to a     normal subroutine: not only the old program counter, but also the     old CPU status word are restored from the stack. Thus the return     from interrrupt has to use the assembler instruction RTE instead     of RTS.         Both setting up the interrupt vector location and preparing     the proper return instruction is done by the INTERRUPT directive.     It has to be the last of the declaration statements, i.e. it has     to be placed between DATA and statement functions (if any). After     the keyword INTERRUPT, either a integer constant in the range     2 to 255 or a '*' must follow. In the first case, the interrupt     vector location with the given constant as index is set to the     routine's entry address during program initialization, much as     with a DATA statement. The interrupt vector location is not     touched during initialization in the second case, but this is     then left for runtime (see subroutine ACTIVATE below). In both     cases, the proper return from interrupt is generated.         Examples:         Subroutine Iresp         Byte reg         Equivalence (reg,'ff3000'x)         Interrupt 200               ! set vector 200 to addr(Iresp)         reg=0                       ! 1st executable instruction         ...         End                         ! exit with RTE         Program Main         External Iresp1         ...         Call Activate(200,Iresp1)   ! set vector 200 to addr(Iresp1)         ...         End         Subroutine Iresp1         Byte reg         Equivalence (reg,'ff3000'x)         Interrupt *         reg=0                       ! 1st executable instruction         ...         End                         ! exit with RTE         In the first example, the interrupt vector is set automatically     during initialization, while this is done explicitely by the main     program in the second example.         If one uses the keyword EVENTFLAG instead of INTERRUPT, the     compiler generates an RTR instruction instead of RTE. A vector     number is not allowed then, only the '*'. This may be useful     for returning from asynchronous event handlers supported by     some operating systems (OS9, VersaDOS). Example:         Common /Flags/ IDone         Program Main         External Iresp2         ...         Call Enable(Iresp2...)      ! tell OS to enable handler         ...         End         Subroutine Iresp2         Eventflag *         IDone=1                     ! 1st executable instruction         ...         End                         ! exit with RTR     2.5.10.  CPU time required for subroutine calls     - - - - - - - - - - - - - - - - - - - - - - - -         The caller has to push the addresses of the N actual arguments     onto the stack (PEA intructions), move N to D0 (MOVEQ), perform the     jump to subroutine (JSR and JMP), and to clean up the stack after     return (ADDQ). The called routine has to setup the local variable     area (LINK), save registers (MOVEM), optionally check the actual     number of arguments and stack limit (two times CMP, Bcc), then     after execution of the user's code restore the registers (MOVEM),     remove the local variable area (UNLK), and return (RTS).         On a 68000 processor, a subroutine call requires thus the     following number of clock cycles:                          96 + 16*(n+m) + 28*c     where n is the number of actual arguments, m is the number of registers     to be saved inside of the routine, and c is 1 if the option     CHECK=ON is chosen, 0 else. For n=2, m=4, c=0 this sums up to 192     clock cycles or roughly 20 usec for a 10 MHz 68000.     2.5.11.  Type conversions for integer arguments     - - - - - - - - - - - - - - - - - - - - - - - -         There are cases where the conformation of actual and formal     subroutine arguments is not evident: for integer constants and     integer expressions containing INTEGER*2 parts. For example, in               INTEGER*2 I,J               ...               J=I+1               ...     the expression I+1 is treated as INTERGER*2, i.e. as a 16-bit     word. The same is true in               Options MULDIV=SHORT               ...               INTEGER*4 I               INTEGER*2 J               ...               J=I/5               ...     for the expression I/5 as a consequence of the 68000's DIVS     instruction, while in the case I/4 (use of shift) the type     is INTEGER*4.         The features mentioned above are justified by optimizing     criteria but are not at all obvious to the user, and hence     could lead to arbitrary results if such expressions are used     as actual subroutine arguments.         Therefore the following scheme is used to arrive at definite     data types for integer actual arguments.     (1) Simple variables and array elements are passed with the type         imposed by type declaration or implication as usual.     (2) Integer constants and integer expressions other than (1)         are passed as INTEGER*4 when the option INTSIZE=4 (default)         is chosen.     (3) Integer constants and integer expressions other than (1)         are passed as INTEGER*2 when the option INTSIZE=2 is chosen.         A similar difficulty occurs in principle also for LOGICAL     variables. However, due to the representation of logical values     with the topmost byte only, confusion of LOGICAL*1, *2, and *4     actual arguments has no effect.     2.6. Other language elements     ----------------------------     2.6.1.  Arithmetic, logical, and character string expressions     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -     2.6.2.  Assignment statements     - - - - - - - - - - - - - - -     2.6.3. Label and variable ASSIGN statements     - - - - - - - - - - - - - - - - - - - - - -         Label ASSIGN statements are used in Fortran in connection     with assigned GOTO statements. The syntax is:         ASSIGN <label> TO <variable>     where <label> is the label of an executable Fortran statement     in the same program unit. <variable> is a simple variable or an     array element of type INTEGER*4. The effect is that the address     of the labeled statement is stored in the variable. Later, this     address may be used in GOTO <variable> which results in an in-     direct jump.         In RTF, there exists an extension to the ASSIGN statement.     It can be used to access addresses of variables or array elements,     in addition to addresses of statement labels. It then acts as a     dynamic EQUIVALENCE performed at run-time. Syntax:         ASSIGN <variable> TO <base>     where <variable> is a simple variable or array element reference     of any data type. <base> has the form:         <name>           or         <name>(<const>)  .     <name> may be a name not declared so far, or a name declared as a     pointer variable or linear pointer-based array. The data type and array     bounds of     In both cases, a pointer-based, linear array of the same data type     as <variable> is declared. In the first case, the element name(1)     gets the same address as the variable, while in the second case,     name(const) gets the same address as the variable. <const> is an     integer constant.     This provides the functionality of the 'abbreviations' known from     the transputer language OCCAM.     Examples:        1.      ASSIGN A(I,J,K) to B(0)                B(0)=B(1)-B(-1)                B(2)=0           has the same effect as                A(I,J,K)=A(I+1,J,K)-A(I-1,J,K)                A(I+2,J,K)=0        2.      EQUIVALENCE (@XX,A4),(I,D7); KEEP A4,D7                ...                ASSIGN X(1,J,K) TO XX                S=0                DO I=1,N                  S=S+XX                  XX(+)=0                ENDDO           has the same effect as                S=0                DO I=1,N                  S=S+X(I,J,K)                  X(I,J,K)=0                ENDDO     In both cases, much speed is gained. In the first example, one     can also speak of an 'abbreviation', while this is not really the     case in the second example. In general, ASSIGN to variables pays     in cases where the same array element or elements with constant     offset relative to each other are accessed frequently.     2.6.4. DO loops     - - - - - - - -         Standard Fortran allows only one form of DO loops:         DO <label> [,] <variable>=<startexpr>,<endexpr> [,<stepexpr>]            [<statements>]     <label> <statement>     where <label> is the label of an executable Fortran statement later     in the same program unit, <variable> is a simple variable or array     reference of arithmetic data type, and <...expr> are arithmetic     expressions. Note that RTF allows only integer data types here.     The range of a DO loop may be empty, in which case the statements     following the DO are not executed. The sign of the optional step     expression determines whether the variable is increased or decreased     on each iteration.     There are additional forms of DO statements available in RTF:         DO [FOR] <variable>=<startexpr>,<endexpr> [,<stepexpr>]            [<statements>]         END DO         DO WHILE(<logical expression>)            [<statements>]         END DO         DO UNTIL(<logical expression>)            [<statements>]         END DO         DO FOREVER            [<statements>]         END DO     Note that ENDDO can be used instead of END DO.     The first form above (block DO) is an extension known from VAX or     NORD Fortran and is useful for more stuctured programming, avoiding     statement labels much like with the block IF.     The second form is an extension known from VAX Fortran. The loop is     executed while the logical expression is .TRUE. (maybe zero times).     Loop control takes place at the beginning of the loop. The third form     also allows loop control according to a logical expression, but here     the loop is executed at least once until the logical expression is     .TRUE.; loop control takes place at the end of the loop. The last     from is equivalent to DO WHILE(.TRUE.) and also results in the same     code.     2.6.5.  IF statements     - - - - - - - - - - -         Three kinds of conditional statements are available in Fortran:     arithmetic, logical, and block IF statements. The syntax is for     arithmetic IF:         IF(<arithmetic expr>) <label>,<label>,<label>     logical IF:         IF(<logical expr>) <statement>     block IF:         IF(<logical expr>) THEN           [<statements>]        [ELSE IF(<logical expr>) THEN           [<statements>] ]        [ELSE IF(<logical expr>) THEN           [<statements>] ]          ...        [ELSE           [<statements>] ]         END IF     where <arithmetic expr> is an expression of an INTEGER or REAL     data type, <label> is a label of an executable Fortran statement     in the same program unit, <logical expr> is an expression of type     LOGICAL, <statement> is a legal Fortran statement and <statements>     is one or more legal Fortran statements.     Arithmetic IF is considered old-style Fortran and bad practice.     In the case of block IF, one must be careful not to confuse an     ELSE IF clause with ELSE, followed by a different IF statement     on a new source statement line; even more so in the case of the     potentially free-format RTF: ELSE IF(...) on one line is the end     if clause, while ELSE followed by IF(...) on a new source line is     an ELSE clause, containing a new IF statement. END IF and ENDIF,     ELSE IF and ELSEIF are synonymous.     2.6.6.  GOTO statements     - - - - - - - - - - - -         There are three kinds of GOTO stetements in Fortran: uncond-     itional, assigned, and computed GOTO. The syntax is for     unconditional GOTO:         GOTO <label>     assigned GOTO:         GOTO <integer var> [ [,] <label>,<label>,... ]     computed GOTO:         GOTO (<label>,<label>...) [,] <integer expr>     where <label> is a label of an executable Fortran statement in the     same program unit, <integer var> is a simple variable or array     element of type INTEGER*4 which previously became defined with a     label ASSIGN statement, and <integer expr> is an expression of an     integer data type.     If a label list is provided in the assigned GOTO, it has only the     purpose of documenting potential GOTO target labels in RTF; the     compiler does not interprete the labels. The variable has to contain     the address of the target label, which is then reached by an ind-     irect JMP instruction.     Assuming a list of n labels is provided in a computed GOTO, the     integer expression should have a value between 1 and n. If the     value is outside of this range, the GOTO is not executed, and     the statement following the GOTO is executed next.     GOTO and GO TO are synonymous.     2.6.7.  Input/Output statements     - - - - - - - - - - - - - - - -     Formatted input:               READ(unit,fmt[,ERR=label][,END=label]) [,] ilist               READ fmt,ilist               ACCEPT fmt,ilist     Unformatted input:               READ(unit[,ERR=label[,END=label]) [,] ilist     Formatted output:               WRITE(unit,fmt[,ERR=label][,END=label]) [,] olist               PRINT fmt,olist               TYPE fmt,olist     Unformatted output:               WRITE(unit[,ERR=label[,END=label]) [,] olist     Unit is the logical I/O unit. It may be *, an integer constant or     expression, an array name, character variable name, or a pointer.     All of the latter three modes provide internal conversions.     The * denotes the default I/O unit (e.g. the terminal).     ilist contains simple variables or array elements, array names, or     implied loops made out of them. olist contains, in addition to ilist     elements, arithmetic, logical, or character string expressions     (including constants).     If the last character of a formatted output record is a "$", and the     output goes to a terminal, the record is output without this last "$"     and without CR/LF. If the last character is a "?", the action is     similar but the "?" is still output. Both are useful when prompting     for input from a terminal.     FORMAT statements are standard. Static fromats (supplied at compile-     time) and variable formats are supported. Format specifications, with     parentheses and between quotes, may also be contained in the I/O     statement itself.       Example:        type '(I5,Z9)',j1,j2           and         type 1000,j1,j2                  1000 format(I5,Z9)           are equivalent.     The following format field descriptors are supported:          I      decimal representation of integer data with default width                 (I12) on output or free-format input          Iw     same with width w on input and output          Iw.n   same, but at least n non-blank digits (leading zeros)                 on output          Z      hexadecimal representation of integer, real, or logical                 data with default width (Z9) on output or free-format                 input          Zw     same with width w on input and output          O      octal representation of integer, real, or logical data                 with default width (O12) on output or free-format input          Ow     same with width w on input and output          B      binary representation or integer, real, or logical data                 with default width (B33) on output or free-format input          Bw     same with width w on input and output          L      representation of logical data (T for .true. and F for                 .false.) with default width (T2) on output or free-format                 input          Lw     same with width w on input and output          A      ASCII representation of character, integer, real, or                 logical data. The width depends on the size of the data.          Aw     same with width w on input and output          F      fixed-point representation of real data with default                 width (F10.3) on output and free-format input          Fw.d   same with width w and d digits after the decimal point                 on input and output          E      normalized exponential representation of real data with                 width (E12.3) on output or free-format input          Ew.d   same with width w and d digits after the decimal point                 on input and output          D or G        same as E          Dw.d or Gw.d  same as Ew.d          X      one blank on output, skip one position on input          Tn     tabulation to column n; fills with blanks on output, skips                 on input          '...'  character constant (quoted) only for output          nH...  character constant (length n) only for output          (..)   encloses group of format descriptors     All of the above descriptors may be preceded by a repetition factor.     Further format elements are:          ,      delimiter between format elements          /      end-of-record mark; serves also as delimiter     OPEN and CLOSE have the following form:          OPEN([UNIT=]lu,[FILE=]filename [,STATUS=status]               [,CARRIAGECONTROL=carriagecontrol]               [,ACCESS=access] [,FORM=format]               [,ERR=errorlabel])          CLOSE([UNIT=]lu [,STATUS=status],[ERR=errorlabel])     Both forms result in according requests to a the local file system     or a file system remote on the host computer. Filename, status,     carriagecontrol, access, and form are character string expressions.     The values of these expressions, even if constants, are not checked     by the compiler. They are interpreted by the local or host computer's     file system. Useful values are for           Status:          'OLD', 'NEW', or 'UNKNOWN' ;                            'KEEP' or 'DELETE' for Close           Carriagecontrol: 'NONE', 'LIST', or 'FORTRAN'           Access:          'READ', 'WRITE', or 'BOTH'           Form:            'FORMATTED' or 'UNFORMATTED' .     Defaults depend on the file system.     The statements          BACKSPACE lu          REWIND lu          ENDFILE lu     complete the set of I/O statements available in RTF/68K.     INQUIRE is not yet implemented.     2.6.8. PRIORITY statement     - - - - - - - - - - - - -         This statement may be used to change the running priority     of the CPU, e.g. in order to allow/disallow interrupts up to     a certain interrupt priority. The statement affects the priority     part of the processor status register and is thus only allowed     in supervisor mode. Form:         PRIORITY = <octal constant>     where <octal constant> is an integer constant in the range 0-7.     PRIORITY is a reserved word in the above context.         For example, the statement is useful to lower the priority     to allow interrupts early in re-entrant interrupt handlers of     certain device drivers. Another example is the protection of     critical code parts by raising the priority to 7 temporarily     (it should be kept in mind that this scheme is incomplete     in multiprocessor setups where semaphores maybe required in     addition or instead).     2.6.9. CACHECONTROL statement     - - - - - - - - - - - - - - -         This statement has been added to allow dynamic changes to     the mode of the instruction cache of 68020 processors. This     statement affects the cache control register and is only allowed     in supervisor mode. Also, the option CPU=68020 must be selected.     Form:          CACHECONTROL = <control constant>     where <control constant> is a 4-bit integer constant. Useful values     are:          0   disable cache          1   enable cache          3   freeze and enable cache          8   clear and disable cache .     Normally, the cache should always be enabled.     2.7. Use of pointers     --------------------     2.8. Registers and absolute addresses     -------------------------------------     2.9. Output from the Compiler     -----------------------------     The compiler produces a list file and an assembler code output file.     The list file contains for each line the line number, the statement     nesting depth (zero outside program units, incremented by one for each     level of program unit, DO, IF, and ALLOCATE), an indication whether     declarations occured in the line, and the source text. The nesting     depth helps to find begins and ends, e.g. of loops, which belong     together. It is good practice to make the nesting levels visible     already when typing the source file by indentations. The declaration     indicator "$" serves as a warning against unintentional implicit     declarations, e.g. against misspelt variables.     The exact syntax of the generated assembly code can be controlled     with the option CODE=...     The assembler code file contains very readable code. If the option     MIX=ON is chosen, declarations result in comment statements (beginning     with "***") which give the name of the variable, its location, data     type etc. This provides the information required for dumps on variable     name level.     2.9.1. Sample Program Listing     - - - - - - - - - - - - - - -         The program has been compiled with OPTIONS LIST=ON (see next     paragraph). The following is the contents of the file SINUS.LIS produced     by the compiler:       1   0  OPTIONS LIST=ON       2   1 $      PROGRAM SINUS       3   1 $      PARAMETER (N=50)       4   1 $      INTEGER II(2)       5   1 $      TYPE *,'ONLY CONSOLE(0), ALSO FILE(1), ALSO VAX(3) ?'       6   1        ACCEPT *,MODE       7   1 $      TYPE *,'START !'       8   1        II(1)=1       9   1        II(2)=1      10   2        IF(BTEST(MODE,0))      11   1       *  OPEN(21,FILE='LOCAL::SINUS.DAT',STATUS='UNKNOWN')      12   2        IF(BTEST(MODE,1))      13   1       *  OPEN(22,FILE='SINUS.TST',STATUS='NEW',CARRIAGECONTROL='LIST')      14   2 $      DO I=1,N      15   2 $        X=RNDM(II)-0.5      16   2 $        X2=(1.-X)**2      17   2          TYPE 1000,I,SIN(I),X,X2      18   3          IF(BTEST(MODE,0)) WRITE(21,1000) I,SIN(I),X,X2      19   3          IF(BTEST(MODE,1)) WRITE(22,1000) I,SIN(I),X,X2      20   2   1000   FORMAT(I5,3F10.5)      21   1        ENDDO      22   1        IF(BTEST(MODE,0)) CLOSE(21)      23   1        IF(BTEST(MODE,1)) CLOSE(22)      24   0        END     Total Errors   0   Warnings   0         The first column gives the source line number. The second column     indicates the statement nesting level (nested DOs, IFs etc.). A '$' in     the third column, if present, indicates that some declaration has been     made in this line (e.g. for the new variables I, X, X2 which are     undeclared so far in the lines 14-16); it serves as a sort of warning. If     undeclared variables would appear on the right-hand side of expressions,     an explicit WARNING was issued.     2.10. Compiler Directives     -------------------------         Directives which control the listing, debugging, and code generation     options can be given within the source file.     2.10.1  OPTIONS directive     - - - - - - - - - - - - -         This directive allows to select between various code generation     options available in the RTF/68K compiler - regarding     the syntax of the generated assembly code, the kind of floating     point hardware/emulation used, the position-independence of the     generated code, and debugging features. Furthermore, various     listing options may be selected.     Syntax:        OPTIONS option,option,...      where 'option' may be any of the                                       following separated by commas                                       (order irrelevant, but in case of                                       contradicting options the last one                                       is valid):        SIZE = LONG | SHORT            LONG has to be selected if the                      -----            code size of the compiled module                                       exceeds 64 kB, i.e., no PC-relative                                       addressing posible. SHORT                                       (default) generates always position                                       independent code, LONG only                                       in the case of CPU=68020.        LIST = ON | OFF | INCLUDE      ON switches source-code listing                    ---                on, but include files are not                                       listed. INCLUDE lists source with                                       include files. OFF (default) lists                                       only errors and warnings.        FLOAT = NS | NSAC | HARD |     NS and NSAC generate special inline                                       code for the NS16081 floating                SOFT                   point chip - NS for the DATASUD CPUA1                ----                   and NSAC for the ELTEC SAC, resp.                                       HARD generates instructions for the                                       MC68881 floating point coprocessor.                                       It is only available for CPU=68020.                                       SOFT (default) uses the software                                       emulation package. - In all cases,                                       IEEE number format is used.        MIX = ON | OFF                 ON transfers the source lines and                   ---                 the memory allocation of the variables                                       to the generated assembler code                                       (as comment lines). OFF (default)                                       generates no such comments.        CODE = CPM | M68MIL | VERSA |  CPM generates the assembly syntax               - -   - - -    - - -    of the CP/M-68K assembler, M68MIL               AZTEC | OS9             the syntax of the M68MIL assembler               - - -   - -             from CERN, VERSA the syntax of the                                       Motorola assembler under VERSADOS,                                       AZTEC the syntax of the assembler                                       of the AZTEC C system, and OS9 the                                       syntax of the assembler of the OS9                                       operating system. Note that 'syntax'                                       also reflects partially the features                                       of the native operating system. The                                       default depends on the respective                                       native or host system.        DEBUG = ON | OFF               ON generates additional code for                     ---               comfortable debugging of the program                                       which imposes a small runtime                                       overhead. OFF (default) generates                                       plain code.        CHECK = ON | OFF               ON (default) causes called routines                --                     to check the number of actual arguments                                       they obtain as well as stack                                       limits. OFF omits such checks which                                       otherwise cost about 7 usec per call.        COMMON = ABSOLUTE | INDIRECT   ABSOLUTE (default) means that blank                 --------              and labeled commons are accessed by                                       absolute addresses. With INDIRECT                                       they are referenced indirectly via                                       a PC-relative pointer. -  Pointer                                       based commons are always referenced                                       indirectly, numerical commons are                                       always referenced absolute, regardless                                       of the COMMON option.        LINK = ABSOLUTE | RELATIVE     ABSOLUTE (default) means that absolute               --------                references to external routines                                       are generated. RELATIVE generates                                       relative references, i.e. modules                                       remain position-independent even                                       after linking. It imposes some runtime                                       overhead.                                       RELATIVE offers a way to overcome                                       the size limitation for position                                       independent code for 68000/68010.        CPU = 68000 | 68010 | 68020    Selects the CPU type for which code              -----   -----            is generated. 68000/010 are treated                                       identically and are the default; code                                       generated this way runs also on the                                       020. In 68020 mode, additional                                       instructions and addressing modes are                                       utilized which speed up execution.        FB = HARD | SOFT               Selects if a subset of Fastbus routines                    ----               is executed by special hardware                                       of software (default).        LENGTH = FULL | 72             Selects truncation of the source line                 ----                  input to 72 columns. The default FULL                                       accepts all of the source.        MULDIV = SHORT | LONG          Selects whether INTEGER multiply and                         ----          divide are performed with full 32-bit                                       arithmetics (default) or not. SHORT                                       gives faster code (MULS/DIVS                                       instructions on the 68000 instead of                                       software emulation).                                       For the 68020, this option has no                                       effect; 32-bit precision is always used.        SAVE = ALL | NORMAL            With ALL, all variables are kept in                     ------            permanent storage, i.e. they will                                       remain valid after routine exit and                                       new entry; NORMAL keeps the variables                                       which are not otherwise declared on                                       the stack, thus providing re-entrancy                                       (default).        INTSIZE = 2 | 4                Determines whether INTEGER and LOGICAL                      -                variables that are not explicitely                                       sized occupy 2 or 4 (default) bytes.        REGSAVE = NORMAL | OUTSIDE     Determines whether the registers are                  ------               saved by the called routine (default)                                       or by the caller. The latter is for                                       compatibility with some other language                                       implementations.        NUMPAR = ON | OFF              Determines whether the number of actual                 --                    arguments is passed (default) to the                                       called routines or not.        INIT = ON | OFF                Determines whether the code for system               --                      dependent initialization is generated                                       (default) or suppressed.        C_CALLS = ON | OFF             Determines whether calling sequences                  --                   are compatible with C (default) or not.                                       Valid only for CODE = OS9.        REGUSE = ON | OFF              Determines whether A0 and A1 are used                 --                    to hold the first two arguments within                                       routines (default) or not.     For example,         OPTIONS LIST=OFF,SIZE=SHORT,MIX=OFF,FLOAT=SOFT,CODE=M68MIL,                 DEBUG=OFF,CHECK=ON,COMMON=ABSOLUTE,LINK=ABSOLUTE,                 CPU=68000,FB=SOFT,LENGTH=FULL,MULDIV=LONG,SAVE=NORMAL,                 INTSIZE=4,REGSAVE=NORMAL,NUMPAR=ON,INIT=ON,C_CALLS=ON,                 REGUSE=ON     resembles the default for the cross compiler.         More than one OPTIONS directive may appear in a program. The     directive may be given at the very beginning of the module and in     front of any program unit. It may start in column 1 or 7.     2.10.2 PUBLIC directive     - - - - - - - - - - - -         The PUBLIC directive controls the format of the compiled module     and thus its adaptation to the operating system environment. - As     stated above, RTF/68K code relies very little on an operating system.     If PUBLIC is omitted, the stack and global space initialization is     done by the generated module itself. If PUBLIC is given, this     initialization is not done; instead, the module is then adapted to an     environment with a minimum linker/loader and has dynamic linking     capability (e.g. for interactive use).     Syntax:        PUBLIC entry,entry,...       where 'entry' is the name of an entry                                     point of one of the units contained                                     in the module. A branch table is set                                     up at the very beginning of the module                                     pointing to these entry points.         Only one PUBLIC directive is allowed. It must be either the first     directive in a module or immediately follow OPTIONS directives if they     are given at the beginning. The PUBLIC block may be in an INCLUDE file.     PUBLIC may start in column 1 or 7.         Please refer to the chapter on generated code for details on the     module layout with/without PUBLIC option.     2.10.3  USE directive     - - - - - - - - - - -         Implementations under some operating systems (e.g. CP/M, OS9) require     that all libraries used are made known to the system by the main program.     This is the purpose of the USE directive. On other systems, this     directive may act as a comment.     Syntax:        USE module,module,...        where 'module' is the name of a program                                     module. Typically, the module                                     name is derived from the source file                                     name of the module; e.g. module TEST                                     from CP/M source file TEST.FTN .                                     Subroutine calls are generated to the                                     initialization entry points of all                                     modules stated in USE.         Only one USE directive is allowed. It is meaningful only in a file     containing a main program. USE must be the first line of the file or     must follow OPTIONS and PUBLIC if any of these is given.         Please refer to the chapter on generated code for details on the     module layout with/without USE option.     2.11. Compilation Error Messages and Warnings     ---------------------------------------------         RTF/68K gives message numbers together with message texts. Error     messages are given in severe cases, warnings in cases which are not     necessarily fatal. The format of the messages is as follows:       ****** ERROR nnn IN LINE llll  -  LAST SYMBOL: sssss...       ----- message text...       listing of source line containing the error       **** WARNING nnn IN LINE llll  -  LAST SYMBOL: sssss...       ----- message text...       listing of source line causing the warning         nnn is the message number which corresponds to the message text in     the second line. llll is the number of the source line where the error     occured. The source symbol within the line which caused the error is also     given; however, a symbol internal to the compiler may also show up here.     When an error (not a warning) is detected, the compiler skips to the next     source statement. However, due to the recursive compilation technique,     recovery from errors is not always possible, and follow-up errors may     be detected in subsequent statements.         After a maximum of 20 errors, the compilation quits. There is no     limit on number of warnings.         The following is a table of the message numbers together with their     meanings.       1: 'Internal compiler error - please contact expert'       2: 'Identifier list expected'       3: 'End of file expected'       4: 'Options list missing or illegal'       5: 'Unknown option'       6: 'Identifier expected'       7: 'END expected'       8: 'Data space too big for 68000 - use COMMON block'       9: 'Keyword misspelt'      10: 'Label doubly defined'      11: 'Error in FORMAT list'      12: 'Pointer must be address register here'      13: 'Indexing not allowed here'      14: 'All variables must be fully declared'      15: 'Variable array bounds illegal here'      16: 'Quoted string expected'      17: 'Data type specification expected'      18: 'IMPLICIT list misspelt'      19: 'This data type or size is not supported'      20: 'Data type or array bounds doubly defined'      21: 'Attempt to redeclare global variables'      22: 'Wrong size specification'      23: 'Not enough indices given for this variable'      24: 'Only five dimensions supported'      25: 'Array bounds required'      26: 'This variable cannot be EXTERNAL'      27: 'Slash or identifier expected'      28: 'Storage doubly allocated'      29: 'Parenthesis or identifier expected'      30: 'COMMON address affected only in current file'      31: '= constant expected'      32: 'Parenthesis expected'      33: 'Comma expected'      34: 'Only two EQUIVALENCE partners supported'      35: 'Illegal EQUIVALENCE partner'      36: 'Illegal formal argument'      37: 'Illegal DATA variable list'      38: 'Variable must be COMMON, SAVE, or global'      39: 'Only one variable per DATA value list supported'      40: 'Error in DATA value list'      41: 'Data type inconsistency in DATA list'      42: 'No statement after label'      43: 'Keyword used as variable name'      44: 'Illegal use of variable name'      45: 'Label expected'      46: 'Expression expected'      47: 'Illegal actual argument'      48: 'Data type inconsistency in assignment statement'      49: 'Illegal mixing of data types'      50: 'Constant too big or unsupported data type'      51: 'Unavailable index for side exit'      52: 'Control constant must be between 0 and 7'      53: '%VAL(...) or %REF(...) expected'      54:             (unused)      55:             (unused)      56: 'Syntax must be: ASSIGN label/variable TO variable'      57: 'Data type must be INTEGER*4'      58: 'Running out of registers - split expression'      59: 'Syntax must be: GOTO (label,...label) [,] expr'      60: 'Data type must be INTEGER'      61: 'Syntax must be: GOTO variable [,(label,...label)]'      62: 'Syntax must be: IF (expression) ...'      63: 'IF statement expected'      64: 'END IF expected'      65: 'Executable statement expected'      66: 'Syntax must be: IF (expr) label,label,label'      67: '(log.expr) expected'      68: 'END DO expected'      69: 'Assignment to loop variable expected'      70: 'Loop terminal or step expression expected'      71: 'Syntax must be: (unit[,form][,ERR=lab][,END=lab])'      72: 'Input/output list expected'      73: 'Syntax must be: ( [UNIT=] unit, [FILE=] file ...)'      74: 'Syntax must be: ( [UNIT=] unit )'      75: 'Format specifier expected'      76: 'String expected'      77: 'ERR=label expected'      78: '(formatlist) expected'      79: 'END=label expected'      80: '= expected'      81: 'Data type must be INTEGER or CHARACTER'      82: 'Unit specifier expected'      83: 'Variable expected'      84: '= expression expected'      85: 'Logical expression expected'      86: 'Character expression expected'      87: 'Arithmetic expression expected'      88: 'Why compare constants? '      89: 'Concatenation operator // expected'      90: 'This operation is redundant'      91: '(variable) expected'      92: 'This variable is not specified so far'      93: '(expr,expr) expected'      94: 'Actual arguments list expected'      95: 'Autoincrement/decrement not allowed here'      96: 'Variable must be a pointer variable'      97: 'Integer constant expected'      98: 'Too many indices given for this variable'      99: 'Constant index expression expected'     100: '=expression expected - maybe keyword misspelt'     101: 'The generated code maybe not position-independent'     102: 'Register variables cannot be indexed'     103: 'Loop step expression is zero'     104: 'Only first array element allowed here'     105: 'Array bounds variable must be INTEGER*4'     106: 'Data type inconsistency in PARAMETER statement'     107: 'You cannot expect a result in this register'     108: 'Possible overlap with user-declared register'     109: 'Arguments of in-line routine must be declared'     110: 'Character string too long - truncated'     111: 'Incorrect FASTBUS coprocessor call'     112: 'Identifier illegal for statement function'     113: 'Substring operation (expr:expr) expected'     114: 'Syntax must be: ALLOCATE expr FOR var'     115: 'END BLOCK expected'     116: 'This label is undefined'     117: 'This DO loop label points backwards'     118: 'Available only on 68020'     119: 'Side exits not allowed for interrupt routines'     120: 'Formal parameter re-positioned at ENTRY'     121: 'Formal parameter doubly declared'     3. THE RUN-TIME LIBRARY     -----------------------     3.1. Main Features     ------------------      -  Floating point package which implements (in single precision)         the basic algebra and the standard functions. The floating point         number format is the 32-bit IEEE format.      -  Input/output to the host computer's file system, independent of         the kind of hardware link between host and microprocessor. OPEN and         subsequent WRITE e.g. to a magnetic tape connected to the host is         possible. A small support program (which is contained in the         RTF/68K package) has to run on the host for this purpose.      -  Routines for dynamic routing of interrupts to Fortran subroutines.         They simply exchange entries in the interrupt vector. This provides         very fast interrupt response directly by Fortran routines.         The vector locations may be defaulted to a dummy routine which         catches unassigned interrupts.     3.2. Details of Specific Routines     ---------------------------------     3.2.1. Floating Point Package (FPP)     -----------------------------------    The package implements arithmetics for single-precision (32 bit)    floating point numbers. On such numbers, it performs            load, store            basic algebra            type conversions            standard arithmetic functions.    The package resembles the NS16081 floating point chip. Two entry    points, _F09 and _F11, are provided to emulate the NS16000 F9 and    F11 instruction formats. Both are parametrized by 16-bit words    which follows the JSR _F09/_F11 instruction in the code.    The external number format is in IEEE 32-bit format :             31 30        23 22                         0            +--+------------+----------------------------+            |sg|  exponent  |         mantissa           |            +--+------------+----------------------------+    The number is negative if sg=1; exponent and mantissa are not    complemented. The offset of the exponent is 127; i.e., $40000000    represents 2.0, $BFC00000 represents -1.5, etc.    The most significant mantissa bit is always set and omitted in the    representation. An all-zero number represents the floating point    zero. If the exponent is zero, the entire number must be zero.    This convention is chosen in order to recognize most integers    (up to 2**23) that are by error handled as floating point numbers.    Two entry points, _FSV and _FRS, are provided for saving and re-    storing FP registers to the caller's save area, from -172(A6) on-    wards. (Please replace 'A6' with 'A5' for OS9 implementations).    The JSR _FSV/_FRS is followed by a word the n'th bit of    which, if set, indicates that Fn should be saved/restored (n=0-7).    A6 is the local base register as usual in the CERN conventions    for 68k.    The package is employed by the RTF/68K Real-Time Fortran-77    compiler for 68k processors. All processor registers remain    unchanged unless an external result (not in FP register) is    produced which is in D0. Arguments and results are passed via    D0. Like the NS16081, only the FP compare generates the correct    condition codes in the main processor's CCR.    The format of the opcode word following the JSR _F09/_F11 is as    follows. Note that the lower and upper byte are swapped!                   7        3 2    0  14 13  11 10 9  8       For _F09:  +----------+----------+------+--+----+                  |   gen1   |   gen2   |  op  | f|  i |                  +----------+----------+------+--+----+       The id-word is $3E.       Gen1 and gen2 denote source and destination, resp., namely:        0 to 7     FP registers F0 to F7          15       data external to FPU (in D0)       Op denotes the opcode: 0 for MOVIF, 5 for MOVFI. Only these two       type-converting moves are implemented.       F denotes the FP data type. Only f=1 (single precision) is im-       plemented.       I denotes the integer data type. Only i=3 (32-bit word) is im-       plemented.                   15      11 10       6 5      2 1   0       For _F11:  +----------+----------+--------+--+--+                  |   gen1   |   gen2   |   op   | 0| f|                  +----------+----------+--------+--+--+       The id-word is $BE.       Opcodes are  1  for  MOVEF                    0       ADDF                    4       SUBF                    C       MULF                    8       DIVF                    5       NEGF                    D       ABSF                    2       CMPF .       Please refer to the National Semiconductors NS16081 data sheet       for further details.    Error messages (floating point overflow, divide by zero, ALOG or    SQRT negative argument, EXP overrange, non-implemented FP instr)    appear on the terminal. The program is aborted.    The internal (unpacked) representation of this package uses two    longwords for the eight pseudo FP registers F0-F7. The FP regist-    ers reside in the 32 bytes from -172(A6) onwards - save/restore of    these software registers are thus dummy operations.             31 30                          8 7         0            +--+-----------------------------+-----------+            | 1|           mantissa          |extra  bits|            +--+-----------------------------+-----------+             31                16 15 14     8 7         0            +--------------------+--+--------+-----------+            |       unused       |sg|    0   |  exponent |            +--------------------+--+--------+-----------+     Execution times of the software package are about 60 usec for basic     arithmetic and about 700 usec for the standard functions on a 10 MHz     68000. This is abou 20 times slower than the 16 MHz 68881 FP coproc-     essor used with the 68020. As programs are seldom pure floating point,     the overall speed remains still reasonable. For example, a matrix     inversion algorithm (Gauss elimination without pivot search) executes     12 times slower on a 10 MHz 68000 than on a VAX 11/780.     3.2.2. Input/Output Package     ---------------------------     The input/output package provides the interface from the Fortran I/O     statements to the hardware involved. This interface comprises I/O     conversions, formatting, associating logical channels (units) with     files via OPEN/CLOSE, routing of requests to the target hardware     devices, queueing of requests if necessary, and performs the actions     specific to the devices.     The package is written in Fortran and also includes a small assembler     part.     3.2.3. Dynamic Interrupt Handling     ---------------------------------     In addition to the static assignment of subroutines to interrupts     during compilation described in 2.3., dynamic activation and     de-activation at run-time is provided by two subroutine calls:                CALL ACTIVATE(vectornumber,routine)                CALL PASSIVATE(vectornumber).     Vectornumber values are hardware-dependent as mentioned in 2.3.;     routine is a subroutine name which is declared EXTERNAL or is a formal     parameter of the routine calling ACTIVATE. The interrupt vector entry     given by vectornumber is set to point to routine. The effect of     ACTIVATE is cancelled by PASSIVATE. The interrupt vector entry is then     reset to its default. This is represented by the library subroutine     IDLE which just types the message "unexpected interrupt on line nnnn"     in case of an interrupt not assigned to another routine. Exception:     the trace interrupt (vectornumber 9) is defaulted to the standard     tracing routine. This routine, TRACE, displays program counter,     status, data and address registers, and then prompts the user for     further action. It may be superseded by ACTIVATEing a user routine     as described above.     3.2.4. CAMAC Address Function     -----------------------------     The integer function ICAMAD calculates the address of a CAMAC module     inside the 68K address space. Arguments are crate, station, subaddress,     and function. Crate number zero means the local crate where     the ACC-processor resides in (standard case), numbers 1-7 mean one     of the crates along the branch if the processor acts as a branch     controller via a branch interface. All parameters are checked for     validity. Abort and traceback are initiated in case of error.     Example: integer*2 @icam              integer*4 @jcam              @icam=icamad(b,0,n,a,f,1)  ! calculate address of b,c=0,n,a,f                                         ! .. the 1 stands for 16-bit size              idat=icam                  ! read from that module              ...              idat2=icam                 ! second time with same address              @jcam=icamad(b,1,m,a,16,0) ! calculate an address in crate 1                                         ! .. the 0 stands for 24-bit size              jcam=0                     ! write zero into module              ...              jcam=icam                  ! direct transfer between modules.                                                                18 FEB 84                                                                HVDS/CERN                Description of Distribution Tape and Diskette for                -------------------------------------------------                 RTF/68K  Fortran-77 Compiler and Runtime System                 -----------------------------------------------     1. Scope     --------         The information stored on this tape and/or floppy disk has been     grouped into three categories:                1) A Fortran-77 CROSS COMPILER generating code                   for Motorola 68K family microprocessors, with                   or without use of a NS16081 floating point                   unit.                2) The same compiler as a NATIVE COMPILER for                   68K family microprocessors.                3) A Fortran-77 RUN-TIME LIBRARY on which the                   code generated by the compiler(s) relies                   for execution on the 68K target system.         The software can be executed WITHOUT MODIFICATIONS on the     following systems:                a) The CROSS COMPILER on any VAX running a VMS                   operating system.                b) The NATIVE COMPILER on VME systems containing                   an ELTEC EUROCOM-3 (and eventually extra memory                   boards) with at least 3/4 MBytes of memory,                   running under CP/M-68K with floppies and/or                   Winchester disk.                c) The same environment as under b) may be used                   as the target system.     2. Adaptation to other systems     ------------------------------         One of the intentions behind RTF/68K is PORTABILITY. This applies     for the compiler as well as for the runtime system. For this     reason the distribution media contain SOURCES of various language     levels, RELOCATABLE files, and EXECUTABLE files.         In fact, the dependence of the runtime system on the environment     is confined in one small assembler file. The entire runtime system     is position-independent.         The native compiler, interfacing to the environment through this     same runtime system, needs little extra. Also, the implementor     might like to modify the user and file-system interface of the compiler     which is a small Fortran program completely separated from the     internal action of the compiler which is confined in a 120-kBytes     object. This object constitutes the body of the native compiler     and is simply called as a Fortran INTEGER FUNCTION expecting line-by-line     I/O from the main program. All sorts of tricks like interactive     compiling, integration with an editor etc. can be played by     modifying the small Fortran program.         The cross compiler, finally, can be installed on any computer     (32-bit) with a big enough Fortran-77 environment. It is actually     running on VAX and NORD computers - and of course 68K ...     3. Media     --------         The physical parameters of the distribution media, and the way     they have been written, are as follows:                a) The distribution tape is 1600 BPI, with the                   ANSI label RTF68K, and is written on a VAX                   with a series of COPY commands.                b) The distribution diskette is 5 1/4 inch,                   80 track, double side, double density, and                   has the CP/M-68K file structure.     4. Types of files     -----------------         In the hierarchy of sources, the source of the compiler in     the SYNTAX-ORIENTED language PRAGMA ranges highest. It is included     on the tape for reference only as the compiler-compiler required     to process them is normally useless and distributed on request     only. This source form is contained in the files with extension     ...PRA . - The source is the same for cross and native versions.         Generated by the compiler-compiler are the derived Fortran     sources of the compiler. They come together with the compile-time     library which is also in Fortran. Here, the cross and native     versions differ because the native version has been extensively     speeded up in a way which is not available in standard Fortran-77     but in RTF/68K. The cross sources have names RTF...FOR and the     native sources RTF...FTN . The COMMON block specifications are     found in the files CPRAGMA.FOR, CPRAGMA.FTN, and NCPRAGMA.FTN .         These sources are then further processed with Fortran compilers     generating code either for the VAX (VAX/11 Fortran) or the     68K (RTF/68K cross compiler). For the VAX, the relocatable object     files are skipped and the file RTF68K.EXE is given as the end product.     This is invoked on the VAX with the command file RXFOR.COM .     Implementors for other host systems might start their (usually minor)     adaptation work with the Fortran sources.         For the 68K, more levels of derived code are provided for     ease of adaptation. The six files RTF...ASM contain the assembly     code generated from RTF...FTN by the RTF/68K cross compiler. They     can be further processed with the M68MIL assembler which then     yields the files RTF...CUF which are ready to be linked with the     run-time library. The CUFOM/PREPUSH/UNIPUSH package can be used     for this purpose.         NOTE: M68MIL, CUFOM, PREPUSH, and UNIPUSH may be obtained from     CERN free of charge for non-profit organizations.         The run-time library is made of two Fortran parts (RTFLIB.FTN     and RTFCPM.FTN) and two assembler parts (RTFAUX.ASM and FPSOFT.ASM).     All four are compiled together with the RTF/68K cross compiler,     yielding RTFLIB.ASM, which by further processing with M68MIL yields     RTFLIB.CUF as input to the CUFOM/PREPUSH/UNIPUSH chain.         The executable native compiler, finally, may be obtained in     various ways, differing in how the parts are arranged in memory.     The executable file delivered here, RTF68K.COD, has been obtained     by linking RTFMAIN.CUF, RTFSYM.CUF, RTFCOMP.CUF, and the four files     RTF68Kn.CUF. The starting address of the module is 28000(hex), just     above RTFLIB which is used and starts at 20100(hex). - RTF68K.COD     consists of S-records. It can be downloaded in the standard way     into any target system or in EPROMs if desired. Also, the way for     importing S-record objects into the CP/M-68K environment described     further below may be used, or the executable file RTF68K.68K on the     floppy may be used directly.         An alternative is to link a) RTFMAIN.CUF with XJFOR.CUF and     RTFSYM.CUF (see below for these two files), b) RTFCOMP.CUF with the     four RTF68Kn.CUF and RTFSYM.CUF, and c) RTFLIB.CUF separately and     keep the three modules at different memory regions if desired.         In addition to compiler and run-time library, the following     information is found on tape and floppy.       o SINUS.FTN is the Fortran source of a test program which does         some arithmetic as well as I/O to the CP/M-68K file system.         Its derivatives are SINUS.ASM and SINUS.CUF, which has to be         linked with RTFLIB.CUF .       o HOST.FTN and XFER.FTN are utilities for transparent mode and         file transfer with the host computer, resp.       o Various command files with extensions ...COM for VMS and         ...SUB for CP/M.       o Various documentation files with extension ...TXT, including         the one you presently read.       o A file RTFSYM.ASM which states all the entry points to RTFLIB         separately. This is useful when the run-time library is loaded         independent from the user programs (e.g. in EPROMs or in order         to save space on the floppy). Note that the library is re-entrant,         so one copy for all tasks is sufficient. Change the address         in RTFSYM.ASM if you want to keep RTFLIB at a different         address. RTFSYM.CUF is the derivative of this file and can be         used alternatively instead of RTFLIB.CUF for linking.       o A file XJFOR.ASM which states the single entry point to the         body of the compiler, JFOR, separately. This is useful under         similar circumstances as for RTFLIB, is you want to keep the         I/O independent, big part of the compiler separately from the         small main program.       o A support program for file I/O on the host computer.                                                                9 Oct 85                                                                  HvdS         FILES USED IN CONJUNCTION WITH RTF/68K (ON VAX COMPUTERS)         =========================================================     0.  Remarks     -----------     0.1. Preparation on the VAX     In order to use the DCL commands described in this text, make     sure that at login the following definitions are made:                     $ DEFINE RTF$DIR [VDSCHMITT]                     $ RTF :== "@RTF _ "                     $ RXASM :== @RXASM.COM                     $ CL*INK :== "@CLINK _ "                     $ SUP :== @SUP.COM     and if you want to use the compiler-compiler, in addition:                     $ HPRAGMA :== @HPRAGMA.COM                     $ NPRAGMA :== @NPRAGMA.COM .     0.2. Different versions of the CERN cross assembler     The old version M68MIL.EXE is not capable of handling the special     68020 addressing modes. This version uses the logical names SRCCODE     for the source file and INCLUDE for the secondary source. It is     bug-free. It is invoked by the command files described below.     The new version M68MIL.EXE includes the extras for the 68020. It     uses SRCFILE and INCFILE, resp. It is, however, not released officialy     yet.     0.3. How to obtain the CERN cross software officially     The cross assembler and cross linker package described below and     associated documentation may be obtained officially from CERN via:                            J. Blake                            CERN Div. DD                            CH-1211 Geneva 23                            Switzerland     It is free for non-profit organizations.     The cross Fortran (RTF/68K) package is available directly from the     author:                            H. von der Schmitt                            Physikalisches Institut                            Philosophenweg 12                            D-6900 Heidelberg                            W.-Germany     It is free for non-profit organizations.     1.  Compiler-compilers     ----------------------     1.0. 'Grandfather'          PRAGMA.EXE     this is an older implementation of PRAGMA                         which generates plain Fortran out of .PRA                         sources. It is used only to generate new                         compiler-compilers, but not new compilers                         any more (which are now table-driven, i.e.                         no longer plain Fortran). PRAGMA could be                         replaced soon by HPRAGMA, see below.          PRAGMA.COM     command file which invokes the former by                         the DCL command :                           $ PRAGMA PragmaSource                         where PragmaSource is a file which has the                         extension .PRA; but the extension is NOT                         given in the command.          PRAGMA.RUN     auxiliary file which just contains the name                         of the .PRA or .FTN file currently processed                         (used by compiler-compilers and compilers).     1.1. Compiler-compiler for generating host (cross)          version of RTF/68K          HPRAGMA.PRA    this is the source of the compiler-compiler                         which generates host version compilers.          HPRAGMA.FOR    generated out of the former by PRAGMA.EXE                         for further processing with VAX Fortran.          HPRAGMA.OBJ    object code from HPRAGMA.FOR by using the                         DCL command:                           $ FORT HPRAGMA          HPRAGMA.LIS    listing generated by PRAGMA.EXE. If you                         request a listing in the above FORT, another                         file with this name will be generated.          PRAGVXTAB.FOR  Fortran source of the compile-compile time                         library used by HPRAGMA (and also NPRAGMA,                         see below.          PRAGVXTAB.OBJ  object code from PRAGVXTAB.FOR.          HPRAGMA.EXE    VAX executable file of the host version                         compiler-compiler, obtained by linking with                         the DCL command:                           $ LINK HPRAGMA,PRAGVXTAB          HPRAGMA2.FOR   Fortran source of pass 2 of the host version                         of the compiler-compiler.          HPRAGMA2.OBJ   object code from HPRAGMA2.FOR.          HPRAGMA2.EXE   VAX executable file of pass 2 of the host                         version compiler-compiler, obtained by                         linking with the DCL command:                           $ LINK HPRAGMA2          HPRAGMA.COM    command file which invokes HPRAGMA and                         subsequently HPRAGMA2 to generate a new host                         version compiler by the DCL command:                           $ HPRAGMA PragmaSource     1.2. Compiler-compiler for generating native (running on 68K)          version of RTF/68K          (Note that there are only minor differences between the           files described here and the files under 1.1.)          NPRAGMA.PRA    this is the source of the compiler-compiler                         which generates native version compilers.          NPRAGMA.FOR    generated out of the former by PRAGMA.EXE                         for further processing with VAX Fortran.          NPRAGMA.OBJ    object code from NPRAGMA.FOR by using the                         DCL command:                           $ FORT NPRAGMA          NPRAGMA.LIS    listing generated by PRAGMA.EXE.          PRAGVXTAB.FOR  \ see          PRAGVXTAB.OBJ  / above          NPRAGMA.EXE    VAX executable file of the native version                         compiler-compiler, obtained by linking with                         the DCL command:                           $ LINK NPRAGMA,PRAGVXTAB          NPRAGMA2.FOR   Fortran source of pass 2 of the native version                         of the compiler-compiler.          NPRAGMA2.OBJ   object code from NPRAGMA2.FOR.          NPRAGMA2.EXE   VAX executable file of pass 2 of the native                         version compiler-compiler, obtained by                         linking with the DCL command:                           $ LINK NPRAGMA2          NPRAGMA.COM    command file which invokes NPRAGMA and                         subsequently HPRAGMA2 to generate a new native                         version compiler by the DCL command:                           $ NPRAGMA PragmaSource     2. Compilers     ------------     2.1. Host (cross) version compiler          RTF68K.PRA     is the source of the RTF/68K compiler. All                         changes to th compiler are made here.                         This source is common to the host and native                         version.          RTF68K.MIX     intermediate file (ASCII) generated from                         RTF68K.PRA by HPRAGMA.          RTF68K.FOR     Fortran generated from RTF68K.MIX by HPRAGMA2.          RTF68K.DAT     compiler tables (binary) generated from                         RTF68K.MIX by HPRAGMA2. Note that RTF68K.FOR                         and RTF68K.DAT must always be consistent, i.e.                         generated in the same compiler-compiler run.          RTF68K.LIS     listing file from RTF68K.PRA.          RTF68K.OBJ     object file generated from RTF68K.FOR by the                         DCL command:                           $ FORT RTF68K          RTF.FOR        Fortran source of the I/O interface of the                         host version compiler.          RTF.OBJ        object file of the former.          RTFCOMP.FOR    Fortran source of the compile-time library                         of the host version compiler.          RTFCOMP.OBJ    object file of the former.          TCPRAGMA.FOR   INCLUDE file used by RTF68K.FOR, RTF.FOR,                         and RTFCOMP.FOR.          RTF.EXE        VAX executable file of the host version                         compiler, obtained by linking with the DCL                         command:                           $ LINK RTF,RTFCOMP,RTF68K          RTF.COM        command file which invokes RTF and subsequently                         the CERN cross assembler by the DCL command:                           $ RTF/option/option... FortranSource                         where FortranSource is a RTF/68K source file                         with or without extension. The default extension                         is .FTN .                         If options are given, they must follow, with                         or without spaces inbetween, the word RTF. The                         SourceFile is required and must be the last                         item in the command.                         The following options are available:                           /[NO]LIST                           /LIST=ListFile                           /[NO]SHOW                           /SHOW=INCLUDE                           /[NO]OUTPUT                           /OUTPUT=OutFile                           /[NO]MACHINE_CODE                           /MACHINE_CODE[=AssListFile]                         as well as the specific options handled by the                         compiler itself rather than this command:                           /SIZE=SHORT | LONG                           /LIST=ON | OFF | INCLUDE                           /FLOAT=NS | NSAC | HARD | SOFT                           /MIX=ON | OFF                           /CODE=CPM | M68MIL | VERSA                           /DEBUG=ON | OFF                           /CHECK=ON | OFF                           /COMMON=ABSOLUTE | INDIRECT                           /LINK=ABSOLUTE | RELATIVE                           /CPU=68000 | 68008 | 68010 | 68020                           /FB=HARD | SOFT                           /LENGTH=FULL | 72                           /MULDIV=SHORT | LONG                           /SAVE=ALL | NORMAL                           /INTSIZE=2 | 4                           /REGSAVE=NORMAL | OUTSIDE                           /NUMPAR=ON | OFF                           /INIT=ON | OFF                         Please refer to the RTF68K manual for details                         on these options.                         The /options may be missing; e.g.:                           $ RTF SINUS                         which is equivalent to                           $ RTF/NOLIST/NOSHOW/NOMACHINE_CODE -                                /SIZE=SHORT/FLOAT=SOFT/MIX=OFF -                                /CODE=M68MIL/DEBUG=OFF/CHECK=ON -                                /COMMON=ABSOLUTE/LINK=ABSOLUTE -                                /CPU=68000/FB=SOFT/LENGTH=FULL -                                /MULDIV=LONG/SAVE=NORMAL/INTSIZE=4 -                                /REGSAVE=NORMAL/NUMPAR=ON -                                /INIT=ON  SINUS     2.2. Native version compiler          (Note that there are only minor differences between the           files described here and the files under 2.1.)          RTF68K.PRA     identical to the one under 2.1.          RTF68K.MIX     intermediate file (ASCII) generated from                         RTF68K.PRA by NPRAGMA. DIFFERENT from 2.1.!          RTF68K.FTN     Fortran generated from RTF68K.MIX by NPRAGMA2.          RTF68K.TAB     compiler tables (hex ASCII) generated from                         RTF68K.MIX by NPRAGMA2. Note that RTF68K.FTN                         and RTF68K.TAB must always be consistent, i.e.                         generated in the same compiler-compiler run.          RTF68K.LIS     listing file from RTF68K.PRA.          RTF.FTN        Fortran source of the I/O interface of the                         native version compiler.          RTF.CUF        object file generated from RTF.FTN by the                         DCL command:                           $ RTF RTF          RTFCOMP.FTN    Fortran source of the compile-time library                         of the native version compiler.          RTFCOMP.CUF    object file of the former (which INCLUDEs                         RTF68K.FTN).          TCPRAGMA.FTN   INCLUDE file used by RTF68K.FTN, RTFMAIN.FTN,                         and RTFCOMP.FTN.          RTF.COD        S-record absolute file obtained by the                         following DCL command:                           $ CLINK/START=StartAddress RTF,RTFCOMP .     3. Further tools used on the host     ---------------------------------     3.1. CERN cross assembler          M68MIL.EXE     VAX executable file of the 68000/68020 cross                         macro assembler written by H. v.Eicken (see                         note 0.2. above).          M68MIL.DAT     \ auxiliary files          M68MIL.TXT     / used by M68MIL.EXE          RXASM.COM      command file which invokes the cross assembler                         alone (without Fortran) by the DCL command:                           $ RXASM AsmSource                         where AsmSource is an assembler source file                         with extension .ASM; but the extension is                         NOT given in the command.     3.2. CERN cross linker          CUFLINK.EXE    VAX executable file of the cross linker.          PREPUSH.EXE    VAX executable file of the cross tool                         which makes absolute addresses.          UNIPUSH.EXE    VAX executable file of the S-record generator.          CLINK.COM      command file which invokes the three tools                         described above in this order, by the DCL                         command:                           $ CLINK [/options] CufomFile,[CufomFile...]                         where CufomFile are object files produced by                         the CERN cross assembler. They have the                         extension .CUF by default.                         The options are:                           /SYM=file   includes the Fortran library entry                                       points specified in file.CUF                           /NOSYM      omits inclusion of default entry                                       point specification UNISYM.CUF                           /START=address   or                           /START=(address,address,...)                                       states the starting addresses of                                       the various sections of the program.                                       If START is not given, the                                       addresses are entered interactively.     4. Runtime libraries     --------------------     The RTF/68K runtime library covers a variety of 68K target systems     which use the same processor type, but different serial I/O chips,     address maps, and basic software environments. The runtime library     smoothens out these differences and is thus necessarily slightly     hardware dependent.     The code sizes is about 28 Kbytes. The runtime library is reentrant     (also sharable), and position-independent. One copy is thus sufficient     for several programs. If the library is located in a global space which     is accessible to several processor modules, even of different kinds     (e.g. in a VME crate), still one copy is sufficient. For this reason,     the library is normally linked and loaded separately from the user     programs, while the user programs are linked only with the entry point     specification of the library by:                   $ CLINK UserCufomFile,...     The alternative of linking with the real code of the library exists also:                   $ CLINK/NOSYM UserCufomFile,...UNILIB     UNISYM contains, apart from the definition of library entry points, also     a system startup routine which is entered at the beginning of the user     program. This routine allows to specify the hardware/software environment     under which the program will run. UNILIB, universal in nature, can then     adapt itself to this environment at runtime.     CPU modules currently supported are:         Datasud    CPUA1         Motorola   MVME130         Xycom      IPROTO         Eltec      EUROCOM 3         Eltec      SAC         Microsys   CPU06/07         NIKHEF     FAMP         ALEPH      Event Builder     Further hardware modules supported are (all VME):         Datasud    4COM       quad serial I/O         Ikon       DR11W      DR11W emulation for link to DEC hosts .     Note that by virtue of the 68K's memory mapped I/O, which is fully     supported by the RTF/68K language, it is easy to access any hardware     devices, e.g. :         Datasud    CAMAC      CAMAC branch driver .     It is forseen that the user extends UNILIB towards new processor     modules. The files are therefore described here in terms of possible     modification by the user.     4.1. Files that need no further modification          COMLIB.FTN     big, general part of the runtime library.          FPSOFT.ASM     floating point software emulation and NS16081                         support routines (not used if MC68881 present).          MDSOFT.ASM     32-bit MUL/DIV software emulation routines                         (not used by the 68020, or if compilation                         option MULDIV=LONG is NOT selected).          RTFCPM.FTN     interfacing routines to the CP/M-68K file                         system.          DUMCPM.FTN     dummy version of the former.     4.2. Files that need modification for extensions          UNILIB.FTN     framework of the runtime library which makes                         global declarations and INCLUDEs the files                         DRIVER.FTN, COMLIB.FTN, FPSOFT.ASM, MDSOFT.ASM,                         and DUMCPM.FTN (or RTFCPM.FTN if running under                         CP/M-69K).          UNILIB.CUF     object file generated from UNILIB.FTN by the DCL                         command:                           $ RTF UNILIB          UNILIB.COD     S-record absolute file generated from UNILIB.CUF                         by the DCL command:                           $ CLINK/NOSYM/START=StartAddress UNILIB          DRIVER.FTN     Fortran source of the set of driver routines for                         character and block oriented I/O, as well as for                         return to the software environment.          UNISYM.ASM     entry point specification for UNILIB, and system                         startup routine (INCLUDEs file UNINIT.ASM). It                         must be consistent with the addess given in the                         CLINK step above!          UNISYM.CUF     object file generated from UNISYM by the DCL                         command:                           $ RXASM UNISYM     5. Example of program preparation     ---------------------------------     Assume you have a MVME130 board together with a MVME222 memory     board jumpered for continuous 2 Mbytes starting at 800000 (hex).     You want to execute the Fortran program SINUS (source SINUS.FTN).     1) Prepare the runtime library (e.g.) for starting address        800000 as follows:            $ RTF/LIST=TT: UNILIB            $ CLINK/START=800000 UNILIB     2) Make the entry point specification consistent with this        starting address and choose a proper initial stack pointer        by editing UNISYM.ASM accordingly. The symbol START        should by EQUed with 800000 and the symbol TOPn with (e.g.)        A00000, using one full megabyte of the MVME222. Then:            $ RXASM UNISYM     3) Prepare the user program SINUS for starting address 808000        (i.e. safely above the library) as follows:            $ RTF SINUS            $ CLINK/START=808000 SINUS     4) You can now download the S-record files for the library        and for SINUS separately. Have the terminal connected to        serial port 1 and the VAX connected to serial port 2 of        the serial I/O board belonging to the MVME130. Be logged        onto the VAX using TM (transparent mode). Caution: when        the MVME130 has been reset or after power-off, initialize        the MVME222 properly and set the VME bus size to 16 bits        (38 in address FFFB003B of the MVME130). After leaving        transparent mode, do:             a)   LO;X=TY UNILIB.COD    to download the                                        library,             b)   LO;X=TY SINUS.COD     to download the                                        user program.     5) You can now start execution of SINUS simply by:                  RM D0 2       (if you have assigned CPU ident 2                                to this MVME130 in UNISYM)                  GO 808000     6) If you want to modify the user program, edit the .FTN        source file, then repeat steps 3) and 4b) only; the        library needs not be touched again (unless your program        has overwritten it!).     7. Installing the software on the VME system from VAX     -----------------------------------------------------     If it is not possible to use the floppy disk directly, follow the     procedure described below to bootstrap the files from tape, via the     host computer, into your VME system.       1) Copy the tape to disk on your host computer.       2) Have the second RS232 port of the VME system connected          to your host computer.       3) Boot CP/M.       4) Go back to the monitor with the MONLOOP program which is on          your CP/M system, or by pressing the SOFTWARE ABORT button.       5) Enter transparent mode with TM.       6) Login on your host computer and give the @SUP command.       7) Exit transparent mode.       8) Download the runtime library with the command LO2;=L RTFLIB.COD .       9) Download the file transfer utility with LO2;=L XFER.COD .      10) Execute the utility by GO 28000 .      11) The utility answers with (d is drive number, e.g. B:) :             give local file name:              enter d:XFER.68K             give host  file name:              enter XFER.COD             direction local to host?           enter N             conversion to command file format? enter Y      12) Some S-records will be displayed. After that, the dialog          goes on with:             want to merge with another file?   enter N             another file?                      enter Y             give local...                      enter d:RTFLIB.68K             give host...                       enter RTFLIB.COD             direction...                       enter N             conversion...                      enter Y          (S-records)             want to merge...                   enter N             another...                         enter N       13) The utility finishes and goes back to CP/M. You have now           the files RTFLIB.68K amd XFER.68K on your floppy and don't           need manual downloading any more.       14) Instead, give the CP/M commands  d:RTFLIB  and  d:XFER to           invoke now the transfer utility in the CP/M fashion and           use it to get the the files over. Always give the local           extension .68K when the host extension is .COD . Use it           also to get text files over, then with the approprite           extensions, e.g B:SINUS.FTN locally and SINUS.FTN on the           host.           The loading of the compiler RTF68K.68K will take a long           coffee break (about one hour at 9600 Baud).       15) Enjoy your system. And don't forget to have the RTFLIB           always in memory before starting a program... either you           keep it in a place not touched by CP/M, or you always load           the library before starting your porgram, most conveniently           by using RUN progname to start your program.     2. Using RTF/68K     ================     2.1 Cross-compilation on the VAX     --------------------------------         The preferred method at CERN for generating downline-loadable code for     microprocessors is via the universal relocatable object format CUFOM.     Consequently, the assembler preferrably used as the second pass of a cross     Fortran compilation is the CERN one, M68MIL. The set of command procedures     for the VAX described below (and contained on the distribution tape) makes     use of this software. - You could as well use the Motorola or comparable     cross-assemblers on the VAX and change the command procedures accordingly.         Note that M68MIL and the CUFOM linker package are property of CERN. Any     non-profit organization can get this software free of charge from CERN. It     is normally not contained on the RTF/68K distribution tape.     2.1.1 Editing     - - - - - - -         Use e.g. the standard full-screen editor EDIT/EDT on the VAX.     2.1.0 Fortran Cross-Compilation     - - - - - - - - - - - - - - - -         The following command invokes the compilation step as well as the     assembly step:       $ RTF file     where file is the name of the source file. The extension is assumed to be     .FTN by default. Files produced are file.ASM for the intermediate assembly     code, file.LIS for the source listing, and file.CUF for the relocatable     object.     2.1.3 Cross-Assembly Only     - - - - - - - - - - - - -         The following command invokes the assembler only:       $ @RXASM file     where file is the name of the assembler source file. The extension is     assumed to be .ASM and must not be given. Files produced are file.LAS for     the assembly code listing and file.CUF for the relocatable object.     2.1.4 Cross-Linkage     - - - - - - - - - -         The following command invokes the three linker-steps (Linker,     Prepusher, and S-format pusher):       $ CLINK file[,file...]     where file (and optionally file1) are relocatable object files. The     extensions are assumed to be .CUF by default. The file produced is     essentially file.COD for the absolute S-record image. Various listings     could be produced during linking but are suppressed in this command     procedure.         CLINK will ask you interactively for the starting addresses of all     sections of your program, e.g. code section, all COMMON sections etc.     2.1.5 Cross File Access     - - - - - - - - - - - -         The RTF/68K runtime library provides a protocol for file access to     the VAX file system from the microprocessor with OPEN/CLOSE/READ/WRITE     (see SINUS example). The physical link used is a terminal line. The VAX     responds in the same way as to terminal I/O.         In order to handle the protocol on the VAX side, a program SUPPORT     is provided. When you intend to start a microprocessor program which     requires the VAX file system, simply do:       $ @SUP     on the VAX before (e.g. in transparent mode through the microprocessor).     All you have to provide hardware-wise for this purpose is to put the     microprocessor with its terminal- and host ports into the existing line     between terminal and VAX.     2.2 Native software development on CP-M/68K systems     ---------------------------------------------------     2.2.1 Editing     - - - - - - -         Use e.g. the full-screen editor described below under utilities.     2.2.2 Fortran Compilation     - - - - - - - - - - - - -         The following command invokes the compilation step as well as the     assembly step:       d> FOR file     The compile step produces a file named file.S which contains the generated     assembly code. If OPTIONS LIST=ON or INCLUDE is given in the source file,     also file.LIS is produced. The assembler AS68 of the CP-M/68K system is     invoked automatically if the compilation was error-free. AS68 produces     the relocatable object file.O out of file.S .     2.2.3 Assembly Only     - - - - - - - - - -         The following commands invoke the assembler AS68 only:       d> ASS file       d> ASL file         The file names you specify MUST have extension .S . AS68 produces     the relocatable object file.O out of file.S . In the first form of the     command, no listing is produced; in the second form, a listing is     written to the terminal.     2.2.4 Linking     - - - - - - -         The following command invokes the linker LO68:       d> LINK file1 [file2 ...]         It links one or several relocatable object files together with the     RTF/68K runtime library entry points. The absolute image file1.68K is     produced.         Note that the runtime library itself is NOT contained in the image     file; only its entry points are made known. Thus the images generated     in this way rely on the runtime library being present when execution     starts. - The reason for this strategy is a) to save disk space, b) the     runtime library is sharable, i.e. only one copy is required in the system,     and this copy could even reside in a reserved memory region hidden     to CP-M (e.g. in a EPROM module).     2.2.5 Program Execution     - - - - - - - - - - - -         According to what was said about the linking with the runtime     library, the following command loads the library before it loads the user     program and starts execution:       d> RUN file     This command looks thus like a VAX command, and unlike a CP-M command.     The absolute image file.68K is loaded and executed.         ONLY if in your implementation the runtime library would reside in     reserved memory regions, you could avoid the loading of the library and     immediadely load and execute the user program by typing:       d> file .     2.2.6 Cross File Access     - - - - - - - - - - - -         What was said under 2.1.5 holds of course also for programs which     have been developed on the CP-M system, i.e. they can access the Host's     file system by means of a small protocol program SUPPORT on the Host.         By the way, SUPPORT is written in Fortran and can be used in     conjunction with Hosts other than VAXes if desired.                                                                      08 Dec. 86                                                                         HvdS                      Installation of RTF/68K on OS9 systems                      ======================================     This note describes briefly how to install Real-Time Fortran-77 for     68k processors, RTF/68K, on OS9-68000 systems.     There are two possible starting points:          (1) the easy one, a distribution diskette containing all the              necessary files,          (2) the other, still simple one, using OS9 assembler source              files on a host, which have to be downloaded into the OS9              system by some means (e.g. the COM package).     The equivalent of the distribution diskette is produced by procedure     (2).     Procedure (1)     -------------     I. Contents os the distribution diskette:          0.    Documentation:            1.  install.txt       (the present document)          1.    Compiler code:            1.  rtfos9.r          Relocatable code of the compiler            2.  rtf               Executable module, generated from 1. and                                  others by l68 (see below)          2.    Compiler tables:            1.  rtf68k.dat        Binary form of parser tables          3.    Runtime library:            1.  os9lib.f          Source code of runtime library            2.  os9lib.r          Relocatable code, generated from 1. by                                  RTF and r68 (see below)          4.    Other stuff:            1.  testos9.f         Fortran source of small test/verification                                  program            2.  rtfbinos.r        Relocatable code of conversion program for                                  parser tables (ascii to binary)            3.  rtfbinos          Executable module of 2.            4.  fstart.a          Assembler source of initialization routine                                  for RTF programs            5.  fstart.r          Relocatable code, generated from 4. by r68     Finally required for running the compiler are only rtf (1.2.) and     rtf68k.dat (2.1.). Required for running a RTF program are, in addition     to the user program, only os9lib.r (3.2.) and fstart.r (4.5.), together     with the os9 system library, sys.l.     II. Installation of the RTF system from diskette:     Assume the distribution diskette is on drive /dx. Then install the RTF     system by:           1. loading the compiler with                load /dx/rtf           2. copying the parser tables to the working device with                copy /dx/rtf68k.dat rtf68k.dat           3. copying the initialization routine with                copy /dx/fstart.r fstart.r           4. copying the runtime library with                copy /dx/os9lib.r os9lib.r     III. Running the RTF compiler:     Assume your RTF source file is /dy/zzzz.f . Note that the extension of     the source should be .f by convention.           1. execute the compiler, generating assembly code, with                rtf /dy/zzzz              or                rtf /dy/zzzz option,option,...              where the options are as described in the RTF manual, e.g.              cpu=68020,check=off.     This step leaves the generated assembly code in /dy/zzzz.a . It also     generates a source listing on the terminal.           2. process it further with the assembler                r68 /dy/zzzz.a -qo=/dy/zzzz.r     Note that the -q option should be used here in order to suppress     warnings for unnecessary long forward branches.     IV. Preparing the executable module:     Link the system library, the initialization routine, the user code,     and the runtime library together. Assume that the relocatable code     has come out of step III., on file /dy/zzzz.r .           1. invoke the linker with the following command:                l68 -l=sys.l fstart.r /dy/zzzz.r os9lib.r -o=zzzz              or, if the total code will exceed 32k, with                l68 -l=sys.l fstart.r /dy/zzzz.r os9lib.r -a -o=zzzz     If more, separately compiled user code is to be linked, insert     the pathnames of the appropriate relocatable files after the     /dy/zzzz.r .     Now you can execute your program simply by the command zzzz .     Example: use the source testos9.f to verify proper operation. For              convenience, copy the source to the working device first              (preferrably a RAM disk).                copy /dx/testos9.f testos9.f                rtf testos9                r68 testos9.a -qo=testos9.r                l68 -l=sys.l fstart.r testos9.r os9lib.r -o=testos9                testos9     Compare the results with what you expect from the source.     -------------------------------------------------     Special NOTE on the RTF implementation under OS9:     -------------------------------------------------     The OS9 Assembler and Linker do not know a construct that would support     Fortran COMMON blocks directly. Thus, RTF introduces them using when the     program starts running issuing system memory requests. The code doing     this is executed automatically during the initialization phase of the     program. In cases where libraries etc. use COMMON blocks which are not     also used in the mainline module (i.e. the one containing the main prog-     ram), the mainline module must have knowledge of these libraries.     A similar scheme has to be obeyed for DATA statements. The initialization     values have to be placed into the variables when the program starts up.     The loader does not do it for all cases (esp., not for COMMON variables).     Thus, again, the mainline module has to know about the other modules with     respect to DATA.     The USE statement described in the manual is intended for these two     purposes. Please refer to the RTF manual.     Procedure (2):     --------------     V. Contents of the host files (VAX as an example):          0.    Documentation:            1.  install.txt       (the present document)            2.  rtfman.txt        RTF manual          1.    Compiler code:            1.  rtfos9.f          Fortran source of compiler            2.  rtf68k.f          Include file to 1.            3.  rtfos9.a          Assembler code, generated from 1.,2. by rtf                                  (cross version on the host)          2.    Compiler tables:            1.  rtf68k.tab        Ascii form of parser tables          3.    Runtime library:            1.  os9lib.f          Fortran source of runtime library            2.  os9lib.a          Assembler code, generated from 1. by rtf                                  (cross version on the host)          4.    Other stuff:            1.  testos9.f         Fortran source of small test/verification                                  program            2.  rtfbinos.f        Fortran source of conversion program for                                  parser tables (ascii to binary)            3.  rtfbinos.a        Assembler code, generated from 4.2. by rtf                                  (cross version on the host)            4.  fstart.a          Assembler source of initialization routine                                  for RTF programs     VI. Transfer from host to the os9 system:     Use your preferred utility to transfer all the files listed under V.     to a fresh floppy in drive /dx. Most of the Fortran sources are     optional, i.e., you can leave out 1.1., 1.2., 3.1., and 4.2. Also, it     is not necessary to transfer rtfman.txt.     Caution: the file rtf68k.tab contains long lines (80 char.). Make sure     that your transfer utility does not split lines, nor add empty lines     at the beginning of the file! Otherwise correct with your preferred     editor.     VII. Generate other files with os9 utilities:     In order to make the missing relocatable files and executables, use the     os9 assembler and linker. Note that <oskdesf> and sys.l are used in the     following steps.          1. generate relocatable of initialization routine:               r68 /dx/fstart.a -o=/dx/fstart.r          2. generate relocatable of compiler:               r68 /dx/rtfos9.a -qo=/dx/rtfos9.r          3. generate relocatable of runtime library:               r68 /dx/os9lib.a -qo=/dx/os9lib.r          4. generate relocatable of table conversion program:               r68 /dx/rtfbinos.a -qo=rtfbinos.r          5. generate executable of compiler:               l68 -l=sys.l /dx/fstart.r /dx/rtfos9.r /dx/os9lib.r                                                     -a -o=rtf -n=rtf          6. generate executable of table conversion program:               l68 -l=sys.l /dx/fstart.r /dx/rtfbinos.r /dx/os9lib.r                                                     -o=rtfbinos          7. run rtfbinos to convert /dx/rtf68k.tab to /dx/rtf68k.dat:               rtfbinos /dx             Watch the checksums printed when rtfbinos finishes: the two             numbers displayed must be identical!     Now you have generated a complete diskette for RTF. You can continue     with step II. of procedure (1).     5.4 Flow of Information     -----------------------         The following diagram shows the files and operations involved in     program preparation.                              +-----------------+                              | RTF/68K source  |                              +-----------------+                                       |                                /-------------\     + - - - - - - +                               ( RTF compiler  )--> | RTF listing |                                \-------------/     + - - - - - - +                                       |                              +-----------------+                              | Assembler code  |                              +-----------------+                                       |                                /-------------\     + - - - - - - +                               (   Assembler   )--> |Ass. listing |                                \-------------/     + - - - - - - +                                       |        +----------------+    +-----------------+        |reloc. libraries|    |   reloc. code   |        +----------------+    +-----------------+                |                      |                 \              /-------------\     + - - - - - - +                   ----------> ( linker/loader )--> |Link listings|                                \-------------/     + - - - - - - +                                       |                              +-----------------+                              | executable code |                              +-----------------+                                       |                                /-------------\                               ( load, execute )                                \-------------/         The following file naming conventions have been chosen for the     cross software implementation on the VAX. "Assembler" then stands for     the M68MIL cross assembler, and "Link/Load" stands for the CUFOM cross     linker package, consisting of CUFLINK, PREPUSH, and UNIPUSH.     Assume that the RTF/68K source file is named file.FTN. The extension     FTN is required. Then the Fortran list file is called file.LIS, the     mnemonic assembler code file is called file.ASM, the assembler list     file is called file.LAS, the relocatable code is called file.CUF, and     the executable code (S-format) file is called file.COD.         The following conventions hold for the native implementation on     CP/M-68K systems. "Assembler" then stands for the AS68 assembler and     "Link/Load" stands for the LO68 linker/loader.     Assume that the RTF/68K source file is named file.FTN. The extension     FTN is required. Then the Fortran list file is called file.LIS, the     mnemonic assembler code file is called file.S, the relocatable code     is called file.O, and the executable code file is called file.68K.         The following conventions hold for the native implementation on     OS9-68K systems. "Assembler" then stands for the r68 assembler and     "Link/Load" stands for the l68 linker/loader.     Assume that the RTF/68K source file is named file.f . The extension     f is required. Then the Fortran list file is called file.lis, the     mnemonic assembler code file is called file.a, the relocatable code     is called file.r, and the executable code file is called file .     2.3 Utility Progams for Host System / CP-M System Connection     ------------------------------------------------------------         The assumption about hardware made here are minimal: the CP-M     system is inserted into the serial line between Host and terminal,     using the two serial ports of the microcomputer module.     2.3.1  Transparent Mode     - - - - - - - - - - - -         You get transparent mode from the terminal through the CP-M     system with the command:       d> VAX     You return to CP-M by typing CTRL-A on the terminal. Note that this     way of transparent mode does no harm to the CP-M operating system,     unlike the respective commands which are provided by the monitor     software in the EPROMs of your microcomputer module.     2.3.2 File Transfer Utility     - - - - - - - - - - - - - -         It is assumed that the SUPPORT program is already running on the     Host. Then, on the CP-M system, the command:       d> XF     invokes the file transfer program. The dialog which follows asks you     for the type of Host computer, source and destination file names, and     the direction of transfer (Y for CP-M to Host, N for Host to CP-M).         Normally, ASCII files are transferred. Data are not changed during     transfer in this case.         If the direction is Host to CP-M, if the Host file extension is     .COD (i.e. S-records from a cross compilation), and the CP-M file     extension given is .68K (absolute image file), XF automatically reformats     the S-record data into the CP-M executable image form. They can then     later be executed as if they had been prepared under CP-M.     2.3.3 VAX-like full-screen editor on CP/M     - - - - - - - - - - - - - - - - - - - - -         A full-screen editor with similar functionality and keypad functions     as the EDIT/EDT on VAX is available for CP-M/68K. It requires a     VT100 compatible terminal. The line-mode commands of EDIT/EDT are not     implemented.         To invoke the editor, do:       d> EDT         The editor then asks for the file name. Press <return> if you are     sure that the text you want to edit is still in the buffer (other TPA     programs could already have destroyed it). - Please refer to the VAX     editor manual for details. Here, only the display of the HELP command     key (PF2) is reproduced:               Cursor movement                     Keypad functions      +-------+-------+-------+-------+    +-------+-------+-------+-------+      |       |   |   |       |       |    |       |       |FNDNEXT|DELLINE|      |   ^   |   v   |  <--  |  -->  |    | GOLD  | HELP  | - - - | - - - |      |   |   |       |       |       |    |       |       | FIND  |UNDLINE|      +-------+-------+-------+-------+    +-------+-------+-------+-------+         up     down    left    right      | PAGE  | SECT  |       |DELWORD|                                           | - - - | - - - | - - - | - - - |                                           |COMMAND|       |       |UNDWORD|      Keypad: The second (lower on key)    +-------+-------+-------+-------+      function is selected by pressing     |ADVANCE|BACKUP |  CUT  |DELCHAR|      GOLD before pressing the key.        | - - - | - - - | - - - | - - - |                                           |BOTTOM |  TOP  | PASTE |UNDCHAR|      Further special keys used:           +-------+-------+-------+-------+      DEL        delete character left     | WORD  |  EOL  | CHAR  |       |                 from cursor               | - - - | - - - | - - - | ENTER |      BACKSPACE  backup to begin of line   |CHCASE |DELEOL |       |       |      CTRL/W     refresh screen            +---------------+-------| - - - |                                           |     LINE      |SELECT |       |                                           | - - - - - - - | - - - |SUBSTIT|      To get help for the command mode,    |   OPEN LINE   | RESET |       |      select this mode and type HELP.      +---------------+-------+-------+         The following is the information you get when you press GOLD/COMMAND     and the type HELP:        HELP          display help information        EXIT or EX    save file and exit from editor        SAVE          save file and stay in editor        SET WRAP=n    set right margin for wraparound/fill        INCLUDE file  insert contents of file at cursor        WRITE   file  write selected range to file        To get help on the keypad functions, go back        to keypad mode and hit the HELP (=PF2) key.     SYNTAX DEFINITION OF RTF/68K (NOT YET COMPLETED)     ---------------------------- -------------------         The RTF/68K syntax definition is given here in a comprehensive     form. It is a copy of the appendix of the ANSI standard which specifies     the Fortran 77 language. Omissions from this standard are indicated     by fat blobs blocking the respective 'railroads', while extensions are     indicated by fat extra railroads and text.     Current developments related with RTF/68K:     ------------------------------------------     a) Implementation of REAL*8 and COMPLEX*8 data types.     b) Implementation of bit-field instructions.     Associated documentation     ------------------------     a) PRAGMA - a Portable Compiler Writing System        H.von der Schmitt, Internal Report PIB     b) An Optimizing Compiler Kit for the MC68000        H.von der Schmitt, Internal Report PIB     c) Performance of a VAX-supported MC68K        V.Mertens, H.von der Schmitt, Note PIB     d) 68CAMICRO - Ein leistungsfaehiger Experimentrechner        auf Mikroprozessorbasis        V.Mertens, BONN-IR-83-10, Bonn, May 1983 (in German)     e) M68MIL, a cross assembler for the Motorola 68000        H.v.Eicken, CERN/DD/80/26, Sept. 1980     f) The CUFOM processors user manual