call name(FCINT,'FC internals')
!head('Introduction')
this document describes the UBC Fortran 77 compiler (FC) internals.
in particular it first describes the format of the threaded code then some
details on how the compiler generates it.
!head('Threaded code')
the compiler generates what is known as "threaded code", where the code
consists of addresses of subroutines to execute and operand addresses.
a machine register (R4) is used point to the next threaded code instruction
to execute. the advantages of threaded code are:
!pt it allows one word subroutine calls, thus producing compact code.
!pt the compiler generates the same code regardless of the model of CPU on
which it is to execute. only the threaded code library need be changed for
different models.
!pt threaded code easily implements polish notation, where operands are first
pushed onto a stack (in this case the hardware (R6) stack), and then operated
on there. 
!pt the transfer to the next threaded code routine is very fast, in fact only
a single instruction (jmp *(r4)+) is required.
!pt most of the other (DEC) Fortran compilers for the PDP 11 generate threaded code.
!p a sample might be in order: 
)l2a
(1) i = j + 1

(2) movi_ms,j
(3) movi_ms,const1
(4) addi_ss
(5) movi_sm,i
) !p 
!count(pt,1,1,integer)
!pt is the Fortran source that is compiled into the threaded code in
lines (2) to (5). "i" and "j" are integer*2 variables.
!pt pushes the value of "j" onto the stack.
!pt pushes the value of 1 (a constant) onto the stack.
!pt adds the two values on the top of the stack and pushes the result
onto the stack replacing the original values.
!pt pops the stack into the variable "i".
!head('threaded code convensions')
in general the following format is used for naming threaded code routines:
)l2a
operation [type1] [type2] [_] [loc1] [loc2]
) !p where: 
!i(operation) is the type of operation that is to be performed, some 
common ones are: mov, add, sub, mul, div, not, and, or, neg.
!i(type1) is optional, and if present gives the type (or mode) of the
operand(s). if two types are specified then "type1" is the type of the 
first.
the possible types are: "i" (integer*2), "q" (integer*4), "f" (real*4), "d" (real*8),
"l" (logical*2), "b" (logical*1), "c" (complex*8), "h" (complex*16), and
"s" (character).
!i(type2) is optional, and is only present when there are two different 
types or modes required. this happens only for the "exp" and "cvt" 
operators.
!i(_) is a delimeter used to (1) identify threaded code routines (all 
threaded code routines have a "_" in their name, but not as the first
character; and (2) to serve as a delimeter.
!i(loc1) is optional, and is the location of the first operand, possible
locations are: "s" (on stack), "m" (in memory, address follows in next word),
"p" (parameter, address of address follows), "i" (immediate, operand follows
in one or more words), "a" (address on stack),
"r" (operand is in appropriate general register).
!i(loc2) is optional, and is present only when more than one operand is 
required.
