Browse Source

fixup commit for tag 'dist2'

cvs2hg 39 years ago
parent
commit
3f3bddef8f
100 changed files with 0 additions and 31187 deletions
  1. 0 131
      Action
  2. 0 17
      Copyright
  3. 0 1
      DistrAction
  4. 0 35
      Makefile
  5. 0 2
      README
  6. 0 102
      TakeAction
  7. 0 26
      distr/todistr
  8. 0 2163
      doc/6500.doc
  9. 0 53
      doc/Makefile
  10. 0 420
      doc/ack.doc
  11. 0 854
      doc/basic.doc
  12. 0 1857
      doc/cg.doc
  13. 0 324
      doc/cref.doc
  14. 0 31
      doc/em/Makefile
  15. 0 1
      doc/em/READ_ME
  16. 0 1121
      doc/em/addend.n
  17. 0 488
      doc/em/app.nr
  18. 0 773
      doc/em/assem.nr
  19. 0 163
      doc/em/descr.nr
  20. 0 377
      doc/em/dspace.nr
  21. 0 1665
      doc/em/em.i
  22. 0 9
      doc/em/even.c
  23. 0 178
      doc/em/exam.e
  24. 0 40
      doc/em/exam.p
  25. 0 32
      doc/em/int/Makefile
  26. 0 5
      doc/em/int/READ_ME
  27. 0 1766
      doc/em/int/em.p
  28. 0 210
      doc/em/int/emdmp.c
  29. 0 244
      doc/em/int/mktables.c
  30. 0 180
      doc/em/intro.nr
  31. 0 376
      doc/em/iotrap.nr
  32. 0 6
      doc/em/ip.awk
  33. 0 62
      doc/em/ispace.nr
  34. 0 2525
      doc/em/itables
  35. 0 390
      doc/em/mach.nr
  36. 0 16
      doc/em/macr.nr
  37. 0 245
      doc/em/mapping.nr
  38. 0 80
      doc/em/mem.nr
  39. 0 5
      doc/em/print
  40. 0 4
      doc/em/show
  41. 0 38
      doc/em/title.nr
  42. 0 130
      doc/em/types.nr
  43. 0 621
      doc/install.doc
  44. 0 2944
      doc/ncg.doc
  45. 0 1555
      doc/pcref.doc
  46. 0 506
      doc/peep.doc
  47. 0 133
      doc/regadd.doc
  48. 0 897
      doc/toolkit.doc
  49. 0 303
      doc/v7bugs.doc
  50. 0 753
      doc/val.doc
  51. 0 19
      emtest/Makefile
  52. 0 136
      emtest/READ_ME
  53. 0 1
      emtest/last
  54. 0 10
      emtest/ok
  55. 0 249
      emtest/select.c
  56. 0 28
      emtest/test.e
  57. 0 0
      emtest/test.h
  58. 0 3605
      emtest/tests
  59. 0 26
      etc/Makefile
  60. 0 175
      etc/em_table
  61. 0 352
      etc/ip_spec.t
  62. 0 71
      etc/new_table
  63. 0 289
      etc/pc_errors
  64. 0 107
      etc/pc_rt_errors
  65. 0 15
      etc/pop_push
  66. 0 28
      etc/traps
  67. 0 32
      first/ckpath
  68. 0 7
      first/did_first
  69. 0 7
      first/em_path.h.src
  70. 0 133
      first/first
  71. 0 7
      first/local.h.src
  72. 0 10
      h/Makefile
  73. 0 12
      h/arch.h
  74. 0 1
      h/as_spec.h
  75. 0 29
      h/bc_io.h
  76. 0 17
      h/bc_string.h
  77. 0 156
      h/cg_pattern.h
  78. 0 154
      h/cgg_cg.h
  79. 0 30
      h/em_abs.h
  80. 0 12
      h/em_ego.h
  81. 0 25
      h/em_flag.h
  82. 0 21
      h/em_mes.h
  83. 0 8
      h/em_ptyp.h
  84. 0 10
      h/em_reg.h
  85. 0 120
      h/out.h
  86. 0 22
      h/pc_err.h
  87. 0 19
      h/pc_file.h
  88. 0 21
      h/pc_size.h
  89. 0 25
      h/ranlib.h
  90. 0 1
      include/_tail_cc/setjmp.h
  91. 0 42
      include/_tail_mon/errno.h
  92. 0 21
      include/_tail_mon/signal.h
  93. 0 34
      lang/basic/lib/LIST
  94. 0 10
      lang/basic/lib/abs.c
  95. 0 11
      lang/basic/lib/asc.c
  96. 0 9
      lang/basic/lib/asrt.c
  97. 0 93
      lang/basic/lib/atn.c
  98. 0 17
      lang/basic/lib/chr.c
  99. 0 40
      lang/basic/lib/conversion.c
  100. 0 63
      lang/basic/lib/error.c

+ 0 - 131
Action

@@ -1,131 +0,0 @@
-name	"System definition"
-dir first
-action did_first
-failure "You have to run the shell script first in the directory first"
-fatal
-end
-name	"EM definition"
-dir etc
-end
-name "C preprocessor"
-dir util/cpp
-end
-name "EM definition library"
-dir util/data
-end
-name "Encode/Decode"
-dir util/misc
-end
-name "Shell files in bin"
-dir util/shf
-end
-name "EM assembler"
-dir util/ass
-end
-name "EM Peephole optimizer"
-dir util/opt
-end
-name "ACK archiver"
-dir util/arch
-end
-name "Program 'ack'"
-dir util/ack
-end
-name "Bootstrap for backend tables"
-dir util/cgg
-end
-name "LL(1) Parser generator"
-dir util/LLgen
-end
-name "Bootstrap for newest form of backend tables"
-dir util/ncgg
-end
-name "C frontend"
-dir lang/cem/comp
-end
-name "Basic frontend"
-dir lang/basic/src
-end
-name "Intel 8086 support"
-dir mach/i86
-indir
-end
-name "MSC6500 support"
-dir mach/6500
-indir
-end
-name "Motorola 6800 support"
-dir mach/6800
-indir
-end
-name "Motorola 6805 support"
-dir mach/6805
-indir
-end
-name "Motorola 6809 support"
-dir mach/6809
-indir
-end
-name "Intel 8080 support"
-dir mach/8080
-indir
-end
-name "2-2 Interpreter support"
-dir mach/int22
-indir
-end
-name "2-4 Interpreter support"
-dir mach/int24
-indir
-end
-name "4-4 Interpreter support"
-dir mach/int44
-indir
-end
-name "IBM PC/IX support"
-dir mach/ix
-indir
-end
-name "Motorola 68000 2-4 support"
-dir mach/m68k2
-indir
-end
-name "NS16032 support"
-dir mach/ns
-indir
-end
-name "PDP 11 support"
-dir mach/pdp
-indir
-end
-name "PMDS support"
-dir mach/pmds
-indir
-end
-name "Signetics 2650 support"
-dir mach/s2650
-indir
-end
-name "Vax 2-4 support"
-dir mach/vax2
-indir
-end
-name "Vax 4-4 support"
-dir mach/vax4
-indir
-end
-name "Z80 support"
-dir mach/z80
-indir
-end
-name "Zilog Z8000 support"
-dir mach/z8000
-indir
-end
-name "Nascom support"
-dir mach/z80a
-indir
-end
-name "Pascal frontend"
-dir lang/pc/pem
-end

+ 0 - 17
Copyright

@@ -1,17 +0,0 @@
-/*
- * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
- *
- *          This product is part of the Amsterdam Compiler Kit.
- *
- * Permission to use, sell, duplicate or disclose this software must be
- * obtained in writing. Requests for such permissions may be sent to
- *
- *      Dr. Andrew S. Tanenbaum
- *      Wiskundig Seminarium
- *      Vrije Universiteit
- *      Postbox 7161
- *      1007 MC Amsterdam
- *      The Netherlands
- *
- */
-

+ 0 - 1
DistrAction

@@ -1 +0,0 @@
-exec sh TakeAction distr distr/Action

+ 0 - 35
Makefile

@@ -1,35 +0,0 @@
-cmp:           # compile everything and compare
-	(cd etc  ; make cmp )
-	(cd util ; make cmp )
-	(cd lang ; make cmp )
-	(cd mach ; make cmp )
-
-install:         # compile everything to machine code
-	(cd etc  ; make install )
-	(cd util ; make install )
-	(cd lang/cem ; make install )
-	(cd mach ; make install )
-	(cd lang/pc ; make install )
-
-clean:        # remove all non-sources, except boot-files
-	(cd doc ; make clean )
-	(cd man ; make clean )
-	(cd h   ; make clean )
-	(cd etc  ; make clean )
-	(cd util ; make clean )
-	(cd lang ; make clean )
-	(cd mach ; make clean )
-
-opr:            # print all sources
-	make pr | opr
-
-pr:             # print all sources
-	@( pr Makefile ; \
-	  (cd doc ; make pr ) ; \
-	  (cd man ; make pr ) ; \
-	  (cd h ; make pr ) ; \
-	  (cd etc  ; make pr ) ; \
-	  (cd lang ; make pr ) ; \
-	  (cd util ; make pr ) ; \
-	  (cd mach ; make pr ) \
-	)

+ 0 - 2
README

@@ -1,2 +0,0 @@
-Before starting installation you should read
-the file doc/install.pr

+ 0 - 102
TakeAction

@@ -1,102 +0,0 @@
-case $# in
-0)	PAR=install ; CMD=Action ;;
-1)	PAR="$1" ; CMD=Action ;;
-2)	PAR="$1" ; CMD="$2" ;;
-*)	echo Syntax: "$0" [param [file]] ; exit 1 ;;
-esac
-if test -r "$CMD"
-then :
-else
-	case "$CMD" in
-	Action)		echo No Action file present ;;
-	*)		echo No Action file "($CMD)" present ;;
-	esac
-fi
-THISFILE=`pwd`/$0
-SYS=
-RETC=0
-{ while read LINE
-do
-	eval set $LINE
-	case x"$1" in
-	x#*)	;;
-	xname)		SYS="$2"
-			ACTION='make $PAR'
-			DIR=.
-			FAIL='Failed for $SYS, see $DIR/Out'
-			SUCC='$SYS -- done'
-			ATYPE=
-			FATAL=no
-			DOIT=yes
-			;;
-	xfatal)		FATAL=yes ;;
-	xaction|xindir)	case x$ATYPE in
-			x)	ACTION=$2 ; ATYPE=$1 ;;
-			*)	echo Already specified an $ATYPE for this name
-				RETC=-1 ;;
-			esac ;;
-	xfailure)	FAIL="$2" ;;
-	xsuccess)	SUCC="$2" ;;
-	xdir)		DIR="$2" ;;
-	xsystem)	case `ack_sys` in
-			$2)	;;
-			*)	echo "Sorry, $SYS can only be made on $2 systems"
-				DOIT=no
-				;;
-			esac ;;
-	xend)		case $DOIT in
-			no)	continue ;;
-			esac
-			case x$SYS in
-			x)	echo Missing name line; RETC=-1 ;;
-			*)	if test -d $DIR
-				then (
-				     cd $DIR
-				     X=
-				     case $ATYPE in
-				     indir)	
-					     if sh $THISFILE $PAR $ACTION
-					     then eval echo $SUCC
-					     else RETC=2 ; eval echo $FAIL
-					     fi ;;
-				     *)
-					     if eval "$ACTION >Out 2>&1 </dev/null"
-					     then eval echo $SUCC
-					     else RETC=1 ; X=: ; eval echo $FAIL
-					     fi
-					     ;;
-				     esac
-				     (echo ------- `pwd`
-				      cat Out
-				      $X rm -f Out
-				     ) 2>/dev/null 1>&- 1>&3
-				     exit $RETC
-				)
-				case $? in
-				0) ;;
-				*) case $RETC in
-				   0) RETC=$? ;;
-				   esac ;;
-				esac
-				else
-				      echo Directory $DIR for $SYS is inaccessible
-				      RETC=-2
-				fi ;;
-			esac
-			case $FATAL$RETC in
-			yes0)	;;
-			yes*)	echo Fatal error, installation stopped.
-				exit $RETC ;;
-			esac
-			SYS=
-			;;
-	*)		echo Unknown keyword "$1"
-			RETC=-3 ;;
-	esac
-done
-} <$CMD
-RETX=$?
-case $RETX in
-0)	exit $RETC ;;
-*)	exit $RETX ;;
-esac

+ 0 - 26
distr/todistr

@@ -1,26 +0,0 @@
-REV=
-FILE=
-while :
-do
-	case $# in
-	0)	break ;;
-	esac
-	ARG="$1"
-	shift
-	case "$ARG" in
-	-r*)	REV=`echo "$ARG"| sed s/-r//` ;;
-	-*)	FLAGS="$FLAGS $ARG" ;;
-	*)	case x$FILE in
-		x)	FILE="$ARG" ;;
-		*)	echo todistr can only be done on one file at the time
-			exit 1 ;;
-		esac
-	esac
-done
-case x$REV in
-x)	REV=`rlog -h "$FILE"|sed -n -e '/head/s/^head:[ 	]*//p'` ;;
-esac
-case x$REV in
-x)	exit 2 ;;
-esac
-rcs -ndistr2:$REV $FLAGS $FILE

+ 0 - 2163
doc/6500.doc

@@ -1,2163 +0,0 @@
-. \" $Header$"
-.po +10
-.ND
-.TL
-.B
-A backend table for the 6500 microprocessor
-.R
-.AU
-Jan van Dalen
-.AB
-The backend table is part of the Amsterdam Compiler Kit (ACK).
-It translates the intermediate language family EM to a machine
-code for the MCS6500 microprocessor family.
-.AE
-.PP
-.bp
-.NH
-Introduction.
-.PP
-As more and more organizations aquire many micro and minicomputers,
-the need for portable compilers is becoming more and more acute.
-The present situation, in which each harware vendor provides its
-own compilers -- each with its own deficiencies and extensions, and
-none of them compatible -- leaves much to be desired.
-The ideal situation would be an integrated system containing
-a family of (cross) compilers, each compiler accepting a standard
-source language and, producing code for a wide variety of target
-machines. Furthermore, the compilers should be compatible, so programs 
-written in one language can call procedures written in another
-language. Finally, the system should be designed so as to make
-adding new languages and, new machines easy. Such an integerated
-system is being built at the Vrije Universiteit.
-.PP
-The compiler building system, which is called the "Amsterdam Compiler
-Kit" (ACK), can be thought of as a "tool kit." It consists of
-a number of parts that can be combined to form compilers (and
-interpreters) with various properties. The tool kit is based
-on an idea (UNCOL) that was first suggested in 1960 [5],
-but which never really caught on then. The problem which UNCOL
-attemps to solve is how to make a compiler for each of
-.B
-N
-.R
-languages on
-.B
-M
-.R
-different machines without having to write
-.B
-N
-.R
-x
-.B
-M
-.R
-programs.
-.PP
-As shown in Fig. 1, the UNCOL approach is to write
-.B
-N
-.R
-"front ends," each of which translates
-one source language to a common
-intermediate language, UNCOL (UNiversal Computer Oriented
-Language), and
-.B
-M
-.R
-"back ends," each of which translates programs
-in UNCOL to a specific machine language. Under these conditions,
-only
-.B
-N
-.R
-+
-.B
-M
-.R
-programs must be written to provide all
-.B
-N
-.R
-languages on all
-.B
-M
-.R
-machines, instead of
-.B
-N
-.R
-x
-.B
-M
-.R
-programs.
-.PP
-Various reseachers have attempted to design a suitable UNCOL [1,6],
-but none of these have become popular. It is the believe of the
-designers of the Amsterdam Compiler Kit that previous attemps 
-have failed because they have been too ambitious, that is, they have
-tried to cover all languages and all machines using a single UNCOL.
-The approach of the designers is more modest:
-they cater only to algebraic languages and machines whose memory
-consist of 8-bit bytes, each with its own address.
-Typical languages that could be handled include Ada, ALGOL 60,
-ALGOL 68, BASIC, C, FORTRAN, Modula, Pascal, PL/I, PL/M, PLAIN and
-RATFOR, where COBOL, LISP and SNOBOL would be less efficient.
-Examples of machines that could be included are the Intel 8080 and
-8086, Motorola 6800, 6809 and 68000, Zilog Z80 and Z8000, DEC PDP-11
-and Vax, MOS Technology MCS6500 family and IBM but not the Burroughs
-6700, CDC Cyber or Univac 1108 (because they are not byte_oriented).
-With these restrictions the designers believe that the old UNCOL
-idea can be used as the basis of a practical compiler-building 
-system.
-.sp 10
-.bp
-.NH
-An overview of the Amsterdam Compiler kit
-.PP
-The tool kit consists of eight components:
-.IP 1.
-The preprocessor.
-.IP 2.
-The front ends.
-.IP 3.
-The peephole optimizer.
-.IP 4.
-The global optimizer.
-.IP 5.
-The back end.
-.IP 6.
-The target machine optimizer.
-.IP 7.
-The universal assembler/linker.
-.IP 8.
-The utility package.
-.PP
-A fully optimizing compiler, depicted in Fig. 2, has seven cascaded
-phases. Conceptually, each component reads an input file and writes
-a transformed output file to be used as input to the next component.
-In practice, some components may use temporary files to allow
-multiple passes over the input or internal intermediate files.
-.sp 20
-.PP
-In the following paragraphs a brief decription of each component
-is given.
-A more detailed description of the back end will be given in the 
-rest of this document. For a more detailed descripiton on the rest
-of the components see [7]. A program to be compiled is first fed
-into the (language independed) preprocessor, which provides a
-simple macro facility and similar textual facilities.
-The preprocessor's ouput is a legal program in one of the programming
-languages supported, whereas the input is a program possibly
-augmented with macro's, etc.
-.PP
-This output goes into the appropriate front end, whose job it is to 
-produce intermediate cade.
-This intermediate code (the UNCOL of ACK) is the machine language
-for a simple stack machine EM (Encoding Machine).
-A typical front end might build a parse tree from the input
-and then use the parse tree to generate EM cade,
-which is similar to reverse Polish.
-In order to perform this work, the front end has to maintain tables of declare
-tables of declared variables, labels, etc., determine where
-to place the data structures in memory and so on.
-.PP
-The EM code generated by the front end is fed into the peephole
-optimizer, which scans it with a window of a view instructions,
-replacing certain inefficient code sequences by better ones.
-Such a search is important because EM contains instructions to
-handle numerous important special cases efficiently
-(e.g. incrementing a variable by 1).
-It is our strategy to relieve the front ends of the burden
-of hunting for special cases because there are many front ends
-and just one peephole optimizer.
-By handeling the special cases in the peephole optimizer,
-the front ends become simpler, easier to write and easier to maintain.
-.PP
-Following the peephole optimizer is a global optimizer [2],
-which unlike the peephole optimizer, examines the program as a whole.
-It builts a data flow graph to make possible a variety of global
-optimizations, among them, moving invariant code out of loops,
-avoiding redundant computations, live/dead analysis and
-eliminating tail recursion.
-Note that the output of the global optimizer is still EM code.
-.PP
-Next comes the back end, which differs from the front ends in a
-fundamental way.
-Each front end is a separate program, whereas the back end is a 
-single program that is driven by a machine dependent driving table.
-The driving table for a specific machine tells how EM code is
-mapped onto the machine's assembly language.
-Although a simple driving table just might macro expand each
-EM instruction into a sequence of target machine instructions,
-a much more sophisticated translation strategy is normaly used,
-as described later.
-For speech, the back end does not actually read in the driving
-table at run time.
-Instead, the tables are compiled along with the back end in advance,
-resulting in one binairy program per machine.
-.PP
-The output of the back end is a program in the assembly language
-of some particular machine.
-The next component in the pipeline reads this program and performs
-peephole optimization on it.
-The optimizations performed here involve idiosyncrasies of the
-target machine that cannot be performed by the machine-independent
-EM-to-EM peephole optimizer.
-Typically these optimizations take advantage of the special
-instructions or special addressing modes.
-.PP
-The optimized target machine assembly code then goes into the final
-component in the pipeline, the universal assembler/linker.
-This program assembles the input to object format, extracting
-routines from libraries and including them as needed.
-.PP
-The final component of the tool kit is the utility package,
-which contains various test programs, interpreters for EM code,
-EM libraries, conversion programs and other aids for the
-implementer and user.
-.bp
-.DS C
-.B
-THE MCS6500 MICROPROCESSOR.
-.R
-.DE
-.NH 0
-Introduction
-.PP
-Why a back end table for the MCS6500 microprocessor family.
-Although the MCS6500 microprocessor family has an simple
-instruction set and internal structure, it is used in a
-variety of microcomputers and homecomputers.
-This is because of is low cost.
-As an example the Apple II, a well known and width spread
-microprocessor, uses the MCS6502 CPU.
-Also the BBC homecomputer, whose popularity is growing day
-by day uses the MCS6502 CPU.
-The BBC homecomputer is based on the MCS6502 CPU although 
-better and stronger microprocessors are available.
-The designers of Acorn computer Industries have probably
-choosen for the MCS6502 because of the amount of software
-available for this CPU.
-Since its width spreaded use, a variaty of software
-will be needed for it.
-One can think of games!!, administration programs,
-teaching programs, basic interpreters and other application
-programs.
-Even do it will not be possible to run the total compiler kit
-on a MCS6500 based computer, it is possible to write application
-programs in a high level language, such as Pascal or C on a
-minicomputer.
-These application programs can be tested and compiled on that
-minicomputer and put in a ROM (Read Only Memory), for example,
-cso that it an be executed by a MCS6500 CPU.
-The strategy of writing testprograms on a minicomputer, 
-compile it and then execute it on a MCS6500 based
-microprocessor is used by the development of the back end.
-The minicomputer used is M68000 based one, manufactured by
-Bleasdale Computer Systems Ltd..
-The micro- or homecomputer used is a BBC microcomputer,
-manufactured by Acorn Computer Ltd..
-.NH
-The MOS Technology MCS6500
-.PP
-The MCS6500 is as a family of CPU devices developed by MOS
-Technology.
-The members of the MCS6500 family are the same chips in a 
-different housing.
-The MCS6502, the big brother in the family, can handle 64k
-bytes of memory, while for example the MCS6504 can only handle
-8k bytes of memory.
-This difference is due to the fact that the MCS6502 is in a
-40 pins house and the MCS6504 has a 28 pins house, so less
-address lines are available.
-.bp
-.NH
-The MCS6500 CPU programmable registers
-.PP
-The MCS6500 series is based on the same chip so all have the
-same programmable registers.
-.sp 9
-.NH 2
-The accumulator A.
-.PP
-The accumulator A is the only register on which the arithmetic
-and logical instructions can be used.
-For example, the instruction ADC (add with carry) adds the
-contents of the accumulator A and a byte from memory or data.
-.NH 2
-The index register X.
-.PP
-As the name suggests this register can be used for some
-indirect addressing modes.
-The modes are explaned below.
-.NH 2
-The index register Y.
-.PP
-This register is, just as the index register X, used for
-certain indirect addressing modes.
-These addressing modes are different from the modes which
-use index register X.
-.NH 2
-The program counter PC
-.PP 
-This is the only 16-bit register available.
-It is used to point to the next instruction to be
-carried out.
-.NH 2
-The stack pointer SP
-.PP
-The stack pointer is an 8-bit register, so the stack can contain
-at most 256 bytes.
-The CPU always appends 00000001 as highbyte of any stack address,
-which means that memory locations
-.B
-0100
-.R
-through
-.B
-01FF
-.R
-are permanently assigned to the stack.
-.sp 12
-.NH 2
-The status register
-.PP
-The status register maintains six status flags and a master
-interrupt control bit.
-.br
-These are the six status flags:
-    Carry        (c)
-    Zero         (z)
-    Overflow     (o)
-    Sign         (n)
-    Decimal mode (d)
-    Break        (b)
-
-
-
-
-
-The bit (i) is the master interrupt control bit.
-.NH
-The MCS6500 memory layout.
-.PP
-In the MCS6500 memory space three area's have special meaning.
-These area's are:
-.IP 1)
-Top page.
-.IP 2)
-Zero page.
-.IP 3)
-The stack.
-.PP
-MCS6500 memory is divided up into pages.
-These pages consist 256 bytes.
-So in a memory address the highbyte denotes the page number
-and the lowbyte the offset within the page.
-.NH 2
-Top page.
-.PP
-When a MCS6500 is restared it jumps indirect via memory address
-.B
-FFFC.
-.R
-At
-.B
-FFFC
-.R
-(lowbyte) and 
-.B
-FFFD
-.R
-(highbyte) there must be the address of the bootstrap subroutine.
-When a break instruction (BRK) occurs or an interrupt takes place,
-the MCS6500 jumps indirect through memory address
-.B
-FFFE.
-.R
-.B
-FFFE
-.R
-and 
-.B
-FFFF
-.R
-thus, must contain the address of the interrupt routine.
-The former only goes for maskeble interrupt.
-There also exist a nonmaskeble interrupt.
-This cause the MCS6500 to jump indirect through memory address
-.B
-FFFA.
-.R
-So the top six bytes of memory are used by the operating system
-and therefore not available for the back end.
-.NH 2
-Zero page.
-.PP
-This page has a special meaning in the sence that addressing
-this page uses special opcodes.
-Since a page consists of 256 bytes, only one byte is needed
-for addressing zero page.
-So an instruction which uses zero page occupies two bytes.
-It also uses less clock cycle's while carrying out the instruction.
-Zero page is also needed when indirect addressing is used.
-This means that when indirect addressing is used, the address must
-reside in zero page (two consecutive bytes).
-In this case (the back end), zero page is used, for example
-to hold the local base, the second local base, the stack pointer
-etc.
-.NH 2
-The stack.
-.PP
-The stack is described in paragraph 3.5 about the MCS6500
-programmable registers.
-.NH 
-The memory adressing modes
-.PP
-MCS6500 memory reference instructions use direct addressing,
-indexed addressing, and indirect addressing.
-.NH 2
-direct addressing.
-.PP
-Three-byte instructions use the second and third bytes of the
-object code to provide a direct 16-bit address:
-therefore, 65.536 bytes of memory can be addressed directly.
-The commonly used memory reference instructions also have a two-byte
-object code variation, where the second byte directly addresses
-one of the first 256 bytes.
-.NH 2
-Base page, indexed addressing.
-.PP
-In this case, the instruction has two bytes of object code.
-The contents of either the X or Y index registers are added to the 
-second  object code byte in order to compute a memory address.
-This may be illustrated as follows:
-.sp 15
-Base page, indexed addressing, as illustrated above, is 
-wraparound - which means that there is no carry.
-If the sum of the index register and second object code byte contents
-is more than
-.B
-FF
-.R
-, the carry bit will be dicarded.
-This may be illustrated as follows:
-.sp 9
-.NH 2
-Absolute indexed addressing.
-.PP
-In this case, the contents of either the X or Y register are added
-to a 16-bit direct address provided by the second and third bytes
-of an instruction's object code.
-This may be illustrated as follows:
-.sp 10
-.NH 2
-Indirect addressing.
-.PP
-Instructions that use simple indirect addressing have three bytes of
-object code.
-The second and third object code bytes provide a 16-bit address;
-therefore, the indirect address can be located anywhere in
-memory.
-This is straightforward indirect addressing.
-.NH 3
-Pre-indexed indirect addressing.
-.PP
-In this case, the object code consists of two bytes and the 
-second object code byte provides an 8-bit address.
-Instructions that use pre-indexed indirect addressing add the contents
-of the X index register and the second object code byte to access
-a memory location in the first 256 bytes of memory, where the 
-indirect address will be found:
-.sp 18
-When using pre-indexed indirect addressing, once again wraparound
-addition is used, which means that when the X index register contents
-are added to the second object code byte, any carry will be discarded.
-Note that only the X index register can be used with pre-indexed
-addressing.
-.NH 3
-Post-indexed indirect addressing.
-.PP
-In this case, the object code consists of two bytes and the
-second object code byte provides an 8-bit address.
-Now the second object code byte indentifies a location
-in the first 256 bytes of memory where an indirect address
-will be found.
-The contents of the Y index register are added to this indirect
-address.
-This may be illustrated as follows:
-.sp 18
-Note that only the Y index register can be used with post-indexed
-indirect addressing.
-.bp
-.NH
-What the CPU has and doesn't has.
-.PP
-Although the designers of the MCS6500 CPUs family state that
-there is nothing very significant about the short stack (only
-256 bytes) this stack caused problems for the back end.
-The designers say that a 256-byte stack usually is sufficient
-for any typical microcomputer, this is only true if the stack
-is used only for return addresses of the JSR (jump to
-subroutine) instruction.
-But since the EM machine is suppost to be a stack machine and
-high level languages need the ability of parameters and
-locals in there procedures and function, this short stack
-is unsufficiant.
-So an software stack is implemented in this back end, requiring two
-additional subroutines for stack handling.
-These two stack handling subroutines slow down the processing time
-of a program since the stack is used heavely.
-.PP
-Since parameters and locals of EM procedures are offseted
-from the localbase of that procedure, indirect addressing
-is havily used.
-Offsets are positive (for parameters) and negative (for
-local variables).
-As explaned before the addressing modes the MCS6500 have a
-post indexed indirect addressing mode.
-This addressing mode can only handle positive offsets.
-This raises a problem for accessing the local variables
-I have chosen for the next solution.
-A second local base is introduced.
-This second local base is the real local base subtracted by
-a constant BASE.
-In the present situation of the back end the value of BASE
-is 240.
-This means that there are 240 bytes reseved for local
-variables to be indirect addressed and 14 bytes for
-the parameters.
-.DS C
-.B
-THE CODE GENERATOR.
-.R
-.DE
-.NH 0
-Description of the machine table.
-.PP
-The machine description table consists of the following sections:
-.IP 1.
-The macro definitions.
-.IP 2.
-Constant definitions.
-.IP 3.
-Register definitions.
-.IP 4.
-Token definitions.
-.IP 5.
-Token expressions.
-.IP 6.
-Code rules.
-.IP 7.
-Move definitions.
-.IP 8.
-Test definitions.
-.IP 9.
-Stack definitions.
-.NH 2
-Macro definitions.
-.PP
-The macro definitions at the top of the table are expanded
-by the preprocessor on occurence in the rest of the table.
-.NH 2
-Constant definitions.
-.PP
-There are three constants which must be defined at first.
-The are:
-.IP EM_WSIZE: 11
-Number of bytes in a machine word.
-This is the number of bytes a simple
-.B
-loc
-.R
-instruction will put on the stack.
-.IP EM_PSIZE:
-Number of bytes in a pointer.
-This is the number of bytes a
-.B
-lal
-.R
-instruction will put on the stack.
-.IP EM_BSIZE:
-Number of bytes in the hole between AB and LB.
-The calling sequence only saves LB on the stack so this
-constant is equal to the pointer size.
-.NH 1
-Register definitions.
-.PP
-The only important register definition is the definition of
-the registerpair AX.
-Since the rest of the machine's registers Y, PC, ST serve
-special purposes, the code generator cannot use them.
-.NH 2
-Token definitions
-.PP
-There is a fake token.
-This token is put in the table, since the code generator generator
-complains if it cannot find one.
-.NH 2
-Token expression definitions.
-.PP
-The token expression is also a fake one.
-This token expression is put in the table, since the code generator
-generator complains if it cannot find one.
-.NH 2
-Code rules.
-.PP
-The code rule section is the largest section in the table.
-They specify EM patterns, stack patterns, code to be generated,
-etc.
-The syntax is:
-.IP code rule:
-EM pattern '|' stack pattern '|' code '|'
-stack replacement '|' EM replacement '|'
-.PP
-All patterns are optional, however there must be at least one
-pattern present.
-If the EM pattern is missing the rule becomes a rewriting
-rule or a
-.B
-coercion
-.R
-to be used when code generation cannot continue because of an
-invalid stack pattern.
-The code rules are preceeded by the word CODE:.
-.NH 3
-The EM pattern.
-.PP
-The EM pattern consists of a list of EM mnemonics followed by
-a boolean expression. Examples:
-.sp 1
-.br
-.B
-loe
-.R
-.sp 1
-will match a single
-.B
-loe
-.R
-instruction,
-.sp 1
-.br
-.B
-loc loc cif
-.R
-$1==2 && $2==8
-.sp 1
-is a pattern that will match
-.sp 1
-.br
-.B
-loc
-.R
-2
-.br
-.B
-loc
-.R
-8
-.br
-.B
-cif
-.R
-.sp 1
-and
-.sp 1
-.br
-.B
-lol
-inc
-stl
-.R
-$1==$3
-.sp 1
-will match for example
-.sp 1
-.br
-.B
-lol
-.R
-6
-.br
-.B
-inc
-.R
-.br
-.B
-stl
-.R
-6
-.sp 1
-A missing boolean expession evaluates to TRUE.
-.PP
-The code generator will match the longest EM pattern on every occasion,
-if two patterns of the same length match the first in the table
-will be chosen, while all patterns of length greater than or equal
-to three are considered to be of the same length.
-.NH 3
-The stack pattern.
-.PP
-The only stack pattern that can occur is R16, which means that the
-registerpair AX contains the word on top of the stack.
-If this is not the case a coersion occurs.
-This coersion generates a "jsr Pop", which means that the top
-of the stack is popped and stored in the registerpair AX.
-.NH 3
-The code part.
-.PP
-The code part consists of three parts, stack cleanup, register
-allocation, and code to be generated.
-All of these may be omitted.
-.NH 4
-Stack cleanup.
-.PP
-When generating something like a branch instruction it might be
-needed to empty the fake stack, that is, remove the AX registerpair.
-This is done by the instruction remove(ALL)
-.NH 4
-Register allocation.
-.PP
-If the machine code to be generated uses the registerpair AX,
-this is signaled to the code generator by the allocate(R16)
-instruction.
-If the registerpair AX resides on the fake stack, this will result
-in a "jsr Push", which means that the registerpair AX is pushed on
-the stack and will be free for further use.
-If registerpair AX is not on the fake stack nothing happens.
-.NH 4
-Code to be generated.
-.PP
-Code to be generated is specified as a list of items of the following
-kind:
-.IP 1)
-A string in double quotes("This is a string").
-This is copied to the codefile and a newline ('\n') is appended.
-Inside the string all normal C string conventions are allowed,
-and substitutions can be made of the following sorts.
-.RS
-.IP a)
-$1, $2 etc. These are the operand of the corresponding EM 
-instructions and are printed according to there type.
-To put a real '$' inside the string it must be doubled ('$$').
-.IP b)
-%[1], %[2.reg], %[b.1] etc. these have there obvious meaning.
-If they describe a complete token (%[1]) the printformat for
-the token is used.
-If they stand fo a basic term in an expression they will be
-printed according to their type.
-To put a real '%' inside the string it must be doubled ('%%').
-.IP c)
-%( arbitrary expression %). This allows inclusion of arbitrary
-expressions inside strings.
-Usually not needed very often, so that the akward notation
-is not too bad.
-Note that %(%[1]%) is equivalent to %[1].
-.RE
-.NH 3
-stack replacement.
-.PP
-The stack replacement is a possibly empty list of items to be
-pushed on the fake stack.
-Three things can occur:
-.IP 1)
-%[1] is used if the registerpair AX was on the fake stack and is
-to be pushed back onto it.
-.IP 2)
-%[a] is used if the registerpair AX is allocated with allocate(R16)
-and is to be pushed onto the fake stack.
-.IP 3)
-It can also be empty.
-.NH 3
-EM replacement.
-.PP
-In exeptional cases it might be useful to leave part of the an EM
-pattern undone.
-For example, a
-.B
-sdl
-.R
-instruction might be split into two
-.B
-stl
-.R
-instructions when there is no 4-byte quantity on the stack.
-The EM replacement part allows one to express this.
-Example:
-.sp 1
-.br
-.B
-stl
-.R
-$1
-.B
-stl
-.R
-$1+2
-.sp 1
-The instructions are inserted in the stream so they can match
-the first part of a pattern in the next step.
-Note that since the code generator traverses the EM instructions
-in a strict linear fashion, it is impossible to let the EM
-replacement match later parts of a pattern.
-So if there is a pattern
-.sp 1
-.br
-.B
-loc
-stl
-.R
-$1==0
-.sp1
-and the input is
-.sp 1
-.br
-.B
-loc
-.R
-0
-.B
-sdl
-.R
-4
-.sp 1
-the
-.B
-loc
-.R
-0
-will be processed first, then the
-.B
-sdl
-.R
-might be split into two
-.B
-stl
-.R
-'s but the pattern cannot match now.
-.NH 3
-Move definitions.
-.PP
-This definition is a fake. This definition is put in the
-table, since the code generator generator complains if it
-cannot find one.
-.NH 3
-Test definitions.
-.PP
-Test definitions aren't used by the table.
-.NH 3
-Stack definitions.
-.PP
-When the generator has to push the registerpair AX, it must
-know how to do so.
-The machine code to be generated is defined here.
-.NH 1
-Some remarks.
-.PP
-The above description of the machine table is
-a description of the table for the MCS6500.
-It uses only a part of the possibilities which the code generator
-generator offers.
-For a more precise and detailed description see [4].
-.DS C
-.B
-THE BACK END TABLE.
-.R
-.DE
-.NH 0
-Introduction.
-.PP
-The code rules are divided in 15 groups.
-These groups are:
-.IP 1.
-Load instructions.
-.IP 2.
-Store instructions.
-.IP 3.
-Integer arithmetic instructions.
-.IP 4.
-Unsigned arithmetic instructions.
-.IP 5.
-Floating point arithmetic instructions.
-.IP 6.
-Pointer arithmetic instructions.
-.IP 7.
-Increment, decrement and zero instructions.
-.IP 8.
-Convert instructions.
-.IP 9.
-Logical instructions.
-.IP 10.
-Set manipulation instructions.
-.IP 11.
-Array instructions.
-.IP 12.
-Compare instructions.
-.IP 13.
-Branch instructions.
-.IP 14.
-Procedure call instructions.
-.IP 15.
-Miscellaneous instructions.
-.PP
-From all of these groups one or two typical EM pattern will be explained
-in the next paragraphs.
-Comment is placed between /* and */ (/* This is a comment */).
-.NH
-The instructions.
-.NH 2
-The load instructions.
-.PP
-In this group a typical instruction is
-.B
-lol
-.R
-.
-A
-.B
-lol
-.R
-instruction pushes the word at local base + offset, where offset
-is the instructions argument, onto the stack.
-Since the MCS6500 can only offset by 256 bytes, as explaned at the
-memory addressing modes, there is a need for two code rules in the
-table.
-One which can offset directly and one that must explicit
-calculate the address of the local.
-.NH 3
-The lol instruction with indirect offsetting.
-.PP
-In this case an indirect offsetted load from the second local base
-is possible.
-The table content is:
-.sp 1
-.br
-.B
-lol
-.R
-IN($1) | |
-.br
-allocate(R16)	/* allocate registerpair AX */
-.br
-"ldy #BASE+$1"	/* load Y with the offset from the second
-.br
-					      local base */
-.br
-"lda (LBl),y"	/* load indirect the lowbyte of the word */
-.br
-"tax"		/* move register A to register X */
-.br
-"iny"		/* increment register Y (offset) */
-.br
-"lda (LBl),y"	/* load indirect the highbyte of the word */
-.br
-| %[a] | |	/* push the word onto the fake stack */
-.NH 3
-The lol instruction whose offset is to big.
-.PP
-In this case, the library subroutine "Lol" is used.
-This subroutine expects the offset in registerpair AX, then
-calculates the address of the local or parameter, and loads
-it into registerpair AX.
-The table content is:
-.sp 1
-.br
-.B
-lol
-.R
-| |
-.br
-allocate(R16)	/* allocate registerpair AX */
-.br
-"lda #[$1].h"	/* load highbyte of offset into register A */
-.br
-"ldx #[$1].l"	/* load lowbyte of offset into register X */
-.br
-"jsr Lol"	/* perform the subroutine */
-.br
-| %[a] | |	/* push word onto the fake stack */
-.NH 2
-The store instructions.
-.PP
-In this group a typical instruction is
-.B
-stl.
-.R
-A
-.B
-stl
-.R
-instruction poppes a word from the stack and stores it in the word
-at local base + offset, where offset is the instructions argument.
-Here also is the need for two code rules in the table as a result
-of the offset limits.
-.NH 3
-The stl instruction with indirect offsetting.
-.PP
-In this case it an indirect offsetted store from the second local
-base is possible.
-The table content is:
-.sp 1
-.br
-.B
-stl
-.R
-IN($1) | R16 |	/* expect registerpair AX on top of the
-.br
-							fake stack */
-.br
-"ldy #BASE+1+$1"  /* load Y with the offset from the
-.br
-						second local base */
-.br
-"sta (LBl),y"	/* store the highbyte of the word from A */
-.br
-"txa"		/* move register X to register A */
-.br
-"dey"		/* decrement offset */
-.br
-"sta (LBl),y"	/* store the lowbyte of the word from A */
-.br
-| | |
-.NH 3
-The stl instruction whose offset is to big.
-.PP
-In this case the library subroutine 'Stl' is used.
-This subroutine expects the offset in registerpair AX, then
-calculates the address, poppes the word stores it at its place.
-The table content is:
-.sp 1
-.br
-.B
-stl
-.R
-| |
-.br
-allocate(R16)	/* allocate registerpair AX */
-.br
-"lda #[$1].h"	/* load highbyte of offset in register A */
-.br
-"ldx #[$1].l"	/* load lowbyte of offset in register X */
-.br
-"jsr Stl"	/* perform the subroutine */
-.br
-| | |
-.NH 2
-Integer arithmetic instructions.
-.PP
-In this group typical instructions are
-.B
-adi
-.R
-and
-.B
-mli.
-.R
-These instructions, in this table, are implemented for 2-byte
-and 4-byte integers.
-The only arithmetic instructions available on the MCS6500 are
-the ADC (add with carry), and SBC (subtract with not(carry)).
-Not(carry) here means that in a subtraction, the one's complement
-of the carry is taken.
-The absence of multiply and division instructions forces the
-use of subroutines to handle these cases.
-Because there are no registers left to perform on the multiply
-and division, zero page is used here.
-The 4-byte integer arithmetic is implemented, because in C there
-exists the integer type long.
-A user is freely to use the type long, but will pay in performance.
-.NH 3
-The adi instruction.
-.PP
-In case of the
-.B
-adi
-.R
-2 (and
-.B
-sbi
-.R
-2) instruction there are many EM
-patterns, so that the instruction can be performed in line in
-most cases.
-For the worst case there exists a subroutine in the library
-which deals with the EM instruction.
-In case of a
-.B
-adi
-.R
-4 (or
-.B
-sbi
-.R
-4) there only is a subroutine to deal with it.
-A table content is:
-.sp 1
-.br
-.B
-lol lol adi
-.R
-(IN($1) && IN($2) && $3==2) | | /* is it in range */
-.br
-allocate(R16)	/* allocate registerpair AX */
-.br
-"ldy #BASE+$1+1" /* load Y with offset for first operand */
-.br
-"lda (LBl),y"	/* load indirect highbyte first operand */
-.br
-"pha"		/* save highbyte first operand on hard_stack */
-.br
-"dey"		/* decrement offset first operand */
-.br
-"lda (LBl),y"	/* load indirect lowbyte first operand */
-.br
-"ldy #BASE+$2"	/* load Y with offset for second operand */
-.br
-"clc"		/* clear carry for addition */
-.br
-"adc (LBl),y"	/* add the lowbytes of the operands */
-.br
-"tax"		/* store lowbyte of result in place */
-.br
-"iny"		/* increment offset second operand */
-.br
-"pla"		/* get highbyte first operand */
-.br
-"adc (LBl),y"	/* add the highbytes of the operands */
-.br
-| %[a] | |	/* push the result onto the fake stack */
-.NH 3
-The mli instruction.
-.PP
-The
-.B
-mli
-.R
-2 instruction uses most the subroutine 'Mlinp'.
-This subroutine expects the multiplicand in zero page
-at locations ARTH, ARTH+1, while the multiplier is in zero
-page locations ARTH+2, ARTH+3.
-For a description of the algorithms used for multiplication and
-division, see [9].
-A table content is:
-.sp  1
-.br
-.B
-lol lol mli
-.R
-(IN($1) && IN($2) && $3==2) | |
-.br
-allocate(R16)	/* allocate registerpair AX */
-.br
-"ldy #BASE+$1"	/* load Y with offset of multiplicand */
-.br
-"lda (LBl),y"	/* load indirect lowbyte of multiplicand */
-.br
-"sta ARTH"	/* store lowbyte in zero page */
-.br
-"iny"		/* increment offset of multiplicand */
-.br
-"lda (LBl),y"	/* load indirect highbyte of multiplicand */
-.br
-"sta ARTH+1"	/* store highbyte in zero page */
-.br
-"ldy #BASE+$2"	/* load Y with offset of multiplier */
-.br
-"lda (LBl),y"	/* load indirect lowbyte of multiplier */
-.br
-"sta ARTH+2"	/* store lowbyte in zero page */
-.br
-"iny"		/* increment offset of multiplier */
-.br
-"lda (LBl),y"	/* load indirect highbyte of multiplier */
-.br
-"sta ARTH+3"	/* store highbyte in zero page */
-.br
-"jsr Mlinp"	/* perform the multiply */
-.br
-| %[a] | |	/* push result onto fake stack */
-.NH 2
-The unsgned arithmetic instructions.
-.PP
-Since unsigned addition an subtraction is performed in the same way
-as signed addition and subtraction, these cases are dealt with by
-an EM replacement.
-For mutiplication and division there are special subroutines.
-.NH 3
-Unsigned addition.
-.PP
-This is an example of the EM replacement strategy.
-.sp 1
-.br
-.B
-lol lol adu
-.R
-	| | | |
-.B
-lol
-.R
-$1
-.B
-lol
-.R
-$2
-.B
-adi
-.R
-$3 |
-.NH 2
-Floating point arithmetic.
-.PP
-Floating point arithmetic isn't implemented in this table.
-.NH 2
-Pointer arithmetic instructions.
-.PP
-A typical pointer arithmetic instruction is
-.B
-adp
-.R
-2.
-This instruction adds an offset and a pointer.
-A table content is:
-.sp 1
-.br
-.B
-adp
-.R
-	| | | |
-.B
-loc
-.R
-$1
-.B
-adi
-.R
-2 |
-.NH 2
-Increment, decrement and zero instructions.
-.PP
-In this group a typical instruction is
-.B
-inl
-.R
-, which increments a local or parameter.
-The MCS6500 doesn't have an instruction to increment the
-accumulator A, so the 'ADC' instruction must be used.
-A table content is:
-.sp 1
-.br
-.B
-inl
-.R
-IN($1) | |
-.br
-allocate(R16)	/* allocate registerpair AX */
-.br
-"ldy #BASE+$1"	/* load Y with offset of the local */
-.br
-"clc"		/* clear carry for addition */
-.br
-"lda (LBl),y"	/* load indirect lowbyte of local */
-.br
-"adc #1"	/* increment lowbyte */
-.br
-"sta (LBl),y"	/* restore indirect the incremented lowbyte */
-.br
-"bcc 1f"	/* if carry is clear then ready */
-.br 
-"iny"		/* increment offset of local */
-.br
-"lda (LBl),y"	/* load indirect highbyte of local */
-.br
-"adc #0"	/* add carry to highbyte */
-.br
-"sta (LBl),y\\n1:"  /* restore indirect the highbyte */
-.PP
-If the offset of the local or parameter is to big, first the
-local or parameter is fetched, than incremented, and then
-restored.
-.NH 2
-Convert instructions.
-.PP
-In this case there are two convert instructions
-which really do something.
-One of them is in line code, and deals with the extension of
-a character (1-byte) to an integer.
-The other one is a subroutine which handles the conversion
-between 2-byte integers and 4-byte integers.
-.NH 3
-The in line conversion.
-.PP
-The table content is:
-.sp 1
-.br
-.B
-loc loc cii
-.R
-$1==1 && $2==2 | R16 |
-.br
-"txa"		/* see if sign extension is needed */
-.br
-"bpl 1f"	/* there is no need for sign extension */
-.br
-"lda #0FFh"	/* sign extension here */
-.br
-"bne 2f"	/* conversion ready */
-.br
-"1: lda #0\\n2:"	/* no sign extension here */
-.NH 2
-Logical instructions.
-.PP
-A typical instruction in this group is the logical
-.B
-and
-.R
-on two 2-byte words.
-The logical
-.B
-and
-.R
-on groups of more than two bytes (max 254)
-is also possible and uses a library subroutine.
-.NH 3
-The logical and on 2-byte groups.
-.PP
-The table content is:
-.sp 1
-.br
-.B
-and
-.R
-$1==2 | R16 |	/* one group must be on the fake stack */
-.br
-"sta ARTH+1"	/* temporary save of first group highbyte */
-.br
-"stx ARTH"	/* temporary save of first group lowbyte */
-.br
-"jsr Pop"	/* pop second group from the stack */
-.br
-"and ARTH+1"	/* logical and on highbytes */
-.br
-"pha"		/* temporary save the result's highbyte */
-.br
-"txa"		/* logical and can only be done in A */
-.br
-"and ARTH"	/* logical and on lowbytes */
-.br
-"tax"		/* restore results lowbyte */
-.br
-"pla"		/* restore results highbyte */
-.br
-| %[1] | |	/* push result onto fake stack */
-.NH 2
-Set manipulation instructions.
-.PP
-A typical EM pattern in this group is
-.B
-loc inn zeq
-.R
-$1>0 && $1<16 && $2==2.
-This EM pattern works on sets of 16 bits.
-Sets can be bigger (max 256 bytes = 2048 bits), but than a
-library routine is used instead of in line code.
-The table content of the above EM pattern is:
-.sp 1
-.br
-.B
-loc inn zeq
-.R
-$1>0 && $1<16 && $2==2 | R16 |
-.br
-"ldy #$1+1"	/* load Y with bit number */
-.br
-"stx ARTH"	/* cannot rotate X, so use zero page */
-.br
-"1: lsr a"	/* right shift A */
-.br
-"ror ARTH"	/* right rotate zero page location */
-.br
-"dey"		/* decrement Y */
-.br
-"bne 1b"	/* shift $1 times */
-.br
-"bcc $1"	/* no carry, so bit is zero */
-.NH 2
-Array instructions.
-.PP
-In this group a typical EM pattern is
-.B
-lae lar
-.R
-defined(rom(1,3)) | | | |
-.B
-lae
-.R
-$1
-.B
-aar
-.R
-$2
-.B
-loi
-.R
-rom(1,3).
-This pattern uses the 
-.B
-aar
-.R
-instruction, which is part of a typical EM pattern:
-.sp 1
-.br
-.B
-lae aar
-.R
-$2==2 && rom(1,3)==2 && rom(1,1)==0 | R16 | /* registerpair AX contains
-the index in the array */
-.br
-"pha"		/* save highbyte of index */
-.br
-"txa"		/* move lowbyte of index to A */
-.br
-"asl a"		/* shift left lowbyte == 2 times lowbyte */
-.br
-"tax"		/* restore lowbyte */
-.br
-"pla"		/* restore highbyte */
-.br
-"rol a"		/* rotate left highbyte == 2 times highbyte */
-.br
-| %[1] | adi 2 | /* push new index, add to lowerbound array */
-.NH 2
-Compare instructions.
-.PP
-In this group all EM patterns are performed by calling
-a subroutine.
-Subroutines are used here because comparison is only
-possible byte by byte.
-This means a lot of code, and since compare are used frequently
-a lot of in line code would be generated, and thus reducing
-the space left for the software stack.
-These subroutines can be found in the library.
-.NH 2
-Branch instructions.
-.PP
-A typical branch instruction is
-.B
-beq.
-.R
-The table content for it is:
-.sp 1
-.br
-.B
-beq
-.R
-| R16 |
-.br
-"sta BRANCH+1"	/* save highbyte second operand in zero page */
-.br
-"stx BRANCH"	/* save lowbyte second operand in zero page */
-.br
-"jsr Pop"	/* pop the first operand */
-.br
-"cmp BRANCH+1" 	/* compare the highbytes */
-.br
-"bne 1f"	/* there not equal so go on */
-.br
-"cpx BRANCH"	/* compare the lowbytes */
-.br
-"beq $1\\n1:"	/* lowbytes are also equal, so branch */
-.PP
-Another typical instruction in this group is
-.B
-zeq.
-.R
-The table content is:
-.sp 1
-.br
-.B
-zeq
-.R
-| R16 |
-.br
-"tay"		/* move A to Y for setting testbits */
-.br
-"bmi $1"	/* highbyte s minus so branch */
-.br
-"txa"		/* move X to A for setting testbits */
-.br
-"beq $1\\n1:"	/* lowbyte also zero, thus branch */
-.NH 2
-Procedure call instructions.
-.PP
-In this group one code generation might seem a little
-akward.
-It is the EM instruction
-.B
-cai
-.R
-which generates a 'jsr Indir'.
-This is because there is no indirect jump_subroutine in the
-MCS6500.
-The only solution is to store the address in zero page, and then
-do a 'jsr' to a known label.
-At this label there must be an indirect jump instruction, which
-perform a jump to the address stored in zero page.
-In this case the label is Indir, and the address is stored in
-zero page at the addresses ADDR, ADDR+1.
-The tabel content is:
-.sp 1
-.br
-.B
-cai
-.R
-| R16 |
-.br
-"stx ADDR"	/* store lowbyte of address in zero page */
-.br
-"sta ADDR+1"	/* store highbyte of address in zero page */
-.br
-"jsr Indir"	/* use the indirect jump */
-.br
-| | |
-.NH 2
-Miscellaneous instructions.
-.PP
-In this group, as the name suggests, there is no
-typical EM instruction or EM pattern.
-Most of the MCS6500 code to be generated uses a library subroutine
-or is straightforward.
-.DS C
-.B
-PERFORMANCE.
-.R
-.DE
-.NH 0
-Introduction.
-.PP
-To measure the performance of the back end table some timing
-tests are done.
-What to time?
-In this case, the execution time of several Pascal statements
-are timed.
-Statements in C, which have a Pascal equivalence are timed also.
-The statements are timed as follows.
-A test program is been written, which executes two
-nested  for_loops from 1 to 1.000.
-Within these for_loops the statement, which is to be tested, is placed,
-so the statement will be executed 1.000.000 times.
-Then the same program is executed without the test statement.
-The time difference between the two executions is the time
-neccesairy to execute the test statement 1.000.000 times.
-The total time to execute the test statement requires thus the
-time difference divided by 1.000.000.
-.NH 0
-Testing Pascal statements.
-.PP
-The next statements are tested.
-.IP 1)
-int1 := 0;
-.IP 2)
-int1 := int2 - 1;
-.IP 3)
-int1 := int1 + 1;
-.IP 4)
-int1 := icon1 - icon2;
-.IP 5)
-int1 := icon2 div icon1;
-.IP 6)
-int1 := int2 * int3;
-.IP 7)
-bool := (int1 < 0);
-.IP 8)
-bool := (int1 < 3);
-.IP 9)
-bool := ((int1 > 3) or (int1 < 3))
-.IP 10)
-case int1 of 1: bool := false; 2: bool := true end;
-.IP 11)
-if int1 = 0 then int2 := 3;
-.IP 12)
-while int1 > 0 do int1 := int1 - 1;
-.IP 13)
-m := a[k];
-.IP 14)
-let2 := ['a'..'c'];
-.IP 15)
-P3(x);
-.IP 16)
-dum := F3(x);
-.IP 17)
-s.overhead := 5400;
-.IP 18)
-with s do overhead := 5400;
-.PP
-These statement were tested in a procedure test.
-.sp 1
-.br
-procedure test;
-.br
-var i, j, ... : integer;
-.br
-    bool : boolean;
-.br
-    let2 : set of char;
-.br
-begin
-.br
-    for i := 1 to 1000
-.br
-	for j := 1 to 1000
-.br
-	    STATEMENT
-.br
-end;
-.sp 1
-.PP
-STATEMENT is one of the statements as shown above, or it is
-the empty statement.
-The assignment of used variables, if neccesairy, is done before
-the first for_loop.
-In case of the statement which uses the procedure call, statement
-15, a dummy procedure is declared whose body is empty.
-In case of the statement which uses the function, statement 16,
-this function returns its argument.
-for the timing of C statements a similar test program was
-written.
-.sp 1
-.br
-main()
-.br
-{
-.br
-    int i, j, ...;
-.br
-    for (i = 1; i <= 1000; i++)
-.br
-	for (j = 1; j <= 1000; j++)
-.br
-	    STATEMENT
-.br
-}
-.sp 1
-.NH
-The results.
-.PP
-Here are tables with the results of the time measurments.
-Times are in microseconds (10^-6).
-Some statements appear twice in the tables.
-In the second case an array of 200 integers was declerated
-before the variable to be tested, so this variable cannot
-be accessed by indirect addressing from the second local base.
-This results in a larger execution time of the statement to be
-tested.
-The column 68000 contains the times measured on a Bleasdale,
-M68000 based, computer.
-The times in column pdp are measured on a DEC pdp11/44, where
-the times from column 6500 come from a BBC microcomputer.
-.bp
-.TS
-expand;
-c s s s
-c c c c
-lw35 nw7 nw7 nw7.
-Pascal timing results
-statement	68000	pdp	6500
-_
-T{
-int1 := 0;
-T}	4.0	5.8	16.7
- 	4.0	4.2	97.8
-_
-T{
-int1 := int2 - 1;
-T}	7.2	7.1	27.2
- 	6.9	7.1	206.5
-_
-T{
-int1 := int1 + 1;
-T}	6.9	6.8	27.2
- 	6.4	6.7	106.5
-_
-T{
-int1 := icon1 + icon2;
-T}	6.2	6.2	25.6
- 	6.2	6.0	106.6
-_
-T{
-int1 := icon2 div icon1;
-T}	14.9	14.3	372.6
- 	14.9	14.7	453.7
-_
-T{
-int1 := int2 * int3;
-T}	11.5	12.0	558.1
- 	11.3	11.6	728.6
-_
-T{
-bool := (int1 < 0);
-T}	7.2	6.9	122.8
- 	7.8	8.1	453.2
-_
-T{
-bool := (int1 < 3);
-T}	7.3	7.6	126.0
- 	7.2	8.1	232.2
-_
-T{
-bool := ((int1 > 3) or (int1 < 3))
-T}	10.1	12.0	307.8
- 	10.2	11.9	440.1
-_
-T{
-case int1 of 1: bool := false; 2: bool := true end;
-T}	18.3	17.9	165.7
-_
-T{
-if int1 = 0 then int2 := 3;
-T}	9.5	8.5	133.8
-_
-T{
-while int1 > 0 do int1 := int1 - 1;
-T}	6.9	6.9	126.0
-_
-T{
-m := a[k];
-T}	7.2	6.8	134.3
-_
-T{
-let2 := ['a'..'c'];
-T}	38.4	38.8	447.4
-_
-T{
-P3(x);
-T}	18.9	18.8	180.3
-_
-T{
-dum := F3(x);
-T}	26.8	27.1	343.3
-_
-T{
-s.overhead := 5400;
-T}	4.6	4.1	16.7
-_
-T{
-with s do overhead := 5400;
-T}	4.2	4.3	16.7
-.TE
-.TS
-expand;
-c s s s
-c c c c
-lw35 nw7 nw7 nw7.
-C timing results
-statement	68000time	pdptime	6500time
-_
-T{
-int1 = 0;
-T}	4.1	3.6	17.2
- 	4.1	4.1	97.7
-_
-T{
-int1 = int2 - 1;
-T}	6.6	6.9	27.2
- 	6.1	6.5	206.4
-_
-T{
-int1 = int1 + 1;
-T}	6.4	7.3	27.2
- 	6.3	6.2	206.4
-_
-T{
-int1 = int2 * int3;
-T}	11.4	12.3	522.6
-	9.6	10.1	721.2
-_
-T{
-int1 = (int2 < 0);
-T}	7.2	7.6	126.4
- 	7.4	7.7	232.5
-_
-T{
-int1 = (int2 < 3);
-T}	7.0	7.5	126.0
- 	7.8	7.8	232.6
-_
-T{
-int1 = ((int2 > 3) || (int2 < 3));
-T}	11.8	12.2	193.4
- 	11.5	13.2	245.6
-_
-T{
-switch (int1) { case 1: int1 = 0; break; case 2: int1 = 1; break; }
-T}	28.3	29.2	164.1
-_
-T{
-if (int1 == 0) int2 = 3;
-T}	4.8	4.8	19.4
-_
-T{
-while (int2 > 0) int2 = int2 - 1;
-T}	5.8	6.0	125.9
-_
-T{
-int2 = a[int2];
-T}	4.8	5.1	192.8
-_
-T{
-P3(int2);
-T}	18.8	18.4	180.3
-_
-T{
-int2 = F3(int2);
-T}	27.0	27.2	309.4
-_
-T{
-s.overhead = 5400;
-T}	5.0	4.1	16.7
-.TE
-.NH
-Pascal statements which don't have a C equivalent.
-.PP
-At first, the two statements who perform an operation on constants
-are left out.
-These are left out while the C front end does constant folding,
-while the Pascal front end doesn't.
-So in C the statements int1 = icon1 + icon2; and int1 = icon1 / icont2;
-will use the same amount of time since the expression is evaluated
-by the front end.
-The two other statements (let2 := ['a'..'c']; and
-.B
-with
-.R
-s
-.B
-do
-.R
-overhead := 5400;), aren't included in the C statement timing table,
-because there constructs do not exist in C.
-Although in C there can be direct bit manipulation, and thus can
-be used to implement sets I have not used it here.
-The
-.B
-with
-.R
-statement does not exists in C and there is nothing with the slightest
-resemblance to it.
-.PP
-At first sight in the table , it looked if there is no much difference
-in the times for the M68000 and the pdp11/44, in comparison with the
-times needed by the MCS6500.
-To verify this impression, I calculated the correlation coefficient
-between the times of the M68000 and pdp11/44.
-It turned out to be 0.997 for both the Pascal time tests and the C
-time tests.
-Since the correlation coefficient is near to one and the difference
-between the times is small, they can be considered to be the same
-as seen from the times of the MCS6500.
-Then I have tried to make a grafic of the times from the M68000 and
-the MCS6500.
-Well, there was't any correlation to been seen, taken all the times.
-The only correlation one could see, with some effort, was in the
-times for the first three Pascal statements.
-The two first C statements show also a correlation, which two points
-always do.
-.PP
-Also the three Pascal statements
-.B
-case
-.R
-,
-.B
-if
-.R
-,
-and
-.B
-while
-.R
-have a correlation coefficient of 0.999.
-This is probably because the
-.B
-case
-.R
-statement uses a subroutine in both cases and the other two
-statements
-.B
-if
-.R
-and,
-.B
-while
-.R
-generate in line code.
-The last two Pascal statements use the same time, since the front
-end wil generate the same EM code for both.
-.PP
-The independence between the rest of the test times is because
-in these cases the object code for the MCS6500 uses library
-subroutines, while the other processors can handle the EM code
-with in line code.
-.PP
-It is clear that the MCS6500 is a slower device, it needs longer
-execution times, the need of more library subroutines, but
-there is no constant factor between it execution times and those
-of other processors.
-.PP
-The slowing down of the MCS6500 as result of the need of a
-library subroutine is illustrated by the muliplication
-statement.
-The MCS6500 needs a library subroutine, while the other
-two processors have a machine instruction to perform the
-multiply.
-This results in a factor of 48.5, when the operands can be accessed
-indirect by the MCS6500.
-When the MCS6500 cannot access the operands indirectly the situation
-is even worse.
-The slight differences between the MCS6500 execution times for
-Pascal statements and C statements is probably the result of the
-front end, and thus beyond the scope of this discussion.
-.PP
-Another timing test is done in C on the statement k = i + j + 1983.
-This statement is tested on many UNIX*
-.FS
-* UNIX is a Trademark of Bell Laboratories.
-.FE
-systems.
-For a complete list see appendix A.
-The slowest one is the IBM XT, which runs on a 8088 microprocessor.
-The fasted one is the Amdahl computer.
-Here is short table to illustrate the performance of the
-MCS6500.
-.TS
-c c c
-c n n.
-machine	short	int
-IBM XT	53.4	53.4
-Amdahl	0.5	0.3
-MCS6500	150.2	150.2
-.TE
-The MCS6500 is three times slower than the IBM XT, but threehundred
-times slower than the Amdahl.
-The reason why the times on the IBM XT and the MCS6500 are the
-same for short's and int's, is that most C compilers make the types
-short and integer the same size on 16-bit machines.
-In this project the MCS6500 is regarded as a 16-bit machine.
-.NH
-Length tests.
-.PP
-I have also compiled several programs written in Pascal and C to
-see if there is a resemblance between the number of bytes generated
-in the machine's language.
-In the tables:
-.IP length: 9
-The number of bytes of the source program.
-.IP 68000:
-The number of bytes of the a.out file for a M68000.
-.IP pdp:
-The number of bytes of the a.out file for a pdp11/44.
-.IP 6500:
-The number of bytes of the a.out file for a MCS6500.
-.LP
-These are the results:
-.TS
-c s s s
-c c c c
-n n n n.
-Pascal programs
-length	68000	pdp	6500
-_
-19946	14383	16090	26710
-19484	20169	20190	35416
-10849	10469	11464	18949
-273	4221	5106	7944
-1854	5807	6610	10301
-.TE
-.TS
-c s s s
-c c c c
-n n n n.
-C progams
-length	68000	pdp	6500
-_
-9444	6927	8234	11559
-7655	14353	18240	26251
-4775	11309	15934	19910
-639	6337	9660	12494
-.TE
-.PP
-In contrast to the execution times of the test statements, the
-object code files sizes show a constant factor between them.
-After calculating the correlation coefficient, I have calculated
-the line fitted between sizes.
-.FS
-* x is the number of bytes
-.FE
-.TS
-c s s
-c c c
-l c c.
-Pascal programs
-processor	corr. coef.	fitted line
-_
-68000-pdp	0.996	 
-68000-6500	0.999	1.76x + 502*
-pdp-6500	0.999	1.80x - 1577
-.TE
-.TS
-c s s
-c c c
-l c c.
-C programs
-processor	corr. coef.	fitted line
-_
-68000-pdp	0.974	 
-68000-6500	0.992	1.80x + 502*
-pdp-6500	0.980	1.40x - 1577
-.TE
-.PP
-As seen from the tables above the correlation coefficient for
-Pascal programs is better than the ones for C programs.
-Thus the line fits best for Pascal programs.
-With the formula of the best fitted line one can now estimate
-the size of the object code, which a program needs, for a MCS6500
-without having the compiler at hand.
-One also can see from these formula that the object code
-generated for a MCS6500 is about 1.8 times more than for the other
-processors.
-Since the number of bytes in the source file havily depends on the
-programmer, how many spaces he or she uses, the size of the indenting
-in structured programs, etc., there is no correlation between the
-size of the source file and the size of the object file.
-Also the use of comments has its influence on the size.
-.bp
-.DS C
-.B
-SUMMARY.
-.R
-.DE
-.NH 0
-Summary
-.PP
-In this chapter some final conclusions are made.
-.PP
-In spite of its simplicity, the MCS6500 is strong enough to
-implement a EM machine.
-A serious deficy of the MCS6500 is the missing of 16-bit
-general purpose registers, and especially the missing of a
-16-bit stackpointer.
-As pointed out before, one 16-bit register can be simulated
-by a pair of 8-bit registers, in fact, the accumulator A to
-hold the highbyte, and the index register X to hold the lowbyte
-of the word.
-By lack of a 16-bit stackpointer, zero page must be used to hold
-a stackpointer and there are also two subroutines needed for
-manipulating the stack (Push and Pop).
-.PP
-As seen at the time tests, the simple instruction set of the
-MCS6500 forces the use of library subroutines.
-These library subroutines increas the execution time of the
-programs.
-.PP
-The sizes of the object code files show a strong correlation
-in contrast to the execution times.
-With this correlatiuon one canestimate the size of a program
-if it is to be used on a MCS6500.
-.bp
-.NH 0
-.B
-REFERENCES.
-.R
-.IP 1.
-Haddon. B.K., and Waite, W.M.
-Experience with the Universal Intermediate Language Janus.
-.B
-Software Practice & Experience 8
-.R
-,
-5 (Sept.-Oct. 1978), 601-616.
-.RS
-.PP
-An intermediate language for use with Algol 68, Pascal, etc.
-is described.
-The paper discusses some problems encountered and how they were
-dealt with.
-.RE
-.IP 2.
-Lowry, E.S., and Medlock, C.W. Object Code Optimization.
-.B
-Commun. ACM 12
-.R
-,
-(Jan. 1969), 13-22.
-.RS
-.PP
-A classical paper on global object code optimization.
-It covers data flow analysis, common subexpressions, code motion,
-register allocation and other techniques.
-.RE
-.IP 3.
-Osborn, A., Jacobson, S., and Kane, J. The Mos Technology MCS6500.
-.B
-An Introduction to Microcomputers ,
-.R
-Volume II, Some Real Products (june 1977) chap. 9.
-.RS
-.PP
-A hardware description of some real existing CPU's, such as
-the Intel Z80, MCS6500, etc. is given in this book.
-.RE
-.IP 4.
-van Staveren, H.
-The table driven code generator from the Amsterdam Compiler Kit.
-Vrije Universiteit, Amsterdam, (July 11, 1983).
-.RS
-.PP
-The defining document for writing a back end table.
-.RE
-.IP 5.
-Steel, T.B., Jr. UNCOL: The Myth and the Fact. in
-.B
-Ann. Rev. Auto. Prog.
-.R
-Goodman, R. (ed.), vol 2., (1960), 325-344.
-.RS
-.PP
-An introduction to the UNCOL idea by its originator.
-.RE
-.IP 6.
-Steel. T.B., Jr. A first Version of UNCOL.
-.B
-Proc. Western Joint Comp. Conf.
-.R
-,
-(1961), 371-377.
-.IP 7.
-Tanenbaum, A.S., Stevenson, J.W., Keizer, E.G., and van Staveren,
-H.
-A Practical Tool Kit for Making Portable Compilers.
-Informatica Rapport 74, Vrije Universiteit, Amsterdam, 1983.
-.RS
-.PP
-An overview on the Amsterdam Compiler Kit.
-.RE
-.IP 8.
-Tanenbaum, A.S., Stevenson, J.W., Keizer, E.G., and van Staveren,
-H.
-Description of an Experimental Machine Architecture for use with
-Block Structured Languages.
-Informatica Rapport 81, Vrije Universiteit, Amsterdam, 1983.
-.RS
-.PP
-The defining document for EM.
-.RE
-.IP 9.
-Tanenbaum, A.S. Structured Computer Organization.
-Prentice Hall. (1976).
-.RS
-.PP
-In this book computers are described as a hierarchy of levels,
-with each one performing some well-defined function.
-.RE

+ 0 - 53
doc/Makefile

@@ -1,53 +0,0 @@
-# $Header$
-
-SUF=pr
-PRINT=cat
-RESFILES=cref.$(SUF) pcref.$(SUF) val.$(SUF) v7bugs.$(SUF) install.$(SUF)\
-ack.$(SUF) cg.$(SUF) regadd.$(SUF) peep.$(SUF) toolkit.$(SUF) LLgen.$(SUF)\
-basic.$(SUF) 6500.$(SUF) ncg.$(SUF)
-NROFF=nroff
-MS=-ms
-
-cref.$(SUF):        cref.doc
-		tbl $? | $(NROFF) >$@
-v7bugs.$(SUF):      v7bugs.doc
-		$(NROFF) $(MS) $? >$@
-ack.$(SUF):         ack.doc
-		$(NROFF) $(MS) $? >$@
-cg.$(SUF):		cg.doc
-		$(NROFF) $(MS) $? >$@
-ncg.$(SUF):		ncg.doc
-		$(NROFF) $(MS) $? >$@
-regadd.$(SUF):		regadd.doc
-		$(NROFF) $(MS) $? >$@
-install.$(SUF):     install.doc
-		$(NROFF) $(MS) $? >$@
-pcref.$(SUF):       pcref.doc
-		$(NROFF) $? >$@
-basic.$(SUF):       basic.doc
-		$(NROFF) $(MS) $? >$@
-peep.$(SUF):	peep.doc
-		$(NROFF) $(MS) $? >$@
-val.$(SUF):         val.doc
-		$(NROFF) $? >$@
-toolkit.$(SUF):	toolkit.doc
-		$(NROFF) $(MS) $? >$@
-LLgen.$(SUF):	LLgen.doc
-		eqn $? | $(NROFF) $(MS) >$@
-6500.$(SUF):	6500.doc
-		$(NROFF) $(MS) $? >$@
-
-install cmp:
-
-distr:		install.doc
-		nroff -Tlp install.doc >install.pr
-pr:
-		@make "SUF="$SUF "NROFF="$NROFF "PRINT="$PRINT $(RESFILES) \
-			>make.pr.out 2>&1
-		@$(PRINT) $(RESFILES)
-
-opr:
-		make pr | opr
-
-clean:
-		-rm -f *.old $(RESFILES) *.t

+ 0 - 420
doc/ack.doc

@@ -1,420 +0,0 @@
-.\" $Header$
-.nr LL 7.5i
-.tr ~
-.nr PD 1v
-.TL
-Ack Description File
-.br
-Reference Manual
-.AU
-Ed Keizer
-.AI
-Wiskundig Seminarium
-Vrije Universiteit
-Amsterdam
-.NH
-Introduction
-.PP
-The program \fIack\fP(I) internally maintains a table of
-possible transformations and a table of string variables.
-The transformation table contains one entry for each possible
-transformation of a file.
-Which transformations are used depends on the suffix of the
-source file.
-Each transformation table entry tells which input suffixes are
-allowed and what suffix/name the output file has.
-When the output file does not already satisfy the request of the
-user, with the flag \fB-c.suffix\fP, the table is scanned
-starting with the next transformation in the table for another
-transformation that has as input suffix the output suffix of
-the previous transformation.
-A few special transformations are recognized, among them is the
-combiner.
-A program combining several files into one.
-When no stop suffix was specified (flag \fB-c.suffix\fP) \fIack\fP
-stops after executing the combiner with as arguments the -
-possibly transformed - input files and libraries.
-\fIAck\fP will only perform the transformations in the order in
-which they are presented in the table.
-.LP
-The string variables are used while creating the argument list
-and program call name for
-a particular transformation.
-.NH
-Which descriptions are used
-.PP
-\fIAck\fP always uses two description files: one to define the
-front-end transformations and one for the machine dependent
-back-end transformations.
-Each description has a name.
-First the way of determining
-the name of the descriptions needed is described.
-.PP
-When the shell environment variable ACKFE is set \fIack\fP uses
-that to determine the front-end table name, otherwise it uses
-\fBfe\fP.
-.PP
-The way the backend table name is determined is more
-convoluted.
-.br
-First, when the last filename in the program call name is not
-one of \fIack\fP, \fIcc\fP, \fIacc\fP, \fIpc\fP or \fIapc\fP,
-this filename is used as the backend description name.
-Second, when the \fB-m\fP is present the \fB-m\fP is chopped of this
-flag and the rest is used as the backend description name.
-Third, when both failed the shell environment variable ACKM is
-used.
-Last, when also ACKM was not present the default backend is
-used, determined by the definition of ACKM in h/local.h.
-The presence and value of the definition of ACKM is
-determined at compile time of \fIack\fP.
-.PP
-Now, we have the names, but that is only the first step.
-\fIAck\fP stores a few descriptions at compile time.
-This descriptions are simply files read in at compile time.
-At the moment of writing this document, the descriptions
-included are: pdp, fe, i86, m68k2, vax2 and int.
-The name of a description is first searched for internally,
-then in the directory lib/ack and finally in the current
-directory of the user.
-.NH
-Using the description file
-.PP
-Before starting on a narrative of the description file,
-the introduction of a few terms is necessary.
-All these terms are used to describe the scanning of zero
-terminated strings, thereby producing another string or
-sequence of strings.
-.IP Backslashing 5
-.br
-All characters preceded by \e are modified to prevent
-recognition at further scanning.
-This modification is undone before a string is passed to the
-outside world as argument or message.
-When reading the description files the
-sequences \e\e, \e# and \e<newline> have a special meaning.
-\e\e translates to a single \e, \e# translates to a single #
-that is not
-recognized as the start of comment, but can be used in
-recognition and finally, \e<newline> translates to nothing at
-all, thereby allowing continuation lines.
-.nr PD 0
-.IP "Variable replacement"
-.br
-The scan recognizes the sequences {{, {NAME} and {NAME?text}
-Where NAME can be any combination if characters excluding ? and
-} and text may be anything excluding }.
-(~\e} is allowed of course~)
-The first sequence produces an unescaped single {.
-The second produces the contents of the NAME, definitions are
-done by \fIack\fP and in description files.
-When the NAME is not defined an error message is produced on
-the diagnostic output.
-The last sequence produces the contents of NAME if it is
-defined and text otherwise.
-.PP
-.IP "Expression replacement"
-.br
-Syntax:  (\fIsuffix sequence\fP:\fIsuffix sequence\fP=\fItext\fP)
-.br
-Example: (.c.p.e:.e=tail_em)
-.br
-If the two suffix sequences have a common member -~\&.e in this
-case~- the text is produced.
-When no common member is present the empty string is produced.
-Thus the example given is a constant expression.
-Normally, one of the suffix sequences is produced by variable
-replacement.
-\fIAck\fP sets three variables while performing the diverse
-transformations: HEAD, TAIL and RTS.
-All three variables depend on the properties \fIrts\fP and
-\fIneed\fP from the transformations used.
-Whenever a transformation is used for the first time,
-the text following the \fIneed\fP is appended to both the HEAD and
-TAIL variable.
-The value of the variable RTS is determined by the first
-transformation used with a \fIrts\fP property.
-.LP
-Two runtime flags have effect on the value of one or more of
-these variables.
-The flag \fB-.suffix\fP has the same effect on these three variables
-as if a file with that \fBsuffix\fP was included in the argument list
-and had to be translated.
-The flag \fB-r.suffix\fP only has that effect on the TAIL
-variable.
-The program call names \fIacc\fP and \fIcc\fP have the effect
-of an automatic \fB-.c\fB flag.
-\fIApc\fP and \fIpc\fP have the effect of an automatic \fB-.p\fP flag.
-.IP "Line splitting"
-.br
-The string is transformed into a sequence of strings by replacing
-the blank space by string separators (nulls).
-.IP "IO replacement"
-.br
-The > in the string is replaced by the output file name.
-The < in the string is replaced by the input file name.
-When multiple input files are present the string is duplicated
-for each input file name.
-.nr PD 1v
-.LP
-Each description is a sequence of variable definitions followed
-by a sequence of transformation definitions.
-Variable definitions use a line each, transformations
-definitions consist of a sequence of lines.
-Empty lines are discarded, as are lines with nothing but
-comment.
-Comment is started by a # character, and continues to the end
-of the line.
-Three special two-characters sequences exist: \e#, \e\e and
-\e<newline>.
-Their effect is described under 'backslashing' above.
-Each - nonempty - line starts with a keyword, possibly
-preceded by blank space.
-The keyword can be followed by a further specification.
-The two are separated by blank space.
-.PP
-Variable definitions use the keyword \fIvar\fP and look like this:
-.DS X
-   var NAME=text
-.DE
-The name can be any identifier, the text may contain any
-character.
-Blank space before the equal sign is not part of the NAME.
-Blank space after the equal is considered as part of the text.
-The text is scanned for variable replacement before it is
-associated with the variable name.
-.br
-.sp 2
-The start of a transformation definition is indicated by the
-keyword \fIname\fP.
-The last line of such a definition contains the keyword
-\fIend\fP.
-The lines in between associate properties to a transformation
-and may be presented in any order.
-The identifier after the \fIname\fP keyword determines the name
-of the transformation.
-This name is used for debugging and by the \fB-R\fP flag.
-The keywords are used to specify which input suffices are
-recognized by that transformation,
-the program to run, the arguments to be handed to that program
-and the name or suffix of the resulting output file.
-Two keywords are used to indicate which run-time startoffs and
-libraries are needed.
-The possible keywords are:
-.IP \fIfrom\fP
-.br
-followed by a sequence of suffices.
-Each file with one of these suffices is allowed as input file.
-Preprocessor transformations, those with the \fBP\fP property
-after the \fIprop\fP keyword, do not need the \fIfrom\fP
-keyword. All other transformations do.
-.nr PD 0
-.IP \fIto\fP
-.br
-followed by the suffix of the output file name or in the case of a
-linker -~indicated by C option after the \fIprop\fP keyword~-
-the output file name.
-.IP \fIprogram\fP
-.br
-followed by name of the load file of the program, a pathname most likely
-starts with either a / or {EM}.
-This keyword must be
-present, the remainder of the line
-is subject to backslashing and variable replacement.
-.IP \fImapflag\fP
-.br
-The mapflags are used to grab flags given to \fIack\fP and
-pass them on to a specific transformation.
-This feature uses a few simple pattern matching and replacement
-facilities.
-Multiple occurences of this keyword are allowed.
-This text following the keyword is
-subjected to backslashing.
-The keyword is followed by a match expression and a variable
-assignment separated by blank space.
-As soon as both description files are read, \fIack\fP looks
-at all transformations in these files to find a match for the
-flags given to \fIack\fP.
-The flags \fB-m\fP, \fB-o\fP,
-\fI-O\fP, \fB-r\fP, \fB-v\fP, \fB-g\fP, -\fB-c\fP, \fB-t\fP,
-\fB-k\fP, \fB-R\fP and -\f-.\fP are specific to \fIack\fP and
-not handed down to any transformation.
-The matching is performed in the order in which the entries
-appear in the definition.
-The scanning stops after first match is found.
-When a match is found, the variable assignment is executed.
-A * in the match expression matches any sequence of characters,
-a * in the right hand part of the assignment is
-replaced by the characters matched by
-the * in the expression.
-The right hand part is also subject to variable replacement.
-The variable will probably be used in the program arguments.
-The \fB-l\fP flags are special,
-the order in which they are presented to \fIack\fP must be
-preserved.
-The identifier LNAME is used in conjunction with the scanning of
-\fB-l\fP flags.
-The value assigned to LNAME is used to replace the flag.
-The example further on shows the use all this.
-.IP \fIargs\fP
-.br
-The keyword is followed by the program call arguments.
-It is subject to backslashing, variable replacement, expression
-replacement, line splitting and IO replacement.
-The variables assigned to by \fImapflags\P will probably be
-used here.
-The flags not recognized by \fIack\fP or any of the transformations
-are passed to the linker and inserted before all other arguments.
-.IP \fIprop\fB
-.br
-This -~optional~- keyword is followed by a sequence of options,
-each option is indicated by one character
-signifying a special property of the transformation.
-The possible options are:
-.DS X
-   <            the input file will be read from standard input
-   >            the output file will be written on standard output
-   p            the input files must be preprocessed
-   m            the input files must be preprocessed when starting with #
-   O            this transformation is an optimizer and may be skipped
-   P            this transformation is the preprocessor
-   C            this transformation is the linker
-.DE
-.IP \fIrts\fP
-.br
-This -~optional~- keyword indicates that the rest of the line must be
-used to set the variable RTS, if it was not already set.
-Thus the variable RTS is set by the first transformation
-executed which such a property or as a result from \fIack\fP's program
-call name (acc, cc, apc or pc) or by the \fB-.suffix\fP flag.
-.IP \fIneed\fP
-.br
-This -~optional~- keyword indicates that the rest of the line must be
-concatenated to the NEEDS variable.
-This is done once for every transformation used or indicated
-by one of the program call names mentioned above or indicated
-by the \fB-.suffix\fP flag.
-.br
-.nr PD 1v
-.NH
-Conventions used in description files
-.PP
-\fIAck\fP reads two description files.
-A few of the variables defined in the machine specific file
-are used by the descriptions of the front-ends.
-Other variables, set by \fack\fB, are of use to all
-transformations.
-.PP
-\fIAck\fP sets the variable EM to the home directory of the
-Amsterdam Compiler Kit.
-The variable SOURCE is set to the name of the argument that is currently
-being massaged, this is usefull for debugging.
-.br
-The variable M indicates the
-directory in mach/{M}/lib/tail_..... and NAME is the string to
-be defined by the preprocessor with -D{NAME}.
-The definitions of {w}, {s}, {l}, {d}, {f} and {p} indicate
-EM_WSIZE, EM_SSIZE, EM_LSIZE, EM_DSIZE, EM_FSIZE and EM_PSIZE
-respectively.
-.br
-The variable INCLUDES is used as the last argument to \fIcpp\fP,
-it is currently used to add the directory {EM}/include to
-the list of directories containing #include files.
-{EM}/include contains a few files used by the library routines
-for part III from the
-.UX
-manual.
-These routines are included in the kit.
-.PP
-The variables HEAD, TAIL and RTS are set by \fIack\fP and used
-to compose the arguments for the linker.
-.NH
-Example
-.sp 1
-description for front-end
-.DS X
-name cpp                        # the C-preprocessor
-        # no from, it's governed by the P property
-        to .i                   # result files have suffix i
-        program {EM}/lib/cpp    # pathname of loadfile
-        mapflag -I* CPP_F={CPP_F?} -I*          # grab -I.. -U.. and
-        mapflag -U* CPP_F={CPP_F?} -U*          # -D.. to use as arguments
-        mapflag -D* CPP_F={CPP_F?} -D*          # in the variable CPP_F
-        args {CPP_F?} {INCLUDES?} -D{NAME} -DEM_WSIZE={w} -DEM_PSIZE={p} \
--DEM_SSIZE={s} -DEM_LSIZE={l} -DEM_FSIZE={f} -DEM_DSIZE={d} <
-                                # The arguments are: first the -[IUD]...
-                                #  then the include dir's for this machine
-                                #  then the NAME and size valeus finally
-                                #  followed by the input file name
-        prop >P                 # Output on stdout, is preprocessor
-end
-name cem                        # the C-compiler proper
-        from .c                 # used for files with suffix .c
-        to .k                   # produces compact code files
-        program {EM}/lib/em_cem # pathname of loadfile
-        mapflag -p CEM_F={CEM_F?} -Xp   # pass -p as -Xp to cem
-        mapflag -L CEM_F={CEM_F?} -l    # pass -L as -l to cem
-        args -Vw{w}i{w}p{p}f{f}s{s}l{l}d{d} {CEM_F?}
-                                # the arguments are the object sizes in
-                                # the -V... flag and possibly -l and -Xp
-        prop <>p                # input on stdin, output on stdout, use cpp
-        rts .c                  # use the C run-time system
-        need .c                 # use the C libraries
-end
-name decode                     # make human readable files from compact code
-        from .k.m               # accept files with suffix .k or .m
-        to .e                   # produce .e files
-        program {EM}/lib/em_decode      # pathname of loadfile
-        args <                  # the input file name is the only argument
-        prop >                  # the output comes on stdout
-end
-.DE
-
-.DS X
-Example of a backend, in this case the EM assembler/loader.
-
-var w=2                         # wordsize 2
-var p=2                         # pointersize 2
-var s=2                         # short size 2
-var l=4                         # long size 4
-var f=4                         # float size 4
-var d=8                         # double size 8
-var M=int                       # Unused in this example
-var NAME=int22                  # for cpp (NAME=int results in #define int 1)
-var LIB=mach/int/lib/tail_      # part of file name for libraries
-var RT=mach/int/lib/head_       # part of file name for run-time startoff
-var SIZE_FLAG=-sm               # default internal table size flag
-var INCLUDES=-I{EM}/include     # use {EM}/include for #include files
-name asld                       # Assembler/loader
-        from .k.m.a             # accepts compact code and archives
-        to e.out                # output file name
-        program {EM}/lib/em_ass         # load file pathname
-        mapflag -l* LNAME={EM}/{LIB}*   # e.g. -ly becomes
-                                        #   {EM}/mach/int/lib/tail_y
-        mapflag -+* ASS_F={ASS_F?} -+*  # recognize -+ and --
-        mapflag --* ASS_F={ASS_F?} --*
-        mapflag -s* SIZE_FLAG=-s*       # overwrite old value of SIZE_FLAG
-        args {SIZE_FLAG} \
-                ({RTS}:.c={EM}/{RT}cc) ({RTS}:.p={EM}/{RT}pc) -o > < \
-                (.p:{TAIL}={EM}/{LIB}pc) \
-                (.c:{TAIL}={EM}/{LIB}cc.1s {EM}/{LIB}cc.2g) \
-                (.c.p:{TAIL}={EM}/{LIB}mon)
-                # -s[sml] must be first argument
-                # the next line contains the choice for head_cc or head_pc
-                # and the specification of in- and output.
-                # the last three args lines choose libraries
-        prop C  # This is the final stage
-end
-.DE
-
-The command "ack -mint -v -v -I../h -L -ly prog.c"
- would result in the following
-calls (with exec(II)):
-.DS X
-1)  /lib/cpp -I../h -I/usr/em/include -Dint22 -DEM_WSIZE=2 -DEM_PSIZE=2
-      -DEM_SSIZE=2 -DEM_LSIZE=4 -DEM_FSIZE=4 -DEM_DSIZE=8 prog.c
-2)  /usr/em/lib/em_cem -Vw2i2p2f4s2l4d8 -l
-3)  /usr/em/lib/em_ass -sm /usr/em/mach/int/lib/head_cc -o e.out prog.k
-      /usr/em/mach/int/lib/tail_y /usr/em/mach/int/lib/tail_cc.1s
-      /usr/em/mach/int/lib/tail_cc.2g /usr/em/mach/int/lib/tail_mon
-.DE

+ 0 - 854
doc/basic.doc

@@ -1,854 +0,0 @@
-.\" $Header$
-.TL
-.de Sy
-.LP
-.IP \fBsyntax\fR 10
-..
-.de PU
-.IP \fBpurpose\fR 10
-..
-.de RM
-.IP \fBremarks\fR 10
-..
-The ABC compiler
-.AU
-Martin L. Kersten
-.AI
-Department of Mathematics and Computer Science.
-.br
-Vrije Universiteit
-.AB
-This manual describes the 
-programming language BASIC and its compiler
-included in the Amsterdam Compiler Kit.
-.AE
-.SH
-INTRODUCTION.
-.LP
-The BASIC-EM compiler is an extensive implementation of the
-programming language BASIC.
-The language structure and semantics are modelled after the 
-BASIC interpreter/compiler of Microsoft (tr), a detailed comparison
-is provided in appendix A.
-.LP
-The compiler generates code for a virtual machine, the EM machine
-[[ACM, etc]]
-Using EM as an intermediate machine results in a highly portable
-compiler and BASIC code.
-The drawback of EM is that it does not directly reflect one particular
-hardware design, which means that many of 
-the low level operations available within 
-BASIC are ill-defined or even inapplicable.
-To mention a few, the peek and poke instructions are likely
-to be behave errorneous, while line printer and tapedeck 
-primitives are unknown.
-.LP
-This manual is divided into three chapters.
-The first chapter discusses the general language syntax and semantics.
-Chapter two describes the statements available in BASIC-EM.
-Chapter 3 describes the predefined functions,
-ordered alphabetically.
-Appendix A discusses the differences with
-Microsoft BASIC. Appendix B describes all reserved symbols.
-Appendix C lists the error messages in use.
-.sp
-Additional information about EM and the Amsterdam Compiler Kit
-can be obtained from .... and found in ......
-.SH
-SyNTAX NOTATION
-.LP
-The conventions for syntax presentation are as follows:
-.IP CAPS 10
-Items are reserved words, must be input as shown
-.IP <> 10
-Items in lowercase letters enclosed in angular brackets
-are to be supplied by the user.
-.IP [] 10
-Items are optional.
-.IP \.\.\. 10
-Items may be repeated any number of times 
-.IP {} 10
-A choice between two or more alternatives. At least one of the entries
-must be chosen.
-.IP | 10
-Vertical bars separate the choices within braces.
-.LP
-All punctuation must be included where shown.
-.NH 1
-GENERAL INFORMATION
-.LP
-The BASIC-EM compiler is designed for a UNIX based environment.
-It accepts a text file with your BASIC program (suffix .b) and generates
-an executable file, called a.out.
-.LP
-Should we call the preprocessor first?
-.NH 2
-LINE FORMAT
-.LP
-A BASIC program consists of a series of lines, starting with a 
-positive line number in the range 0 to 65529.
-A line may consists of more then one physical line on your terminal, but must
-is limited to 1024 characters.
-Multiple BASIC statements may be placed on a single line, provided
-they are separated by a colon (:).
-.NH 2
-CONSTANTS
-.LP
-The BASIC compiler character set is comprised of alphabetic
-characters, numeric characters, and special characters shown below.
-.DS
-= + - * / ^ ( ) % # $ \\ _
-! [ ] , . ; : & ' ? > <  \\ (blanc)
-.DE
-.LP
-BASIC uses two different types of constants during processing:
-numeric and string constants.
-.br
-A string constant is a sequence of characters taken from the ASCII
-character set enclosed by double quotation marks.
-.br
-Numeric constants are positive or negative numbers, grouped into
-five different classes.
-.IP "a) integer constants" 25
-Whole numbers in the range of -32768 and 32767. Integer constants do
-not contain decimal points.
-.IP "b) fixed point constants" 25
-Positive or negative real numbers, i.e. numbers with a decimal point.
-.IP "c) floating point constants" 25
-Real numbers in scientific notation. A floating point constant
-consists of an optional signed integer or fixed point number
-followed by the letter E (or D) and an optional signed integer
-(the exponent).
-The allowable range of floating point constants is 10^-38 to 10^+38.
-.IP "d) Hex constants" 25
-Hexadecimal numbers, denoted by the prefix &H.
-.IP "d) Octal constants" 25
-Octal numbers, denoted by the prefix &O.
-.NH 2
-VARIABLES
-.LP
-Variables are names used to represent values in a BASIC program.
-A variable is assigned a value by assigment specified in the program.
-Before a variable is assigned its value is assumed to be zero.
-.br
-Variable names are composed of letters, digits or the decimal point,
-starting with a letter. Up to 40 characters are significant.
-A variable name be be followed by any of the following  type 
-declaration characters:
-.IP % 5
-Defines an integer variable
-.IP ! 5
-Defines a single precision variable (see below)
-.IP # 5
-Defines a double precision variable
-.IP $ 5
-Defines a string variable.
-.LP
-NOTE: Two variables with the same name but different type is
-considered illegal (DONE?).
-.LP
-Beside single valued variables, values may be grouped
-into tables or arrays.
-Each element in an array is referenced by the array name and an index,
-such a variable is called a subscripted variable.
-An array has as many subscripts as there are dimensions in the array,
-the maximum of which is 11.
-.br
-If a variable starts with FN it is assumed to be a call to a user defined
-function. 
-.br
-A variable name may not be a reserved word nor the name 
-of a predefined function.
-A list of all reserved identifiers is included as Appendix ?.
-.NH 2
-EXPRESSIONS
-.LP
-BASIC-EM differs from Microsoft BASIC in supporting floats in one precision
-only (due to EM).
-All floating point constants have the same precision, i.e. 16 digits.
-.LP
-When necessary the compiler will convert a numeric value from
-one type to another.
-A value is always converted to the precision of the variable it is assigned
-to.
-When a floating point value is converted to an integer the fractional
-portion is rounded.
-In an expression all values are converted to the same degree of precision,
-i.e. that of the most precise operand.
-.br
-Division by zero results in the message "Division by zero".
-If overflow (or underflow) occurs, the "Overflow (underflow)" message is
-displayed and  execution is terminated (contrary to Microsoft).
-.SH
-Arithmetic
-.LP
-The arithmetic operators in order of precedence,a re:
-.DS L
-\^		Exponentiation
--		Negation
-*,/,\\,MOD	Multiplication, Division, Remainder
-+,-		Addition, Substraction
-.DE
-The operator \\\\ denotes integer division, its operands are rounded to
-integers before the operator is applied.
-Modulus arithmetic is denoted by the operator MOD, which yields the
-integer value that is the remainder of an integer division.
-.br
-The order in which operators are performed can be changec with parentheses.
-.SH
-Relational
-.LP
-The relational operators in order of precedence, are:
-.DS
-=	Equality
-<>	Inequality
-<	Less than
->	Greater than
-<=	Less than or equal to
->=	Greater than or equal to
-.DE
-The relational operators are used to compare two values and returns
-either "true" (-1) or "false" (0) (See IF statement).
-The precedence of the relational operators is lower 
-then the arithmetic operators.
-.SH
-Logical
-.LP
-The logical operators performs tests on multiple relations, bit manipulations,
-or Boolean operations.
-The logical operators returns a bitwise result ("true" or "false").
-In an expression, logical operators are performed after the relational and
-arithmetic operators.
-The logical operators work by converting their operands to signed
-two-complement integers in the range -32768 to 32767.
-.DS
-NOT		Bitwise negation
-AND		Bitwise and
-OR		Bitwise or
-XOR		Bitwise exclusive or
-EQV		Bitwise equivalence
-IMP		Bitwise implies
-.DE
-.SH
-Functional
-.LP
-A function is used in  an expression to call a system or user defined
-function.
-A list of predefined functions is presented in chapter 3.
-.SH
-String operations
-.LP
-Strings can be concatenated by using +. Strings can be compared with
-the relational operators. String comparison is performed in lexicographic
-order.
-.NH 2
-ERROR MESSAGES
-.LP
-The occurence of an error results in termination of the program
-unless an ON....ERROR statement has been encountered.
-.NH 1
-B-EM STATEMENTS
-.LP
-This chapter describes the statements available within the BASIC-EM
-compiler. Each description is formatted as follows:
-.Sy
-Shows the correct syntax for the statement. See introduction of
-syntax notation above.
-.PU
-Describes the purpose and details of the instructions.
-.RM
-Describes special cases, deviation from Microsoft BASIC etc.
-.LP
-.NH 2 
-CALL
-.Sy
-CALL <variable name>[(<argument list>)]
-.PU
-The CALL statement provides the means to execute procedures
-and functions written in another language included in the
-Amsterdam Compiler Kit.
-The argument list consist of (subscripted) variables.
-The BASIC compiler pushes the address of the arguments on the stack in order
-of encounter.
-.RM
-Not yet available
-.NH 2
-CLOSE
-.Sy
-CLOSE [[#]<file number>[,[#]<file number...>]]
-.PU
-To terminate I/O on a disk file.
-<file number> is the number associated with the file 
-when it was OPENed (See OPEN). Ommission of parameters results in closing
-all files.
-.sp
-The END statement and STOP statement always issue a CLOSE of
-all files.
-.NH 2
-DATA
-.Sy
-DATA <list of constants>
-.PU
-DATA statements are used to construct a data bank of values that are
-accessed by the program's READ statement.
-DATA statements are non-executable,
-the data items are assembled in a data file by the BASIC compiler.
-This file can be replaced, provided the layout remains
-the same (otherwise the RESTORE won't function properly).
-.sp
-The list of data items consists of numeric and string constants
-as discussed in section 1.
-Moreover, string constants starting with a letter and not
-containing blancs, newlines, commas, colon need not be enclosed with
-the string quotes.
-.sp
-DATA statements can be reread using the RESTORE statement.
-.NH 2
-DEF FN
-.Sy
-DEF FN<name> [(<parameterlist>)]=<expression>
-.PU
-To define and name a function that is written by the user.
-<name> must be an identifier and should be preceded by FN,
-which is considered integral part of the function name. 
-<expression> defines the expression to be evaluated upon function call.
-.sp
-The parameter list is comprised of a comma separated 
-list of variable names, used within the function definition,
-that are to replaced by values upon function call.
-The variable names defined in the parameterlist, called formal
-parameters, do not affect the definition and use of variables
-defined with the same name in the rest of the BASIC program.
-.sp
-A type declaration character may be suffixed to the function name to
-designate the data type of the function result.
-.NH 2
-DEFINT/SNG/DBL/STR
-.Sy
-DEF<type> <range of letters>
-.PU
-Any undefined variable starting with the letter included in the range of
-letters is declared of type <type> unless a type declaration character
-is appended.
-The range of letters is a comma separated list of characters and
-character ranges (<letter>-<letter>).
-.NH 2
-DIM
-.Sy
-DIM <list of subscripted variable>
-.PU
-The DIM statement allocates storage for subscripted variables.
-If an undefined subscripted variable is used 
-the maximum value of the array subscript(s) is assumed to be 10.
-A subscript out of range is signalled by the program (when RCK works)
-The minimum subscript value is 0, unless the OPTION BASE statement has been
-encountered.
-.sp
-All variables in a subscripted variable are initially zero.
-.sp
-BUG. Multi-dimensional arrays MUST be defined.
-.NH 2
-END
-.Sy
-END
-.PU
-END terminates a BASIC program and returns to the UNIX shell.
-An END statement at the end of the BASIC program is optional.
-.NH 2
-ERR and ERL
-.PU
-Whenever an error occurs the variable ERR contains the
-error number and ERL the BASIC line where the error occurred.
-The variables are usually used in error handling routines
-provided by the user.
-.NH 2
-ERROR
-.Sy
-ERROR <integer expression>
-.PU
-To simulate the occurrence of a BASIC error.
-To define your own error code use a value not already in
-use by the BASIC runtime system.
-The list of error messages currently in use 
-can be found in appendix B.
-.NH 2
-FIELD
-.PU
-To be implemented.
-.NH 2
-FOR...NEXT
-.Sy
-FOR <variable>= <low>TO<high>[STEP<size>]
-.br
- ......
-.br
-NEXT [<variable>][,<variable>...]
-.PU
-The FOR statements allows a series of statements to be performed
-repeatedly. <variable> is used as a counter. During the first
-execution pass it is assigned the value <low>,
-an arithmetic expression. After each pass the counter
-is incremented with the step size <size>, an expression.
-Ommission of the step size is intepreted as an increment of 1.
-Execution of the program lines specified between the FOR and the NEXT
-statement is terminated as soon as <low> is greater than <high>
-.sp
-The NEXT statement is labeled with the name(s) of the counter to be
-incremented.
-.sp
-The body of the FOR statement is skipped when the initial value of the
-loop times the sign of the step exceeds the value of the highest value
-times the sign of the step.
-.sp
-The variables mentioned in the NEXT statement may be ommitted, in which case
-the variable of increment the counter of the most recent FOR statement.
-If a NEXT statement is encountered before its corresponding FOR statement,
-the error message "NEXT without FOR" is generated.
-.NH 2
-GET
-.Sy
-GET [#]<file number>[, <record number>]
-.PU
-To be implemented.
-.NH 2
-GOSUB...RETURN
-.Sy
-GOSUB <line number
-  ...
-.br
-RETURN
-.PU
-The GOSUB statement branches to the first statement of a subroutine.
-The RETURN statement cause a branch back to the statement following the
-most recent GOSUB statement.
-A subroutine may contain more than one RETURN statement.
-.sp
-Subroutines may be called recursively. 
-Nesting of subroutine calls is limited, upon exceeding the maximum depth
-the error message "XXXXX" is displayed.
-.NH 2
-GOTO
-.Sy
-GOTO <line number>
-.PU
-To branch unconditionally to a specified line in the program.
-If <line number> does not exists, the compilation error message
-"Line not defined" is displayed.
-.RM
-Microsoft BASIC continues at the first line
-equal or greater then the line specified.
-.NH 2
-IF...THEN
-.Sy
-.br
-IF <expression> THEN {<statements>|<line number>}
-[ELSE {<statements>|<line number>}]
-.br
-.Sy
-IF <expression> GOTO <line number>
-[ELSE {<statements>|<line number>}]
-.PU
-The IF statement is used
-to make a decision regarding the program flow based on the
-result of the expressions.
-If the expression is not zero, the THEN or GOTO clause is
-executed. If the result of <expression> is zero, the THEN or
-GOTO clause is ignored and the ELSE clause, if present is
-executed.
-.br
-IF..THEN..ELSE statements may be nested.
-Nesting is limited by the length of the line.
-The ELSE clause matches with the closests unmatched THEN.
-.sp
-When using IF to test equality for a value that is the
-result of a floating point expression, remember that the
-internal representation of the value may not be exact.
-Therefore, the test should be against a range to
-handle the relative error.
-.RM
-Microsoft BASIC allows a comma before THEN.
-.NH 2
-INPUT
-.Sy
-INPUT [;][<"prompt string">;]<list of variables>
-.PU
-An INPUT statement can be used to obtain values from the user at the
-terminal.
-When an INPUT statement is encountered a question mark is printed
-to indicate the program is awaiting data.
-IF <"prompt string"> is included, the string is printed before the
-the question mark. The question mark is suppressed when the prompt
-string is followed by a comma, rather then a semicolon.
-.sp
-For each variable in the variable a list a value should be supplied.
-Data items presented should be separated by a comma.
-.sp
-The type of the variable in the variable list must aggree with the
-type of the data item entered. Responding with too few or too many
-data items causes the message "?Redo". No assignment of input values
-is made until an acceptable response is given.
-.RM
-The option to disgard the carriage return with the semicolon after the
-input symbol is not yet implemented.
-.NH 2
-INPUT [#]
-.Sy
-INPUT #<file number>,<list of variables>
-.PU
-The purpose of the INPUT# statement is to read data items from a sequential
-file and assign them to program variables.
-<file number> is the number used to open the file for input.
-The variables mentioned are (subscripted) variables.
-The type of the data items read should aggree with the type of the variables.
-A type mismatch results in the error message "XXXXX".
-.sp
-The data items on the sequential file are separated by commas and newlines.
-In scanning the file, leading spaces, new lines, tabs, and
-carriage returns are ignored. The first character encountered 
-is assumed to be the state of a new item.
-String items need not be enclosed with double quotes, provided
-it does not contain spaces, tabs, newlines and commas,
-.RM
-Microsoft BASIC won't assign values until the end of input statement.
-This means that the user has to supply all the information.
-.NH 2
-LET
-.Sy
-[LET]<variable>=<expression>
-.PU
-To assign  the value of an expression to a (subscribted) variable.
-The type convertions as dictated in section 1.X apply.
-.NH 2
-LINE INPUT
-.Sy
-LINE INPUT [;][<"prompt string">;]<string variable>
-.PU
-An entire line of input is assigned to the string variable.
-See INPUT for the meaning of the <"prompt string"> option.
-.NH 2
-LINE INPUT [#]
-.Sy
-LINE INPUT #<file number>,<string variable>
-.PU
-Read an entire line of text from a sequential file <file number>
-and assign it to a string variable.
-.NH 2
-LSET and RSET
-.PU
-To be implemented
-.NH 2
-MID$
-.Sy
-MID$(<string expr1>,n[,m])=<string expr2>
-.PU
-To replace a portion of a string with another string value.
-The characters of <string expr> replaces characters in <string expr1>
-starting at position n. If m is present, at most m characters are copied,
-otherwise all characters are copied.
-However, the string obtained never exceeds the length of string expr1.
-.NH 2
-ON ERROR GOTO
-.Sy
-ON ERROR GOTO <line number>
-.PU
-To enable error handling within the BASIC program.
-An error may result from arithmetic errors, disk problems, interrupts, or
-as a result of the ERROR statement.
-After printing an error message the program is continued at the
-statements associated with <line number>.
-.sp
-Error handling is disabled using ON ERROR GOTO 0.
-Subsequent errors result in an error message and program termination.
-.NH 2
-ON...GOSUB and ON ...GOTO
-.Sy
-ON <expression> GOSUB <list of line numbers>
-ON <expression> GOTO <list of line numbers>
-.PU
-To branch to one of several specified line numbers or subroutines, based
-on the result of the <expression>. The list of line numbers are considered
-the first, second, etc alternative. Branching to the first occurs when
-the expression evaluates to one, to the second alternative on two, etc.
-If the value of the expression in zero or greater than the number of alternatives, processing continues at the first statement following the ON..GOTO 
-(ON GOSUB) statement.
-When the expression results in a negative number the 
-an "Illegal function call" error occurs.
-.NH 2
-OPEN
-.NH 2
-OPTION BASE
-.Sy
-OPTION BASE n
-.PU
-To declare the lower bound of subsequent array subscripts as either
-0 or 1. The default lower bound is zero.
-.NH 2
-POKE
-.Sy
-POKE <expr1>,<expr2>
-.PU
-To poke around in memory. The use of this statement is not recommended,
-because it requires full understanding of both
-the implementation of the Amsterdam
-Compiler Kit and the hardware characteristics.
-.NH 2
-PRINT [USING]
-.NH 2
-PUT
-.PU
-To be implemented
-.NH 2
-RANDOMIZE
-.Sy
-RANDOMIZE [<expression>]
-.PU
-To reset the random seed. When the expression is ommitted, the system
-will ask for a value between -32768 and 32767.
-The random number generator returns the same sequence of values provided
-the same seed is used.
-.NH 2
-READ
-.Sy
-READ <list of variables>
-.PU
-To read values from the DATA statements and assign them to variables.
-The type of the variables should match to the type of the items being read,
-otherwise a "Syntax error" occurs.
-.NH 2
-REM
-.Sy
-REM <remark>
-.PU
-To include explantory information in a program.
-The REM statements are not executed.
-A single quote has the same effect as  : REM, which
-allows for the inclusion of comment at the end of the line.
-.RM
-Microsoft BASIC does not allow REM statements as part of
-DATA lines.
-.NH 2
-RESTORE
-.Sy
-RESTORE  [<line number>]
-.PU
-To allow DATA statements to be re-read from a specific line.
-After a RESTORE statement is executed, the next READ accesses
-the first item of the DATA statements.
-If <line number> is specified, the next READ accesses the first
-item in the specified line.
-.sp
-Note that data statements result in a sequential datafile generated
-by the compiler, being read by the read statements.
-This data file may be replaced using the operating system functions
-with a modified version, provided the same layout of items
-(same number of lines and items per line) is used.
-.NH 2
-STOP
-.Sy
-STOP
-.PU
-To terminate the execution of a program and return to the operating system
-command interpreter. A STOP statement results in the message "Break in line
-???"
-.NH 2
-SWAP
-.Sy
-SWAP <variable>,<variable>
-.PU
-To exchange the values of two variables.
-.NH 2
-TRON/TROFF
-.Sy
-TRON
-.Sy
-TROFF
-.PU
-As an aid in debugging the TRON statement results in a program
-listing each line being interpreted. TROFF disables generation of
-this code.
-.NH 2
-WHILE...WEND
-.Sy
-WHILE <expression>
-  .....
-WEND
-.PU
-To execute a series of BASIC statements as long as a conditional expression
-is true. WHILE...WEND loops may be nested.
-.NH 2
-WRITE 
-.Sy
-WRITE [<list of expressions>]
-.PU
-To write data at the terminal in DATA statement layout conventions.
-The expressions should be separated by commas.
-.NH 2
-WRITE #
-.Sy
-WRITE #<file number> ,<list of expressions>
-.PU
-To write a sequential data file, being opened with the "O" mode.
-The values are being writting using the DATA statements layout conventions.
-.NH
-FUNCTIONS
-.LP
-.IP ABS(X) 12
-Returns the absolute value of expression X
-.IP ASC(X$) 12
-Returns the numeric value of the first character of the string.
-If X$ is not initialized an "Illegal function call" error
-is returned.
-.IP ATN(X) 12
-Returns the arctangent of X in radians. Result is in the range
-of -pi/2 to pi/2.
-.IP CDBL(X) 12
-Converts X to a double precision number.
-.IP CHR$(X) 12
-Converts the integer value X to its ASCII character. 
-X must be in the range of 0 to 127.
-It is used for cursor addressing and generating bel signals.
-.IP CINT(X) 12
-Converts X to an integer by rounding the fractional portion.
-If X is not in the range -32768 to 32767 an "Overflow"
-error occurs.
-.IP COS(X) 12
-Returns the cosine of X in radians.
-.IP CSNG(X) 12
-Converts X to a double precision number.
-.IP CVI(<2-bytes>) 12
-Convert two byte string value to integer number.
-.IP CVS(<4-bytes>) 12
-Convert four byte string value to single precision number.
-.IP CVD(<8-bytes>) 12
-Convert eight byte string value to double precision number.
-.IP EOF[(<file-number>)] 12
-Returns -1 (true) if the end of a sequential file has been reached.
-.IP EXP(X) 12
-Returns e(base of natural logarithm) to the power of X.
-X should be less then 10000.0.
-.IP FIX(X) 12
-Returns the truncated integer part of X. FIX(X) is
-equivalent to SGN(X)*INT(ABS(X)).
-The major difference between FIX and INT is that FIX does not
-return the next lower number for negative X.
-.IP HEX$(X) 12
-Returns the string which represents the hexadecimal value of
-the decimal argument. X is rounded to an integer using CINT
-before HEX$ is evaluated.
-.IP INT(X) 12
-Returns the largest integer <= X.
-.IP INPUT$(X[,[#]Y]) 12
-Returns the string of X characters read from the terminal or
-the designated file.
-.IP LEX(X$) 12
-Returns the number of characters in the string X$.
-Non printable and blancs are counted too.
-.IP LOC(<file\ number>) 12
-For sequential files LOC returns 
-position of the read/write head, counted in number of bytes.
-For random files the function returns the record number just
-read or written from a GET or PUT statement.
-If nothing was read or written 0 is returned.
-.IP LOG(X) 12
-Returns the natural logarithm of X. X must be greater than zero.
-.IP MID$(X,I,[J]) 12
-To be implemented.
-.IP MKI$(X) 12
-Converts an integer expression to a two-byte string.
-.IP MKS$(X) 12
-Converts a single precision expression to a four-byte string.
-.IP MKD$(X) 12
-Converts a double precision expression to a eight-byte string.
-.IP OCT$(X) 12
-Returns the string which represents the octal value of the decimal
-argument. X is rounded to an integer using CINT before OCTS is evaluated.
-.IP PEEK(I) 12
-Returns the byte read from the indicated memory. (Of limited use
-in the context of ACK)
-.IP POS(I) 12
-Returns the current cursor position. To be implemented.
-.IP RIGHT$(X$,I)
-Returns the right most I characters of string X$.
-If I=0 then the empty string is returned.
-.IP RND(X) 12
-Returns a random number between 0 and 1. X is a dummy argument.
-.IP SGN(X) 12
-If X>0 , SGN(X) returns 1.
-.br
-if X=0, SGN(X) returns 0.
-.br
-if X<0, SGN(X) returns -1.
-.IP SIN(X) 12
-Returns the sine of X in radians.
-.IP SPACE$(X) 12
-Returns  a string of spaces length X. The expression
-X is rounded to an integer using CINT.
-.IP STR$(X)
-Returns the string representation value of X.
-.IP STRING$(I,J) 12
-Returns thes string of length Iwhose characters all
-have ASCII code J. (or first character when J is a string)
-.IP TAB(I) 12
-Spaces to position I on the terminal. If the current
-print position is already beyond space I,TAB
-goes to that position on the next line.
-Space 1 is leftmost position, and the rightmost position
-is width minus 1. To be used within PRINT statements only.
-.IP TAN(X) 12
-Returns the tangent of X in radians. If TAN overflows
-the "Overflow" message is displayed.
-.IP VAL(X$) 12
-Returns the numerical value of string X$.
-The VAL function strips leading blanks and tabs from the
-argument string.
-.SH
-APPENDIX A DIFFERENCES WITH MICROSOFT BASIC
-.LP
-The following list of Microsoft commands and statements are
-not recognized by the compiler.
-.DS
-SPC
-USR
-VARPTR
-AUTO
-CHAIN
-CLEAR	
-CLOAD
-COMMON
-CONT
-CSAVE
-DELETE
-EDIT
-ERASE
-FRE
-KILL
-LIST
-LLIST
-LOAD
-LPRINT
-MERGE
-NAME
-NEW
-NULL
-RENUM
-RESUME
-RUN
-SAVE
-WAIT
-WIDTH LPRINT
-.DE
-Some statements are in the current implementation not available,
-but will be soon. These include:
-.DS
-CALL
-DEFUSR
-FIELD
-GET
-INKEY
-INPUT$
-INSTR$
-LEFT$
-LSET
-RSET
-PUT
-.DE

+ 0 - 1857
doc/cg.doc

@@ -1,1857 +0,0 @@
-.\" $Header$
-.RP
-.TL
-The table driven code generator from 
-.br
-the Amsterdam Compiler Kit
-.AU
-Hans van Staveren
-.AI
-Dept. of Mathematics and Computer Science
-Vrije Universiteit
-Amsterdam, The Netherlands
-.AB
-It is possible to automate the process of compiler building
-to a great extent using collections of tools.
-The Amsterdam Compiler Kit is such a collection of tools.
-This document provides a description of the internal workings
-of the table driven code generator in the Amsterdam Compiler Kit,
-and a description of syntax and semantics of the driving table.
-.AE
-.NH 1
-Introduction
-.PP
-Part of the Amsterdam Compiler Kit is a code generator system consisting
-of a code generator generator (\fIcgg\fP for short) and some machine
-independent C code.
-.I Cgg
-reads a machine description table and creates two files,
-tables.h and tables.c.
-These are then used together with other C code to produce
-a code generator for the machine at hand.
-.PP
-This in turn reads compact EM code and produces
-assembly code.
-The remainder of this document will first broadly describe
-the working of the code generator,
-then a description of the machine table follows after which
-the internal workings of the code generator will be explained.
-.PP
-The reader is assumed to have at least a vague notion about the
-semantics of the intermediary EM code.
-Someone wishing to write a table for a new machine
-should be thoroughly acquainted with EM code
-and the assembly code of the machine at hand.
-.NH 1
-Global overview of the workings of the code generator.
-.PP
-The code generator or
-.I cg
-tries to generate good code by simulating the runtime stack
-of the program compiled and delaying emission of code as long
-as possible.
-It also keeps track of register contents, which enables it to
-eliminate redundant moves, and tries to eliminate redundant tests
-by keeping information about condition code status,
-if applicable for the machine.
-.PP
-.I Cg
-maintains a `fakestack' containing `tokens' that are built
-by executing the pseudo code contained in the code rules given
-by the table writer.
-One can think of the fakestack as a logical extension of the real
-stack the program compiled will have when run.
-During code generation tokens will be kept on the fakestack as long
-as possible but when they are moved to the real stack,
-by generating code for the push,
-all tokens above\u*\d
-.FS
-* in the rest of this document the stack is assumed to grow downwards,
-although the top of the stack will mean the first element that will
-be popped.
-.FE
-the tokens pushed will be pushed also,
-so that the fakestack will not contain holes.
-.PP
-The main loop of
-.I cg
-is this:
-.IP 1)
-find a pattern of EM instructions starting at the current one to
-generate code for.
-This pattern will usually be of length one but longer patterns can be used.
-.IP 2)
-Select one of the possibly many stack patterns that go with this
-EM pattern on the basis of heuristics and/or lookahead.
-.IP 3)
-Force the current fakestack contents to match the pattern.
-This may involve
-copying tokens to registers, making dummy transformations, e.g. to
-transform a "local" into an "register offsetted" or might even
-cause to have the complete fakestack contents put to the real stack
-and then back into registers if no suitable transformations
-were provided by the table writer.
-.IP 4)
-Execute the pseudocode associated with the code rule just selected,
-this may cause registers to be allocated,
-code to be emitted etc..
-.IP 5)
-Put tokens onto the fakestack to reflect the result of the operation.
-.IP 6)
-Insert some EM instructions into the stream,
-this is possible but not common.
-.IP 7)
-Account for the cost.
-The cost is kept in a (space, time) vector and lookahead decisions
-are based on a linear combination of these.
-.PP
-The table that drives
-.I cg
-is not read in every time,
-but instead is used at compiletime
-of
-.I cg
-to set parameters and to load pseudocode tables.
-A program called
-.I cgg
-reads the table and produces large lists of numbers that are
-compiled together with machine independent code to produce
-a code generator for the machine at hand.
-.NH 1
-Description of the machine table
-.PP
-The machine description table consists of the following sections:
-.IP 1)
-Constant definitions
-.IP 2)
-Register definitions
-.IP 3)
-Token definitions
-.IP 4)
-Token expression definitions
-.IP 5)
-Code rules
-.IP 6)
-Move definitions
-.IP 7)
-Test definitions
-.IP 8)
-Stacking definitions
-.PP
-Input is in free format, white space and newlines may be used
-at will to improve legibility.
-Identifiers used in the table have the same syntax as C identifiers,
-upper and lower case considered different, all characters significant.
-There is however one exception:
-identifiers must be more than one character long for parsing reasons.
-C style comments are accepted
-.DS
-	/* this is a comment */
-.DE
-and #define macros may be used if the need arises.
-.NH 2
-Some constants
-.PP
-Before anything else three constants must be defined,
-all with the syntax NAME=value, value being an integer.
-These constants are:
-.IP EM_WSIZE 10
-Number of bytes in a machine word.
-This is the number of bytes
-a simple \fBloc\fP instruction will put on the stack.
-.IP EM_PSIZE
-Number of bytes in a pointer.
-This is the number of bytes
-a \fBlal\fP instruction will put on the stack.
-.IP EM_BSIZE
-Number of bytes in the hole between AB and LB.
-If the calling sequence just saves PC and LB this
-size will be twice the pointersize.
-.PP
-EM_WSIZE and EM_PSIZE are checked when a program is compiled
-with the resulting code generator.
-EM_BSIZE is used by
-.I cg
-to add to the offset of instructions dealing with locals
-having positive offsets,
-i.e. parameters.
-.PP
-Optionally one can give here the factors with which the size and time
-parts of the cost function have to be multiplied to ensure they have the
-same order of magnitude.
-This can be done as
-.DS
-TIMEFACTOR = C\d1\u/C\d2\u
-SIZEFACTOR = C\d3\u/C\d4\u
-.DE
-Above numbers must be read as rational numbers.
-Defaults are 1/1 for both of them.
-These constants set the default size/time tradeoff in the code generator,
-so if TIMEFACTOR and SIZEFACTOR are both 1 the code generator will choose
-at random between two codesequences where one has
-cost (10,4) and the other has cost (8,6).
-See also the description of the cost field below.
-.PP
-Also optional is the definition of a printformat for integers in the codefile.
-This is given as
-.DS
-FORMAT = string
-.DE
-The default for string is "%d" or "%ld" depending on the wordsize of 
-the machine. For example on the PDP 11 one can use
-.DS
-FORMAT= "0%o"
-.DE
-to satisfy the old UNIX assembler that reads octal unless followed by
-a period, and the ACK assembler that follows C conventions.
-.NH 2
-Register definition
-.PP
-The next part of the tables describes the various registers of the
-machine and defines identifiers
-to be used in later parts of the tables.
-Example for the PDP-11:
-.DS L
-REGISTERS:
-R0 = ( "r0",2), REG.
-R1 = ( "r1",2), REG, ODDREG.
-R2 = ( "r2",2), REG.
-R3 = ( "r3",2), REG, ODDREG.
-R4 = ( "r4",2), REG.
-LB = ( "r5",2), LOCALBASE.
-R01= ( "r0",4,R0,R1), REGPAIR.
-R23= ( "r2",4,R2,R3), REGPAIR.
-FR0= ( "r0",4), FREG.
-FR1= ( "r1",4), FREG.
-FR2= ( "r2",4), FREG.
-FR3= ( "r3",4), FREG.
-DR0= ( "r0",8,FR0), DREG.
-DR1= ( "r1",8,FR1), DREG.
-DR2= ( "r2",8,FR2), DREG.
-DR3= ( "r3",8,FR3), DREG.
-.DE
-.PP
-The identifier before the '=' sign is the name of the register
-as used further on in the table.
-The string is the name of the register as far as the assembler is concerned.
-The number is the size of the register in bytes.
-Identifiers following the number but within the parentheses are previously
-defined registernames that are contained in the register being defined.
-The identifiers following the closing parenthesis are properties
-of the register.
-So for example R23 is a register with assembler name r2, 4 bytes long,
-contains the registers R2 and R3 and has the property REGPAIR.
-.PP
-It might seem wise to list each and every property of a register,
-so one might give R0 the extra property MFPTREG named after the not
-too well known MFPT instruction on newer PDP-11 types,
-but this is not a good idea.
-Every extra property means the registerset is more unorthogonal
-and 
-.I cg
-execution time is influenced by that,
-because it has to take into account a larger set of registers
-that are not equivalent.
-.PP
-There is a predefined property SCRATCH that is dynamic,
-i.e. a register can have the property SCRATCH one time,
-and loose it the next.
-A register has the property SCRATCH when it has a reference count of one.
-One needs to be able to discriminate between SCRATCH registers
-and others,
-because it is only allowed to do arithmetic on
-SCRATCH registers.
-.NH 2
-Stack token definition
-.PP
-The next part describes all possible tokens that can reside on
-the fakestack during code generation.
-Attributes of a token are described in the form of a C struct declaration,
-this is followed by the size in bytes of the token,
-optionally followed by the cost of the token when used as an addressing mode
-and the format
-to be used on output.
-.PP
-Tokens should usually be declared for every addressing mode
-of the machine at hand and for every size directly usable in
-a machine instruction.
-Example for the PDP-11 (incomplete):
-.DS L
-TOKENS:
-IREG2 =		{ REGISTER reg; } 2 "*%[reg]" /* indirect register */
-REGCONST =	{ REGISTER reg; STRING off; } 2 /* not really addressable */
-REGOFF2 =	{ REGISTER reg; STRING off; } 2 "%[off](%[reg])"
-IREGOFF2 =	{ REGISTER reg; STRING off; } 2 "*%[off](%[reg])"
-CONST =		{ INT off; } 2 cost=(2,850) "$%[off]."
-EXTERN2 =	{ STRING off; } 2 "%[off]"
-IEXTERN2 =	{ STRING off; } 2 "*%[off]"
-PAIRSIGNED =	{ REGISTER regeven,regodd; } 2 "%[regeven]"
-.DE
-.PP
-Types allowed in the struct are REGISTER, INT and STRING.
-Tokens without a printformat should never be output.
-.PP
-Notice that tokens need not correspond to addressing modes,
-the REGCONST token listed above,
-meaning the sum of the contents of the register and the constant,
-has no corresponding addressing mode on the PDP-11,
-but is included so that a sequence of add constant, load indirect,
-can be handled efficiently.
-This REGCONST token is needed as part of the path
-.DS
-REGISTER -> REGCONST -> REGOFF
-.DE
-of which the first and the last "exist" and the middle is needed
-only as an intermediate step.
-.NH 2
-Token expressions
-.PP
-Usually machines have certain collections of addressing modes that
-can be used with certain instructions.
-The stack patterns in the table are lists of these collections
-and since it is cumbersome to write out these long lists
-every time, there is a section here to give names to these
-collections.
-Please note that it is not forbidden to write out a token expression
-in the remainder of the table,
-but for clarity it is usually better not to.
-Example for the PDP-11 (incomplete):
-.DS L
-TOKENEXPRESSIONS:
-SOURCE2 = REG + IREG2 + REGOFF2 + IREGOFF2 + CONST + EXTERN2 +
-	  IEXTERN2
-SREG    = REG * SCRATCH
-.DE
-Permissible in the expressions are all PASCAL set operators, i.e.
-.IP +
-set union
-.IP -
-set difference
-.IP *
-set intersection
-.PP
-Every tokenidentifier is also a token expression identifier
-denoting the singleton collection of tokens containing
-just itself.
-Every register property as defined above is also a token expression
-matching all registers with that property when on the fakestack.
-The standard token expression identifier ALL denotes the collection of 
-all tokens.
-.NH 2
-Expressions
-.PP
-Throughout the rest of the table expressions can be used in some
-places.
-This section will give the syntax and semantics of expressions.
-There are four types of expressions: integer, string, register and undefined.
-Type checking is performed by
-.I cgg .
-An operator with at least one undefined operand returns undefined except
-for the defined() function mentioned below.
-An undefined expression is interpreted as FALSE when it is needed
-as a truth value.
-Basic terms in an expression are
-.IP number 16
-A number is a constant of type integer.
-.IP "string"
-A string within double quotes is a constant of type string.
-All the normal C style escapes may be used within the string.
-.IP REGIDENT
-The name of a register is a constant of type register.
-.IP $\fIi\fP
-A dollarsign followed by a number is the representation of the argument
-of EM instruction \fI\fP.
-The type of the operand is dependent on the instruction,
-sometimes it is integer,
-sometimes it is string.
-It is undefined when the instruction has no operand.
-.br
-Although an exhaustive list could be given describing all the types
-the following rule of thumb will suffice.
-If you cannot imagine the operand of the instruction ever to be
-something different from a plain integer, the type is integer,
-otherwise it is string.
-.br
-.I Cg
-makes all necessary conversions for you,
-like adding EM_BSIZE to positive arguments of instructions
-dealing with locals,
-prepending underlines to global names,
-converting codelabels into a unique representation etc.
-Details about this can be found in the section about
-machine dependent C code.
-.IP %[1]
-This in general means the token mentioned first in the
-stack pattern.
-When used inside an expression the token must be a simple register.
-Type of this is register.
-.IP %[1.off]
-This means field "off" of the first stack pattern token.
-Type is the same as that of field "off".
-To use this expression implies a check that all tokens
-in the token expression used have the same attributes.
-.IP %[1.1]
-This is the first subregister of the first token.
-Previous comments apply.
-.IP %[b]
-The second allocated register.
-.IP %[a.2]
-The second subregister of the first allocated register.
-.PP
-All normal C operators apply to integers,
-the + operator serves for string concatenation
-and register expressions can only be compared to each other.
-Furthermore there are some special "functions":
-.IP tostring(e) 16
-Converts an integer expression e to a string.
-.IP defined(e)
-Returns 1 if expression e is defined, 0 otherwise.
-.IP samesign(e1,e2)
-Returns 1 if integer expression e1 and e2 have the same sign.
-.IP sfit(e1,e2)
-Returns 1 if integer expression e1 fits as a signed integer
-into a field of e2 bits, 0 otherwise.
-.IP ufit(e1,e2)
-Same as above but now for unsigned e1.
-.IP rom(a,n)
-Integer expression giving the n'th argument from the \fBrom\fP descriptor
-pointed at by the a'th EM instruction.
-Undefined if that descriptor does not exist.
-.IP loww(a)
-Returns the lower half of the argument of the a'th EM instruction.
-This is used to split the arguments of a \fBldc\fP instruction.
-.IP highw(a)
-Same for upper half.
-.NH 2
-Code rules
-.PP
-The largest section of the tables consists of the code generation rules.
-They specify EM patterns, stack patterns, code to be generated etc.
-Syntax is
-.DS L
-code rule : EM pattern '|' stack pattern '|' code '|' 
-	   stack replacement '|' EM replacement '|' cost ;
-.DE
-All parts are optional, however there must be at least one pattern present.
-If the empattern is missing the rule becomes a rewriting rule or
-.I coercion
-to be used when code generation cannot continue 
-because of an invalid stack pattern.
-The code rules are preceded by the word
-.DS
-CODE:
-.DE
-The next paragraphs describe the various parts in detail.
-.NH 3
-The EM pattern
-.PP
-The EM pattern consists of a list of EM mnemonics followed
-by a boolean expression.
-Examples:
-.DS
-\fBloe\fP
-.DE
-will match a single \fBloe\fP instruction,
-.DS
-\fBloc\fP \fBloc\fP \fBcif\fP $1==2 && $2==8
-.DE
-is a pattern that will match
-.DS
-\fBloc\fP 2
-\fBloc\fP 8
-\fBcif\fP
-.DE
-and
-.DS
-\fBlol\fP \fBinc\fP \fBstl\fP $1==$3
-.DE
-will match for example
-.DS
-.ta 10m 20m 30m 40m 50m 60m
-\fBlol\fP 6	\fBlol\fP -2		\fBlol\fP 4
-\fBinc\fP	\fBinc\fP	but \fInot\fP	\fBinc\fP
-\fBstl\fP 6	\fBstl\fP -2		\fBstl\fP -4
-.DE
-A missing boolean expression evaluates to TRUE.
-.PP
-When the EM pattern is the same as in the previous code rule the pattern
-should be given as `...'.
-The code generator will match the longest EM pattern on every occasion,
-if two patterns of the same length match the first in the table will be chosen,
-while all patterns of length greater than or equal to three are considered
-to be of the same length.
-.NH 3
-The stack pattern
-.PP
-The stack pattern is a list of token expressions,
-usually token expression identifiers for clarity.
-No boolean expression is allowed here.
-The first expression is the one that matches the top of the stack.
-.PP
-The pattern can be followed by the word STACK
-in which case the pattern only matches if there is nothing
-else on the fakestack.
-The code generator will stack everything not matched at the start
-of the rule.
-.PP
-The pattern can be preceded with the word
-.DS
-nocoercions:
-.DE
-which tells the code generator not to try to coerce to the pattern
-but only to use it when it is already there.
-There are two reasons for this construction,
-correctness and speed.
-It is needed for correctness when the pattern contains a register
-that is not transparent when data is moved through it.
-.PP
-Example: on the PDP-11 the shortest code for
-.DS
-\fBlae\fP a
-\fBloi\fP 8
-\fBlae\fP b
-\fBsti\fP 8
-.DE
-is
-.DS
-movf _a,fr0
-movf fr0,_b
-.DE
-assuming that the floating point processor is in double
-precision mode and fr0 is free.
-Unfortunately this is not correct since a trap can occur on certain
-kinds of data.
-This could happen if there was a pattern for \fBsti\fP\ 8 that allowed
-one to move a floating point register not preceded by nocoercions: .
-The code generator would then find that moving the 8-byte global _a
-to a floating point register and then storing it to _b was the cheapest,
-assuming that the space/time knob was turned far enough to space.
-It is unfortunate that the type information is no longer present,
-since if _a really is a floating point number the move could be
-made without error.
-.PP
-The second reason for the nocoercions: construct is speed.
-When the code generator has a long list of possible stack patterns
-for one EM pattern it can waste a lot of time trying to find coercions
-to all of them, while the mere presence of such a long list
-indicates that the table writer has given a lot of special cases.
-In this case prepending all the special cases by nocoercions:
-will stop the code generator from trying to find things there aren't.
-.NH 3
-The code part
-.PP
-The code part consists of three parts, stack cleanup, register allocation
-and code to generate.
-All of these may be omitted.
-.NH 4
-Stack cleanup
-.PP
-The stack cleanup part describes certain stacktokens that should neither remain on
-the fakestack, nor remembered as contents of registers.
-This is usually only required with store operations.
-The entire fakestack, except for the part matched in the stack pattern,
-is searched for tokens matching the expression and they are copied
-to the real stack.
-Every register that contains the stacktoken is marked as empty.
-.PP
-Syntax is
-.DS
-remove(token expression) \fIor\fP
-remove(token expression, boolean expression)
-.DE
-Example:
-.DS
-remove(REGOFF2,%[reg] != LB || %[off] == $1)
-.DE
-is part of a remove() call for use in the \fBstl\fP code rule.
-It removes all register offsetted tokens where the register is not the
-localbase plus the local wherein the store is done.
-The necessity for this can be seen from the following example:
-.DS
-\fBlol\fP 4
-\fBinl\fP 4
-\fBstl\fP 6
-.DE
-Without a proper remove() call in the rule for \fBinl\fP code would
-be generated as here
-.DS
-inc 4(r5)
-mov 4(r5),6(r5)
-.DE
-so local 6 would be given the new value of local 4 instead of the old
-as the EM code prescribed.
-.PP
-When generating something like a branch instruction it 
-might be needed to empty the fakestack completely.
-This can of course be done with
-.DS
-remove(ALL)
-.DE
-.NH 4
-Register allocation
-.PP
-The register allocation part describes the kind of registers needed.
-Syntax for allocate() is
-.DS
-allocate(itemlist)
-.DE
-where itemlist is a list of three kinds of things:
-.IP 1)
-a tokendescription, for example %[1].
-.br
-This will instruct the code generator to temporarily decrement the reference count 
-of all registers contained in the token,
-so that they are available for allocation in this allocate() call
-if they were only used in that token.
-See example below.
-.IP 2)
-a register property.
-.br
-This will allocate a register with that property.
-The register will be marked as empty at this point.
-Lookahead will be performed if necessary.
-.IP 3)
-a register property with initialization.
-.br
-This will allocate the register as in 2) but will also
-initialize it.
-This eases the task of the code generator because it can
-find a register already filled with the right value
-if it exists.
-.PP
-Examples:
-.DS
-allocate(OREG)
-.DE
-will allocate an odd register, while 
-.DS
-allocate(REG={REGOFF2,LB,$1})
-.DE
-will allocate a register while simultaneously filling it with
-the asked value.
-.br
-Inside the coercion from SOURCE2 to REGISTER in the PDP-11 table
-the following allocate() can be found.
-.DS
-allocate(%[1],REG=%[1])
-.DE
-This tells the code generator that registers contained in %[1] can be used
-again and asks to fill the register allocated with %[1].
-So if %[1]={REGOFF2,R3,"4"} and R3 has a reference count of 1
-the following code might be generated.
-.DS
-mov 4(r3),r3
-.DE
-In the rest of the line the registers allocated can be named by
-%[a] and %[b.1],%[b.2], i.e. with lower case letters
-in order of allocation.
-.PP
-Warning: 
-.DS
-allocate(R3)
-.DE
-is \fRnot\fP the way to allocate R3.
-R3 is not a register property, so it will be seen as a token description
-and the effect is that R3 will have its reference count decremented.
-.NH 4
-Code
-.PP
-Code to be generated is specified as a list of items of the following kind:
-.IP 1)
-a string in double quotes ("This is a string").
-.br
-This is copied to the codefile and a newline ( \en ) is appended.
-Inside the string all normal C string conventions are allowed,
-and substitutions can be made of the following sorts.
-.RS
-.IP a)
-$1, $2 etc.
-These are the operands of the corresponding EM instructions
-and are printed according to their type.
-To put a real '$' inside the string it must be doubled ('$$').
-.IP b)
-%[1], %[2.reg], %[b.1] etc.
-These have their obvious meaning.
-If they describe a complete token ( %[1] )
-the printformat for the token is used.
-If they stand for a basic term in an expression
-they will be printed according to their type.
-To put a real '%' inside the string it must be doubled ('%%').
-.IP c)
-%( arbitrary expression %).
-This allows inclusion of arbitrary expressions inside strings.
-Usually not needed very often,
-so that the awkward notation is not too bad.
-Note that %(%[1]%) is equivalent to %[1].
-.RE
-.IP 2)
-a move() call.
-This has the following syntax:
-.DS
-move(token description, token description)
-.DE
-Moves are handled specially since that enables the code generator
-to keep track of register contents.
-Example:
-.DS
-move(R3,{REGOFF2,LB,$1})
-.DE
-will generate code to move R3 to $1(r5) except when
-R3 already was a copy of $1(r5).
-Then the code will be omitted.
-The rules describing how to move things to each other
-can be found in the MOVES section described below.
-.IP 3)
-an erase() call.
-This has the following syntax:
-.DS
-erase(register expression)
-.DE
-This tells the code generator that the register mentioned no longer has any
-useful value.
-This is 
-.I necessary
-after code in the table has changed the contents of registers.
-For example, after an add to a register the register must be erased,
-because the contents do no longer match any token.
-.IP 4)
-For machines that have condition codes,
-alas most of them do,
-there are provisions to remember condition code setting
-and prevent needless testing.
-To set the condition code to a token put in the code the following call:
-.DS
-test(token)
-.DE
-where token can be all of the standard forms that can also be used in move().
-This will generate a test if the condition codes 
-were not already set to that token.
-It is also possible to tell 
-.I cg
-that a certain operation, like a preceding add
-has set the condition codes to some token with the call
-.DS
-setcc(token)
-.DE
-So a sequence of a setcc and a test on the same token will generate
-no code. 
-Another allowed call within the code is
-.DS
-samecc
-.DE
-which tells the code generator that condition codes were unaffected
-in this rule.
-If no setcc or samecc has been given the default is
-.DS
-nocc
-.DE
-when a piece of code contained strings,
-which tells the code generator that the condition codes
-have no useful value any more.
-.NH 3
-Stack replacement
-.PP
-The stack replacement is a possibly empty list of items to be pushed onto
-the fakestack. Three kinds of items are possible:
-.IP 1)
-An item of the form %[1]. This will push the stacktoken mentioned back
-onto the stack unchanged.
-.IP 2)
-A register expression. This will push the register mentioned
-onto the fakestack.
-.IP 3)
-An item of the form { REGOFF2,%[1.reg],$1 }.
-This generates a token with tokenidentifier REGOFF2 and attributes 
-in order of declaration.
-.PP
-All tokens matched by the stack pattern at the beginning of the code rule
-are first removed and their registers deallocated.
-Items are pushed in the order of appearance.
-This means that the last item will be on the top of the
-stack after the push.
-So if the stack pattern contained two token expressions
-and you want to push them back unchanged,
-you have to specify as stack replacement
-.DS
-%[2] %[1]
-.DE
-and not the other way around.
-.NH 3
-EM replacement
-.PP
-In exceptional cases it might be useful to leave part of an empattern
-undone.
-For example, a \fBsdl\fP instruction might be split into two \fBstl\fP instructions
-when there is no 4-byte quantity on the stack. The emreplacement part allows
-one to express this.
-Example:
-.DS
-\fBstl\fP $1 \fBstl\fP $1+2
-.DE
-The instructions are inserted in the stream so that they can match
-the first part of a pattern in the next step.
-Note that since the code generator traverses the EM instructions in a strict
-linear fashion,
-it is impossible to let the EM replacement match later parts of a pattern.
-So if there is a pattern
-.DS
-\fBloc\fP \fBstl\fP $1==0
-.DE
-and the input is
-.DS
-\fBloc\fP 0 \fBsdl\fP 4
-.DE
-the \fBloc\fP\ 0 will be processed first,
-then the \fBsdl\fP might be split into two \fBstl\fP's but the pattern
-cannot match now.
-.NH 3
-Cost
-.PP
-The cost field can be specified when there is more than one
-code rule with the same empattern.
-If the code generator has a choice between two possibilities
-to generate code it will choose the cheapest according to
-the cost field.
-The cost for a code generation is the sum of the costs
-of all the coercions needed, plus the cost for freeing
-registers plus the cost of the code rule itself.
-.PP
-The format of the costfield is
-.DS
-( nbytes, time )		or
-( nbytes, time ) + %[\fIi\fP]
-.DE
-with time in the metric desired, like nanoseconds or states.
-See constants section above.
-The %[\fIi\fP] in the second example is used for adding the cost of a certain
-address mode used in the code generated.
-This can of course be repeated if desired.
-The cost of the address mode must then be specified in the token definition
-section.
-.NH 3
-Examples
-.PP
-A list of examples for the PDP-11 is given here.
-Far from being complete it gives examples of most kinds
-of instructions.
-.DS L
-\fBadi\fP $1==2 | SREG,SOURCE2 |
-	"add %[2],%[1]" erase(%[1]) setcc(%[1])
-	  | %[1] | | (2,450) + %[2]
-\&...       | SOURCE2,SREG |
-	"add %[1],%[2]" erase(%[2]) setcc(%[2])
-	  | %[2] | | (2,450) + %[1]
-.DE
-is an example of the use of the `...' construct
-and shows how to place erase() and setcc() calls.
-.DS L
-
-\fBdvi\fP $1==2 | SOURCE2,SPAIRSIGNED |
-	"div %[1],%[2]" erase(%[2])
-	  | %[2.regeven] | |
-
-\fBcmi\fP \fBtgt\fP $1==2 | SOURCE2,SOURCE2 | allocate(REG={CONST,0})
-	"cmp %[2],%[1];ble 1f;inc %[a];1:" erase(%[a])
-	  | %[a] | |
-
-\fBcal\fP | STACK |
-	"jsr pc,$1" 
-	  | | |
-
-\fBlol\fP | | | { REGOFF2, LB, $1 } | |
-
-\fBstl\fP | SOURCE2 |
-	remove(REGOFF2,%[off]==$1)
-	move(%[1],{REGOFF2,LB,$1})
-	  | | |
-
-| SOURCE2 |
-	allocate(%[1],REGPAIR)
-	move(%[1],%[a.2])
-	test(%[a.2])
-	"sxt %[a.even]" | { PAIRSIGNED, %[a.1], %[a.2] }| | 
-.DE
-This coercion shows how to use the move and test calls.
-At first you might think that the testcall is unnecessary,
-since the move will have set the condition codes,
-but the move may never have been executed
-if the register already contained the value,
-in which case it is necessary to do the test.
-If the move was executed the test will be omitted.
-.DS L
-| SOURCE2 | allocate(%[1],REG=%[1]) | %[a] | |
-
-\fBsdl\fP | SOURCE2 | | %[1] | \fBstl\fP $1 \fBstl\fP $1+2 |
-
-\fBexg\fP $1==2 | SOURCE2 SOURCE2 | | %[1] %[2] | |
-.DE
-This last example again shows the difference in the order
-of the stack pattern and the stack replacement.
-.NH 2
-Move code rules
-.PP
-When issuing a move() call as described above or a register allocation
-with initialization, the code generator has to know which
-instruction to use for the move.
-The code will of course only be generated if it cannot be omitted.
-This is listed in the move section of the tables by giving a list
-of tuples:
-.DS
-( source, destination, codepart [ , costfield ] )
-.DE
-where the square brackets mean the costfield is optional.
-Example for the PDP-11
-.DS
-MOVES:
-( CONST %[off]==0 , SOURCE2, "clr %[2]" )
-( SOURCE2, SOURCE2, "mov %[1],%[2]" )
-.DE
-The moves are scanned from top to bottom,
-so the first one that matches will be chosen.
-.NH 2
-Test code rules
-.PP
-When issuing a test() call as described above,
-the code generator has to know which instruction
-to use for the test.
-The code will only be generated if the condition codes
-were not already set to the token.
-This is listed in the test section of the tables by giving
-a list of tuples:
-.DS
-( source, codepart [ , costfield ] )
-.DE
-Example for the PDP-11
-.DS
-TESTS:
-( SOURCE2, "tst %[1]")
-( DREG, "tstf %[1]\encfcc")
-.DE
-The tests are scanned from top to bottom,
-so the first one that matches will be chosen.
-.NH 2
-Stacking code rules.
-.PP
-When the code generator has to stack a token it must know
-which code to use.
-Since it must at all times be possible to empty the fakestack
-even when no registers are free,
-it is mandatory that all
-tokens used must have a rule attached for stacking them
-without using a scratch register.
-Since however this might be clumsy and 
-a register might in practice be available
-it is also possible to give rules
-which use a register.
-On the Intel 8086 for example,
-there is no instruction to push a constant without using a register,
-and the code needed to do it without, must use global data
-and as such is very complicated and wasteful of memory and time.
-It can therefore be left to be used in extreme cases,
-while in general the constant is pushed through a register.
-The stacking rules are listed in the stack section of the table as a list
-of tuples:
-.DS
-(source, [ register property ] , codepart [ , costfield ] )
-.DE
-Example for the Intel 8086:
-.DS
-STACKS:
-(CONST, REG, move(%[1],%[a]) "push %[a]")
-(REG ,, "push %[1]")
-.DE
-.NH 1
-The files mach.h and mach.c
-.PP
-The table writer must also supply two files containing
-machine dependent declarations and C code.
-These files are mach.h and mach.c.
-.NH 2
-Types in the code generator
-.PP
-Three different types of integer coexist in the code generator
-and their range depends on the machine at hand.
-The type 'int' is used for things like labelcounters that won't require
-more than 16 bits precision.
-The type 'word' is used among others to assemble datawords and
-is of type 'long' if EM_WSIZE>2.
-The type 'full' is used for addresses and is of type 'long' if
-EM_WSIZE>2 or EM_PSIZE>2.
-.PP
-In macro and function definitions in later paragraphs implicit typing
-will be used for parameters, that is parameters starting with an 's'
-will be of type string, and the letters 'i','w','f' will stand for
-int, word and full respectively.
-.NH 2
-Global variables to work with
-.PP
-Some global variables are present in the code generator
-that can be manipulated by the routines in mach.h and mach.c.
-.LP
-The declarations are:
-.DS L
-.ta 20
-FILE *codefile;	/* code is emitted on this stream */
-word part_word;	/* words to be output are put together here */
-int part_size;	/* number of bytes already put in part_word */
-char str[];	/* Last string read in */
-long argval;	/* Last int read and kept */
-.DE
-.NH 2
-Macros in mach.h
-.PP
-In the file mach.h a collection of macros is defined that have
-to do with formatting of assembly code for the machine at hand.
-Some of these macros can of course be left undefined in which case the
-macro calls are left in the source and will be treated as 
-function calls.
-These functions can then be defined in \fImach.c\fR.
-.PP
-The macros to be defined are:
-.IP ex_ap(s) 16
-Must print the magic incantations that will mark the symbol \fI\fR
-to be exported to other modules.
-This is the translation of the EM \fBexa\fP and \fBexp\fP instructions.
-.IP in_ap(s)
-Same to import the symbol.
-Translation of \fBina\fP and \fBinp\fP.
-.IP newplb(s)
-Must print the definition of procedure label \fIs\fR.
-If left undefined the newilb() macro is used instead.
-.IP newilb(s)
-Must print the definition of instruction label \fIs\fR.
-.IP newdlb(s)
-Must print the definition of data label \fIs\fR.
-.IP dlbdlb(s1,s2)
-Must define data label
-.I s1
-to be equal to
-.I s2 .
-.IP newlbss(s,f)
-Must declare a piece of memory initialized to BSS_INIT(see below)
-of length 
-.I f
-and with label
-.I s .
-.IP cst_fmt
-Format to be used when converting constant arguments of
-EM instructions to string.
-Argument to be formatted will be 'full'.
-.IP off_fmt
-Format to be used for integer part of label+constant,
-argument will be 'full'.
-.IP fmt_ilb(ip,il,s)
-Must use the numbers 
-.I ip
-and 
-.I il
-which are a procedure number
-and a label number respectively and copy a string to
-.I s
-that must be unique for that combination.
-This procedure is optional, if it is not given ilb_fmt
-must be defined as below.
-.IP ilb_fmt
-Format to be used for creation of unique instruction labels.
-Arguments will be a unique procedure number (int) and the label
-number (int).
-.IP dlb_fmt
-Format to be used for printing numeric data labels.
-Argument will be 'int'.
-.IP hol_fmt
-Format to be used for generation of labels for
-space generated by a
-.B hol
-pseudo.
-Argument will be 'int'.
-.IP hol_off
-Format to be used for printing of the address of an element in
-.B hol
-space.
-Arguments will be the offset in the
-.B hol
-block (word) and the number of the
-.B hol
-(int).
-.IP con_cst(w)
-Must generate output that will assemble into one machineword.
-.IP con_ilb(s)
-Must generate output that will put the address of the instruction label
-into the datastream.
-.IP con_dlb(s)
-Must generate output that will put the address of the data label
-into the datastream.
-.IP fmt_id(sf,st)
-Must take the string in
-.I sf
-which is a nonnumeric global label, and transform it into a copy made to
-.I st
-which will not collide with reserved assembler words and system labels.
-This procedure is optional, if it is not given the id_first macro is used
-as defined below.
-.IP id_first
-Must be a character.
-This is prepended to all nonnumeric global labels if their length
-is shorter than the maximum allowed(currently 8) or if they already
-start with that character.
-This is to avoid conflicts of user labels with system labels.
-.IP BSS_INIT
-Must be a constant.
-This is the value filled in all the words not initialized explicitly.
-This is loader and system dependent.
-If omitted no initialization is assumed.
-.NH 3
-Example mach.h for the PDP-11
-.DS L
-.ta 8 16 24 32 40 48 56
-#define ex_ap(y)	fprintf(codefile,"\et.globl %s\en",y)
-#define in_ap(y)	/* nothing */
-
-#define newplb(x)	fprintf(codefile,"%s:\en",x)
-#define newilb(x)	fprintf(codefile,"%s:\en",x)
-#define newdlb(x)	fprintf(codefile,"%s:\en",x)
-#define	dlbdlb(x,y)	fprintf(codefile,"%s=%s\en",x,y)
-#define newlbss(l,x)	fprintf(codefile,"%s:.=.+%d.\en",l,x);
-
-#define cst_fmt		"$%d."
-#define off_fmt		"%d."
-#define ilb_fmt		"I%02x%x"
-#define dlb_fmt		"_%d"
-#define	hol_fmt		"hol%d"
-
-#define hol_off		"%d.+hol%d"
-
-#define con_cst(x)	fprintf(codefile,"%d.\en",x)
-#define con_ilb(x)	fprintf(codefile,"%s\en",x)
-#define con_dlb(x)	fprintf(codefile,"%s\en",x)
-
-#define id_first	'_'
-#define BSS_INIT	0
-.DE
-.NH 2
-Functions in mach.c
-.PP
-In mach.c some functions must be supplied,
-mostly manipulating data resulting from pseudoinstructions.
-The specifications are given here,
-implicit typing of parameters as above.
-.IP con_part(isz,word) 20
-This function must manipulate the globals 
-part_word and part_size to append the isz bytes
-contained in word to the output stream.
-If part_word is full, i.e. part_size==EM_WSIZE
-the function part_flush() may be called to empty the buffer.
-This is the function that must go through the trouble of
-doing byte order in words correct.
-.IP con_mult(w_size)
-This function must take the string str[] and create an integer
-from the string of size w_size and generate code to assemble global
-data for that integer.
-Only the sizes for which arithmetic is implemented need be
-handled,
-so if you didn't implement 200-byte integer division
-you don't have to implement 200-byte integer global data.
-Here one must take care of word order in long integers.
-.IP con_float()
-This function must generate code to assemble a floating
-point number of which the size is contained in argval
-and the ASCII representation in str[].
-.IP prolog(f_nlocals)
-This function is called at the start of every procedure.
-Function prolog code must be generated,
-and room made for local variables for a total of f_nlocals bytes.
-.IP mes(w_mesno)
-This function is called when a
-.B mes
-pseudo is seen that is not handled by the machine independent part.
-Example below shows all you probably have to know about that.
-.IP segname[]
-This is not a function,
-but an array of four strings.
-These strings are put out whenever the code generator
-switches segments.
-Segments are SEGTXT, SEGCON, SEGROM and SEGBSS in that order.
-.NH 3
-Example mach.c for the PDP-11
-.PP
-As an example of the sort of code expected,
-the mach.c for the PDP-11 is presented here.
-.DS L
-.ta 8 16 24 32 40 48 56 64
-/*
- * machine dependent back end routines for the PDP-11
- */
-
-con_part(sz,w) register sz; word w; {
-
-	while (part_size % sz)
-		part_size++;
-	if (part_size == EM_WSIZE)
-		part_flush();
-	if (sz == 1) {
-		w &= 0xFF;
-		if (part_size)
-			w <<= 8;
-		part_word |= w;
-	} else {
-		assert(sz == 2);
-		part_word = w;
-	}
-	part_size += sz;
-}
-
-con_mult(sz) word sz; {
-	long l;
-
-	if (sz != 4)
-		fatal("bad icon/ucon size");
-	l = atol(str);
-	fprintf(codefile,"\et%o;%o\en",(int)(l>>16),(int)l);
-}
-
-con_float() {
-	double f;
-	register short *p,i;
-
-	/*
-	 * This code is correct only when the code generator is
-	 * run on a PDP-11 or VAX-11 since it assumes native
-	 * floating point format is PDP-11 format.
-	 */
-
-	if (argval != 4 && argval != 8)
-		fatal("bad fcon size");
-	f = atof(str);
-	p = (short *) &f;
-	i = *p++;
-	if (argval == 8) {
-		fprintf(codefile,"\et%o;%o;",i,*p++);
-		i = *p++;
-	}
-	fprintf(codefile,"\et%o;%o\en",i,*p++);
-}
-
-prolog(nlocals) full nlocals; {
-
-	fprintf(codefile,"mov r5,-(sp)\enmov sp,r5\en");
-	if (nlocals == 0)
-		return;
-	if (nlocals == 2)
-		fprintf(codefile,"tst -(sp)\en");
-	else
-		fprintf(codefile,"sub $%d.,sp\en",nlocals);
-}
-
-mes(type) word type; {
-	int argt ;
-
-	switch ( (int)type ) {
-	case ms_ext :
-		for (;;) {
-			switch ( argt=getarg(
-			    ptyp(sp_cend)|ptyp(sp_pnam)|sym_ptyp) ) {
-			case sp_cend :
-				return ;
-			default:
-				strarg(argt) ;
-				fprintf(codefile,".globl %s\en",argstr) ;
-				break ;
-			}
-		}
-	default :
-		while ( getarg(any_ptyp) != sp_cend ) ;
-		break ;
-	}
-}
-
-char    *segname[] = {
-	".text",        /* SEGTXT */
-	".data",        /* SEGCON */
-	".data",        /* SEGROM */
-	".bss"          /* SEGBSS */
-};
-.DE
-.NH 1
-Coercions
-.PP
-A central part in code generation is taken by the
-.I coercions .
-It is the responsibility of the table writer to provide
-all necessary coercions so that code generation can continue.
-The very minimal set of coercions are
-the coercions to unstack every token expression,
-in combination with the rules to stack every token.
-.PP
-If these are present the code generator can always make the necessary
-transformations by stacking and unstacking.
-Of course for codequality it is usually best to provide extra coercions
-to prevent this stacking to take place.
-.I Cg
-discriminates three types of coercions:
-.IP 1)
-Unstacking coercions.
-This category can use the allocate() call in its code.
-.IP 2)
-Splitting coercions, these are the coercions that split
-larger tokens into smaller ones.
-.IP 3)
-Transforming coercions, these are the coercions that transform
-a token into another one of the same size.
-This category can use the allocate() call in its code.
-.PP
-When a stack configuration does not match the stack pattern
-.I coercions
-are searched for in the following order:
-.IP 1)
-First tokens are split if necessary to get their sizes right.
-.IP 2)
-Then transforming coercions are found that will make the pattern match.
-.IP 3)
-Finally if the stack pattern is longer than the fakestack contents
-unstacking coercions will be used to fill up the pattern.
-.PP
-At any point, when coercions are missing so code generation could not
-continue, the offending tokens are stacked.
-.NH 1
-Internal workings of the code generator.
-.NH 2
-Description of tables.c and tables.h contents
-.PP
-In this section the intermediate files will be described 
-that are produced by
-.I cgg
-and compiled with machine independent code to produce a code generator.
-.NH 3
-Tables.c
-.PP
-Tables.c contains a large number of initialized array's of all sorts.
-Description of each follows:
-.br
-.in 1i
-.ti -0.5i
-byte code rules[]
-.br
-Pseudo code interpreted by the code generator.
-Always starts with some opcode followed by operands depending
-on the opcode.
-Integers in this table are between 0 and 32767 and have a one byte
-encoding if between 0 and 127.
-.ti -0.5i
-char stregclass[]
-.br
-Number of computed static register class per register.
-Two registers are in the same class if they have the same properties
-and don't share a common subregister.
-.ti -0.5i
-struct reginfo machregs[]
-.br
-Info per register.
-Initialized with representation string, size,
-members of the register and set of registers affected when this
-one is changed.
-Also contains room for runtime information,
-like contents and reference count.
-.ti -0.5i
-tkdef_t tokens[]
-.br
-Information per tokentype.
-Initialized with size, cost, type of operands and formatstring.
-.ti -0.5i
-node_t enodes[]
-.br
-List of triples representing expressions for the code generator.
-.ti -0.5i
-string code strings[]
-.br
-List of strings.
-All strings are put in a list and checked for duplication,
-so only one copy per string will reside here.
-.ti -0.5i
-set_t machsets[]
-.br
-List of token expression sets.
-Bit 0 of the set is used for the SCRATCH property of registers,
-bit 1 upto NREG are for the corresponding registers
-and bit NREG+1 upto the end are for corresponding tokens.
-.ti -0.5i
-inst_t tokeninstances[]
-.br
-List of descriptions for building tokens.
-Contains type of rule for building one,
-plus operands depending on the type.
-.ti -0.5i
-move_t moves[]
-.br
-List of move rules.
-Contains token expressions for source and destination
-plus cost and index for code rule.
-.ti -0.5i
-byte pattern[]
-.br
-EM patterns.
-This is structured internally as chains of patterns,
-each chain pointed at by pathash[].
-After each pattern the list of possible code rules is given.
-.ti -0.5i
-int pathash[256]
-.br
-Indices into pattern[] for all patterns with a certain low order
-byte of the hashing function.
-.ti -0.5i
-c1_t c1coercs[]
-.br
-List of rules to stack tokens.
-Contains token expressions,
-register needed,
-cost
-and code rule.
-.ti -0.5i
-c2_t c2coercs[]
-.br
-List of splitting coercions.
-Token expressions,
-split factor,
-replacements
-and code rule.
-.ti -0.5i
-c3_t c3coercs[]
-.br
-List of one to one coercions.
-Token expressions,
-register needed,
-replacement
-and code rule.
-.ti -0.5i
-struct reginfo **reglist[]
-.br
-List of lists of pointers to register information.
-For every property the list is here
-to find the registers corresponding to it.
-.in 0
-.NH 3
-tables.h
-.PP
-In tables.h various derived constants for the tables are
-given.
-They are then used to determine array sizes in the actual code generator,
-plus loop termination in some cases.
-.NH 2
-Other important data structures
-.PP
-During code generation some other data structures are used
-and here is a short description of some of the important ones.
-.PP
-Tokens are kept in the code generator as a struct consisting of
-one integer
-.I t_token
-which is -1 if the token is a register,
-and the number of the token otherwise,
-plus an array of
-.I TOKENSIZE
-unions
-.I t_att
-of which the first is the register number in case of a register.
-.PP
-The fakestack is an array of these tokens,
-there is a global variable
-.I stackheight .
-.PP
-The results of expressions are kept in a struct
-.I result
-with elements
-.I e_typ ,
-giving the type of the expression:
-.I EV_INT ,
-.I EV_REG
-or
-.I EV_STR ,
-and a union
-.I e_v
-which contains the real result.
-.NH 2
-A tour through the sources
-.NH 3
-codegen.c
-.PP
-The file codegen.c contains one large function consisting
-of one giant switch statement.
-It is the interpreter for the code generator pseudo code
-as contained in code rules[].
-This function can call itself recursively when doing lookahead.
-Arguments are:
-.IP codep 10
-Pointer into code rules, pseudo program counter.
-.IP ply
-Number of EM pattern lookahead allowed.
-.IP toplevel
-Boolean telling whether this is the toplevel codegen() or
-a deeper incarnation.
-.IP costlimit
-A cutoff value to limit searches.
-If the cost crosses costlimit the incarnation can terminate.
-.IP forced
-A register number if nonzero.
-This is used inside coercions to force the allocate() call to allocate
-a register determined by earlier lookahead.
-.PP
-The instructions inplemented in the switch:
-.NH 4
-DO_NEXTEM
-.PP
-Matches the next EM pattern and does lookahead if necessary to find the best
-code rule associated with this pattern.
-Heuristics are used to determine best code rule when possible.
-This is done by calling the distance() function.
-.NH 4
-DO_COERC
-.PP
-This sets the code generator in the state to do a from stack coercion.
-.NH 4
-DO_XMATCH
-.PP
-This is done when a match no longer has to be checked.
-Used when the nocoercions: trick is used in the table.
-.NH 4
-DO_MATCH
-.PP
-This is the big one inside this function.
-It has the task to transform the contents of the current
-fakestack to match the pattern given after it.
-.PP
-Since the code generator does not know combining coercions,
-i.e. there is no way to make a big token out of two smaller ones,
-the first thing done is to stack every token that is too small.
-After that all tokens too big are split if possible to the right size.
-.PP
-Next the coercions are sought that would transform tokens in place to
-the right one, plus the coercions that would pop tokens of the stack.
-Each of those might need a register, so a list of registers is generated
-and at the end of looking for coercions the function 
-.I tuples()
-is called to generate the list of all possible \fIn\fP-tuples,
-where 
-.I n
-equals the number of registers needed.
-.PP
-Lookahead is now performed if the number of tuples is greater than one.
-If no possibility is found within the costlimit,
-the fakestack is made smaller by pushing the bottom token,
-and this process is repeated until either a way is found or
-the fakestack is completely empty and there is still no way
-to make the match.
-.PP
-If there is a way the corresponding coercions are executed
-and the code is finished.
-.NH 4
-DO_REMOVE
-.PP
-Here the remove() call is executed, all tokens matched by the 
-token expression plus boolean expression are pushed.
-In the current implementation there is no attempt to move those
-tokens to registers, but that is a possible future extension.
-.NH 4
-DO_DEALLOCATE
-.PP
-This one temporarily decrements by one the reference count of all registers
-contained in the token given as argument.
-.NH 4
-DO_REALLOCATE
-.PP
-Here all temporary deallocates are made undone.
-.NH 4
-DO_ALLOCATE
-.PP
-This is the part that allocates a register and decides which one to use.
-If the
-.I forced
-argument was given its task is simple,
-otherwise some work must be done.
-First the list of possible registers is scanned,
-all free registers noted and it is noted whether any of those
-registers is already
-containing the initialization.
-If no registers are available some fakestack token is stacked and the
-process is repeated.
-.PP
-After that if an exact match was found, 
-the list of registers is reduced to one register matching exactly
-out of every register class.
-Now lookahead is performed if necessary and the register chosen.
-If an initialization was given the corresponding move is performed,
-otherwise the register is marked empty.
-.NH 4
-DO_LOUTPUT
-.PP
-This prints a string and an expression.
-Only done on toplevel.
-.NH 4
-DO_ROUTPUT
-.PP
-Prints a string and a new line.
-Only on toplevel.
-.NH 4
-DO_MOVE
-.PP
-Calls the move() function in the code generator to implement the move()
-function in the table.
-.NH 4
-DO_ERASE
-.PP
-Marks the register that is its argument as empty.
-.NH 4
-DO_TOKREPLACE
-.PP
-This is the token replacement part.
-It is also called if there is no token replacement because it has
-some other functions as well.
-.PP
-First the tokens that will be pushed on the fakestack are computed
-and stored in a temporary array.
-Then the tokens that were matched in this rule are popped
-and their embedded registers have their reference count
-decremented.
-After that the replacement tokens are pushed.
-.PP
-Finally all registers allocated in this rule have their reference count
-decremented.
-If they were not pushed on the fakestack they will be available again
-in the next code rule.
-.NH 4
-DO_EMREPLACE
-.PP
-Places replacement EM instructions back into the instruction stream.
-.NH 4
-DO_COST
-.PP
-Accounts for cost as given in the code rule.
-.NH 4
-DO_RETURN
-.PP
-Returns from this level of codegen().
-Is used at the end of coercions,
-move rules etc..
-.NH 3
-compute.c
-.PP
-This module computes the various expressions as given
-in the enodes[] array.
-Nothing very special happens here,
-it is just a recursive function computing leaves
-of expressions and applying the operator.
-.NH 3
-equiv.c
-.PP
-In this module the tuples() function is implemented.
-It is given the number of registers needed and
-a list of register lists and it constructs a list of tuples
-where the \fIn\fP'th register comes from the \fIn\fP'th list.
-Before the list is constructed however 
-the dynamic register classes are computed.
-Two registers are in the same dynamic class if they are in the
-same static class and their contents is the same.
-.PP
-After that the permute() recursive function is called to
-generate the list of tuples.
-After construction a generated tuple is added to the list
-if it is not already pairwise in the same class
-or if the register relations are not the same,
-i.e. if the first and second register share a common
-subregister in one tuple and not in the other they are considered different.
-.NH 3
-fillem.c
-.PP
-This is the routine that does the reading of EM instructions
-and the handling of pseudos.
-The mach.c module provided by the table writer is included
-at the end of this module.
-The routine fillemlines() is called by nextem() at toplevel
-to make sure there are enough instruction to match.
-It fills the EM instruction buffer up to 5 places from the end to
-keep room for EM replacement instructions,
-or up to a pseudo.
-.PP
-The dopseudo() function performs the function of the pseudo last
-encountered.
-If the pseudo is a 
-.B rom
-the corresponding label is saved with the contents of the
-.B rom
-to be available to the code generator later.
-The rest of the routines are small service routines for either
-input or data output.
-.NH 3
-gencode.c
-.PP
-This module contains routines called by codegen() to generate the real
-code to the codefile.
-The function gencode() gets a string as argument and copies it to codefile
-while processing certain embedded control characters implementing
-the $2 and [1.reg] escapes.
-The function genexpr() prints the expression given as argument.
-It is used to implement the %(\ expr\ %) escape.
-The prtoken() function interprets the tokenformat as given in
-the tokens[] array.
-.NH 3
-glosym.c
-.PP
-This module maintains a list of global symbols that have a 
-.B rom
-pseudo associated.
-There are functions to enter a symbol and to find a symbol.
-.NH 3
-main.c
-.PP
-Main routine of the code generator.
-Processes arguments and flags.
-Flags available are:
-.IP -d
-Sets debug mode if the code generator was not compiled with
-the NDEBUG macro defined.
-Debug mode gives very long output on stderr indicating
-all steps of the code generation process including nesting
-of the codegen() function.
-.IP -p\fIn\fP
-Sets the lookahead depth to
-.I n ,
-the
-.I p
-stands for ply,
-a well known word in chess playing programs.
-.IP -w\fIn\fP
-Sets the weight percentage for size in the cost function to
-.I n
-percent.
-Uses Euclides algorithm to simplify rationals.
-.NH 3
-move.c
-.PP
-Function to implement the move() pseudo function in the tables,
-register initialization and the setcc and test pseudo functions.
-First tests are made to try to prevent the move from really happening.
-The condition code register is treated special here.
-After that, if there is an after that,
-the move rule is found and the code executed.
-.NH 3
-nextem.c
-.PP
-The entry point of this module is nextem().
-It hashes the next three EM instructions,
-and uses the low order byte of the hash
-as an index into the array pathash[],
-to find a chain of patterns in the array
-pattern[],
-that are all tried for a match.
-.PP
-The function trypat() does most of the work
-checking patterns.
-When a pattern is found to match all instructions
-the operands of the instruction are placed into the dollar[] array.
-Then the boolean expression is tried.
-If it matches the function can return,
-leaving the operands still in the dollar[] array,
-so later in the code rule they can still be used.
-.NH 3
-reg.c
-.PP
-Collection of routines to handle registers.
-Reference count routines are here,
-chrefcount() and getrefcount(),
-plus routines to erase a single register or all of them,
-erasereg() and cleanregs().
-.PP
-If NDEBUG hasn't been defined, here is also the routine that checks
-if the reference count kept with the register information is in
-agreement with the number of times it occurs on the fakestack.
-.NH 3
-salloc.c
-.PP
-Module for string allocation and garbage collection.
-Contains entry points myalloc(),
-a routine calling malloc() and checking whether room is left,
-myfree(), just free(),
-popstr() a function called from state.c to free all strings
-made since the last saved status.
-Furthermore there is salloc() which has the size of the string as parameter
-and returns a pointer to the allocated space,
-while keeping a copy of the pointer for garbage allocation purposes.
-.PP
-The function garbage_collect is called from codegen() at toplevel
-every now and then,
-and checks all places where strings may reside to mark strings
-as being in use.
-Strings not in use are returned to the pool of free space.
-.NH 3
-state.c
-.PP
-Set of routines called to save current status,
-restore a previous saved state and to free the room
-occupied by a saved state.
-A list of structs is kept here to save the state.
-If this is not done,
-small allocates will take space
-from the holes big enough for state saves,
-and as a result every new state save will need a new struct.
-The code generator runs out of room very rapidly under these conditions.
-.NH 3
-subr.c
-.PP
-Random set of leftover routines.
-.NH 4
-match
-.PP
-Computes whether a certain token matches a certain token expression.
-Just computes a bitnumber according to the algorithm explained with
-machsets[],
-and tests the bit and the boolean expression if it is there.
-.NH 4
-instance,cinstance
-.PP
-These two functions compute a token from a description.
-They differ very slight, cinstance() is used to compute
-the result of a coercion in a certain context
-and therefore has more arguments, which it uses instead of
-the global information instance() works on.
-.NH 4
-eqtoken
-.PP
-eqtoken computes whether two tokens can be considered identical.
-Used to check register contents during moves mainly.
-.NH 4
-distance
-.PP
-This is the heuristic function that computes a distance from
-the current fakestack contents to the token pattern in the table.
-It likes exact matches most, then matches where at least the sizes are correct
-and if the sizes are not correct it likes too large sizes more than too
-small, since splitting a token is easier than combining one.
-.NH 4
-split
-.PP
-This function tries to find a splitting coercion
-and executes it immediately when found.
-The fakestack is shuffled thoroughly when this happens,
-so pieces below the token that must be split are saved first.
-.NH 4
-docoerc
-.PP
-This function executes a coercion that was found.
-The same shuffling is done, so the top of the stack is again saved.
-.NH 4
-stackupto
-.PP
-This function gets a pointer into the fakestack and must stack
-every token including the one pointed at up to the bottom of the fakestack.
-The first stacking rule possible is used,
-so rules using registers must come first.
-.NH 4
-findcoerc
-.PP
-Looks for a one to one coercion, if found it returns a pointer
-to it and leaves a list of possible registers to use in the global
-variable curreglist.
-This is used by codegen().
-.NH 3
-var.c
-.PP
-Global variables used by more than one module.
-External definitions are in extern.h.

+ 0 - 324
doc/cref.doc

@@ -1,324 +0,0 @@
-.\" $Header$
-.ll 72
-.nr ID 4
-.de hd
-'sp 2
-'tl ''-%-''
-'sp 3
-..
-.de fo
-'bp
-..
-.tr ~
-.               TITLE
-.de TL
-.sp 15
-.ce
-\\fB\\$1\\fR
-..
-.               AUTHOR
-.de AU
-.sp 15
-.ce
-by
-.sp 2
-.ce
-\\$1
-..
-.               DATE
-.de DA
-.sp 3
-.ce
-( Dated \\$1 )
-..
-.               INSTITUTE
-.de VU
-.sp 3
-.ce 4
-Wiskundig Seminarium
-Vrije Universteit
-De Boelelaan 1081
-Amsterdam
-..
-.               PARAGRAPH
-.de PP
-.sp
-.ti +\n(ID
-..
-.nr CH 0 1
-.               CHAPTER
-.de CH
-.nr SH 0 1
-.bp
-.in 0
-\\fB\\n+(CH.~\\$1\\fR
-.PP
-..
-.               SUBCHAPTER
-.de SH
-.sp 3
-.in 0
-\\fB\\n(CH.\\n+(SH.~\\$1\\fR
-.PP
-..
-.               INDENT START
-.de IS
-.sp
-.in +\n(ID
-..
-.               INDENT END
-.de IE
-.in -\n(ID
-.sp
-..
-.de PT
-.ti -\n(ID
-.ta \n(ID
-.fc " @
-"\\$1@"\c
-.fc
-..
-.               DOUBLE INDENT START
-.de DS
-.sp
-.in +\n(ID
-.ll -\n(ID
-..
-.               DOUBLE INDENT END
-.de DE
-.ll +\n(ID
-.in -\n(ID
-.sp
-..
-.               EQUATION START
-.de EQ
-.sp
-.nf
-..
-.               EQUATION END
-.de EN
-.fi
-.sp
-..
-.               ITEM
-.de IT
-.sp
-.in 0
-\\fB~\\$1\\fR
-.ti +5
-..
-.de CS
-.br
-~-~\\
-..
-.br
-.fi
-.TL "Ack-C reference manual"
-.AU "Ed Keizer"
-.DA "September 12, 1983"
-.VU
-.wh 0 hd
-.wh 60 fo
-.CH "Introduction"
-The C frontend included in the Amsterdam Compiler Kit
-translates UNIX-V7 C into compact EM code [1].
-The language accepted is described in [2] and [3].
-This document describes which implementation dependent choices were
-made in the Ack-C frontend and
-some restrictions and additions.
-.CH "The language"
-.PP
-Under the same heading as used in [2] we describe the
-properties of the Ack-C frontend.
-.IT "2.2 Identifiers"
-External identifiers are unique up to 7 characters and allow
-both upper and lower case.
-.IT "2.3 Keywords"
-The word \fBvoid\fP is also reserved as a keyword.
-.IT "2.4.3 Character constants"
-The ASCII-mapping is used when a character is converted to an
-integer.
-.IT "2.4.4 Floating constants"
-To prevent loss of precision the compiler does not perform
-floating point constant folding.
-.IT "2.6 Hardware characteristics"
-The size of objects of the several arithmetic types and 
-pointers depend on the EM-implementation used.
-The ranges of the arithmetic types depend on the size used,
-the C-frontend assumes two's complement representation for the
-integral types.
-All sizes are multiples of bytes.
-The calling program \fIack\fP[4] passes information about the
-size of the types to the compiler proper.
-.br
-However, a few general remarks must be made:
-.sp 1
-.IS
-.PT (a)
-The size of pointers is a multiple of
-(or equal to) the size of an \fIint\fP.
-.PT (b)
-The following relations exist for the sizes of the types
-mentioned:
-.br
-.ti +5
-\fIchar<=short<=int<=long\fP
-.PT (c)
-Objects of type \fIchar\fP use one 8-bit byte of storage,
-although several bytes are allocated sometimes.
-.PT (d)
-All sizes are in multiples of bytes.
-.PT (e)
-Most EM implementations use 4 bytes for floats and 8 bytes
-for doubles, but exceptions to this rule occur.
-.IE
-.IT "4 What's in a name"
-The type \fIvoid\fP is added.
-Objects of type void do not exist.
-Functions declared as returning void, do not return a value at all.
-.IT "6.1 Characters and integers"
-Objects of type \fIchar\fP are unsigned and do not cause
-sign-extension when converted to \fIint\fP.
-The range of characters values is from 0 to 255.
-.IT "6.3 Floating and integral"
-Floating point numbers are truncated towards zero when
-converted to the integral types.
-.IT "6.4 Pointers and integers"
-When a \fIlong\fP is added to or subtracted from a pointer and
-longs are larger then pointers the \fIlong\fP is converted to an
-\fIint\fP before the operation is performed.
-.IT "7.2 Unary operators"
-It is allowed to cast any expression to the type \fIvoid\fP.
-.IT "8.2 Type specifiers"
-One type is added to the type-specifiers:
-.br
-.IS
-void
-.IE
-.IT "8.5 Structure and union declarations"
-The only type allowed for fields is \fIint\fP.
-Fields with exactly the size of \fIint\fP are signed,
-all other fields are unsigned.
-.br
-The size of any single structure must be less then 4096 bytes.
-.IT "8.6 Initialization"
-Initialization of structures containing bit fields is not
-allowed.
-There is one restriction when using an 'address expression' to initialize
-an integral variable.
-The integral variable must have the same size as a pointer.
-Conversions altering the size of the address expression are not allowed.
-.IT "9.10 Return statement"
-Return statements of the form:
-.IS
-	return ;
-.IE
-are the only form of return statement allowed in a function of type
-function returning void.
-.IT "10.1 External function definitions"
-The total amount for storage used for parameters
-in any function must be less then 4096 bytes.
-The same holds for the total amount of storage occupied by the
-automatic variables declared inside any function.
-.sp
-Using formal parameters whose size is smaller the the size of an int
-is less efficient on several machines.
-At procedure entry these parameters are converted from integer to the
-declared type, because the compiler doesn't know where the least
-significant bytes are stored in the int.
-.IT "11.2 Scope of externals"
-Most C compilers are rather lax in enforcing the restriction
-that only one external definition without the keyword
-\fIextern\fP is allowed in a program.
-The Ack-C frontend is very strict in this.
-The only exception is that declarations of arrays with a
-missing first array bounds expression are regarded to have an
-explicit keyword \fIextern\fP.
-.IT "14.4 Explicit pointer conversions"
-Pointers may be larger the ints, thus assigning a pointer to an
-int and back will not always result in the same pointer.
-The process mentioned above works with integrals
-of the same size or larger as pointers in all EM implementations
-having such integrals.
-When converting pointers to an integral type or vice-versa,
-the pointers is seen as an unsigned int.
-.br
-EM guarantees that any object can be placed at a word boundary,
-this allows the C-programs to use \fIint\fP pointers
-as pointers to objects of any type not smaller than an \fIint\fP.
-.CH "Frontend options"
-The C-frontend has a few options, these are controlled
-by flags:
-.IS
-.PT -V
-This flag is followed by a sequence of letters each followed by
-positive integers. Each letter indicates a
-certain type, the integer following it specifies the size of
-objects of that type. One letter indicates the wordsize used.
-.IS
-.sp 1
-.TS
-center tab(:);
-l l16 l l.
-letter:type:letter:type
-
-w:wordsize:i:int
-s:short:l:long
-f:float:d:double
-p:pointer::
-.TE
-.sp 1
-All existing implementations use an integer size equal to the
-wordsize.
-.IE
-The calling program \fIack\fP[4] provides the frontend with
-this flag, with values depending on the machine used.
-.sp 1
-.PT -l
-The frontend normally generates code to keep track of the line
-number and source file name at runtime for debugging purposes.
-Currently a pointer to a
-string containing the filename is stored at a fixed place in
-memory at each function
-entry and the line number at the start of every expression.
-At the return from a function these memory locations are not reset to
-the values they had before the call.
-Most library routines do not use this feature and thus do not
-ruin the current line number and filename when called.
-However, you are really unlucky when your program crashes due
-to a bug in such a library function, because the line number
-and filename do not indicate that something went wrong inside
-the library function.
-.br
-Providing the flag -l to the frontend tells it not to generate
-the code updating line number and file name.
-This is, for example, used when translating the stdio library.
-.br
-When the \fIack\fP[4] is called with the -L flag it provides
-the frontend with this flag.
-.sp 1
-.PT -Xp
-When this flag is present the frontend generates a call to
-the function \fBprocentry\fP at each function entry and a
-call to \fBprocexit\fP at each function exit.
-Both functions are provided with one parameter,
-a pointer to a string containing the function name.
-.br
-When \fIack\fP is called with the -p flag it provides the
-frontend with this flag.
-.IE
-.CH References
-.IS
-.PT [1]
-A.S. Tanenbaum, Hans van Staveren, Ed Keizer and Johan
-Stevenson \fIDescription of a machine architecture for use with
-block structured languages\fP Informatica report IR-81.
-.sp 1
-.PT [2]
-B.W. Kernighan and D.M. Ritchie, \fIThe C Programming
-language\fP, Prentice-Hall, 1978
-.PT [3]
-D.M. Ritchie, \fIC Reference Manual\fP
-.sp
-.PT [4]
-UNIX manual ack(I).

+ 0 - 31
doc/em/Makefile

@@ -1,31 +0,0 @@
-head:   doc.pr
-
-NROFF=nroff
-FILES = macr.nr title.nr intro.nr mem.nr ispace.nr dspace.nr mapping.nr types.nr descr.nr iotrap.nr mach.nr assem.nr app.nr
-IOP=../../util/ass/ip_spec.t
-
-doc.pr: $(FILES) itables em.i
-	tbl $(FILES) | $(NROFF) >doc.pr
-
-distr:	$(FILES) itables em.i
-	tbl $(FILES) | nroff -Tlp >doc.pr
-
-opr:	doc.pr
-	make pr | opr
-
-pr:
-	@make "NROFF="$NROFF doc.pr >makepr.out 2>&1
-	@cat doc.pr
-
-app.t:	itables em.i
-
-em.i:	int/em.p
-	@echo Sorry, this copy was edited by hand from int/em.p
-
-itables: $(IOP)
-	awk -f ip.awk $(IOP) | tbl >itables
-
-.SUFFIXES : .pr .nr
-.nr.pr: ; tbl macr.nr $*.nr | $(NROFF) >$@
-
-cont.t intro.t mem.t ispace.t dspace.t mapping.t succ.t descr.t iotrap.t mach.t assem.t kern.t app.t: macr.nr

+ 0 - 1
doc/em/READ_ME

@@ -1 +0,0 @@
-Sorry, the kun macro package is not ours to distribute.

+ 0 - 1121
doc/em/addend.n

@@ -1,1121 +0,0 @@
-.lg 0
-.ta 8 16 24 32 40 48 56 64 72 80
-.hw iden-ti-fi-er
-.nr a 0 1
-.nr f 1 1
-.de x1
-'sp 2
-'tl '''%'
-'sp 2
-.ns
-..
-.wh 0 x1
-.de fo
-'bp
-..
-.wh 60 fo
-.ll 79
-.lt 79
-.de HT
-.ti -4
-..
-.de PP
-.sp
-.ne 2
-.ti +5
-..
-.de SE
-.bp
-\fB\\n+a. \\$1\fR
-.nr b 0 1
-..
-.de SB
-.br
-.ne 10
-.sp 5
-\fB\\na.\\n+b. \\$1\fR
-..
-.de DC
-.ti -14
-DECISION~\\$1:
-..
-.de IN
-.in +6
-..
-.de OU
-.in -6
-..
-.tr ~
-.sp 5
-.rs
-.sp 10
-.ce 3
-Changes in EM-1
-
-Addendum to Informatica Rapport IR-54
-.sp 5
-.PP
-This document describes a revision of EM-1.
-A list of differences is presented roughly in the order IR-54
-describes the original architecture.
-A complete list of EM-1 pseudo's and instructions is also included.
-.SE Introduction
-.PP
-EM is a family of intermediate languages, resembling assembly
-language for a stack machine.
-EM defines the layout of data memory and a partitioning
-of instruction memory.
-EM has can do operations on five basic types:
-pointers, signed integers, unsigned integers, floating point numbers
-and sets of bits.
-The size of pointers is fixed in each member,
-in contrast to the sizes of the other types.
-Each member has one more fixed size: the word size.
-This is the mimimum size of any object on the stack.
-The sizes of all objects on the stack are assumed to
-multiples of the word size.
-We assume that pointer and word-sizes are both powers of two.
-.PP
-It is possible to load objects smaller then the word size from memory.
-These objects are converted to objects of the word size by
-clearing the most significant bytes.
-(A separate conversion instruction can do sign extension).
-While storing objects smaller then the word size are stored in memory,
-the most significant bytes are ignored.
-The size of such objects has to be a divisor of the word size.
-.PP
-Put in other terms, instructions such as LOC, LOL, LOE, STF, etc.
-manipulate WORDS.  Up until now, a word was defined as 16 bits.
-It is now possible to define a word size other than 16 bits.  For
-example, MES 2,1,2 defines a word to be 8 bits and a pointer to be
-16 bits.  As another example, MES 2,4,4 defines a word to be 32 bits
-and a pointer to be 32 bits.
-.PP
-If a compiler receives flags telling it to use 32 bit integers, it now
-has a choice of setting the word length to 16 bits and using LDL etc
-for dealing with integers, or setting the word length to 32 bits and using
-LOL etc for integers.
-For example, x:=a+b for 32-bit integers would become:
-
-  MES 2,2,4                          MES 2,4,4
-  LDL a                              LOL a
-  LDL b                              LOL b
-  ADI 4                              ADI 4
-  SDL x                              STL x
-
-In many cases, the target machine code that is finally produced from either
-of the above sequences will not show any traces of the stack machine, however
-for some instructions actual pushes and pops at run time will be necessary.
-Choosing a wider EM word will usually produce fewer stack operations than
-a narrower word, but it eliminates the possibility of doing arithmetic on
-quantities smaller than a word.  If, for example, a compiler chooses a 32-bit
-EM word, it will be difficult to add two 16 bit integers with ADI, since
-the argument must be multiple of the word size.
-(The operation can be done by converting the operands to 32 bits using CII,
-adding the 32-bit numbers, and reconverting the result.)
-On the other hand, choosing a 16-bit EM word makes it possible to do both
-16-bit adds (ADI 2) and 32-bit adds (ADI 4), 
-but the price paid is that 32-bit operations will be viewed as double
-precision, and may be slightly less efficient on target machines with a
-32-bit word, i.e. the EM to target translator may not take full advantage
-of the 32 bit facilities.
-.PP
-Note that since LOC pushes a WORD on the stack, the argument of LOC
-must fit ina word.  LOC 256 on an EM machine with a 1-byte word length
-is not allowed.  LDC 256 is allowed, however.
-.PP
-A general rule of thumb is that the compiler should choose an EM word
-length equal to the width of a single precision integer.
-Obviously, compilers should be well parameterized to allow the integer
-size(s) and word size(s) to be changed by just changing a few constants.
-.PP
-The size of a instruction space pointer in is the same
-as the size of a data space pointer.
-.PP
-EM assumes two's complement arithmetic on signed integers,
-but does not define an ordering of the bytes in a integer.
-The lowest numbered byte of a two-byte object can contain
-either the most or the least significant part.
-.SE Memory
-.PP
-EM has two separate addressing spaces, instruction and data.
-The sizes of these spaces are not specified.
-The layout of instruction space in not defined.
-Any interpreter or translator may assume a layout fitting his/her needs.
-The layout of data memory is specified by EM.
-EM data memory consists of a sequence of 8-bit bytes each separately
-addressable.
-Certain alignment restrictions exist for object consisting of multiple bytes.
-Objects smaller then the word size can only be addressed
-at multiples of the object size.
-For example: in a member with a four-byte word size, two-byte integers
-can only be accessed from even addresses.
-Objects larger then the word size can only be placed at multiples
-of the word size.
-For example: in a member with a four-byte word size,
-eight-byte floating point numbers can be fetched at addresses
-0, 4, 8, 12, etc.
-.SB "Procedure identifiers"
-.PP
-Procedure identifiers in EM have the same size
-as pointers.
-Any implementation of EM is free to use any method of identifying procedures.
-Common methods are indices into tables containing further information
-and addresses of the first instructions of procedures.
-.SB "Heap and Stack in global data"
-.PP
-The stack grows downward, the heap grows upward.
-The stack pointer points to the lowest occupied word on the stack.
-The heap pointer marks the first free word in the heap area.
-.br
-.ne 39
-.sp 1
-.nf
-       65534 -> |-------------------------------|
-                |///////////////////////////////|
-		|//// unimplemented memory /////|
-                |///////////////////////////////|
-          SB -> |-------------------------------|
-		|				|
-		|     stack and local area      | <- LB
-                |                               |
-		|				|
-                |-------------------------------| <- SP
-		|///////////////////////////////|
-		|// implementation dependent  //|
-		|///////////////////////////////|
-                |-------------------------------| <- HP
-		|				|
-		|           heap area           |
-		|				|
-		|                               |
-                |-------------------------------|
-		|				|
-		|          global area          |
-		|				|
-          EB -> |-------------------------------|
-		|				|
-		|				|
-                |         program text          | <- PC
-		|				|
-		|				|
-          PB -> |-------------------------------|
-		|///////////////////////////////|
-		|////////// undefined //////////|
-		|///////////////////////////////|
-           0 -> |-------------------------------|
-
-	   Fig. \nf.  Example of memory layout showing typical register
-           positions during execution of an EM program.
-.fi
-.SB "Data addresses as arguments"
-.PP
-Anywhere previous versions of the EM assembly language
-allowed identifiers of objects in
-data space,
-it is also possible to use 'identifier+constant' or 'identifier-constant'.
-For example, both "CON LABEL+4" and "LAE SAVED+3" are allowed.
-More complicated expressions are illegal.
-.SB "Local data area"
-.PP
-The mark block has been banished.
-When calling a procedure,
-the calling routine first has to push the actual parameters.
-All language implementations currently push their arguments
-in reverse order, to be compatible with C.
-Then the procedure is called using a CAL or CAI instruction.
-Either the call or the procedure prolog somehow has to save
-the return address and dynamic link.
-The prolog allocates the space needed for locals and is free to
-surround this space with saved registers and other information it
-deems necessary.
-.PP
-The locals are now accessed using negative offsets in LOL, LDL, SDL, LAL,
-LIL, SIL and STL instructions.
-The parameters are accessed using positive offsets in LOL, LDL, SDL, LAL,
-LIL, STL and
-STL instructions.
-The prolog might have stored information in the area between parameters and
-locals.
-As a consequence there are two bases, AB(virtual) and LB.
-AB stands for Argument Base and LB stands for Local Base.
-Positive arguments to LOL etc ... are interpreted as offsets from AB,
-negative arguments as offsets from LB.
-.PP
-The BEG instruction is not needed to allocate the locals because
-storage for locals is set aside in the prolog.
-The instruction still exists under the name ASP (Adjust Stack Pointer).
-.PP
-Procedures return using the RET instruction.
-The RET pops the function result from the stack and
-brings the stack pointer and other relevant registers to the state
-they had just before the procedure was called.
-The RET instruction expects that - aside from possible function results -
-the stack pointer has the value it had after execution of the prolog.
-RET finally returns control to the calling routine.
-The actual parameters have to be removed from the stack by the calling routine,
-and not by the called procedure.
-.sp 1
-.ne 38
-.nf
-
-
-
-		|===============================|
-                |     actual argument  n        |
-		|-------------------------------|
-                |              .                |
-                |              .                |
-                |              .                |
-		|-------------------------------|
-                |     actual argument  1        | ( <- AB )
-		|===============================|
-		|///////////////////////////////|
-		|// implementation dependent  //|
-		|///////////////////////////////|   <- LB
-                |===============================|
-                |                               |
-                |       local variables         |
-                |                               |
-		|-------------------------------|
-                |                               |
-                |      compiler temporaries     |
-                |                               |
-		|===============================|
-		|///////////////////////////////|
-		|// implementation dependent  //|
-		|///////////////////////////////|
-                |===============================|
-                |                               |
-                |   dynamic local generators    |
-                |                               |
-		|===============================|
-                |           operand             |
-		|-------------------------------|
-                |           operand             | <- SP
-		|===============================|
-
-                A sample procedure frame.
-
-.fi
-.sp 1
-This scheme allows procedures to be called with a variable number
-of parameters.
-The parameters have to be pushed in reverse order,
-because the called procedure has to be able to locate the first one.
-.PP
-.PP
-Since the mark block has disappeared, a new mechanism for static
-links had to be created.
-All compilers use the convention that EM procedures needing
-a static link will find a link in their zero'th parameter,
-i.e. the last one pushed on the stack.
-This parameter should be invisible to users of the compiler.
-The link needs to be in a fixed place because the lexical instructions
-have to locate it.
-The LEX instruction is replaced by two instructions: LXL and LXA.
-\&"LXL~n" finds the LB of a procedure n static levels removed.
-\&"LXA~n" finds the (virtual) AB.
-The value used for static link is LB.
-.PP
-When a procedure needing a static link is called, first the actual
-parameters are pushed, then the static link is pushed using LXL
-and finally the procedure is called with a CAL with the procedure's
-name as argument.
-.br
-.ne 40
-.nf
-
-
-
-		|===============================|
-                |     actual argument  n        |
-		|-------------------------------|
-                |              .                |
-                |              .                |
-                |              .                |
-		|-------------------------------|
-                |     actual argument  1        |
-		|-------------------------------|
-                |        static link            | ( <- AB )
-		|===============================|
-		|///////////////////////////////|
-		|// implementation dependent  //|
-		|///////////////////////////////|   <- LB
-                |===============================|
-                |                               |
-                |       local variables         |
-                |                               |
-		|-------------------------------|
-                |                               |
-                |      compiler temporaries     |
-                |                               |
-		|===============================|
-		|///////////////////////////////|
-		|// implementation dependent  //|
-		|///////////////////////////////|
-                |===============================|
-                |                               |
-                |   dynamic local generators    |
-                |                               |
-		|===============================|
-                |           operand             |
-		|-------------------------------|
-                |           operand             | <- SP
-		|===============================|
-
-                A procedure frame with static link.
-
-.fi
-.sp 1
-.sp 1
-.PP
-Pascal and other languages have to use procedure
-instance identifiers containing
-the procedure identifier
-'ul
-and
-the static link the procedure has to be called with.
-A static link having a value of zero signals
-that the called procedure does not need a static link.
-C uses the same convention for pointers to C-routines.
-In pointers to C-routines the static link is set to zero.
-.PP
-Note: The distance from LB to AB must be known for each procedure, otherwise
-LXA can not be implemented.
-Most implementations will have a fixed size area between
-the parameter and local storage.
-The zone between the compiler temporaries and the dynamic
-local generators can be used
-to save a variable number of registers.
-.PP
-.ne 11
-Prolog examples:
-.sp 2
-.nf
-
-	       proc1                       proc2
-	   
-	   mov lb,-(sp)                mov lb,-(sp)
-	   mov sp,lb                   mov sp,lb
-	   sub $loc_size,sp            sub $loc_size,sp
-	   mov r2,-(sp) ; save r2      mov r2,-(sp)
-	   mov r4,-(sp) ; save r4
-
-.fi
-.SB "Return values"
-.PP
-The return value popped by RET is stored in an unnamed 'function return area'.
-This area can be different for different sized objects returned,
-e.g. one register for two byte objects,
-two registers for four byte objects,
-memory for larger objects.
-The area is available for 'READ-ONCE' access using the LFR instruction.
-The result of a LFR is only defined if the sizes used to store and
-fetch are identical.
-The only instructions guaranteed not to destroy the contents of
-any 'function return area' are ASP and BRA.
-Thus parameters can be popped before fetching the function result.
-The maximum size of all function return areas is
-implementation dependant,
-but allows procedure instance identifiers and all
-implemented objects of type integer, unsigned, float
-and pointer to be returned.
-
-.SE "EM Assembly Language"
-.nr b 0 1
-.SB "Object types and instructions"
-.PP
-EM knows five basic object types:
-pointers,
-signed integers,
-unsigned integers,
-floating point numbers and
-sets of bits.
-Operations on objects of the last four types do not assume
-a specific size.
-Pointers (including procedure identifiers) have a fixed size in each
-implementation.
-Instructions acting on one or more objects of the last four types need
-explicit size information.
-This information can be given either as the argument of the
-instruction or on top of the stack.
-.sp 1
-For example:
-.nf
-addition of integers         LOL a, LOL b, ADI 2
-subtraction of two floats    LDL a, LDL b, SBF 4
-integer to float             LOL a, LOC 2, LOC 4, CIF, SDL b
-.fi
-.sp
-Note that conversion instructions always expect size
-before and size after conversion on the stack.
-.sp
-No obligation exists to implement all operations on all possible sizes.
-.PP
-The EM assembly language
-allows constants as instruction arguments up to a size of four bytes.
-In all EM's it is possible to initialize any type and size object.
-BSS, HOL, CON and ROM allow type and size indication in initializers.
-.SB "Conversion instructions"
-.PP
-The conversion operators can convert from any type and size to any
-type and size.
-The types are specified by the instruction,
-the sizes should be in words on top of the stack.
-Normally the sizes are multiples of the word size,
-There is one exception: the CII instructions sign-extends if the
-size of the source is a divisor of the word size.
-.SB "CSA and CSB"
-.PP
-The tables used by these instructions do not contain the procedure
-identifier any more.
-See also "Descriptors".
-.SB EXG
-.PP
-The EXG instruction is deleted from the EM instruction set.
-If future applications show any need for this instruction,
-it will be added again.
-.SB "FIL"
-.PP
-A FIL instruction has been introduced.
-When using separate compilation,
-the LIN feature of EM was insufficient.
-FIL expects as argument an address in global data.
-This address is stored in a fixed place in memory,
-where it can be used by any implementation for diagnostics etc.
-Like LIN, it provides access to the ABS fragment at the start
-of external data.
-.SB "LAI and SAI"
-.PP
-LAI and SAI have been dropped, they thwarted register optimization.
-.SB LNC
-.PP
-The LNC instruction is deleted from the instruction set.
-LOC -n wil do what it is supposed to.
-.SB "Branch instructions"
-.PP
-The branch instructions are allowed to branch both forward and backward.
-Consequently BRF and BRB are deleted and a BRA instruction is added.
-BRA branches unconditionally in any direction.
-.SB LDC
-.PP
-Loads a double word constant on the stack.
-.SB LEX
-.PP
-LXA and LXL replace LEX.
-.SB LFR
-.PP
-LFR loads the function result stored by RET.
-.SB "LIL and SIL"
-.PP
-They replace LOP and STP. (Name change only)
-.SB "Traps and Interrupts"
-.PP
-The numbers used for distinguishing the various types
-of traps and interrupts have been reassigned.
-The new instructions LIM and SIM
-allow setting and clearing of bits in a mask.
-The bits in the mask control the action taken upon encountering certain
-errors at runtime.
-A 1 bit causes the corresponding error to be ignored,
-a 0 bit causes the run-time system to trap.
-.SB LPI
-.PP
-Loads a procedure identifier on the stack.
-LOC cannot be used to do this anymore.
-.SB "ZER and ZRF"
-.PP
-ZER loads S zero bytes on the stack.
-ZRF loads a floating point zero of size S.
-.SB "Descriptors"
-.PP
-All instructions using descriptors have the size of the integer used
-in the descriptor as argument.
-The descriptors are: case descriptors (CSA and CSB),
-range check descriptors (RCK) and
-array descriptors ( LAR, SAR, AAR).
-.SB "Case descriptors"
-.PP
-The value used in a case descriptor to indicate the absence of a label
-is zero instead of -1.
-.SE "EM assembly language"
-.SB "Instruction arguments"
-.PP
-The previous EM had different instructions for distinguishing
-between operand on the stack and explicit argument in the instruction.
-For example, LOI and LOS.
-This distinction has been removed.
-Several instructions have two possible forms:
-with explicit argument and with implicit argument on top of the stack.
-The size of the implicit argument is the word size.
-The implicit argument is always popped before all other operands.
-Appendix 1 shows what is allowed for each instruction.
-.SB Notation
-.PP
-First the notation used for the arguments of
-instructions and pseudo instructions.
-.in +12
-.ti -11
-<num>~~=~~an integer number in the range -32768..32767
-.ti -11
-<off>~~=~~an offset -2**31..2**31~-~1
-.ti -11
-<sym>~~=~~an identifier
-.ti -11
-<arg>~~=~~<off> or <sym> or <sym>+<off> or <sym>-<off>
-.ti -11
-<con>~~=~~integer constant,
-unsigned constant,
-floating point constant
-.ti -11
-<str>~~=~~string constant (surrounded by double quotes),
-.ti -11
-<lab>~~=~~instruction label ('*' followed by an integer in the range
-0..32767).
-.ti -11
-<pro>~~=~~procedure number ('$' followed by a procedure name)
-.ti -11
-<val>~~=~~<arg>,
-<con>,
-<pro> or
-<lab>.
-.ti -11
-<...>*~=~~zero or more of <...>
-.ti -11
-<...>+~=~~one or more of <...>
-.ti -11
-[...]~~=~~optional ...
-.in -12
-.SB Labels
-.PP
-No label, instruction or data, can have a (pseudo) instruction
-on the same line.
-.SB Constants
-.PP
-All constants in EM are interpreted in the decimal base.
-.PP
-In BSS, HOL, CON and ROM pseudo-instructions
-numbers must be followed by I, U or F
-indicating Integer, Unsigned or Float.
-If no character is present I is assumed.
-This character can be followed by an even positive number or a 1.
-The number indicates the size in bytes of the object to be initialized,
-up to 32766.
-Double precision integers can no longer be indicated by a trailing L.
-As said before CON and ROM also allow expressions of the form:
-\&"LABEL+offset" and "LABEL-offset".
-The offset must be an unsigned decimal number.
-The 'IUF' indicators cannot be used with the offsets.
-.PP
-Areas reserved in the global data area by HOL or BSS can be
-initialized.
-BSS and HOL have a third parameter indicating whether the initialization
-is mandatory or optional.
-.PP
-Since EM needs aligment of objects, this alignment is enforced by the
-pseudo instructions.
-All objects are aligned on a multiple of their size or the word size
-whichever is smaller.
-Switching to another type of fragment or placing a label forces word-alignment.
-There are three types of fragments in global data space: CON, ROM and BSS-HOL.
-.sp
-.SB "Pseudo instructions"
-.PP
-The LET, IMC and FWC pseudo's have disappeared.
-The only application of these pseudo's was in postponing the
-specification of the size of the local storage to just before
-the END of the procedure.
-A new mechanism has been introduced to handle this problem.
-.ti +5
-The pseudos involved in separate compilation and linking have
-been reorganized.
-.ti +5
-PRO and END are altered and reflect the new calling sequence.
-EOF has disappeared.
-.ti +5
-BSS and HOL allow initialization of the requested data areas.
-.sp 2
-Four pseudo instructions request global data:
-.sp 2
-  BSS <off>,<val>,<num>
-.IN
-Reserve <off> bytes.
-<val> is the value used to initialize the area.
-<off> must be a multiple of the size of <val>.
-<num> is 0 if the initialization is not strictly necessary,
-1 otherwise.
-.OU
-.sp
-  HOL <off>,<val>,<num> 
-.IN
-Idem, but all following absolute global data references will
-refer to this block.
-Only one HOL is allowed per procedure,
-it has to be placed before the first instruction.
-.OU
-.sp
-  CON <val>+ 
-.IN
-Assemble global data words initialized with the <val> constants.
-.OU
-.sp
-  ROM <val>+ 
-.IN
-Idem, but the initialized data will never be changed by the program.
-.OU
-.sp 2
-Two pseudo instructions partition the input into procedures:
-.sp 2
-  PRO <sym>[,<off>] 
-.IN
-Start of procedure.
-<sym> is the procedure name.
-<off> is the number of bytes for locals.
-The number of bytes for locals must be specified in the PRO or
-END pseudo-instruction.
-When specified in both, they must be identical.
-.OU
-.sp
-  END  [<off>]
-.IN
-End of Procedure.
-<off> is the number of bytes for locals.
-The number of bytes for locals must be specified in either the PRO or
-END pseudo-instruction or both.
-.OU
-.PP
-Names of data and procedures in a EM module can either be
-internal or external.
-External names are known outside the module and are used to link
-several pieces of a program.
-Internal names are not known outside the modules they are used in.
-Other modules will not 'see' an internal name.
-.ti +5
-In order to reduce the number of passes needed,
-it must be known at the first occurrence whether
-a name is internal or external.
-If the first occurrence of a name is in a definition,
-the name is considered to be internal.
-If the first occurrence of a name is a reference,
-the name is considered to be external.
-If the first occurrence is in one of the following pseudo instructions,
-the effect of the pseudo has precedence.
-.sp 2
-  EXA <sym> 
-.IN
-External name.
-<sym> is external to this module.
-Note that <sym> may be defined in the same module.
-.OU
-.sp
-  EXP <pro>
-.IN
-External procedure identifier.
-Note that <sym> may be defined in the same module.
-.OU
-.sp
-  INA <sym>
-.IN
-Internal name.
-<sym> is internal to this module and must be defined in this module.
-.OU
-.sp
-  INP <pro> 
-.IN
-Internal procedure.
-<sym> is internal to this module and must be defined in this module.
-.OU
-.sp 2
-Two other pseudo instructions provide miscellaneous features:
-.sp 2
-  EXC <num1>,<num2> 
-.IN
-Two blocks of instructions preceding this one are
-interchanged before being processed.
-<num1> gives the number of lines of the first block.
-<num2> gives the number of lines of the second one.
-Blank and pure comment lines do not count.
-.OU
-.sp
-  MES <num>,<val>* 
-.IN
-A special type of comment.  Used by compilers to communicate with the
-optimizer, assembler, etc. as follows:
-.br
-  MES 0 -
-.IN
-An error has occurred, stop further processing.
-.OU
-.br
-  MES 1 -
-.IN
-Suppress optimization
-.OU
-.br
-  MES 2,<num1>,<num2>
-.IN
-Use word-size <num1> and pointer size <num2>.
-.OU
-.br
-  MES 3,<off>,<num1>,<num2> -
-.IN
-Indicates that a local variable is never referenced indirectly.
-<off> is offset in bytes from LB if positive
-and offset from AB if negative.
-<num1> gives the size of the variable.
-<num2> indicates the class of the variable.
-.OU
-.br
-  MES 4,<num>,<str>
-.IN
-Number of source lines in file <str> (for profiler).
-.OU
-.br
-  MES 5 -
-.IN
-Floating point used.
-.OU
-.br
-  MES 6,<val>* -
-.IN
-Comment.  Used to provide comments in compact assembly language (see below).
-.OU
-.sp 1
-Each back end is free to skip irrelevant MES pseudos.
-.OU
-.SB "The Compact Assembly Language"
-.PP
-The assembler accepts input in a highly encoded form.  This
-form is intended to reduce the amount of file transport between the compiler
-and assembler, and also reduce the amount of storage required for storing
-libraries.
-Libraries are stored as archived compact assembly language, not machine language.
-.PP
-When beginning to read the input, the assembler is in neutral state, and
-expects either a label or an instruction (including the pseudoinstructions).
-The meaning of the next byte(s) when in neutral state is as follows, where b1, b2 
-etc. represent the succeeding bytes.
-.sp
-       0   Reserved for future use
-   1-129   Machine instructions, see Appendix 2, alphabetical list
- 130-149   Reserved for future use
- 150-161   BSS,CON,END,EXC,EXA,EXP,HOL,INA,INP,MES,PRO,ROM
- 162-179   Reserved for future pseudoinstructions
- 180-239   Instruction labels 0 - 59  (180 is local label 0 etc.)
- 240-244   See the Common Table below
- 245-255   Not used
-
-After a label, the assembler is back in neutral state; it can immediately
-accept another label or an instruction in the very next byte.  There are
-no linefeeds used to separate lines.
-.PP
-If an opcode expects no arguments,
-the assembler is back in neutral state after
-reading the one byte containing the instruction number.  If it has one or
-more arguments (only pseudos have more than 1), the arguments follow directly,
-encoded as follows:
-.sp
-   0-239     Offsets from -120 to 119
-.br
- 240-255     See the Common Table below
-.sp 2
-If an opcode has one optional argument,
-a special byte is used to announce that the argument is not present.
-.ce 1
-Common Table for Neutral State and Arguments
-.sp
-.nf
-<lab>   240 b1                Instruction label b1  (Not used for branches)
-<lab>   241 b1 b2             16 bit instruction label  (256*b2 + b1)
-<sym>   242 b1                Global label .0-.255, with b1 being the label
-<sym>   243 b1 b2             Global label .0-.32767
-			      with 256*b2+b1 being the label
-<sym>   244 <string>          Global symbol not of the form .nnn
-. \" Only the previous can occur in neutral state.
-<num>   245 b1 b2             (16 bit constant) 256*b2+b1
-<off>   246 b1 b2 b3 b4       (32 bit constant) (256*(256*(256*b4)+b3)+b2)+b1
-<arg>   247 <sym><off>        Global label + (possibly negative) constant
-<pro>   248 <string>          Procedure name  (not including $)
-<str>   249 <string>          String used in CON or ROM (no quotes)
-<con>   250 <num><string>     Integer constant, size <num> bytes
-<con>   251 <num><string>     Unsigned constant, size <num> bytes
-<con>   252 <num><string>     Floating constant, size <num> bytes
-<end>   255                   Delimiter for argument lists or
-			      indicates absence of optional argument
-
-.fi
-.PP
-The notation <string> consists first of a length field, and then an
-arbitrary string of bytes.
-The length is specified by a <num>.
-.PP
-.ne 8
-The pseudoinstructions fall into several categories, depending on their
-arguments:
-.sp
- Group 1 -- EXC, BSS, HOL have a known number of arguments
- Group 2 -- EXA, EXP, INA, INP start with a string
- Group 3 -- CON, MES, ROM have a variable number of various things
- Group 4 -- END, PRO have a trailing optional argument.
-
-Groups 1 and 2
-use the encoding described above.
-Group 3 also uses the encoding listed above, with a <end> byte after the
-last argument to indicate the end of the list.  
-Group 4 uses
-a <end> byte if the trailing argument is not present.
-
-.ad
-.fi
-.sp 2
-.ne 12
-.nf
-Example  ASCII			Example compact
-(LOC = 66, BRA = 18 here):
-
-  2				182
-  1				181
-   LOC 10			66 130
-   LOC -10			66 110
-   LOC 300			66 245 44 1
-   BRA 19			18 139
-  300				241 44 1
-  .3				242 3 
-   CON 4,9,*2,$foo		151 124 130 240 2 248 3 102 111 111 255
-   LOC .35			66 242 35
-.fi
-.nr a 0 1
-.SE "ASSEMBLY LANGUAGE INSTRUCTION LIST"
-.PP
-For each instruction in the list the range of operand values
-in the assembly language is given.
-All constants, offsets and sizes are in the range -2**31~..~2**31-1.
-The column headed \fIassem\fP contains the mnemonics defined
-in 4.1.
-The following column indicates restrictions in the range of the operand.
-Addresses have to obey the restrictions mentioned in chapter 2 - Memory -.
-The size parameter of most instructions has to be a multiple
-of the word size.
-The classes of operands
-are indicated by letters:
-.ds b \fBb\fP
-.ds c \fBc\fP
-.ds d \fBd\fP
-.ds g \fBg\fP
-.ds f \fBf\fP
-.ds l \fBl\fP
-.ds n \fBn\fP
-.ds i \fBi\fP
-.ds p \fBp\fP
-.ds r \fBr\fP
-.ds s \fBs\fP
-.ds z \fBz\fP
-.ds - \fB-\fP
-.nf
-
-  \fIassem\fP       constraints            rationale
-
-\&\*c  off                                 1-word constant
-\&\*d  off                                 2-word constant
-\&\*l  off                                 local offset
-\&\*g  arg          >= 0                   global offset
-\&\*f  off                                 fragment offset
-\&\*n  num          >= 0                   counter
-\&\*s  off          > 0                    object size
-\&\*z  off          >= 0                   object size
-\&\*i  off          > 0                    object size *
-\&\*p  pro                                 pro identifier
-\&\*b  lab          >= 0                   label number
-\&\*r  num          0,1,2                  register number
-\&\*-                                      no operand
-
-.fi
-.PP
-The * at the rationale for \*i indicates that the operand
-can either be given as argument or on top of the stack.
-If the operand has to be fetched from the stack,
-it is assumed to be a word-sized unsigned integer.
-.PP
-Instructions that check for undefined operands and underflow or overflow
-are indicated by (*).
-.nf
-
-GROUP 1 - LOAD
-
-  LOC \*c : Load constant (i.e. push one word onto the stack)
-  LDC \*d : Load double constant ( push two words )
-  LOL \*l : Load word at \*l-th local (l<0) or parameter (l>=0)
-  LOE \*g : Load external word \*g
-  LIL \*l : Load word pointed to by \*l-th local or parameter
-  LOF \*f : Load offsetted. (top of stack + \*f yield address)
-  LAL \*l : Load address of local or parameter
-  LAE \*g : Load address of external
-  LXL \*n : Load lexical. (address of LB \*n static levels back)
-  LXA \*n : Load lexical. (address of AB \*n static levels back)
-  LOI \*s : Load indirect \*s bytes (address is popped from the stack)
-  LOS \*i : Load indirect. \*i-byte integer on top of stack gives object size
-  LDL \*l : Load double local or parameter (two consecutive words are stacked)
-  LDE \*g : Load double external (two consecutive externals are stacked)
-  LDF \*f : Load double offsetted (top of stack + \*f yield address)
-  LPI \*p : Load procedure identifier
-
-GROUP 2 - STORE
-
-  STL \*l : Store local or parameter
-  STE \*g : Store external
-  SIL \*l : Store into word pointed to by \*l-th local or parameter
-  STF \*f : Store offsetted
-  STI \*s : Store indirect \*s bytes (pop address, then data)
-  STS \*i : Store indirect. \*i-byte integer on top of stack gives object size
-  SDL \*l : Store double local or parameter
-  SDE \*g : Store double external
-  SDF \*f : Store double offsetted
-
-GROUP 3 - INTEGER ARITHMETIC
-
-  ADI \*i : Addition (*)
-  SBI \*i : Subtraction (*)
-  MLI \*i : Multiplication (*)
-  DVI \*i : Division (*)
-  RMI \*i : Remainder (*)
-  NGI \*i : Negate (two's complement) (*)
-  SLI \*i : Shift left (*)
-  SRI \*i : Shift right (*)
-
-GROUP 4 - UNSIGNED ARITHMETIC
-
-  ADU \*i : Addition
-  SBU \*i : Subtraction
-  MLU \*i : Multiplication
-  DVU \*i : Division
-  RMU \*i : Remainder
-  SLU \*i : Shift left
-  SRU \*i : Shift right
-
-GROUP 5 - FLOATING POINT ARITHMETIC   (Format not defined)
-
-  ADF \*i : Floating add (*)
-  SBF \*i : Floating subtract (*)
-  MLF \*i : Floating multiply (*)
-  DVF \*i : Floating divide (*)
-  NGF \*i : Floating negate (*)
-  FIF \*i : Floating multiply and split integer and fraction part (*)
-  FEF \*i : Split floating number in exponent and fraction part (*)
-
-GROUP 6 - POINTER ARITHMETIC
-
-  ADP \*f : Add \*c to pointer on top of stack
-  ADS \*i : Add \*i-byte value and pointer
-  SBS \*i : Subtract pointers in same fragment and push diff as size \*i integer
-
-GROUP 7 - INCREMENT/DECREMENT/ZERO
-
-  INC \*- : Increment top of stack by 1 (*)
-  INL \*l : Increment local or parameter (*)
-  INE \*g : Increment external (*)
-  DEC \*- : Decrement top of stack by 1 (*)
-  DEL \*l : Decrement local or parameter (*)
-  DEE \*g : Decrement external (*)
-  ZRL \*l : Zero local or parameter
-  ZRE \*g : Zero external
-  ZRF \*i : Load a floating zero of size \*i
-  ZER \*i : Load \*i zero bytes
-
-GROUP 8 - CONVERT    ( stack: source, source size, dest. size (top) )
-
-  CII \*- : Convert integer to integer (*)
-  CUI \*- : Convert unsigned to integer (*)
-  CFI \*- : Convert floating to integer (*)
-  CIF \*- : Convert integer to floating (*)
-  CUF \*- : Convert unsigned to floating (*)
-  CFF \*- : Convert floating to floating (*)
-  CIU \*- : Convert integer to unsigned
-  CUU \*- : Convert unsigned to unsigned
-  CFU \*- : Convert floating to unsigned
-
-GROUP 9 - LOGICAL
-
-  AND \*i : Boolean and on two groups of \*i bytes
-  IOR \*i : Boolean inclusive or on two groups of \*i bytes
-  XOR \*i : Boolean exclusive or on two groups of \*i bytes
-  COM \*i : Complement (one's complement of top \*i bytes)
-  ROL \*i : Rotate left a group of \*i bytes
-  ROR \*i : Rotate right a group of \*i bytes
-
-GROUP 10 - SETS
-
-  INN \*i : Bit test on \*i byte set (bit number on top of stack)
-  SET \*i : Create singleton \*i byte set with bit n on (n is top of stack)
-
-GROUP 11 - ARRAY
- 
-  LAR \*i : Load array element, descriptor contains integers of size \*i
-  SAR \*i : Store array element
-  AAR \*i : Load address of array element
-
-GROUP 12 - COMPARE
-
-  CMI \*i : Compare \*i byte integers. Push negative, zero, positive for <, = or >
-  CMF \*i : Compare \*i byte reals
-  CMU \*i : Compare \*i byte unsigneds
-  CMS \*i : Compare \*i byte sets. can only be used for equality test.
-  CMP \*- : Compare pointers
-
-  TLT \*- : True if less, i.e. iff top of stack < 0
-  TLE \*- : True if less or equal, i.e. iff top of stack <= 0
-  TEQ \*- : True if equal, i.e. iff top of stack = 0
-  TNE \*- : True if not equal, i.e. iff top of stack non zero
-  TGE \*- : True if greater or equal, i.e. iff top of stack >= 0
-  TGT \*- : True if greater, i.e. iff top of stack > 0
-
-GROUP 13 - BRANCH
-
-  BRA \*b : Branch unconditionally to label \*b
-
-  BLT \*b : Branch less (pop 2 words, branch if top > second)
-  BLE \*b : Branch less or equal
-  BEQ \*b : Branch equal
-  BNE \*b : Branch not equal
-  BGE \*b : Branch greater or equal
-  BGT \*b : Branch greater
-
-  ZLT \*b : Branch less than zero (pop 1 word, branch negative)
-  ZLE \*b : Branch less or equal to zero
-  ZEQ \*b : Branch equal zero
-  ZNE \*b : Branch not zero
-  ZGE \*b : Branch greater or equal zero
-  ZGT \*b : Branch greater than zero
-
-GROUP 14 - PROCEDURE CALL
-
-  CAI \*- : Call procedure (procedure instance identifier on stack)
-  CAL \*p : Call procedure (with name \*p)
-  LFR \*s : Load function result
-  RET \*z : Return (function result consists of top \*z bytes)
-
-GROUP 15 - MISCELLANEOUS
-
-  ASP \*f : Adjust the stack pointer by \*f
-  ASS \*i : Adjust the stack pointer by \*i-byte integer
-  BLM \*z : Block move \*z bytes; first pop destination addr, then source addr
-  BLS \*i : Block move, size is in \*i-byte integer on top of stack
-  CSA \*i : Case jump; address of jump table at top of stack
-  CSB \*i : Table lookup jump; address of jump table at top of stack
-  DUP \*s : Duplicate top \*s bytes
-  DUS \*i : Duplicate top \*i bytes
-  FIL \*g : File name (external 4 := \*g)
-  LIM \*- : Load 16 bit ignore mask
-  LIN \*n : Line number (external 0 := \*n)
-  LNI \*- : Line number increment
-  LOR \*r : Load register (0=LB, 1=SP, 2=HP)
-  MON \*- : Monitor call
-  NOP \*- : No operation
-  RCK \*i : Range check; trap on error
-  RTT \*- : Return from trap
-  SIG \*- : Trap errors to proc nr on top of stack (-2 resets default).  Static
-          link of procedure is below procedure number. Old values returned
-  SIM \*- : Store 16 bit ignore mask
-  STR \*r : Store register (0=LB, 1=SP, 2=HP)
-  TRP \*- : Cause trap to occur (Error number on stack)
-.fi

+ 0 - 488
doc/em/app.nr

@@ -1,488 +0,0 @@
-.BP
-.AP "EM INTERPRETER"
-.nf
-.ta 8 16 24 32 40 48 56 64 72 80
-.so em.i
-.fi
-.BP
-.AP "EM CODE TABLES"
-The following table is used by the assembler for EM machine
-language.
-It specifies the opcodes used for each instruction and
-how arguments are mapped to machine language arguments.
-The table is presented in three columns,
-each line in each column contains three or four fields.
-Each line describes a range of interpreter opcodes by
-specifying for which instruction the range is used, the type of the
-opcodes (mini, shortie, etc..) and range for the instruction
-argument.
-.A
-The first field on each line gives the EM instruction mnemonic,
-the second field gives some flags.
-If the opcodes are minis or shorties the third field specifies
-how many minis/shorties are used.
-The last field gives the number of the (first) interpreter
-opcode.
-.N 1
-Flags :
-.IS 3
-.N 1
-Opcode type, only one of the following may be specified.
-.PS - 5 "  "
-.PT -
-opcode without argument
-.PT m
-mini
-.PT s
-shortie
-.PT 2
-opcode with 2-byte signed argument
-.PT 4
-opcode with 4-byte signed argument
-.PT 8
-opcode with 8-byte signed argument
-.PE
-Secondary (escaped) opcodes.
-.PS - 5 "  "
-.PT e
-The opcode thus marked is in the secondary opcode group instead
-of the primary
-.PE
-restrictions on arguments
-.PS - 5 "  "
-.PT N
-Negative arguments only
-.PT P
-Positive and zero arguments only
-.PE
-mapping of arguments
-.PS - 5 "  "
-.PT w
-argument must be divisible by the wordsize and is divided by the
-wordsize before use as opcode argument.
-.PT o
-argument ( possibly after division ) must be >= 1 and is
-decremented before use as opcode argument
-.PE
-.IE
-If the opcode type is 2,4 or 8 the resulting argument is used as
-opcode argument (least significant byte first).
-.N
-If the opcode type is mini, the argument is added
-to the first opcode - if in range - .
-If the argument is negative, the absolute value minus one is
-used in the algorithm above.
-.N
-For shorties with positive arguments the first opcode is used
-for arguments in the range 0..255, the second for the range
-256..511, etc..
-For shorties with negative arguments the first opcode is used
-for arguments in the range -1..-256, the second for the range
--257..-512, etc..
-The byte following the opcode contains the least significant
-byte of the argument.
-First some examples of these specifications.
-.PS - 5
-.PT "aar mwPo 1 34"
-Indicates that opcode 34 is used as a mini for Positive
-instruction arguments only.
-The w and o indicate division and decrementing of the
-instruction argument.
-Because the resulting argument must be zero ( only opcode 34 may be used
-), this mini can only be used for instruction argument 2.
-Conclusion: opcode 34 is for "AAR 2".
-.PT "adp sP 1 41"
-Opcode 41 is used as shortie for ADP with arguments in the range
-0..255.
-.PT "bra sN 2 60"
-Opcode 60 is used as shortie for BRA with arguments -1..-256,
-61 is used for arguments -257..-512.
-.PT "zer e- 145"
-Escaped opcode 145 is used for ZER.
-.PE
-The interpreter opcode table:
-.N 1
-.IS 3
-.DS B
-.so itables
-.DE 0
-.IE
-.P
-The table above results in the following dispatch tables.
-Dispatch tables are used by interpreters to jump to the
-routines implementing the EM instructions, indexed by the next opcode.
-Each line of the dispatch tables gives the routine names
-of eight consecutive opcodes, preceded by the first opcode number
-on that line.
-Routine names consist of an EM mnemonic followed by a suffix.
-The suffices show the encoding used for each opcode.
-.N
-The following suffices exist:
-.N 1
-.VS 1 0
-.IS 4
-.PS - 11
-.PT .z
-no arguments
-.PT .l
-16-bit argument
-.PT .lw
-16-bit argument divided by the wordsize
-.PT .p
-positive 16-bit argument
-.PT .pw
-positive 16-bit argument divided by the wordsize
-.PT .n
-negative 16-bit argument
-.PT .nw
-negative 16-bit argument divided by the wordsize
-.PT .s<num>
-shortie with <num> as high order argument byte
-.PT .sw<num>
-shortie with argument divided by the wordsize
-.PT .<num>
-mini with <num> as argument
-.PT .<num>W
-mini with <num>*wordsize as argument
-.PE 3
-<num> is a possibly negative integer.
-.VS 1 1
-.IE
-The dispatch table for the 256 primary opcodes:
-.DS B
-   0   loc.0    loc.1    loc.2    loc.3    loc.4    loc.5    loc.6    loc.7
-   8   loc.8    loc.9    loc.10   loc.11   loc.12   loc.13   loc.14   loc.15
-  16   loc.16   loc.17   loc.18   loc.19   loc.20   loc.21   loc.22   loc.23
-  24   loc.24   loc.25   loc.26   loc.27   loc.28   loc.29   loc.30   loc.31
-  32   loc.32   loc.33   aar.1W   adf.s0   adi.1W   adi.2W   adp.l    adp.1
-  40   adp.2    adp.s0   adp.s-1  ads.1W   and.1W   asp.1W   asp.2W   asp.3W
-  48   asp.4W   asp.5W   asp.w0   beq.l    beq.s0   bge.s0   bgt.s0   ble.s0
-  56   blm.s0   blt.s0   bne.s0   bra.l    bra.s-1  bra.s-2  bra.s0   bra.s1
-  64   cal.1    cal.2    cal.3    cal.4    cal.5    cal.6    cal.7    cal.8
-  72   cal.9    cal.10   cal.11   cal.12   cal.13   cal.14   cal.15   cal.16
-  80   cal.17   cal.18   cal.19   cal.20   cal.21   cal.22   cal.23   cal.24
-  88   cal.25   cal.26   cal.27   cal.28   cal.s0   cff.z    cif.z    cii.z
-  96   cmf.s0   cmi.1W   cmi.2W   cmp.z    cms.s0   csa.1W   csb.1W   dec.z
- 104   dee.w0   del.w-1  dup.1W   dvf.s0   dvi.1W   fil.l    inc.z    ine.lw
- 112   ine.w0   inl.-1W  inl.-2W  inl.-3W  inl.w-1  inn.s0   ior.1W   ior.s0
- 120   lae.l    lae.w0   lae.w1   lae.w2   lae.w3   lae.w4   lae.w5   lae.w6
- 128   lal.p    lal.n    lal.0    lal.-1   lal.w0   lal.w-1  lal.w-2  lar.W
- 136   ldc.0    lde.lw   lde.w0   ldl.0    ldl.w-1  lfr.1W   lfr.2W   lfr.s0
- 144   lil.w-1  lil.w0   lil.0    lil.1W   lin.l    lin.s0   lni.z    loc.l
- 152   loc.-1   loc.s0   loc.s-1  loe.lw   loe.w0   loe.w1   loe.w2   loe.w3
- 160   loe.w4   lof.l    lof.1W   lof.2W   lof.3W   lof.4W   lof.s0   loi.l
- 168   loi.1    loi.1W   loi.2W   loi.3W   loi.4W   loi.s0   lol.pw   lol.nw
- 176   lol.0    lol.1W   lol.2W   lol.3W   lol.-1W  lol.-2W  lol.-3W  lol.-4W
- 184   lol.-5W  lol.-6W  lol.-7W  lol.-8W  lol.w0   lol.w-1  lxa.1    lxl.1
- 192   lxl.2    mlf.s0   mli.1W   mli.2W   rck.1W   ret.0    ret.1W   ret.s0
- 200   rmi.1W   sar.1W   sbf.s0   sbi.1W   sbi.2W   sdl.w-1  set.s0   sil.w-1
- 208   sil.w0   sli.1W   ste.lw   ste.w0   ste.w1   ste.w2   stf.l    stf.W
- 216   stf.2W   stf.s0   sti.1    sti.1W   sti.2W   sti.3W   sti.4W   sti.s0
- 224   stl.pw   stl.nw   stl.0    stl.1W   stl.-1W  stl.-2W  stl.-3W  stl.-4W
- 232   stl.-5W  stl.w-1  teq.z    tgt.z    tlt.z    tne.z    zeq.l    zeq.s0
- 240   zeq.s1   zer.s0   zge.s0   zgt.s0   zle.s0   zlt.s0   zne.s0   zne.s-1
- 248   zre.lw   zre.w0   zrl.-1W  zrl.-2W  zrl.w-1  zrl.nw   escape1  escape2
-.DE 2
-The list of secondary opcodes (escape1):
-.N  1
-.DS  B
-   0   aar.l    aar.z    adf.l    adf.z    adi.l    adi.z    ads.l    ads.z
-   8   adu.l    adu.z    and.l    and.z    asp.lw   ass.l    ass.z    bge.l
-  16   bgt.l    ble.l    blm.l    bls.l    bls.z    blt.l    bne.l    cai.z
-  24   cal.l    cfi.z    cfu.z    ciu.z    cmf.l    cmf.z    cmi.l    cmi.z
-  32   cms.l    cms.z    cmu.l    cmu.z    com.l    com.z    csa.l    csa.z
-  40   csb.l    csb.z    cuf.z    cui.z    cuu.z    dee.lw   del.pw   del.nw
-  48   dup.l    dus.l    dus.z    dvf.l    dvf.z    dvi.l    dvi.z    dvu.l
-  56   dvu.z    fef.l    fef.z    fif.l    fif.z    inl.pw   inl.nw   inn.l
-  64   inn.z    ior.l    ior.z    lar.l    lar.z    ldc.l    ldf.l    ldl.pw
-  72   ldl.nw   lfr.l    lil.pw   lil.nw   lim.z    los.l    los.z    lor.s0
-  80   lpi.l    lxa.l    lxl.l    mlf.l    mlf.z    mli.l    mli.z    mlu.l
-  88   mlu.z    mon.z    ngf.l    ngf.z    ngi.l    ngi.z    nop.z    rck.l
-  96   rck.z    ret.l    rmi.l    rmi.z    rmu.l    rmu.z    rol.l    rol.z
- 104   ror.l    ror.z    rtt.z    sar.l    sar.z    sbf.l    sbf.z    sbi.l
- 112   sbi.z    sbs.l    sbs.z    sbu.l    sbu.z    sde.l    sdf.l    sdl.pw
- 120   sdl.nw   set.l    set.z    sig.z    sil.pw   sil.nw   sim.z    sli.l
- 128   sli.z    slu.l    slu.z    sri.l    sri.z    sru.l    sru.z    sti.l
- 136   sts.l    sts.z    str.s0   tge.z    tle.z    trp.z    xor.l    xor.z
- 144   zer.l    zer.z    zge.l    zgt.l    zle.l    zlt.l    zne.l    zrf.l
- 152   zrf.z    zrl.pw   dch.z    exg.s0   exg.l    exg.z    lpb.z    gto.l
-.DE 2
-Finally, the list of opcodes with four byte arguments (escape2).
-.DS
-
-   0  loc
-.DE 0
-.BP
-.AP "AN EXAMPLE PROGRAM"
-.DS B
- 1      program example(output);
- 2      {This program just demonstrates typical EM code.}
- 3      type rec = record r1: integer; r2:real; r3: boolean end;
- 4      var mi: integer;  mx:real;  r:rec;
- 5
- 6      function sum(a,b:integer):integer;
- 7      begin
- 8        sum := a + b
- 9      end;
-10
-11      procedure test(var r: rec);
-12      label 1;
-13      var i,j: integer;
-14          x,y: real;
-15          b: boolean;
-16          c: char;
-17          a: array[1..100] of integer;
-18
-19      begin
-20              j := 1;
-21              i := 3 * j + 6;
-22              x := 4.8;
-23              y := x/0.5;
-24              b := true;
-25              c := 'z';
-26              for i:= 1 to 100 do a[i] := i * i;
-27              r.r1 := j+27;
-28              r.r3 := b;
-29              r.r2 := x+y;
-30              i := sum(r.r1, a[j]);
-31              while i > 0 do begin j := j + r.r1; i := i - 1 end;
-32              with r do begin r3 := b;  r2 := x+y;  r1 := 0 end;
-33              goto 1;
-34      1:      writeln(j, i:6, x:9:3, b)
-35      end; {test}
-36      begin {main program}
-37        mx := 15.96;
-38        mi := 99;
-39        test(r)
-40      end.
-.DE 0
-.BP
-The EM code as produced by the Pascal-VU compiler is given below. Comments
-have been added manually.  Note that this code has already been  optimized.
-.DS B
-  mes 2,2,2              ; wordsize 2, pointersize 2
- .1
-  rom 't.p\e000'         ; the name of the source file
-  hol 552,-32768,0       ; externals and buf occupy 552 bytes
-  exp $sum               ; sum can be called from other modules
-  pro $sum,2             ; procedure sum; 2 bytes local storage
-  lin 8                  ; code from source line 8
-  ldl 0                  ; load two locals ( a and b )
-  adi 2                  ; add them
-  ret 2                  ; return the result
-  end 2                  ; end of procedure ( still two bytes local storage )
- .2
-  rom 1,99,2             ; descriptor of array a[]
-  exp $test              ; the compiler exports all level 0 procedures
-  pro $test,226          ; procedure test, 226 bytes local storage
- .3
-  rom 4.8F8              ; assemble Floating point 4.8 (8 bytes) in
- .4                              ; global storage
-  rom 0.5F8              ; same for 0.5
-  mes 3,-226,2,2         ; compiler temporary not referenced by address
-  mes 3,-24,2,0          ; the same is true for i, j, b and c in test
-  mes 3,-22,2,0
-  mes 3,-4,2,0
-  mes 3,-2,2,0
-  mes 3,-20,8,0          ; and for x and y
-  mes 3,-12,8,0
-  lin 20                 ; maintain source line number
-  loc 1
-  stl -4                 ; j := 1
-  lni                    ; lin 21 prior to optimization
-  lol -4
-  loc 3
-  mli 2
-  loc 6
-  adi 2
-  stl -2                 ; i := 3 * j + 6
-  lni                    ; lin 22 prior to optimization
-  lae .3
-  loi 8
-  lal -12
-  sti 8                  ; x := 4.8
-  lni                    ; lin 23 prior to optimization
-  lal -12
-  loi 8
-  lae .4
-  loi 8
-  dvf 8
-  lal -20
-  sti 8                  ; y := x / 0.5
-  lni                    ; lin 24 prior to optimization
-  loc 1
-  stl -22                ; b := true
-  lni                    ; lin 25 prior to optimization
-  loc 122
-  stl -24                ; c := 'z'
-  lni                    ; lin 26 prior to optimization
-  loc 1
-  stl -2                 ; for i:= 1
- 2
-  lol -2
-  dup 2
-  mli 2                  ; i*i
-  lal -224
-  lol -2
-  lae .2
-  sar 2                  ; a[i] :=
-  lol -2
-  loc 100
-  beq *3                 ; to 100 do
-  inl -2                 ; increment i and loop
-  bra *2
- 3
-  lin 27
-  lol -4
-  loc 27
-  adi 2                  ; j + 27
-  sil 0                  ; r.r1 :=
-  lni                    ; lin 28 prior to optimization
-  lol -22                ; b
-  lol 0
-  stf 10                 ; r.r3 :=
-  lni                    ; lin 29 prior to optimization
-  lal -20
-  loi 16
-  adf 8                  ; x + y
-  lol 0
-  adp 2
-  sti 8                  ; r.r2 :=
-  lni                    ; lin 23 prior to optimization
-  lal -224
-  lol -4
-  lae .2
-  lar 2                  ; a[j]
-  lil 0                  ; r.r1
-  cal $sum               ; call now
-  asp 4                  ; remove parameters from stack
-  lfr 2                  ; get function result
-  stl -2                 ; i :=
- 4
-  lin 31
-  lol -2
-  zle *5                 ; while i > 0 do
-  lol -4
-  lil 0
-  adi 2
-  stl -4                 ; j := j + r.r1
-  del -2                 ; i := i - 1
-  bra *4                 ; loop
- 5
-  lin 32
-  lol 0
-  stl -226               ; make copy of address of r
-  lol -22
-  lol -226
-  stf 10                 ; r3 := b
-  lal -20
-  loi 16
-  adf 8
-  lol -226
-  adp 2
-  sti 8                  ; r2 := x + y
-  loc 0
-  sil -226               ; r1 := 0
-  lin 34                 ; note the abscence of the unnecesary jump
-  lae 22                 ; address of output structure
-  lol -4
-  cal $_wri              ; write integer with default width
-  asp 4                  ; pop parameters
-  lae 22
-  lol -2
-  loc 6
-  cal $_wsi              ; write integer width 6
-  asp 6
-  lae 22
-  lal -12
-  loi 8
-  loc 9
-  loc 3
-  cal $_wrf              ; write fixed format real, width 9, precision 3
-  asp 14
-  lae 22
-  lol -22
-  cal $_wrb              ; write boolean, default width
-  asp 4
-  lae 22
-  cal $_wln              ; writeln
-  asp 2
-  ret 0                  ; return, no result
-  end 226
-  exp $_main
-  pro $_main,0           ; main program
- .6
-  con 2,-1,22            ; description of external files
- .5
-  rom 15.96F8
-  fil .1                 ; maintain source file name
-  lae .6                 ; description of external files
-  lae 0                  ; base of hol area to relocate buffer addresses
-  cal $_ini              ; initialize files, etc...
-  asp 4
-  lin 37
-  lae .5
-  loi 8
-  lae 2
-  sti 8                  ; mx := 15.96
-  lni                    ; lin 38 prior to optimization
-  loc 99
-  ste 0                  ; mi := 99
-  lni                    ; lin 39 prior to optimization
-  lae 10                 ; address of r
-  cal $test
-  asp 2
-  loc 0                  ; normal exit
-  cal $_hlt              ; cleanup and finish
-  asp 2
-  end 0
-  mes 5                  ; reals were used
-.DE 0
-The compact code corresponding to the above program is listed below.
-Read it horizontally, line by line, not column by column.
-Each number represents a byte of compact code, printed in decimal.
-The first two bytes form the magic word.
-.N 1
-.IS 3
-.DS B
-173   0 159 122 122 122 255 242   1 161 250 124 116  46 112   0
-255 156 245  40   2 245   0 128 120 155 249 123 115 117 109 160
-249 123 115 117 109 122  67 128  63 120   3 122  88 122 152 122
-242   2 161 121 219 122 255 155 249 124 116 101 115 116 160 249
-124 116 101 115 116 245 226   0 242   3 161 253 128 123  52  46
- 56 255 242   4 161 253 128 123  48  46  53 255 159 123 245  30
-255 122 122 255 159 123  96 122 120 255 159 123  98 122 120 255
-159 123 116 122 120 255 159 123 118 122 120 255 159 123 100 128
-120 255 159 123 108 128 120 255  67 140  69 121 113 116  68  73
-116  69 123  81 122  69 126   3 122 113 118  68  57 242   3  72
-128  58 108 112 128  68  58 108  72 128  57 242   4  72 128  44
-128  58 100 112 128  68  69 121 113  98  68  69 245 122   0 113
- 96  68  69 121 113 118 182  73 118  42 122  81 122  58 245  32
-255  73 118  57 242   2  94 122  73 118  69 220  10 123  54 118
- 18 122 183  67 147  73 116  69 147   3 122 104 120  68  73  98
- 73 120 111 130  68  58 100  72 136   2 128  73 120   4 122 112
-128  68  58 245  32 255  73 116  57 242   2  59 122  65 120  20
-249 123 115 117 109   8 124  64 122 113 118 184  67 151  73 118
-128 125  73 116  65 120   3 122 113 116  41 118  18 124 185  67
-152  73 120 113 245  30 255  73  98  73 245  30 255 111 130  58
-100  72 136   2 128  73 245  30 255   4 122 112 128  69 120 104
-245  30 255  67 154  57 142  73 116  20 249 124  95 119 114 105
-  8 124  57 142  73 118  69 126  20 249 124  95 119 115 105   8
-126  57 142  58 108  72 128  69 129  69 123  20 249 124  95 119
-114 102   8 134  57 142  73  98  20 249 124  95 119 114  98   8
-124  57 142  20 249 124  95 119 108 110   8 122  88 120 152 245
-226   0 155 249 125  95 109  97 105 110 160 249 125  95 109  97
-105 110 120 242   6 151 122 119 142 255 242   5 161 253 128 125
- 49  53  46  57  54 255  50 242   1  57 242   6  57 120  20 249
-124  95 105 110 105   8 124  67 157  57 242   5  72 128  57 122
-112 128  68  69 219 110 120  68  57 130  20 249 124 116 101 115
-116   8 122  69 120  20 249 124  95 104 108 116   8 122 152 120
-159 124 160 255 159 125 255
-.DE 0
-.IE
-.MS T A 0
-.ME
-.BP
-.MS B A 0
-.ME
-.CT

+ 0 - 773
doc/em/assem.nr

@@ -1,773 +0,0 @@
-.BP
-.SN 11
-.S1 "EM ASSEMBLY LANGUAGE"
-We use two representations for assembly language programs,
-one is in ASCII and the other is the compact assembly language.
-The latter needs less space than the first for the same program
-and therefore allows faster processing.
-Our only program accepting ASCII assembly
-language converts it to the compact form.
-All other programs expect compact assembly input.
-The first part of the chapter describes the ASCII assembly
-language and its semantics.
-The second part describes the syntax of the compact assembly
-language.
-The last part lists the EM instructions with the type of
-arguments allowed and an indication of the function.
-Appendix A gives a detailed description of the effect of all
-instructions in the form of a Pascal program.
-.S2 "ASCII assembly language"
-An assembly language program consists of a series of lines, each
-line may be blank, contain one (pseudo)instruction or contain one
-label.
-Input to the assembler is in lower case.
-Upper case is used in this
-document merely to distinguish keywords from the surrounding prose.
-Comment is allowed at the end of each line and starts with a semicolon ";".
-This kind of comment does not exist in the compact form.
-.A
-Labels must be placed all by themselves on a line and start in
-column 1.
-There are two kinds of labels, instruction and data labels.
-Instruction labels are unsigned positive integers.
-The scope of an instruction label is its procedure.
-.A
-The pseudoinstructions CON, ROM and BSS may be preceded by a
-line containing a
-1-8 character data label, the first character of which is a
-letter, period or underscore.
-The period may only be followed by
-digits, the others may be followed by letters, digits and underscores.
-The use of the character "." followed by a constant,
-which must be in the range 1 to 32767 (e.g. ".40") is recommended
-for compiler
-generated programs.
-These labels are considered as a special case and handled
-more efficiently in compact assembly language (see below).
-Note that a data label on its own or two consecutive labels are not
-allowed.
-.P
-Each statement may contain an instruction mnemonic or pseudoinstruction.
-These must begin in column 2 or later (not column 1) and must be followed
-by a space, tab, semicolon or LF.
-Everything on the line following a semicolon is
-taken as a comment.
-.P
-Each input file contains one module.
-A module may contain many procedures,
-which may be nested.
-A procedure consists of
-a PRO statement, a (possibly empty)
-collection of instructions and pseudoinstructions and finally an END
-statement.
-Pseudoinstructions are also allowed between procedures.
-They do not belong to a specific procedure.
-.P
-All constants in EM are interpreted in the decimal base.
-The ASCII assembly language accepts constant expressions
-wherever constants are allowed.
-The operators recognized are: +, -, *, % and / with the usual
-precedence order.
-Use of the parentheses ( and ) to alter the precedence order is allowed.
-.S3 "Instruction arguments"
-Unlike many other assembly languages, the EM assembly
-language requires all arguments of normal and pseudoinstructions
-to be either a constant or an identifier, but not a combination
-of these two.
-There is one exception to this rule: when a data label is used
-for initialization or as an instruction argument,
-expressions of the form 'label+constant' and 'label-constant'
-are allowed.
-This makes it possible to address, for example, the
-third word of a ten word BSS block
-directly.
-Thus LOE LABEL+4 is permitted and so is CON LABEL+3.
-The resulting address is must be in the same fragment as the label.
-It is not allowed to add or subtract from instruction labels or procedure
-identifiers,
-which certainly is not a severe restriction and greatly aids
-optimization.
-.P
-Instruction arguments can be constants,
-data labels, data labels offsetted by a constant, instruction
-labels and procedure identifiers.
-The range of integers allowed depends on the instruction.
-Most instructions allow only integers
-(signed or unsigned)
-that fit in a word.
-Arguments used as offsets to pointers should fit in a
-pointer-sized integer.
-Finally, arguments to LDC should fit in a double-word integer.
-.P
-Several instructions have two possible forms:
-with an explicit argument and with an implicit argument on top of the stack.
-The size of the implicit argument is the wordsize.
-The implicit argument is always popped before all other operands.
-For example: 'CMI 4' specifies that two four-byte signed
-integers on top of the stack are to be compared.
-\&'CMI' without an argument expects a wordsized integer
-on top of the stack that specifies the size of the integers to
-be compared.
-Thus the following two sequences are equivalent:
-.N 2
-.TS
-center, tab(:) ;
-l r 30 l r.
-LDL:-10:LDL:-10
-LDL:-14:LDL:-14
-::LOC:4
-CMI:4:CMI:
-ZEQ:*1:ZEQ:*1
-.TE 2
-Section 11.1.6 shows the arguments allowed for each instruction.
-.S3 "Pseudoinstruction arguments"
-Pseudoinstruction arguments can be divided in two classes:
-Initializers and others.
-The following initializers are allowed: signed integer constants,
-unsigned integer constants, floating-point constants, strings,
-data labels, data labels offsetted by a constant, instruction
-labels and procedure identifiers.
-.P
-Constant initializers in BSS, HOL, CON and ROM pseudoinstructions
-can be followed by a letter I, U or F.
-This indicator
-specifies the type of the initializer: Integer, Unsigned or Float.
-If no indicator is present I is assumed.
-The size of the initializer is the wordsize unless
-the indicator is followed by an integer specifying the
-initializer's size.
-This integer is governed by the same restrictions as for
-transfer of objects to/from memory.
-As in instruction arguments, initializers include expressions of the form:
-\&"LABEL+offset" and "LABEL-offset".
-The offset must be an unsigned decimal constant.
-The 'IUF' indicators cannot be used in the offsets.
-.P
-Data labels are referred to by their name.
-.P
-
-Strings are surrounded by double quotes (").
-Semicolon's in string do not indicate the start of comment.
-In the ASCII representation the escape character \e (backslash)
-alters the meaning of subsequent character(s).
-This feature allows inclusion of zeroes, graphic characters and
-the double quote in the string.
-The following escape sequences exist:
-.DS
-.TS
-center, tab(:);
-l l l.
-newline:NL\|(LF):\en
-horizontal tab:HT:\et
-backspace:BS:\eb
-carriage return:CR:\er
-form feed:FF:\ef
-backslash:\e:\e\e
-double quote:":\e"
-bit pattern:\fBddd\fP:\e\fBddd\fP
-.TE
-.DE
-The escape \fBddd\fP consists of the backslash followed by 1,
-2, or 3 octal digits specifing the value of
-the desired character.
-If the character following a backslash is not one of those
-specified,
-the backslash is ignored.
-Example: CON "hello\e012\e0".
-Each string element initializes a single byte.
-The ASCII character set is used to map characters onto values.
-.P
-Instruction labels are referred to as *1, *2, etc.  in both branch
-instructions and as initializers.
-.P
-The notation $procname means the identifier for the procedure
-with the specified name.
-This identifier has the size of a pointer.
-.S3 Notation
-First, the notation used for the arguments, classes of
-instructions and pseudoinstructions.
-.IS 2
-.TS
-tab(:);
-l l l.
-<cst>:\&=:integer constant (current range -2**31..2**31-1)
-<dlb>:\&=:data label
-<arg>:\&=:<cst> or <dlb> or <dlb>+<cst> or <dlb>-<cst>
-<con>:\&=:integer constant, unsigned constant, floating-point constant
-<str>:\&=:string constant (surrounded by double quotes),
-<ilb>:\&=:instruction label
-::'*' followed by an integer in the range 0..32767.
-<pro>:\&=:procedure number ('$' followed by a procedure name)
-<val>:\&=:<arg>, <con>, <pro> or <ilb>.
-<par>:\&=:<val> or <str>
-<...>*:\&=:zero or more of <...>
-<...>+:\&=:one or more of <...>
-[...]:\&=:optional ...
-.TE
-.IE
-.S3 "Pseudoinstructions"
-.S4 Storage declaration
-Initialized global data is allocated by the pseudoinstruction CON,
-which needs at least one argument.
-Each argument is used to allocate and initialize a number of
-consequtive bytes in data memory.
-The number of bytes to be allocated and the alignment depend on the type
-of the argument.
-For each argument, an integral number of words,
-determined by the argument type, is allocated and initialized.
-.P
-The pseudoinstruction ROM is the same as CON,
-except that it guarantees that the initialized words
-will not change during the execution of the program.
-This information allows optimizers to do
-certain calculations such as array indexing and
-subrange checking at compile time instead
-of at run time.
-.P
-The pseudoinstruction BSS allocates
-uninitialized global data or large blocks of data initialized
-by the same value.
-The first argument to this pseudo is the number
-of bytes required, which must be a multiple of the wordsize.
-The other arguments specify the value used for initialization and
-whether the initialization is only for convenience or a strict necessity.
-The pseudoinstruction HOL is similar to BSS in that it requests an
-(un)initialized global data block.
-Addressing of a HOL block, however, is quasi absolute.
-The first byte is addressed by 0,
-the second byte by 1 etc. in assembly language.
-The assembler/loader adds the base address of
-the HOL block to these numbers to obtain the
-absolute address in the machine language.
-.P
-The scope of a HOL block starts at the HOL pseudo and
-ends at the next HOL pseudo or at the end of a module
-whatever comes first.
-Each instruction falls in the scope of at most one
-HOL block, the current HOL block.
-It is not allowed to have more than one HOL block per procedure.
-.P
-The alignment restrictions are enforced by the
-pseudoinstructions.
-All initializers are aligned on a multiple of their size or the wordsize
-whichever is smaller.
-Strings form an exception, they are to be seen as a sequence of initializers
-each for one byte, i.e. strings are not padded with zero bytes.
-Switching to another type of fragment or placing a label forces
-word-alignment.
-There are three types of fragments in global data space: CON, ROM and
-BSS/HOL.
-.N 2
-.IS 2
-.PS - 4
-.PT "BSS <cst1>,<val>,<cst2>"
-Reserve <cst1> bytes.
-<val> is the value used to initialize the area.
-<cst1> must be a multiple of the size of <val>.
-<cst2> is 0 if the initialization is not strictly necessary,
-1 if it is.
-.PT "HOL <cst1>,<val>,<cst2>"
-Idem, but all following absolute global data references will
-refer to this block.
-Only one HOL is allowed per procedure,
-it has to be placed before the first instruction.
-.PT "CON <val>+"
-Assemble global data words initialized with the <val> constants.
-.PT "ROM <val>+"
-Idem, but the initialized data will never be changed by the program.
-.PE
-.IE
-.S4 Partitioning
-Two pseudoinstructions partition the input into procedures:
-.IS 2
-.PS - 4
-.PT "PRO <pro>[,<cst>]"
-Start of procedure.
-<pro> is the procedure name.
-<cst> is the number of bytes for locals.
-The number of bytes for locals must be specified in the PRO or
-END pseudoinstruction.
-When specified in both, they must be identical.
-.PT "END  [<cst>]"
-End of Procedure.
-<cst> is the number of bytes for locals.
-The number of bytes for locals must be specified in either the PRO or
-END pseudoinstruction or both.
-.PE
-.IE
-.S4 Visibility
-Names of data and procedures in an EM module can either be
-internal or external.
-External names are known outside the module and are used to link
-several pieces of a program.
-Internal names are not known outside the modules they are used in.
-Other modules will not 'see' an internal name.
-.A
-To reduce the number of passes needed,
-it must be known at the first occurrence whether
-a name is internal or external.
-If the first occurrence of a name is in a definition,
-the name is considered to be internal.
-If the first occurrence of a name is a reference,
-the name is considered to be external.
-If the first occurrence is in one of the following pseudoinstructions,
-the effect of the pseudo has precedence.
-.IS 2
-.PS - 4
-.PT "EXA <dlb>"
-External name.
-<dlb> is known, possibly defined, outside this module.
-Note that <dlb> may be defined in the same module.
-.PT "EXP <pro>"
-External procedure identifier.
-Note that <pro> may be defined in the same module.
-.PT "INA <dlb>"
-Internal name.
-<dlb> is internal to this module and must be defined in this module.
-.PT "INP <pro>"
-Internal procedure.
-<pro> is internal to this module and must be defined in this module.
-.PE
-.IE
-.S4 Miscellaneous
-Two other pseudoinstructions provide miscellaneous features:
-.IS 2
-.PS - 4
-.PT "EXC <cst1>,<cst2>"
-Two blocks of instructions preceding this one are
-interchanged before being processed.
-<cst1> gives the number of lines of the first block.
-<cst2> gives the number of lines of the second one.
-Blank and pure comment lines do not count.
-.PT "MES <cst>[,<par>]*"
-A special type of comment.
-Used by compilers to communicate with the
-optimizer, assembler, etc. as follows:
-.VS 1 0
-.PS - 4
-.PT "MES 0"
-An error has occurred, stop further processing.
-.PT "MES 1"
-Suppress optimization.
-.PT "MES 2,<cst1>,<cst2>"
-Use wordsize <cst1> and pointer size <cst2>.
-.PT "MES 3,<cst1>,<cst2>,<cst3>,<cst4>"
-Indicates that a local variable is never referenced indirectly.
-Used to indicate that a register may be used for a specific
-variable.
-<cst1> is offset in bytes from AB if positive
-and offset from LB if negative.
-<cst2> gives the size of the variable.
-<cst3> indicates the class of the variable.
-The following values are currently recognized:
-.PS
-.PT 0
-The variable can be used for anything.
-.PT 1
-The variable is used as a loopindex.
-.PT 2
-The variable is used as a pointer.
-.PT 3
-The variable is used as a floating point number.
-.PE 0
-<cst4> gives the priority of the variable,
-higher numbers indicate better candidates.
-.PT "MES 4,<cst>,<str>"
-Number of source lines in file <str> (for profiler).
-.PT "MES 5"
-Floating point used.
-.PT "MES 6,<val>*"
-Comment.  Used to provide comments in compact assembly language.
-.PT "MES 7,....."
-Reserved.
-.PT "MES 8,<pro>[,<dlb>]..."
-Library module. Indicates that the module may only be loaded
-if it is useful, that is, if it can satisfy any unresolved
-references during the loading process.
-May not be preceded by any other pseudo, except MES's.
-.PT "MES 9,<cst>"
-Guarantees that no more than <cst> bytes of parameters are
-accessed, either directly or indirectly.
-.PT "MES 10,<cst>[,<par>]*
-This message number is reserved for the global optimizer.
-It inserts these messages in its output as hints to backends.
-<cst> indicates the type of hint.
-.PT "MES 11"
-Procedures containing this message are possible destinations of
-non-local goto's with the GTO instruction.
-Some backends keep locals in registers,
-the locals in this procedure should not be kept in registers and
-all registers containing locals of other procedures should be
-saved upon entry to this procedure.
-.PE 1
-.VS 1 1
-Each backend is free to skip irrelevant MES pseudos.
-.PE
-.IE
-.S2 "The Compact Assembly Language"
-The assembler accepts input in a highly encoded form.
-This
-form is intended to reduce the amount of file transport between the
-front ends, optimizers
-and back ends, and also reduces the amount of storage required for storing
-libraries.
-Libraries are stored as archived compact assembly language, not machine
-language.
-.P
-When beginning to read the input, the assembler is in neutral state, and
-expects either a label or an instruction (including the pseudoinstructions).
-The meaning of the next byte(s) when in neutral state is as follows, where
-b1, b2
-etc. represent the succeeding bytes.
-.N 1
-.DS
-.TS
-tab(:) ;
-rw17 4 l.
-0:Reserved for future use
-1-129:Machine instructions, see Appendix A, alphabetical list
-130-149:Reserved for future use
-150-161:BSS,CON,END,EXA,EXC,EXP,HOL,INA,INP,MES,PRO,ROM
-162-179:Reserved for future pseudoinstructions
-180-239:Instruction labels 0 - 59  (180 is local label 0 etc.)
-240-244:See the Common Table below
-245-255:Not used
-.TE 1
-.DE 0
-After a label, the assembler is back in neutral state; it can immediately
-accept another label or an instruction in the next byte.
-No linefeeds are used to separate lines.
-.P
-If an opcode expects no arguments,
-the assembler is back in neutral state after
-reading the one byte containing the instruction number.
-If it has one or
-more arguments (only pseudos have more than 1), the arguments follow directly,
-encoded as follows:
-.N 1
-.IS 2
-.TS
-tab(:);
-r l.
-0-239:Offsets from -120 to 119
-
-240-255:See the Common Table below
-.TE 1
-Absence of an optional argument is indicated by a special
-byte.
-.IE 2
-.CS
-Common Table for Neutral State and Arguments
-.CE
-.TS
-tab(:);
-c c s c
-l8 l l8 l.
-class:bytes:description
-
-<ilb>:240:b1:Instruction label b1  (Not used for branches)
-<ilb>:241:b1 b2:16 bit instruction label  (256*b2 + b1)
-<dlb>:242:b1:Global label .0-.255, with b1 being the label
-<dlb>:243:b1 b2:Global label .0-.32767
-:::with 256*b2+b1 being the label
-<dlb>:244:<string>:Global symbol not of the form .nnn
-<cst>:245:b1 b2:16 bit constant
-<cst>:246:b1 b2 b3 b4:32 bit constant
-<cst>:247:b1 .. b8:64 bit constant
-<arg>:248:<dlb><cst>:Global label + (possibly negative) constant
-<pro>:249:<string>:Procedure name  (not including $)
-<str>:250:<string>:String used in CON or ROM (no quotes-no escapes)
-<con>:251:<cst><string>:Integer constant, size <cst> bytes
-<con>:252:<cst><string>:Unsigned constant, size <cst> bytes
-<con>:253:<cst><string>:Floating constant, size <cst> bytes
-:254::unused
-<end>:255::Delimiter for argument lists or
-:::indicates absence of optional argument
-.TE 1
-.P
-The bytes specifying the value of a 16, 32 or 64 bit constant
-are presented in two's complement notation, with the least
-significant byte first. For example: the value of a 32 bit
-constant is ((s4*256+b3)*256+b2)*256+b1, where s4 is b4-256 if
-b4 is greater than 128 else s4 takes the value of b4.
-A <string> consists of a <cst> inmediatly followed by
-a sequence of bytes with length <cst>.
-.P
-.ne 8
-The pseudoinstructions fall into several categories, depending on their
-arguments:
-.N 1
-.DS
- Group 1 -- EXC, BSS, HOL have a known number of arguments
- Group 2 -- EXA, EXP, INA, INP have a string as argument
- Group 3 -- CON, MES, ROM have a variable number of various things
- Group 4 -- END, PRO have a trailing optional argument.
-.DE 1
-Groups 1 and 2
-use the encoding described above.
-Group 3 also uses the encoding listed above, with an <end> byte after the
-last argument to indicate the end of the list.
-Group 4 uses
-an <end> byte if the trailing argument is not present.
-.N 2
-.IS 2
-.TS
-tab(|);
-l s l
-l s s
-l 2 lw(46) l.
-Example  ASCII|Example compact
-(LOC = 69, BRA = 18 here):
-
-2||182
-1||181
- LOC|10|69 130
- LOC|-10|69 110
- LOC|300|69 245 44 1
- BRA|*19|18 139
-300||241 44 1
-.3||242 3
- CON|4,9,*2,$foo|151 124 129 240 2 249 123 102 111 111 255
- CON|.35|151 242 35 255
-.TE 0
-.IE 0
-.BP
-.S2 "Assembly language instruction list"
-.P
-For each instruction in the list the range of argument values
-in the assembly language is given.
-The column headed \fIassem\fP contains the mnemonics defined
-in 11.1.3.
-The following column specifies restrictions of the argument
-value.
-Addresses have to obey the restrictions mentioned in chapter 2.
-The classes of arguments
-are indicated by letters:
-.ds b \fBb\fP
-.ds c \fBc\fP
-.ds d \fBd\fP
-.ds g \fBg\fP
-.ds f \fBf\fP
-.ds l \fBl\fP
-.ds n \fBn\fP
-.ds w \fBw\fP
-.ds p \fBp\fP
-.ds r \fBr\fP
-.ds s \fBs\fP
-.ds z \fBz\fP
-.ds o \fBo\fP
-.ds - \fB-\fP
-.N 1
-.TS
-tab(:);
-c s l l
-l l 15 l l.
-\fIassem\fP:constraints:rationale
-
-\&\*c:cst:fits word:constant
-\&\*d:cst:fits double word:constant
-\&\*l:cst::local offset
-\&\*g:arg:>= 0:global offset
-\&\*f:cst::fragment offset
-\&\*n:cst:>= 0:counter
-\&\*s:cst:>0 , word multiple:object size
-\&\*z:cst:>= 0 , zero or word multiple:object size
-\&\*o:cst:> 0 , word multiple or fraction:object size
-\&\*w:cst:> 0 , word multiple:object size *
-\&\*p:pro::pro identifier
-\&\*b:ilb:>= 0:label number
-\&\*r:cst:0,1,2:register number
-\&\*-:::no argument
-.TE 1
-.P
-The * at the rationale for \*w indicates that the argument
-can either be given as argument or on top of the stack.
-If the argument is omitted, the argument is fetched from the
-stack;
-it is assumed to be a wordsized unsigned integer.
-Instructions that check for undefined integer or floating-point
-values and underflow or overflow
-are indicated below by (*).
-.N 1
-.DS B
-GROUP 1 - LOAD
-
-  LOC \*c : Load constant (i.e. push one word onto the stack)
-  LDC \*d : Load double constant ( push two words )
-  LOL \*l : Load word at \*l-th local (\*l<0) or parameter (\*l>=0)
-  LOE \*g : Load external word \*g
-  LIL \*l : Load word pointed to by \*l-th local or parameter
-  LOF \*f : Load offsetted (top of stack + \*f yield address)
-  LAL \*l : Load address of local or parameter
-  LAE \*g : Load address of external
-  LXL \*n : Load lexical (address of LB \*n static levels back)
-  LXA \*n : Load lexical (address of AB \*n static levels back)
-  LOI \*o : Load indirect \*o bytes (address is popped from the stack)
-  LOS \*w : Load indirect, \*w-byte integer on top of stack gives object size
-  LDL \*l : Load double local or parameter (two consecutive words are stacked)
-  LDE \*g : Load double external (two consecutive externals are stacked)
-  LDF \*f : Load double offsetted (top of stack + \*f yield address)
-  LPI \*p : Load procedure identifier
-
-GROUP 2 - STORE
-
-  STL \*l : Store local or parameter
-  STE \*g : Store external
-  SIL \*l : Store into word pointed to by \*l-th local or parameter
-  STF \*f : Store offsetted
-  STI \*o : Store indirect \*o bytes (pop address, then data)
-  STS \*w : Store indirect, \*w-byte integer on top of stack gives object size
-  SDL \*l : Store double local or parameter
-  SDE \*g : Store double external
-  SDF \*f : Store double offsetted
-
-GROUP 3 - INTEGER ARITHMETIC
-
-  ADI \*w : Addition (*)
-  SBI \*w : Subtraction (*)
-  MLI \*w : Multiplication (*)
-  DVI \*w : Division (*)
-  RMI \*w : Remainder (*)
-  NGI \*w : Negate (two's complement) (*)
-  SLI \*w : Shift left (*)
-  SRI \*w : Shift right (*)
-
-GROUP 4 - UNSIGNED ARITHMETIC
-
-  ADU \*w : Addition
-  SBU \*w : Subtraction
-  MLU \*w : Multiplication
-  DVU \*w : Division
-  RMU \*w : Remainder
-  SLU \*w : Shift left
-  SRU \*w : Shift right
-
-GROUP 5 - FLOATING POINT ARITHMETIC
-
-  ADF \*w : Floating add (*)
-  SBF \*w : Floating subtract (*)
-  MLF \*w : Floating multiply (*)
-  DVF \*w : Floating divide (*)
-  NGF \*w : Floating negate (*)
-  FIF \*w : Floating multiply and split integer and fraction part (*)
-  FEF \*w : Split floating number in exponent and fraction part (*)
-
-GROUP 6 - POINTER ARITHMETIC
-
-  ADP \*f : Add \*f to pointer on top of stack
-  ADS \*w : Add \*w-byte value and pointer
-  SBS \*w : Subtract pointers in same fragment and push diff as size \*w integer
-
-GROUP 7 - INCREMENT/DECREMENT/ZERO
-
-  INC \*- : Increment word on top of stack by 1 (*)
-  INL \*l : Increment local or parameter (*)
-  INE \*g : Increment external (*)
-  DEC \*- : Decrement word on top of stack by 1 (*)
-  DEL \*l : Decrement local or parameter (*)
-  DEE \*g : Decrement external (*)
-  ZRL \*l : Zero local or parameter
-  ZRE \*g : Zero external
-  ZRF \*w : Load a floating zero of size \*w
-  ZER \*w : Load \*w zero bytes
-
-GROUP 8 - CONVERT    (stack: source, source size, dest. size (top))
-
-  CII \*- : Convert integer to integer (*)
-  CUI \*- : Convert unsigned to integer (*)
-  CFI \*- : Convert floating to integer (*)
-  CIF \*- : Convert integer to floating (*)
-  CUF \*- : Convert unsigned to floating (*)
-  CFF \*- : Convert floating to floating (*)
-  CIU \*- : Convert integer to unsigned
-  CUU \*- : Convert unsigned to unsigned
-  CFU \*- : Convert floating to unsigned
-
-GROUP 9 - LOGICAL
-
-  AND \*w : Boolean and on two groups of \*w bytes
-  IOR \*w : Boolean inclusive or on two groups of \*w bytes
-  XOR \*w : Boolean exclusive or on two groups of \*w bytes
-  COM \*w : Complement (one's complement of top \*w bytes)
-  ROL \*w : Rotate left a group of \*w bytes
-  ROR \*w : Rotate right a group of \*w bytes
-
-GROUP 10 - SETS
-
-  INN \*w : Bit test on \*w byte set (bit number on top of stack)
-  SET \*w : Create singleton \*w byte set with bit n on (n is top of stack)
-
-GROUP 11 - ARRAY
-
-  LAR \*w : Load array element, descriptor contains integers of size \*w
-  SAR \*w : Store array element
-  AAR \*w : Load address of array element
-
-GROUP 12 - COMPARE
-
-  CMI \*w : Compare \*w byte integers, Push negative, zero, positive for <, = or >
-  CMF \*w : Compare \*w byte reals
-  CMU \*w : Compare \*w byte unsigneds
-  CMS \*w : Compare \*w byte values, can only be used for bit for bit equality test
-  CMP \*- : Compare pointers
-
-  TLT \*- : True if less, i.e. iff top of stack < 0
-  TLE \*- : True if less or equal, i.e. iff top of stack <= 0
-  TEQ \*- : True if equal, i.e. iff top of stack = 0
-  TNE \*- : True if not equal, i.e. iff top of stack non zero
-  TGE \*- : True if greater or equal, i.e. iff top of stack >= 0
-  TGT \*- : True if greater, i.e. iff top of stack > 0
-
-GROUP 13 - BRANCH
-
-  BRA \*b : Branch unconditionally to label \*b
-
-  BLT \*b : Branch less (pop 2 words, branch if top > second)
-  BLE \*b : Branch less or equal
-  BEQ \*b : Branch equal
-  BNE \*b : Branch not equal
-  BGE \*b : Branch greater or equal
-  BGT \*b : Branch greater
-
-  ZLT \*b : Branch less than zero (pop 1 word, branch negative)
-  ZLE \*b : Branch less or equal to zero
-  ZEQ \*b : Branch equal zero
-  ZNE \*b : Branch not zero
-  ZGE \*b : Branch greater or equal zero
-  ZGT \*b : Branch greater than zero
-
-GROUP 14 - PROCEDURE CALL
-
-  CAI \*- : Call procedure (procedure identifier on stack)
-  CAL \*p : Call procedure (with identifier \*p)
-  LFR \*s : Load function result
-  RET \*z : Return (function result consists of top \*z bytes)
-
-GROUP 15 - MISCELLANEOUS
-
-  ASP \*f : Adjust the stack pointer by \*f
-  ASS \*w : Adjust the stack pointer by \*w-byte integer
-  BLM \*z : Block move \*z bytes; first pop destination addr, then source addr
-  BLS \*w : Block move, size is in \*w-byte integer on top of stack
-  CSA \*w : Case jump; address of jump table at top of stack
-  CSB \*w : Table lookup jump; address of jump table at top of stack
-  DCH \*- : Follow dynamic chain, convert LB to LB of caller
-  DUP \*s : Duplicate top \*s bytes
-  DUS \*w : Duplicate top \*w bytes
-  EXG \*w : Exchange top \*w bytes
-  FIL \*g : File name (external 4 := \*g)
-  GTO \*g : Non-local goto, descriptor at \*g
-  LIM \*- : Load 16 bit ignore mask
-  LIN \*n : Line number (external 0 := \*n)
-  LNI \*- : Line number increment
-  LOR \*r : Load register (0=LB, 1=SP, 2=HP)
-  LPB \*- : Convert local base to argument base
-  MON \*- : Monitor call
-  NOP \*- : No operation
-  RCK \*w : Range check; trap on error
-  RTT \*- : Return from trap
-  SIG \*- : Trap errors to proc identifier on top of stack, -2 resets default
-  SIM \*- : Store 16 bit ignore mask
-  STR \*r : Store register (0=LB, 1=SP, 2=HP)
-  TRP \*- : Cause trap to occur (Error number on stack)
-.DE 0

+ 0 - 163
doc/em/descr.nr

@@ -1,163 +0,0 @@
-.SN 7
-.BP
-.S1 "DESCRIPTORS"
-Several instructions use descriptors, notably the range check instruction,
-the array instructions, the goto instruction and the case jump instructions.
-Descriptors reside in data space.
-They may be constructed at run time, but
-more often they are fixed and allocated in ROM data.
-.P
-All instructions using descriptors, except GTO, have as argument
-the size of the integers in the descriptor.
-All implementations have to allow integers of the size of a
-word in descriptors.
-All integers popped from the stack and used for indexing or comparing
-must have the same size as the integers in the descriptor.
-.S2 "Range check descriptors"
-Range check descriptors consist of two integers:
-.IS 2
-.PS 1 4 "" .
-.PT
-lower bound~~~~~~~signed
-.PT
-upper bound~~~~~~~signed
-.PE
-.IE
-The range check instruction checks an integer on the stack against
-these bounds and causes a trap if the value is outside the interval.
-The value itself is neither changed nor removed from the stack.
-.S2 "Array descriptors"
-Each array descriptor describes a single dimension.
-For multi-dimensional arrays, several array instructions are
-needed to access a single element.
-Array descriptors contain the following three integers:
-.IS 2
-.PS 1 4 "" .
-.PT
-lower bound~~~~~~~~~~~~~~~~~~~~~signed
-.PT
-upper bound - lower bound~~~~~~~unsigned
-.PT
-number of bytes per element~~~~~unsigned
-.PE
-.IE
-The array instructions LAR, SAR and AAR have the pointer to the start
-of the descriptor as operand on the stack.
-.sp
-The element A[I] is fetched as follows:
-.IS 2
-.PS 1 4 "" .
-.PT
-Stack the address of A  (e.g., using LAE or LAL)
-.PT
-Stack the value of I (n-byte integer)
-.PT
-Stack the pointer to the descriptor (e.g., using LAE)
-.PT
-LAR n (n is the size of the integers in the descriptor and I)
-.PE
-.IE
-All array instructions first pop the address of the descriptor
-and the index.
-If the index is not within the bounds specified, a trap occurs.
-If ok, (I~-~lower bound) is multiplied
-by the number of bytes per element (the third word).  The result is added
-to the address of A and replaces A on the stack.
-.A
-At this point LAR, SAR and AAR diverge.
-AAR is finished.  LAR pops the address and fetches the data
-item,
-the size being specified by the descriptor.
-The usual restrictions for memory access must be obeyed.
-SAR pops the address and stores the
-data item now exposed.
-.S2 "Non-local goto descriptors"
-The GTO instruction provides a way of returning directly to any
-active procedure invocation.
-The argument of the instruction is the address of a descriptor
-containing three pointers:
-.IS 2
-.PS 1 4 "" .
-.PT
-value of PC after the jump
-.PT
-value of SP after the jump
-.PT
-value of LB after the jump
-.PE
-.IE
-GTO replaces the loads PC, SP and LB from the descriptor,
-thereby jumping to a procedure
-and removing zeor or more frames from the stack.
-The LB, SP and PC in the descriptor must belong to a
-dynamically enclosing procedure,
-because some EM implementations will need to backtrack through
-the dynamic chain and use the implementation dependent data
-in frames to restore registers etc.
-.S2 "Case descriptors"
-The case jump instructions CSA and CSB both
-provide multiway branches selected by a case index.
-Both fetch two operands from the stack:
-first a pointer to the low address of the case descriptor
-and then the case index.
-CSA uses the case index as index in the descriptor table, but CSB searches
-the table for an occurrence of the case index.
-Therefore, the descriptors for CSA and CSB,
-as shown in figure 4, are different.
-All pointers in the table must be addresses of instructions in the
-procedure executing the case instruction.
-.P
-CSA selects the new PC by indexing.
-If the index, a signed integer, is greater than or equal to
-the lower bound and less than or equal to the upper bound,
-then fetch the new PC from the list of instruction pointers by indexing with
-index-lower.
-The table does not contain the value of the upper bound,
-but the value of upper-lower as an unsigned integer.
-The default instruction pointer is used when the index is out of bounds.
-If the resulting PC is 0, then trap.
-.P
-CSB selects the new PC by searching.
-The table is searched for an entry with index value equal to the case index.
-That entry or, if none is found, the default entry contains the
-new PC.
-When the resulting PC is 0, a trap is performed.
-.P
-The choice of which case instruction to use for
-each source language case statement
-is up to the front end.
-If the range of the index value is dense, i.e
-.DS
-(highest value - lowest value) / number of cases
-.DE 1
-is less than some threshold, then CSA is the obvious choice.
-If the range is sparse, CSB is better.
-.N 2
-.DS
-   |--------------------|        |--------------------|  high address
-   | pointer for upb    |        |    pointer n-1     |
-   |--------------------|        |-  -  -  -  -  -  - |
-   |         .          |        |     index  n-1     |
-   |         .          |        |--------------------|
-   |         .          |        |          .         |
-   |         .          |        |          .         |
-   |         .          |        |          .         |
-   |         .          |        |--------------------|
-   |         .          |        |    pointer  1      |
-   |--------------------|        |-  -  -  -  -  -  - |
-   | pointer for lwb+1  |        |     index   1      |
-   |--------------------|        |--------------------|
-   | pointer for lwb    |        |    pointer  0      |
-   |--------------------|        |-  -  -  -  -  -  - |
-   |   upper - lower    |        |     index   0      |
-   |--------------------|        |--------------------|
-   |    lower bound     |        | number of entries  |
-   |--------------------|        |--------------------|
-   |  default pointer   |        |  default pointer   |  low address
-   |--------------------|        |--------------------|
-
-       CSA descriptor                CSB descriptor
-
-
-      Figure 4. Descriptor layout for CSA and CSB
-.DE

+ 0 - 377
doc/em/dspace.nr

@@ -1,377 +0,0 @@
-.BP
-.SN 4
-.S1 "DATA ADDRESS SPACE"
-The data address space is divided into three parts, called 'areas',
-each with its own addressing method:
-global data area,
-local data area (including the stack),
-and heap data area.
-These data areas must be part of the same
-address space because all data is accessed by
-the same type of pointers.
-.P
-Space for global data is reserved using several pseudoinstructions in the
-assembly language, as described in
-the next paragraph and chapter 11.
-The size of the global data area is fixed per program.
-.A
-Global data is addressed absolutely in the machine language.
-Many instructions are available to address global data.
-They all have an absolute address as argument.
-Examples are LOE, LAE and STE.
-.P
-Part of the global data area is initialized by the
-compiler, the
-rest is not initialized at all or is initialized
-with a value, typically -32768 or 0.
-Part of the initialized global data may be made read-only
-if the implementation supports protection.
-.P
-The local data area is used as a stack,
-which grows from high to low addresses
-and contains some data for each active procedure
-invocation, called a 'frame'.
-The size of the local data area varies dynamically during
-execution.
-Below the current procedure frame resides the operand stack.
-The stack pointer SP always points to the bottom of
-the local data area.
-Local data is addressed by offsetting from the local base pointer LB.
-LB always points to the frame of the current procedure.
-Only the words of the current frame and the parameters
-can be addressed directly.
-Variables in other active procedures are addressed by following
-the chain of statically enclosing procedures using the LXL or LXA instruction.
-The variables in dynamically enclosing procedures can be
-addressed with the use of the DCH instruction.
-.A
-Many instructions have offsets to LB as argument,
-for instance LOL, LAL and STL.
-The arguments of these instructions range from -1 to some
-(negative) minimum
-for the access of local storage and from 0 to some (positive)
-maximum for parameter access.
-.P
-The procedure call instructions CAL and CAI each create a new frame
-on the stack.
-Each procedure has an assembly-time parameter specifying
-the number of bytes needed for local storage.
-This storage is allocated each time the procedure is called and
-must be a multiple of the wordsize.
-Each procedure, therefore, starts with a stack with the local variables
-already allocated.
-The return instructions RET and RTT remove a frame.
-The actual parameters must be removed by the calling procedure.
-.P
-RET may copy some words from the stack of
-the returning procedure to an unnamed 'function return area'.
-This area is available for 'READ-ONCE' access using the LFR instruction.
-The result of a LFR is only defined if the size used to fetch
-is identical to the size used in the last return.
-The instruction ASP, used to remove the parameters from the
-stack, the branch instruction BRA and the non-local goto
-instrucion GTO are the only ones that leave the contents of
-the 'function return area' intact.
-All other instructions are allowed to destroy the function
-return area.
-Thus parameters can be popped before fetching the function result.
-The maximum size of all function return areas is
-implementation dependent,
-but should allow procedure instance identifiers and all
-implemented objects of type integer, unsigned, float
-and pointer to be returned.
-In most implementations
-the maximum size of the function return
-area is twice the pointer size,
-because we want to be able to handle 'procedure instance
-identifiers' which consist of a procedure identifier and the LB
-of a frame belonging to that procedure.
-.P
-The heap data area grows upwards, to higher numbered
-addresses.
-It is initially empty.
-The initial value of the heap pointer HP
-marks the low end.
-The heap pointer may be manipulated
-by the LOR and STR instructions.
-The heap can only be addressed indirectly,
-by pointers derived from previous values of HP.
-.S2 "Global data area"
-The initial size of the global data area is determined at assembly time.
-Global data is allocated by several
-pseudoinstructions in the EM assembly
-language.
-Each pseudoinstruction allocates one or more bytes.
-The bytes allocated for a single pseudo form
-a 'block'.
-A block differs from a fragment, because,
-under certain conditions, several blocks are allocated
-in a single fragment.
-This guarantees that the bytes of these blocks
-are consecutive.
-.P
-Global data is addressed absolutely in binary
-machine language.
-Most compilers, however,
-cannot assign absolute addresses to their global variables,
-especially not if the language
-allows programs to be composed of several separately compiled modules.
-The assembly language therefore allows the compiler to name
-the first address of a global data block with an alphanumeric label.
-Moreover, the only way to address such a named global data block
-in the assembly language is by using its name.
-It is the task of the assembler/loader to
-translate these labels into absolute addresses.
-These labels may also be used
-in CON and ROM pseudoinstructions to initialize pointers.
-.P
-The pseudoinstruction CON allocates initialized data.
-ROM acts like CON but indicates that the initialized data will
-not change during execution of the program.
-The pseudoinstruction BSS allocates a block of uninitialized
-or identically initialized
-data.
-The pseudoinstruction HOL is similar to BSS,
-but it alters the meaning of subsequent absolute addressing in
-the assembly language.
-.P
-Another type of global data is a small block,
-called the ABS block, with an implementation defined size.
-Storage in this type of block can only be addressed
-absolutely in assembly language.
-The first word has address 0 and is used to maintain the
-source line number.
-Special instructions LIN and LNI are provided to
-update this counter.
-A pointer at location 4 points to a string containing the
-current source file name.
-The instruction FIL can be used to update the pointer.
-.P
-All numeric arguments of the instructions that address
-the global data area refer to locations in the
-ABS block unless
-they are preceded by at least one HOL pseudo in the same
-module,
-in which case they refer to the storage area allocated by the
-last HOL pseudoinstruction.
-Thus LOE 0 loads the zeroth word of the most recent HOL, unless no HOL has
-appeared in the current file so
-far, in which case it loads the zeroth word of the
-ABS fragment.
-.P
-The global data area is highly fragmented.
-The ABS block and each HOL and BSS block are separate fragments.
-The way fragments are formed from CON and ROM blocks is more complex.
-The assemblers group several blocks into a single fragment.
-A fragment only contains blocks of the same type: CON or ROM.
-It is guaranteed that the bytes allocated for two consecutive CON pseudos are
-allocated consecutively in a single fragment, unless
-these CON pseudos are separated in the assembly language program
-by a data label definition or one or more of the following pseudos:
-.DS
-
-     ROM, BSS, HOL and END
-
-.DE
-An analogous rule holds for ROM pseudos.
-.S2 "Local data area"
-The local data area consists of a sequence of frames, one for
-each active procedure.
-Below the frame of the current procedure resides the
-expression stack.
-Frames are generated by procedure calls and are
-removed by procedure returns.
-A procedure frame consists of six 'zones':
-.DS
-
-  1.  The return status block
-  2.  The local variables and compiler temporaries
-  3.  The register save block
-  4.  The dynamic local generators
-  5.  The operand stack.
-  6.  The parameters of a procedure one level deeper
-
-.DE
-A sample frame is shown in Figure 1.
-.P
-Before a procedure call is performed the actual
-parameters are pushed onto the stack of the calling procedure.
-The exact details are compiler dependent.
-EM allows procedures to be called with a variable number of
-parameters.
-The implementation of the C-language almost forces its runtime
-system to push the parameters in reverse order, that is,
-the first positional parameter last.
-Most compilers use the C calling convention to be compatible.
-The parameters of a procedure belong to the frame of the
-calling procedure.
-Note that the evaluation of the actual parameters may imply
-the calling of procedures.
-The parameters can be accessed with certain instructions using
-offsets of 0 and greater.
-The first byte of the last parameter pushed has offset 0.
-Note that the parameter at offset 0 has a special use in the
-instructions following the static chain (LXL and LXA).
-These instructions assume that this parameter contains the LB of
-the statically enclosing procedure.
-Procedures that do not have a dynamically enclosing procedure
-do not need a static link at offset 0.
-.P
-Two instructions are available to perform procedure calls, CAL
-and CAI.
-Several tasks are performed by these call instructions.
-.A
-First, a part of the status of the calling procedure is
-saved on the stack in the return status block.
-This block should contain the return address of the calling
-procedure, its LB and other implementation dependent data.
-The size of this block is fixed for any given implementation
-because the lexical instructions LPB, LXL and LXA must be able to
-obtain the base addresses of the procedure parameters \fBand\fP local
-variables.
-An alternative solution can be used on machines with a highly
-segmented address space.
-The stack frames need not be contiguous then and the first
-status save area can contain the parameter base AB,
-which has the value of SP just after the last parameter has
-been pushed.
-.A
-Second, the LB is changed to point to the
-first word above the local variables.
-The new LB is a copy of the SP after the return status
-block has been pushed.
-.A
-Third, the amount of local storage needed by the procedure is
-reserved.
-The parameters and local storage are accessed by the same instructions.
-Negative offsets are used for access to local variables.
-The highest byte, that is the byte nearest
-to LB, has to be accessed with offset -1.
-The pseudoinstruction specifying the entry point of a
-procedure, has an argument that specifies the amount of local
-storage needed.
-The local variables allocated by the CAI or CAL instructions
-are the only ones that can be accessed with a fixed negative offset.
-The initial value of the allocated words is
-not defined, but implementations that check for undefined
-values will probably initialize them with a
-special 'undefined' pattern, typically -32768.
-.A
-Fourth, any EM implementation is allowed to reserve a variable size
-block beneath the local variables.
-This block could, for example, be used to save a variable number
-of registers.
-.A
-Finally, the address of the entry point of the called procedure
-is loaded into the Program Counter.
-.P
-The ASP instruction can be used to allocate further (dynamic)
-local storage.
-The base address of such storage must be obtained with a LOR~SP
-instruction.
-This same instruction ASP may also be used
-to remove some words from the stack.
-.P
-There is a version of ASP, called ASS, which fetches the number
-of bytes to allocate from the stack.
-It can be used to allocate space for local
-objects whose size is unknown at compile time,
-so called 'dynamic local generators'.
-.P
-Control is returned to the calling procedure with a RET instruction.
-Any return value is then copied to the 'function return area'.
-The frame created by the call is deallocated and the status of
-the calling procedure is restored.
-The value of SP just after the return value has been popped must
-be the same as the
-value of SP just before executing the first instruction of this
-invocation.
-This means that when a RET is executed the operand stack can
-only contain the return value and all dynamically generated locals must be
-deallocated.
-Violating this restriction might result in hard to detect
-errors.
-The calling procedure has to remove the parameters from the stack.
-This can be done with the aforementioned ASP instruction.
-.P
-Each procedure frame is a separate fragment.
-Because any fragment may be placed anywhere in memory,
-procedure frames need not be contiguous.
-.DS
-                |===============================|
-                |     actual parameter  n-1     |
-                |-------------------------------|
-                |              .                |
-                |              .                |
-                |              .                |
-                |-------------------------------|
-                |     actual parameter  0       | ( <- AB )
-                |===============================|
-
-
-                |===============================|
-                |///////////////////////////////|
-                |///// return status block /////|
-                |///////////////////////////////|   <- LB
-                |===============================|
-                |                               |
-                |       local variables         |
-                |                               |
-                |-------------------------------|
-                |                               |
-                |      compiler temporaries     |
-                |                               |
-                |===============================|
-                |///////////////////////////////|
-                |///// register save block /////|
-                |///////////////////////////////|
-                |===============================|
-                |                               |
-                |   dynamic local generators    |
-                |                               |
-                |===============================|
-                |           operand             |
-                |-------------------------------|
-                |           operand             |
-                |===============================|
-                |         parameter  m-1        |
-                |-------------------------------|
-                |              .                |
-                |              .                |
-                |              .                |
-                |-------------------------------|
-                |         parameter  0          | <- SP
-                |===============================|
-
-          Figure 1. A sample procedure frame and parameters.
-.DE
-.S2 "Heap data area"
-The heap area starts empty, with HP
-pointing to the low end of it.
-HP always contains a word address.
-A copy of HP can always be obtained with the LOR instruction.
-A new value may be stored in the heap pointer using the STR instruction.
-If the new value is greater than the old one,
-then the heap grows.
-If it is smaller, then the heap shrinks.
-HP may never point below its original value.
-All words between the current HP and the original HP
-are allocated to the heap.
-The heap may not grow into a part of memory that is already allocated
-for the stack.
-When this is attempted, the STR instruction will cause a trap to occur.
-.P
-The only way to address the heap is indirectly.
-Whenever an object is allocated by increasing HP,
-then the old HP value must be saved and can be used later to address
-the allocated object.
-If, in the meantime, HP is decreased so that the object
-is no longer part of the heap, then an attempt to access
-the object is not allowed.
-Furthermore, if the heap pointer is increased again to above
-the object address, then access to the old object gives undefined results.
-.P
-The heap is a single fragment.
-All bytes have consecutive addresses.
-No limits are imposed on the size of the heap as long as it fits
-in the available data address space.

+ 0 - 1665
doc/em/em.i

@@ -1,1665 +0,0 @@
-{ This  is an interpreter for EM.  It serves as  the official machine
-  definition.  This interpreter must run on a machine which supports
-  arithmetic with words and memory offsets.
-
-  Certain aspects of the definition are over specified.  In particular:
-
-    1. The representation of  an  address on the stack  need not be the
-       numerical value of the memory location.
-
-    2. The state of  the stack is not defined  after a trap has aborted
-       an instruction in the middle.  For example, it is officially un-
-       defined  whether the second  operand of an  ADD  instruction has
-       been popped  or  not  if the  first one is undefined ( -32768 or
-       unsigned 32768).
-
-    3. The memory layout is implementation dependent. Only the most
-       basic checks are performed whenever memory is accessed.
-
-    4. The representation of an integer or set on the stack is not fixed
-       in bit order.
-
-    5. The format and existence of the procedure descriptors depends on
-       the implementation.
-
-    6. The result of the compare operators  CMI etc.  are -1, 0  and  1
-       here, but other negative  and  positive values will do  and they
-       need not be the same each time.
-
-    7. The shift count for SHL, SHR, ROL and ROR must be in the range 0
-       to object size in bits - 1.  The effect of a  count  not in this
-       range is undefined.
-}
-.BP
-{$i256} {$d+}
-program em(tables,prog,input,output);
-
-label 8888,9999;
-
-const
-  t15   = 32768;        { 2**15    }
-  t15m1 = 32767;        { 2**15 -1 }
-  t16   = 65536;        { 2**16    }
-  t16m1 = 65535;        { 2**16 -1 }
-  t31m1 = 2147483647;   { 2**31 -1 }
-
-  wsize = 2;            { number of bytes in a word }
-  asize = 2;            { number of bytes in an address }
-  fsize = 4;            { number of bytes in a floating point number }
-  maxret =4;            { number of words in the return value area }
-
-  signbit = t15;        { the power of two indicating the sign bit }
-  negoff  = t16;        { the next power of two }
-  maxsint = t15m1;      { the maximum signed integer }
-  maxuint = t16m1;      { the maximum unsigned integer }
-  maxdbl  = t31m1;      { the maximum double signed integer }
-  maxadr  = t16m1;      { the maximum address }
-  maxoffs = t15m1;      { the maximum offset from an address }
-  maxbitnr= 15;         { the number of the highest bit }
-
-  lineadr = 0;          { address of the line number }
-  fileadr = 4;          { address of the file name }
-  maxcode = 8191;       { highest byte in code address space }
-  maxdata = 8191;       { highest byte in data address space }
-
-  { format of status save area }
-  statd   = 4;          { how far is static link from lb }
-  dynd    = 2;          { how far is dynamic link from lb }
-  reta    = 0;          { how far is the return address from lb }
-  savsize = 4;          { size of save area in bytes }
-
-  { procedure descriptor format }
-  pdlocs  = 0;          { offset for size of local variables in bytes }
-  pdbase  = asize;      { offset for the procedure base }
-  pdsize  = 4;          { size of procedure descriptor in bytes = 2*asize }
-
-  { header words }
-  NTEXT   = 1;
-  NDATA   = 2;
-  NPROC   = 3;
-  ENTRY   = 4;
-  NLINE   = 5;
-  SZDATA  = 6;
-
-  escape1 = 254;        { escape to secondary opcodes }
-  escape2 = 255;        { escape to tertiary opcodes }
-  undef   = signbit;    { the range of integers is -32767 to +32767 }
-
-  { error codes }
-  EARRAY   =  0; ERANGE   =  1; ESET     =  2; EIOVFL   =  3; EFOVFL   =  4; 
-  EFUNFL   =  5; EIDIVZ   =  6; EFDIVZ   =  7; EIUND    =  8; EFUND    =  9; 
-  ECONV    = 10; ESTACK   = 16; EHEAP    = 17; EILLINS  = 18; EODDZ    = 19; 
-  ECASE    = 20; EMEMFLT  = 21; EBADPTR  = 22; EBADPC   = 23; EBADLAE  = 24;
-  EBADMON  = 25; EBADLIN  = 26; EBADGTO  = 27;
-.ne 20
-.bp
-{---------------------------------------------------------------------------}
-{                             Declarations                                  }
-{---------------------------------------------------------------------------}
-
-type
-  bitval= 0..1;             { one bit }
-  bitnr=  0..maxbitnr;      { bits in machine words are numbered 0 to 15 }
-  byte=   0..255;           { memory is an array of bytes }
-  adr=    {0..maxadr} long; { the range of addresses }
-  word=   {0..maxuint} long;{ the range of unsigned integers }
-  offs=  -maxoffs..maxoffs; { the range of signed offsets from addresses }
-  size=   0..maxoffs;       { the range of sizes is the positive offsets }
-  sword= {-signbit..maxsint} long; { the range of signed integers }
-  full=  {-maxuint..maxuint} long; { intermediate results need this range }
-  double={-maxdbl..maxdbl} long;   { double precision range }
-  bftype= (andf,iorf,xorf); { tells which boolean operator needed }
-  insclass=(prim,second,tert); { tells which opcode table is in use }
-  instype=(implic,explic);  { does opcode have implicit or explicit operand }
-  iflags= (mini,short,sbit,wbit,zbit,ibit);
-  ifset=  set of iflags;
-
-  mnem = ( NON,
-	   AAR, ADF, ADI, ADP, ADS, ADU,XAND, ASP, ASS, BEQ,
-	   BGE, BGT, BLE, BLM, BLS, BLT, BNE, BRA, CAI, CAL,
-	   CFF, CFI, CFU, CIF, CII, CIU, CMF, CMI, CMP, CMS,
-	   CMU, COM, CSA, CSB, CUF, CUI, CUU, DCH, DEC, DEE,
-	   DEL, DUP, DUS, DVF, DVI, DVU, EXG, FEF, FIF, FIL,
-	   GTO, INC, INE, INL, INN, IOR, LAE, LAL, LAR, LDC,
-	   LDE, LDF, LDL, LFR, LIL, LIM, LIN, LNI, LOC, LOE,
-	   LOF, LOI, LOL, LOR, LOS, LPB, LPI, LXA, LXL, MLF,
-	   MLI, MLU, MON, NGF, NGI, NOP, RCK, RET, RMI, RMU,
-	   ROL, ROR, RTT, SAR, SBF, SBI, SBS, SBU, SDE, SDF,
-	   SDL,XSET, SIG, SIL, SIM, SLI, SLU, SRI, SRU, STE,
-	   STF, STI, STL, STR, STS, TEQ, TGE, TGT, TLE, TLT,
-	   TNE, TRP, XOR, ZEQ, ZER, ZGE, ZGT, ZLE, ZLT, ZNE,
-	   ZRE, ZRF, ZRL);
-
-  dispatch = record
-		iflag: ifset;
-		instr: mnem;
-		case instype of
-		implic: (implicit:sword);
-		explic: (ilength:byte);
-	     end;
-
-
-var
-  code: packed array[0..maxcode] of byte;      { code space }
-  data: packed array[0..maxdata] of byte;      { data space }
-  retarea: array[1..maxret ] of word;          { return area }
-  pc,lb,sp,hp,pd: adr;  { internal machine registers }
-  i: integer;           { integer scratch variable }
-  s,t :word;            { scratch variables }
-  sz:size;              { scratch variables }
-  ss,st: sword;         { scratch variables }
-  k :double;            { scratch variables }
-  j:size;               { scratch variable used as index }
-  a,b:adr;              { scratch variable used for addresses }
-  dt,ds:double;         { scratch variables for double precision }
-  rt,rs,x,y:real;       { scratch variables for real }
-  found:boolean;        { scratch }
-  opcode: byte;         { holds the opcode during execution }
-  iclass: insclass;     { true for escaped opcodes }
-  dispat: array[insclass,byte] of dispatch;
-  retsize:size;         { holds size of last LFR }
-  insr: mnem;           { holds the instructionnumber }
-  halted: boolean;      { normally false }
-  exitstatus:word;      { parameter of MON 1 }
-  ignmask:word;         { ignore mask for traps }
-  uerrorproc:adr;       { number of user defined error procedure }
-  intrap:boolean;       { Set when executing trap(), to catch recursive calls}
-  trapval:byte;         { Set to number of last trap }
-  header: array[1..8] of adr;
-
-  tables: text;         { description of EM instructions }
-  prog: file of byte;   { program and initialized data }
-.ne 20
-.sp 2
-{---------------------------------------------------------------------------}
-{                        Various check routines                             }
-{---------------------------------------------------------------------------}
-
-{ Only the most basic checks are performed. These routines are inherently
-  implementation dependent. }
-
-procedure trap(n:byte); forward;
-
-procedure memadr(a:adr);
-begin if (a>maxdata) or ((a<sp) and (a>=hp)) then trap(EMEMFLT) end;
-
-procedure wordadr(a:adr);
-begin memadr(a); if (a mod wsize<>0) then trap(EBADPTR) end;
-
-procedure chkadr(a:adr; s:size);
-begin memadr(a); memadr(a+s-1); { assumption: size is ok }
-      if s<wsize
-      then begin if a mod s<>0  then trap(EBADPTR) end
-      else       if a mod wsize<>0 then trap(EBADPTR)
-end;
-
-procedure newpc(a:double);
-begin if (a<0) or (a>maxcode) then trap(EBADPC); pc:=a end;
-
-procedure newsp(a:adr);
-begin if (a>lb) or (a<hp) or (a mod wsize<>0) then trap(ESTACK); sp:=a end;
-
-procedure newlb(a:adr);
-begin if (a<sp) or (a mod wsize<>0) then trap(ESTACK); lb:=a end;
-
-procedure newhp(a:adr);
-begin if (a>sp) or (a>maxdata+1) or (a mod wsize<>0)
-      then trap(EHEAP); hp:=a
-end;
-
-function argc(a:double):sword;
-begin if (a<-signbit) or (a>maxsint) then trap(EILLINS); argc:=a end;
-
-function argd(a:double):double;
-begin if (a<-maxdbl) or (a>maxdbl) then trap(EILLINS); argd:=a end;
-
-function argl(a:double):offs;
-begin if (a<-maxoffs) or (a>maxoffs) then trap(EILLINS); argl:=a end;
-
-function argg(k:double):adr;
-begin if (k<0) or (k>maxadr) then trap(EILLINS); argg:=k end;
-
-function argf(a:double):offs;
-begin if (a<-maxoffs) or (a>maxoffs) then trap(EILLINS); argf:=a end;
-
-function argn(a:double):word;
-begin if (a<0) or (a>maxuint) then trap(EILLINS); argn:=a end;
-
-function args(a:double):size;
-begin if (a<=0) or (a>maxoffs)
-	then trap(EODDZ)
-	else if (a mod wsize)<>0 then trap(EODDZ);
-      args:=a ;
-end;
-
-function argz(a:double):size;
-begin if (a<0) or (a>maxoffs)
-	then trap(EODDZ)
-	else if (a mod wsize)<>0 then trap(EODDZ);
-      argz:=a ;
-end;
-
-function argo(a:double):size;
-begin if (a<=0) or (a>maxoffs)
-	then trap(EODDZ)
-	else if (a mod wsize<>0) and (wsize mod a<>0) then trap(EODDZ);
-      argo:=a ;
-end;
-
-function argw(a:double):size;
-begin if (a<=0) or (a>maxoffs) or (a>maxuint)
-	then trap(EODDZ)
-	else if (a mod wsize)<>0 then trap(EODDZ);
-      argw:=a ;
-end;
-
-function argp(a:double):size;
-begin if (a<0) or (a>=header[NPROC]) then trap(EILLINS); argp:=a end;
-
-function argr(a:double):word;
-begin if (a<0) or (a>2) then trap(EILLINS); argr:=a end;
-
-procedure argwf(s:double);
-begin if argw(s)<>fsize then trap(EILLINS) end;
-
-function szindex(s:double):integer;
-begin s:=argw(s); if (s mod wsize <> 0) or (s>2*wsize) then trap(EILLINS);
-      szindex:=s div wsize
-end;
-
-function locadr(l:double):adr;
-begin l:=argl(l); if l<0 then locadr:=lb+l else locadr:=lb+l+savsize end;
-
-function signwd(w:word):sword;
-begin if w = undef then trap(EIUND);
-      if w >= signbit then signwd:=w-negoff else signwd:=w
-end;
-
-function dosign(w:word):sword;
-begin if w >= signbit then dosign:=w-negoff else dosign:=w end;
-
-function unsign(w:sword):word;
-begin if w<0 then unsign:=w+negoff else unsign:=w end;
-
-function chopw(dw:double):word;
-begin chopw:=dw mod negoff end;
-
-function fitsw(w:full;trapno:byte):word;
-{ checks whether value fits in signed word, returns unsigned representation}
-begin
-  if (w>maxsint) or (w<-signbit) then
-    begin trap(trapno);
-      if w<0 then fitsw:=negoff- (-w)mod negoff
-	     else fitsw:=w mod negoff;
-    end
-  else fitsw:=unsign(w)
-end;
-
-function fitd(w:full):double;
-begin
-  if abs(w) > maxdbl then trap(ECONV);
-  fitd:=w
-end;
-.ne 20
-.sp 2
-{---------------------------------------------------------------------------}
-{                        Memory access routines                             }
-{---------------------------------------------------------------------------}
-
-{ memw returns a machine word as an unsigned integer
-  memb returns a single byte as a positive integer: 0 <= memb <= 255
-  mems(a,s) fetches an object smaller than a word and returns a word
-  store(a,v) stores the word v at machine address a
-  storea(a,v) stores the address v at machine address a
-  storeb(a,b) stores the byte b at machine address a
-  stores(a,s,v) stores the s least significant bytes of a word at address a
-  memi returns an offset from the instruction space
-       Note that the procedure descriptors are part of instruction space.
-  nextpc returns the next byte addressed by pc, incrementing pc
-
-  lino changes the line number word.
-  filna changes the pointer to the file name.
-
-  All routines check to make sure the address is within range and valid for
-  the size of the object. If an addressing error is found, a trap occurs.
-}
-
-
-function memw(a:adr):word;
-var b:word; i:integer;
-begin wordadr(a); b:=0;
-      for i:=wsize-1 downto 0 do b:=256*b + data[a+i] ;
-      memw:=b
-end;
-
-function memd(a:adr):double; { Always signed }
-var b:double; i:integer;
-begin wordadr(a); b:=data[a+2*wsize-1];
-      if b>=128 then b:=b-256;
-      for i:=2*wsize-2 downto 0 do b:=256*b + data[a+i] ;
-      memd:=b
-end;
-
-function mema(a:adr):adr;
-var b:adr; i:integer;
-begin wordadr(a); b:=0;
-      for i:=asize-1 downto 0 do b:=256*b + data[a+i] ;
-      mema:=b
-end;
-
-function mems(a:adr;s:size):word;
-var i:integer; b:word;
-begin chkadr(a,s); b:=0; for i:=1 to s do b:=b*256+data[a+s-i]; mems:=b end;
-
-function memb(a:adr):byte;
-begin memadr(a); memb:=data[a] end;
-
-procedure store(a:adr; x:word);
-var i:integer;
-begin wordadr(a);
-  for i:=0 to wsize-1 do
-     begin data[a+i]:=x mod 256; x:=x div 256 end
-end;
-
-procedure storea(a:adr; x:adr);
-var i:integer;
-begin wordadr(a);
-  for i:=0 to asize-1 do
-     begin data[a+i]:=x mod 256; x:=x div 256 end
-end;
-
-procedure stores(a:adr;s:size;v:word);
-var i:integer;
-begin chkadr(a,s);
-  for i:=0 to s-1 do begin data[a+i]:=v mod 256; v:=v div 256 end;
-end;
-
-procedure storeb(a:adr; b:byte);
-begin memadr(a); data[a]:=b end;
-
-function memi(a:adr):adr;
-var b:adr; i:integer;
-begin if (a mod wsize<>0) or (a+asize-1>maxcode) then trap(EBADPTR); b:=0;
-      for i:=asize-1 downto 0 do b:=256*b + code[a+i] ;
-      memi:=b
-end;
-
-function nextpc:byte;
-begin if pc>=pd then trap(EBADPC); nextpc:=code[pc]; newpc(pc+1) end;
-
-procedure lino(w:word);
-begin store(lineadr,w) end;
-
-procedure filna(a:adr);
-begin storea(fileadr,a) end;
-.ne 20
-.sp 2
-{---------------------------------------------------------------------------}
-{                    Stack Manipulation Routines                            }
-{---------------------------------------------------------------------------}
-
-{ push puts a word on the stack
-  pushsw takes a signed one word integer and pushes it on the stack
-  pop removes a machine word from the stack and delivers it as a word
-  popsw removes a machine word from the stack and delivers a signed integer
-  pusha pushes an address on the stack
-  popa removes a machine word from the stack and delivers it as an address
-  pushd pushes a double precision number on the stack
-  popd removes two machine words and returns a double precision integer
-  pushr pushes a float (floating point) number on the stack
-  popr removes several machine words and returns a float number
-  pushx puts an object of arbitrary size on the stack
-  popx removes an object of arbitrary size
-									  }
-
-procedure push(x:word);
-begin newsp(sp-wsize); store(sp,x) end;
-
-procedure pushsw(x:sword);
-begin newsp(sp-wsize); store(sp,unsign(x)) end;
-
-function pop:word;
-begin pop:=memw(sp); newsp(sp+wsize) end;
-
-function popsw:sword;
-begin popsw:=signwd(pop) end;
-
-procedure pusha(x:adr);
-begin newsp(sp-asize); storea(sp,x) end;
-
-function popa:adr;
-begin popa:=mema(sp); newsp(sp+asize) end;
-
-procedure pushd(y:double);
-begin { push double integer onto the stack } newsp(sp-2*wsize) end;
-
-function popd:double;
-begin { pop double integer from the stack } newsp(sp+2*wsize); popd:=0 end;
-
-procedure pushr(z:real);
-begin { Push a float onto the stack } newsp(sp-fsize) end;
-
-function popr:real;
-begin { pop float from the stack } newsp(sp+fsize); popr:=0.0 end;
-
-procedure pushx(objsize:size; a:adr);
-var i:integer;
-begin
-  if objsize<wsize
-     then push(mems(a,objsize))
-     else for i:=1 to objsize div wsize do push(memw(a+objsize-wsize*i))
-end;
-
-procedure popx(objsize:size; a:adr);
-var i:integer;
-begin
-  if objsize<wsize
-     then stores(a,objsize,pop)
-     else for i:=1 to objsize div wsize do store(a-wsize+wsize*i,pop)
-end;
-.ne 20
-.sp 2
-{---------------------------------------------------------------------------}
-{              Bit manipulation routines (extract, shift, rotate)           }
-{---------------------------------------------------------------------------}
-
-procedure sleft(var w:sword);  { 1 bit left shift   }
-begin w:= dosign(fitsw(2*w,EIOVFL)) end;
-
-procedure suleft(var w:word);  { 1 bit left shift   }
-begin w := chopw(2*w) end;
-
-procedure sdleft(var d:double);  { 1 bit left shift   }
-begin { shift two word signed integer } end;
-
-procedure sright(var w:sword);  { 1 bit right shift with sign extension }
-begin if w >= 0 then w := w div 2 else w := (w-1) div 2 end;
-
-procedure suright(var w:word);    { 1 bit right shift without sign extension }
-begin w := w div 2 end;
-
-procedure sdright(var d:double);  { 1 bit right shift   }
-begin { shift two word signed integer } end;
-
-procedure rleft(var w:word);  { 1 bit left rotate }
-begin if w >= t15
-	then w:=(w-t15)*2 + 1
-	else w:=w*2
-end;
-
-procedure rright(var w:word);  { 1 bit right rotate }
-begin if w mod 2 = 1
-	then w:=w div 2 + t15
-	else w:=w div 2
-end;
-
-function sextend(w:word;s:size):word;
-var i:size;
-begin
-  for i:=1 to (wsize-s)*8 do rleft(w);
-  for i:=1 to (wsize-s)*8 do sright(w);
-  sextend:=w;
-end;
-
-function bit(b:bitnr; w:word):bitval; { return bit b of the word w }
-var i:bitnr;
-begin for i:= 1 to b do rright(w); bit:= w mod 2 end;
-
-function bf(ty:bftype; w1,w2:word):word;  { return boolean fcn of 2 words }
-var i:bitnr; j:word;
-begin j:=0;
-      for i:= maxbitnr downto 0 do
-	begin j := 2*j;
-	      case ty of
-		andf: if bit(i,w1)+bit(i,w2) = 2 then j:=j+1;
-		iorf: if bit(i,w1)+bit(i,w2) > 0 then j:=j+1;
-		xorf: if bit(i,w1)+bit(i,w2) = 1 then j:=j+1
-	      end
-	end;
-      bf:=j
-end;
-
-{---------------------------------------------------------------------------}
-{                           Array indexing
-{---------------------------------------------------------------------------}
-
-function arraycalc(c:adr):adr; { subscript calculation }
-var j:full; objsize:size; a:adr;
-begin j:= popsw - signwd(memw(c));
-  if (j<0) or (j>memw(c+wsize)) then trap(EARRAY);
-  objsize := argo(memw(c+wsize+wsize));
-  a := j*objsize+popa; chkadr(a,objsize);
-  arraycalc:=a
-end;
-.ne 20
-.sp 2
-{---------------------------------------------------------------------------}
-{                       Double and Real Arithmetic                          }
-{---------------------------------------------------------------------------}
-
-{ All routines for doubles and floats are dummy routines, since the format of
-  doubles and floats is not defined in EM.
-}
-
-function doadi(ds,dt:double):double;
-begin { add two doubles } doadi:=0 end;
-
-function dosbi(ds,dt:double):double;
-begin { subtract two doubles } dosbi:=0 end;
-
-function domli(ds,dt:double):double;
-begin { multiply two doubles } domli:=0 end;
-
-function dodvi(ds,dt:double):double;
-begin { divide two doubles } dodvi:=0 end;
-
-function dormi(ds,dt:double):double;
-begin { modulo of two doubles } dormi:=0 end;
-
-function dongi(ds:double):double;
-begin { negative of a double } dongi:=0 end;
-
-function doadf(x,y:real):real;
-begin { add two floats } doadf:=0.0 end;
-
-function dosbf(x,y:real):real;
-begin { subtract two floats } dosbf:=0.0 end;
-
-function domlf(x,y:real):real;
-begin { multiply two floats } domlf:=0.0 end;
-
-function dodvf(x,y:real):real;
-begin { divide two floats } dodvf:=0.0 end;
-
-function dongf(x:real):real;
-begin { negate a float } dongf:=0.0 end;
-
-procedure dofif(x,y:real;var intpart,fraction:real);
-begin { dismember x*y into integer and fractional parts }
-  intpart:=0.0;  { integer part of x*y, same sign as x*y }
-  fraction:=0.0;
-	{ fractional part of x*y, 0<=abs(fraction)<1 and same sign as x*y }
-end;
-
-procedure dofef(x:real;var mantissa:real;var exponent:sword);
-begin { dismember x into mantissa and exponent parts }
-  mantissa:=0.0;  { mantissa of x , >= 1/2 and <1 }
-  exponent:=0;    { base 2 exponent of x }
-end;
-.bp
-{---------------------------------------------------------------------------}
-{                            Trap and Call                                  }
-{---------------------------------------------------------------------------}
-
-procedure call(p:adr); { Perform the call }
-begin
-  pusha(lb);pusha(pc);
-  newlb(sp);newsp(sp - memi(pd + pdsize*p + pdlocs));
-  newpc(memi(pd + pdsize*p+ pdbase))
-end;
-
-procedure dotrap(n:byte);
-var i:size;
-begin
-  if (uerrorproc=0) or intrap then
-    begin
-      if intrap then
-	writeln('Recursive trap, first trap number was ', trapval:1);
-      writeln('Error ', n:1);
-      writeln('With',ord(insr):4,' arg ',k:1);
-      goto 9999
-    end;
-  { Deposit all interpreter variables that need to be saved on
-    the stack. This includes all scratch variables that can
-    be in use at the moment and ( not possible in this interpreter )
-    the internal address of the interpreter where the error occurred.
-    This would make it possible to execute an RTT instruction totally
-    transparent to the user program.
-    It can, for example, occur within an ADD instruction that both
-    operands are undefined and that the result overflows.
-    Although this will generate 3 error traps it must be possible
-    to ignore them all.
-}
-  intrap:=true; trapval:=n;
-  for i:=retsize div wsize downto 1 do push(retarea[i]);
-  push(retsize);              { saved return area }
-  pusha(mema(fileadr));       { saved current file name pointer }
-  push(memw(lineadr));        { saved line number }
-  push(n);                    { push error number }
-  a:=argp(uerrorproc);
-  uerrorproc:=0;              { reset signal }
-  call(a);                    { call the routine }
-  intrap:=false;              { Don't catch recursive traps anymore }
-  goto 8888;                  { reenter main loop }
-end;
-
-procedure trap;
-{ This routine is invoked for overflow, and other run time errors.
-  For non-fatal errors, trap returns to the calling routine
-}
-begin
-  if n>=16 then dotrap(n) else if bit(n,ignmask)=0 then dotrap(n);
-end;
-
-procedure dortt;
-{ The restoration of file address and line number is not essential.
-  The restoration of the return save area is.
-}
-var i:size;
-    n:word;
-begin
-  newsp(lb); lb:=maxdata+1 ; { to circumvent ESTACK for the popa + pop }
-  newpc(popa); newlb(popa); { So far a plain RET 0 }
-  n:=pop; if (n>=16) and (n<64) then goto 9999 ;
-  lino(pop); filna(popa); retsize:=pop;
-  for i:=1 to retsize div wsize do retarea[i]:=pop ;
-end;
-.sp 2
-{---------------------------------------------------------------------------}
-{                              monitor calls                                }
-{---------------------------------------------------------------------------}
-
-
-procedure domon(entry:word);
-var     index:  1..63;
-	dummy:  double;
-	count,rwptr:    adr;
-	token:  byte;
-	i:      integer;
-begin
-  if (entry<=0) or (entry>63) then entry:=63 ;
-  index:=entry;
-  case index of
-   1: begin { exit } exitstatus:=pop; halted:=true end;
-   3: begin { read }  dummy:=pop; { All input is from stdin }
-	rwptr:=popa; count:=popa;
-	i:=0 ;
-	while (not eof(input)) and (i<count) do
-	begin
-	  if eoln(input) then begin storeb(rwptr,10) ; count:=i end
-			 else storeb(rwptr,ord(input^)) ;
-	  get(input); rwptr:=rwptr+1 ; i:=i+1 ;
-	end;
-	pusha(i); push(0)
-      end;
-   4: begin { write } dummy:=pop; { All output is to stdout }
-	rwptr:=popa; count:=popa;
-	for i:=1 to count do
-	  begin token:=memb(rwptr); rwptr:=rwptr+1 ;
-	    if token=10 then writeln else write(chr(token))
-	  end ;
-	pusha(count);
-	push(0)
-      end;
-  54: begin { ioctl, faked } dummy:=popa;dummy:=popa;dummy:=pop;push(0) end ;
-       2,          5,  6,  7,  8,  9, 10,
-  11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
-  21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
-  31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
-  41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
-  51, 52, 53,     55, 56, 57, 58, 59, 60,
-  61, 62:
-      begin push(22); push(22) end;
-  63: { exists only for the trap }
-      trap(EBADMON)
-  end
-end;
-.bp
-{---------------------------------------------------------------------------}
-{                       Initialization and debugging                        }
-{---------------------------------------------------------------------------}
-
-procedure doident; { print line number and file name }
-var a:adr; i,c:integer; found:boolean;
-begin
-  write('at line ',memw(lineadr):1,' ');
-  a:=mema(fileadr); if a<>0 then
-  begin i:=20; found:=false;
-    while (i<>0) and not found do
-    begin c:=memb(a); a:=a+1; found:=true; i:=i-1;
-      if (c>=48) and (c<=57) then
-	begin found:=false; write(chr(ord('0')+c-48)) end;
-      if (c>=65) and (c<=90) then
-	begin found:=false; write(chr(ord('A')+c-65)) end;
-      if (c>=97) and (c<=122) then
-	begin found:=false; write(chr(ord('a')+c-97)) end;
-    end;
-  end;
-  writeln;
-end;
-
-procedure initialize;  { start the ball rolling }
-{ This is not part of the machine definition }
-var cset:set of char;
-    f:ifset;
-    iclass:insclass;
-    insno:byte;
-    nops:integer;
-    opcode:byte;
-    i,j,n:integer;
-    wtemp:sword;
-    count:integer;
-    repc:adr;
-    nexta,firsta:adr;
-    elem:byte;
-    amount,ofst:size;
-    c:char;
-
-    function readb(n:integer):double;
-    var b:byte;
-    begin read(prog,b); if n>1 then readb:=readb(n-1)*256+b else readb:=b end;
-
-    function readbyte:byte;
-    begin readbyte:=readb(1) end;
-
-    function readword:word;
-    begin readword:=readb(wsize) end;
-
-    function readadr:adr;
-    begin readadr:=readb(asize) end;
-
-    function ifind(ordinal:byte):mnem;
-    var loopvar:mnem;
-	found:boolean;
-    begin ifind:=NON;
-      loopvar:=insr; found:=false;
-      repeat
-	if ordinal=ord(loopvar) then
-	  begin found:=true; ifind:=loopvar end;
-	if loopvar<>ZRL then loopvar:=succ(loopvar) else loopvar:=NON;
-      until found or (loopvar=insr) ;
-   end;
-
-    procedure readhdr;
-    type hdrw=0..32767 ; { 16 bit header words }
-    var  hdr: hdrw;
-	 i: integer;
-    begin
-      for i:=0 to 7 do
-      begin hdr:=readb(2);
-	case i of
-	0: if hdr<>3757 then { 07255 }
-	   begin writeln('Not an em load file'); halt end;
-	2: if hdr<>0 then
-	   begin writeln('Unsolved references'); halt end;
-	3: if hdr<>3 then
-	   begin writeln('Incorrect load file version'); halt end;
-	4: if hdr<>wsize then
-	   begin writeln('Incorrect word size'); halt end;
-	5: if hdr<>asize then
-	   begin writeln('Incorrect pointer size'); halt end;
-	1,6,7:;
-	end
-      end
-    end;
-
-    procedure noinit;
-    begin writeln('Illegal initialization'); halt end;
-
-    procedure readint(a:adr;s:size);
-    var i:size;
-    begin { construct integer out of byte sequence }
-      for i:=1 to s do { construct the value and initialize at a }
-	begin storeb(a,readbyte); a:=a+1 end
-    end;
-
-    procedure readuns(a:adr;s:size);
-    begin { construct unsigned out of byte sequence }
-      readint(a,s) { identical to readint }
-    end;
-
-    procedure readfloat(a:adr;s:size);
-    var i:size; b:byte;
-    begin { construct float out of string}
-      if (s<>4) and (s<>8) then noinit; i:=0;
-      repeat { eat the bytes, construct the value and intialize at a }
-	b:=readbyte; i:=i+1;
-      until b=0 ;
-    end;
-
-begin
-  halted:=false;
-  exitstatus:=undef;
-  uerrorproc:=0; intrap:=false;
-
-  { initialize tables }
-  for i:=0 to maxcode do code[i]:=0;
-  for i:=0 to maxdata do data[i]:=0;
-  for iclass:=prim to tert do
-    for i:=0 to 255 do
-      with dispat[iclass][i] do
-	begin instr:=NON; iflag:=[zbit] end;
-
-  { read instruction table file. see appendix B }
-  { The table read here is a simple transformation of the table on page xx }
-  { - instruction names were transformed to numbers }
-  { - the '-' flag was transformed to an 'i' flag for 'w' type instructions }
-  { - the 'S' flag was added for instructions having signed operands }
-  reset(tables);
-  insr:=NON;
-  repeat
-    read(tables,insno) ; cset:=[]; f:=[];
-    insr:=ifind(insno);
-    if insr=NON then begin writeln('Incorrect table'); halt end;
-    repeat read(tables,c) until c<>' ' ;
-    repeat
-      cset:=cset+[c];
-      read(tables,c)
-    until c=' ' ;
-    if 'm' in cset then f:=f+[mini];
-    if 's' in cset then f:=f+[short];
-    if '-' in cset then f:=f+[zbit];
-    if 'i' in cset then f:=f+[ibit];
-    if 'S' in cset then f:=f+[sbit];
-    if 'w' in cset then f:=f+[wbit];
-    if (mini in f) or (short in f) then read(tables,nops) else nops:=1 ;
-    readln(tables,opcode);
-    if ('4' in cset) or ('8' in cset) then
-      begin iclass:=tert end
-    else if 'e' in cset then
-      begin iclass:=second end
-    else iclass:=prim;
-    for i:=0 to nops-1 do
-    begin
-      with dispat[iclass,opcode+i] do
-      begin
-	iflag:=f; instr:=insr;
-	if '2' in cset      then ilength:=2
-	else if '4' in cset then ilength:=4
-	else if '8' in cset then ilength:=8
-	else if (mini in f) or (short in f) then
-	  begin
-	    if 'N' in cset then wtemp:=-1-i else wtemp:=i ;
-	    if 'o' in cset then wtemp:=wtemp+1 ;
-	    if short in f then wtemp:=wtemp*256 ;
-	    implicit:=wtemp
-	  end
-      end
-    end
-  until eof(tables);
-
-  { read in program text, data and procedure descriptors }
-  reset(prog);
-  readhdr;                               { verify first header }
-  for i:=1 to 8 do header[i]:=readadr;  { read second header }
-  hp:=maxdata+1; sp:=maxdata+1; lino(0);
-  { read program text }
-  if header[NTEXT]+header[NPROC]*pdsize>maxcode then
-    begin writeln('Text size too large'); halt end;
-  if header[SZDATA]>maxdata then
-    begin writeln('Data size too large'); halt end;
-  for i:=0 to header[NTEXT]-1 do code[i]:=readbyte;
-  { read data blocks }
-  nexta:=0;
-  for i:=1 to header[NDATA] do
-    begin
-      n:=readbyte;
-      if n<>0 then
-	begin
-	  elem:=readbyte; firsta:=nexta;
-	  case n of
-	  1: { uninitialized words }
-	     for j:=1 to elem do
-	     begin store(nexta,undef); nexta:=nexta+wsize end;
-	  2: { initialized bytes }
-	     for j:=1 to elem do
-	     begin storeb(nexta,readbyte); nexta:=nexta+1 end;
-	  3: { initialized words }
-	     for j:=1 to elem do
-	     begin store(nexta,readword); nexta:=nexta+wsize end;
-	  4,5: { instruction and data pointers }
-	     for j:=1 to elem do
-	     begin storea(nexta,readadr); nexta:=nexta+asize end;
-	  6: { signed integers }
-	     begin readint(nexta,elem); nexta:=nexta+elem end;
-	  7: { unsigned integers }
-	     begin readuns(nexta,elem); nexta:=nexta+elem end;
-	  8: { floating point numbers }
-	     begin readfloat(nexta,elem); nexta:=nexta+elem end;
-	  end
-	end
-      else
-	begin
-	  repc:=readadr; amount:=nexta-firsta;
-	  for count:=1 to repc do
-	  begin
-	    for ofst:=0 to amount-1 do data[nexta+ofst]:=data[firsta+ofst];
-	    nexta:=nexta+amount;
-	  end
-	end
-    end;
-  if header[SZDATA]<>nexta then writeln('Data initialization error');
-  hp:=nexta;
-  { read descriptor table }
-  pd:=header[NTEXT];
-  for i:=1 to header[NPROC]*pdsize do code[pd+i-1]:=readbyte;
-  { call the entry point routine }
-  ignmask:=0;	   { catch all traps, higher numbered traps cannot be ignored}
-  retsize:=0;
-  lb:=maxdata;     { illegal dynamic link }
-  pc:=maxcode;     { illegal return address }
-  push(0); a:=sp;  { No environment }
-  push(0); b:=sp;  { No args }
-  pusha(a);        { envp }
-  pusha(b);        { argv }
-  push(0);         { argc }
-  call(argp(header[ENTRY]));
-end;
-.bp
-{---------------------------------------------------------------------------}
-{                       MAIN LOOP OF THE INTERPRETER                        }
-{---------------------------------------------------------------------------}
-{ It should be noted that the interpreter (microprogram) for  an  EM
-  machine  can be written in two fundamentally different ways: (1) the
-  instruction operands are fetched in the main loop, or  (2)  the  in-
-  struction operands are fetched after the 256 way branch, by the exe-
-  cution routines themselves.  In this interpreter, method (1) is used
-  to  simplify  the  description  of execution  routines. The dispatch
-  table dispat is used to determine how the operand is  encoded. There
-  are 4 possibilities:
-
-     0. There is no operand
-     1. The operand and  instruction are  together in 1  byte (mini)
-     2. The operand is  one byte long and follows the opcode byte(s)
-     3. The operand is two bytes long and follows the opcode byte(s)
-     4. The operand is four bytes long and follows the opcode byte(s)
-
-  In  this  interpreter,  the  main  loop determines the operand type,
-  fetches it, and leaves it in the global variable k for the execution
-  routines  to use.  Consequently, instructions such as LOL, which use
-  three different formats, need only be described once in the body  of
-  the interpreter.
-      However, for  a  production  interpreter,  or  a  hardware  EM
-  machine,  it  is  probably better to use method (2), i.e. to let the
-  execution routines themselves fetch their own operands.  The  reason
-  for this is that each opcode uniquely determines the operand format,
-  so no table lookup in the dispatch table is needed.  The whole table
-  is not needed. Method (2) therefore executes much faster.
-      However, separate execution routines will be needed for LOL with
-  a one byte offset,  and  LOL with a two byte offset.  It is to avoid
-  this additional clutter that method (1) is used here.  In a  produc-
-  tion interpreter, it is envisioned that the main loop will fetch the
-  next instruction byte, and use it as an index into a 256 word  table
-  to  find  the  address  of  the interpreter routine to jump to.  The
-  routine jumped to will  begin  by  fetching  its  operand,  if  any,
-  without  any  table  lookup,  since it knows which format to expect.
-  After doing the work, it returns to the main  loop  by  jumping  in-
-  directly  to  a register that contains the address of the main loop.
-      A slight variation on this idea is to have the  register contain
-  the address of the branch table, rather than the address of the main
-  loop.
-      Another  issue  is whether the execution routines for LOL 0, LOL
-  2, LOL 4, etc. should all be have distinct execution routines. Doing
-  so  provides for the maximum speed, since the operand is implicit in
-  the routine itself.  The disadvantage is that many nearly  identical
-  execution  routines will then be needed.  Another way of doing it is
-  to keep the instruction byte fetched from memory (LOL 0, LOL 2,  LOL
-  4, etc.) in some register, and have all the LOL mini format instruc-
-  tions branch to a common routine.  This routine can  then  determine
-  the  operand  by  subtracting  the code for LOL 0 from the register,
-  leaving the true operand in the register  (as  a  word  quantity  of
-  course).   This  method  makes the interpreter smaller, but is a bit
-  slower.
-.bp
-       To make this important point a little clearer, consider how a
-  production interpreter for the PDP-11 might appear.  Let us assume the
-  following opcodes have been assigned:
-
-       31: LOL -2     (2 bytes, i.e. next word)
-       32: LOL -4
-       33: LOL -6
-       34: LOL b      (format with a one byte offset)
-       35: LOL w      (format with a one word, i.e. two byte offset)
-
-  Further assume that each of the 5 opcodes will have its own execution
-  routine, i.e. we are making a tradeoff in favor of fast execution and
-  a slightly larger interpreter.
-       Register r5 is the em program counter.
-       Register r4 is the em LB register
-       Register r3 is the em SP register (the stack grows toward low core)
-       Register r2 contains the interpreter address of the main loop
-
-  The main loop looks like this:
-
-       movb (r5)+,r0           /fetch the opcode into r0 and increment r5
-       asl r0                  /shift r0 left 1 bit. Now: -256<=r0<=+254
-       jmp *table(r0)          /jump to execution routine
-
-  Notice that no operand fetching has been done. The execution routines for
-  the 5 sample instructions given above might be as follows:
-
-  lol2: mov -2(r4),-(sp)       /push local -2 onto stack
-	jmp (r2)               /go back to main loop
-  lol4: mov -4(r4),-(sp)       /push local -4 onto stack
-	jmp (r2)               /go back to main loop
-  lol6: mov -6(r4),-(sp)       /push local -6 onto stack
-	jmp (r2)               /go back to main loop
-  lolb: mov $177400,r0         /prepare to fetch the 1 byte operand
-	bisb (r5)+,r0          /operand is now in r0
-	asl r0                 /r0 is now offset from LB in bytes, not words
-	add r4,r0              /r0 is now address of the needed local
-	mov (r0),-(sp)         /push the local onto the stack
-	jmp (r2)
-  lolw: clr r0                 /prepare to fetch the 2 byte operand
-	bisb (r5)+,r0          /fetch high order byte first !!!
-	swab r0                /insert high order byte in place
-	bisb (r5)+,r0          /insert low order byte in place
-	asl r0                 /convert offset to bytes, from words
-	add r4,r0              /r0 is now address of needed local
-	mov (r0),-(sp)         /stack the local
-	jmp (r2)               /done
-
-  The important thing to notice is where and how the operand fetch occurred:
-       lol2, lol4, and lol6, (the mini's) have implicit operands
-       lolb knew it had to fetch one byte, and did so without any table lookup
-       lolw knew it had to fetch a word, and did so, high order byte first }
-.bp
-.sp 4
-{---------------------------------------------------------------------------}
-{           Routines for the individual instructions                        }
-{---------------------------------------------------------------------------}
-procedure loadops;
-var j:integer;
-begin
-  case insr of
-    { LOAD GROUP }
-    LDC: pushd(argd(k));
-    LOC: pushsw(argc(k));
-    LOL: push(memw(locadr(k)));
-    LOE: push(memw(argg(k)));
-    LIL: push(memw(mema(locadr(k))));
-    LOF: push(memw(popa+argf(k)));
-    LAL: pusha(locadr(k));
-    LAE: pusha(argg(k));
-    LXL: begin a:=lb; for j:=1 to argn(k) do a:=mema(a+savsize); pusha(a) end;
-    LXA: begin a:=lb;
-	   for j:=1 to argn(k) do a:= mema(a+savsize);
-	   pusha(a+savsize)
-	 end;
-    LOI: pushx(argo(k),popa);
-    LOS: begin k:=argw(k); if k<>wsize then trap(EILLINS);
-	   k:=pop; pushx(argo(k),popa)
-	 end;
-    LDL: begin a:=locadr(k); push(memw(a+wsize)); push(memw(a)) end;
-    LDE: begin k:=argg(k); push(memw(k+wsize)); push(memw(k)) end;
-    LDF: begin k:=argf(k);
-	   a:=popa; push(memw(a+k+wsize)); push(memw(a+k))
-	 end;
-    LPI: push(argp(k))
-  end
-end;
-
-procedure storeops;
-begin
-  case insr of
-    { STORE GROUP }
-    STL: store(locadr(k),pop);
-    STE: store(argg(k),pop);
-    SIL: store(mema(locadr(k)),pop);
-    STF: begin a:=popa; store(a+argf(k),pop) end;
-    STI: popx(argo(k),popa);
-    STS: begin k:=argw(k); if k<>wsize then trap(EILLINS);
-	   k:=popa; popx(argo(k),popa)
-	 end;
-    SDL: begin a:=locadr(k); store(a,pop); store(a+wsize,pop) end;
-    SDE: begin k:=argg(k); store(k,pop); store(k+wsize,pop) end;
-    SDF: begin k:=argf(k); a:=popa; store(a+k,pop); store(a+k+wsize,pop) end
-  end
-end;
-
-procedure intarith;
-var i:integer;
-begin
-  case insr of
-    { SIGNED INTEGER ARITHMETIC }
-    ADI: case szindex(argw(k)) of
-	 1: begin st:=popsw; ss:=popsw; push(fitsw(ss+st,EIOVFL)) end;
-	 2: begin dt:=popd; ds:=popd; pushd(doadi(ds,dt)) end;
-	 end ;
-    SBI: case szindex(argw(k)) of
-	 1: begin st:=popsw; ss:= popsw; push(fitsw(ss-st,EIOVFL)) end;
-	 2: begin dt:=popd; ds:=popd; pushd(dosbi(ds,dt)) end;
-	 end ;
-    MLI: case szindex(argw(k)) of
-	 1: begin st:=popsw; ss:= popsw; push(fitsw(ss*st,EIOVFL)) end;
-	 2: begin dt:=popd; ds:=popd; pushd(domli(ds,dt)) end;
-	 end ;
-    DVI: case szindex(argw(k)) of
-	 1: begin st:= popsw; ss:= popsw;
-	       if st=0 then trap(EIDIVZ) else pushsw(ss div st)
-	    end;
-	 2: begin dt:=popd; ds:=popd; pushd(dodvi(ds,dt)) end;
-	 end;
-    RMI: case szindex(argw(k)) of
-	 1: begin st:= popsw; ss:=popsw;
-	       if st=0 then trap(EIDIVZ) else pushsw(ss - (ss div st)*st)
-	    end;
-	 2: begin dt:=popd; ds:=popd; pushd(dormi(ds,dt)) end
-	 end;
-    NGI: case szindex(argw(k)) of
-	 1: begin st:=popsw; pushsw(-st) end;
-	 2: begin ds:=popd; pushd(dongi(ds)) end
-	 end;
-    SLI: begin t:=pop;
-	   case szindex(argw(k)) of
-	   1: begin ss:=popsw;
-		 for i:= 1 to t do sleft(ss); pushsw(ss)
-	      end
-	   end
-	 end;
-    SRI: begin t:=pop;
-	   case szindex(argw(k)) of
-	   1: begin ss:=popsw;
-		 for i:= 1 to t do sright(ss); pushsw(ss)
-	      end;
-	   2: begin ds:=popd;
-		 for i:= 1 to t do sdright(ss); pushd(ss)
-	      end
-	   end
-	 end
-  end
-end;
-
-procedure unsarith;
-var i:integer;
-begin
-  case insr of
-    { UNSIGNED INTEGER ARITHMETIC }
-    ADU: case szindex(argw(k)) of
-	 1: begin t:=pop; s:= pop; push(chopw(s+t)) end;
-	 2: trap(EILLINS);
-	 end ;
-    SBU: case szindex(argw(k)) of
-	 1: begin t:=pop; s:= pop; push(chopw(s-t)) end;
-	 2: trap(EILLINS);
-	 end ;
-    MLU: case szindex(argw(k)) of
-	 1: begin t:=pop; s:= pop; push(chopw(s*t)) end;
-	 2: trap(EILLINS);
-	 end ;
-    DVU: case szindex(argw(k)) of
-	 1: begin t:= pop; s:= pop;
-	       if t=0 then trap(EIDIVZ) else push(s div t)
-	    end;
-	 2: trap(EILLINS);
-	 end;
-    RMU: case szindex(argw(k)) of
-	 1: begin t:= pop; s:=pop;
-	       if t=0 then trap(EIDIVZ) else push(s - (s div t)*t)
-	    end;
-	 2: trap(EILLINS);
-	 end;
-    SLU: case szindex(argw(k)) of
-	 1: begin t:=pop; s:=pop;
-	       for i:= 1 to t do suleft(s); push(s)
-	    end;
-	 2: trap(EILLINS);
-	 end;
-    SRU: case szindex(argw(k)) of
-	 1: begin t:=pop; s:=pop;
-	       for i:= 1 to t do suright(s); push(s)
-	    end;
-	 2: trap(EILLINS);
-	 end
-  end
-end;
-
-procedure fltarith;
-begin
-  case insr of
-    { FLOATING POINT ARITHMETIC }
-    ADF: begin argwf(k); rt:=popr; rs:=popr; pushr(doadf(rs,rt)) end;
-    SBF: begin argwf(k); rt:=popr; rs:=popr; pushr(dosbf(rs,rt)) end;
-    MLF: begin argwf(k); rt:=popr; rs:=popr; pushr(domlf(rs,rt)) end;
-    DVF: begin argwf(k); rt:=popr; rs:=popr; pushr(dodvf(rs,rt)) end;
-    NGF: begin argwf(k); rt:=popr; pushr(dongf(rt)) end;
-    FIF: begin argwf(k); rt:=popr; rs:=popr;
-	       dofif(rt,rs,x,y); pushr(y); pushr(x)
-	 end;
-    FEF: begin argwf(k); rt:=popr; dofef(rt,x,ss); pushr(x); pushsw(ss) end
-  end
-end;
-
-procedure ptrarith;
-begin
-  case insr of
-    { POINTER ARITHMETIC }
-    ADP: pusha(popa+argf(k));
-    ADS: case szindex(argw(k)) of
-	 1: begin st:=popsw; pusha(popa+st) end;
-	 2: begin dt:=popd; pusha(popa+dt) end;
-	 end;
-    SBS: begin
-	   a:=popa; b:=popa;
-	   case szindex(argw(k)) of
-	     1: push(fitsw(b-a,EIOVFL));
-	     2: pushd(b-a)
-	   end
-	 end
-  end
-end;
-
-procedure incops;
-var j:integer;
-begin
-  case insr of
-    { INCREMENT/DECREMENT/ZERO }
-    INC: push(fitsw(popsw+1,EIOVFL));
-    INL: begin a:=locadr(k); store(a,fitsw(signwd(memw(a))+1,EIOVFL)) end;
-    INE: begin a:=argg(k); store(a,fitsw(signwd(memw(a))+1,EIOVFL)) end;
-    DEC: push(fitsw(popsw-1,EIOVFL));
-    DEL: begin a:=locadr(k); store(a,fitsw(signwd(memw(a))-1,EIOVFL)) end;
-    DEE: begin a:=argg(k); store(a,fitsw(signwd(memw(a))-1,EIOVFL)) end;
-    ZRL: store(locadr(k),0);
-    ZRE: store(argg(k),0);
-    ZER: for j:=1 to argw(k) div wsize do push(0);
-    ZRF: pushr(0);
-  end
-end;
-
-procedure convops;
-begin
-  case insr of
-    { CONVERT GROUP }
-    CII: begin s:=pop; t:=pop;
-	   if t<wsize then begin push(sextend(pop,t)); t:=wsize end;
-	   case szindex(argw(t)) of
-	   1: if szindex(argw(s))=2 then pushd(popsw);
-	   2: if szindex(argw(s))=1 then push(fitsw(popd,ECONV))
-	   end
-	 end;
-    CIU: case szindex(argw(pop)) of
-	 1: if szindex(argw(pop))=2 then push(unsign(popd mod negoff));
-	 2: trap(EILLINS);
-	 end;
-    CIF: begin argwf(pop);
-	   case szindex(argw(pop)) of 1:pushr(popsw); 2:pushr(popd) end
-	 end;
-    CUI: case szindex(argw(pop)) of
-	 1: case szindex(argw(pop)) of
-	    1: begin s:=pop; if s>maxsint then trap(ECONV); push(s) end;
-	    2: trap(EILLINS);
-	    end;
-	 2: case szindex(argw(pop)) of
-	    1: pushd(pop);
-	    2: trap(EILLINS);
-	    end;
-	 end;
-    CUU: case szindex(argw(pop)) of
-	 1: if szindex(argw(pop))=2 then trap(EILLINS);
-	 2: trap(EILLINS);
-	 end;
-    CUF: begin argwf(pop);
-	   if szindex(argw(pop))=1 then pushr(pop) else trap(EILLINS)
-	 end;
-    CFI: begin sz:=argw(pop); argwf(pop); rt:=popr;
-	   case szindex(sz) of
-	   1: push(fitsw(trunc(rt),ECONV));
-	   2: pushd(fitd(trunc(rt)));
-	   end
-	 end;
-    CFU: begin sz:=argw(pop); argwf(pop); rt:=popr;
-	   case szindex(sz) of
-	   1: push( chopw(trunc(abs(rt)-0.5)) );
-	   2: trap(EILLINS);
-	   end
-	 end;
-    CFF: begin argwf(pop); argwf(pop) end
-  end
-end;
-
-procedure logops;
-var i,j:integer;
-begin
-  case insr of
-    { LOGICAL GROUP }
-    XAND:
-	 begin k:=argw(k);
-	   for j:= 1 to k div wsize do
-	     begin a:=sp+k; t:=pop; store(a,bf(andf,memw(a),t)) end;
-	 end;
-    IOR:
-	 begin k:=argw(k);
-	   for j:= 1 to k div wsize do
-	     begin a:=sp+k; t:=pop; store(a,bf(iorf,memw(a),t)) end;
-	 end;
-    XOR:
-	 begin k:=argw(k);
-	   for j:= 1 to k div wsize do
-	     begin a:=sp+k; t:=pop; store(a,bf(xorf,memw(a),t)) end;
-	 end;
-    COM:
-	 begin k:=argw(k);
-	   for j:= 1 to k div wsize do
-	     begin
-	       store(sp+k-wsize*j, bf(xorf,memw(sp+k-wsize*j), negoff-1))
-	     end
-	 end;
-    ROL: begin k:=argw(k); if k<>wsize then trap(EILLINS);
-	   t:=pop; s:=pop; for i:= 1 to t do rleft(s); push(s)
-	 end;
-    ROR: begin k:=argw(k); if k<>wsize then trap(EILLINS);
-	   t:=pop; s:=pop; for i:= 1 to t do rright(s); push(s)
-	 end
-  end
-end;
-
-procedure setops;
-var i,j:integer;
-begin
-  case insr of
-    { SET GROUP }
-    INN:
-	 begin k:=argw(k);
-	   t:=pop;
-	   i:= t mod 8; t:= t div 8;
-	   if t>=k then
-	     begin trap(ESET); s:=0 end
-	   else
-	     begin s:=memb(sp+t) end;
-	   newsp(sp+k); push(bit(i,s));
-	 end;
-    XSET:
-	 begin k:=argw(k);
-	   t:=pop;
-	   i:= t mod 8; t:= t div 8;
-	   for j:= 1 to k div wsize do push(0);
-	   if t>=k then
-	     trap(ESET)
-	   else
-	     begin s:=1; for j:= 1 to i do rleft(s); storeb(sp+t,s) end
-	 end
-  end
-end;
-
-procedure arrops;
-begin
-  case insr of
-    { ARRAY GROUP }
-    LAR:
-	 begin k:=argw(k); if k<>wsize then trap(EILLINS); a:=popa;
-	   pushx(argo(memw(a+2*k)),arraycalc(a))
-	 end;
-    SAR:
-	 begin k:=argw(k); if k<>wsize then trap(EILLINS); a:=popa;
-	   popx(argo(memw(a+2*k)),arraycalc(a))
-	 end;
-    AAR:
-	 begin k:=argw(k); if k<>wsize then trap(EILLINS); a:=popa;
-	   push(arraycalc(a))
-	 end
-  end
-end;
-
-procedure cmpops;
-begin
-  case insr of
-    { COMPARE GROUP }
-    CMI: case szindex(argw(k)) of
-	 1: begin st:=popsw; ss:=popsw;
-	      if ss<st then pushsw(-1) else if ss=st then push(0) else push(1)
-	    end;
-	 2: begin dt:=popd; ds:=popd;
-	      if ds<dt then pushsw(-1) else if ds=dt then push(0) else push(1)
-	    end;
-	 end;
-    CMU: case szindex(argw(k)) of
-	 1: begin t:=pop; s:=pop;
-	      if s<t then pushsw(-1) else if s=t then push(0) else push(1)
-	    end;
-	 2: trap(EILLINS);
-	 end;
-    CMP: begin a:=popa; b:=popa;
-	  if b<a then pushsw(-1) else if b=a then push(0) else push(1)
-	 end;
-    CMF: begin argwf(k); rt:=popr; rs:=popr;
-	   if rs<rt then pushsw(-1) else if rs=rt then push(0) else push(1)
-	 end;
-    CMS: begin k:=argw(k);
-	   t:= 0; j:= 0;
-	   while (j < k) and (t=0) do
-	     begin if memw(sp+j) <> memw(sp+k+j) then t:=1;
-	       j:=j+wsize
-	     end;
-	   newsp(sp+wsize*k); push(t);
-	 end;
-
-    TLT: if popsw <  0 then push(1) else push(0);
-    TLE: if popsw <= 0 then push(1) else push(0);
-    TEQ: if pop   =  0 then push(1) else push(0);
-    TNE: if pop   <> 0 then push(1) else push(0);
-    TGE: if popsw >= 0 then push(1) else push(0);
-    TGT: if popsw >  0 then push(1) else push(0);
-  end
-end;
-
-procedure branchops;
-begin
-  case insr of
-    { BRANCH GROUP }
-    BRA: newpc(pc+k);
-
-    BLT: begin st:=popsw; if popsw <  st then newpc(pc+k) end;
-    BLE: begin st:=popsw; if popsw <= st then newpc(pc+k) end;
-    BEQ: begin t :=pop  ; if pop   =   t then newpc(pc+k) end;
-    BNE: begin t :=pop  ; if pop   <>  t then newpc(pc+k) end;
-    BGE: begin st:=popsw; if popsw >= st then newpc(pc+k) end;
-    BGT: begin st:=popsw; if popsw >  st then newpc(pc+k) end;
-
-    ZLT: if popsw <  0 then newpc(pc+k);
-    ZLE: if popsw <= 0 then newpc(pc+k);
-    ZEQ: if pop   =  0 then newpc(pc+k);
-    ZNE: if pop   <> 0 then newpc(pc+k);
-    ZGE: if popsw >= 0 then newpc(pc+k);
-    ZGT: if popsw >  0 then newpc(pc+k)
-  end
-end;
-
-procedure callops;
-var j:integer;
-begin
-  case insr of
-    { PROCEDURE CALL GROUP }
-    CAL: call(argp(k));
-    CAI: begin call(argp(popa)) end;
-    RET: begin k:=argz(k); if k div wsize>maxret  then trap(EILLINS);
-	   for j:= 1 to k div wsize do retarea[j]:=pop; retsize:=k;
-	   newsp(lb); lb:=maxdata+1; { To circumvent stack overflow error }
-	   newpc(popa);
-	   if pc=maxcode then
-	   begin
-	     halted:=true;
-	     if retsize=wsize then exitstatus:=retarea[1]
-	       else exitstatus:=undef
-	  end
-	  else
-	     newlb(popa);
-	 end;
-    LFR: begin k:=args(k); if k<>retsize then trap(EILLINS);
-	   for j:=k div wsize downto 1 do push(retarea[j]);
-	 end
-  end
-end;
-
-procedure miscops;
-var i,j:integer;
-begin
-  case insr of
-    { MISCELLANEOUS GROUP }
-    ASP,ASS:
-	 begin if insr=ASS then
-	   begin k:=argw(k); if k<>wsize then trap(EILLINS); k:=popsw end;
-	   k:=argf(k);
-	   if k<0
-	     then for j:= 1 to -k div wsize do push(undef)
-	     else newsp(sp+k);
-	 end;
-    BLM,BLS:
-	 begin if insr=BLS then
-	   begin k:=argw(k); if k<>wsize then trap(EILLINS); k:=pop end;
-	   k:=argz(k);
-	   b:=popa; a:=popa;
-	   for j := 1 to k div wsize do
-	     store(b-wsize+wsize*j,memw(a-wsize+wsize*j))
-	 end;
-    CSA: begin k:=argw(k); if k<>wsize then trap(EILLINS);
-	   a:=popa;
-	   st:= popsw - signwd(memw(a+asize));
-	   if (st>=0) and (st<=memw(a+wsize+asize)) then
-	      b:=mema(a+2*wsize+asize+asize*st) else b:=mema(a);
-	   if b=0 then trap(ECASE) else newpc(b)
-	 end;
-    CSB: begin k:=argw(k); if k<>wsize then trap(EILLINS); a:=popa;
-	   t:=pop; i:=1; found:=false;
-	   while (i<=memw(a+asize)) and not found do
-	     if t=memw(a+(asize+wsize)*i) then found:=true else i:=i+1;
-	   if found then b:=memw(a+(asize+wsize)*i+wsize) else b:=memw(a);
-	   if b=0 then trap(ECASE) else newpc(b);
-	 end;
-    DCH: begin pusha(mema(popa+dynd)) end;
-    DUP,DUS:
-	 begin if insr=DUS then
-	      begin k:=argw(k); if k<>wsize then trap(EILLINS); k:=pop end;
-	   k:=args(k);
-	   for i:=1 to k div wsize do push(memw(sp+k-wsize));
-	 end;
-    EXG: begin
-	   k:=argw(k);
-	   for i:=1 to k div wsize do push(memw(sp+k-wsize));
-	   for i:=0 to k div wsize - 1 do
-	     store(sp+k+i*wsize,memw(sp+k+k+i*wsize));
-	   for i:=1 to k div wsize do
-	   begin t:=pop ; store(sp+k+k-wsize,t) end;
-	 end;
-    FIL: filna(argg(k));
-    GTO: begin k:=argg(k);
-	   newlb(mema(k+2*asize)); newsp(mema(k+asize)); newpc(mema(k))
-	 end;
-    LIM: push(ignmask);
-    LIN: lino(argn(k));
-    LNI: lino(memw(0)+1);
-    LOR: begin i:=argr(k);
-	   case i of 0:pusha(lb); 1:pusha(sp); 2:pusha(hp) end;
-	 end;
-    LPB: pusha(popa+statd);
-    MON: domon(pop);
-    NOP: writeln('NOP at line ',memw(0):5) ;
-    RCK: begin a:=popa;
-	   case szindex(argw(k)) of
-	   1: if (signwd(memw(sp))<signwd(memw(a))) or
-		(signwd(memw(sp))>signwd(memw(a+wsize))) then trap(ERANGE);
-	   2: if (memd(sp)<memd(a)) or
-		(memd(sp)>memd(a+2*wsize)) then trap(ERANGE);
-	   end
-	 end;
-    RTT: dortt;
-    SIG: begin a:=popa; pusha(uerrorproc); uerrorproc:=a end;
-    SIM: ignmask:=pop;
-    STR: begin i:=argr(k);
-	   case i of 0: newlb(popa); 1: newsp(popa); 2: newhp(popa) end;
-	 end;
-    TRP: trap(pop)
-  end
-end;
-.bp
-{---------------------------------------------------------------------------}
-{                               Main Loop                                   }
-{---------------------------------------------------------------------------}
-
-begin initialize;
-8888:
-  repeat
-    opcode := nextpc;       { fetch the first byte of the instruction }
-    if opcode=escape1 then iclass:=second
-    else if opcode=escape2 then iclass:=tert
-    else iclass:=prim;
-    if iclass<>prim then opcode := nextpc;
-    with dispat[iclass][opcode] do
-      begin insr:=instr;
-	if not (zbit in iflag) then
-	  if ibit in iflag then k:=pop else
-	    begin
-	      if mini in iflag then k:=implicit else
-		begin
-		  if short in iflag then k:=implicit+nextpc else
-		    begin k:=nextpc;
-		      if (sbit in iflag) and (k>=128) then k:=k-256;
-		      for i:=2 to ilength do k:=256*k + nextpc
-		    end
-		end;
-	      if wbit in iflag then k:=k*wsize;
-	    end
-      end;
-case insr of
-
-  NON: trap(EILLINS);
-
-  { LOAD GROUP }
-  LDC,LOC,LOL,LOE,LIL,LOF,LAL,LAE,LXL,LXA,LOI,LOS,LDL,LDE,LDF,LPI:
-      loadops;
-
-  { STORE GROUP }
-  STL,STE,SIL,STF,STI,STS,SDL,SDE,SDF:
-      storeops;
-
-  { SIGNED INTEGER ARITHMETIC }
-  ADI,SBI,MLI,DVI,RMI,NGI,SLI,SRI:
-      intarith;
-
-  { UNSIGNED INTEGER ARITHMETIC }
-  ADU,SBU,MLU,DVU,RMU,SLU,SRU:
-      unsarith;
-
-  { FLOATING POINT ARITHMETIC }
-  ADF,SBF,MLF,DVF,NGF,FIF,FEF:
-      fltarith;
-
-  { POINTER ARITHMETIC }
-  ADP,ADS,SBS:
-      ptrarith;
-
-  { INCREMENT/DECREMENT/ZERO }
-  INC,INL,INE,DEC,DEL,DEE,ZRL,ZRE,ZER,ZRF:
-      incops;
-
-  { CONVERT GROUP }
-  CII,CIU,CIF,CUI,CUU,CUF,CFI,CFU,CFF:
-      convops;
-
-  { LOGICAL GROUP }
- XAND,IOR,XOR,COM,ROL,ROR:
-      logops;
-
-  { SET GROUP }
-  INN,XSET:
-      setops;
-
-  { ARRAY GROUP }
-  LAR,SAR,AAR:
-      arrops;
-
-  { COMPARE GROUP }
-  CMI,CMU,CMP,CMF,CMS,  TLT,TLE,TEQ,TNE,TGE,TGT:
-      cmpops;
-
-  { BRANCH GROUP }
-  BRA,  BLT,BLE,BEQ,BNE,BGE,BGT,  ZLT,ZLE,ZEQ,ZNE,ZGE,ZGT:
-      branchops;
-
-  { PROCEDURE CALL GROUP }
-  CAL,CAI,RET,LFR:
-      callops;
-
-  { MISCELLANEOUS GROUP }
-  ASP,ASS,BLM,BLS,CSA,CSB,DCH,DUP,DUS,EXG,FIL,GTO,LIM,
-  LIN,LNI,LOR,LPB,MON,NOP,RCK,RTT,SIG,SIM,STR,TRP:
-      miscops;
-
-    end;        { end of case statement }
-    if not ( (insr=RET) or (insr=ASP) or (insr=BRA) or (insr=GTO) ) then
-	retsize:=0 ;
-  until halted;
-9999:
-  writeln('halt with exit status: ',exitstatus:1);
-  doident;
-end.

+ 0 - 9
doc/em/even.c

@@ -1,9 +0,0 @@
-main() {
-	register int l,j ;
-
-	for ( j=0 ; (l=getchar()) != -1 ; j++ ) {
-		if ( j%16 == 15 ) printf("%3d\n",l&0377 ) ;
-		else              printf("%3d ",l&0377 ) ;
-	}
-	printf("\n") ;
-}

+ 0 - 178
doc/em/exam.e

@@ -1,178 +0,0 @@
-  mes 2,2,2              ; wordsize 2, pointersize 2
- .1
-  rom 't.p\000'          ; the name of the source file
-  hol 552,-32768,0       ; externals and buf occupy 552 bytes
-  exp $sum               ; sum can be called from other modules
-  pro $sum,2             ; procedure sum; 2 bytes local storage
-  lin 8                  ; code from source line 8
-  ldl 0                  ; load two locals ( a and b )
-  adi 2                  ; add them
-  ret 2                  ; return the result
-  end 2                  ; end of procedure ( still two bytes local storage )
- .2
-  rom 1,99,2             ; descriptor of array a[]
-  exp $test              ; the compiler exports all level 0 procedures
-  pro $test,226          ; procedure test, 226 bytes local storage
- .3
-  rom 4.8F8              ; assemble Floating point 4.8 (8 bytes) in
- .4                              ; global storage
-  rom 0.5F8              ; same for 0.5
-  mes 3,-226,2,2         ; compiler temporary not referenced indirect
-  mes 3,-24,2,0          ; the same is true for i, j, b and c in test
-  mes 3,-22,2,0
-  mes 3,-4,2,0
-  mes 3,-2,2,0
-  mes 3,-20,8,0          ; and for x and y
-  mes 3,-12,8,0
-  lin 20                 ; maintain source line number
-  loc 1
-  stl -4                 ; j := 1
-  lni                    ; was lin 21 prior to optimization
-  lol -4
-  loc 3
-  mli 2
-  loc 6
-  adi 2
-  stl -2                 ; i := 3 * j + 6
-  lni                    ; was lin 22 prior to optimization
-  lae .3
-  loi 8
-  lal -12
-  sti 8                  ; x := 4.8
-  lni                    ; was lin 23 prior to optimization
-  lal -12
-  loi 8
-  lae .4
-  loi 8
-  dvf 8
-  lal -20
-  sti 8                  ; y := x / 0.5
-  lni                    ; was lin 24 prior to optimization
-  loc 1
-  stl -22                ; b := true
-  lni                    ; was lin 25 prior to optimization
-  loc 122
-  stl -24                ; c := 'z'
-  lni                    ; was lin 26 prior to optimization
-  loc 1
-  stl -2                 ; for i:= 1
- 2
-  lol -2
-  dup 2
-  mli 2                  ; i*i
-  lal -224
-  lol -2
-  lae .2
-  sar 2                  ; a[i] :=
-  lol -2
-  loc 100
-  beq *3                 ; to 100 do
-  inl -2                 ; increment i and loop
-  bra *2
- 3
-  lin 27
-  lol -4
-  loc 27
-  adi 2                  ; j + 27
-  sil 0                  ; r.r1 :=
-  lni                    ; was lin 28 prior to optimization
-  lol -22                ; b
-  lol 0
-  stf 10                 ; r.r3 :=
-  lni                    ; was lin 29 prior to optimization
-  lal -20
-  loi 16
-  adf 8                  ; x + y
-  lol 0
-  adp 2
-  sti 8                  ; r.r2 :=
-  lni                    ; was lin 23 prior to optimization
-  lal -224
-  lol -4
-  lae .2
-  lar 2                  ; a[j]
-  lil 0                  ; r.r1
-  cal $sum               ; call now
-  asp 4                  ; remove parameters from stack
-  lfr 2                  ; get function result
-  stl -2                 ; i :=
- 4
-  lin 31
-  lol -2
-  zle *5                 ; while i > 0 do
-  lol -4
-  lil 0
-  adi 2
-  stl -4                 ; j := j + r.r1
-  del -2                 ; i := i - 1
-  bra *4                 ; loop
- 5
-  lin 32
-  lol 0
-  stl -226               ; make copy of address of r
-  lol -22
-  lol -226
-  stf 10                 ; r3 := b
-  lal -20
-  loi 16
-  adf 8
-  lol -226
-  adp 2
-  sti 8                  ; r2 := x + y
-  loc 0
-  sil -226               ; r1 := 0
-  lin 34                 ; note the abscence of the unnecesary jump
-  lae 22                 ; address of output structure
-  lol -4
-  cal $_wri              ; write integer with default width
-  asp 4                  ; pop parameters
-  lae 22
-  lol -2
-  loc 6
-  cal $_wsi              ; write integer width 6
-  asp 6
-  lae 22
-  lal -12
-  loi 8
-  loc 9
-  loc 3
-  cal $_wrf              ; write fixed format real, width 9, precision 3
-  asp 14
-  lae 22
-  lol -22
-  cal $_wrb              ; write boolean, default width
-  asp 4
-  lae 22
-  cal $_wln              ; writeln
-  asp 2
-  ret 0                  ; return, no result
-  end 226
-  exp $_main
-  pro $_main,0           ; main program
- .6
-  con 2,-1,22            ; description of external files
- .5
-  rom 15.96F8
-  fil .1                 ; maintain source file name
-  lae .6                 ; description of external files
-  lae 0                  ; base of hol area to relocate buffer addresses
-  cal $_ini              ; initialize files, etc...
-  asp 4
-  lin 37
-  lae .5
-  loi 8
-  lae 2
-  sti 8                  ; x := 15.9
-  lni                    ; was lin 38 prior to optimization
-  loc 99
-  ste 0                  ; mi := 99
-  lni                    ; was lin 39 prior to optimization
-  lae 10                 ; address of r
-  cal $test
-  asp 2
-  loc 0                  ; normal exit
-  cal $_hlt              ; cleanup and finish
-  asp 2
-  end 0
-  mes 4,40               ; length of source file is 40 lines
-  mes 5                  ; reals were used

+ 0 - 40
doc/em/exam.p

@@ -1,40 +0,0 @@
-  program example(output);
-  {This program just demonstrates typical EM code.}
-  type rec = record r1: integer; r2:real; r3: boolean end;
-  var mi: integer;  mx:real;  r:rec;
-
-  function sum(a,b:integer):integer;
-  begin
-    sum := a + b
-  end;
-
-  procedure test(var r: rec);
-  label 1;
-  var   i,j: integer;
-	x,y: real;
-	b: boolean;
-	c: char;
-	a: array[1..100] of integer;
-
-  begin
-	j := 1;
-	i := 3 * j + 6;
-	x := 4.8;
-	y := x/0.5;
-	b := true;
-	c := 'z';
-	for i:= 1 to 100 do a[i] := i * i;
-	r.r1 := j+27;
-	r.r3 := b;
-	r.r2 := x+y;
-	i := sum(r.r1, a[j]);
-	while i > 0 do begin j := j + r.r1; i := i - 1 end;
-	with r do begin r3 := b;  r2 := x+y;  r1 := 0 end;
-	goto 1;
-  1:    writeln(j, i:6, x:9:3, b)
-  end; {test}
-  begin {main program}
-    mx := 15.96;
-    mi := 99;
-    test(r)
-  end.

+ 0 - 32
doc/em/int/Makefile

@@ -1,32 +0,0 @@
-CFLAGS=-O
-HOME=../../..
-
-install \
-all:            em emdmp tables
-
-tables:         mktables $(HOME)/util/ass/ip_spec.t
-		mktables $(HOME)/util/ass/ip_spec.t tables
-
-mktables:       mktables.c $(HOME)/h/em_spec.h $(HOME)/h/em_flag.h \
-		$(HOME)/util/data/em_data.a $(HOME)/util/ass/ip_spec.h
-		cc -O -o mktables mktables.c $(HOME)/util/data/em_data.a
-
-em.out:         em.p
-		apc -mint -O em.p >emerrs ; mv e.out em.out
-
-em:             em.p
-		apc -O -i em.p >emerrs ; mv a.out em
-
-nem.p:          em.p
-		sed -e '/maxadr  = t16/s//maxadr  =t15/' -e '/maxdata = 8191; /s//maxdata = 14335;/' -e '/ adr=.*long/s// adr=    0..maxadr/' <em.p >nem.p
-
-nem:            nem.p
-		apc -O -i nem.p >emerrs ; mv a.out nem
-
-emdmp:          emdmp.c
-		cc -o emdmp -O emdmp.c
-
-cmp:
-
-pr:		
-		@pr em.p mktables.c emdmp.c

+ 0 - 5
doc/em/int/READ_ME

@@ -1,5 +0,0 @@
-This interpreter is meant for inclusion in the EM manual.
-Although slow, it showed decent behaviour on several tests.
-The only monitor calls implemented are exit, read(untested),
-write and ioctl - just reurns the correct code for telling it's
-a terminal -

+ 0 - 1766
doc/em/int/em.p

@@ -1,1766 +0,0 @@
-#
-{ This  is an interpreter for EM.  It serves as a specification for the
-  EM machine.  This interpreter must run on a machine which supports
-  arithmetic with words and memory offsets.
-
-  Certain aspects are over specified.  In particular:
-
-    1. The representation of  an  address on the stack  need not be the
-       numerical value of the memory location.
-
-    2. The state of  the stack is not defined  after a trap has aborted
-       an instruction in the middle.  For example, it is officially un-
-       defined  whether the second  operand of an  ADD  instruction has
-       been popped  or  not  if the  first one is undefined ( -32768 or
-       unsigned 32768).
-
-    3. The memory layout is implementation dependent. Only the most
-       basic checks are performed whenever memory is accessed.
-
-    4. The representation of an integer or set on the stack is not fixed
-       in bit order.
-
-    5. The format and existence of the procedure descriptors depends on
-       the implementation.
-
-    6. The result of the compare operators  CMI etc.  are -1, 0  and  1
-       here, but other negative  and  positive values will do  and they
-       need not be the same each time.
-
-    7. The shift count for SHL, SHR, ROL and ROR must be in the range 0
-       to object size in bits - 1.  The effect of a  count  not in this
-       range is undefined.
-
-    8. This interpreter does not work for double word integers, although
-       any decent EM implementation will include double word arithmetic.
-									}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-{$i256}
-{$d+}
-#ifndef DOC
-program em(tables,prog,core,input,output);
-#else
-program em(tables,prog,input,output);
-#endif
-
-
-label 8888,9999;
-
-const
-  t15   = 32768;        { 2**15    }
-  t15m1 = 32767;        { 2**15 -1 }
-  t16   = 65536;        { 2**16    }
-  t16m1 = 65535;        { 2**16 -1 }
-  t31m1 = 2147483647;   { 2**31 -1 }
-
-  { constants indicating the size of words and addresses }
-  wsize = 2;            { number of bytes in a word }
-  asize = 2;            { number of bytes in an address }
-  fsize = 4;            { number of bytes in a floating point number }
-  maxret =4;            { number of words in the return value area }
-
-  signbit = t15;        { the power of two indicating the sign bit }
-  negoff  = t16;        { the next power of two }
-  maxsint = t15m1;      { the maximum signed integer }
-  maxuint = t16m1;      { the maximum unsigned integer }
-  maxdbl  = t31m1;      { the maximum double signed integer }
-  maxadr  = t16m1;      { the maximum address }
-  maxoffs = t15m1;      { the maximum offset from an address }
-  maxbitnr= 15;         { the number of the highest bit }
-
-  lineadr = 0;          { address of the line number }
-  fileadr = 4;          { address of the file name }
-  maxcode = 8191;       { highest byte in code address space }
-  maxdata = 8191;       { highest byte in data address space }
-
-  { format of status save area }
-  statd   = 4;          { how far is static link from lb }
-  dynd    = 2;          { how far is dynamic link from lb }
-  reta    = 0;          { how far is the return address from lb }
-  savsize = 4;          { size of save area in bytes }
-
-  { procedure descriptor format }
-  pdlocs  = 0;          { offset for size of local variables in bytes }
-  pdbase  = asize;      { offset for the procedure base }
-  pdsize  = 4;          { size of procedure descriptor in bytes = 2*asize }
-
-  { header words }
-  NTEXT   = 1;
-  NDATA   = 2;
-  NPROC   = 3;
-  ENTRY   = 4;
-  NLINE   = 5;
-  SZDATA  = 6;
-
-  escape1 = 254;        { escape to secondary opcodes }
-  escape2 = 255;        { escape to tertiary opcodes }
-  undef   = signbit;    { the range of integers is -32767 to +32767 }
-
-  { error codes }
-  EARRAY   =  0; ERANGE   =  1; ESET     =  2; EIOVFL   =  3;
-  EFOVFL   =  4; EFUNFL   =  5; EIDIVZ   =  6; EFDIVZ   =  7;
-  EIUND    =  8; EFUND    =  9; ECONV    = 10; ESTACK   = 16;
-  EHEAP    = 17; EILLINS  = 18; EODDZ    = 19; ECASE    = 20;
-  EMEMFLT  = 21; EBADPTR  = 22; EBADPC   = 23; EBADLAE  = 24;
-  EBADMON  = 25; EBADLIN  = 26; EBADGTO  = 27;
-{
-.ne 20
-.bp
-----------------------------------------------------------------------------}
-{                             Declarations                                  }
-{---------------------------------------------------------------------------}
-
-type
-  bitval= 0..1;             { one bit }
-  bitnr=  0..maxbitnr;      { bits in machine words are numbered 0 to 15 }
-  byte=   0..255;           { memory is an array of bytes }
-  adr=    {0..maxadr} long; { the range of addresses }
-  word=   {0..maxuint} long;{ the range of unsigned integers }
-  offs=  -maxoffs..maxoffs; { the range of signed offsets from addresses }
-  size=   0..maxoffs;       { the range of sizes is the positive offsets }
-  sword= {-signbit..maxsint} long; { the range of signed integers }
-  full=  {-maxuint..maxuint} long; { intermediate results need this range }
-  double={-maxdbl..maxdbl} long;   { double precision range }
-  bftype= (andf,iorf,xorf); { tells which boolean operator needed }
-  insclass=(prim,second,tert); { tells which opcode table is in use }
-  instype=(implic,explic);  { does opcode have implicit or explicit operand }
-  iflags= (mini,short,sbit,wbit,zbit,ibit);
-  ifset=  set of iflags;
-
-  mnem = ( NON,
-	   AAR, ADF, ADI, ADP, ADS, ADU,XAND, ASP, ASS, BEQ,
-	   BGE, BGT, BLE, BLM, BLS, BLT, BNE, BRA, CAI, CAL,
-	   CFF, CFI, CFU, CIF, CII, CIU, CMF, CMI, CMP, CMS,
-	   CMU, COM, CSA, CSB, CUF, CUI, CUU, DCH, DEC, DEE,
-	   DEL, DUP, DUS, DVF, DVI, DVU, EXG, FEF, FIF, FIL,
-	   GTO, INC, INE, INL, INN, IOR, LAE, LAL, LAR, LDC,
-	   LDE, LDF, LDL, LFR, LIL, LIM, LIN, LNI, LOC, LOE,
-	   LOF, LOI, LOL, LOR, LOS, LPB, LPI, LXA, LXL, MLF,
-	   MLI, MLU, MON, NGF, NGI, NOP, RCK, RET, RMI, RMU,
-	   ROL, ROR, RTT, SAR, SBF, SBI, SBS, SBU, SDE, SDF,
-	   SDL,XSET, SIG, SIL, SIM, SLI, SLU, SRI, SRU, STE,
-	   STF, STI, STL, STR, STS, TEQ, TGE, TGT, TLE, TLT,
-	   TNE, TRP, XOR, ZEQ, ZER, ZGE, ZGT, ZLE, ZLT, ZNE,
-	   ZRE, ZRF, ZRL);
-
-  dispatch = record
-		iflag: ifset;
-		instr: mnem;
-		case instype of
-		implic: (implicit:sword);
-		explic: (ilength:byte);
-	     end;
-
-
-var
-  code: packed array[0..maxcode] of byte;      { code space }
-  data: packed array[0..maxdata] of byte;      { data space }
-  retarea: array[1..maxret ] of word;          { return area }
-  pc,lb,sp,hp,pd: adr;  { internal machine registers }
-  i: integer;           { integer scratch variable }
-  s,t :word;            { scratch variables }
-  sz:size;              { scratch variables }
-  ss,st: sword;         { scratch variables }
-  k :double;            { scratch variables }
-  j:size;               { scratch variable used as index }
-  a,b:adr;              { scratch variable used for addresses }
-  dt,ds:double;         { scratch variables for double precision }
-  rt,rs,x,y:real;       { scratch variables for real }
-  found:boolean;        { scratch }
-  opcode: byte;         { holds the opcode during execution }
-  iclass: insclass;     { true for escaped opcodes }
-  dispat: array[insclass,byte] of dispatch;
-  retsize:size;         { holds size of last LFR }
-  insr: mnem;           { holds the instructionnumber }
-  halted: boolean;      { normally false }
-  exitstatus:word;      { parameter of MON 1 }
-  ignmask:word;         { ignore mask for traps }
-  uerrorproc:adr;       { number of user defined error procedure }
-  intrap:boolean;       { Set when executing trap(), to catch recursive calls}
-  trapval:byte;         { Set to number of last trap }
-  header: array[1..8] of adr;
-
-  tables: text;         { description of EM instructions }
-  prog: file of byte;   { program and initialized data }
-#ifndef DOC
-  core: file of byte;   { post mortem dump }
-#endif
-{
-.ne 20
-.sp 5
-{---------------------------------------------------------------------------}
-{                        Various check routines                             }
-{---------------------------------------------------------------------------}
-
-{ Only the most basic checks are performed. These routines are inherently
-  implementation dependent. }
-
-procedure trap(n:byte); forward;
-#ifndef DOC
-procedure writecore(n:byte); forward;
-#endif
-
-procedure memadr(a:adr);
-begin if (a>maxdata) or ((a<sp) and (a>=hp)) then trap(EMEMFLT) end;
-
-procedure wordadr(a:adr);
-begin memadr(a); if (a mod wsize<>0) then trap(EBADPTR) end;
-
-procedure chkadr(a:adr; s:size);
-begin memadr(a); memadr(a+s-1); { assumption: size is ok }
-      if s<wsize
-      then begin if a mod s<>0  then trap(EBADPTR) end
-      else       if a mod wsize<>0 then trap(EBADPTR)
-end;
-
-procedure newpc(a:double);
-begin if (a<0) or (a>maxcode) then trap(EBADPC); pc:=a end;
-
-procedure newsp(a:adr);
-begin if (a>lb) or (a<hp) or (a mod wsize<>0) then trap(ESTACK); sp:=a end;
-
-procedure newlb(a:adr);
-begin if (a<sp) or (a mod wsize<>0) then trap(ESTACK); lb:=a end;
-
-procedure newhp(a:adr);
-begin if (a>sp) or (a>maxdata+1) or (a mod wsize<>0)
-      then trap(EHEAP); hp:=a
-end;
-
-function argc(a:double):sword;
-begin if (a<-signbit) or (a>maxsint) then trap(EILLINS); argc:=a end;
-
-function argd(a:double):double;
-begin if (a<-maxdbl) or (a>maxdbl) then trap(EILLINS); argd:=a end;
-
-function argl(a:double):offs;
-begin if (a<-maxoffs) or (a>maxoffs) then trap(EILLINS); argl:=a end;
-
-function argg(k:double):adr;
-begin if (k<0) or (k>maxadr) then trap(EILLINS); argg:=k end;
-
-function argf(a:double):offs;
-begin if (a<-maxoffs) or (a>maxoffs) then trap(EILLINS); argf:=a end;
-
-function argn(a:double):word;
-begin if (a<0) or (a>maxuint) then trap(EILLINS); argn:=a end;
-
-function args(a:double):size;
-begin if (a<=0) or (a>maxoffs)
-	then trap(EODDZ)
-	else if (a mod wsize)<>0 then trap(EODDZ);
-      args:=a ;
-end;
-
-function argz(a:double):size;
-begin if (a<0) or (a>maxoffs)
-	then trap(EODDZ)
-	else if (a mod wsize)<>0 then trap(EODDZ);
-      argz:=a ;
-end;
-
-function argo(a:double):size;
-begin if (a<=0) or (a>maxoffs)
-	then trap(EODDZ)
-	else if (a mod wsize<>0) and (wsize mod a<>0) then trap(EODDZ);
-      argo:=a ;
-end;
-
-function argw(a:double):size;
-begin if (a<=0) or (a>maxoffs) or (a>maxuint)
-	then trap(EODDZ)
-	else if (a mod wsize)<>0 then trap(EODDZ);
-      argw:=a ;
-end;
-
-function argp(a:double):size;
-begin if (a<0) or (a>=header[NPROC]) then trap(EILLINS); argp:=a end;
-
-function argr(a:double):word;
-begin if (a<0) or (a>2) then trap(EILLINS); argr:=a end;
-
-procedure argwf(s:double);
-begin if argw(s)<>fsize then trap(EILLINS) end;
-
-function szindex(s:double):integer;
-begin s:=argw(s); if (s mod wsize <> 0) or (s>2*wsize) then trap(EILLINS);
-      szindex:=s div wsize
-end;
-
-function locadr(l:double):adr;
-begin l:=argl(l); if l<0 then locadr:=lb+l else locadr:=lb+l+savsize end;
-
-function signwd(w:word):sword;
-begin if w = undef then trap(EIUND);
-      if w >= signbit then signwd:=w-negoff else signwd:=w
-end;
-
-function dosign(w:word):sword;
-begin if w >= signbit then dosign:=w-negoff else dosign:=w end;
-
-function unsign(w:sword):word;
-begin if w<0 then unsign:=w+negoff else unsign:=w end;
-
-function chopw(dw:double):word;
-begin chopw:=dw mod negoff end;
-
-function fitsw(w:full;trapno:byte):word;
-{ checks whether value fits in signed word, returns unsigned representation}
-begin
-  if (w>maxsint) or (w<-signbit) then
-    begin trap(trapno);
-      if w<0 then fitsw:=negoff- (-w)mod negoff
-	     else fitsw:=w mod negoff;
-    end
-  else fitsw:=unsign(w)
-end;
-
-function fitd(w:full):double;
-begin
-  if abs(w) > maxdbl then trap(ECONV);
-  fitd:=w
-end;
-
-{
-.ne 20
-.sp 5
-{---------------------------------------------------------------------------}
-{                        Memory access routines                             }
-{---------------------------------------------------------------------------}
-
-{ memw returns a machine word as an unsigned integer
-  memb returns a single byte as a positive integer: 0 <= memb <= 255
-  mems(a,s) fetches an object smaller than a word and returns a word
-  store(a,v) stores the word v at machine address a
-  storea(a,v) stores the address v at machine address a
-  storeb(a,b) stores the byte b at machine address a
-  stores(a,s,v) stores the s least significant bytes of a word at address a
-  memi returns an offset from the instruction space
-       Note that the procedure descriptors are part of instruction space.
-  nextpc returns the next byte addressed by pc, incrementing pc
-
-  lino changes the line number word.
-  filna changes the pointer to the file name.
-
-  All routines check to make sure the address is within range and valid for
-  the size of the object. If an addressing error is found, a trap occurs.
-}
-
-
-function memw(a:adr):word;
-var b:word; i:integer;
-begin wordadr(a); b:=0;
-      for i:=wsize-1 downto 0 do b:=256*b + data[a+i] ;
-      memw:=b
-end;
-
-function memd(a:adr):double; { Always signed }
-var b:double; i:integer;
-begin wordadr(a); b:=data[a+2*wsize-1];
-      if b>=128 then b:=b-256;
-      for i:=2*wsize-2 downto 0 do b:=256*b + data[a+i] ;
-      memd:=b
-end;
-
-function mema(a:adr):adr;
-var b:adr; i:integer;
-begin wordadr(a); b:=0;
-      for i:=asize-1 downto 0 do b:=256*b + data[a+i] ;
-      mema:=b
-end;
-
-function mems(a:adr;s:size):word;
-var i:integer; b:word;
-begin chkadr(a,s); b:=0; for i:=1 to s do b:=b*256+data[a+s-i]; mems:=b end;
-
-function memb(a:adr):byte;
-begin memadr(a); memb:=data[a] end;
-
-procedure store(a:adr; x:word);
-var i:integer;
-begin wordadr(a);
-  for i:=0 to wsize-1 do
-     begin data[a+i]:=x mod 256; x:=x div 256 end
-end;
-
-procedure storea(a:adr; x:adr);
-var i:integer;
-begin wordadr(a);
-  for i:=0 to asize-1 do
-     begin data[a+i]:=x mod 256; x:=x div 256 end
-end;
-
-procedure stores(a:adr;s:size;v:word);
-var i:integer;
-begin chkadr(a,s);
-  for i:=0 to s-1 do begin data[a+i]:=v mod 256; v:=v div 256 end;
-end;
-
-procedure storeb(a:adr; b:byte);
-begin memadr(a); data[a]:=b end;
-
-function memi(a:adr):adr;
-var b:adr; i:integer;
-begin if (a mod wsize<>0) or (a+asize-1>maxcode) then trap(EBADPTR); b:=0;
-      for i:=asize-1 downto 0 do b:=256*b + code[a+i] ;
-      memi:=b
-end;
-
-function nextpc:byte;
-begin if pc>=pd then trap(EBADPC); nextpc:=code[pc]; newpc(pc+1) end;
-
-procedure lino(w:word);
-begin store(lineadr,w) end;
-
-procedure filna(a:adr);
-begin storea(fileadr,a) end;
-{
-.ne 20
-.sp 5
-{---------------------------------------------------------------------------}
-{                    Stack Manipulation Routines                            }
-{---------------------------------------------------------------------------}
-
-{ push puts a word on the stack
-  pushsw takes a signed one word integer and pushes it on the stack
-  pop removes a machine word from the stack and delivers it as a word
-  popsw removes a machine word from the stack and delivers a signed integer
-  pusha pushes an address on the stack
-  popa removes a machine word from the stack and delivers it as an address
-  pushd pushes a double precision number on the stack
-  popd removes two machine words and returns a double precision integer
-  pushr pushes a float (floating point) number on the stack
-  popr removes several machine words and returns a float number
-  pushx puts an object of arbitrary size on the stack
-  popx removes an object of arbitrary size
-									  }
-
-procedure push(x:word);
-begin newsp(sp-wsize); store(sp,x) end;
-
-procedure pushsw(x:sword);
-begin newsp(sp-wsize); store(sp,unsign(x)) end;
-
-function pop:word;
-begin pop:=memw(sp); newsp(sp+wsize) end;
-
-function popsw:sword;
-begin popsw:=signwd(pop) end;
-
-procedure pusha(x:adr);
-begin newsp(sp-asize); storea(sp,x) end;
-
-function popa:adr;
-begin popa:=mema(sp); newsp(sp+asize) end;
-
-procedure pushd(y:double);
-begin { push double integer onto the stack } newsp(sp-2*wsize) end;
-
-function popd:double;
-begin { pop double integer from the stack } newsp(sp+2*wsize); popd:=0 end;
-
-procedure pushr(z:real);
-begin { Push a float onto the stack } newsp(sp-fsize) end;
-
-function popr:real;
-begin { pop float from the stack } newsp(sp+fsize); popr:=0.0 end;
-
-procedure pushx(objsize:size; a:adr);
-var i:integer;
-begin
-  if objsize<wsize
-     then push(mems(a,objsize))
-     else for i:=1 to objsize div wsize do push(memw(a+objsize-wsize*i))
-end;
-
-procedure popx(objsize:size; a:adr);
-var i:integer;
-begin
-  if objsize<wsize
-     then stores(a,objsize,pop)
-     else for i:=1 to objsize div wsize do store(a-wsize+wsize*i,pop)
-end;
-{
-.ne 20
-.sp 5
-{---------------------------------------------------------------------------}
-{              Bit manipulation routines (extract, shift, rotate)           }
-{---------------------------------------------------------------------------}
-
-procedure sleft(var w:sword);  { 1 bit left shift   }
-begin w:= dosign(fitsw(2*w,EIOVFL)) end;
-
-procedure suleft(var w:word);  { 1 bit left shift   }
-begin w := chopw(2*w) end;
-
-procedure sdleft(var d:double);  { 1 bit left shift   }
-begin { shift two word signed integer } end;
-
-procedure sright(var w:sword);  { 1 bit right shift with sign extension }
-begin if w >= 0 then w := w div 2 else w := (w-1) div 2 end;
-
-procedure suright(var w:word);    { 1 bit right shift without sign extension }
-begin w := w div 2 end;
-
-procedure sdright(var d:double);  { 1 bit right shift   }
-begin { shift two word signed integer } end;
-
-procedure rleft(var w:word);  { 1 bit left rotate }
-begin if w >= t15
-	then w:=(w-t15)*2 + 1
-	else w:=w*2
-end;
-
-procedure rright(var w:word);  { 1 bit right rotate }
-begin if w mod 2 = 1
-	then w:=w div 2 + t15
-	else w:=w div 2
-end;
-
-function sextend(w:word;s:size):word;
-var i:size;
-begin
-  for i:=1 to (wsize-s)*8 do rleft(w);
-  for i:=1 to (wsize-s)*8 do sright(w);
-  sextend:=w;
-end;
-
-function bit(b:bitnr; w:word):bitval; { return bit b of the word w }
-var i:bitnr;
-begin for i:= 1 to b do rright(w); bit:= w mod 2 end;
-
-function bf(ty:bftype; w1,w2:word):word;  { return boolean fcn of 2 words }
-var i:bitnr; j:word;
-begin j:=0;
-      for i:= maxbitnr downto 0 do
-	begin j := 2*j;
-	      case ty of
-		andf: if bit(i,w1)+bit(i,w2) = 2 then j:=j+1;
-		iorf: if bit(i,w1)+bit(i,w2) > 0 then j:=j+1;
-		xorf: if bit(i,w1)+bit(i,w2) = 1 then j:=j+1
-	      end
-	end;
-      bf:=j
-end;
-
-{---------------------------------------------------------------------------}
-{                           Array indexing
-{---------------------------------------------------------------------------}
-
-function arraycalc(c:adr):adr; { subscript calculation }
-var j:full; objsize:size; a:adr;
-begin j:= popsw - signwd(memw(c));
-  if (j<0) or (j>memw(c+wsize)) then trap(EARRAY);
-  objsize := argo(memw(c+wsize+wsize));
-  a := j*objsize+popa; chkadr(a,objsize);
-  arraycalc:=a
-end;
-{
-.ne 20
-.sp 5
-{---------------------------------------------------------------------------}
-{                       Double and Real Arithmetic                          }
-{---------------------------------------------------------------------------}
-
-{ All routines for doubles and floats are dummy routines, since the format of
-  doubles and floats is not defined in EM.
-}
-
-function doadi(ds,dt:double):double;
-begin { add two doubles } doadi:=0 end;
-
-function dosbi(ds,dt:double):double;
-begin { subtract two doubles } dosbi:=0 end;
-
-function domli(ds,dt:double):double;
-begin { multiply two doubles } domli:=0 end;
-
-function dodvi(ds,dt:double):double;
-begin { divide two doubles } dodvi:=0 end;
-
-function dormi(ds,dt:double):double;
-begin { modulo of two doubles } dormi:=0 end;
-
-function dongi(ds:double):double;
-begin { negative of a double } dongi:=0 end;
-
-function doadf(x,y:real):real;
-begin { add two floats } doadf:=0.0 end;
-
-function dosbf(x,y:real):real;
-begin { subtract two floats } dosbf:=0.0 end;
-
-function domlf(x,y:real):real;
-begin { multiply two floats } domlf:=0.0 end;
-
-function dodvf(x,y:real):real;
-begin { divide two floats } dodvf:=0.0 end;
-
-function dongf(x:real):real;
-begin { negate a float } dongf:=0.0 end;
-
-procedure dofif(x,y:real;var intpart,fraction:real);
-begin { dismember x*y into integer and fractional parts }
-  intpart:=0.0;  { integer part of x*y, same sign as x*y }
-  fraction:=0.0;
-	{ fractional part of x*y, 0<=abs(fraction)<1 and same sign as x*y }
-end;
-
-procedure dofef(x:real;var mantissa:real;var exponent:sword);
-begin { dismember x into mantissa and exponent parts }
-  mantissa:=0.0;  { mantissa of x , >= 1/2 and <1 }
-  exponent:=0;    { base 2 exponent of x }
-end;
-
-{
-.ne 20
-.sp 5
-.bp
-{---------------------------------------------------------------------------}
-{                            Trap and Call                                  }
-{---------------------------------------------------------------------------}
-
-procedure call(p:adr); { Perform the call }
-begin
-  pusha(lb);pusha(pc);
-  newlb(sp);newsp(sp - memi(pd + pdsize*p + pdlocs));
-  newpc(memi(pd + pdsize*p+ pdbase))
-end;
-
-procedure dotrap(n:byte);
-var i:size;
-begin
-  if (uerrorproc=0) or intrap then
-    begin
-      if intrap then
-	writeln('Recursive trap, first trap number was ', trapval:1);
-      writeln('Error ', n:1);
-      writeln('With',ord(insr):4,' arg ',k:1);
-#ifndef DOC
-      writecore(n);
-#endif
-      goto 9999
-    end;
-  { Deposit all interpreter variables that need to be saved on
-    the stack. This includes all scratch variables that can
-    be in use at the moment and ( not possible in this interpreter )
-    the internal address of the interpreter where the error occurred.
-    This would make it possible to execute an RTT instruction totally
-    transparent to the user program.
-    It can, for example, occur within an ADD instruction that both
-    operands are undefined and that the result overflows.
-    Although this will generate 3 error traps it must be possible
-    to ignore them all.
-
-    }
-  intrap:=true; trapval:=n;
-  for i:=retsize div wsize downto 1 do push(retarea[i]);
-  push(retsize);              { saved return area }
-  pusha(mema(fileadr));       { saved current file name pointer }
-  push(memw(lineadr));        { saved line number }
-  push(n);                    { push error number }
-  a:=argp(uerrorproc);
-  uerrorproc:=0;              { reset signal }
-  call(a);                    { call the routine }
-  intrap:=false;              { Do not catch recursive traps anymore }
-  goto 8888;                  { reenter main loop }
-end;
-
-procedure trap;
-{ This routine is invoked for overflow, and other run time errors.
-  For non-fatal errors, trap returns to the calling routine
-}
-begin
-  if n>=16 then dotrap(n) else if bit(n,ignmask)=0 then dotrap(n);
-end;
-
-procedure dortt;
-{ The restoration of file address and line number is not essential.
-  The restoration of the return save area is.
-}
-var i:size;
-    n:word;
-begin
-  newsp(lb); lb:=maxdata+1 ; { to circumvent ESTACK for the popa + pop }
-  newpc(popa); newlb(popa); { So far a plain RET 0 }
-  n:=pop; if (n>=16) and (n<64) then
-  begin
-#ifndef DOC
-	writecore(n);
-#endif
-	goto 9999
-  end;
-  lino(pop); filna(popa); retsize:=pop;
-  for i:=1 to retsize div wsize do retarea[i]:=pop ;
-end;
-{
-.sp 5
-{---------------------------------------------------------------------------}
-{                              monitor calls                                }
-{---------------------------------------------------------------------------}
-
-
-procedure domon(entry:word);
-var     index:  1..63;
-	dummy:  double;
-	count,rwptr:    adr;
-	token:  byte;
-	i:      integer;
-begin
-  if (entry<=0) or (entry>63) then entry:=63 ;
-  index:=entry;
-  case index of
-   1: begin { exit } exitstatus:=pop; halted:=true end;
-   3: begin { read }  dummy:=pop; { All input is from stdin }
-	rwptr:=popa; count:=popa;
-	i:=0 ;
-	while (not eof(input)) and (i<count) do
-	begin
-	  if eoln(input) then begin storeb(rwptr,10) ; count:=i end
-			 else storeb(rwptr,ord(input^)) ;
-	  get(input); rwptr:=rwptr+1 ; i:=i+1 ;
-	end;
-	pusha(i); push(0)
-      end;
-   4: begin { write } dummy:=pop; { All output is to stdout }
-	rwptr:=popa; count:=popa;
-	for i:=1 to count do
-	  begin token:=memb(rwptr); rwptr:=rwptr+1 ;
-	    if token=10 then writeln else write(chr(token))
-	  end ;
-	pusha(count);
-	push(0)
-      end;
-  54: begin { ioctl, faked } dummy:=popa;dummy:=popa;dummy:=pop;push(0) end ;
-       2,          5,  6,  7,  8,  9, 10,
-  11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
-  21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
-  31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
-  41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
-  51, 52, 53,     55, 56, 57, 58, 59, 60,
-  61, 62:
-      begin push(22); push(22) end;
-  63: { exists only for the trap }
-      trap(EBADMON)
-  end
-end;
-{
-.bp
-{---------------------------------------------------------------------------}
-{                       Initialization and debugging                        }
-{---------------------------------------------------------------------------}
-
-procedure doident; { print line number and file name }
-var a:adr; i,c:integer; found:boolean;
-begin
-  write('at line ',memw(lineadr):1,' ');
-  a:=mema(fileadr); if a<>0 then
-  begin i:=20; found:=false;
-    while (i<>0) and not found do
-    begin c:=memb(a); a:=a+1; found:=true; i:=i-1;
-      if (c>=48) and (c<=57) then
-	begin found:=false; write(chr(ord('0')+c-48)) end;
-      if (c>=65) and (c<=90) then
-	begin found:=false; write(chr(ord('A')+c-65)) end;
-      if (c>=97) and (c<=122) then
-	begin found:=false; write(chr(ord('a')+c-97)) end;
-    end;
-  end;
-  writeln;
-end;
-
-#ifndef DOC
-{---------------------------------------------------------------------------}
-{                              Post Mortem Dump                             }
-{                                                                           }
-{This a not a part of the machine definition, but an ad hoc debugging method}
-{---------------------------------------------------------------------------}
-
-procedure writecore;
-var ncoreb,i:integer;
-
-procedure wrbyte(b:byte);
-begin write(core,b); ncoreb:=ncoreb+1 end;
-
-procedure wradr(a:adr);
-var i:integer;
-begin for i:=1 to asize do begin wrbyte(a mod 256); a:=a div 256 end end;
-
-begin
-  rewrite(core); ncoreb:=0;
-  wrbyte(173); wrbyte(16);      { Magic }
-  wrbyte(3);wrbyte(0);          { Version }
-  wrbyte(wsize);wrbyte(0);      { Wordsize }
-  wrbyte(asize);wrbyte(0);      { Address size }
-  wradr(0);                     { Text size in dump }
-  wradr(maxdata+1);             { Data size in dump }
-  wradr(ignmask);
-  wradr(uerrorproc);
-  wradr(n);                     { Cause }
-  wradr(pc); wradr(sp); wradr(lb); wradr(hp); wradr(pd); wradr(0){pb} ;
-  while ncoreb<>512 do wradr(0); { Fill }
-  for i:=0 to maxdata do wrbyte(data[i])
-end;
-
-#endif
-
-procedure initialize;  { start the ball rolling }
-{ This is not part of the machine definition }
-var cset:set of char;
-    f:ifset;
-    iclass:insclass;
-    insno:byte;
-    nops:integer;
-    opcode:byte;
-    i,j,n:integer;
-    wtemp:sword;
-    count:integer;
-    repc:adr;
-    nexta,firsta:adr;
-    elem:byte;
-    amount,ofst:size;
-    c:char;
-
-    function readb(n:integer):double;
-    var b:byte;
-    begin read(prog,b); if n>1 then readb:=readb(n-1)*256+b else readb:=b end;
-
-    function readbyte:byte;
-    begin readbyte:=readb(1) end;
-
-    function readword:word;
-    begin readword:=readb(wsize) end;
-
-    function readadr:adr;
-    begin readadr:=readb(asize) end;
-
-    function ifind(ordinal:byte):mnem;
-    var loopvar:mnem;
-	found:boolean;
-    begin ifind:=NON;
-      loopvar:=insr; found:=false;
-      repeat
-	if ordinal=ord(loopvar) then
-	  begin found:=true; ifind:=loopvar end;
-	if loopvar<>ZRL then loopvar:=succ(loopvar) else loopvar:=NON;
-      until found or (loopvar=insr) ;
-   end;
-
-    procedure readhdr;
-    type hdrw=0..32767 ; { 16 bit header words }
-    var  hdr: hdrw;
-	 i: integer;
-    begin
-      for i:=0 to 7 do
-      begin hdr:=readb(2);
-	case i of
-	0: if hdr<>3757 then { 07255 }
-	   begin writeln('Not an em load file'); halt end;
-	2: if hdr<>0 then
-	   begin writeln('Unsolved references'); halt end;
-	3: if hdr<>3 then
-	   begin writeln('Incorrect load file version'); halt end;
-	4: if hdr<>wsize then
-	   begin writeln('Incorrect word size'); halt end;
-	5: if hdr<>asize then
-	   begin writeln('Incorrect pointer size'); halt end;
-	1,6,7:;
-	end
-      end
-    end;
-
-    procedure noinit;
-    begin writeln('Illegal initialization'); halt end;
-
-    procedure readint(a:adr;s:size);
-    var i:size;
-    begin { construct integer out of byte sequence }
-      for i:=1 to s do { construct the value and initialize at a }
-	begin storeb(a,readbyte); a:=a+1 end
-    end;
-
-    procedure readuns(a:adr;s:size);
-    begin { construct unsigned out of byte sequence }
-      readint(a,s) { identical to readint }
-    end;
-
-    procedure readfloat(a:adr;s:size);
-    var i:size; b:byte;
-    begin { construct float out of string}
-      if (s<>4) and (s<>8) then noinit; i:=0;
-      repeat { eat the bytes, construct the value and intialize at a }
-	b:=readbyte; i:=i+1;
-      until b=0 ;
-    end;
-
-begin
-  halted:=false;
-  exitstatus:=undef;
-  uerrorproc:=0; intrap:=false;
-
-  { initialize tables }
-  for i:=0 to maxcode do code[i]:=0;
-  for i:=0 to maxdata do data[i]:=0;
-  for iclass:=prim to tert do
-    for i:=0 to 255 do
-      with dispat[iclass][i] do
-	begin instr:=NON; iflag:=[zbit] end;
-
-  { read instruction table file. see appendix B }
-  { The table read here is a simple transformation of the table on page xx }
-  { - instruction names were transformed to numbers }
-  { - the '-' flag was transformed to an 'i' flag for 'w' type instructions }
-  { - the 'S' flag was added for instructions having signed operands }
-  reset(tables);
-  insr:=NON;
-  repeat
-    read(tables,insno) ; cset:=[]; f:=[];
-    insr:=ifind(insno);
-    if insr=NON then begin writeln('Incorrect table'); halt end;
-    repeat read(tables,c) until c<>' ' ;
-    repeat
-      cset:=cset+[c];
-      read(tables,c)
-    until c=' ' ;
-    if 'm' in cset then f:=f+[mini];
-    if 's' in cset then f:=f+[short];
-    if '-' in cset then f:=f+[zbit];
-    if 'i' in cset then f:=f+[ibit];
-    if 'S' in cset then f:=f+[sbit];
-    if 'w' in cset then f:=f+[wbit];
-    if (mini in f) or (short in f) then read(tables,nops) else nops:=1 ;
-    readln(tables,opcode);
-    if ('4' in cset) or ('8' in cset) then
-      begin iclass:=tert end
-    else if 'e' in cset then
-      begin iclass:=second end
-    else iclass:=prim;
-    for i:=0 to nops-1 do
-    begin
-      with dispat[iclass,opcode+i] do
-      begin
-	iflag:=f; instr:=insr;
-	if '2' in cset      then ilength:=2
-	else if '4' in cset then ilength:=4
-	else if '8' in cset then ilength:=8
-	else if (mini in f) or (short in f) then
-	  begin
-	    if 'N' in cset then wtemp:=-1-i else wtemp:=i ;
-	    if 'o' in cset then wtemp:=wtemp+1 ;
-	    if short in f then wtemp:=wtemp*256 ;
-	    implicit:=wtemp
-	  end
-      end
-    end
-  until eof(tables);
-
-  { read in program text, data and procedure descriptors }
-  reset(prog);
-  readhdr;                               { verify first header }
-  for i:=1 to 8 do header[i]:=readadr;  { read second header }
-  hp:=maxdata+1; sp:=maxdata+1; lino(0);
-  { read program text }
-  if header[NTEXT]+header[NPROC]*pdsize>maxcode then
-    begin writeln('Text size too large'); halt end;
-  if header[SZDATA]>maxdata then
-    begin writeln('Data size too large'); halt end;
-  for i:=0 to header[NTEXT]-1 do code[i]:=readbyte;
-  { read data blocks }
-  nexta:=0;
-  for i:=1 to header[NDATA] do
-    begin
-      n:=readbyte;
-      if n<>0 then
-	begin
-	  elem:=readbyte; firsta:=nexta;
-	  case n of
-	  1: { uninitialized words }
-	     for j:=1 to elem do
-	     begin store(nexta,undef); nexta:=nexta+wsize end;
-	  2: { initialized bytes }
-	     for j:=1 to elem do
-	     begin storeb(nexta,readbyte); nexta:=nexta+1 end;
-	  3: { initialized words }
-	     for j:=1 to elem do
-	     begin store(nexta,readword); nexta:=nexta+wsize end;
-	  4,5: { instruction and data pointers }
-	     for j:=1 to elem do
-	     begin storea(nexta,readadr); nexta:=nexta+asize end;
-	  6: { signed integers }
-	     begin readint(nexta,elem); nexta:=nexta+elem end;
-	  7: { unsigned integers }
-	     begin readuns(nexta,elem); nexta:=nexta+elem end;
-	  8: { floating point numbers }
-	     begin readfloat(nexta,elem); nexta:=nexta+elem end;
-	  end
-	end
-      else
-	begin
-	  repc:=readadr;
-	  amount:=nexta-firsta;
-	  for count:=1 to repc do
-	  begin
-	    for ofst:=0 to amount-1 do data[nexta+ofst]:=data[firsta+ofst];
-	    nexta:=nexta+amount;
-	  end
-	end
-    end;
-  if header[SZDATA]<>nexta then writeln('Data initialization error');
-  hp:=nexta;
-  { read descriptor table }
-  pd:=header[NTEXT];
-  for i:=1 to header[NPROC]*pdsize do code[pd+i-1]:=readbyte;
-  { call the entry point routine }
-  ignmask:=0;	   { catch all traps, higher numbered traps cannot be ignored}
-  retsize:=0;
-  lb:=maxdata;     { illegal dynamic link }
-  pc:=maxcode;     { illegal return address }
-  push(0); a:=sp;  { No environment }
-  push(0); b:=sp;  { No args }
-  pusha(a);        { envp }
-  pusha(b);        { argv }
-  push(0);         { argc }
-  call(argp(header[ENTRY]));
-end;
-{
-.bp
-{---------------------------------------------------------------------------}
-{                       MAIN LOOP OF THE INTERPRETER                        }
-{---------------------------------------------------------------------------}
-{ It should be noted that the interpreter (microprogram) for  an  EM
-  machine  can be written in two fundamentally different ways: (1) the
-  instruction operands are fetched in the main loop, or  (2)  the  in-
-  struction operands are fetched after the 256 way branch, by the exe-
-  cution routines themselves.  In this interpreter, method (1) is used
-  to  simplify  the  description  of execution  routines. The dispatch
-  table dispat is used to determine how the operand is  encoded. There
-  are 4 possibilities:
-
-     0. There is no operand
-     1. The operand and  instruction are  together in 1  byte (mini)
-     2. The operand is  one byte long and follows the opcode byte(s)
-     3. The operand is two bytes long and follows the opcode byte(s)
-     4. The operand is four bytes long and follows the opcode byte(s)
-
-  In  this  interpreter,  the  main  loop determines the operand type,
-  fetches it, and leaves it in the global variable k for the execution
-  routines  to use.  Consequently, instructions such as LOL, which use
-  three different formats, need only be described once in the body  of
-  the interpreter.
-      However, for  a  production  interpreter,  or  a  hardware  EM
-  machine,  it  is  probably better to use method (2), i.e. to let the
-  execution routines themselves fetch their own operands.  The  reason
-  for this is that each opcode uniquely determines the operand format,
-  so no table lookup in the dispatch table is needed.  The whole table
-  is not needed. Method (2) therefore executes much faster.
-      However, separate execution routines will be needed for LOL with
-  a one byte offset,  and  LOL with a two byte offset.  It is to avoid
-  this additional clutter that method (1) is used here.  In a  produc-
-  tion interpreter, it is envisioned that the main loop will fetch the
-  next instruction byte, and use it as an index into a 256 word  table
-  to  find  the  address  of  the interpreter routine to jump to.  The
-  routine jumped to will  begin  by  fetching  its  operand,  if  any,
-  without  any  table  lookup,  since it knows which format to expect.
-  After doing the work, it returns to the main  loop  by  jumping  in-
-  directly  to  a register that contains the address of the main loop.
-      A slight variation on this idea is to have the  register contain
-  the address of the branch table, rather than the address of the main
-  loop.
-      Another  issue  is whether the execution routines for LOL 0, LOL
-  2, LOL 4, etc. should all be have distinct execution routines. Doing
-  so  provides for the maximum speed, since the operand is implicit in
-  the routine itself.  The disadvantage is that many nearly  identical
-  execution  routines will then be needed.  Another way of doing it is
-  to keep the instruction byte fetched from memory (LOL 0, LOL 2,  LOL
-  4, etc.) in some register, and have all the LOL mini format instruc-
-  tions branch to a common routine.  This routine can  then  determine
-  the  operand  by  subtracting  the code for LOL 0 from the register,
-  leaving the true operand in the register  (as  a  word  quantity  of
-  course).   This  method  makes the interpreter smaller, but is a bit
-  slower.
-.bp
-       To make this important point a little clearer, consider how a
-  production interpreter for the PDP-11 might appear.  Let us assume the
-  following opcodes have been assigned:
-
-       31: LOL -2     (2 bytes, i.e. next word)
-       32: LOL -4
-       33: LOL -6
-       34: LOL b      (format with a one byte offset)
-       35: LOL w      (format with a one word, i.e. two byte offset)
-
-  Further assume that each of the 5 opcodes will have its own execution
-  routine, i.e. we are making a tradeoff in favor of fast execution and
-  a slightly larger interpreter.
-       Register r5 is the em program counter.
-       Register r4 is the em LB register
-       Register r3 is the em SP register (the stack grows toward low core)
-       Register r2 contains the interpreter address of the main loop
-
-  The main loop looks like this:
-
-       movb (r5)+,r0           /fetch the opcode into r0 and increment r5
-       asl r0                  /shift r0 left 1 bit. Now: -256<=r0<=+254
-       jmp *table(r0)          /jump to execution routine
-
-  Notice that no operand fetching has been done. The execution routines for
-  the 5 sample instructions given above might be as follows:
-
-  lol2: mov -2(r4),-(sp)       /push local -2 onto stack
-	jmp (r2)               /go back to main loop
-  lol4: mov -4(r4),-(sp)       /push local -4 onto stack
-	jmp (r2)               /go back to main loop
-  lol6: mov -6(r4),-(sp)       /push local -6 onto stack
-	jmp (r2)               /go back to main loop
-  lolb: mov $177400,r0         /prepare to fetch the 1 byte operand
-	bisb (r5)+,r0          /operand is now in r0
-	asl r0                 /r0 is now offset from LB in bytes, not words
-	add r4,r0              /r0 is now address of the needed local
-	mov (r0),-(sp)         /push the local onto the stack
-	jmp (r2)
-  lolw: clr r0                 /prepare to fetch the 2 byte operand
-	bisb (r5)+,r0          /fetch high order byte first !!!
-	swab r0                /insert high order byte in place
-	bisb (r5)+,r0          /insert low order byte in place
-	asl r0                 /convert offset to bytes, from words
-	add r4,r0              /r0 is now address of needed local
-	mov (r0),-(sp)         /stack the local
-	jmp (r2)               /done
-
-  The important thing to notice is where and how the operand fetch occurred:
-       lol2, lol4, and lol6, (the minis) have implicit operands
-       lolb knew it had to fetch one byte, and did so without any table lookup
-       lolw knew it had to fetch a word, and did so, high order byte first }
-{
-.bp
-.sp 4
-{---------------------------------------------------------------------------}
-{           Routines for the individual instructions                        }
-{---------------------------------------------------------------------------}
-procedure loadops;
-var j:integer;
-begin
-  case insr of
-    { LOAD GROUP }
-    LDC: pushd(argd(k));
-    LOC: pushsw(argc(k));
-    LOL: push(memw(locadr(k)));
-    LOE: push(memw(argg(k)));
-    LIL: push(memw(mema(locadr(k))));
-    LOF: push(memw(popa+argf(k)));
-    LAL: pusha(locadr(k));
-    LAE: pusha(argg(k));
-    LXL: begin a:=lb; for j:=1 to argn(k) do a:=mema(a+savsize); pusha(a) end;
-    LXA: begin a:=lb;
-	   for j:=1 to argn(k) do a:= mema(a+savsize);
-	   pusha(a+savsize)
-	 end;
-    LOI: pushx(argo(k),popa);
-    LOS: begin k:=argw(k); if k<>wsize then trap(EILLINS);
-	   k:=pop; pushx(argo(k),popa)
-	 end;
-    LDL: begin a:=locadr(k); push(memw(a+wsize)); push(memw(a)) end;
-    LDE: begin k:=argg(k); push(memw(k+wsize)); push(memw(k)) end;
-    LDF: begin k:=argf(k);
-	   a:=popa; push(memw(a+k+wsize)); push(memw(a+k))
-	 end;
-    LPI: push(argp(k))
-  end
-end;
-
-procedure storeops;
-begin
-  case insr of
-    { STORE GROUP }
-    STL: store(locadr(k),pop);
-    STE: store(argg(k),pop);
-    SIL: store(mema(locadr(k)),pop);
-    STF: begin a:=popa; store(a+argf(k),pop) end;
-    STI: popx(argo(k),popa);
-    STS: begin k:=argw(k); if k<>wsize then trap(EILLINS);
-	   k:=popa; popx(argo(k),popa)
-	 end;
-    SDL: begin a:=locadr(k); store(a,pop); store(a+wsize,pop) end;
-    SDE: begin k:=argg(k); store(k,pop); store(k+wsize,pop) end;
-    SDF: begin k:=argf(k); a:=popa; store(a+k,pop); store(a+k+wsize,pop) end
-  end
-end;
-
-procedure intarith;
-var i:integer;
-begin
-  case insr of
-    { SIGNED INTEGER ARITHMETIC }
-    ADI: case szindex(argw(k)) of
-	 1: begin st:=popsw; ss:=popsw; push(fitsw(ss+st,EIOVFL)) end;
-	 2: begin dt:=popd; ds:=popd; pushd(doadi(ds,dt)) end;
-	 end ;
-    SBI: case szindex(argw(k)) of
-	 1: begin st:=popsw; ss:= popsw; push(fitsw(ss-st,EIOVFL)) end;
-	 2: begin dt:=popd; ds:=popd; pushd(dosbi(ds,dt)) end;
-	 end ;
-    MLI: case szindex(argw(k)) of
-	 1: begin st:=popsw; ss:= popsw; push(fitsw(ss*st,EIOVFL)) end;
-	 2: begin dt:=popd; ds:=popd; pushd(domli(ds,dt)) end;
-	 end ;
-    DVI: case szindex(argw(k)) of
-	 1: begin st:= popsw; ss:= popsw;
-	       if st=0 then trap(EIDIVZ) else pushsw(ss div st)
-	    end;
-	 2: begin dt:=popd; ds:=popd; pushd(dodvi(ds,dt)) end;
-	 end;
-    RMI: case szindex(argw(k)) of
-	 1: begin st:= popsw; ss:=popsw;
-	       if st=0 then trap(EIDIVZ) else pushsw(ss - (ss div st)*st)
-	    end;
-	 2: begin dt:=popd; ds:=popd; pushd(dormi(ds,dt)) end
-	 end;
-    NGI: case szindex(argw(k)) of
-	 1: begin st:=popsw; pushsw(-st) end;
-	 2: begin ds:=popd; pushd(dongi(ds)) end
-	 end;
-    SLI: begin t:=pop;
-	   case szindex(argw(k)) of
-	   1: begin ss:=popsw;
-		 for i:= 1 to t do sleft(ss); pushsw(ss)
-	      end
-	   end
-	 end;
-    SRI: begin t:=pop;
-	   case szindex(argw(k)) of
-	   1: begin ss:=popsw;
-		 for i:= 1 to t do sright(ss); pushsw(ss)
-	      end;
-	   2: begin ds:=popd;
-		 for i:= 1 to t do sdright(ss); pushd(ss)
-	      end
-	   end
-	 end
-  end
-end;
-
-procedure unsarith;
-var i:integer;
-begin
-  case insr of
-    { UNSIGNED INTEGER ARITHMETIC }
-    ADU: case szindex(argw(k)) of
-	 1: begin t:=pop; s:= pop; push(chopw(s+t)) end;
-	 2: trap(EILLINS);
-	 end ;
-    SBU: case szindex(argw(k)) of
-	 1: begin t:=pop; s:= pop; push(chopw(s-t)) end;
-	 2: trap(EILLINS);
-	 end ;
-    MLU: case szindex(argw(k)) of
-	 1: begin t:=pop; s:= pop; push(chopw(s*t)) end;
-	 2: trap(EILLINS);
-	 end ;
-    DVU: case szindex(argw(k)) of
-	 1: begin t:= pop; s:= pop;
-	       if t=0 then trap(EIDIVZ) else push(s div t)
-	    end;
-	 2: trap(EILLINS);
-	 end;
-    RMU: case szindex(argw(k)) of
-	 1: begin t:= pop; s:=pop;
-	       if t=0 then trap(EIDIVZ) else push(s - (s div t)*t)
-	    end;
-	 2: trap(EILLINS);
-	 end;
-    SLU: case szindex(argw(k)) of
-	 1: begin t:=pop; s:=pop;
-	       for i:= 1 to t do suleft(s); push(s)
-	    end;
-	 2: trap(EILLINS);
-	 end;
-    SRU: case szindex(argw(k)) of
-	 1: begin t:=pop; s:=pop;
-	       for i:= 1 to t do suright(s); push(s)
-	    end;
-	 2: trap(EILLINS);
-	 end
-  end
-end;
-
-procedure fltarith;
-begin
-  case insr of
-    { FLOATING POINT ARITHMETIC }
-    ADF: begin argwf(k); rt:=popr; rs:=popr; pushr(doadf(rs,rt)) end;
-    SBF: begin argwf(k); rt:=popr; rs:=popr; pushr(dosbf(rs,rt)) end;
-    MLF: begin argwf(k); rt:=popr; rs:=popr; pushr(domlf(rs,rt)) end;
-    DVF: begin argwf(k); rt:=popr; rs:=popr; pushr(dodvf(rs,rt)) end;
-    NGF: begin argwf(k); rt:=popr; pushr(dongf(rt)) end;
-    FIF: begin argwf(k); rt:=popr; rs:=popr;
-	       dofif(rt,rs,x,y); pushr(y); pushr(x)
-	 end;
-    FEF: begin argwf(k); rt:=popr; dofef(rt,x,ss); pushr(x); pushsw(ss) end
-  end
-end;
-
-procedure ptrarith;
-begin
-  case insr of
-    { POINTER ARITHMETIC }
-    ADP: pusha(popa+argf(k));
-    ADS: case szindex(argw(k)) of
-	 1: begin st:=popsw; pusha(popa+st) end;
-	 2: begin dt:=popd; pusha(popa+dt) end;
-	 end;
-    SBS: begin
-	   a:=popa; b:=popa;
-	   case szindex(argw(k)) of
-	     1: push(fitsw(b-a,EIOVFL));
-	     2: pushd(b-a)
-	   end
-	 end
-  end
-end;
-
-procedure incops;
-var j:integer;
-begin
-  case insr of
-    { INCREMENT/DECREMENT/ZERO }
-    INC: push(fitsw(popsw+1,EIOVFL));
-    INL: begin a:=locadr(k); store(a,fitsw(signwd(memw(a))+1,EIOVFL)) end;
-    INE: begin a:=argg(k); store(a,fitsw(signwd(memw(a))+1,EIOVFL)) end;
-    DEC: push(fitsw(popsw-1,EIOVFL));
-    DEL: begin a:=locadr(k); store(a,fitsw(signwd(memw(a))-1,EIOVFL)) end;
-    DEE: begin a:=argg(k); store(a,fitsw(signwd(memw(a))-1,EIOVFL)) end;
-    ZRL: store(locadr(k),0);
-    ZRE: store(argg(k),0);
-    ZER: for j:=1 to argw(k) div wsize do push(0);
-    ZRF: pushr(0);
-  end
-end;
-
-procedure convops;
-begin
-  case insr of
-    { CONVERT GROUP }
-    CII: begin s:=pop; t:=pop;
-	   if t<wsize then begin push(sextend(pop,t)); t:=wsize end;
-	   case szindex(argw(t)) of
-	   1: if szindex(argw(s))=2 then pushd(popsw);
-	   2: if szindex(argw(s))=1 then push(fitsw(popd,ECONV))
-	   end
-	 end;
-    CIU: case szindex(argw(pop)) of
-	 1: if szindex(argw(pop))=2 then push(unsign(popd mod negoff));
-	 2: trap(EILLINS);
-	 end;
-    CIF: begin argwf(pop);
-	   case szindex(argw(pop)) of 1:pushr(popsw); 2:pushr(popd) end
-	 end;
-    CUI: case szindex(argw(pop)) of
-	 1: case szindex(argw(pop)) of
-	    1: begin s:=pop; if s>maxsint then trap(ECONV); push(s) end;
-	    2: trap(EILLINS);
-	    end;
-	 2: case szindex(argw(pop)) of
-	    1: pushd(pop);
-	    2: trap(EILLINS);
-	    end;
-	 end;
-    CUU: case szindex(argw(pop)) of
-	 1: if szindex(argw(pop))=2 then trap(EILLINS);
-	 2: trap(EILLINS);
-	 end;
-    CUF: begin argwf(pop);
-	   if szindex(argw(pop))=1 then pushr(pop) else trap(EILLINS)
-	 end;
-    CFI: begin sz:=argw(pop); argwf(pop); rt:=popr;
-	   case szindex(sz) of
-	   1: push(fitsw(trunc(rt),ECONV));
-	   2: pushd(fitd(trunc(rt)));
-	   end
-	 end;
-    CFU: begin sz:=argw(pop); argwf(pop); rt:=popr;
-	   case szindex(sz) of
-	   1: push( chopw(trunc(abs(rt)-0.5)) );
-	   2: trap(EILLINS);
-	   end
-	 end;
-    CFF: begin argwf(pop); argwf(pop) end
-  end
-end;
-
-procedure logops;
-var i,j:integer;
-begin
-  case insr of
-    { LOGICAL GROUP }
-    XAND:
-	 begin k:=argw(k);
-	   for j:= 1 to k div wsize do
-	     begin a:=sp+k; t:=pop; store(a,bf(andf,memw(a),t)) end;
-	 end;
-    IOR:
-	 begin k:=argw(k);
-	   for j:= 1 to k div wsize do
-	     begin a:=sp+k; t:=pop; store(a,bf(iorf,memw(a),t)) end;
-	 end;
-    XOR:
-	 begin k:=argw(k);
-	   for j:= 1 to k div wsize do
-	     begin a:=sp+k; t:=pop; store(a,bf(xorf,memw(a),t)) end;
-	 end;
-    COM:
-	 begin k:=argw(k);
-	   for j:= 1 to k div wsize do
-	     begin
-	       store(sp+k-wsize*j, bf(xorf,memw(sp+k-wsize*j), negoff-1))
-	     end
-	 end;
-    ROL: begin k:=argw(k); if k<>wsize then trap(EILLINS);
-	   t:=pop; s:=pop; for i:= 1 to t do rleft(s); push(s)
-	 end;
-    ROR: begin k:=argw(k); if k<>wsize then trap(EILLINS);
-	   t:=pop; s:=pop; for i:= 1 to t do rright(s); push(s)
-	 end
-  end
-end;
-
-procedure setops;
-var i,j:integer;
-begin
-  case insr of
-    { SET GROUP }
-    INN:
-	 begin k:=argw(k);
-	   t:=pop;
-	   i:= t mod 8; t:= t div 8;
-	   if t>=k then
-	     begin trap(ESET); s:=0 end
-	   else
-	     begin s:=memb(sp+t) end;
-	   newsp(sp+k); push(bit(i,s));
-	 end;
-    XSET:
-	 begin k:=argw(k);
-	   t:=pop;
-	   i:= t mod 8; t:= t div 8;
-	   for j:= 1 to k div wsize do push(0);
-	   if t>=k then
-	     trap(ESET)
-	   else
-	     begin s:=1; for j:= 1 to i do rleft(s); storeb(sp+t,s) end
-	 end
-  end
-end;
-
-procedure arrops;
-begin
-  case insr of
-    { ARRAY GROUP }
-    LAR:
-	 begin k:=argw(k); if k<>wsize then trap(EILLINS); a:=popa;
-	   pushx(argo(memw(a+2*k)),arraycalc(a))
-	 end;
-    SAR:
-	 begin k:=argw(k); if k<>wsize then trap(EILLINS); a:=popa;
-	   popx(argo(memw(a+2*k)),arraycalc(a))
-	 end;
-    AAR:
-	 begin k:=argw(k); if k<>wsize then trap(EILLINS); a:=popa;
-	   push(arraycalc(a))
-	 end
-  end
-end;
-
-procedure cmpops;
-begin
-  case insr of
-    { COMPARE GROUP }
-    CMI: case szindex(argw(k)) of
-	 1: begin st:=popsw; ss:=popsw;
-	      if ss<st then pushsw(-1) else if ss=st then push(0) else push(1)
-	    end;
-	 2: begin dt:=popd; ds:=popd;
-	      if ds<dt then pushsw(-1) else if ds=dt then push(0) else push(1)
-	    end;
-	 end;
-    CMU: case szindex(argw(k)) of
-	 1: begin t:=pop; s:=pop;
-	      if s<t then pushsw(-1) else if s=t then push(0) else push(1)
-	    end;
-	 2: trap(EILLINS);
-	 end;
-    CMP: begin a:=popa; b:=popa;
-	  if b<a then pushsw(-1) else if b=a then push(0) else push(1)
-	 end;
-    CMF: begin argwf(k); rt:=popr; rs:=popr;
-	   if rs<rt then pushsw(-1) else if rs=rt then push(0) else push(1)
-	 end;
-    CMS: begin k:=argw(k);
-	   t:= 0; j:= 0;
-	   while (j < k) and (t=0) do
-	     begin if memw(sp+j) <> memw(sp+k+j) then t:=1;
-	       j:=j+wsize
-	     end;
-	   newsp(sp+wsize*k); push(t);
-	 end;
-
-    TLT: if popsw <  0 then push(1) else push(0);
-    TLE: if popsw <= 0 then push(1) else push(0);
-    TEQ: if pop   =  0 then push(1) else push(0);
-    TNE: if pop   <> 0 then push(1) else push(0);
-    TGE: if popsw >= 0 then push(1) else push(0);
-    TGT: if popsw >  0 then push(1) else push(0);
-  end
-end;
-
-procedure branchops;
-begin
-  case insr of
-    { BRANCH GROUP }
-    BRA: newpc(pc+k);
-
-    BLT: begin st:=popsw; if popsw <  st then newpc(pc+k) end;
-    BLE: begin st:=popsw; if popsw <= st then newpc(pc+k) end;
-    BEQ: begin t :=pop  ; if pop   =   t then newpc(pc+k) end;
-    BNE: begin t :=pop  ; if pop   <>  t then newpc(pc+k) end;
-    BGE: begin st:=popsw; if popsw >= st then newpc(pc+k) end;
-    BGT: begin st:=popsw; if popsw >  st then newpc(pc+k) end;
-
-    ZLT: if popsw <  0 then newpc(pc+k);
-    ZLE: if popsw <= 0 then newpc(pc+k);
-    ZEQ: if pop   =  0 then newpc(pc+k);
-    ZNE: if pop   <> 0 then newpc(pc+k);
-    ZGE: if popsw >= 0 then newpc(pc+k);
-    ZGT: if popsw >  0 then newpc(pc+k)
-  end
-end;
-
-procedure callops;
-var j:integer;
-begin
-  case insr of
-    { PROCEDURE CALL GROUP }
-    CAL: call(argp(k));
-    CAI: begin call(argp(popa)) end;
-    RET: begin k:=argz(k); if k div wsize>maxret  then trap(EILLINS);
-	   for j:= 1 to k div wsize do retarea[j]:=pop; retsize:=k;
-	   newsp(lb); lb:=maxdata+1; { To circumvent stack overflow error }
-	   newpc(popa);
-	   if pc=maxcode then
-	   begin
-	     halted:=true;
-	     if retsize=wsize then exitstatus:=retarea[1]
-	       else exitstatus:=undef
-	  end
-	  else
-	     newlb(popa);
-	 end;
-    LFR: begin k:=args(k); if k<>retsize then trap(EILLINS);
-	   for j:=k div wsize downto 1 do push(retarea[j]);
-	 end
-  end
-end;
-
-procedure miscops;
-var i,j:integer;
-begin
-  case insr of
-    { MISCELLANEOUS GROUP }
-    ASP,ASS:
-	 begin if insr=ASS then
-	   begin k:=argw(k); if k<>wsize then trap(EILLINS); k:=popsw end;
-	   k:=argf(k);
-	   if k<0
-	     then for j:= 1 to -k div wsize do push(undef)
-	     else newsp(sp+k);
-	 end;
-    BLM,BLS:
-	 begin if insr=BLS then
-	   begin k:=argw(k); if k<>wsize then trap(EILLINS); k:=pop end;
-	   k:=argz(k);
-	   b:=popa; a:=popa;
-	   for j := 1 to k div wsize do
-	     store(b-wsize+wsize*j,memw(a-wsize+wsize*j))
-	 end;
-    CSA: begin k:=argw(k); if k<>wsize then trap(EILLINS);
-	   a:=popa;
-	   st:= popsw - signwd(memw(a+asize));
-	   if (st>=0) and (st<=memw(a+wsize+asize)) then
-	      b:=mema(a+2*wsize+asize+asize*st) else b:=mema(a);
-	   if b=0 then trap(ECASE) else newpc(b)
-	 end;
-    CSB: begin k:=argw(k); if k<>wsize then trap(EILLINS); a:=popa;
-	   t:=pop; i:=1; found:=false;
-	   while (i<=memw(a+asize)) and not found do
-	     if t=memw(a+(asize+wsize)*i) then found:=true else i:=i+1;
-	   if found then b:=memw(a+(asize+wsize)*i+wsize) else b:=memw(a);
-	   if b=0 then trap(ECASE) else newpc(b);
-	 end;
-    DCH: begin pusha(mema(popa+dynd)) end;
-    DUP,DUS:
-	 begin if insr=DUS then
-	      begin k:=argw(k); if k<>wsize then trap(EILLINS); k:=pop end;
-	   k:=args(k);
-	   for i:=1 to k div wsize do push(memw(sp+k-wsize));
-	 end;
-    EXG: begin
-	   k:=argw(k);
-	   for i:=1 to k div wsize do push(memw(sp+k-wsize));
-	   for i:=0 to k div wsize - 1 do
-	     store(sp+k+i*wsize,memw(sp+k+k+i*wsize));
-	   for i:=1 to k div wsize do
-	   begin t:=pop ; store(sp+k+k-wsize,t) end;
-	 end;
-    FIL: filna(argg(k));
-    GTO: begin k:=argg(k);
-	   newlb(mema(k+2*asize)); newsp(mema(k+asize)); newpc(mema(k))
-	 end;
-    LIM: push(ignmask);
-    LIN: lino(argn(k));
-    LNI: lino(memw(0)+1);
-    LOR: begin i:=argr(k);
-	   case i of 0:pusha(lb); 1:pusha(sp); 2:pusha(hp) end;
-	 end;
-    LPB: pusha(popa+statd);
-    MON: domon(pop);
-    NOP: writeln('NOP at line ',memw(0):5) ;
-    RCK: begin a:=popa;
-	   case szindex(argw(k)) of
-	   1: if (signwd(memw(sp))<signwd(memw(a))) or
-		(signwd(memw(sp))>signwd(memw(a+wsize))) then trap(ERANGE);
-	   2: if (memd(sp)<memd(a)) or
-		(memd(sp)>memd(a+2*wsize)) then trap(ERANGE);
-	   end
-	 end;
-    RTT: dortt;
-    SIG: begin a:=popa; pusha(uerrorproc); uerrorproc:=a end;
-    SIM: ignmask:=pop;
-    STR: begin i:=argr(k);
-	   case i of 0: newlb(popa); 1: newsp(popa); 2: newhp(popa) end;
-	 end;
-    TRP: trap(pop)
-  end
-end;
-{
-.bp
-{---------------------------------------------------------------------------}
-{                               Main Loop                                   }
-{---------------------------------------------------------------------------}
-
-begin initialize;
-8888:
-  repeat
-    opcode := nextpc;       { fetch the first byte of the instruction }
-    if opcode=escape1 then iclass:=second
-    else if opcode=escape2 then iclass:=tert
-    else iclass:=prim;
-    if iclass<>prim then opcode := nextpc;
-    with dispat[iclass][opcode] do
-      begin insr:=instr;
-	if not (zbit in iflag) then
-	  if ibit in iflag then k:=pop else
-	    begin
-	      if mini in iflag then k:=implicit else
-		begin
-		  if short in iflag then k:=implicit+nextpc else
-		    begin k:=nextpc;
-		      if (sbit in iflag) and (k>=128) then k:=k-256;
-		      for i:=2 to ilength do k:=256*k + nextpc
-		    end
-		end;
-	      if wbit in iflag then k:=k*wsize;
-	    end
-      end;
-case insr of
-
-  NON: trap(EILLINS);
-
-  { LOAD GROUP }
-  LDC,LOC,LOL,LOE,LIL,LOF,LAL,LAE,LXL,LXA,LOI,LOS,LDL,LDE,LDF,LPI:
-      loadops;
-
-  { STORE GROUP }
-  STL,STE,SIL,STF,STI,STS,SDL,SDE,SDF:
-      storeops;
-
-  { SIGNED INTEGER ARITHMETIC }
-  ADI,SBI,MLI,DVI,RMI,NGI,SLI,SRI:
-      intarith;
-
-  { UNSIGNED INTEGER ARITHMETIC }
-  ADU,SBU,MLU,DVU,RMU,SLU,SRU:
-      unsarith;
-
-  { FLOATING POINT ARITHMETIC }
-  ADF,SBF,MLF,DVF,NGF,FIF,FEF:
-      fltarith;
-
-  { POINTER ARITHMETIC }
-  ADP,ADS,SBS:
-      ptrarith;
-
-  { INCREMENT/DECREMENT/ZERO }
-  INC,INL,INE,DEC,DEL,DEE,ZRL,ZRE,ZER,ZRF:
-      incops;
-
-  { CONVERT GROUP }
-  CII,CIU,CIF,CUI,CUU,CUF,CFI,CFU,CFF:
-      convops;
-
-  { LOGICAL GROUP }
- XAND,IOR,XOR,COM,ROL,ROR:
-      logops;
-
-  { SET GROUP }
-  INN,XSET:
-      setops;
-
-  { ARRAY GROUP }
-  LAR,SAR,AAR:
-      arrops;
-
-  { COMPARE GROUP }
-  CMI,CMU,CMP,CMF,CMS,  TLT,TLE,TEQ,TNE,TGE,TGT:
-      cmpops;
-
-  { BRANCH GROUP }
-  BRA,  BLT,BLE,BEQ,BNE,BGE,BGT,  ZLT,ZLE,ZEQ,ZNE,ZGE,ZGT:
-      branchops;
-
-  { PROCEDURE CALL GROUP }
-  CAL,CAI,RET,LFR:
-      callops;
-
-  { MISCELLANEOUS GROUP }
-  ASP,ASS,BLM,BLS,CSA,CSB,DCH,DUP,DUS,EXG,FIL,GTO,LIM,
-  LIN,LNI,LOR,LPB,MON,NOP,RCK,RTT,SIG,SIM,STR,TRP:
-      miscops;
-
-    end;        { end of case statement }
-    if not ( (insr=RET) or (insr=ASP) or (insr=BRA) or (insr=GTO) ) then
-	retsize:=0 ;
-  until halted;
-9999:
-  writeln('halt with exit status: ',exitstatus:1);
-  doident;
-end.

+ 0 - 210
doc/em/int/emdmp.c

@@ -1,210 +0,0 @@
-/*
- * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
- *
- *          This product is part of the Amsterdam Compiler Kit.
- *
- * Permission to use, sell, duplicate or disclose this software must be
- * obtained in writing. Requests for such permissions may be sent to
- *
- *      Dr. Andrew S. Tanenbaum
- *      Wiskundig Seminarium
- *      Vrije Universiteit
- *      Postbox 7161
- *      1007 MC Amsterdam
- *      The Netherlands
- *
- */
-
-/* Author: E.G. Keizer */
-
-/* Print a readable version of the data in the post mortem dump */
-/* dmpc [-s] [-dn,m] [file] */
-
-#include "/usr/em/h/local.h"
-#include <stdio.h>
-#include <ctype.h>
-
-int dflag = 0 ;
-long l_low,l_high;
-
-int sflag;
-
-int wsize,asize;
-long tsize,dsize;
-long ignmask,uerrorproc,cause;
-long pc,sp,lb,hp,pd,pb;
-
-char *cstr[] = {
-	"Array bound error",
-	"Range bound error",
-	"Set error",
-	"Integer overflow",
-	"Float overflow",
-	"Float underflow",
-	"Divide by 0",
-	"Divide by 0.0",
-	"Integer undefined",
-	"Float undefined",
-	"Conversion error",
-	"User error 11",
-	"User error 12",
-	"User error 13",
-	"User error 14",
-	"User error 15",
-	"Stack overflow",
-	"Heap overflow",
-	"Illegal instruction",
-	"Illegal size parameter",
-	"Case error",
-	"Memory fault",
-	"Illegal pointer",
-	"Illegal pc",
-	"Bad argument of LAE",
-	"Bad monitor call",
-	"Bad line number",
-	"GTO descriptor error"
-};
-
-FILE *fcore;
-char *core = "core" ;
-int nbyte=0;
-
-char *pname;
-
-int readbyte();
-int read2();
-long readaddr();
-long readword();
-unsigned getbyte();
-long getword();
-long getaddr();
-
-main(argc,argv) char **argv;
-{
-	register i ;
-	long line,fileaddr;
-	char tok ;
-
-	scanargs(argc,argv); fcore=fopen(core,"r") ;
-	if ( fcore==NULL ) fatal("Can't open %s",core) ;
-
-	if ( read2()!=010255 ) fatal("not a post mortem dump");
-	if ( read2()!=VERSION ) fatal("wrong version dump file");
-	wsize=read2(); asize=read2();
-	if ( wsize>4 ) fatal("cannot handle word size %d",wsize) ;
-	if ( asize>4 ) fatal("cannot handle pointer size %d",asize) ;
-	tsize=readaddr(); dsize=readaddr();
-	ignmask=readaddr(); uerrorproc=readaddr(); cause=readaddr();
-	pc=readaddr(); sp=readaddr(); lb=readaddr(); hp=readaddr();
-	pd=readaddr(); pb=readaddr();
-	if ( sflag==0 ) {
-		line=getword(0L);
-		fileaddr=getaddr(4L);
-		if ( fileaddr ) {
-			for ( i=0 ; i<40 ; i++ ) {
-				tok=getbyte(fileaddr++) ;
-				if ( !isprint(tok) ) break ;
-				putc(tok,stdout);
-			}
-			printf(" ");
-		}
-		if ( line ) {
-			printf("line %D",line) ;
-		}
-		if ( fileaddr || line ) printf(", ");
-		fseek(fcore,512L,0);
-
-		if ( cause>27 ) {
-			printn("cause",cause) ;
-		} else {
-			prints("cause",cstr[(int)cause]);
-		}
-		printn("pc",pc);printn("sp",sp);printn("lb",lb);
-		printn("hp",hp);
-		if ( pd ) printn("pd",pd) ;
-		if ( pb ) printn("pb",pb) ;
-		printn("errproc",uerrorproc) ;
-		printn("ignmask",ignmask) ;
-		if ( tsize ) printn("Text size",tsize) ;
-		if ( dsize ) printn("Data size",dsize) ;
-	}
-	if ( dflag==0 ) return 0;
-	fatal("d-flag not implemeted (yet)");
-	return 1 ;
-}
-
-scanargs(argc,argv) char **argv ; {
-	pname=argv[0];
-	while ( argv++, argc-- > 1 ) {
-		switch( argv[0][0] ) {
-		case '-':    switch( argv[0][1] ) {
-				case 's':    sflag++ ; break ;
-				case 'l':    dflag++ ; break ;
-				default : fatal(": [-s] [-ln.m] [file]") ;
-			} ;
-			break ;
-		default :core=argv[0] ;
-		}
-	}
-}
-
-prints(s1,s2) char *s1,*s2; {
-	printf("%-15s %s\n",s1,s2);
-}
-
-printn(s1,d) char *s1; long d; {
-	printf("%-15s %15ld\n",s1,d);
-}
-
-/* VARARGS1 */
-fatal(s1,p1,p2,p3,p4,p5) char *s1 ; {
-	fprintf(stderr,"%s: ",pname);
-	fprintf(stderr,s1,p1,p2,p3,p4,p5) ;
-	fprintf(stderr,"\n") ;
-	exit(1) ;
-}
-
-int getb() {
-	int i ;
-	i=getc(fcore) ;
-	if ( i==EOF ) fatal("Premature EOF");
-	return i&0377 ;
-}
-
-int read2() {
-	int i ;
-	i=getb() ; return getb()*256 + i ;
-}
-
-long readaddr() {
-	long res ;
-	register int i ;
-
-	res=0 ;
-	for (i=0 ; i<asize ; i++ ) res |= getb()<<(8*i) ;
-	return res ;
-}
-
-long readword() {
-	long res ;
-	register int i ;
-
-	res=0 ;
-	for (i=0 ; i<wsize ; i++ ) res |= getb()<<(8*i) ;
-	return res ;
-}
-
-unsigned getbyte(a) long a ; {
-	fseek(fcore,a+512,0) ;
-	return getb() ;
-}
-
-long getword(a) long a ; {
-	fseek(fcore,a+512,0) ;
-	return readword() ;
-}
-
-long getaddr(a) long a ; {
-	fseek(fcore,a+512,0) ;
-	return readaddr() ;
-}

+ 0 - 244
doc/em/int/mktables.c

@@ -1,244 +0,0 @@
-/*
- * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
- *
- *          This product is part of the Amsterdam Compiler Kit.
- *
- * Permission to use, sell, duplicate or disclose this software must be
- * obtained in writing. Requests for such permissions may be sent to
- *
- *      Dr. Andrew S. Tanenbaum
- *      Wiskundig Seminarium
- *      Vrije Universiteit
- *      Postbox 7161
- *      1007 MC Amsterdam
- *      The Netherlands
- *
- */
-
-/* Author: E.G. Keizer */
-
-#include <stdio.h>
-#include "/usr/em/util/ass/ip_spec.h"
-#include "/usr/em/h/em_spec.h"
-#include "/usr/em/h/em_flag.h"
-
-/* This program reads the human readable interpreter specification
-   and produces a efficient machine representation that can be
-   translated by a C-compiler.
-*/
-
-#define ESCAP   256
-
-int nerror = 0 ;
-int atend  = 0 ;
-int line   = 1 ;
-int maxinsl= 0 ;
-
-extern char em_mnem[][4] ;
-char esca[] = "escape" ;
-#define ename(no)       ((no)==ESCAP?esca:em_mnem[(no)])
-
-extern char em_flag[] ;
-
-main(argc,argv) char **argv ; {
-	if ( argc>1 ) {
-		if ( freopen(argv[1],"r",stdin)==NULL) {
-			fatal("Cannot open %s",argv[1]) ;
-		}
-	}
-	if ( argc>2 ) {
-		if ( freopen(argv[2],"w",stdout)==NULL) {
-			fatal("Cannot create %s",argv[2]) ;
-		}
-	}
-	if ( argc>3 ) {
-		fatal("%s [ file [ file ] ]",argv[0]) ;
-	}
-	atend=0 ;
-	readin();
-	atend=1 ;
-	return nerror ;
-}
-
-readin() {
-	char *ident();
-	char *firstid ;
-	int opcode,flags;
-	int c;
-
-	while ( !feof(stdin) ) {
-		firstid=ident() ;
-		if ( *firstid=='\n' || feof(stdin) ) continue ;
-		opcode = getmnem(firstid) ;
-		printf("%d ",opcode+1) ;
-		flags  = decflag(ident(),opcode) ;
-		switch(em_flag[opcode]&EM_PAR) {
-		case PAR_D: case PAR_F: case PAR_B: case PAR_L: case PAR_C:
-			putchar('S') ;
-		}
-		putchar(' ');
-		while ( (c=readchar())!='\n' && c!=EOF ) putchar(c) ;
-		putchar('\n') ;
-	}
-}
-
-char *ident() {
-	/* skip spaces and tabs, anything up to space,tab or eof is
-	   a identifier.
-	   Anything from # to end-of-line is an end-of-line.
-	   End-of-line is an identifier all by itself.
-	*/
-
-	static char array[200] ;
-	register int c ;
-	register char *cc ;
-
-	do {
-		c=readchar() ;
-	} while ( c==' ' || c=='\t' ) ;
-	for ( cc=array ; cc<&array[(sizeof array) - 1] ; cc++ ) {
-		if ( c=='#' ) {
-			do {
-				c=readchar();
-			} while ( c!='\n' && c!=EOF ) ;
-		}
-		*cc = c ;
-		if ( c=='\n' && cc==array ) break ;
-		c=readchar() ;
-		if ( c=='\n' ) {
-			pushback(c) ;
-			break ;
-		}
-		if ( c==' ' || c=='\t' || c==EOF ) break ;
-	}
-	*++cc=0 ;
-	return array ;
-}
-
-int getmnem(str) char *str ; {
-	char (*ptr)[4] ;
-
-	for ( ptr = em_mnem ; *ptr<= &em_mnem[sp_lmnem][0] ; ptr++ ) {
-		if ( strcmp(*ptr,str)==0 ) return (ptr-em_mnem) ;
-	}
-	error("Illegal mnemonic") ;
-	return 0 ;
-}
-
-error(str,a1,a2,a3,a4,a5,a6) /* VARARGS1 */ char *str ; {
-	if ( !atend ) fprintf(stderr,"line %d: ",line) ;
-	fprintf(stderr,str,a1,a2,a3,a4,a5,a6) ;
-	fprintf(stderr,"\n");
-	nerror++ ;
-}
-
-mess(str,a1,a2,a3,a4,a5,a6) /* VARARGS1 */ char *str ; {
-	if ( !atend ) fprintf(stderr,"line %d: ",line) ;
-	fprintf(stderr,str,a1,a2,a3,a4,a5,a6) ;
-	fprintf(stderr,"\n");
-}
-
-fatal(str,a1,a2,a3,a4,a5,a6) /* VARARGS1 */ char *str ; {
-	error(str,a1,a2,a3,a4,a5,a6) ;
-	exit(1) ;
-}
-
-#define ILLGL   -1
-
-check(val) int val ; {
-	if ( val!=ILLGL ) error("Illegal flag combination") ;
-}
-
-int decflag(str,opc) char *str ; {
-	int type ;
-	int escape ;
-	int range ;
-	int wordm ;
-	int notzero ;
-	char c;
-
-	type=escape=range=wordm=notzero= ILLGL ;
-	while ( c= *str++ ) {
-		switch ( c ) {
-		case 'm' :
-			check(type) ; type=OPMINI ; break ;
-		case 's' :
-			check(type) ; type=OPSHORT ; break ;
-		case '-' :
-			check(type) ; type=OPNO ;
-			if ( (em_flag[opc]&EM_PAR)==PAR_W ) c='i' ;
-			break ;
-		case '1' :
-			check(type) ; type=OP8 ; break ;
-		case '2' :
-			check(type) ; type=OP16 ; break ;
-		case '4' :
-			check(type) ; type=OP32 ; break ;
-		case '8' :
-			check(type) ; type=OP64 ; break ;
-		case 'e' :
-			check(escape) ; escape=0 ; break ;
-		case 'N' :
-			check(range) ; range= 2 ; break ;
-		case 'P' :
-			check(range) ; range= 1 ; break ;
-		case 'w' :
-			check(wordm) ; wordm=0 ; break ;
-		case 'o' :
-			check(notzero) ; notzero=0 ; break ;
-		default :
-			error("Unknown flag") ;
-		}
-		putchar(c);
-	}
-	if ( type==ILLGL ) error("Type must be specified") ;
-	switch ( type ) {
-	case OP64 :
-	case OP32 :
-		if ( escape!=ILLGL ) error("Conflicting escapes") ;
-		escape=ILLGL ;
-	case OP16 :
-	case OP8 :
-	case OPSHORT :
-	case OPNO :
-		if ( notzero!=ILLGL ) mess("Improbable OPNZ") ;
-		if ( type==OPNO && range!=ILLGL ) {
-			mess("No operand in range") ;
-		}
-	}
-	if ( escape!=ILLGL ) type|=OPESC ;
-	if ( wordm!=ILLGL ) type|=OPWORD ;
-	switch ( range) {
-	case ILLGL : type|=OP_BOTH ; break ;
-	case 1     : type|=OP_POS  ; break ;
-	case 2     : type|=OP_NEG  ; break ;
-	}
-	if ( notzero!=ILLGL ) type|=OPNZ ;
-	return type ;
-}
-
-static int pushchar ;
-static int pushf ;
-
-int readchar() {
-	int c ;
-
-	if ( pushf ) {
-		pushf=0 ;
-		c = pushchar ;
-	} else {
-		if ( feof(stdin) ) return EOF ;
-		c=getc(stdin) ;
-	}
-	if ( c=='\n' ) line++ ;
-	return c ;
-}
-
-pushback(c) {
-	if ( pushf ) {
-		fatal("Double pushback") ;
-	}
-	pushf++ ;
-	pushchar=c ;
-	if ( c=='\n' ) line-- ;
-}

+ 0 - 180
doc/em/intro.nr

@@ -1,180 +0,0 @@
-.BP
-.S1 "INTRODUCTION"
-EM is a family of intermediate languages designed for producing
-portable compilers.
-The general strategy is for a program called
-.B front end
-to translate the source program to EM.
-Another program,
-.B back
-.BW end
-translates EM to target assembly language.
-Alternatively, the EM code can be assembled to a binary form
-and interpreted.
-These considerations led to the following goals:
-.IS 2 10
-.PS 1 4
-.PT
-The design should allow translation to,
-or interpretation on, a wide range of existing machines.
-Design decisions should be delayed as far as possible
-and the implications of these decisions should
-be localized as much as possible.
-.N
-The current microcomputer technology offers 8, 16 and 32 bit machines
-with various sizes of address space.
-EM should be flexible enough to be useful on most of these
-machines.
-The differences between the members of the EM family should only
-concern the wordsize and address space size.
-.PT
-The architecture should ease the task of code generation for
-high level languages such as Pascal, C, Ada, Algol 68, BCPL.
-.PT
-The instruction set used by the interpreter should be compact,
-to reduce the amount of memory needed
-for program storage, and to reduce the time needed to transmit
-programs over communication lines.
-.PT
-It should be designed with microprogrammed implementations in
-mind; in particular, the use of many short fields within
-instruction opcodes should be avoided, because their extraction by the
-microprogram or conversion to other instruction formats is inefficient.
-.PE
-.IE
-.A
-The basic architecture is based on the concept of a stack. The stack
-is used for procedure return addresses, actual parameters, local variables,
-and arithmetic operations.
-There are several built-in object types,
-for example, signed and unsigned integers,
-floating point numbers, pointers and sets of bits.
-There are instructions to push and pop objects
-to and from the stack.
-The push and pop instructions are not typed.
-They only care about the size of the objects.
-For each built-in type there are
-reverse Polish type instructions that pop one or more
-objects from the top of
-the stack, perform an operation, and push the result back onto the
-stack.
-For all types except pointers,
-these instructions have the object size
-as argument.
-.P
-There are no visible general registers used for arithmetic operands
-etc. This is in contrast to most third generation computers, which usually
-have 8 or 16 general registers. The decision not to have a group of
-general registers was fully intentional, and follows W.L. Van der
-Poel's dictum that a machine should have 0, 1, or an infinite
-number of any feature. General registers have two primary uses: to hold
-intermediate results of complicated expressions, e.g.
-.IS 5 0 1
-((a*b + c*d)/e + f*g/h) * i
-.IE 1
-and to hold local variables.
-.P
-Various studies
-have shown that the average expression has fewer than two operands,
-making the former use of registers of doubtful value. The present trend
-toward structured programs consisting of many small
-procedures greatly reduces the value of registers to hold local variables
-because the large number of procedure calls implies a large overhead in
-saving and restoring the registers at every call.
-.BP
-.P
-Although there are no general purpose registers, there are a
-few internal registers with specific functions as follows:
-.IS 2
-.N 1
-.TS
-tab(:);
-l 1 l l.
-PC:-:Program Counter:Pointer to next instruction
-LB:-:Local Base:Points to base of the local variables \
-in the current procedure.
-SP:-:Stack Pointer:Points to the highest occupied word on the stack.
-HP:-:Heap Pointer:Points to the top of the heap area.
-.TE 1
-.IE
-.A
-Furthermore, reverse Polish code is much easier to generate than
-multi-register machine code, especially if highly efficient code is
-desired.
-When translating to assembly language the back end can make
-good use of the target machine's registers.
-An EM machine can
-achieve high performance by keeping part of the stack
-in high speed storage (a cache or microprogram scratchpad memory) rather
-than in primary memory.
-.P
-Again according to van der Poel's dictum,
-all EM instructions have zero or one argument.
-We believe that instructions needing two arguments
-can be split into two simpler ones.
-The simpler ones can probably be used in other
-circumstances as well.
-Moreover, these two instructions together often
-have a shorter encoding than the single
-instruction before.
-.P
-This document describes EM at three different levels:
-the abstract level, the assembly language level and
-the machine language level.
-.A
-The most important level is that of the abstract EM architecture.
-This level deals with the basic design issues.
-Only the functional capabilities of instructions are relevant, not their
-format or encoding.
-Most chapters of this document refer to the abstract level
-and it is explicitly stated whenever
-another level is described.
-.A
-The assembly language is intended for the compiler writer.
-It presents a more or less orthogonal instruction
-set and provides symbolic names for data.
-Moreover, it facilitates the linking of
-separately compiled 'modules' into a single program
-by providing several pseudoinstructions.
-.A
-The machine language is designed for interpretation with a compact
-program text and easy decoding.
-The binary representation of the machine language instruction set is
-far from orthogonal.
-Frequent instructions have a short opcode.
-The encoding is fully byte oriented.
-These bytes do not contain small bit fields, because
-bit fields would slow down decoding considerably.
-.P
-A common use for EM is for producing portable (cross) compilers.
-When used this way, the compilers produce
-EM assembly language as their output.
-To run the compiled program on the target machine,
-the back end, translates the EM assembly language to
-the target machine's assembly language.
-When this approach is used, the format of the EM
-machine language instructions is irrelevant.
-On the other hand, when writing an interpreter for EM machine language
-programs, the interpreter must deal with the machine language
-and not with the symbolic assembly language.
-.P
-As mentioned above, the
-current microcomputer technology offers 8, 16 and 32 bit
-machines with address spaces ranging from 2\v'-0.5m'16\v'0.5m'
-to 2\v'-0.5m'32\v'0.5m' bytes.
-Having one size of pointers and integers restricts
-the usefulness of the language.
-We decided to have a different language for each combination of
-word and pointer size.
-All languages offer the same instruction set and differ only in
-memory alignment restrictions and the implicit size assumed in
-several instructions.
-The languages
-differ slightly for the
-different size combinations.
-For example: the
-size of any object on the stack and alignment restrictions.
-The wordsize is restricted to powers of 2 and
-the pointer size must be a multiple of the wordsize.
-Almost all programs handling EM will be parametrized with word
-and pointer size.

+ 0 - 376
doc/em/iotrap.nr

@@ -1,376 +0,0 @@
-.SN 8
-.VS 1 0
-.BP
-.S1 "ENVIRONMENT INTERACTIONS"
-EM programs can interact with their environment in three ways.
-Two, starting/stopping and monitor calls, are dealt with in this chapter.
-The remaining way to interact, interrupts, will be treated
-together with traps in chapter 9.
-.S2 "Program starting and stopping"
-EM user programs start with a call to a procedure called
-m_a_i_n.
-The assembler and backends look for the definition of a procedure
-with this name in their input.
-The call passes three parameters to the procedure.
-The parameters are similar to the parameters supplied by the
-UNIX
-.FS
-UNIX is a Trademark of Bell Laboratories.
-.FE
-operating system to C programs.
-These parameters are often called
-.BW argc ,
-.B argv
-and
-.BW envp .
-Argc is the parameter nearest to LB and is a wordsized integer.
-The other two are pointers to the first element of an array of
-string pointers.
-.N
-The
-.B argv
-array contains
-.B argc
-strings, the first of which contains the program call name.
-The other strings in the
-.B argv
-array are the program parameters.
-.P
-The
-.B envp
-array contains strings in the form "name=string", where 'name'
-is the name of an environment variable and string its value.
-The
-.B envp
-is terminated by a zero pointer.
-.P
-An EM user program stops if the program returns from the first
-invocation of m_a_i_n.
-The contents of the function return area are used to procure a
-wordsized program return code.
-EM programs also stop when traps and interrupts occur that are
-not caught and when the exit monitor call is executed.
-.S2 "Input/Output and other monitor calls"
-EM differs from most conventional machines in that it has high level i/o
-instructions.
-Typical instructions are OPEN FILE and READ FROM FILE instead
-of low level instructions such as setting and clearing
-bits in device registers.
-By providing such high level i/o primitives, the task of implementing
-EM on various non EM machines is made considerably easier.
-.P
-I/O is initiated by the MON instruction, which expects an iocode on top
-of the stack.
-Often there are also parameters which are pushed on the
-stack in reverse order, that is: last
-parameter first.
-Some i/o functions also provide results, which are returned on the stack.
-In the list of monitor calls we use several types of parameters and results,
-these types consist of integers and unsigneds of varying sizes, but never
-smaller than the wordsize, and the two pointer types.
-.N 1
-The names of the types used are:
-.IS 4
-.PS - 10
-.PT int
-an integer of wordsize
-.PT int2
-an integer whose size is the maximum of the wordsize and 2
-bytes
-.PT int4
-an integer whose size is the maximum of the wordsize and 4
-bytes
-.PT intp
-an integer with the size of a pointer
-.PT uns2
-an unsigned integer whose size is the maximum of the wordsize and 2
-.PT unsp
-an unsigned integer with the size of a pointer
-.PT ptr
-a pointer into data space
-.PE 1
-.IE 0
-The table below lists the i/o codes with their results and
-parameters.
-This list is similar to the system calls of the UNIX Version 7
-operating system.
-.BP
-.A
-To execute a monitor call, proceed as follows:
-.IS 2
-.N 1
-.PS a 4 "" )
-.PT
-Stack the parameters, in reverse order, last parameter first.
-.PT
-Push the monitor call number (iocode) onto the stack.
-.PT
-Execute the MON instruction.
-.PE 1
-.IE
-An error code is present on the top of the stack after
-execution of most monitor calls.
-If this error code is zero, the call performed the action
-requested and the results are available on top of the stack.
-Non-zero error codes indicate a failure, in this case no
-results are available and the error code has been pushed twice.
-This construction enables programs to test for failure with a
-single instruction (~TEQ or TNE~) and still find out the cause of
-the failure.
-The result name 'e' is reserved for the error code.
-.N 1
-List of monitor calls.
-.DS B
-number name    parameters      results           function
-
-   1   Exit    status:int                        Terminate this process
-   2   Fork                    e,flag,pid:int    Spawn new process
-   3   Read    fildes:int;buf:ptr;nbytes:unsp
-                               e:int;rbytes:unsp Read from file
-   4   Write   fildes:int;buf:ptr;nbytes:unsp
-                               e:int;wbytes:unsp Write on a file
-   5   Open    string:ptr;flag:int
-                               e,fildes:int      Open file for read and/or write
-   6   Close   fildes:int      e:int             Close a file
-   7   Wait                    e:int;status,pid:int2
-                                                 Wait for child
-   8   Creat   string:ptr;mode:int
-                               e,fildes:int      Create a new file
-   9   Link    string1,string2:ptr
-                               e:int             Link to a file
-  10   Unlink  string:ptr      e:int             Remove directory entry
-  12   Chdir   string:ptr      e:int             Change default directory
-  14   Mknod   string:ptr;mode,addr:int2
-                               e:int             Make a special file
-  15   Chmod   string:ptr;mode:int2
-                               e:int             Change mode of file
-  16   Chown   string:ptr;owner,group:int2
-                               e:int             Change owner/group of a file
-  18   Stat    string,statbuf:ptr
-                               e:int             Get file status
-  19   Lseek   fildes:int;off:int4;whence:int
-                               e:int;oldoff:int4 Move read/write pointer
-  20   Getpid                  pid:int2          Get process identification
-  21   Mount   special,string:ptr;rwflag:int
-                               e:int             Mount file system
-  22   Umount  special:ptr     e:int             Unmount file system
-  23   Setuid  userid:int2     e:int             Set user ID
-  24   Getuid                  e_uid,r_uid:int2  Get user ID
-  25   Stime   time:int4       e:int             Set time and date
-  26   Ptrace  request:int;pid:int2;addr:ptr;data:int
-                               e,value:int       Process trace
-  27   Alarm   seconds:uns2    previous:uns2     Schedule signal
-  28   Fstat   fildes:int;statbuf:ptr
-                               e:int             Get file status
-  29   Pause                                     Stop until signal
-  30   Utime   string,timep:ptr
-                               e:int             Set file times
-  33   Access  string,mode:int e:int             Determine file accessibility
-  34   Nice    incr:int                          Set program priority
-  35   Ftime   bufp:ptr        e:int             Get date and time
-  36   Sync                                      Update filesystem
-  37   Kill    pid:int2;sig:int
-                               e:int             Send signal to a process
-  41   Dup     fildes,newfildes:int
-                               e,fildes:int      Duplicate a file descriptor
-  42   Pipe                    e,w_des,r_des:int Create a pipe
-  43   Times   buffer:ptr                        Get process times
-  44   Profil  buff:ptr;bufsiz,offset,scale:intp Execution time profile
-  46   Setgid  gid:int2        e:int             Set group ID
-  47   Getgid                  e_gid,r_gid:int   Get group ID
-  48   Sigtrp  trapno,signo:int
-                               e,prevtrap:int    See below
-  51   Acct    file:ptr        e:int             Turn accounting on or off
-  53   Lock    flag:int        e:int             Lock a process
-  54   Ioctl   fildes,request:int;argp:ptr
-                               e:int             Control device
-  56   Mpxcall cmd:int;vec:ptr e:int             Multiplexed file handling
-  59   Exece   name,argv,envp:ptr
-                               e:int             Execute a file
-  60   Umask   complmode:int2  oldmask:int2      Set file creation mode mask
-  61   Chroot  string:ptr      e:int             Change root directory
-.DE 1
-Codes 0, 11, 13, 17, 31, 32, 38, 39, 40, 45, 49, 50, 52,
-55, 57, 58, 62, and 63 are
-not used.
-.P
-All monitor calls, except fork and sigtrp
-are the same as the UNIX version 7 system calls.
-.P
-The sigtrp entry maps UNIX signals onto EM interrupts.
-Normally, trapno is in the range 0 to 252.
-In that case it requests that signal signo
-will cause trap trapno to occur.
-When given trap number -2, default signal handling is reset, and when given
-trap number -3, the signal is ignored.
-.P
-The flag returned by fork is 1 in the child process and 0 in
-the parent.
-The pid returned is the process-id of the other process.
-.BP
-.S1 "TRAPS AND INTERRUPTS"
-EM provides a means for the user program to catch all traps
-generated by the program itself, the hardware, or external conditions.
-This mechanism uses five instructions: LIM, SIM, SIG, TRP and RTT.
-This section of the manual may be omitted on the first reading since it
-presupposes knowledge of the EM instruction set.
-.P
-The action taken when a trap occures is determined by the value
-of an internal EM trap register.
-This register contains a pointer to a procedure.
-Initially the pointer used is zero and all traps halt the
-program with, hopefully, a useful message to the outside world.
-The SIG instruction can be used to alter the trap register,
-it pops a procedure pointer from the
-stack into the trap register.
-When a trap occurs after storing a nonzero value in the trap
-register, the procedure pointed to by the trap register
-is called with the trap number
-as the only parameter (see below).
-SIG returns the previous value of the trap register on the
-stack.
-Two consecutive SIGs are a no-op.
-When a trap occurs, the trap register is reset to its initial
-condition, to prevent recursive traps from hanging the machine up,
-e.g. stack overflow in the stack overflow handling procedure.
-.P
-The runtime systems for some languages need to ignore some EM
-traps.
-EM offers a feature called the ignore mask.
-It contains one bit for each of the lowest 16 trap numbers.
-The bits are numbered 0 to 15, with the least significant bit
-having number 0.
-If a certain bit is 1 the corresponding trap never
-occurs and processing simply continues.
-The actions performed by the offending instruction are
-described by the Pascal program in appendix A.
-.N
-If the bit is 0, traps are not ignored.
-The instructions LIM and SIM allow copying and replacement of
-the ignore mask.~
-.P
-The TRP instruction generates a trap, the trap number being found on the
-stack.
-This is, among other things,
-useful for library procedures and runtime systems.
-It can also be used by a low level trap procedure to pass the trap to a
-higher level one (see example below).
-.P
-The RTT instruction returns from the trap procedure and continues after the
-trap.
-In the list below all traps marked with an asterisk ('*') are
-considered to be fatal and it is explicitly undefined what happens if
-you try to restart after the trap.
-.P
-The way a trap procedure is called is completely compatible
-with normal calling conventions. The only way a trap procedure
-differs from normal procedures is the return. It has to use RTT instead
-of RET. This is necessary because the complete runtime status is saved on the
-stack before calling the procedure and all this status has to be reloaded.
-Error numbers are in the range 0 to 252.
-The trap numbers are divided into three categories:
-.IS 4
-.N 1
-.PS - 10
-.PT ~~0-~63
-EM machine errors, e.g. illegal instruction.
-.PS - 8
-.PT ~0-15
-maskable
-.PT 16-63
-not maskable
-.PE
-.PT ~64-127
-Reserved for use by compilers, run time systems, etc.
-.PT 128-252
-Available for user programs.
-.PE 1
-.IE
-EM machine errors are numbered as follows:
-.DS I 5
-.TS
-tab(@);
-n l l.
-0@EARRAY@Array bound error
-1@ERANGE@Range bound error
-2@ESET@Set bound error
-3@EIOVFL@Integer overflow
-4@EFOVFL@Floating overflow
-5@EFUNFL@Floating underflow
-6@EIDIVZ@Divide by 0
-7@EFDIVZ@Divide by 0.0
-8@EIUND@Undefined integer
-9@EFUND@Undefined float
-10@ECONV@Conversion error
-16*@ESTACK@Stack overflow
-17*@EHEAP@Heap overflow
-18*@EILLINS@Illegal instruction
-19*@EODDZ@Illegal size argument
-20*@ECASE@Case error
-21*@EMEMFLT@Addressing non existent memory
-22*@EBADPTR@Bad pointer used
-23*@EBADPC@Program counter out of range
-24@EBADLAE@Bad argument of LAE
-25@EBADMON@Bad monitor call
-26@EBADLIN@Argument of LIN too high
-27@EBADGTO@GTO descriptor error
-.TE
-.DE 0
-.P
-As an example,
-suppose a subprocedure has to be written to do a numeric
-calculation.
-When an overflow occurs the computation has to be stopped and
-the higher level procedure must be resumed.
-This can be programmed as follows using the mechanism described above:
-.DS B
- mes 2,2,2              ; set sizes
-ersave
- bss 2,0,0              ; Room to save previous value of trap procedure
-msave
- bss 2,0,0              ; Room to save previous value of trap mask
-
- pro calcule,0          ; entry point
- lxl 0                  ; fill in non-local goto descriptor with LB
- ste jmpbuf+4
- lor 1                  ; and SP
- ste jmpbuf+2
- lim                    ; get current ignore mask
- ste msave              ; save it
- lim
- loc 4                  ; bit for EFOVFL
- ior 2                  ; set in mask
- sim                    ; ignore EFOVFL from now on
- lpi $catch             ; load procedure identifier
- sig                    ; catch wil get all traps now
- ste ersave             ; save previous trap procedure identifier
-; perform calculation now, possibly generating overflow
-1                       ; label jumped to by catch procedure
- loe ersave             ; get old trap procedure
- sig                    ; refer all following trap to old procedure
- asp 2                  ; remove result of sig
- loe msave              ; restore previous mask
- sim                    ; done now
-; load result of calculation
- ret 2                  ; return result
-jmpbuf
- con *1,0,0
- end
-.DE 0
-.VS 1 1
-.DS
-Example of catch procedure
- pro catch,0            ; Local procedure that must catch the overflow trap
- lol 2                  ; Load trap number
- loc 4                  ; check for overflow
- bne *1                 ; if other trap, call higher trap procedure
- gto jmpbuf             ; return to procedure calcule
-1                       ; other trap has occurred
- loe ersave             ; previous trap procedure
- sig                    ; other procedure will get the traps now
- asp 2                  ; remove the result of sig
- lol 2                  ; stack trap number
- trp                    ; call other trap procedure
- rtt                    ; if other procedure returns, do the same
- end
-.DE

+ 0 - 6
doc/em/ip.awk

@@ -1,6 +0,0 @@
-BEGIN { printf ".TS\nlw(6) lw(8) rw(3) rw(6) 14 lw(6) lw(8) rw(3) rw(6) 14 lw(6) lw(8) rw(3) rw(6).\n" }
-NF == 4 { printf "%s\t%s\t%d\t%d",$1,$2,$3,$4 }
-NF == 3 { printf "%s\t%s\t\t%d",$1,$2,$3 }
- { if ( NR%3 == 0 ) printf("\n") ; else printf("\t"); }
-END { if ( NR%3 != 0 ) printf("\n")
-      printf ".TE\n" }

+ 0 - 62
doc/em/ispace.nr

@@ -1,62 +0,0 @@
-.SN 3
-.BP
-.S1 "INSTRUCTION ADDRESS SPACE"
-The instruction space of the EM machine contains
-the code for procedures.
-Tables necessary for the execution of this code, for example, procedure
-descriptor tables, may also be present.
-The instruction space does not change during
-the execution of a program, so that it may be
-protected.
-No further restrictions to the instruction address space are
-necessary for the abstract and assembly language level.
-.P
-Each procedure has a single entry point: the first instruction.
-A special type of pointer identifies a procedure.
-Pointers into the instruction
-address space have the same size as pointers into data space and
-can, for example, contain the address of the first instruction
-or an index in a procedure descriptor table.
-.A
-There is a single EM program counter, PC, pointing
-to the next instruction to be executed.
-The procedure pointed to by PC is
-called the 'current' procedure.
-A procedure may call another procedure using the CAL or CAI
-instruction.
-The calling procedure remains 'active' and is resumed whenever the called
-procedure returns.
-Note that a procedure has several 'active' invocations when
-called recursively.
-.P
-Each procedure must return properly.
-It is not allowed to fall through to the
-code of the next procedure.
-There are several ways to exit from a procedure:
-.IS 3
-.PS
-.PT
-the RET instruction, which returns to the
-calling procedure.
-.PT
-the RTT instruction, which exits a trap handling routine and resumes
-the trapping instruction (see next chapter).
-.PT
-the GTO instruction, which is used for non-local goto's.
-It can remove several frames from the stack and transfer
-control to an active procedure.
-(see also MES~11 in paragraph 11.1.4.4)
-.PE
-.IE
-.P
-All branch instructions can transfer control
-to any label within the same procedure.
-Branch instructions can never jump out of a procedure.
-.P
-Several language implementations use a so called procedure
-instance identifier, a combination of a procedure identifier and
-the LB of a stack frame, also called static link.
-.P
-The program text for each procedure, as well as any tables,
-are fragments and can be allocated anywhere
-in the instruction address space.

+ 0 - 2525
doc/em/itables

@@ -1,2525 +0,0 @@
-.TS
-.if \n+(b.=1 .nr d. \n(.c-\n(c.-1
-.de 35
-.ps \n(.s
-.vs \n(.vu
-.in \n(.iu
-.if \n(.u .fi
-.if \n(.j .ad
-.if \n(.j=0 .na
-..
-.nf
-.nr #~ 0
-.if n .nr #~ 0.6n
-.ds #d .d
-.if \(ts\n(.z\(ts\(ts .ds #d nl
-.fc
-.nr 33 \n(.s
-.rm 80 81 82 83 84 85 86 87 88 89 90 91
-.nr 80 0
-.nr 38 \waar
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wadp
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wadp
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wasp
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wbeq
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wble
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wbne
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wbra
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wcff
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wcmf
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wcms
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wdec
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wdup
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wfil
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wine
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \winn
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wlae
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wlal
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wlal
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wldc
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wldl
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wlfr
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wlil
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wlni
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wloc
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wloe
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wlof
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wloi
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wlol
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wlol
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wlxa
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wmli
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wret
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wsbf
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wset
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wsli
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wstf
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wsti
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wstl
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wstl
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wtgt
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wzeq
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wzge
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wzlt
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wzre
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wzrl
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \waar
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wadi
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wads
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wand
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wass
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wbgt
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wbls
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wbne
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wcfi
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wcmf
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wcmi
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wcmu
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wcom
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wcsb
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wcui
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wdel
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wdus
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wdvf
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wdvu
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wfef
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \winl
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \winn
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wlar
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wldf
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wlfr
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wlim
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wlor
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wlxl
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wmli
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wmlu
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wngf
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wnop
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wret
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wrmu
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wrol
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wrtt
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wsbf
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wsbi
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wsbu
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wsdf
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wset
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wsil
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wsli
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wslu
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wsru
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wsts
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wtge
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wxor
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wzer
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wzle
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wzrf
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wdch
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wexg
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \wldc
-.if \n(80<\n(38 .nr 80 \n(38
-.80
-.rm 80
-.nr 38 6n
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 81 0
-.nr 38 \wmwPo
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \w2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wsN
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wmwPo
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wsP
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wsP
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wsP
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wsP
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \w-
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wsP
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wsP
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \w-
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wmwPo
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \w2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wsw
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wsP
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \w2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wN2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wswP
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wmP
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wmP
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wsP
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wmwP
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \w-
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wmN
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \ww2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wmwPo
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wmPo
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wwP2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wmwN
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wmPo
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wmwPo
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wsP
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wsP
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wsP
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wmwPo
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \w2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wmPo
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wwP2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wmwN
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \w-
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \w2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wsP
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wsP
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \ww2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wswN
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we-
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we-
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we-
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we-
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we-
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we-
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wewP2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we-
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we-
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wewP2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we-
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we-
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wesP
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we-
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we-
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we-
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we-
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we-
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we-
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wewP2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we-
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we-
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we-
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we2
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we-
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \we-
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \w4
-.if \n(81<\n(38 .nr 81 \n(38
-.81
-.rm 81
-.nr 38 8n
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 82 0
-.nr 38 \w1
-.if \n(82<\n(38 .nr 82 \n(38
-.nr 38 \w1
-.if \n(82<\n(38 .nr 82 \n(38
-.nr 38 \w5
-.if \n(82<\n(38 .nr 82 \n(38
-.nr 38 \w1
-.if \n(82<\n(38 .nr 82 \n(38
-.nr 38 \w1
-.if \n(82<\n(38 .nr 82 \n(38
-.nr 38 \w1
-.if \n(82<\n(38 .nr 82 \n(38
-.nr 38 \w2
-.if \n(82<\n(38 .nr 82 \n(38
-.nr 38 \w1
-.if \n(82<\n(38 .nr 82 \n(38
-.nr 38 \w1
-.if \n(82<\n(38 .nr 82 \n(38
-.nr 38 \w1
-.if \n(82<\n(38 .nr 82 \n(38
-.nr 38 \w1
-.if \n(82<\n(38 .nr 82 \n(38
-.nr 38 \w1
-.if \n(82<\n(38 .nr 82 \n(38
-.nr 38 \w1
-.if \n(82<\n(38 .nr 82 \n(38
-.nr 38 \w1
-.if \n(82<\n(38 .nr 82 \n(38
-.nr 38 \w1
-.if \n(82<\n(38 .nr 82 \n(38
-.nr 38 \w1
-.if \n(82<\n(38 .nr 82 \n(38
-.nr 38 \w2
-.if \n(82<\n(38 .nr 82 \n(38
-.nr 38 \w1
-.if \n(82<\n(38 .nr 82 \n(38
-.nr 38 \w4
-.if \n(82<\n(38 .nr 82 \n(38
-.nr 38 \w1
-.if \n(82<\n(38 .nr 82 \n(38
-.nr 38 \w8
-.if \n(82<\n(38 .nr 82 \n(38
-.nr 38 \w1
-.if \n(82<\n(38 .nr 82 \n(38
-.nr 38 \w2
-.if \n(82<\n(38 .nr 82 \n(38
-.nr 38 \w1
-.if \n(82<\n(38 .nr 82 \n(38
-.nr 38 \w1
-.if \n(82<\n(38 .nr 82 \n(38
-.nr 38 \w1
-.if \n(82<\n(38 .nr 82 \n(38
-.nr 38 \w1
-.if \n(82<\n(38 .nr 82 \n(38
-.nr 38 \w1
-.if \n(82<\n(38 .nr 82 \n(38
-.nr 38 \w5
-.if \n(82<\n(38 .nr 82 \n(38
-.nr 38 \w1
-.if \n(82<\n(38 .nr 82 \n(38
-.nr 38 \w1
-.if \n(82<\n(38 .nr 82 \n(38
-.nr 38 \w1
-.if \n(82<\n(38 .nr 82 \n(38
-.nr 38 \w1
-.if \n(82<\n(38 .nr 82 \n(38
-.82
-.rm 82
-.nr 38 3n
-.if \n(82<\n(38 .nr 82 \n(38
-.nr 83 0
-.nr 38 \w34
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w38
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w42
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w45
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w52
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w55
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w58
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w62
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w93
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w96
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w100
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w103
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w106
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w109
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w112
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w117
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w120
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w129
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w132
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w136
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w139
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w143
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w146
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w150
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w152
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w155
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w162
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w168
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w174
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w180
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w190
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w194
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w199
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w202
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w206
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w209
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w214
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w218
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w224
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w228
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w235
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w238
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w242
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w245
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w248
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w252
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w1
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w4
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w7
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w10
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w13
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w16
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w19
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w22
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w25
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w28
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w31
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w34
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w37
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w40
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w43
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w46
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w49
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w52
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w55
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w58
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w61
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w64
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w67
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w70
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w73
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w76
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w79
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w82
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w85
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w88
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w91
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w94
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w97
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w100
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w103
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w106
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w109
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w112
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w115
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w118
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w121
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w124
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w127
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w130
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w133
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w136
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w139
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w142
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w145
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w148
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w151
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w154
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w157
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 38 \w0
-.if \n(83<\n(38 .nr 83 \n(38
-.83
-.rm 83
-.nr 38 6n
-.if \n(83<\n(38 .nr 83 \n(38
-.nr 84 0
-.nr 38 \wadf
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wadp
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wads
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wasp
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wbge
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wblm
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wbra
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wcal
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wcif
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wcmi
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wcsa
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wdee
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wdvf
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \winc
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \winl
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wior
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wlae
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wlal
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wlal
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wlde
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wldl
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wlil
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wlin
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wloc
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wloc
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wloe
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wlof
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wloi
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wlol
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wlol
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wlxl
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wrck
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wrmi
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wsbi
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wsil
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wste
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wstf
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wsti
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wstl
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wstl
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wtlt
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wzeq
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wzgt
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wzne
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wzre
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wzrl
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wadf
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wadi
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wadu
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wand
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wass
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wble
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wbls
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wcai
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wcfu
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wcmf
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wcms
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wcmu
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wcsa
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wcsb
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wcuu
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wdel
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wdus
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wdvi
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wdvu
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wfif
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \winl
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wior
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wlar
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wldl
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wlil
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wlos
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wlpi
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wmlf
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wmli
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wmon
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wngi
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wrck
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wrmi
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wrmu
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wror
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wsar
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wsbf
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wsbs
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wsbu
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wsdl
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wset
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wsil
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wsli
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wsri
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wsru
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wsts
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wtle
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wxor
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wzge
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wzlt
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wzrf
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wexg
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 38 \wlpb
-.if \n(84<\n(38 .nr 84 \n(38
-.84
-.rm 84
-.nr 38 6n
-.if \n(84<\n(38 .nr 84 \n(38
-.nr 85 0
-.nr 38 \wsP
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wmPo
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wmwPo
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wswP
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wsP
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wsP
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \w2
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wmPo
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \w-
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wmwPo
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wmwPo
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wsw
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wsP
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \w-
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wmwN
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wmwPo
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wsw
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wm
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wswN
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \ww2
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wswN
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wswN
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \w2
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \w2
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wsP
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wsw
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wsP
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wmwPo
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wwN2
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wswP
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wmPo
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wmwPo
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wmwPo
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wmwPo
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wswN
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \ww2
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wmwPo
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wmwPo
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wwN2
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wswN
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \w-
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wsP
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wsP
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wsP
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wsw
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wwN2
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we2
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we-
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we2
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we-
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we-
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we2
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we-
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we-
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we-
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we-
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we2
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we-
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we2
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we-
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we-
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wewN2
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we-
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we2
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we-
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we2
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wewN2
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we2
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we-
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wewP2
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wewP2
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we2
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we2
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we2
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we-
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we-
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we2
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we2
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we2
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we-
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we2
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we2
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we-
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we2
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we-
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wewP2
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we-
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wewN2
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we-
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we2
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we-
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we-
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we-
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we-
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we2
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we2
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we-
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \wesP
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 38 \we-
-.if \n(85<\n(38 .nr 85 \n(38
-.85
-.rm 85
-.nr 38 8n
-.if \n(85<\n(38 .nr 85 \n(38
-.nr 86 0
-.nr 38 \w1
-.if \n(86<\n(38 .nr 86 \n(38
-.nr 38 \w2
-.if \n(86<\n(38 .nr 86 \n(38
-.nr 38 \w1
-.if \n(86<\n(38 .nr 86 \n(38
-.nr 38 \w1
-.if \n(86<\n(38 .nr 86 \n(38
-.nr 38 \w1
-.if \n(86<\n(38 .nr 86 \n(38
-.nr 38 \w1
-.if \n(86<\n(38 .nr 86 \n(38
-.nr 38 \w28
-.if \n(86<\n(38 .nr 86 \n(38
-.nr 38 \w2
-.if \n(86<\n(38 .nr 86 \n(38
-.nr 38 \w1
-.if \n(86<\n(38 .nr 86 \n(38
-.nr 38 \w1
-.if \n(86<\n(38 .nr 86 \n(38
-.nr 38 \w1
-.if \n(86<\n(38 .nr 86 \n(38
-.nr 38 \w3
-.if \n(86<\n(38 .nr 86 \n(38
-.nr 38 \w1
-.if \n(86<\n(38 .nr 86 \n(38
-.nr 38 \w7
-.if \n(86<\n(38 .nr 86 \n(38
-.nr 38 \w1
-.if \n(86<\n(38 .nr 86 \n(38
-.nr 38 \w2
-.if \n(86<\n(38 .nr 86 \n(38
-.nr 38 \w1
-.if \n(86<\n(38 .nr 86 \n(38
-.nr 38 \w1
-.if \n(86<\n(38 .nr 86 \n(38
-.nr 38 \w1
-.if \n(86<\n(38 .nr 86 \n(38
-.nr 38 \w5
-.if \n(86<\n(38 .nr 86 \n(38
-.nr 38 \w1
-.if \n(86<\n(38 .nr 86 \n(38
-.nr 38 \w4
-.if \n(86<\n(38 .nr 86 \n(38
-.nr 38 \w1
-.if \n(86<\n(38 .nr 86 \n(38
-.nr 38 \w2
-.if \n(86<\n(38 .nr 86 \n(38
-.nr 38 \w1
-.if \n(86<\n(38 .nr 86 \n(38
-.nr 38 \w1
-.if \n(86<\n(38 .nr 86 \n(38
-.nr 38 \w2
-.if \n(86<\n(38 .nr 86 \n(38
-.nr 38 \w1
-.if \n(86<\n(38 .nr 86 \n(38
-.nr 38 \w2
-.if \n(86<\n(38 .nr 86 \n(38
-.nr 38 \w4
-.if \n(86<\n(38 .nr 86 \n(38
-.nr 38 \w1
-.if \n(86<\n(38 .nr 86 \n(38
-.nr 38 \w2
-.if \n(86<\n(38 .nr 86 \n(38
-.nr 38 \w1
-.if \n(86<\n(38 .nr 86 \n(38
-.nr 38 \w1
-.if \n(86<\n(38 .nr 86 \n(38
-.nr 38 \w1
-.if \n(86<\n(38 .nr 86 \n(38
-.nr 38 \w1
-.if \n(86<\n(38 .nr 86 \n(38
-.86
-.rm 86
-.nr 38 3n
-.if \n(86<\n(38 .nr 86 \n(38
-.nr 87 0
-.nr 38 \w35
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w39
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w43
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w50
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w53
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w56
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w59
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w64
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w94
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w97
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w101
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w104
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w107
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w110
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w113
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w118
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w121
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w130
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w133
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w137
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w140
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w144
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w148
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w151
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w153
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w156
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w166
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w169
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w175
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w188
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w191
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w196
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w200
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w203
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w207
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w210
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w215
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w219
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w225
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w233
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w236
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w239
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w243
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w246
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w249
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w253
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w2
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w5
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w8
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w11
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w14
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w17
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w20
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w23
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w26
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w29
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w32
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w35
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w38
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w41
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w44
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w47
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w50
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w53
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w56
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w59
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w62
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w65
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w68
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w71
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w74
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w77
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w80
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w83
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w86
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w89
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w92
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w95
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w98
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w101
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w104
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w107
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w110
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w113
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w116
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w119
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w122
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w125
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w128
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w131
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w134
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w137
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w140
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w143
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w146
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w149
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w152
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w155
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 38 \w158
-.if \n(87<\n(38 .nr 87 \n(38
-.87
-.rm 87
-.nr 38 6n
-.if \n(87<\n(38 .nr 87 \n(38
-.nr 88 0
-.nr 38 \wadi
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wadp
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wand
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wbeq
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wbgt
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wblt
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wbra
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wcal
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wcii
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wcmp
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wcsb
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wdel
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wdvi
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wine
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \winl
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wior
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wlal
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wlal
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wlar
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wlde
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wlfr
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wlil
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wlin
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wloc
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wloc
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wlof
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wloi
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wloi
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wlol
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wlol
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wmlf
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wret
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wsar
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wsdl
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wsil
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wste
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wstf
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wsti
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wstl
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wteq
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wtne
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wzer
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wzle
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wzne
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wzrl
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \waar
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wadf
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wads
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wadu
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wasp
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wbge
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wblm
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wblt
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wcal
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wciu
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wcmi
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wcms
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wcom
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wcsa
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wcuf
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wdee
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wdup
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wdvf
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wdvi
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wfef
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wfif
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \winn
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wior
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wldc
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wldl
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wlil
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wlos
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wlxa
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wmlf
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wmlu
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wngf
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wngi
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wrck
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wrmi
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wrol
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wror
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wsar
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wsbi
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wsbs
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wsde
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wsdl
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wsig
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wsim
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wslu
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wsri
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wsti
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wstr
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wtrp
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wzer
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wzgt
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wzne
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wzrl
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wexg
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 38 \wgto
-.if \n(88<\n(38 .nr 88 \n(38
-.88
-.rm 88
-.nr 38 6n
-.if \n(88<\n(38 .nr 88 \n(38
-.nr 89 0
-.nr 38 \wmwPo
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wsP
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wmwPo
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \w2
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wsP
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wsP
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wsN
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wsP
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \w-
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \w-
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wmwPo
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wswN
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wmwPo
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \ww2
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wswN
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wsP
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wP2
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wmN
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wmwPo
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wsw
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wmwPo
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wswP
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wsP
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wmP
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wsN
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \w2
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \w2
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wsP
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wmwP
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wswN
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wsP
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wmwP
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wmwPo
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wswN
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wswP
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wsw
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wsP
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wsP
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wmwP
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \w-
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \w-
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wsP
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wsP
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wsN
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wmwN
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we2
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we-
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we2
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we-
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wew2
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we2
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we2
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we2
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we2
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we-
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we2
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we-
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we2
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we-
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we-
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wew2
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we2
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we2
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we-
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we2
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we-
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we2
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we-
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we2
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wewN2
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wewN2
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we-
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we2
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we-
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we2
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we2
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we-
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we-
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we-
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we2
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we-
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we-
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we2
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we-
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we2
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wewN2
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we-
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we-
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we2
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we-
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we2
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wesP
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we-
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we2
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we2
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we2
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \wewP2
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we2
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 38 \we2
-.if \n(89<\n(38 .nr 89 \n(38
-.89
-.rm 89
-.nr 38 8n
-.if \n(89<\n(38 .nr 89 \n(38
-.nr 90 0
-.nr 38 \w2
-.if \n(90<\n(38 .nr 90 \n(38
-.nr 38 \w1
-.if \n(90<\n(38 .nr 90 \n(38
-.nr 38 \w1
-.if \n(90<\n(38 .nr 90 \n(38
-.nr 38 \w1
-.if \n(90<\n(38 .nr 90 \n(38
-.nr 38 \w1
-.if \n(90<\n(38 .nr 90 \n(38
-.nr 38 \w2
-.if \n(90<\n(38 .nr 90 \n(38
-.nr 38 \w1
-.if \n(90<\n(38 .nr 90 \n(38
-.nr 38 \w1
-.if \n(90<\n(38 .nr 90 \n(38
-.nr 38 \w1
-.if \n(90<\n(38 .nr 90 \n(38
-.nr 38 \w1
-.if \n(90<\n(38 .nr 90 \n(38
-.nr 38 \w1
-.if \n(90<\n(38 .nr 90 \n(38
-.nr 38 \w1
-.if \n(90<\n(38 .nr 90 \n(38
-.nr 38 \w1
-.if \n(90<\n(38 .nr 90 \n(38
-.nr 38 \w1
-.if \n(90<\n(38 .nr 90 \n(38
-.nr 38 \w1
-.if \n(90<\n(38 .nr 90 \n(38
-.nr 38 \w2
-.if \n(90<\n(38 .nr 90 \n(38
-.nr 38 \w1
-.if \n(90<\n(38 .nr 90 \n(38
-.nr 38 \w1
-.if \n(90<\n(38 .nr 90 \n(38
-.nr 38 \w34
-.if \n(90<\n(38 .nr 90 \n(38
-.nr 38 \w1
-.if \n(90<\n(38 .nr 90 \n(38
-.nr 38 \w1
-.if \n(90<\n(38 .nr 90 \n(38
-.nr 38 \w4
-.if \n(90<\n(38 .nr 90 \n(38
-.nr 38 \w1
-.if \n(90<\n(38 .nr 90 \n(38
-.nr 38 \w1
-.if \n(90<\n(38 .nr 90 \n(38
-.nr 38 \w2
-.if \n(90<\n(38 .nr 90 \n(38
-.nr 38 \w1
-.if \n(90<\n(38 .nr 90 \n(38
-.nr 38 \w1
-.if \n(90<\n(38 .nr 90 \n(38
-.nr 38 \w1
-.if \n(90<\n(38 .nr 90 \n(38
-.nr 38 \w3
-.if \n(90<\n(38 .nr 90 \n(38
-.nr 38 \w1
-.if \n(90<\n(38 .nr 90 \n(38
-.nr 38 \w1
-.if \n(90<\n(38 .nr 90 \n(38
-.nr 38 \w2
-.if \n(90<\n(38 .nr 90 \n(38
-.nr 38 \w1
-.if \n(90<\n(38 .nr 90 \n(38
-.nr 38 \w1
-.if \n(90<\n(38 .nr 90 \n(38
-.nr 38 \w1
-.if \n(90<\n(38 .nr 90 \n(38
-.nr 38 \w2
-.if \n(90<\n(38 .nr 90 \n(38
-.nr 38 \w1
-.if \n(90<\n(38 .nr 90 \n(38
-.90
-.rm 90
-.nr 38 3n
-.if \n(90<\n(38 .nr 90 \n(38
-.nr 91 0
-.nr 38 \w36
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w41
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w44
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w51
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w54
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w57
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w60
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w92
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w95
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w99
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w102
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w105
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w108
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w111
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w116
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w119
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w128
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w131
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w135
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w138
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w141
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w145
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w149
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w0
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w154
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w161
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w167
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w173
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w176
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w189
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w193
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w197
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w201
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w205
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w208
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w211
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w217
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w223
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w226
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w234
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w237
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w241
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w244
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w247
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w250
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w0
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w3
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w6
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w9
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w12
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w15
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w18
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w21
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w24
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w27
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w30
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w33
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w36
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w39
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w42
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w45
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w48
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w51
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w54
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w57
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w60
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w63
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w66
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w69
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w72
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w75
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w78
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w81
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w84
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w87
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w90
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w93
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w96
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w99
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w102
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w105
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w108
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w111
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w114
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w117
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w120
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w123
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w126
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w129
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w132
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w135
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w138
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w141
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w144
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w147
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w150
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w153
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w156
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 \w159
-.if \n(91<\n(38 .nr 91 \n(38
-.91
-.rm 91
-.nr 38 6n
-.if \n(91<\n(38 .nr 91 \n(38
-.nr 38 1n
-.nr 79 0
-.nr 40 \n(79+(0*\n(38)
-.nr 80 +\n(40
-.nr 41 \n(80+(3*\n(38)
-.nr 81 +\n(41
-.nr 42 \n(81+(3*\n(38)
-.nr 82 +\n(42
-.nr 43 \n(82+(3*\n(38)
-.nr 83 +\n(43
-.nr 44 \n(83+(14*\n(38)
-.nr 84 +\n(44
-.nr 45 \n(84+(3*\n(38)
-.nr 85 +\n(45
-.nr 46 \n(85+(3*\n(38)
-.nr 86 +\n(46
-.nr 47 \n(86+(3*\n(38)
-.nr 87 +\n(47
-.nr 48 \n(87+(14*\n(38)
-.nr 88 +\n(48
-.nr 49 \n(88+(3*\n(38)
-.nr 89 +\n(49
-.nr 50 \n(89+(3*\n(38)
-.nr 90 +\n(50
-.nr 51 \n(90+(3*\n(38)
-.nr 91 +\n(51
-.nr TW \n(91
-.if t .if (\n(TW+\n(.o)>7.65i .tm Table at line 103 file Input is too wide - \n(TW units
-.fc  
-.nr #T 0-1
-.nr #a 0-1
-.eo
-.de T#
-.ds #d .d
-.if \(ts\n(.z\(ts\(ts .ds #d nl
-.mk ##
-.nr ## -1v
-.ls 1
-.ls
-..
-.ec
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'aar\h'|\n(41u'mwPo\h'|\n(42u'1\h'|\n(43u'34\h'|\n(44u'adf\h'|\n(45u'sP\h'|\n(46u'1\h'|\n(47u'35\h'|\n(48u'adi\h'|\n(49u'mwPo\h'|\n(50u'2\h'|\n(51u'36
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'adp\h'|\n(41u'2\h'|\n(42u'\h'|\n(43u'38\h'|\n(44u'adp\h'|\n(45u'mPo\h'|\n(46u'2\h'|\n(47u'39\h'|\n(48u'adp\h'|\n(49u'sP\h'|\n(50u'1\h'|\n(51u'41
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'adp\h'|\n(41u'sN\h'|\n(42u'1\h'|\n(43u'42\h'|\n(44u'ads\h'|\n(45u'mwPo\h'|\n(46u'1\h'|\n(47u'43\h'|\n(48u'and\h'|\n(49u'mwPo\h'|\n(50u'1\h'|\n(51u'44
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'asp\h'|\n(41u'mwPo\h'|\n(42u'5\h'|\n(43u'45\h'|\n(44u'asp\h'|\n(45u'swP\h'|\n(46u'1\h'|\n(47u'50\h'|\n(48u'beq\h'|\n(49u'2\h'|\n(50u'\h'|\n(51u'51
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'beq\h'|\n(41u'sP\h'|\n(42u'1\h'|\n(43u'52\h'|\n(44u'bge\h'|\n(45u'sP\h'|\n(46u'1\h'|\n(47u'53\h'|\n(48u'bgt\h'|\n(49u'sP\h'|\n(50u'1\h'|\n(51u'54
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'ble\h'|\n(41u'sP\h'|\n(42u'1\h'|\n(43u'55\h'|\n(44u'blm\h'|\n(45u'sP\h'|\n(46u'1\h'|\n(47u'56\h'|\n(48u'blt\h'|\n(49u'sP\h'|\n(50u'1\h'|\n(51u'57
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'bne\h'|\n(41u'sP\h'|\n(42u'1\h'|\n(43u'58\h'|\n(44u'bra\h'|\n(45u'2\h'|\n(46u'\h'|\n(47u'59\h'|\n(48u'bra\h'|\n(49u'sN\h'|\n(50u'2\h'|\n(51u'60
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'bra\h'|\n(41u'sP\h'|\n(42u'2\h'|\n(43u'62\h'|\n(44u'cal\h'|\n(45u'mPo\h'|\n(46u'28\h'|\n(47u'64\h'|\n(48u'cal\h'|\n(49u'sP\h'|\n(50u'1\h'|\n(51u'92
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'cff\h'|\n(41u'-\h'|\n(42u'\h'|\n(43u'93\h'|\n(44u'cif\h'|\n(45u'-\h'|\n(46u'\h'|\n(47u'94\h'|\n(48u'cii\h'|\n(49u'-\h'|\n(50u'\h'|\n(51u'95
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'cmf\h'|\n(41u'sP\h'|\n(42u'1\h'|\n(43u'96\h'|\n(44u'cmi\h'|\n(45u'mwPo\h'|\n(46u'2\h'|\n(47u'97\h'|\n(48u'cmp\h'|\n(49u'-\h'|\n(50u'\h'|\n(51u'99
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'cms\h'|\n(41u'sP\h'|\n(42u'1\h'|\n(43u'100\h'|\n(44u'csa\h'|\n(45u'mwPo\h'|\n(46u'1\h'|\n(47u'101\h'|\n(48u'csb\h'|\n(49u'mwPo\h'|\n(50u'1\h'|\n(51u'102
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'dec\h'|\n(41u'-\h'|\n(42u'\h'|\n(43u'103\h'|\n(44u'dee\h'|\n(45u'sw\h'|\n(46u'1\h'|\n(47u'104\h'|\n(48u'del\h'|\n(49u'swN\h'|\n(50u'1\h'|\n(51u'105
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'dup\h'|\n(41u'mwPo\h'|\n(42u'1\h'|\n(43u'106\h'|\n(44u'dvf\h'|\n(45u'sP\h'|\n(46u'1\h'|\n(47u'107\h'|\n(48u'dvi\h'|\n(49u'mwPo\h'|\n(50u'1\h'|\n(51u'108
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'fil\h'|\n(41u'2\h'|\n(42u'\h'|\n(43u'109\h'|\n(44u'inc\h'|\n(45u'-\h'|\n(46u'\h'|\n(47u'110\h'|\n(48u'ine\h'|\n(49u'w2\h'|\n(50u'\h'|\n(51u'111
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'ine\h'|\n(41u'sw\h'|\n(42u'1\h'|\n(43u'112\h'|\n(44u'inl\h'|\n(45u'mwN\h'|\n(46u'3\h'|\n(47u'113\h'|\n(48u'inl\h'|\n(49u'swN\h'|\n(50u'1\h'|\n(51u'116
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'inn\h'|\n(41u'sP\h'|\n(42u'1\h'|\n(43u'117\h'|\n(44u'ior\h'|\n(45u'mwPo\h'|\n(46u'1\h'|\n(47u'118\h'|\n(48u'ior\h'|\n(49u'sP\h'|\n(50u'1\h'|\n(51u'119
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'lae\h'|\n(41u'2\h'|\n(42u'\h'|\n(43u'120\h'|\n(44u'lae\h'|\n(45u'sw\h'|\n(46u'7\h'|\n(47u'121\h'|\n(48u'lal\h'|\n(49u'P2\h'|\n(50u'\h'|\n(51u'128
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'lal\h'|\n(41u'N2\h'|\n(42u'\h'|\n(43u'129\h'|\n(44u'lal\h'|\n(45u'm\h'|\n(46u'1\h'|\n(47u'130\h'|\n(48u'lal\h'|\n(49u'mN\h'|\n(50u'1\h'|\n(51u'131
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'lal\h'|\n(41u'swP\h'|\n(42u'1\h'|\n(43u'132\h'|\n(44u'lal\h'|\n(45u'swN\h'|\n(46u'2\h'|\n(47u'133\h'|\n(48u'lar\h'|\n(49u'mwPo\h'|\n(50u'1\h'|\n(51u'135
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'ldc\h'|\n(41u'mP\h'|\n(42u'1\h'|\n(43u'136\h'|\n(44u'lde\h'|\n(45u'w2\h'|\n(46u'\h'|\n(47u'137\h'|\n(48u'lde\h'|\n(49u'sw\h'|\n(50u'1\h'|\n(51u'138
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'ldl\h'|\n(41u'mP\h'|\n(42u'1\h'|\n(43u'139\h'|\n(44u'ldl\h'|\n(45u'swN\h'|\n(46u'1\h'|\n(47u'140\h'|\n(48u'lfr\h'|\n(49u'mwPo\h'|\n(50u'2\h'|\n(51u'141
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'lfr\h'|\n(41u'sP\h'|\n(42u'1\h'|\n(43u'143\h'|\n(44u'lil\h'|\n(45u'swN\h'|\n(46u'1\h'|\n(47u'144\h'|\n(48u'lil\h'|\n(49u'swP\h'|\n(50u'1\h'|\n(51u'145
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'lil\h'|\n(41u'mwP\h'|\n(42u'2\h'|\n(43u'146\h'|\n(44u'lin\h'|\n(45u'2\h'|\n(46u'\h'|\n(47u'148\h'|\n(48u'lin\h'|\n(49u'sP\h'|\n(50u'1\h'|\n(51u'149
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'lni\h'|\n(41u'-\h'|\n(42u'\h'|\n(43u'150\h'|\n(44u'loc\h'|\n(45u'2\h'|\n(46u'\h'|\n(47u'151\h'|\n(48u'loc\h'|\n(49u'mP\h'|\n(50u'34\h'|\n(51u'0
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'loc\h'|\n(41u'mN\h'|\n(42u'1\h'|\n(43u'152\h'|\n(44u'loc\h'|\n(45u'sP\h'|\n(46u'1\h'|\n(47u'153\h'|\n(48u'loc\h'|\n(49u'sN\h'|\n(50u'1\h'|\n(51u'154
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'loe\h'|\n(41u'w2\h'|\n(42u'\h'|\n(43u'155\h'|\n(44u'loe\h'|\n(45u'sw\h'|\n(46u'5\h'|\n(47u'156\h'|\n(48u'lof\h'|\n(49u'2\h'|\n(50u'\h'|\n(51u'161
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'lof\h'|\n(41u'mwPo\h'|\n(42u'4\h'|\n(43u'162\h'|\n(44u'lof\h'|\n(45u'sP\h'|\n(46u'1\h'|\n(47u'166\h'|\n(48u'loi\h'|\n(49u'2\h'|\n(50u'\h'|\n(51u'167
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'loi\h'|\n(41u'mPo\h'|\n(42u'1\h'|\n(43u'168\h'|\n(44u'loi\h'|\n(45u'mwPo\h'|\n(46u'4\h'|\n(47u'169\h'|\n(48u'loi\h'|\n(49u'sP\h'|\n(50u'1\h'|\n(51u'173
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'lol\h'|\n(41u'wP2\h'|\n(42u'\h'|\n(43u'174\h'|\n(44u'lol\h'|\n(45u'wN2\h'|\n(46u'\h'|\n(47u'175\h'|\n(48u'lol\h'|\n(49u'mwP\h'|\n(50u'4\h'|\n(51u'176
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'lol\h'|\n(41u'mwN\h'|\n(42u'8\h'|\n(43u'180\h'|\n(44u'lol\h'|\n(45u'swP\h'|\n(46u'1\h'|\n(47u'188\h'|\n(48u'lol\h'|\n(49u'swN\h'|\n(50u'1\h'|\n(51u'189
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'lxa\h'|\n(41u'mPo\h'|\n(42u'1\h'|\n(43u'190\h'|\n(44u'lxl\h'|\n(45u'mPo\h'|\n(46u'2\h'|\n(47u'191\h'|\n(48u'mlf\h'|\n(49u'sP\h'|\n(50u'1\h'|\n(51u'193
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'mli\h'|\n(41u'mwPo\h'|\n(42u'2\h'|\n(43u'194\h'|\n(44u'rck\h'|\n(45u'mwPo\h'|\n(46u'1\h'|\n(47u'196\h'|\n(48u'ret\h'|\n(49u'mwP\h'|\n(50u'2\h'|\n(51u'197
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'ret\h'|\n(41u'sP\h'|\n(42u'1\h'|\n(43u'199\h'|\n(44u'rmi\h'|\n(45u'mwPo\h'|\n(46u'1\h'|\n(47u'200\h'|\n(48u'sar\h'|\n(49u'mwPo\h'|\n(50u'1\h'|\n(51u'201
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'sbf\h'|\n(41u'sP\h'|\n(42u'1\h'|\n(43u'202\h'|\n(44u'sbi\h'|\n(45u'mwPo\h'|\n(46u'2\h'|\n(47u'203\h'|\n(48u'sdl\h'|\n(49u'swN\h'|\n(50u'1\h'|\n(51u'205
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'set\h'|\n(41u'sP\h'|\n(42u'1\h'|\n(43u'206\h'|\n(44u'sil\h'|\n(45u'swN\h'|\n(46u'1\h'|\n(47u'207\h'|\n(48u'sil\h'|\n(49u'swP\h'|\n(50u'1\h'|\n(51u'208
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'sli\h'|\n(41u'mwPo\h'|\n(42u'1\h'|\n(43u'209\h'|\n(44u'ste\h'|\n(45u'w2\h'|\n(46u'\h'|\n(47u'210\h'|\n(48u'ste\h'|\n(49u'sw\h'|\n(50u'3\h'|\n(51u'211
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'stf\h'|\n(41u'2\h'|\n(42u'\h'|\n(43u'214\h'|\n(44u'stf\h'|\n(45u'mwPo\h'|\n(46u'2\h'|\n(47u'215\h'|\n(48u'stf\h'|\n(49u'sP\h'|\n(50u'1\h'|\n(51u'217
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'sti\h'|\n(41u'mPo\h'|\n(42u'1\h'|\n(43u'218\h'|\n(44u'sti\h'|\n(45u'mwPo\h'|\n(46u'4\h'|\n(47u'219\h'|\n(48u'sti\h'|\n(49u'sP\h'|\n(50u'1\h'|\n(51u'223
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'stl\h'|\n(41u'wP2\h'|\n(42u'\h'|\n(43u'224\h'|\n(44u'stl\h'|\n(45u'wN2\h'|\n(46u'\h'|\n(47u'225\h'|\n(48u'stl\h'|\n(49u'mwP\h'|\n(50u'2\h'|\n(51u'226
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'stl\h'|\n(41u'mwN\h'|\n(42u'5\h'|\n(43u'228\h'|\n(44u'stl\h'|\n(45u'swN\h'|\n(46u'1\h'|\n(47u'233\h'|\n(48u'teq\h'|\n(49u'-\h'|\n(50u'\h'|\n(51u'234
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'tgt\h'|\n(41u'-\h'|\n(42u'\h'|\n(43u'235\h'|\n(44u'tlt\h'|\n(45u'-\h'|\n(46u'\h'|\n(47u'236\h'|\n(48u'tne\h'|\n(49u'-\h'|\n(50u'\h'|\n(51u'237
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'zeq\h'|\n(41u'2\h'|\n(42u'\h'|\n(43u'238\h'|\n(44u'zeq\h'|\n(45u'sP\h'|\n(46u'2\h'|\n(47u'239\h'|\n(48u'zer\h'|\n(49u'sP\h'|\n(50u'1\h'|\n(51u'241
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'zge\h'|\n(41u'sP\h'|\n(42u'1\h'|\n(43u'242\h'|\n(44u'zgt\h'|\n(45u'sP\h'|\n(46u'1\h'|\n(47u'243\h'|\n(48u'zle\h'|\n(49u'sP\h'|\n(50u'1\h'|\n(51u'244
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'zlt\h'|\n(41u'sP\h'|\n(42u'1\h'|\n(43u'245\h'|\n(44u'zne\h'|\n(45u'sP\h'|\n(46u'1\h'|\n(47u'246\h'|\n(48u'zne\h'|\n(49u'sN\h'|\n(50u'1\h'|\n(51u'247
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'zre\h'|\n(41u'w2\h'|\n(42u'\h'|\n(43u'248\h'|\n(44u'zre\h'|\n(45u'sw\h'|\n(46u'1\h'|\n(47u'249\h'|\n(48u'zrl\h'|\n(49u'mwN\h'|\n(50u'2\h'|\n(51u'250
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'zrl\h'|\n(41u'swN\h'|\n(42u'1\h'|\n(43u'252\h'|\n(44u'zrl\h'|\n(45u'wN2\h'|\n(46u'\h'|\n(47u'253\h'|\n(48u'aar\h'|\n(49u'e2\h'|\n(50u'\h'|\n(51u'0
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'aar\h'|\n(41u'e-\h'|\n(42u'\h'|\n(43u'1\h'|\n(44u'adf\h'|\n(45u'e2\h'|\n(46u'\h'|\n(47u'2\h'|\n(48u'adf\h'|\n(49u'e-\h'|\n(50u'\h'|\n(51u'3
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'adi\h'|\n(41u'e2\h'|\n(42u'\h'|\n(43u'4\h'|\n(44u'adi\h'|\n(45u'e-\h'|\n(46u'\h'|\n(47u'5\h'|\n(48u'ads\h'|\n(49u'e2\h'|\n(50u'\h'|\n(51u'6
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'ads\h'|\n(41u'e-\h'|\n(42u'\h'|\n(43u'7\h'|\n(44u'adu\h'|\n(45u'e2\h'|\n(46u'\h'|\n(47u'8\h'|\n(48u'adu\h'|\n(49u'e-\h'|\n(50u'\h'|\n(51u'9
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'and\h'|\n(41u'e2\h'|\n(42u'\h'|\n(43u'10\h'|\n(44u'and\h'|\n(45u'e-\h'|\n(46u'\h'|\n(47u'11\h'|\n(48u'asp\h'|\n(49u'ew2\h'|\n(50u'\h'|\n(51u'12
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'ass\h'|\n(41u'e2\h'|\n(42u'\h'|\n(43u'13\h'|\n(44u'ass\h'|\n(45u'e-\h'|\n(46u'\h'|\n(47u'14\h'|\n(48u'bge\h'|\n(49u'e2\h'|\n(50u'\h'|\n(51u'15
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'bgt\h'|\n(41u'e2\h'|\n(42u'\h'|\n(43u'16\h'|\n(44u'ble\h'|\n(45u'e2\h'|\n(46u'\h'|\n(47u'17\h'|\n(48u'blm\h'|\n(49u'e2\h'|\n(50u'\h'|\n(51u'18
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'bls\h'|\n(41u'e2\h'|\n(42u'\h'|\n(43u'19\h'|\n(44u'bls\h'|\n(45u'e-\h'|\n(46u'\h'|\n(47u'20\h'|\n(48u'blt\h'|\n(49u'e2\h'|\n(50u'\h'|\n(51u'21
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'bne\h'|\n(41u'e2\h'|\n(42u'\h'|\n(43u'22\h'|\n(44u'cai\h'|\n(45u'e-\h'|\n(46u'\h'|\n(47u'23\h'|\n(48u'cal\h'|\n(49u'e2\h'|\n(50u'\h'|\n(51u'24
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'cfi\h'|\n(41u'e-\h'|\n(42u'\h'|\n(43u'25\h'|\n(44u'cfu\h'|\n(45u'e-\h'|\n(46u'\h'|\n(47u'26\h'|\n(48u'ciu\h'|\n(49u'e-\h'|\n(50u'\h'|\n(51u'27
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'cmf\h'|\n(41u'e2\h'|\n(42u'\h'|\n(43u'28\h'|\n(44u'cmf\h'|\n(45u'e-\h'|\n(46u'\h'|\n(47u'29\h'|\n(48u'cmi\h'|\n(49u'e2\h'|\n(50u'\h'|\n(51u'30
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'cmi\h'|\n(41u'e-\h'|\n(42u'\h'|\n(43u'31\h'|\n(44u'cms\h'|\n(45u'e2\h'|\n(46u'\h'|\n(47u'32\h'|\n(48u'cms\h'|\n(49u'e-\h'|\n(50u'\h'|\n(51u'33
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'cmu\h'|\n(41u'e2\h'|\n(42u'\h'|\n(43u'34\h'|\n(44u'cmu\h'|\n(45u'e-\h'|\n(46u'\h'|\n(47u'35\h'|\n(48u'com\h'|\n(49u'e2\h'|\n(50u'\h'|\n(51u'36
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'com\h'|\n(41u'e-\h'|\n(42u'\h'|\n(43u'37\h'|\n(44u'csa\h'|\n(45u'e2\h'|\n(46u'\h'|\n(47u'38\h'|\n(48u'csa\h'|\n(49u'e-\h'|\n(50u'\h'|\n(51u'39
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'csb\h'|\n(41u'e2\h'|\n(42u'\h'|\n(43u'40\h'|\n(44u'csb\h'|\n(45u'e-\h'|\n(46u'\h'|\n(47u'41\h'|\n(48u'cuf\h'|\n(49u'e-\h'|\n(50u'\h'|\n(51u'42
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'cui\h'|\n(41u'e-\h'|\n(42u'\h'|\n(43u'43\h'|\n(44u'cuu\h'|\n(45u'e-\h'|\n(46u'\h'|\n(47u'44\h'|\n(48u'dee\h'|\n(49u'ew2\h'|\n(50u'\h'|\n(51u'45
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'del\h'|\n(41u'ewP2\h'|\n(42u'\h'|\n(43u'46\h'|\n(44u'del\h'|\n(45u'ewN2\h'|\n(46u'\h'|\n(47u'47\h'|\n(48u'dup\h'|\n(49u'e2\h'|\n(50u'\h'|\n(51u'48
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'dus\h'|\n(41u'e2\h'|\n(42u'\h'|\n(43u'49\h'|\n(44u'dus\h'|\n(45u'e-\h'|\n(46u'\h'|\n(47u'50\h'|\n(48u'dvf\h'|\n(49u'e2\h'|\n(50u'\h'|\n(51u'51
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'dvf\h'|\n(41u'e-\h'|\n(42u'\h'|\n(43u'52\h'|\n(44u'dvi\h'|\n(45u'e2\h'|\n(46u'\h'|\n(47u'53\h'|\n(48u'dvi\h'|\n(49u'e-\h'|\n(50u'\h'|\n(51u'54
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'dvu\h'|\n(41u'e2\h'|\n(42u'\h'|\n(43u'55\h'|\n(44u'dvu\h'|\n(45u'e-\h'|\n(46u'\h'|\n(47u'56\h'|\n(48u'fef\h'|\n(49u'e2\h'|\n(50u'\h'|\n(51u'57
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'fef\h'|\n(41u'e-\h'|\n(42u'\h'|\n(43u'58\h'|\n(44u'fif\h'|\n(45u'e2\h'|\n(46u'\h'|\n(47u'59\h'|\n(48u'fif\h'|\n(49u'e-\h'|\n(50u'\h'|\n(51u'60
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'inl\h'|\n(41u'ewP2\h'|\n(42u'\h'|\n(43u'61\h'|\n(44u'inl\h'|\n(45u'ewN2\h'|\n(46u'\h'|\n(47u'62\h'|\n(48u'inn\h'|\n(49u'e2\h'|\n(50u'\h'|\n(51u'63
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'inn\h'|\n(41u'e-\h'|\n(42u'\h'|\n(43u'64\h'|\n(44u'ior\h'|\n(45u'e2\h'|\n(46u'\h'|\n(47u'65\h'|\n(48u'ior\h'|\n(49u'e-\h'|\n(50u'\h'|\n(51u'66
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'lar\h'|\n(41u'e2\h'|\n(42u'\h'|\n(43u'67\h'|\n(44u'lar\h'|\n(45u'e-\h'|\n(46u'\h'|\n(47u'68\h'|\n(48u'ldc\h'|\n(49u'e2\h'|\n(50u'\h'|\n(51u'69
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'ldf\h'|\n(41u'e2\h'|\n(42u'\h'|\n(43u'70\h'|\n(44u'ldl\h'|\n(45u'ewP2\h'|\n(46u'\h'|\n(47u'71\h'|\n(48u'ldl\h'|\n(49u'ewN2\h'|\n(50u'\h'|\n(51u'72
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'lfr\h'|\n(41u'e2\h'|\n(42u'\h'|\n(43u'73\h'|\n(44u'lil\h'|\n(45u'ewP2\h'|\n(46u'\h'|\n(47u'74\h'|\n(48u'lil\h'|\n(49u'ewN2\h'|\n(50u'\h'|\n(51u'75
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'lim\h'|\n(41u'e-\h'|\n(42u'\h'|\n(43u'76\h'|\n(44u'los\h'|\n(45u'e2\h'|\n(46u'\h'|\n(47u'77\h'|\n(48u'los\h'|\n(49u'e-\h'|\n(50u'\h'|\n(51u'78
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'lor\h'|\n(41u'esP\h'|\n(42u'1\h'|\n(43u'79\h'|\n(44u'lpi\h'|\n(45u'e2\h'|\n(46u'\h'|\n(47u'80\h'|\n(48u'lxa\h'|\n(49u'e2\h'|\n(50u'\h'|\n(51u'81
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'lxl\h'|\n(41u'e2\h'|\n(42u'\h'|\n(43u'82\h'|\n(44u'mlf\h'|\n(45u'e2\h'|\n(46u'\h'|\n(47u'83\h'|\n(48u'mlf\h'|\n(49u'e-\h'|\n(50u'\h'|\n(51u'84
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'mli\h'|\n(41u'e2\h'|\n(42u'\h'|\n(43u'85\h'|\n(44u'mli\h'|\n(45u'e-\h'|\n(46u'\h'|\n(47u'86\h'|\n(48u'mlu\h'|\n(49u'e2\h'|\n(50u'\h'|\n(51u'87
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'mlu\h'|\n(41u'e-\h'|\n(42u'\h'|\n(43u'88\h'|\n(44u'mon\h'|\n(45u'e-\h'|\n(46u'\h'|\n(47u'89\h'|\n(48u'ngf\h'|\n(49u'e2\h'|\n(50u'\h'|\n(51u'90
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'ngf\h'|\n(41u'e-\h'|\n(42u'\h'|\n(43u'91\h'|\n(44u'ngi\h'|\n(45u'e2\h'|\n(46u'\h'|\n(47u'92\h'|\n(48u'ngi\h'|\n(49u'e-\h'|\n(50u'\h'|\n(51u'93
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'nop\h'|\n(41u'e-\h'|\n(42u'\h'|\n(43u'94\h'|\n(44u'rck\h'|\n(45u'e2\h'|\n(46u'\h'|\n(47u'95\h'|\n(48u'rck\h'|\n(49u'e-\h'|\n(50u'\h'|\n(51u'96
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'ret\h'|\n(41u'e2\h'|\n(42u'\h'|\n(43u'97\h'|\n(44u'rmi\h'|\n(45u'e2\h'|\n(46u'\h'|\n(47u'98\h'|\n(48u'rmi\h'|\n(49u'e-\h'|\n(50u'\h'|\n(51u'99
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'rmu\h'|\n(41u'e2\h'|\n(42u'\h'|\n(43u'100\h'|\n(44u'rmu\h'|\n(45u'e-\h'|\n(46u'\h'|\n(47u'101\h'|\n(48u'rol\h'|\n(49u'e2\h'|\n(50u'\h'|\n(51u'102
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'rol\h'|\n(41u'e-\h'|\n(42u'\h'|\n(43u'103\h'|\n(44u'ror\h'|\n(45u'e2\h'|\n(46u'\h'|\n(47u'104\h'|\n(48u'ror\h'|\n(49u'e-\h'|\n(50u'\h'|\n(51u'105
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'rtt\h'|\n(41u'e-\h'|\n(42u'\h'|\n(43u'106\h'|\n(44u'sar\h'|\n(45u'e2\h'|\n(46u'\h'|\n(47u'107\h'|\n(48u'sar\h'|\n(49u'e-\h'|\n(50u'\h'|\n(51u'108
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'sbf\h'|\n(41u'e2\h'|\n(42u'\h'|\n(43u'109\h'|\n(44u'sbf\h'|\n(45u'e-\h'|\n(46u'\h'|\n(47u'110\h'|\n(48u'sbi\h'|\n(49u'e2\h'|\n(50u'\h'|\n(51u'111
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'sbi\h'|\n(41u'e-\h'|\n(42u'\h'|\n(43u'112\h'|\n(44u'sbs\h'|\n(45u'e2\h'|\n(46u'\h'|\n(47u'113\h'|\n(48u'sbs\h'|\n(49u'e-\h'|\n(50u'\h'|\n(51u'114
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'sbu\h'|\n(41u'e2\h'|\n(42u'\h'|\n(43u'115\h'|\n(44u'sbu\h'|\n(45u'e-\h'|\n(46u'\h'|\n(47u'116\h'|\n(48u'sde\h'|\n(49u'e2\h'|\n(50u'\h'|\n(51u'117
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'sdf\h'|\n(41u'e2\h'|\n(42u'\h'|\n(43u'118\h'|\n(44u'sdl\h'|\n(45u'ewP2\h'|\n(46u'\h'|\n(47u'119\h'|\n(48u'sdl\h'|\n(49u'ewN2\h'|\n(50u'\h'|\n(51u'120
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'set\h'|\n(41u'e2\h'|\n(42u'\h'|\n(43u'121\h'|\n(44u'set\h'|\n(45u'e-\h'|\n(46u'\h'|\n(47u'122\h'|\n(48u'sig\h'|\n(49u'e-\h'|\n(50u'\h'|\n(51u'123
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'sil\h'|\n(41u'ewP2\h'|\n(42u'\h'|\n(43u'124\h'|\n(44u'sil\h'|\n(45u'ewN2\h'|\n(46u'\h'|\n(47u'125\h'|\n(48u'sim\h'|\n(49u'e-\h'|\n(50u'\h'|\n(51u'126
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'sli\h'|\n(41u'e2\h'|\n(42u'\h'|\n(43u'127\h'|\n(44u'sli\h'|\n(45u'e-\h'|\n(46u'\h'|\n(47u'128\h'|\n(48u'slu\h'|\n(49u'e2\h'|\n(50u'\h'|\n(51u'129
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'slu\h'|\n(41u'e-\h'|\n(42u'\h'|\n(43u'130\h'|\n(44u'sri\h'|\n(45u'e2\h'|\n(46u'\h'|\n(47u'131\h'|\n(48u'sri\h'|\n(49u'e-\h'|\n(50u'\h'|\n(51u'132
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'sru\h'|\n(41u'e2\h'|\n(42u'\h'|\n(43u'133\h'|\n(44u'sru\h'|\n(45u'e-\h'|\n(46u'\h'|\n(47u'134\h'|\n(48u'sti\h'|\n(49u'e2\h'|\n(50u'\h'|\n(51u'135
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'sts\h'|\n(41u'e2\h'|\n(42u'\h'|\n(43u'136\h'|\n(44u'sts\h'|\n(45u'e-\h'|\n(46u'\h'|\n(47u'137\h'|\n(48u'str\h'|\n(49u'esP\h'|\n(50u'1\h'|\n(51u'138
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'tge\h'|\n(41u'e-\h'|\n(42u'\h'|\n(43u'139\h'|\n(44u'tle\h'|\n(45u'e-\h'|\n(46u'\h'|\n(47u'140\h'|\n(48u'trp\h'|\n(49u'e-\h'|\n(50u'\h'|\n(51u'141
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'xor\h'|\n(41u'e2\h'|\n(42u'\h'|\n(43u'142\h'|\n(44u'xor\h'|\n(45u'e-\h'|\n(46u'\h'|\n(47u'143\h'|\n(48u'zer\h'|\n(49u'e2\h'|\n(50u'\h'|\n(51u'144
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'zer\h'|\n(41u'e-\h'|\n(42u'\h'|\n(43u'145\h'|\n(44u'zge\h'|\n(45u'e2\h'|\n(46u'\h'|\n(47u'146\h'|\n(48u'zgt\h'|\n(49u'e2\h'|\n(50u'\h'|\n(51u'147
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'zle\h'|\n(41u'e2\h'|\n(42u'\h'|\n(43u'148\h'|\n(44u'zlt\h'|\n(45u'e2\h'|\n(46u'\h'|\n(47u'149\h'|\n(48u'zne\h'|\n(49u'e2\h'|\n(50u'\h'|\n(51u'150
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'zrf\h'|\n(41u'e2\h'|\n(42u'\h'|\n(43u'151\h'|\n(44u'zrf\h'|\n(45u'e-\h'|\n(46u'\h'|\n(47u'152\h'|\n(48u'zrl\h'|\n(49u'ewP2\h'|\n(50u'\h'|\n(51u'153
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'dch\h'|\n(41u'e-\h'|\n(42u'\h'|\n(43u'154\h'|\n(44u'exg\h'|\n(45u'esP\h'|\n(46u'1\h'|\n(47u'155\h'|\n(48u'exg\h'|\n(49u'e2\h'|\n(50u'\h'|\n(51u'156
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'exg\h'|\n(41u'e-\h'|\n(42u'\h'|\n(43u'157\h'|\n(44u'lpb\h'|\n(45u'e-\h'|\n(46u'\h'|\n(47u'158\h'|\n(48u'gto\h'|\n(49u'e2\h'|\n(50u'\h'|\n(51u'159
-.ta \n(80u \n(81u \n(82u \n(83u \n(84u \n(85u \n(86u \n(87u \n(88u \n(89u \n(90u \n(91u 
-.nr 31 \n(.f
-.nr 35 1m
-\&\h'|\n(40u'ldc\h'|\n(41u'4\h'|\n(42u'\h'|\n(43u'0\h'|\n(44u'\h'|\n(45u'\h'|\n(46u'\h'|\n(47u'\h'|\n(48u'\h'|\n(49u'\h'|\n(50u'\h'|\n(51u'
-.fc
-.nr T. 1
-.T# 1
-.35
-.TE
-.if \n-(b.=0 .nr c. \n(.c-\n(d.-102

+ 0 - 390
doc/em/mach.nr

@@ -1,390 +0,0 @@
-.BP
-.SN 10
-.S1 "EM MACHINE LANGUAGE"
-The EM machine language is designed to make program text compact
-and to make decoding easy.
-Compact program text has many advantages: programs execute faster,
-programs occupy less primary and secondary storage and loading
-programs into satellite processors is faster.
-The decoding of EM machine language is so simple,
-that it is feasible to use interpreters as long as EM hardware
-machines are not available.
-This chapter is irrelevant when back ends are used to
-produce executable target machine code.
-.S2 "Instruction encoding"
-A design goal of EM is to make the
-program text as compact as possible.
-Decoding must be easy, however.
-The encoding is fully byte oriented, without any small bit fields.
-There are 256 primary opcodes, two of which are an escape to
-two groups of 256 secondary opcodes each.
-.A
-EM instructions without arguments have a single opcode assigned,
-possibly escaped:
-.DS
-
-         |--------------|
-         |    opcode    |
-         |--------------|
-
-                or
-
-         |--------------|--------------|
-         |    escape    |     opcode   |
-         |--------------|--------------|
-
-.DE
-The encoding for instructions with an argument is more complex.
-Several instructions have an address from the global data area
-as argument.
-Other instructions have different opcodes for positive
-and negative arguments.
-.N 1
-There is always an opcode that takes the next two bytes as argument,
-high byte first:
-.DS
-
-         |--------------|--------------|--------------|
-         |    opcode    |    hibyte    |    lobyte    |
-         |--------------|--------------|--------------|
-
-                or
-
-         |--------------|--------------|--------------|--------------|
-         |    escape    |    opcode    |    hibyte    |    lobyte    |
-         |--------------|--------------|--------------|--------------|
-
-.DE
-.DS
-An extra escape is provided for instructions with four or eight byte arguments.
-
-  |--------------|--------------|--------------|   |--------------|
-  |    ESCAPE    |    opcode    |    hibyte    |...|    lobyte    |
-  |--------------|--------------|--------------|   |--------------|
-
-.DE
-For most instructions some argument values predominate.
-The most frequent combinations of instruction and argument
-will be encoded in a single byte, called a mini:
-.DS
-
-         |---------------|
-         |opcode+argument|  (mini)
-         |---------------|
-
-.DE
-The number of minis is restricted, because only
-254 primary opcodes are available.
-Many instructions have the bulk of their arguments
-fall in the range 0 to 255.
-Instructions that address global data have their arguments
-distributed over a wider range,
-but small values of the high byte are common.
-For all these cases there is another encoding
-that combines the instruction and the high byte of the argument
-into a single opcode.
-These opcodes are called shorties.
-Shorties may be escaped.
-.DS
-
-         |--------------|--------------|
-         | opcode+high  |    lobyte    |  (shortie)
-         |--------------|--------------|
-
-                or
-
-         |--------------|--------------|--------------|
-         |    escape    | opcode+high  |    lobyte    |
-         |--------------|--------------|--------------|
-
-.DE
-Escaped shorties are useless if the normal encoding has a primary opcode.
-Note that for some instruction-argument combinations
-several different encodings are available.
-It is the task of the assembler to select the shortest of these.
-The savings by these mini and shortie
-opcodes are considerable, about 55%.
-.P
-Further improvements are possible:
-the arguments of
-many instructions are a multiple of the wordsize.
-Some do also not allow zero as an argument.
-If these arguments are divided by the wordsize and,
-when zero is not allowed, then decremented by 1, more of them can
-be encoded as shortie or mini.
-The arguments of some other instructions
-rarely or never assume the value 0, but start at 1.
-The value 1 is then encoded as 0,
-2 as 1 and so on.
-.P
-Assigning opcodes to instructions by the assembler is completely
-table driven.
-For details see appendix B.
-.S2 "Procedure descriptors"
-The procedure identifiers used in the interpreter are indices
-into a table of procedure descriptors.
-Each descriptor contains:
-.IS 6
-.PS - 4
-.PT 1.
-the number of bytes to be reserved for locals at each
-invocation.
-.N
-This is a pointer-szied integer.
-.PT 2.
-the start address of the procedure
-.PE
-.IE
-.S2 "Load format"
-The EM machine language load format defines the interface between
-the EM assembler/loader and the EM machine itself.
-A load file consists of a header, the program text to be executed,
-a description of the global data area and the procedure descriptor table,
-in this order.
-All integers in the load file are presented with the
-least significant byte first.
-.P
-The header has two parts: the first half (eight 16-bit integers)
-aids in selecting
-the correct EM machine or interpreter.
-Some EM machines, for instance, may have hardware floating point
-instructions.
-.N
-The header entries are as follows (bit 0 is rightmost):
-.IS 2
-.VS 1 0
-.PS 1 4 "" :
-.PT
-magic number (07255)
-.PT
-flag bits with the following meaning:
-.PS - 7 "" :
-.PT bit 0
-TEST; test for integer overflow etc.
-.PT bit 1
-PROFILE; for each source line: count the number of memory
-cycles executed.
-.PT bit 2
-FLOW; for each source line: set a bit in a bit map table if
-instructions on that line are executed.
-.PT bit 3
-COUNT; for each source line: increment a counter if that line
-is entered.
-.PT bit 4
-REALS; set if a program uses floating point instructions.
-.PT bit 5
-EXTRA; more tests during compiler debugging.
-.PE
-.PT
-number of unresolved references.
-.PT
-version number; used to detect obsolete EM load files.
-.PT
-wordsize ; the number of bytes in each machine word.
-.PT
-pointer size ; the number of bytes available for addressing.
-.PT
-unused
-.PT
-unused
-.PE
-.IE
-The second part of the header (eight entries, of pointer size bytes each)
-describes the load file itself:
-.IS 2
-.PS 1 4 "" :
-.PT
-NTEXT; the program text size in bytes.
-.PT
-NDATA; the number of load-file descriptors (see below).
-.PT
-NPROC; the number of entries in the procedure descriptor table.
-.PT
-ENTRY; procedure number of the procedure to start with.
-.PT
-NLINE; the maximum source line number.
-.PT
-SZDATA; the address of the lowest uninitialized data byte.
-.PT
-unused
-.PT
-unused
-.PE
-.IE
-.P
-The program text consists of NTEXT bytes.
-NTEXT is always a multiple of the wordsize.
-The first byte of the program text is the
-first byte of the instruction address
-space, i.e. it has address 0.
-Pointers into the program text are found in the procedure descriptor
-table where relocation is simple and in the global data area.
-The initialization of the global data area allows easy
-relocation of pointers into both address spaces.
-.P
-The global data area is described by the NDATA descriptors.
-Each descriptor describes a number of consecutive words (of~wordsize)
-and consists of a sequence of bytes.
-While reading the descriptors from the load file, one can
-initialize the global data area from low to high addresses.
-The size of the initialized data area is given by SZDATA,
-this number can be used to check the initialization.
-.N
-The header of each descriptor consists of a byte, describing the type,
-and a count.
-The number of bytes used for this (unsigned) count depends on the
-type of the descriptor and
-is either a pointer-sized integer
-or one byte.
-The meaning of the count depends on the descriptor type.
-At load time an interpreter can
-perform any conversion deemed necessary, such as
-reordering bytes in integers
-and pointers and adding base addresses to pointers.
-.BP
-.A
-In the following pictures we show a graphical notation of the
-initializers.
-The leftmost rectangle represents the leading byte.
-.N 1
-.DS
-.PS - 4 " "
-Fields marked with
-.N 1
-.PT n
-contain a pointer-sized integer used as a count
-.PT m
-contain a one-byte integer used as a count
-.PT b
-contain a one-byte integer
-.PT w
-contain a wordsized integer
-.PT p
-contain a data or instruction pointer
-.PT s
-contain a null terminated ASCII string
-.PE 1
-.DE 0
-.VS 1 1
-.DS
-
-    -------------------
-    | 0 |      n      |           repeat last initialization n times
-    -------------------
-.DE
-.DS
-    ---------
-    | 1 | m |                     m uninitialized words
-    ---------
-.DE
-.DS
-               ____________
-              /    bytes   \e
-    -----------------   -----
-    | 2 | m | b | b |...| b |     m initialized bytes
-    -----------------   -----
-.DE
-.DS
-               _________
-              /  word   \e
-    -----------------------
-    | 3 | m |      w      |...    m initialized wordsized integers
-    -----------------------
-.DE
-.DS
-               _________
-              / pointer \e
-    -----------------------
-    | 4 | m |      p      |...    m initialized data pointers
-    -----------------------
-.DE
-.DS
-               _________
-              / pointer \e
-    -----------------------
-    | 5 | m |      p      |...    m initialized instruction pointers
-    -----------------------
-.DE
-.DS
-               ____________
-              /    bytes   \e
-    -------------------------
-    | 6 | m | b | b |...| b |     initialized integer of size m
-    -------------------------
-.DE
-.DS
-               ____________
-              /    bytes   \e
-    -------------------------
-    | 7 | m | b | b |...| b |     initialized unsigned of size m
-    -------------------------
-.DE
-.DS
-               ____________
-              /   string   \e
-    -------------------------
-    | 8 | m |        s      |     initialized float of size m
-    -------------------------
-.DE 3
-.PS - 8
-.PT type~0:
-If the last initialization initialized k bytes starting
-at address \fIa\fP, do the same initialization again n times,
-starting at \fIa\fP+k, \fIa\fP+2*k, .... \fIa\fP+n*k.
-This is the only descriptor whose starting byte
-is followed by an integer with the
-size of a
-pointer,
-in all other descriptors the first byte is followed by a one-byte count.
-This descriptor must be preceded by a descriptor of
-another type.
-.PT type~1:
-Reserve m words, not explicitly initialized (BSS and HOL).
-.PT type~2:
-The m bytes following the descriptor header are
-initializers for the next m bytes of the
-global data area.
-m is divisible by the wordsize.
-.PT type~3:
-The m words following the header are initializers for the next m words of the
-global data area.
-.PT type~4:
-The m data address space pointers following the header are
-initializers for the next
-m data pointers in the global data area.
-Interpreters that represent EM pointers by
-target machine addresses must relocate all data pointers.
-.PT type~5:
-The m instruction address space pointers following the header are
-initializers for the next
-m instruction pointers in the global data area.
-Interpreters that represent EM instruction pointers by
-target machine addresses must relocate these pointers.
-.PT type~6:
-The m bytes following the header form
-a signed integer number with a size of m bytes,
-which is an initializer for the next m bytes
-of the global data area.
-m is governed by the same restrictions as for
-transfer of objects to/from memory.
-.PT type~7:
-The m bytes following the header form
-an unsigned integer number with a size of m bytes,
-which is an initializer for the next m bytes
-of the global data area.
-m is governed by the same restrictions as for
-transfer of objects to/from memory.
-.PT type~8:
-The header is followed by an ASCII string, null terminated, to
-initialize, in global data,
-a floating point number with a size of m bytes.
-m is governed by the same restrictions as for
-transfer of objects to/from memory.
-The ASCII string contains the notation of a real as used in the
-Pascal language.
-.PE
-.P
-The NPROC procedure descriptors on the load file consist of
-an instruction space address (of~pointer~size) and
-an integer (of~pointer~size) specifying the number of bytes for
-locals.

+ 0 - 16
doc/em/macr.nr

@@ -1,16 +0,0 @@
-.so /usr/lib/tmac/tmac.kun
-.SS 6
-.RP
-.PL 12i 11i
-.LL 89
-.MS T E
-\!.TL '%'''
-.ME
-.MS T O
-\!.TL '''%'
-.ME
-.MS B
-.sp 1
-.ME
-.SM S1 B
-.SM S2 B

+ 0 - 245
doc/em/mapping.nr

@@ -1,245 +0,0 @@
-.SN 5
-.BP
-.S1 "MAPPING OF EM DATA MEMORY ONTO TARGET MACHINE MEMORY"
-The EM architecture is designed to be implemented
-on many existing and future machines.
-EM memory is highly fragmented to make
-adaptation to various memory architectures possible.
-Format and encoding of pointers is explicitly undefined.
-.P
-This chapter gives solutions to some of the
-anticipated problems.
-First, we describe a possible memory layout for machines
-with 64K bytes of address space.
-Here we use a member of the EM family with 2-byte word and pointer
-size.
-The most straightforward layout is shown in figure 2.
-.N 1
-.DS
-       65534 -> |-------------------------------|
-                |///////////////////////////////|
-                |//// unimplemented memory /////|
-                |///////////////////////////////|
-          ML -> |-------------------------------|
-                |                               |
-                |                               | <- LB
-                |     stack and local area      |
-                |                               |
-                |-------------------------------| <- SP
-                |///////////////////////////////|
-                |//////// inaccessible /////////|
-                |///////////////////////////////|
-                |-------------------------------| <- HP
-                |                               |
-                |           heap area           |
-                |                               |
-                |                               |
-          HB -> |-------------------------------|
-                |                               |
-                |       global data area        |
-                |                               |
-          EB -> |-------------------------------|
-                |                               |
-                |         program text          | <- PC
-                |                               |
-                |        ( and tables )         |
-                |                               |
-                |                               |
-          PB -> |-------------------------------|
-                |///////////////////////////////|
-                |////////// undefined //////////|
-                |///////////////////////////////|
-           0 -> |-------------------------------|
-
-           Figure 2.  Memory layout showing typical register
-           positions during execution of an EM program.
-.DE 2
-The base registers for the various memory pieces can be stored
-in target machine registers or memory.
-.IS
-.N 1
-.TS
-tab(;);
-l 1 l l l.
-PB;:;program base;points to the base of the instruction address space.
-EB;:;external base;points to the base of the data address space.
-HB;:;heap base;points to the base of the heap area.
-ML;:;memory limit;marks the high end of the addressable data space.
-.TE 1
-.IE
-The stack grows from high
-EM addresses to low EM addresses, and the heap the
-other way.
-The memory between SP and HP is not accessible,
-but may be allocated later to the stack or the heap if needed.
-The local data area is allocated starting at the high end of
-memory.
-.P
-Because EM address 0 is not mapped onto target
-address 0, a problem arises when pointers are used.
-If a program pushed a constant, say 6, onto the stack,
-and then tried to indirect through it,
-the wrong word would be fetched,
-because EM address 6 is mapped onto target address EB+6
-and not target address 6 itself.
-This particular problem is solved by explicitly declaring
-the format of a pointer to be undefined,
-so that using a constant as a pointer is completely illegal.
-However, the general problem of mapping pointers still exists.
-.P
-There are two possible solutions.
-In the first solution, EM pointers are represented
-in the target machine as true EM addresses,
-for example, a pointer to EM address 6 really is
-stored as a 6 in the target machine.
-This solution implies that every time a pointer is fetched
-EB must be added before referencing
-the target machine's memory.
-If the target machine has powerful indexing
-facilities, EB can be kept in a target machine register,
-and the relocation can indeed be done on
-every reference to the data address space
-at a modest cost in speed.
-.P
-The other solution consists of having EM pointers
-refer to the true target machine address.
-Thus the instruction LAE 6 (Load Address of External 6)
-would push the value of EB+6 onto the stack.
-When this approach is chosen, back ends must know
-how to offset from EB, to translate all
-instructions that manipulate EM addresses.
-However, the problem is not completely solved,
-because a front end may have to initialize a pointer
-in CON or ROM data to point to a global address.
-This pointer must also be relocated by the back end or the interpreter.
-.P
-Although the EM stack grows from high to low EM addresses,
-some machines have hardware PUSH and POP
-instructions that require the stack to grow upwards.
-If reasons of efficiency urge you to use these
-instructions, then EM
-can be implemented with the memory layout
-upside down, as shown in figure 3.
-This is possible because the pointer format is explicitly undefined.
-The first element of a word array will have a
-lower physical address than the second element.
-.N 2
-.DS
-          |                 |                    |                 |
-          |      EB=60      |                    |        ^        |
-          |                 |                    |        |        |
-          |-----------------|                    |-----------------|
-      105 |   45   |   44   | 104            214 |   41   |   40   | 215
-          |-----------------|                    |-----------------|
-      103 |   43   |   42   | 102            212 |   43   |   42   | 213
-          |-----------------|                    |-----------------|
-      101 |   41   |   40   | 100            210 |   45   |   44   | 211
-          |-----------------|                    |-----------------|
-          |        |        |                    |                 |
-          |        v        |                    |      EB=255     |
-          |                 |                    |                 |
-
-                Type A                                 Type B
-.sp 2
-              Figure 3. Two possible memory implementations.
-                 Numbers within the boxes are EM addresses.
-                 The other numbers are physical addresses.
-.DE 2
-.A 0 0
-So, we have two different EM memory implementations:
-.IS
-.PS - 4
-.PT A~-
-stack downwards
-.PT B~-
-stack upwards
-.PE
-.IE
-.P
-For each of these two possibilities we give the translation of
-the EM instructions to push the third byte of a global data
-block starting at EM address 40 onto the stack and to load the
-word at address 40.
-All translations assume a word and pointer size of two bytes.
-The target machine used is a PDP-11 augmented with push and pop instructions.
-Registers 'r0' and 'r1' are used and suffer from sign extension for byte
-transfers.
-Push $40 means push the constant 40, not word 40.
-.P
-The translation of the EM instructions depends on the pointer representation
-used.
-For each of the two solutions explained above the translation is given.
-.P
-First, the translation for the two implementations using EM addresses as
-pointer representation:
-.DS
-.TS
-tab(:), center;
-l s l s l s
-_ s _ s _ s
-l 2 l 6 l 2 l 6 l 2 l.
-EM:type A:type B
-
-
-LAE:40:push:$40:push:$40
-
-ADP:3:pop:r0:pop:r0
-::add:$3,r0:add:$3,r0
-::push:r0:push:r0
-
-LOI:1:pop:r0:pop:r0
-::-::neg:r0
-::clr:r1:clr:r1
-::bisb:eb(r0),r1:bisb:eb(r0),r1
-::push:r1:push:r1
-
-LOE:40:push:eb+40:push:eb-41
-.TE
-.DE
-.BP
-.P
-The translation for the two implementations, if the target machine address is
-used as pointer representation, is:
-.N 1
-.DS
-.TS
-tab(:), center;
-l s l s l s
-_ s _ s _ s
-l 2 l 6 l 2 l 6 l 2 l.
-EM:type A:type B
-
-
-LAE:40:push:$eb+40:push:$eb-40
-
-ADP:3:pop:r0:pop:r0
-::add:$3,r0:sub:$3,r0
-::push:r0:push:r0
-
-LOI:1:pop:r0:pop:r0
-::clr:r1:clr:r1
-::bisb:(r0),r1:bisb:(r0),r1
-::push:r1:push:r1
-
-LOE:40:push:eb+40:push:eb-41
-.TE
-.DE
-.P
-The translation presented above is not intended to be optimal.
-Most machines can handle these simple cases in one or two instructions.
-It demonstrates, however, the flexibility of the EM design.
-.P
-There are several possibilities to implement EM on machines with
-address spaces larger than 64k bytes.
-For EM with two byte pointers one could allocate instruction and
-data space each in a separate 64k piece of memory.
-EM pointers still have to fit in two bytes,
-but the base registers PB and EB may be loaded in hardware registers
-wider than 16 bits, if available.
-EM implementations can also make efficient use of a machine
-with separate instruction and data space.
-.P
-EM with 32 bit pointers allows one to make use of machines
-with large address spaces.
-In a virtual, segmented memory system one could use a separate
-segment for each fragment.

+ 0 - 80
doc/em/mem.nr

@@ -1,80 +0,0 @@
-.BP
-.SN 2
-.S1 MEMORY
-The EM machine has two distinct address spaces,
-one for instructions and one for data.
-The data space is divided up into 8-bit bytes.
-The smallest addressable unit is a byte.
-Bytes are numbered consecutively from 0 to some maximum.
-All sizes in EM are expressed in bytes.
-.P
-Some EM instructions can transfer objects containing several bytes
-to and/or from memory.
-The size of all objects larger than a word must be a multiple of
-the wordsize.
-The size of all objects smaller than a word must be a divisor
-of the wordsize.
-For example: if the wordsize is 2 bytes, objects of the sizes 1,
-2, 4, 6,... are allowed.
-The address of such an object is the lowest address of all bytes it contains.
-For objects smaller than the wordsize, the
-address must be a multiple of the object size.
-For all other objects the address must be a multiple of the
-wordsize.
-For example, if an instruction transfers a 4-byte object to memory at
-location \fIm\fP and the wordsize is 2,
-\fIm\fP must be a multiple of 2 and the bytes at
-locations \fIm\fP, \fIm\fP\|+\|1,\fIm\fP\|+\|2 and
-\fIm\fP\|+\|3 are overwritten.
-.P
-The size of almost all objects in EM
-is an integral number of words.
-Only two operations are allowed on
-objects whose size is a divisor of the wordsize:
-push it onto the stack and pop it from the stack.
-The addressing of these objects in memory is always indirect.
-If such a small object is pushed onto the stack
-it is assumed to be a small integer and stored
-in the least significant part of a word.
-The rest of the word is cleared to zero,
-although
-EM provides a way to sign-extend a small integer.
-Popping a small object from the stack removes a word
-from the stack, stores the least significant byte(s)
-of this word in memory and discards the rest of the word.
-.P
-The format of pointers into both address spaces is explicitly undefined.
-The size of a pointer, however, is fixed for a member of EM, so that
-the compiler writer knows how much storage to allocate for a pointer.
-.P
-A minor problem is raised by the undefined pointer format.
-Some languages, notably Pascal, require a special,
-otherwise illegal, pointer value to represent the nil pointer.
-The current Pascal-VU compiler uses the
-integer value 0 as nil pointer.
-This value is also used by many C programs as a normally impossible address.
-A better solution would be to have a special
-instruction loading an illegal pointer value,
-but it is hard to imagine an implementation
-for which the current solution is inadequate,
-especially because the first word in the EM data space
-is special and probably not the target of any pointer.
-.P
-The next two chapters describe the EM memory
-in more detail.
-One describes the instruction address space,
-the other the data address space.
-.P
-A design goal of EM has been to allow
-its implementation on a wide range of existing machines,
-as well as allowing a new one to be built in hardware.
-To this extent we have tried to minimize the demands
-of EM on the memory structure of the target machine.
-Therefore, apart from the logical partitioning,
-EM memory is divided into 'fragments'.
-A fragment consists of consecutive machine
-words and has a base address and a size.
-Pointer arithmetic is only defined within a fragment.
-The only exception to this rule is comparison with the null
-pointer.
-All fragments must be word aligned.

+ 0 - 5
doc/em/print

@@ -1,5 +0,0 @@
-
-case $# in
-1)      make "$1".t ; ntlp "$1".t^lpr ;;
-*)      echo $0 heeft een argument nodig ;;
-esac

+ 0 - 4
doc/em/show

@@ -1,4 +0,0 @@
-case $# in
-1)      make $1.t ; ntout $1.t ;;
-*)      echo $0 heeft een argument nodig ;;
-esac

+ 0 - 38
doc/em/title.nr

@@ -1,38 +0,0 @@
-.po 0
-.TP 1
-.ll 79
-.sp 15
-.ce 4
-DESCRIPTION OF A MACHINE
-ARCHITECTURE FOR  USE WITH
-BLOCK  STRUCTURED  LANGUAGES
-.sp 6
-.ce 4
-Andrew S. Tanenbaum
-Hans  van  Staveren
-Ed G. Keizer
-Johan  W. Stevenson\v'-0.5m'*\v'0.5m'
-.sp 2
-.ce
-August 1983
-.sp 2
-.ce
-Informatica Rapport IR-81
-.sp 13
-Abstract
-.sp 2
-.ti +5
-EM is a family of intermediate languages
-designed for producing portable compilers.
-A program called
-.B front end
-translates source programs to EM.
-Another program,
-.B back
-.BW end ,
-translates EM to the assembly language of the target machine.
-Alternatively, the EM program can be assembled to a highly
-efficient binary format for interpretation.
-This document describes the EM languages in detail.
-.sp 4
-\v'-0.5m'*\v'0.5m' Present affiliation: NV Philips, Eindhoven

+ 0 - 130
doc/em/types.nr

@@ -1,130 +0,0 @@
-.SN 6
-.BP
-.S1 "TYPE REPRESENTATIONS"
-The representations used for typed objects are not precisely
-specified by EM.
-Sometimes we only specify that a typed object occupies a
-certain amount of space and state no further restrictions.
-If one wants to have a different representation of the value of
-an object on the stack one has to use a convert instruction
-in most cases.
-We do specify some relations between the representations of
-types.
-This allows some intermixed use of operators for different types
-on the same object(s).
-For example, the instruction ZER pushes signed and
-unsigned integers with the value zero and empty sets.
-ZER has as only argument the size of the object.
-.A
-The representation of floating point numbers is a good example,
-it allows widely varying implementations.
-The only ways to create floating point numbers are via
-initialization and via conversions from integer numbers.
-Only by using conversions to integers and comparing
-two floating point numbers with each other, can these numbers
-be converted to human readable output.
-Implementations may use base 10, base 2 or any other
-base for exponents, and have freedom in choosing the range of
-exponent and mantissa.
-.A
-Other types are more precisely described.
-In the following paragraphs a description will be given of the
-restrictions imposed on the representation of the types used.
-A number \fBn\fP used in these paragraphs indicates the size of
-the object in \fIbits\fP.
-.S2 "Unsigned integers"
-The range of unsigned integers is 0..2\v'-0.5m'\fBn\fP\v'0.5m'-1.
-A binary representation is assumed.
-The order of the bits within an object is knowingly left
-unspecified.
-Discussing bit order within each 8-bit byte is academic,
-so the only real freedom of this specification lies in the byte
-order.
-We really do not care whether an implementation of a 4-byte
-integer has its bytes in a particular order of significance.
-This of course means that some sequences of instructions have
-unpredictable effects.
-For example:
-.DS
-   LOC 258 ; STL 0 ; LAL 0 ; LOI 1      ( wordsize >=2 )
-.DE
-The value on the stack after executing this sequence
-can be anything,
-but will most likely be 1 or 2.
-.A
-Conversion between unsigned integers of different sizes have to
-be done with explicit convert instructions.
-One cannot simply pad an unsigned integer with zero's at either end
-and expect a correct result.
-.A
-We assume existence of at least single word unsigned arithmetic
-in any implementation.
-.S2 "Signed Integers"
-The range of signed integers is -2\v'-0.5m'\fBn\fP-1\v'0.5m'~..~2\v'-0.5m'\fBn\fP-1\v'0.5m'-1,
-in other words the range of signed integers of \fBn\fP bits
-using two's complement arithmetic.
-The representation is the same as for unsigned integers except
-the range 2\v'-0.5m'\fBn\fP-1\v'0.5m'~..~2\v'-0.5m'\fBn\fP\v'0.5m'-1 is mapped on the
-range -2\v'-0.5m'\fBn\fP-1\v'0.5m'~..~-1.
-In other words, the most significant bit is used as sign bit.
-The convert instructions between signed and unsigned integers
-of the same size can be used to catch errors.
-.A
-The value -2\v'-0.5m'\fBn\fP-1\v'0.5m' is used for undefined
-signed integers.
-EM implementations should trap when this value is used in an
-operation on signed integers.
-The instruction mask, accessed with SIM and LIM -~see chapter 9~- ,
-can be used to disable such traps.
-.A
-We assume existence of at least single word signed arithmetic
-in any implementation.
-.BP
-.S2 "Floating point values"
-Floating point values must have a signed mantissa and a signed
-exponent.
-Although no base is specified, base 2 is the normal choice,
-because the FEF instruction pushes the exponent in base 2.
-.A
-The implementation of floating point arithmetic is optional.
-The compilers currently in use have runtime parameters for the
-size of the floating point values they should use.
-Common choices are 4 and/or 8 bytes.
-.S2 Pointers
-EM has two kinds of pointers: for instruction and for data
-space.
-Each kind can only be used for its own space, conversion between
-these two subtypes is impossible.
-We assume that pointers have a range from 0 upwards.
-Any implementation may have holes in the pointer range between
-fragments.
-One can of course not expect to be able to address two megabyte
-of memory using a 2-byte pointer.
-Normally, a 2-byte pointer allows up to 65536 bytes of
-addressable memory.
-.A
-Pointer representation has one restriction.
-The pointer with the same representation as the integer zero of
-the same size should be invalid.
-Some languages and/or runtime systems represent the nil
-pointer as zero.
-.S2 "Bit sets"
-All bit sets of size \fBn\fP are subsets of the set
-{~i~|~i>=0,~i<\fBn\fP~}.
-A bit set contains a bit for each element showing its
-presence or absence.
-Bit sets are subdivided into words.
-The word with the lowest EM address governs the subset
-{~i~|~i>=0,~i<\fBm\fP~}, where \fBm\fP is the number of bits in
-a word.
-The next higher words each govern the next higher \fBm\fP set elements.
-The relation between a set with size of
-a word and an unsigned integer word is that
-the value of the unsigned integer is the summation of the
-2\v'-0.5m'i\v'0.5m' where i is in the set.
-.A
-Example: a 2-word bit set (wordsize 2) containing the
-elements 1, 6, 8, 15, 18, 21, 27 and 28 is composed of two
-integers, e.g. at addresses 40 and 42.
-The word at 40 contains the value 33090 (or~-32446),
-the word at 42 contains the value 6180.

+ 0 - 621
doc/install.doc

@@ -1,621 +0,0 @@
-.\" $Header$
-.nr LL 7.5i
-.nr PD 1v
-.TL
-Amsterdam Compiler Kit installation guide
-.AU
-Ed Keizer
-.AI
-Wiskundig Seminarium
-Vrije Universiteit
-Amsterdam
-.NH
-Introduction
-.PP
-This document
-describes the process of installing Amsterdam Compiler Kit.
-It depends on your combination of hard- and software how
-hard it will be to install the kit.
-This description is intended for a PDP 11/44 running
-.UX
-Version 7.
-Installation on other PDP 11's should be easy, as long
-as they have separate instruction and data space.
-Installation on machine's without this feature, like PDP 11/34,
-PDP 11/60 requires extensive surgery on some programs and is
-thought of as impossible.
-See chapter 6 for installation on other systems.
-.NH
-Restoring tree
-.PP
-The process of installing Amsterdam Compiler Kit is quite simple.
-It is important that the original Amsterdam Compiler Kit
-distribution tree structure is restored.
-Proceed as follows
-.IP "  -" 10
-Create a directory, for example /usr/em, on a device
-with at least 20000 blocks left.
-.IP "  -"
-Change to that directory (cd ...); it will be the working directory.
-.IP "  -"
-Extract all files from the distribution medium, for instance
-magtape:
-\fBtar x\fP.
-.IP "  -"
-Keep a copy of the original distribution to be able to repeat the process
-of installation in case of disasters.
-This copy is also useful as a reference point for diff-listings.
-.LP
-The directories in the tree contain the following information:
-.nr PD 1v
-.IP "lib" 14
-.br
-almost all binaries and shell files used by commands and
-library em_data.a from misc/data
-.IP "lib/ack"
-.br
-The command descriptor files used by the program ack.
-.nr PD 0
-.IP "bin"
-.br
-the few utilities that knot things together
-.IP "etc"
-.br
-The MAIN description of EM sits here.
-contains files (e.g. em_table) describing
-the opcodes and pseudos in use,
-the operands allowed, effect in stack etc. etc.
-Make in this directory creates most of the files in h
-.IP "include"
-.br
-More or less system independent include files needed by modules
-in the C library from lang/cem/libcc.
-Especially needed for "stdio".
-.IP "h"
-.br
-The #include files for:
-.nf
-as_spec.h    Used by EM assembler and interpreters.
-em_abs.h     Contains trap numbers and address for lin and fil
-em_flag.h    Definition of bits in array em_flag in lib/em_data.a
-             Describes parameters effect on flow of instructions
-em_mes.h     Definition of names for mes pseudo numbers
-em_mnem.h    instruction => compact mapping.
-em_pseu.h    pseudo instruction => compact mapping
-em_ptyp.h    Useful for compact code reading/writing,
-             defines classes of parameters
-em_spec.h    Definition of constants used in compact code
-local.h      Various definitions for local versions
-pc_err.h     Definitions of error numbers in Pascal
-pc_file.h    Macro's used in file handling in Pascal
-em_path.h    Pathnames used by \fIack\fP, intended
-             for all utilities
-pc_size.h    Sizes of objects used by Pascal compiler and
-             run-time system.
-em_reg.h     Definition of names for register types.
-.IP "doc"
-.br
-Documentation
-.nf
-cg.doc          Use and internal specification of the backend.
-.br
-regadd.doc      Update for cg.doc concerning register variables
-.br
-regadd.doc      Description of steps to add register variables.
-.br
-ack.doc         Layout of description files needed for each machine.
-.br
-cref.doc        C reference manual, addendum
-.br
-install.doc     Ack Installation Guide
-.br
-pcref.doc       Pascal reference manual, addendum
-.br
-peep.doc        Description of the peephole optimizer
-.br
-em.doc          EM reference manual
-.br
-toolkit.doc     A general overview of the toolkit
-.br
-v7bugs.doc      Bugs in the standard V7 system
-.br
-val.doc         Pascal validation suite version 3 report
-.nf
-.IP "doc/em.doc"
-.br
-The EM-manual IR-81
-.IP "doc/em.doc/int"
-.br
-The EM interpreter written in pascal
-.IP "mkun"
-.br
-The PUBMAC macro package for nroff/troff from the Katholieke Universiteit at
-Nijmegen.
-It is used for the EM reference manual,
-the Makefile installs the macro package in
-/usr/lib/tmac/tmac.mkun*.
-This package is in the public domain.
-.IP "mach"
-.br
-just there to group the directories for all machines
-these directories have sub-directories named:
-.nf
-  as      the assembler ( *.s + libraries => a.out )
-  cg      the new backend   ( *.m => *.s )
-  lib     the libraries for all run-time systems
-          these libraries are used by the assembler.
-  libpc   Used to create Pascal run-time system in 'lib'
-  libcc   Used to create C run-time system in 'lib'
-  libem   Sources for EM runtime system, result sits in 'lib'
-  test    Various tests
-  dl      Down-load programs
-  int     Source for an interpreter
-available are:
-    PMDS II 68000, wordsize 2, ptrsize 4
-        mach/m68k2
-        mach/m68k2/as
-        mach/m68k2/cg
-        mach/m68k2/libem
-        mach/m68k2/lib
-        mach/m68k2/dl
-        mach/m68k2/libpc
-        mach/m68k2/libcc
-        mach/m68k2/libsys
-    bare 6809
-        mach/6809
-        mach/6809/as
-    8080, wordsize 2, ptrsize 2
-        mach/8080
-        mach/8080/as
-        mach/8080/test
-        mach/8080/libcc
-        mach/8080/lib
-   bare 8086, wordsize 2, ptrsize 2
-        mach/i86
-        mach/i86/as
-        mach/i86/lib
-        mach/i86/libcc
-        mach/i86/dl
-        mach/i86/libem
-        mach/i86/libpc
-        mach/i86/saio  (library for stand-alone EM on 86/12A )
-    pdp 11, UNIX/V7, wordsize 2, ptrsize 2
-        mach/pdp
-        mach/pdp/test
-        mach/pdp/libem
-        mach/pdp/lib
-        mach/pdp/libcc
-        mach/pdp/libpc
-        mach/pdp/cg
-        mach/pdp/int         -PDP 11/44 EM interpreter
-    vax 780, UNIX V7, wordsize 4, ptrsize 4
-        mach/vax4
-        mach/vax4/cg
-        mach/vax4/lib
-        mach/vax4/libcc
-        mach/vax4/libem
-        mach/vax4/libpc
-    z80, CP/M, wordsize 2, ptrsize 2
-        mach/z80
-        mach/z80/as
-        mach/z80/libem
-        mach/z80/lib
-        mach/z80/libcc
-        mach/z80/libpc
-        mach/z80/int         -Z80 EM interpreter
-    z80, nascom
-        mach/z80a
-        mach/z80a/dl
-    vax 11/780, Berkeley UNIX, wordsize 2, ptrsize 4
-        mach/vax2
-        mach/vax2/cg
-        mach/vax2/lib
-        mach/vax2/libpc
-        mach/vax2/libem
-    bare 6500, wordsize 2, ptrsize 2
-        mach/6500
-        mach/6500/as
-        mach/6500/dl
-        mach/6500/libem
-        mach/6500/lib
-    bare 6800, wordsize 2, ptrsize 2
-        mach/6800
-        mach/6800/as
-    EM virtual machine code, wordsize 2, ptrsize 2
-        mach/int
-        mach/int/libcc
-        mach/int/libpc
-        mach/int/lib
-        mach/int/test
-    The directory proto contains files used by most machines.
-    e.g. makefiles for libraries for C and Pascal
-        mach/proto
-        mach/proto/libg
-.fi
-.IP "emtest"
-.br
-Contains prototype of em test set.
-.IP "man"
-.br
-Man files for various utilities
-.IP "lang"
-.br
-just there to group the directories for all front-ends
-.IP "lang/pc"
-.br
-Pascal front-end
-.IP "lang/pc/libpc"
-.br
-Source of Pascal run-time system ( in EM or C )
-.IP "lang/pc/test"
-.br
-Some test programs written in Pascal
-.IP "lang/pc/pem"
-.br
-The compiler proper
-.IP "lang/cem"
-.br
-C front-end
-.IP "lang/cem/libcc"
-.br
-Directories with sources of C runtime system, libraries (in EM or C)
-.IP "lang/cem/libcc/gen"
-.br
-Sources for routines in chapter III of UNIX programmers manual,
-excluding STDIO
-.IP "lang/cem/libcc/stdio"
-.br
-STDIO sources
-.IP "lang/cem/libcc/mon"
-.br
-Sources for routines in chapter II, written in EM
-.IP "lang/cem/comp"
-.br
-The compiler proper
-.IP "lang/cem/ctest"
-.br
-C test set
-.IP "lang/cem/ctest/cterr"
-.br
-Programs developed for pinpointing previous errors
-.IP "lang/cem/ctest/ct*"
-.br
-The test programs.
-.IP "util"
-.br
-Contains directories with various utilities
-.IP "util/opt"
-.br
-EM peephole optimizer (*.k => *.m)
-.IP "util/misc"
-.br
-Decode (*.[km] => *.e) + encode (*.e => *.k)
-.IP "util/data"
-.br
-The C-code for `lib/em_data.a`
-These sources are created by the Makefile in `etc`
-.IP "util/ass"
-.br
-The EM assembler ( *.[km] + libraries => e.out )
-.IP "util/arch"
-.br
-The archiver to be used for ALL EM utilities
-.IP "util/cgg"
-.br
-A program needed for compiling backends.
-.IP "util/cpp"
-.br
-The V7 C preprocessor.
-.LP
-All pathnames mentioned in the text of this document are relative to the
-working directory, unless they start with '/'.
-.PP
-The person doing the installation needs permission to write in the
-directories of the Amsterdam Compiler Kit distribution tree.
-Preferably you should log in as sys (uid=3,gid=0).
-.NH
-Pathnames
-.PP
-Absolute pathnames are concentrated in "h/em_path.h".
-Only the pascal runtime system and the utility \fIack\fP use
-absolute pathnames to access files in the kit.
-The tree is distributed with /usr/em as the working
-directory.
-The definition of EM_DIR in em_path.h should be altered to
-specify the root
-directory for the Compiler Kit distribution on your system.
-Em_path.h also specifies which directory should be used for
-temporary files.
-Most programs from the kit do indeed use that directory
-although some remain stubborn and use /tmp or /usr/tmp.
-.LP
-The shape of the tree should not be altered lightly because
-most Makefiles and the
-utility \fIack\fP know the shape of the ACK tree.
-All pathnames in all Makefiles are relative, that is do not
-have "/" as the first character.
-The knowledge of the utility \fIack\fP about the shape of the tree is
-concentrated in the files in the directory lib/ack.
-.NH
-Commands
-.PP
-The kit is distributed with all available commands in the bin
-directory.
-The commands distributed are:
-.IP "\fIack\fP, \fIacc\fP, \fIapc\fP and their links"
-.br
-They are used to compile the Pascal, C, etc... programs.
-.IP \fIarch\fP
-.br
-The archiver used for the EM- and universal assembler.
-.IP "\fIem\fP and \fIeminform\fP"
-.br
-The EM interpretator for the PDP-11 and the program to unravel
-its post-mortem information.
-.LP
-We currently make the kit available to our users by telling
-them that they should include the bin directory of the kit in
-their PATH shell variable.
-The programs will still work when moved to a different
-directory.
-The copying should preferably be done with tar, since links are
-heavily used.
-Renaming of the programs linked to \fIack\fP will not always
-produce the desired result.
-This program uses its call name as an argument.
-Any call name not being \fIcc\fP, \fIacc\fP, \fIpc\fP or \fIapc\fP will be
-interpreted as the name of a 'machine description' and the
-program will try to find a description file with that name.
-All recompilations will only touch the utilities in the bin
-directory, not your own copies.
-.NH
-Options
-.PP
-There is one important option in h/local.h.
-The utility \fIack\fP uses a default machine name when called
-as \fIacc\fP, \fIcc\fP, \fIapc\fP, \fIpc\fP or \fIack\fP.
-The machine name used for default is determined by the
-definition of ACKM in h/local.h.
-The current definition is \fIpdp\fP.
-.PP
-The distribution is tailored to one specific opreating system per CPU type.
-For some of these  CPU's it is possible to tailor the distribution to another
-operating system.
-The steps to be taken are described in READ_ME (or README) files in the
-subdirectories of the directory in EM_DIR/mach for that particular machine.
-For example: The vax2 distribution is tailoerd to BSD4.1, but has #define's
-for BSD4.1c and BSD4.2.
-For the names and places of these define's look in EM_DIR/mach/vax2/cg and
-EM_DIR/mach/vax2/libem.
-.NH
-Recompilation
-.PP
-The kit comes with binaries in the directories \fBbin\fP and
-\fBlib\fP.
-Some directories among mach/*/lib contain archives with object files,
-notably mach/pdp/lib.
-The binaries and object files are for a PDP 11/44 with floating
-point running UNIX V7.
-.PP
-Almost all directories contain a "Makefile" or a shell command file called
-"make".
-Apart from commands applying to that specific directory these
-files all recognize a few special commands.
-When called with one of these they will apply the command to
-their own directory and all subdirectories.
-The special commands are:
-.IP "install" 20
-recompile and install all binaries and libraries.
-.br
-Some Makefiles allow errors to occur in the programs they call.
-They ignore such errors and notify the user with the message
-"~....... error code n: ignored".
-Whenever such a message appears in the output you can ignore it
-too.
-.br
-The installation of the PUBMAC macro package is not done
-automatically from the higher level directory.
-.IP "cmp"
-recompile all binaries and libraries and compare them to the
-ones already installed.
-.IP pr
-print the sources and documentation on the standard output.
-.IP opr
-make pr | opr
-.br
-Opr should be an off-line printer daemon.
-On some systems it exists under another name e.g. lpr.
-The easiest way to call such a spooler is using a shell script
-with the name opr that calls lpr.
-This script should be placed in /usr/bin or EM_DIR/bin or
-one of the directories in your PATH.
-.IP clean
-remove all files not needed for day-to-day use,
-that is binaries not in bin or lib, object files etc.
-.LP
-Example:
-.nf
-.sp 1
-        make install
-.sp 1
-.fi
-given as command in the home directory will cause
-recompilation of all programs in the kit.
-.LP
-Recompilation of the complete kit lasts about 9 hours an a PDP
-11/44.
-.NH 2
-Recompilation on a different machine.
-.PP
-Installation on other systems will often require recompilation
-of all programs.
-The presence of a C compiler is essential for recompilation.
-Except the Pascal compiler proper all programs are written in C.
-Some modules are derived from \fIyacc\fP sources.
-Retranslating these programs from that yacc source is not
-necessary, although it might improve performance.
-Some versions of \fIyacc\fP 'know' that the resulting C programs will
-run on a 32-bit int machine.
-C modules produced by such a \fIyacc\fP are not portable and
-should not be used to (cross)compile programs for 16-bit machines.
-We assume a version UNIX which, apart from the C-compiler,
-contains most normal utilities, like ed, sed, grep, make, the
-Bourne shell etc.
-All Makefiles use the system C-compiler.
-The existence of a backend for your system is of course essential
-if you wish to produce executable files for that system.
-When the backend exists it is also possible to boot the Pascal
-Compiler,
-that is written in Pascal itself.
-The kit contains the compact code files for the 2/2 and 2/4
-versions of the Pascal compiler.
-The current version of this compiler can only be used on machines
-with a 16-bit word size and 16- or 32-bit pointers.
-The Makefile automatically tries to boot the Pascal compiler
-from one of these compact code files, if the compiler proves
-unable to compile itself.
-.PP
-The native assemblers and loaders are used on PDP-11 and VAX.
-The description files in lib/ack for other systems use our
-universal assembler.
-The load file produced by this assembler is not directly
-usable in any system known to us,
-but has to be converted before it can be put to use.
-The \fIdl\fP programs present for some machines unravel
-these load files and transmit commands to load memory
-to a microprocessor over a serial line.
-The PDP-11 version of our universal assembler is supplied
-with a conversion program.
-The file man/a.out.5 contains a description of the format of
-the universal assembler load file,
-it might be useful to those who wish or need to write their
-own conversion programs.
-.br
-Berkeley UNIX for the VAX'en has (at least) three different
-versions, BSD4.1a, BSD4.1c and BSD4.2. The READ_ME files in the
-directories mach/vax2/cg, mach/vax2/libem, mach/vax4/cg and
-mach/vax4/libem tell you how to adapt the vax2 and vax4 backend
-to these versions.
-.NH 2
-Recompiling libraries
-.PP
-The kit contains sources for part II and III of the C-library, except
-the math functions, they are grabbed from our V7 system and sometimes
-altered in a EM dependent way or replaced altogether when the original
-was in assembly.
-These files can be used to make libraries for the Ack C-compiler.
-The recompilation process uses a few include files.
-The include directory in the EM home directory contains a few more
-or less system independent include files.
-The system dependent include files are fetched from /usr/include
-on the system you use to recompile.
-This may lead to several problems.
-Sometimes the system differs so much from V7 that certain manifest constants
-do not exist any more.
-At other times these include files were written for a compiler without
-a restriction on name length.
-In that case - I've seen it happen - people tend to use differing
-identifiers that are identical in the first eight characters.
-All these problems you have to solve yourself,
-the libraries are only included as an extra and too much system
-dependent to give any guarantees.
-.NH
-Fixes to the UNIX V7 system
-.PP
-UNIX System V7 has a few bugs that prevent a part of or the whole kit
-from working properly.
-To be honest, we do not know which of the following changes are
-essential to the functioning of our kit.
-.PP
-The file "doc/v7bugs.doc" gives for each of the following bugs
-a small test program and a diff listing of the source files that have to be
-modified.
-.IP 1
-Bug in the C optimizer for unsigned comparison
-.nr PD 0
-.IP 2
-The loader 'ld' fails for large data and text portions
-.IP 3
-Floating point registers are not saved if more memory is needed.
-.IP 4
-Floating point registers are not copied to child in fork().
-.nr PD 1v
-.LP
-Use the test programs to see if the errors are present in your system
-and to check if the modifications are effective.
-.NH
-Testing
-.PP
-Test sets are available in Pascal, C and EM assembly.
-.IP em 8
-.br
-The directory emtest contains a few EM test programs.
-The EM assembly files in these tests must be transformed into
-load files, thereby avoiding use of the EM optimizer.
-These tests use the LIN and NOP instructions to mark the passing of each
-test.
-The NOP instruction prints the current line number during the
-test phase.
-Each test notifies its correctness by calling LIN with a unique
-number followed by a NOP which prints this line number.
-The test finishes normally with 0 as the last number printed
-In all other cases a bug showed its
-existence.
-.IP Pascal
-.br
-The directory lang/pc/test contains a few pascal test programs.
-All these programs print the number of errors found and a
-identification of these errors.
-.IP C
-.br
-The sub-directories in lang/cem/ctest contain C test programs.
-The idea behind these tests is:
-when you have a program called xx.c, compile it into xx.cem.
-Run it with standard output to xx.cem.r, compare this file to
-xx.cem.g, a file containing the 'ideal' output.
-Any differences will point to implementation differences or
-bugs.
-Giving the command "run gen" or plain "run" starts this
-process.
-The differences will be presented on standard output.
-The contents of the result files depend on the wordsize,
-the xx.cem.g files on the distribution are intended for a
-16-bit machine.
-.NH
-Documentation
-.PP
-Manual pages for Amsterdam Compiler Kit can be copied
-to "/usr/man/man?" by the
-following commands:
-.DS
-cd man
-make install
-.DE
-.LP
-Several documents are provided:
-.DS
-doc/toolkit.doc: a general overview
-doc/pcref.doc: the Pascal-frontend reference manual
-doc/val.doc: the results of running the Pascal Validation Suite
-doc/cref.doc: the C-frontend manual
-doc/em.doc: a description of the EM machine architecture
-doc/peep.doc: internal documentation for the peephole optimizer
-doc/cg.doc: documentation for backend writers and maintainers
-doc/regadd.doc: addendum to previous document describing register variables
-doc/install.doc: this document
-.DE
-.LP
-The Validation Suite is a collection of more than 200 Pascal programs,
-designed by Brian Wichmann and Arthur Sale to test Pascal compilers.
-We are not allowed to distribute it, but you may
-request a copy from
-.DS
-Richard J. Cichelli
-A.N.P.A.
-1350 Sullivan Trail
-P.O. Box 598
-Easton, Pennsylvania 18042
-USA
-.DE
-.LP
-Good luck.

+ 0 - 2944
doc/ncg.doc

@@ -1,2944 +0,0 @@
-.\" $Header$
-.RP
-.ND
-.TL
-The table driven code generator
-.br
-from the
-.br
-Amsterdam Compiler Kit
-.br
-Second Revised Edition
-.AU
-Hans van Staveren
-.AI
-Dept. of Mathematics and Computer Science
-Vrije Universiteit
-Amsterdam, The Netherlands
-.AB
-The Amsterdam Compiler Kit is a collection of tools
-designed to help automate the process of compiler building.
-Part of it is a table driven code generator,
-called
-.I cg ,
-and a program to check and translate machine description
-tables called
-.I cgg .
-This document provides a description of the internal workings of 
-.I cg ,
-and a description of syntax and semantics of the driving table.
-This is required reading for those wishing to write a new table.
-.AE
-.NH 1
-Introduction
-.PP
-Part of the Amsterdam Compiler Kit is a code generator system consisting
-of a code generator generator (\fIcgg\fP for short) and some machine
-independent C code.
-.I Cgg
-reads a machine description table and creates two files,
-tables.h and tables.c.
-These are then used together with other C code to produce
-a code generator for the machine at hand.
-.PP
-This in turn reads compact EM code and produces
-assembly code.
-The remainder of this document will first broadly describe
-the working of the code generator,
-then the machine table will be described after which
-some light is shed onto
-the internal workings of the code generator.
-.PP
-The reader is assumed to have at least a vague notion about the
-semantics of the intermediary EM code.
-Someone wishing to write a table for a new machine
-should be thoroughly acquainted with EM code
-and the assembly code of the machine at hand.
-.NH 1
-What has changed since version 1 ?
-.PP
-This chapter can be skipped by anyone not familiar with the first version.
-It is not needed to understand the current version.
-.PP
-This paper describes the second version of the code generator system.
-Although the code generator itself is for the main part unchanged,
-the table format has been drastically redesigned and the opportunities
-to make faulty tables are reduced.
-The format is now aesthaticly more pleasing (according to \fIme\fP that is),
-mainly because the previous version was designed for one line code rules,
-which did not work out that way.
-.PP
-The `SCRATCH' property is now automatically generated by
-.I cgg ,
-.I erase
-and
-.I setcc
-calls and their ilk are now no longer needed
-(read: can no longer be forgotten)
-and all this because the table now 
-.I knows
-what the machine instructions look like and what arguments they
-destroy.
-.PP
-Checks are now made for register types, so it is no longer possible
-to generate a `regind2' token with a floating point register as a base.
-In general, if the instructions of the machine are correctly defined,
-it is no longer possible to generate code that does not assemble,
-which of course does not mean that it is not possible to generate
-assembly code that does not do what was intended!
-.PP
-Checks are made now for missing moves, tests, coercions, etc.
-There is a form of procedure call now to reduce table size:
-it is no longer necessary to write the code for conditional
-instructions six times.
-.PP
-The inreg() pseudo-function returns other results!!
-.NH 1
-Global overview of the workings of the code generator.
-.PP
-The code generator or
-.I cg
-tries to generate good code by simulating the stack
-of the compiled program and delaying emission of code as long
-as possible.
-It also keeps track of register contents, which enables it to
-eliminate redundant moves, and tries to eliminate redundant tests
-by keeping information about condition code status,
-if applicable for the machine.
-.PP
-.I Cg
-maintains a `fake stack' containing `tokens' that are built
-by executing the pseudo code contained in the code rules given
-by the table writer.
-One can think of the fake stack as a logical extension of the real
-stack the compiled program will have when run.
-Alternatively one can think of the real stack as an infinite extension
-at the bottom of the fake stack.
-Both ways, the concatenation of the real stack and the fake stack
-will be the stack as it would have been on a real EM machine (see figure).
-.KF
-.DS L
-.ta 8 16 24 32 40 48 56 64 72
-	   EM machine		 target machine
-
-	|		|	|		|
-	|		|	|		|
-	|		|	|		|
-	|		|	|		|
-	|		|	|   real stack	|
-	|		|	|		|	|
-	|		|	|		|	| growing
-	|    EM stack	|	|		|	|
-	|		|	|_______________|      \e|/
-	|		|	|		|
-	|		|	|		|
-	|		|	|		|
-	|		|	|   fake stack	|
-	|		|	|		|
-	|_______________|	|_______________|
-
-
-.I
-	Relation between EM stack, real stack and fake stack.
-.R
-.DE
-.KE
-During code generation tokens will be kept on the fake stack as long
-as possible but when they are moved to the real stack,
-by generating code for the push,
-all tokens above\u*\d
-.FS
-* in this document the stack is assumed to grow downwards,
-although the top of the stack will mean the first element that will
-be popped.
-.FE
-the pushed tokens will be pushed also,
-so the fake stack will not contain holes.
-.PP
-The information about the machine that 
-.I cg
-needs has to be given in a machine description table,
-with as a major part a list of code rules telling 
-.I cg
-what to do when certain EM-instructions occur
-with certain tokens on the fake stack.
-Not all possible fake stack possibilities have to be given of course,
-there is a possibility for providing rewriting rules, or
-.I coercions
-as they are called in this document.
-.PP
-The main loop of
-.I cg
-is:
-.IP 1)
-find a pattern of EM instructions starting at the current one to
-generate code for.
-This pattern will usually be of length one but longer patterns can be used.
-Process any pseudo-instructions found.
-.IP 2)
-Select one of the possibly many stack patterns that go with this
-EM pattern on the basis of heuristics, look ahead or both.
-The cost fields provided in the token definitions and
-instruction definitions are used
-to compute costs during look ahead.
-.IP 3)
-Force the current fake stack contents to match the pattern.
-This may involve
-copying tokens to registers, making dummy transformations, e.g. to
-transform a `local' into an `indexed from register' or might even
-cause the move of the complete fake stack contents to the real stack
-and then back into registers if no suitable coercions
-were provided by the table writer.
-.IP 4)
-Execute the pseudocode associated with the code rule just selected,
-this may cause registers to be allocated,
-code to be emitted etc..
-.IP 5)
-Put tokens onto the fake stack to reflect the result of the operation.
-.IP 6)
-Insert some EM instructions into the stream;
-this is possible but not common.
-.IP 7)
-Account for the cost.
-The cost is kept in a (space, time) vector and look ahead decisions
-are based on a linear combination of these.
-The code generator calls on itself recursively during look ahead,
-and the recursive incarnations return the costs they made.
-The costs the top-level code generator makes is of course irrelevant.
-.PP
-The table that drives
-.I cg
-is not read in every time,
-but instead is used at compile time
-of
-.I cg
-to set parameters and to load pseudocode tables.
-A program called
-.I cgg
-reads the table and produces large lists of numbers that are
-compiled together with machine independent code to produce
-a code generator for the machine at hand.
-.PP
-Part of the information needed is not easily expressed in this table
-format and must be supplied in two separate files,
-mach.h and mach.c.
-Their contents are described later in this document.
-.NH 1
-Register variables
-.PP
-If the machine has more than enough registers to generate code with,
-it is possible to reserve some of them for use as register variables.
-If it has not, you can skip this section and ignore any references
-to register variables in the rest of this document.
-.PP
-The front ends generate messages to the back ends telling them which
-local variables could go into registers.
-The information given is the offset of the local, it's size and type
-and a scoring number, roughly the number of times it occurs.
-.PP
-The decision which variable to put in which register is taken by the
-machine independent part of
-.I cg
-with the help of a scoring function provided by the table writer in mach.c.
-The types of variables known are
-.IP reg_any 12
-Just a variable of some integer type.
-Nothing special known about it.
-.IP reg_float
-A floating point variable.
-.IP reg_loop
-A loop control variable.
-.IP reg_pointer
-A pointer variable.
-Usually they are better candidates to put in registers.
-.PP
-If you use register variables in your table you must supply
-more functions in mach.c.
-These functions are explained later.
-.NH 1
-Description of the machine table
-.PP
-The machine description table consists of the
-concatenation of the following sections:
-.IP 1)
-Constant definitions
-.IP 2)
-Property definitions
-.IP 3)
-Register definitions
-.IP 4)
-Token definitions
-.IP 5)
-Set definitions
-.IP 6)
-Instruction definitions
-.IP 7)
-Move definitions
-.IP 8)
-Test definitions
-.IP 9)
-Stack definitions
-.IP 10)
-Coercions
-.IP 11)
-Code rules
-.PP
-This is the order in the table
-but the descriptions in this document will use a slightly different
-order.
-All sections except the first start with an uppercase header word.
-Examples may be given in early stages that use knowledge that is explained
-in a later stage.
-If something is not clear the first time, please read on.
-All will clear up in a couple of pages.
-.PP
-Input is in free format, white space and newlines may be used
-at will to improve legibility.
-Identifiers used in the table have the same syntax as C identifiers,
-upper and lower case considered different, all characters significant.
-Here is a list of reserved words; all of these are unavailable as identifiers.
-.DS L
-.ta 14 28 42 56
-ADDR	STACK	from	reg_any	test
-COERCIONS	STACKINGRULES	gen	reg_float	to
-INSTRUCTIONS	TESTS	highw	reg_loop	ufit
-INT	TIMEFACTOR	inreg	reg_pointer	uses
-MOVES	TOKENS	kills	regvar	with
-PATTERNS	call	leaving	return	yields
-PROPERTIES	cost	loww	reusing	
-REGISTERS	defined	move	rom	
-SETS	exact	pat	samesign	
-SIZEFACTOR	example	proc	sfit	
-.DE
-C style comments are accepted.
-.DS
-/* this is a comment */
-.DE
-If the standard constant facility is not enough the C-preprocessor can
-be used to enhance the table format.
-.PP
-Integers in the table have the normal C-style syntax.
-Decimal by default, octal when preceded by a 0
-and hexadecimal when preceded by 0x.
-.NH 2
-Constant section
-.PP
-In the first part of the table some constants can be defined,
-most with the syntax
-.DS
-NAME=value
-.DE
-value being an integer or string.
-Three constants must be defined here:
-.IP EM_WSIZE 10
-Number of bytes in a machine word.
-This is the number of bytes
-a \fBloc\fP instruction will put on the stack.
-.IP EM_PSIZE
-Number of bytes in a pointer.
-This is the number of bytes
-a \fBlal\fP instruction will put on the stack.
-.IP EM_BSIZE
-Number of bytes in the hole between AB and LB.
-If the calling sequence just saves PC and LB this
-size will be twice the pointersize.
-.PP
-EM_WSIZE and EM_PSIZE are checked when a program is compiled
-with the resulting code generator.
-EM_BSIZE is used by
-.I cg
-to add to the offset of instructions dealing with locals
-having positive offsets,
-i.e. parameters.
-.PP
-Other constants can be defined here to be used as mnemonics
-later in the table.
-.PP
-Optional is the definition of a printformat for integers in the code file.
-This is given as
-.DS
-FORMAT = string
-.DE
-The string must be a valid printf(III) format,
-and defaults to "%d" or "%ld" depending on the wordsize of 
-the machine. For example on the PDP-11 one can use
-.DS
-FORMAT= "0%o"
-.DE
-to satisfy the old UNIX assembler that reads octal unless followed by
-a period, and the ACK assembler that follows C conventions.
-.PP
-Tables under control of programs like
-.I sccs
-or
-.I rcs
-can put their id-string here, for example
-.DS
-rcsid="$Header$"
-.DE
-These strings, like all strings in the table, will eventually
-end up in the binary code generator produced.
-.PP
-Optionally one can give the factors with which the size and time
-parts of the cost vector have to be multiplied to ensure they have the
-same order of magnitude.
-This can be done as
-.DS
-SIZEFACTOR = C\d3\u/C\d4\u
-TIMEFACTOR = C\d1\u/C\d2\u
-.DE
-Above numbers must be read as rational numbers.
-Defaults are 1/1 for both of them.
-These constants set the default size/time tradeoff in the code generator,
-so if TIMEFACTOR and SIZEFACTOR are both 1 the code generator will choose
-at random between two code sequences where one has
-cost (10,4) and the other has cost (8,6).
-See also the description of the cost field below.
-.NH 2
-Property definition
-.PP
-This part of the table defines the list of properties that can be used
-to differentiate between register classes.
-It consists of a list of user-defined 
-identifiers optionally followed by the size
-of the property in parentheses, default EM_WSIZE.
-Example for the PDP-11:
-.DS
-.ta 8 16 24 32 40
-PROPERTIES		/* The header word for this section */
-
-GENREG			/* All PDP registers */
-REG			/* Normal registers (allocatable) */
-ODDREG			/* All odd registers (allocatable) */
-REGPAIR(4)		/* Register pairs for division */
-FLTREG(4)		/* Floating point registers */
-DBLREG(8)		/* Same, double precision */
-GENFREG(4)		/* generic floating point */
-GENDREG(8)		/* Same, double precision */
-FLTREGPAIR(8)		/* register pair for modf */
-DBLREGPAIR(16)		/* Same, double precision */
-LOCALBASE		/* Guess what */
-STACKPOINTER
-PROGRAMCOUNTER
-.DE
-Registers are allocated by asking for a property,
-so if for some reason in later parts of the table
-one particular register must be allocated it
-has to have a unique property.
-.NH 2
-Register definition
-.PP
-The next part of the tables describes the various registers of the
-machine and defines identifiers
-to be used in later parts of the tables.
-Syntax:
-.DS
-<register definitions> : REGISTERS <list of definitions>
-<definition> : <registerlist> ':' <propertylist> <optional regvar> '.'
-<register> : ident [ '(' string ')' ] [ '=' ident [ '+' ident ] ]
-.DE
-Example for the PDP-11:
-.DS L
-.ta 8 16 24 32 40 48 56 64
-REGISTERS
-
-r0,r2,r4				: GENREG,REG.
-r1,r3					: GENREG,REG,ODDREG.
-r01("r0")=r0+r1				: REGPAIR.
-fr0("r0"),fr1("r1"),fr2("r2"),fr3("r3") : GENFREG,FLTREG.
-dr0("r0")=fr0,dr1("r1")=fr1,
-	dr2("r2")=fr2,dr3("r3")=fr3 	: GENDREG,DBLREG.
-fr01("r0")=fr0+fr1,fr23("r2")=fr2+fr3	: FLTREGPAIR.
-dr01("r0")=dr0+dr1,dr23("r2")=dr2+dr3	: DBLREGPAIR.
-lb("r5")				: GENREG,LOCALBASE.
-sp					: GENREG,STACKPOINTER.
-pc					: GENREG,PROGRAMCOUNTER.
-.DE
-.PP
-The names in the left hand lists are names of registers as used
-in the table.
-They can optionally be followed by a string in parentheses,
-their name as far as the assembler is concerned.
-The default assembler name is the same as the table name.
-A name can also be followed by
-.DS
-= othername
-.DE
-or
-.DS
-= othername + othername
-.DE
-which says that the register is composed of the parts
-after the '=' sign.
-The identifiers at the right hand side of the lists are
-names of properties.
-The end of each register definition is a period.
-.PP
-It might seem wise to list every property of a register,
-so one might give r0 the extra property MFPTREG named after the not
-too well known MFPT instruction on newer PDP-11 types,
-but this is not a good idea,
-especially since no use can be made of that instruction anyway.
-Every extra property means the register set is more unorthogonal
-and 
-.I cg
-execution time is influenced by that,
-because it has to take into account a larger set of registers
-that are not equivalent.
-So try to keep the number of different register classes to a minimum.
-When faced with the choice between two possible code rules
-for a nonfrequent EM sequence,
-one being elegant but requiring an extra property,
-and the other less elegant,
-elegance should probably loose.
-.PP
-Tables that implement register variables must mark registers to be used
-for variable storage here by following the list of properties by one
-of the following:
-.DS
-regvar \fIor\fP regvar(reg_any)
-regvar(reg_loop)
-regvar(reg_pointer)
-regvar(reg_float)
-.DE
-meaning they are candidates for that type of variable.
-All register variables of one type must be of the same size,
-and they may have no subregisters.
-Such registers are not available for normal code generation.
-.NH 2
-Stack token definition
-.PP
-The next part describes all possible tokens that can reside on
-the fake stack during code generation.
-Attributes of a token are described as a C struct declaration;
-this is followed by the size of the token in bytes,
-optionally followed by the cost of the token when used as an addressing mode
-and the format to be used on output.
-.PP
-In general, when writing a table, it is not wise to try
-to think of all necessary tokens in advance.
-While writing the necessity or advisability for some token
-will be seen and it can then be added together with the
-stacking rules and coercions needed.
-.PP
-Tokens should usually be declared for every addressing mode
-of the machine at hand and for every size directly usable in
-a machine instruction.
-Example for the PDP-11 (incomplete):
-.DS L
-TOKENS
-
-const2 		= { INT num; } 2 cost(2,300) "$" num .
-addr_local 	= { INT ind; } 2 .
-addr_external 	= { ADDR off; } 2 "$" off.
-
-regdef2 	= { GENREG reg; } 2 "*" reg.
-regind2 	= { GENREG reg; ADDR off; } 2 off "(" reg ")" .
-reginddef2 	= { GENREG reg; ADDR off; } 2 "*" off "(" reg ")" .
-regconst2	= { GENREG reg; ADDR off; } 2 .
-relative2	= { ADDR off; } 2 off .
-reldef2		= { ADDR off; } 2 "*" off.
-.DE
-.PP
-Types allowed in the struct are ADDR, INT and all register properties.
-The type ADDR means a string and an integer,
-which is output as string+integer,
-and arithmetic on mixed ADDR and INT is possible.
-This is the right mode for anything that can be an
-assembler address expression.
-The type of the register in the token is strict.
-At any assignment of an expression of type register to a token attribute
-of type register
-.I cgg
-will check if the set of possible results from the expression is a subset
-of the set of permissible values for the token attribute.
-.PP
-The cost-field is made up by the word
-.I cost
-followed by two numbers in parentheses, the size and timecosts
-of this token when output in the code file.
-If omitted, zero cost is assumed.
-While generating code,
-.I cg
-keeps track of a linear combination of these costs together
-with the costs of the instructions itself which we will see later.
-The coefficients of this linear combination are influenced
-by two things:
-.IP 1)
-The SIZEFACTOR and TIMEFACTOR constants,
-as mentioned above.
-.IP 2)
-A run time option to
-.I cg
-that can adjust the time/space tradeoff to all positions
-from 100% time to 100% space.
-.LP
-By supplying different code rules in certain situations
-it is possible to get a code generator that can adjust it's
-code to the need of the moment.
-This is probably most useful with small machines,
-experience has shown that on the larger micro's and mini's
-the difference between time-optimal and space-optimal code
-is often small.
-.PP
-The printformat consists of a list of strings intermixed with
-attributes from the token.
-Strings are output literally, attributes are printed according
-to their type and value.
-Tokens without a printformat should never be output,
-and
-.I cgg
-checks for this.
-.PP
-Notice that tokens need not correspond to addressing modes;
-the regconst2 token listed above,
-meaning the sum of the contents of the register and the constant,
-has no corresponding addressing mode on the PDP-11,
-but is included so that a sequence of add constant, load indirect,
-can be handled efficiently.
-This regconst2 token is needed as part of the path
-.DS
-REG -> regconst2 -> regind2
-.DE
-of which the first and the last "exist" and the middle is needed
-only as an intermediate step.
-.PP
-Tokens with name `LOCAL' or `DLOCAL' are a special case when
-register variables are used, this is explained further in the
-section on token descriptions.
-.NH 2
-Sets
-.PP
-Usually machines have certain collections of addressing modes that
-can be used with certain instructions.
-The stack patterns in the table are lists of these collections
-and since it is cumbersome to write out these long lists
-every time, there is a section here to give names to these
-collections.
-Please note that it is not forbidden to write out a set
-in the remainder of the table,
-but for clarity it is usually better not to.
-.LP
-Example for the PDP-11 (incomplete):
-.DS L
-.ta 8 16 24 32 40 48 56 64
-SETS
-
-src2		= GENREG + regdef2 + regind2 + reginddef2 + relative2 +
-		  reldef2 + addr_external + const2 + LOCAL + ILOCAL +
-		  autodec + autoinc .
-dst2		= src2 - ( const2 + addr_external ) .
-xsrc2		= src2 + ftoint .
-src1		= regdef1 + regind1 + reginddef1 + relative1 + reldef1 .
-dst1		= src1 .
-src1or2		= src1 + src2 .
-src4		= relative4 + regdef4 + DLOCAL + regind4 .
-dst4		= src4 .
-.DE
-Permissible in the set construction are all the usual set operators, i.e.
-.IP +
-set union
-.IP -
-set difference
-.IP *
-set intersection
-.PP
-Normal operator priorities apply, and parentheses can be
-used.
-Every token identifier is also a set identifier
-denoting the singleton collection of tokens containing
-just itself.
-Every register property as defined above is also a set
-matching all registers with that property.
-The standard set identifier ALL denotes the collection of 
-all tokens.
-.NH 2
-Instruction definitions
-.PP
-In the next part of the table the instructions for the machine
-are declared together with information about their operands.
-Example for the PDP-11(very incomplete):
-.DS
-.ta 8 16 24 32 40 48 56 64
-INSTRUCTIONS
-/* default cost */
-
-cost(2,600)
-
-/* Normal instructions */
-
-adc dst2:rw:cc .
-add src2:ro,dst2:rw:cc cost(2,450).
-ash src2:ro,REG:rw:cc .
-ashc src2:ro,REGPAIR+ODDREG:rw .
-asl dst2:rw:cc .
-asr dst2:rw:cc .
-bhis "bcc" label .
-
-/* floating point instructions */
-
-movf "ldf" fsrc,freg .
-movf "stf" freg,fdst .
-.DE
-As the examples show an instruction definition consists of the name
-of the instruction,
-optionally followed by an assembler mnemonic in
-quotes-default is the name itself-and then
-a list of operands,
-optionally followed by the cost and then a period.
-If the cost is omitted the cost just after the word
-INSTRUCTIONS is assumed,
-if that is also omitted the cost is zero.
-The cost must be known by
-.I cg
-of course if it has multiple
-code generation paths to choose from.
-.PP
-For each operand we have the set of possible token values,
-followed by a qualifier that can be
-.IP :ro
-signifies that this operand is read only,
-so it can be replaced by a register with the same contents
-if available.
-.IP :rw
-signifies that the operand is read-write
-.IP :wo
-signifies that the operand is write only.
-.IP :cc
-says that after the instruction is finished, the condition codes
-are set to this operand.
-If none of the operands have the :cc qualifier set,
-.I cg
-will assume that condition codes were unaffected
-(but see below).
-.PP
-The first three qualifiers are of course mutually exclusive.
-The :ro qualifier does not cause any special action in the current
-implementation, and the :wo and :rw qualifiers are treated equal.
-It must be recommended however to be precise in the specifications,
-since later enhancements to the code generator might use them.
-.PP
-As the last examples show it is not necessary to give one definition
-for an instruction.
-There are machines that have very unorthogonal instruction sets,
-in fact most of them do,
-and it is possible to declare each possible combination
-of operands.
-The
-.I cgg
-program will check all uses of the instruction to find out which
-one was meant.
-.PP
-Although not in the PDP-11 example above there is a possibility
-to describe instructions that have side effects to registers not
-in the operand list.
-The only thing possible is to say that the instruction is destructive
-to some registers or the condition codes, by following the operand list
-with the word 
-.I kills
-and a list of the things destroyed.
-Example for some hypothetic accumulator machine:
-.DS
-add source2:ro kills ACCU :cc .
-.DE
-.PP
-The cost fields in the definitions for tokens and instructions
-are added together when generating code.
-It depends on the machine at hand whether the costs are orthogonal
-enough to make use of both these costs,
-in extreme cases every combination of instructions and operands
-can be given in this section,
-all with their own costs.
-.NH 2
-Expressions
-.PP
-Throughout the rest of the table expressions can be used in some
-places.
-This section will give the syntax and semantics of expressions.
-There are four types of expressions: integer, address, register and undefined.
-Really the type register is nonexistent as such,
-for each register expression
-.I cgg
-keeps a set of possible values,
-and this set can be seen as the real type.
-.PP
-Type checking is performed by
-.I cgg .
-An operator with at least one undefined operand returns undefined except
-for the defined() function mentioned below.
-An undefined expression is interpreted as FALSE when it is needed
-as a truth value.
-It is the responsibility of the table writer to ensure no undefined
-expressions are ever used as initialisers for token attributes.
-This is unfortunately almost impossible to check for
-.I cgg
-so be careful.
-.LP
-Basic terms in an expression are
-.IP number 16
-A number is a constant of type integer.
-Also usable is an identifier defined to a number in the constant
-definition section.
-.IP """string"""
-A string within double quotes is a constant of type address.
-All the normal C style escapes may be used within the string.
-Also usable is an identifier defined to a string in the constant
-definition section.
-.IP [0-9][bf]
-This must be read as a grep-pattern.
-It evaluates to a string that is the label name for the
-temporary label meant.
-More about this in the section on code rules.
-.IP REGIDENT
-The name of a register is a constant of type register.
-.IP $\fIi\fP
-A dollarsign followed by a number is the representation of the argument
-of EM instruction \fI\fP.
-The type of the operand is dependent on the instruction,
-sometimes it is integer,
-sometimes it is address.
-It is undefined when the instruction has no operand.
-Watch out for instructions with type-letter w.
-They can occur without an operand.
-Check for this in your code rule with the defined() pseudo function.
-.br
-If you cannot imagine the operand of the instruction ever to be
-something different from a plain integer, the type is integer,
-otherwise it is address.
-.br
-Those who want to know it exactly, the integer instruction types
-are the instructions marked with the
-type-letters c,f,l,n,o,s,r,w,z in the EM manual.
-.br
-.I Cg
-makes all necessary conversions for you,
-like adding EM_BSIZE to positive arguments of instructions
-dealing with locals,
-prepending underlines to global names,
-converting code labels into a unique representation etc.
-Details about this can be found in the section about
-machine dependent C code.
-.IP %1
-This in general means the token mentioned first in the
-stack pattern.
-When used inside an expression the token must be a simple register.
-Type of this is register.
-.IP %1.off
-This means attribute "off" of the first stack pattern token.
-Type is the same as that of attribute "off".
-To use this expression implies a check that all tokens
-in the set used have the same attribute in the same place.
-.IP %off
-This means attribute "off" in the `current' token.
-This can only be used when no confusion is possible about which token
-was meant, eg. in the optional boolean expressions following token sets
-in the move and test rules, in coercions or in the kills section inside
-the code rules.
-Same check as above.
-.IP %1.1
-This is the first subregister of the first token.
-Previous comments apply.
-.IP %b
-A percent sign followed by a lowercase letter
-stands for an allocated register.
-This is the second allocated register.
-.IP %a.2
-The second subregister of the first allocated register.
-.PP
-All normal C operators apply to integers,
-the + operator on addresses behaves as you would expect
-and the only operators allowed on register expressions
-are == and != .
-Furthermore there are some special `functions':
-.IP defined(e) 16
-Returns 1 if expression 
-.I e
-is defined, 0 otherwise.
-.IP samesign(e1,e2)
-Returns 1 if integer expression 
-.I e1
-and 
-.I e2
-have the same sign.
-.IP sfit(e1,e2)
-Returns 1 if integer expression 
-.I e1
-fits as a signed integer
-into a field of 
-.I e2
-bits, 0 otherwise.
-.IP ufit(e1,e2)
-Same as above but now for unsigned 
-.I e1 .
-.IP rom($a,n)
-Integer expression giving word
-.I n
-from the \fBrom\fP descriptor
-pointed at by EM instruction
-number
-.I a
-in the EM-pattern.
-Undefined if that descriptor does not exist.
-.IP loww($a)
-Returns the lower half of the argument of EM instruction number
-.I a .
-This is used to split the arguments of a \fBldc\fP instruction.
-.IP highw($a)
-Same for upper half.
-.LP
-The next two `functions' are only needed in a table that
-implements register variables.
-.IP inreg(e) 16
-Returns the status of the local variable with offset
-.I e
-from the localbase.
-Value is an integer,
-negative if the local was not allowed as a register
-variable,
-zero if it was allowed but not assigned to a register,
-and the type of the register if it was assigned to a register.
-This makes it possible to write
-.DS
-inreg($1)==reg_pointer
-.DE
-and similar things.
-.IP regvar(e,t)
-Type of this is register.
-It returns the register the local with offset
-.I e
-is assigned to.
-The table writer guarantees the register is one of type
-.I t ,
-with
-.I t
-one of reg_any, reg_loop, reg_pointer or reg_float.
-If
-.I t
-is omitted reg_any is assumed.
-Undefined if inreg(\fIe\fP)<=0 .
-.NH 2
-Token descriptions
-.PP
-Throughout the rest of the table tokens must be described,
-be it as operands of instructions or as stack-replacements.
-In all those cases we will speak about a token description.
-The possibilities for these will be described here.
-.PP
-All expressions of type register are token descriptions.
-The construct %1 means the token matched first in the stack pattern.
-All other token descriptions are those that are built on the spot.
-They look like this:
-.DS
-{ <tokenname> , <list of token attribute initializing expressions> }
-.DE
-All expressions are type-checked by
-.I cgg ,
-and the number of initializers is also checked.
-.PP
-A special case of the last token descriptions occurs when
-the token name is `LOCAL' or `DLOCAL' and the table uses register
-variables. The first token attribute then must be of type integer and
-the token description is automagically replaced by the register chosen
-if the LOCAL (wordsize) or DLOCAL (twice the wordsize) was assigned
-to a register.
-.NH 2
-Code rules
-.PP
-The largest section of the tables consists of the code generation rules.
-They specify EM patterns, stack patterns, code to be generated etc.
-Broadly the syntax is
-.DS L
-code rule : EM-part code-part
-EM-part : EM-pattern | procedure-heading
-code-part : code-description | procedure-call
-code-description : stackpattern kills allocates generates yields leaving
-.DE
-Ignoring the "procedure"-part for now, the description for the EM-pattern
-and the code-description follows.
-Almost everything here is optional, the minimum code rule
-is:
-.DS
-pat nop
-.DE
-that will simply throw away
-.I nop
-instructions.
-.NH 3
-The EM pattern
-.PP
-The EM pattern consists of a list of EM mnemonics
-preceded by the word
-.I pat
-optionally followed by a boolean expression.
-Examples:
-.DS
-pat \fBloe\fP
-.DE
-will match a single \fBloe\fP instruction,
-.DS
-pat \fBloc\fP \fBloc\fP \fBcif\fP $1==2 && $2==8
-.DE
-is a pattern that will match
-.DS
-\fBloc\fP 2
-\fBloc\fP 8
-\fBcif\fP
-.DE
-and
-.DS
-pat \fBlol\fP \fBinc\fP \fBstl\fP $1==$3
-.DE
-will match for example
-.DS
-.ta 10m 20m 30m 40m 50m 60m
-\fBlol\fP 6	\fBlol\fP -2		\fBlol\fP 4
-\fBinc\fP	\fBinc\fP	but \fInot\fP	\fBinc\fP
-\fBstl\fP 6	\fBstl\fP -2		\fBstl\fP -4
-.DE
-A missing boolean expression evaluates to TRUE.
-.PP
-The code generator will match the longest EM pattern on every occasion,
-if two patterns of the same length match the first in the table will be chosen,
-while all patterns of length greater than or equal to three are considered
-to be of the same length.
-This rule of three is an unfortunate implementation dependent restriction,
-but patterns longer than three EM instructions are luckily not needed
-too often.
-.PP
-Following the EM-pattern there may be more than one code
-rule,
-.I cg
-will choose using heuristics and the cost
-information provided with the instruction and token
-definitions.
-Owing to parsing reasons of the table, the word
-.I with
-(see below)
-is mandatory when there are more code rules attached to one
-EM-pattern.
-The stack pattern may be empty however.
-.NH 3
-The stack pattern
-.PP
-The optional stack pattern is a list of token sets preceded by the word
-.I with .
-The token sets are usually represented by set identifiers for clarity.
-No boolean expression is allowed here.
-The first expression is the one that matches the top of the stack.
-.PP
-If the pattern is followed by the word STACK
-it only matches if there is nothing
-else on the fake stack,
-and the code generator will stack everything not matched at the start
-of the rule.
-.PP
-The pattern can be preceded with the word
-.I exact
-following the
-.I with
-that tells the code generator not to try to coerce to the pattern
-but only to use it when it is already present on the fake stack.
-There are two reasons for this construction,
-correctness and speed.
-It is needed for correctness when the pattern contains a register
-that is not transparent when data is moved through it.
-.LP
-Example: on the PDP-11 the shortest code for
-.DS
-\fBlae\fP a
-\fBloi\fP 8
-\fBlae\fP b
-\fBsti\fP 8
-.DE
-is
-.DS
-movf _a,fr0
-movf fr0,_b
-.DE
-if the floating point processor is in double
-precision mode and fr0 is free.
-Unfortunately this is not correct since a trap can occur on certain
-kinds of data.
-This could happen if there was a stack pattern for \fBsti\fP\ 8
-like this:
-.DS
-with DBLREG
-.DE
-The code generator would then find that coercing the 8-byte global _a
-to a floating point register and then storing it to _b was the cheapest,
-if the space/time knob was turned far enough to space.
-This can be prevented by changing the stack pattern to
-.DS
-with exact DBLREG
-.DE
-It is unfortunate that the type information is no longer present,
-since if _a really is a floating point number the move could be
-made without error.
-.PP
-The second reason for the 
-.I exact
-construct is speed.
-When the code generator has a long list of possible stack patterns
-for one EM pattern it can waste much time trying to find coercions
-to all of them, while the mere presence of such a long list
-indicates that the table writer has given many special cases.
-Prepending all the special cases by
-.I exact
-will stop the code generator from trying to find things
-that either cannot be done,
-or are too expensive anyway.
-.PP
-So in general it is wise to prepend all stack patterns that
-cannot be made by coercions with
-.I exact .
-.PP
-Using both
-.I exact
-and STACK in the stack pattern has the effect that the rule will
-only be taken if there is nothing else on the fake stack.
-.NH 3
-The kills part
-.PP
-The optional kills part describes certain tokens 
-that should neither remain on
-the fake stack, nor remembered as contents of registers.
-This is usually only required with store operations.
-The entire fake stack, except for the part matched in the stack pattern,
-is searched for tokens matching the expression and they are copied
-to the real stack.
-Every register that contains the token is marked as empty.
-.PP
-Syntax is
-.DS
-kills <list of things to kill separated by commas>
-thing to kill : token set optionally followed by boolean expression
-.DE
-Example:
-.DS
-kills regind2 %reg != lb || %off == $1
-.DE
-is a kills part used for example in the \fBinl\fP or \fBstl\fP code rule.
-It removes all register offsetted tokens where the register is not the
-localbase plus the local in which the store is done.
-The necessity for this can be seen from the following example:
-.DS
-\fBlol\fP 4
-\fBinl\fP 4
-\fBstl\fP 6
-.DE
-Without a proper kills part in the rule for \fBinl\fP code would
-be generated as here
-.DS
-inc 4(r5)
-mov 4(r5),6(r5)
-.DE
-so local 6 would be given the new value of local 4 instead of the old
-as the EM code prescribed.
-.PP
-When generating code for an EM-instruction like
-.B sti
-it is necessary to write a line in the table like
-.DS
-kills all_except_constant_or_register
-.DE
-where the long identifier is a set containing all tokens
-that can be the destination of some random indirect store.
-These indirect stores are the main reason to prevent this
-.I kills
-line to be deduced automatically by
-.I cgg .
-.PP
-When generating something like a branch instruction it 
-might be needed to empty the fake stack completely.
-This can of course be done with
-.DS
-kills ALL
-.DE
-or by ending the stack pattern with the word STACK, which is equivalent,
-if the stack pattern does not start with
-.I exact .
-.PP
-It is unfortunate that this part is still present in the table
-but it is too much for now to let the
-.I cgg
-program discover what rules ruin what kind of tokens.
-Maybe some day .....
-.NH 3
-The allocates part
-.PP
-The optional register allocation part describes the registers needed.
-Syntax is
-.DS
-uses <list of use elements separated by commas>
-.DE
-where itemlist is a list of three kinds of things:
-.IP 1)
-.I reusing
-< a token description >, for example %1.
-.br
-This will instruct the code generator that all registers
-contained in this token can be reused if they are not used
-in another token on the fakestack,
-so that they are available for allocation in this 
-.I uses
-line
-if they were only used in that token.
-See example below.
-.IP 2)
-a register property.
-.br
-This will allocate a register with that property,
-that is marked as empty at this point.
-Look ahead can be performed if there is more than one register available.
-.IP 3)
-a register property with initialization.
-.br
-This will allocate the register as in 2) but will also
-initialize it.
-This eases the task of the code generator because it can
-find a register already filled with the right value
-if it exists.
-.LP
-Examples:
-.DS
-uses ODDREG
-.DE
-will allocate an odd register, while 
-.DS
-uses REG={regind2,lb,$1}
-.DE
-will allocate a register while simultaneously filling it with
-the asked value.
-.br
-Inside the coercion from xsrc2 to REG in the PDP-11 table
-the following line can be found.
-.DS
-uses reusing %1, REG=%1
-.DE
-This tells the code generator that registers contained in %1 can be used
-again and asks to fill the register allocated with %1.
-So if %1={regind2,r3,"4"} and r3 is not in use elsewhere on the fake stack
-the following code might be generated.
-.DS
-mov 4(r3),r3
-.DE
-In the rest of the line the registers allocated can be named by
-%a and %b.1,%b.2, i.e. with lower case letters
-in order of allocation.
-.NH 3
-The generates part
-.PP
-Code to be generated, also optionally, is specified as
-the word
-.I gen
-followed by a list of items of the following kind:
-.IP 1)
-An instruction name followed by a comma-separated
-list of token descriptions.
-.I Cgg
-will search the instruction definitions for the machine to find a suitable
-instruction.
-At code generation time the assembler name of the
-instruction will be output followed by a space,
-followed by a comma separated list of tokens.
-.br
-In the table an instruction without operands must be
-followed by a period.
-The author of
-.I cgg
-could not get 
-.I yacc
-to be silent without it.
-Sorry about this.
-.IP 2)
-a 
-.I move
-call.
-This has the following syntax:
-.DS
-move <token description>,<token description>
-.DE
-Moves are handled specially since that enables the code generator
-to keep track of register contents.
-Example:
-.DS
-move r3,{regind2,lb,$1}
-.DE
-will generate code to move r3 to $1(r5) except when
-r3 already was a copy of $1(r5).
-Then the code will be omitted.
-The rules describing how to move things to each other
-can be found in the move definitions section described below.
-.IP 3)
-For machines that have condition codes,
-which alas most of them do,
-there are provisions to remember condition code settings
-and prevent needless testing.
-To set the condition code to a token put in the code the following call:
-.DS
-test <token description>
-.DE
-This will generate a test if the condition codes 
-were not already set to that token.
-The rules describing how to test things
-can be found in the test definitions section described below.
-See also the :cc qualifier that can be used at instruction
-definition time.
-.IP 4)
-The
-.I return
-statement.
-Only used when register variables are in use.
-This statement causes a call to the machine dependent
-C-routine 
-.I regreturn .
-Explanation of this must wait for the description of the
-file mach.c below.
-.IP 5)
-A temporary label of the form <digit>: may be placed here.
-Expressions of the form [0-9][bf] in this code rule
-generate the same string as is used for this label.
-The code generator system could probably easily be changed
-to make this work for assemblers that do not support this
-type of label by generating unique labels itself.
-Implementation of this is not contemplated at the moment,
-bad luck if your assembler cannot do it.
-.NH 3
-Stack replacement
-.PP
-The optional stack replacement is a possibly empty list 
-of tokens to be pushed onto the fake stack.
-It start with the word
-.I yields ,
-and is followed by a list of token descriptions.
-.PP
-All tokens matched by the stack pattern at the beginning of the code rule
-are first removed and their registers deallocated.
-Items are pushed in the order of appearance.
-This means that the last item will be on the top of the
-stack after the push.
-So if the stack pattern contained two sets
-and you want to push them back unchanged,
-you have to specify as stack replacement
-.DS
-yields %2 %1
-.DE
-and not the other way around.
-This is known to cause errors in tables so watch out for
-this!
-.NH 3
-EM replacement
-.PP
-In exceptional cases it might be useful to leave part of an EM-pattern
-undone.
-For example, a \fBsdl\fP instruction might 
-be split into two \fBstl\fP instructions
-when there is no 4-byte quantity on the stack.
-The EM replacement part allows
-one to express this.
-It is activated by the word
-.I leaving .
-.LP
-Example:
-.DS
-leaving \fBstl\fP $1 \fBstl\fP $1+2
-.DE
-The instructions are inserted in the stream so that they can match
-the first part of a pattern in the next step.
-Note that since the code generator traverses the EM instructions in a strict
-linear fashion,
-it is impossible to let the EM replacement match later parts of a pattern.
-So if there is a pattern
-.DS
-\fBloc\fP \fBstl\fP $1==0
-.DE
-and the input is
-.DS
-\fBloc\fP 0 \fBsdl\fP 4
-.DE
-the \fBloc\fP\ 0 will be processed first,
-then the \fBsdl\fP might be split into two \fBstl\fP's but the pattern
-cannot match now.
-.NH 3
-Examples
-.PP
-A list of examples for the PDP-11 is given here.
-Far from being complete it gives examples of most kinds
-of instructions.
-.DS
-.ta 8 16 24 32 40 48 56 64
-pat loc					yields {const2, $1}
-
-pat ldc					yields {const2, loww($1)}
-					       {const2, highw($1)}
-.DE
-These simple patterns just push one or more tokens onto the fake stack.
-.DS
-.ta 8 16 24 32 40 48 56 64
-pat lof
-with REG				yields {regind2,%1,$1}
-with exact regconst2 			yields {regind2,%1.reg,$1+%1.off}
-with exact addr_external		yields {relative2,$1+%1.off}
-with exact addr_local			yields {LOCAL, %1.ind + $1,2}
-.DE
-This pattern shows the possibility to do different things
-depending on the fake stack contents,
-there are some rules for some specific cases plus a general rule,
-not preceded by
-.I exact
-that can always be taken after a coercion,
-if necessary.
-.DS
-.ta 8 16 24 32 40 48 56 64
-pat lxl $1>3
-uses REG={LOCAL, SL, 2},
-     REG={const2,$1-1}
-gen 1:
-    move {regind2,%a, SL},%a
-    sob %b,{label,1b}			yields %a
-.DE
-This rule shows register allocation with initialisation,
-and the use of a temporary label.
-The constant SL used here is defined to be the offset from lb
-of the static link,
-that is pushed by the Pascal compiler as the last argument of
-a function.
-.DS
-.ta 8 16 24 32 40 48 56 64
-pat stf
-with regconst2 xsrc2
-  kills allexeptcon
-  gen move %2,{regind2,%1.reg,$1+%1.off}
-with addr_external xsrc2
-  kills allexeptcon
-  gen move %2,{relative2,$1+%1.off}
-.DE
-This rule shows the use of a
-.I kills
-part in a store instruction.
-The set allexeptcon contains all tokens that can be the destination
-of an indirect store.
-.DS
-.ta 8 16 24 32 40 48 56 64
-pat sde
-with exact FLTREG
-  kills posextern
-  gen move %1,{relative4,$1}
-with exact ftolong
-  kills posextern
-  gen setl.
-      movfi %1.reg,{relative4,$1}
-      seti.
-with src2 src2
-  kills posextern
-  gen move %1, {relative2, $1 }
-      move %2, {relative2, $1+2}
-.DE
-The rule for
-.B sde
-shows the use of the
-.I exact
-clause in both qualities,
-the first is for correctness,
-the second for efficiency.
-The third rule is taken by default,
-resulting in two separate stores,
-nothing better exists on the PDP-11.
-.DS
-.ta 8 16 24 32 40 48 56 64
-pat sbi $1==2
-with src2 REG
-  gen sub %1,%2				yields %2
-with exact REG src2-REG
-  gen sub %2,%1
-      neg %1				yields %1
-.DE
-This rule for
-.I sbi
-has a normal first part,
-and a hand optimized special case as it's second part.
-.DS
-.ta 8 16 24 32 40 48 56 64
-pat mli $1==2
-with ODDREG src2
-  gen mul %2,%1				yields %1
-with src2 ODDREG
-  gen mul %1,%2				yields %2
-.DE
-This shows the general property for rules with commutative
-operators,
-heuristics or look ahead will have to decide which rule is the best.
-.DS
-.ta 8 16 24 32 40 48 56 64
-pat loc sli $1==1 && $2==2
-with REG
-gen asl %1				yields %1
-.DE
-A simple rule involving a longer EM-pattern,
-to make use of a specialized instruction available.
-.DS
-.ta 8 16 24 32 40 48 56 64
-pat loc loc cii $1==1 && $2==2
-with src1or2
-uses reusing %1,REG
-gen movb %1,%a				yields %a
-.DE
-A somewhat more complicated example of the same.
-Note the
-.I reusing
-clause.
-.DS
-.ta 8 16 24 32 40 48 56 64
-pat loc loc loc cii $1>=0 && $2==2 && $3==4	leaving loc $1 loc 0
-.DE
-Shows a trivial example of EM-replacement.
-This is a rule that could be done by the
-peephole optimizer,
-if word order in longs was defined in EM.
-On a `big-endian' machine the two replacement
-instructions would be the other way around.
-.DS
-.ta 8 16 24 32 40 48 56 64
-pat and $1==2
-with const2 REG
-  gen bic {const2,~%1.num},%2		yields %2
-with REG const2
-  gen bic {const2,~%2.num},%1		yields %1
-with REG REG
-  gen com %1
-      bic %1,%2				yields %2
-.DE
-Shows the way you have to twist the table,
-if an
-.I and -instruction
-is not available on your machine.
-.DS
-.ta 8 16 24 32 40 48 56 64
-pat set $1==2
-with REG
-uses REG={const2,1}
-gen ash %1,%a				yields %a
-.DE
-Shows the building of a word-size set.
-.DS
-.ta 8 16 24 32 40 48 56 64
-pat lae aar $2==2 && rom($1,3)==1 && rom($1,1)==0 
-					leaving adi 2
-
-pat lae aar $2==2 && rom($1,3)==1 && rom($1,1)!=0 
-					leaving adi 2 adp 0-rom($1,1)
-.DE
-Two rules showing the use of the rom pseudo function,
-and some array optimalisation.
-.DS
-.ta 8 16 24 32 40 48 56 64
-pat bra
-with STACK
-gen jbr {label, $1}
-.DE
-A simple jump.
-The stack pattern guarantees that everything will be stacked
-before the jump is taken.
-.DS
-.ta 8 16 24 32 40 48 56 64
-pat cal
-with STACK
-gen jsr pc,{label, $1}
-.DE
-A simple call.
-Same comments as previous rule.
-.DS
-.ta 8 16 24 32 40 48 56 64
-pat lfr $1==2				yields r0
-pat lfr $1==4				yields r1 r0
-.DE
-Shows the return area conventions of the PDP-11 table.
-At this point a reminder:
-the
-.B asp
-instruction, and some other instructions must leave
-the function return area intact.
-See the defining document for EM for exact information.
-.DS
-.ta 8 16 24 32 40 48 56 64
-pat ret $1==0
-with STACK
-gen mov lb,sp
-    rts pc
-.DE
-This shows a rule for 
-.B ret
-in a table not using register variables.
-In a table with register variables the 
-.I gen
-part would just contain
-.I return .
-.DS
-.ta 8 16 24 32 40 48 56 64
-pat blm
-with REG REG
-uses REG={const2,$1/2}
-gen 1:
-    mov {autoinc,%2},{autoinc,%1}
-    sob %a,{label,1b}
-.DE
-This rule for 
-.B blm
-already uses three registers of the same type.
-.I Cgg
-contains code to check all your rules
-to see if they can be applied from an empty fakestack.
-It uses the marriage thesis from Hall,
-a thesis from combinatorial mathematics,
-to accomplish this.
-.DS
-.ta 8 16 24 32 40 48 56 64
-pat exg $1==2
-with src2 src2				yields %1 %2
-.DE
-This rule shows the exchanging of two elements on the fake stack.
-.NH 2
-Code rules using procedures
-.PP
-To start this chapter it must be admitted at once that the
-word procedure is chosen here mainly for it's advertising
-value.
-It more resembles a glorified goto but this of course can
-not be admitted in the glossy brochures.
-This document will continue to use the word
-procedure.
-.PP
-The need for procedures was felt after the first version of
-the code generator system was made,
-mainly because of conditional instructions.
-Often the code sequences for
-.B tlt ,
-.B tle ,
-.B teq ,
-.B tne ,
-.B tge
-and
-.B tgt
-were identical apart from one opcode in the code rule.
-The code sequence had to be written out six times however.
-Not only did this increase the table size and bore the
-table writer, it also led to errors when changing the table
-since it happened now and then that five out of six
-rules were changed.
-.PP
-In general the procedures in this table format are used to
-keep one copy instead of six of the code rules for all
-sorts of conditionals and one out of two for things like
-increment/decrement.
-.PP
-And now the syntax, first the procedure definition,
-which must indeed be defined before the call because
-.I cgg
-is one-pass.
-The procedure heading replaces the EM-pattern in a code rule
-and looks like this:
-.DS
-proc <identifier> <optional example>
-.DE
-The identifier is used in later calls and the example must
-be used if expressions like $1 are used in the code rule.
-.DS
-<optional example> : example <list of EM-instructions>
-.DE
-so an example looks just like an EM-pattern, but without
-the optional boolean expression.
-The example is needed to know the types of $1 expressions.
-The current version of
-.I cgg
-does not check correctness of the example, so be careful.
-.PP
-A procedure is called with one or two string-parameters,
-that are assembler opcodes.
-They can be accessed by appending the strings `[1]' or `[2]'
-to a table opcode.
-The string `*' can be used as an equivalent for `[1]'.
-Just in case this is not clear, here is an example for
-a procedure to increment/decrement a register.
-.DS
-.ta 8 16 24 32 40 48 56 64
-incop REG:rw:cc .	/* in the INSTRUCTIONS part of course */
-
-proc incdec
-with REG
-gen incop* %1				yields %1
-.DE
-The procedure is called with parameter "inc" or "dec".
-.PP
-The procedure call is given instead of the code-part of the
-code rule and looks like this
-.DS
-call <identifier> '(' string [ ',' string ] ')'
-.DE
-which leads to the following large example:
-.DS
-.ta 8 16 24 32 40 48 56 64
-proc bxx example beq
-with src2 src2 STACK
-gen cmp %2,%1
-    jxx* {label, $1}
-
-pat blt				call bxx("jlt")
-pat ble				call bxx("jle")
-pat beq				call bxx("jeq")
-pat bne				call bxx("jne")
-pat bgt				call bxx("jgt")
-pat bge				call bxx("jge")
-.DE
-.NH 2
-Move definitions
-.PP
-We now jump back to near the beginning of the table
-where the move definitions are found.
-The move definitions directly follow the instruction
-definitions.
-.PP
-In certain cases a move is called for,
-either explicitly when a
-.I move
-instruction is used in a code rule,
-or implicitly in a register initialization.
-The different code rules possible to move data from one
-spot to another are described here.
-Example for the PDP-11:
-.DS
-.ta 8 16 24 32 40 48 56 64
-MOVES
-
-from const2 %num==0 to dst2
-gen clr %2
-
-from src2 to dst2
-gen mov %1,%2
-
-from FLTREG to longf4-FLTREG
-gen movfo %1,%2
-
-from longf4-FLTREG to FLTREG
-gen movof %1,%2
-.DE
-The example shows that the syntax is just
-.DS
-from <source> to <destination> gen <list of instructions>
-.DE
-Source and destination are a token set, optionally followed by
-a boolean expression.
-The code generator will take the first move that matches,
-whenever a move is necessary.
-.I Cgg
-checks whether all moves called for in the table are present.
-.NH 2
-Test definitions
-.PP
-This part describes the instructions necessary to set the condition codes
-to a certain token.
-These rules are needed when the
-.I test
-instruction is used in code rules.
-Example for the PDP-11:
-.DS
-.ta 8 16 24 32 40 48 56 64
-TESTS
-
-to test src2
-gen tst %1
-.DE
-So syntax is just
-.DS
-to test <source> gen <instruction list>
-.DE
-Source is the same thing as in the move definition.
-.I Cgg
-checks whether all tests called for in the table are present.
-.NH 2
-Some explanation about the rules behind coercions
-.PP
-A central part in code generation is taken by the
-.I coercions .
-It is the responsibility of the table writer to provide
-all necessary coercions so that code generation can continue.
-The minimal set of coercions are
-the coercions to unstack every token expression,
-in combination with the rules to stack every token.
-It should not be possible to smuggle a table through
-.I cgg
-without these basic set available.
-.PP
-If these are present the code generator can always make the necessary
-transformations by stacking and unstacking.
-Of course for code quality it is usually best to provide extra coercions
-to prevent this stacking to take place.
-.I Cg
-discriminates three types of coercions:
-.IP 1)
-Unstacking coercions.
-This category can use the
-.I uses
-clause in its code.
-.IP 2)
-Splitting coercions, these are the coercions that split
-larger tokens into smaller ones.
-.IP 3)
-Transforming coercions, these are the coercions that transform
-a token into another of the same size.
-This category can use the
-.I uses
-clause in its code.
-.PP
-When a stack configuration does not match the stack pattern
-.I coercions
-are searched for in the following order:
-.IP 1)
-First tokens are split if necessary to get their sizes right.
-.IP 2)
-Then transforming coercions are found that will make the pattern match.
-.IP 3)
-Finally if the stack pattern is longer than the fake stack contents
-unstacking coercions will be used to fill up the pattern.
-.PP
-At any point, when coercions are missing so code generation could not
-continue, the offending tokens are stacked.
-.NH 2
-Stack definitions
-.PP
-The next part of the table defines the stacking rules for the machine.
-Each token that may reside on the fake stack must have a rule attached
-to put it on the real stack.
-Example for the PDP-11:
-.DS
-.ta 8 16 24 32 40 48 56 64
-STACKINGRULES
-
-from const2 %num==0 to STACK
-gen clr {autodec,sp}
-
-from src2 to STACK
-gen mov %1,{autodec,sp}
-
-from regconst2 to STACK
-gen mov %1.reg,{autodec,sp}
-    add {addr_external, %1.off},{regdef2,sp}
-
-from DBLREG to STACK
-gen movf %1,{autodec,sp}
-
-from FLTREG  to STACK
-gen movfo %1,{autodec,sp}
-
-from regind8 to STACK
-uses REG
-gen move %1.reg,%a
-    add {addr_external, 8+%1.off},%a
-    mov {autodec, %a},{autodec,sp}
-    mov {autodec, %a},{autodec,sp}
-    mov {autodec, %a},{autodec,sp}
-    mov {autodec, %a},{autodec,sp}
-.DE
-.PP
-These examples should be self-explanatory, except maybe for the last one.
-It is possible inside a stacking-rule to use a register.
-Since however the stacking might also take place at a moment
-when no registers are free, it is mandatory that for each token
-there is one stackingrule that does not use a register.
-The code generator uses the first rule possible.
-.NH 2
-Coercions
-.PP
-The next part of the table defines the coercions that are possible
-on the defined tokens.
-Example for the PDP-11:
-.DS
-.ta 8 16 24 32 40 48 56 64
-COERCIONS
-
-from STACK
-uses REG
-gen mov {autoinc,sp},%a			yields %a
-
-from STACK
-uses DBLREG
-gen movf {autoinc,sp},%a		yields %a
-
-from STACK
-uses REGPAIR
-gen mov {autoinc,sp},%a.1
-    mov {autoinc,sp},%a.2		yields %a
-.DE
-These three coercions just deliver a certain type
-of register by popping it from the real stack.
-.DS
-.ta 8 16 24 32 40 48 56 64
-from LOCAL				yields {regind2,lb,%1.ind}
-
-from DLOCAL				yields {regind4,lb,%1.ind}
-
-from REG				yields {regconst2, %1, 0}
-.DE
-These three are zero-cost rewriting rules.
-.DS
-.ta 8 16 24 32 40 48 56 64
-from regconst2 %1.off==1
-uses reusing %1,REG=%1.reg
-gen inc %a				yields %a
-
-from regconst2
-uses reusing %1,REG=%1.reg
-gen add {addr_external, %1.off},%a	yields %a
-
-from addr_local
-uses REG
-gen mov lb,%a
-    add {const2, %1.ind},%a		yields %a
-.DE
-The last three are three different cases of the coercion
-register+constant to register.
-Only in the last case is it always necessary to allocate
-an extra register,
-since arithmetic on the localbase is unthinkable.
-.DS
-.ta 8 16 24 32 40 48 56 64
-from xsrc2
-uses reusing %1, REG=%1			yields %a
-
-from longf4
-uses FLTREG=%1				yields %a
-
-from double8
-uses DBLREG=%1				yields %a
-
-from src1
-uses REG={const2,0}
-gen bisb %1,%a				yields %a
-.DE
-These examples show the coercion of different
-tokens to a register of the needed type.
-The last one shows the trouble needed on a PDP-11 to
-ensure bytes are not sign-extended.
-In EM it is defined that the result of a \fBloi\fP\ 1
-instruction is an integer in the range 0..255.
-.DS
-.ta 8 16 24 32 40 48 56 64
-from REGPAIR				yields %1.2 %1.1
-
-from regind4				yields {regind2,%1.reg,2+%1.off}
-					       {regind2,%1.reg,%1.off}
-
-from relative4				yields {relative2,2+%1.off}
-					       {relative2,%1.off}
-.DE
-The last examples are splitting rules.
-.PP
-The examples show that
-all coercions change one token on the fake stack into one or more others,
-possibly generating code.
-The STACK token is supposed to be on the fake stack when it is
-really empty, and can only be changed into one other token.
-.NH 1
-The files mach.h and mach.c
-.PP
-The table writer must also supply two files containing
-machine dependent declarations and C code.
-These files are mach.h and mach.c.
-.NH 2
-Types in the code generator
-.PP
-Three different types of integer coexist in the code generator
-and their range depends on the machine at hand.
-They are defined depending on the Target EM_WSIZE, or TEM_WSIZE,
-and TEM_PSIZE.
-The type 'int' is used for things like counters that won't require
-more than 16 bits precision.
-The type 'word' is used among others to assemble datawords and
-is of type 'long' if TEM_WSIZE>2.
-The type 'full' is used for addresses and is of type 'long' if
-TEM_WSIZE>2 or TEM_PSIZE>2.
-.PP
-In macro and function definitions in later paragraphs implicit typing
-will be used for parameters, that is parameters starting with an 's'
-will be of type string, and the letters 'i','w','f' will stand for
-int, word and full respectively.
-.NH 2
-Global variables to work with
-.PP
-Some global variables are present in the code generator
-that can be manipulated by the routines in mach.h and mach.c.
-.LP
-The declarations are:
-.DS L
-.ta 20
-FILE *codefile;	/* code is emitted on this stream */
-word part_word;	/* words to be output are put together here */
-int part_size;	/* number of bytes already put in part_word */
-char str[];	/* Last string read in */
-long argval;	/* Last int read and kept */
-.DE
-.NH 2
-Macros in mach.h
-.PP
-In the file mach.h a collection of macros is defined that have
-to do with formatting of assembly code for the machine at hand.
-Some of these macros can of course be left undefined in which case the
-macro calls are left in the source and will be treated as 
-function calls.
-These functions can then be defined in \fImach.c\fR.
-.PP
-The macros to be defined are:
-.IP ex_ap(s) 16
-Must print the magic incantations that will mark the symbol \fI\fR
-to be exported to other modules.
-This is the translation of the EM \fBexa\fP and \fBexp\fP instructions.
-.IP in_ap(s)
-Same to import the symbol.
-Translation of \fBina\fP and \fBinp\fP.
-.IP newplb(s)
-Must print the definition of procedure label \fIs\fR.
-If left undefined the newilb() macro is used instead.
-.IP newilb(s)
-Must print the definition of instruction label \fIs\fR.
-.IP newdlb(s)
-Must print the definition of data label \fIs\fR.
-.IP dlbdlb(s1,s2)
-Must define data label
-.I s1
-to be equal to
-.I s2 .
-.IP newlbss(s,f)
-Must declare a piece of memory initialized to BSS_INIT(see below)
-of length 
-.I f
-and with label
-.I s .
-.IP cst_fmt
-Format to be used when converting constant arguments of
-EM instructions to string.
-Argument to be formatted will be 'full'.
-.IP off_fmt
-Format to be used for integer part of label+constant,
-argument will be 'full'.
-.IP fmt_ilb(ip,il,s)
-Must use the numbers 
-.I ip
-and 
-.I il
-that are a procedure number
-and a label number respectively and copy a string to
-.I s
-that must be unique for that combination.
-This procedure is optional, if it is not given ilb_fmt
-must be defined as below.
-.IP ilb_fmt
-Format to be used for creation of unique instruction labels.
-Arguments will be a unique procedure number (int) and the label
-number (int).
-.IP dlb_fmt
-Format to be used for printing numeric data labels.
-Argument will be 'int'.
-.IP hol_fmt
-Format to be used for generation of labels for
-space generated by a
-.B hol
-pseudo.
-Argument will be 'int'.
-.IP hol_off
-Format to be used for printing of the address of an element in
-.B hol
-space.
-Arguments will be the offset in the
-.B hol
-block (word) and the number of the
-.B hol
-(int).
-.IP con_cst(w)
-Must generate output that will assemble into one machine word.
-.IP con_ilb(s)
-Must generate output that will put the address of the instruction label
-into the datastream.
-.IP con_dlb(s)
-Must generate output that will put the address of the data label
-into the datastream.
-.IP fmt_id(sf,st)
-Must take the string in
-.I sf
-that is a nonnumeric global label, and transform it into a copy made to
-.I st
-that will not collide with reserved assembler words and system labels.
-This procedure is optional, if it is not given the id_first macro is used
-as defined below.
-.IP id_first
-Must be a character.
-This is prepended to all nonnumeric global labels if their length
-is shorter than the maximum allowed(currently 8) or if they already
-start with that character.
-This is to avoid conflicts of user labels with system labels.
-.IP BSS_INIT
-Must be a constant.
-This is the value filled in all the words not initialized explicitly.
-This is loader and system dependent.
-If omitted no initialization is assumed.
-.NH 3
-Example mach.h for the PDP-11
-.DS L
-.ta 8 16 24 32 40 48 56
-#define ex_ap(y)	fprintf(codefile,"\et.globl %s\en",y)
-#define in_ap(y)	/* nothing */
-
-#define newplb(x)	fprintf(codefile,"%s:\en",x)
-#define newilb(x)	fprintf(codefile,"%s:\en",x)
-#define newdlb(x)	fprintf(codefile,"%s:\en",x)
-#define	dlbdlb(x,y)	fprintf(codefile,"%s=%s\en",x,y)
-#define newlbss(l,x)	fprintf(codefile,"%s:.=.+%d.\en",l,x);
-
-#define cst_fmt		"$%d."
-#define off_fmt		"%d."
-#define ilb_fmt		"I%02x%x"
-#define dlb_fmt		"_%d"
-#define	hol_fmt		"hol%d"
-
-#define hol_off		"%d.+hol%d"
-
-#define con_cst(x)	fprintf(codefile,"%d.\en",x)
-#define con_ilb(x)	fprintf(codefile,"%s\en",x)
-#define con_dlb(x)	fprintf(codefile,"%s\en",x)
-
-#define id_first	'_'
-#define BSS_INIT	0
-.DE
-.NH 2
-Functions in mach.c
-.PP
-In mach.c some functions must be supplied,
-mostly manipulating data resulting from pseudoinstructions.
-The specifications are given here,
-implicit typing of parameters as above.
-.IP -
-con_part(isz,word)
-.br
-This function must manipulate the globals 
-part_word and part_size to append the isz bytes
-contained in word to the output stream.
-If part_word is full, i.e. part_size==TEM_WSIZE
-the function part_flush() may be called to empty the buffer.
-This is the function that must go through the trouble of
-doing byte order in words correct.
-.IP -
-con_mult(w_size)
-.br
-This function must take the string str[] and create an integer
-from the string of size w_size and generate code to assemble global
-data for that integer.
-Only the sizes for which arithmetic is implemented need be
-handled,
-so if you didn't implement 200-byte integer division
-you don't have to implement 200-byte integer global data.
-Here one must take care of word order in long integers.
-.IP -
-con_float()
-.br
-This function must generate code to assemble a floating
-point number of which the size is contained in argval
-and the ASCII representation in str[].
-.IP -
-prolog(f_nlocals)
-.br
-This function is called at the start of every procedure.
-Function prolog code must be generated,
-and room made for local variables for a total of f_nlocals bytes.
-.IP -
-mes(w_mesno)
-.br
-This function is called when a
-.B mes
-pseudo is seen that is not handled by the machine independent part.
-Example below shows all you probably have to know about that.
-.IP -
-segname[]
-.br
-This is not a function,
-but an array of four strings.
-These strings are put out whenever the code generator
-switches segments.
-Segments are SEGTXT, SEGCON, SEGROM and SEGBSS in that order.
-.PP
-If register variables are used in a table, the program
-.I cgg
-will define the word REGVARS during compilation of the sources.
-So the following functions described here should be bracketed
-by #ifdef REGVARS and #endif.
-.IP -
-regscore(off,size,typ,freq,totyp) long off;
-.br
-This function should assign a score to a register variable,
-the score should preferably be the estimated number of bytes
-gained when it is put in a register.
-Off and size are the offset and size of the variable,
-typ is the type, that is reg_any, reg_pointer, reg_loop or reg_float.
-Freq is the count of static occurrences, and totyp
-is the type of the register it is planned to go into.
-.br
-Keep in mind that the gain should be net, that is the cost for
-register save/restore sequences and the cost of initialisation
-in the case of parameters should already be included.
-.IP -
-i_regsave()
-.br
-This function is called at the start of a procedure, just before
-register saves are done.
-It can be used to initialise some variables if needed.
-.IP -
-f_regsave()
-.br
-This function is called at end of the register save sequence.
-It can be used to do the real saving if multiple register move
-instructions are available.
-.IP -
-regsave(regstr,off,size) char *regstr; long off;
-.br
-Should either do the real saving or set up a table to have
-it done by f_regsave.
-Note that initialisation of parameters should also be done,
-or planned here.
-.IP -
-regreturn()
-.br
-Should restore saved registers and return.
-The function result is already in the function return area by now.
-.NH 3
-Example mach.c for the PDP-11
-.PP
-As an example of the sort of code expected,
-the mach.c for the PDP-11 is presented here.
-.DS L
-.ta 8 16 24 32 40 48 56 64
-/*
- * machine dependent back end routines for the PDP-11
- */
-
-con_part(sz,w) register sz; word w; {
-
-	while (part_size % sz)
-		part_size++;
-	if (part_size == 2)
-		part_flush();
-	if (sz == 1) {
-		w &= 0xFF;
-		if (part_size)
-			w <<= 8;
-		part_word |= w;
-	} else {
-		assert(sz == 2);
-		part_word = w;
-	}
-	part_size += sz;
-}
-
-con_mult(sz) word sz; {
-	long l;
-
-	if (sz != 4)
-		fatal("bad icon/ucon size");
-	l = atol(str);
-	fprintf(codefile,"\et%o;%o\en",(int)(l>>16),(int)l);
-}
-
-con_float() {
-	double f;
-	register short *p,i;
-
-	/*
-	 * This code is correct only when the code generator is
-	 * run on a PDP-11 or VAX-11 since it assumes native
-	 * floating point format is PDP-11 format.
-	 */
-
-	if (argval != 4 && argval != 8)
-		fatal("bad fcon size");
-	f = atof(str);
-	p = (short *) &f;
-	i = *p++;
-	if (argval == 8) {
-		fprintf(codefile,"\et%o;%o;",i,*p++);
-		i = *p++;
-	}
-	fprintf(codefile,"\et%o;%o\en",i,*p++);
-}
-
-#ifdef REGVARS
-
-char Rstring[10];
-full lbytes;
-struct regadm {
-	char *ra_str;
-	long  ra_off;
-} regadm[2];
-int n_regvars;
-
-regscore(off,size,typ,score,totyp) long off; {
-
-	/*
-	 * This function is full of magic constants.
-	 * They are a result of experimentation.
-	 */
-
-	if (size != 2)
-		return(-1);
-	score -= 1;	/* allow for save/restore */
-	if (off>=0)
-		score -= 2;
-	if (typ==reg_pointer)
-		score *= 17;
-	else if (typ==reg_loop)
-		score = 10*score+50;	/* Guestimate */
-	else
-		score *= 10;
-	return(score);	/* 10 * estimated # of words of profit */
-}
-
-i_regsave() {
-
-	Rstring[0] = 0;
-	n_regvars=0;
-}
-
-f_regsave() {
-	register i;
-
-	if (n_regvars==0 || lbytes==0) {
-		fprintf(codefile,"mov r5,-(sp)\enmov sp,r5\en");
-		if (lbytes == 2)
-			fprintf(codefile,"tst -(sp)\en");
-		else if (lbytes!=0)
-			fprintf(codefile,"sub $0%o,sp\en",lbytes);
-		for (i=0;i<n_regvars;i++)
-			fprintf(codefile,"mov %s,-(sp)\en",regadm[i].ra_str);
-	} else {
-		if (lbytes>6) {
-			fprintf(codefile,"mov $0%o,r0\en",lbytes);
-			fprintf(codefile,"jsr r5,PR%s\en",Rstring);
-		} else {
-			fprintf(codefile,"jsr r5,PR%d%s\en",lbytes,Rstring);
-		}
-	}
-	for (i=0;i<n_regvars;i++)
-		if (regadm[i].ra_off>=0)
-			fprintf(codefile,"mov 0%lo(r5),%s\en",regadm[i].ra_off,
-						regadm[i].ra_str);
-}
-
-regsave(regstr,off,size) char *regstr; long off; {
-
-	fprintf(codefile,"/ Local %ld into %s\en",off,regstr);
-	strcat(Rstring,regstr);
-	regadm[n_regvars].ra_str = regstr;
-	regadm[n_regvars].ra_off = off;
-	n_regvars++;
-}
-
-regreturn() {
-
-	fprintf(codefile,"jmp RT%s\en",Rstring);
-}
-
-#endif
-
-prolog(nlocals) full nlocals; {
-
-#ifndef REGVARS
-	fprintf(codefile,"mov r5,-(sp)\enmov sp,r5\en");
-	if (nlocals == 0)
-		return;
-	if (nlocals == 2)
-		fprintf(codefile,"tst -(sp)\en");
-	else
-		fprintf(codefile,"sub $0%o,sp\en",nlocals);
-#else
-	lbytes = nlocals;
-#endif
-}
-
-mes(type) word type; {
-	int argt ;
-
-	switch ( (int)type ) {
-	case ms_ext :
-		for (;;) {
-			switch ( argt=getarg(
-			    ptyp(sp_cend)|ptyp(sp_pnam)|sym_ptyp) ) {
-			case sp_cend :
-				return ;
-			default:
-				strarg(argt) ;
-				fprintf(codefile,".globl %s\en",argstr) ;
-				break ;
-			}
-		}
-	default :
-		while ( getarg(any_ptyp) != sp_cend ) ;
-		break ;
-	}
-}
-
-char    *segname[] = {
-	".text",        /* SEGTXT */
-	".data",        /* SEGCON */
-	".data",        /* SEGROM */
-	".bss"          /* SEGBSS */
-};
-.DE
-.NH 1
-Internal workings of the code generator.
-.NH 2
-Description of tables.c and tables.h contents
-.PP
-In this section the intermediate files will be described 
-that are produced by
-.I cgg
-and compiled with machine independent code to produce a code generator.
-.NH 3
-Tables.c
-.PP
-Tables.c contains a large number of initialized array's of all sorts.
-Description of each follows:
-.br
-.in 1i
-.ti -0.5i
-byte coderules[]
-.br
-Pseudo code interpreted by the code generator.
-Always starts with some opcode followed by operands depending
-on the opcode.
-Some of the opcodes have an argument encoded in the upper three
-bits of the opcode byte.
-Integers in this table are between 0 and 32767 and have a one byte
-encoding if between 0 and 127.
-.ti -0.5i
-char wrd_fmt[]
-.br
-The format used for output of words.
-.ti -0.5i
-char stregclass[]
-.br
-Number of computed static register class per register.
-Two registers are in the same class if they have the same properties
-and don't share a common subregister.
-.ti -0.5i
-struct reginfo machregs[]
-.br
-Info per register.
-Initialized with representation string, size,
-members of the register and set of registers affected when this
-one is changed.
-Also contains room for run time information,
-like contents and reference count.
-.ti -0.5i
-tkdef_t tokens[]
-.br
-Information per tokentype.
-Initialized with size, cost, type of operands and formatstring.
-.ti -0.5i
-node_t enodes[]
-.br
-List of triples representing expressions for the code generator.
-.ti -0.5i
-string codestrings[]
-.br
-List of strings.
-All strings are put in a list and checked for duplication,
-so only one copy per string will reside here.
-.ti -0.5i
-set_t machsets[]
-.br
-List of token expression sets.
-Bit 0 of the set is used for the SCRATCH property of registers,
-bit 1 upto NREG are for the corresponding registers
-and bit NREG+1 upto the end are for corresponding tokens.
-.ti -0.5i
-inst_t tokeninstances[]
-.br
-List of descriptions for building tokens.
-Contains type of rule for building one,
-plus operands depending on the type.
-.ti -0.5i
-move_t moves[]
-.br
-List of move rules.
-Contains token expressions for source and destination
-plus index for code rule.
-.ti -0.5i
-test_t tests[]
-.br
-List of test rules.
-Contains token expressions for source
-plus index for code rule.
-.ti -0.5i
-byte pattern[]
-.br
-EM patterns.
-This is structured internally as chains of patterns,
-each chain pointed at by pathash[].
-After each pattern the list of possible code rules is given.
-.ti -0.5i
-int pathash[256]
-.br
-Indices into pattern[] for all patterns with a certain low order
-byte of the hashing function.
-.ti -0.5i
-c1_t c1coercs[]
-.br
-List of rules to stack tokens.
-Contains token expressions,
-register needed,
-cost
-and code rule.
-.ti -0.5i
-c2_t c2coercs[]
-.br
-List of splitting coercions.
-Token expressions,
-split factor,
-replacements
-and code rule.
-.ti -0.5i
-c3_t c3coercs[]
-.br
-List of one to one coercions.
-Token expressions,
-register needed,
-replacement
-and code rule.
-.ti -0.5i
-struct reginfo **reglist[]
-.br
-List of lists of pointers to register information.
-For every property the list is here
-to find the registers corresponding to it.
-.in 0
-.NH 3
-tables.h
-.PP
-In tables.h various derived constants for the tables are
-given.
-They are then used to determine array sizes in the actual code generator,
-plus loop termination in some cases.
-.NH 2
-Other important data structures
-.PP
-During code generation some other data structures are used
-and here is a short description of some of the important ones.
-.PP
-Tokens are kept in the code generator as a struct consisting of
-one integer
-.I t_token
-which is -1 if the token is a register,
-and the number of the token otherwise,
-plus an array of
-.I TOKENSIZE
-unions
-.I t_att
-of which the first is the register number in case of a register.
-.PP
-The fakestack is an array of these tokens,
-there is a global variable
-.I stackheight .
-.PP
-The results of expressions are kept in a struct
-.I result
-with elements
-.I e_typ ,
-giving the type of the expression:
-.I EV_INT ,
-.I EV_REG
-or
-.I EV_ADDR ,
-and a union
-.I e_v
-which contains the real result.
-.NH 2
-A tour through the sources
-.NH 3
-codegen.c
-.PP
-The file codegen.c contains one large function consisting
-of one giant switch statement.
-It is the interpreter for the code generator pseudo code
-as contained in code rules[].
-This function can call itself recursively when doing look ahead.
-Arguments are:
-.IP codep 10
-Pointer into code rules, pseudo program counter.
-.IP ply
-Number of EM pattern look ahead allowed.
-.IP toplevel
-Boolean telling whether this is the toplevel codegen() or
-a deeper incarnation.
-.IP costlimit
-A cutoff value to limit searches.
-If the cost crosses costlimit the incarnation can terminate.
-.IP forced
-A register number if nonzero.
-This is used inside coercions to force the allocate() call to allocate
-a register determined by earlier look ahead.
-.PP
-The instructions inplemented in the switch:
-.NH 4
-DO_DLINE
-.PP
-Prints debugging information if the code generator runs in debug mode.
-This information is only generated if
-.I cgg
-was called with the -d flag.
-.NH 4
-DO_NEXTEM
-.PP
-Matches the next EM pattern and does look ahead if necessary to find the best
-code rule associated with this pattern.
-Heuristics are used to determine best code rule when possible.
-This is done by calling the distance() function.
-It can also handle the procedure mechanism.
-.NH 4
-DO_COERC
-.PP
-This sets the code generator in the state to do a from stack coercion.
-.NH 4
-DO_XMATCH
-.PP
-This is done when a match no longer has to be checked.
-Used when the nocoercions: trick is used in the table.
-.NH 4
-DO_MATCH
-.PP
-This is the big one inside this function.
-It has the task to transform the contents of the current
-fake stack to match the pattern given after it.
-.PP
-Since the code generator does not know combining coercions,
-i.e. there is no way to make a big token out of two smaller ones,
-the first thing done is to stack every token that is too small.
-After that all tokens too big are split if possible to the right size.
-.PP
-Next the coercions are sought that would transform tokens in place to
-the right one, plus the coercions that would pop tokens of the stack.
-Each of those might need a register, so a list of registers is generated
-and at the end of looking for coercions the function 
-.I tuples()
-is called to generate the list of all possible \fIn\fP-tuples,
-where 
-.I n
-equals the number of registers needed.
-.PP
-Look ahead is now performed if the number of tuples is greater than one.
-If no possibility is found within the costlimit,
-the fake stack is made smaller by pushing the bottom token,
-and this process is repeated until either a way is found or
-the fake stack is completely empty and there is still no way
-to make the match.
-.PP
-If there is a way the corresponding coercions are executed
-and the code is finished.
-.NH 4
-DO_REMOVE
-.PP
-Here the kills clause is executed, all tokens matched by the 
-token expression plus boolean expression are pushed.
-In the current implementation there is no attempt to move those
-tokens to registers, but that is a possible future extension.
-.NH 4
-DO_DEALLOCATE
-.PP
-This one temporarily decrements by one the reference count of all registers
-contained in the token given as argument.
-.NH 4
-DO_REALLOCATE
-.PP
-Here all temporary deallocates are made undone.
-.NH 4
-DO_ALLOCATE
-.PP
-This is the part that allocates a register and decides which one to use.
-If the
-.I forced
-argument was given its task is simple,
-otherwise some work must be done.
-First the list of possible registers is scanned,
-all free registers noted and it is noted whether any of those
-registers is already
-containing the initialization.
-If no registers are available some fakestack token is stacked and the
-process is repeated.
-.PP
-After that if an exact match was found, 
-the list of registers is reduced to one register matching exactly
-out of every register class.
-Now look ahead is performed if necessary and the register chosen.
-If an initialization was given the corresponding move is performed,
-otherwise the register is marked empty.
-.NH 4
-DO_INSTR
-.PP
-This prints an instruction and it's operands.
-Only done on toplevel.
-.NH 4
-DO_MOVE
-.PP
-Calls the move() function in the code generator to implement the move
-instruction in the table.
-.NH 4
-DO_TEST
-.PP
-Calls the test() function in the code generator to implement the test
-instruction in the table.
-.NH 4
-DO_ERASE
-.PP
-Marks the register that is its argument as empty.
-.NH 4
-DO_TOKREPLACE
-.PP
-This is the token replacement part.
-It is also called if there is no token replacement because it has
-some other functions as well.
-.PP
-First the tokens that will be pushed on the fake stack are computed
-and stored in a temporary array.
-Then the tokens that were matched in this rule are popped
-and their embedded registers have their reference count
-decremented.
-After that the replacement tokens are pushed.
-.PP
-Finally all registers allocated in this rule have their reference count
-decremented.
-If they were not pushed on the fake stack they will be available again
-in the next code rule.
-.NH 4
-DO_EMREPLACE
-.PP
-Places replacement EM instructions back into the instruction stream.
-.NH 4
-DO_COST
-.PP
-Accounts for cost as given in the code rule.
-.NH 4
-DO_RETURN
-.PP
-Returns from this level of codegen().
-Is used at the end of coercions,
-move rules etc..
-.NH 3
-compute.c
-.PP
-This module computes the various expressions as given
-in the enodes[] array.
-Nothing very special happens here,
-it is just a recursive function computing leaves
-of expressions and applying the operator.
-.NH 3
-equiv.c
-.PP
-In this module the tuples() function is implemented.
-It is given the number of registers needed and
-a list of register lists and it constructs a list of tuples
-where the \fIn\fP'th register comes from the \fIn\fP'th list.
-Before the list is constructed however 
-the dynamic register classes are computed.
-Two registers are in the same dynamic class if they are in the
-same static class and their contents is the same.
-.PP
-After that the permute() recursive function is called to
-generate the list of tuples.
-After construction a generated tuple is added to the list
-if it is not already pairwise in the same class
-or if the register relations are not the same,
-i.e. if the first and second register share a common
-subregister in one tuple and not in the other they are considered different.
-.NH 3
-fillem.c
-.PP
-This is the routine that does the reading of EM instructions
-and the handling of pseudos.
-The mach.c module provided by the table writer is included
-at the end of this module.
-The routine fillemlines() is called by nextem() at toplevel
-to make sure there are enough instruction to match.
-It fills the EM instruction buffer up to 5 places from the end to
-keep room for EM replacement instructions,
-or up to a pseudo.
-.PP
-The dopseudo() function performs the function of the pseudo last
-encountered.
-If the pseudo is a 
-.B rom
-the corresponding label is saved with the contents of the
-.B rom
-to be available to the code generator later.
-The rest of the routines are small service routines for either
-input or data output.
-.NH 3
-gencode.c
-.PP
-This module contains routines called by codegen() to generate the real
-code to the codefile.
-The function genstr() gets a string as argument and copies it to codefile.
-The prtoken() function interprets the tokenformat as given in
-the tokens[] array.
-.NH 3
-glosym.c
-.PP
-This module maintains a list of global symbols that have a 
-.B rom
-pseudo associated.
-There are functions to enter a symbol and to find a symbol.
-.NH 3
-main.c
-.PP
-Main routine of the code generator.
-Processes arguments and flags.
-Flags available are:
-.IP -d
-Sets debug mode if the code generator was not compiled with
-the NDEBUG macro defined.
-The flag can be followed by a digit specifying the amount of debugging
-wanted,
-and by @labelname giving the start of debugging.
-Debug mode gives very long output on stderr indicating
-all steps of the code generation process including nesting
-of the codegen() function.
-.IP -p\fIn\fP
-Sets the look ahead depth to
-.I n ,
-the
-.I p
-stands for ply,
-a well known word in chess playing programs.
-.IP -w\fIn\fP
-Sets the weight percentage for size in the cost function to
-.I n
-percent.
-Uses Euclides algorithm to simplify rationals.
-.NH 3
-move.c
-.PP
-Function to implement the move instruction in the tables,
-register initialization and the test instruction and associated bookkeeping.
-First tests are made to try to prevent the move from really happening.
-After that, if there is an after that,
-the move rule is found and the code executed.
-.NH 3
-nextem.c
-.PP
-The entry point of this module is nextem().
-It hashes the next three EM instructions,
-and uses the low order byte of the hash
-as an index into the array pathash[],
-to find a chain of patterns in the array
-pattern[],
-that are all tried for a match.
-.PP
-The function trypat() does most of the work
-checking patterns.
-When a pattern is found to match all instructions
-the operands of the instruction are placed into the dollar[] array.
-Then the boolean expression is tried.
-If it matches the function can return,
-leaving the operands still in the dollar[] array,
-so later in the code rule they can still be used.
-.NH 3
-reg.c
-.PP
-Collection of routines to handle registers.
-Reference count routines are here,
-chrefcount() and getrefcount(),
-plus routines to erase a single register or all of them,
-erasereg() and cleanregs().
-.PP
-If NDEBUG hasn't been defined, here is also the routine that checks
-if the reference count kept with the register information is in
-agreement with the number of times it occurs on the fake stack.
-.NH 3
-salloc.c
-.PP
-Module for string allocation and garbage collection.
-Contains entry points myalloc(),
-a routine calling malloc() and checking whether room is left,
-myfree(), just free(),
-popstr() a function called from state.c to free all strings
-made since the last saved status.
-Furthermore there is salloc() which has the size of the string as parameter
-and returns a pointer to the allocated space,
-while keeping a copy of the pointer for garbage allocation purposes.
-.PP
-The function garbage_collect is called from codegen() at toplevel
-every now and then,
-and checks all places where strings may reside to mark strings
-as being in use.
-Strings not in use are returned to the pool of free space.
-.NH 3
-state.c
-.PP
-Set of routines called to save current status and
-restore a previous saved state.
-.NH 3
-subr.c
-.PP
-Random set of leftover routines.
-.NH 4
-match
-.PP
-Computes whether a certain token matches a certain token expression.
-Just computes a bitnumber according to the algorithm explained with
-machsets[],
-and tests the bit and the boolean expression if it is there.
-.NH 4
-instance,cinstance
-.PP
-These two functions compute a token from a description.
-They differ very slight, cinstance() is used to compute
-the result of a coercion in a certain context
-and therefore has more arguments, which it uses instead of
-the global information instance() works on.
-.NH 4
-eqtoken
-.PP
-eqtoken computes whether two tokens can be considered identical.
-Used to check register contents during moves mainly.
-.NH 4
-distance
-.PP
-This is the heuristic function that computes a distance from
-the current fake stack contents to the token pattern in the table.
-It likes exact matches most, then matches where at least the sizes are correct
-and if the sizes are not correct it likes too large sizes more than too
-small, since splitting a token is easier than combining one.
-.NH 4
-split
-.PP
-This function tries to find a splitting coercion
-and executes it immediately when found.
-The fake stack is shuffled thoroughly when this happens,
-so pieces below the token that must be split are saved first.
-.NH 4
-docoerc
-.PP
-This function executes a coercion that was found.
-The same shuffling is done, so the top of the stack is again saved.
-.NH 4
-stackupto
-.PP
-This function gets a pointer into the fake stack and must stack
-every token including the one pointed at up to the bottom of the fake stack.
-The first stacking rule possible is used,
-so rules using registers must come first.
-.NH 4
-findcoerc
-.PP
-Looks for a one to one coercion, if found it returns a pointer
-to it and leaves a list of possible registers to use in the global
-variable curreglist.
-This is used by codegen().
-.NH 3
-var.c
-.PP
-Global variables used by more than one module.
-External definitions are in extern.h.

+ 0 - 1555
doc/pcref.doc

@@ -1,1555 +0,0 @@
-.\" $Header$
-.ds OF \\fBtest~off:~\\fR
-.ds ON \\fBtest~on:~~\\fR
-.ds AL \\fBtest~all:~\\fR
-.ll 72
-.wh 0 hd
-.wh 60 fo
-.de hd
-'sp 5
-..
-.de fo
-'bp
-..
-.tr ~
-.               TITLE
-.de TL
-.sp 15
-.ce
-\\fB\\$1\\fR
-..
-.               AUTHOR
-.de AU
-.sp 15
-.ce
-by
-.sp 2
-.ce
-\\$1
-..
-.               DATE
-.de DA
-.sp 3
-.ce
-( Dated \\$1 )
-..
-.               INSTITUTE
-.de VU
-.sp 3
-.ce 4
-Wiskundig Seminarium
-Vrije Universiteit
-De Boelelaan 1081
-Amsterdam
-..
-.               PARAGRAPH
-.de PP
-.sp
-.ti +5
-..
-.nr CH 0 1
-.               CHAPTER
-.de CH
-.nr SH 0 1
-.bp
-.in 0
-\\fB\\n+(CH.~\\$1\\fR
-.PP
-..
-.               SUBCHAPTER
-.de SH
-.sp 3
-.in 0
-\\fB\\n(CH.\\n+(SH.~\\$1\\fR
-.PP
-..
-.               INDENT START
-.de IS
-.sp
-.in +5
-..
-.               INDENT END
-.de IE
-.in -5
-.sp
-..
-.               DOUBLE INDENT START
-.de DS
-.sp
-.in +5
-.ll -5
-..
-.               DOUBLE INDENT END
-.de DE
-.ll +5
-.in -5
-.sp
-..
-.               EQUATION START
-.de EQ
-.sp
-.nf
-..
-.               EQUATION END
-.de EN
-.fi
-.sp
-..
-.               ITEM
-.de IT
-.sp
-.in 0
-\\fBISO~\\$1:\\fR~\\
-..
-.               IMPLEMENTATION 1
-.de I1
-.IS
-.ti -3
-1.~\\
-..
-.               IMPLEMENTATION 2
-.de I2
-.sp
-.ti -3
-2.~\\
-..
-.de CS
-.br
-~-~\\
-..
-.br
-.fi
-.TL "Amsterdam Compiler Kit-Pascal reference manual"
-.AU "Johan W. Stevenson"
-.DA "January 4, 1983"
-.VU
-.CH "Introduction"
-This document refers to the (March 1980) ISO standard proposal for Pascal [1].
-Ack-Pascal complies with the requirements of this proposal almost completely.
-The standard requires an accompanying document describing the
-implementation-defined and implementation-dependent features,
-the reaction on errors and the extensions to standard Pascal.
-These four items will be treated in the rest of this document,
-each in a separate chapter.
-The other chapters describe the deviations from the standard and
-the list of options recognized by the compiler.
-.PP
-The Ack-Pascal compiler produces code for an EM machine as defined in [2].
-It is up to the implementor of the EM machine to decide whether errors like
-integer overflow, undefined operand and range bound error are recognized or not.
-For these errors the reaction of some known implementations is given.
-.PP
-There does not (yet) exist a hardware EM machine.
-Therefore, EM programs must be interpreted, or translated into
-instructions for a target machine.
-For the following implementations the behavior is documented:
-.I1
-an interpreter running on a PDP-11.
-Normally the interpreter performs some tests to detect undefined
-integers, integer overflow, range errors, etc.
-However, an option of the interpreter is to skip these tests.
-Another option is to perform some extra tests
-to check for instance the number of actual parameter
-words against the number expected by
-the called procedure.
-We will refer to these modes of operation as 'test all', 'test on' and 'test off'.
-.I2
-a translator into PDP-11 instructions.
-.IE
-.CH "Implementation-defined features"
-For each implementation-defined feature mentioned in the ISO standard
-we give the section number, the quotation from that section and the definition.
-First we quote the definition of implementation-defined:
-.DS
-Those parts of the language which may differ between processors, but which
-will be defined for any particular processor.
-.DE
-.IT 6.1.7
-Each string-character shall denote an implementation-defined value of char-type.
-.IS
-All 7-bits ASCII characters except linefeed LF (10) are allowed.
-Note that an apostrophe ' must be doubled within a string.
-.IE
-.IT 6.4.2.2
-The values of type real shall be an implementation-defined subset
-of the real numbers denoted as specified by 6.1.5.
-.IS
-The format of reals is not defined in EM.
-Even the size of reals depends on the implementation.
-The compiler can be instructed, by the f-option, to use a different
-size for real values.
-The size of reals is preset by the calling program \fIack\fP
-[4] to
-the proper size.
-For each implementation of EM the following constants must be defined:
-     epbase: the base for the exponent part
-     epprec: the precision of the fraction
-     epemin: the minimum exponent
-     epemax: the maximum exponent
-.br
-These constants must be chosen so that zero and all numbers with
-exponent e in the range
-.EQ
-     epemin <= e <= epemax
-.EN
-and fraction-parts of the form
-.EQ
-     f = +_ f\d1\u.b\u-1\d + ... + f\depprec\u.b\u-epprec\d
-.EN
-where
-.EQ
-     f\di\u = 0,...,epbase-1 and f\d1\u <> 0
-.EN
-are possible values for reals.
-All other values of type real are considered illegal.
-(See [3] for more information about these constants).
-.br
-For the known EM implementations these constants are:
-.I1
-epbase = 2
-.br
-epprec = 24
-.br
-epemin = -127
-.br
-epemax = +127
-.I2
-ditto
-.IE
-.IT 6.4.2.2
-The type char shall be the enumeration of a set of implementation-defined
-characters, some possibly without graphic representations.
-.IS
-The 7-bits ASCII character set is used, where LF (10) denotes the
-end-of-line marker on text-files.
-.IT 6.4.2.2
-The ordinal numbers of the character values shall be values of integer-type,
-that are implementation-defined, and that are determined by mapping
-the character values on to consecutive non-negative integer values
-starting at zero.
-.IS
-The normal ASCII ordering is used: ord('0')=48, ord('A')=65, ord('a')=97, etc.
-.IE
-.IT 6.4.3.4
-The largest and smallest values of integer-type
-permitted as numbers of a value
-of a set-type shall be implementation-defined.
-.IS
-The smallest value is 0. The largest value is default 15, but can be
-changed by using the i-option of the compiler up to a maximum
-of 32767.
-The compiler allocates as many bits for set-type variables as are necessary
-to store all possible values of the host-type of the base-type of the set,
-rounded up to the nearest multiple of 16.
-If 8 bits are sufficient then only
-8 bits are used if part of a packed structure.
-Thus, the variable s, declared by
-.EQ
-     var s: set of '0'..'9';
-.EN
-will contain 128 bits, not 10 or 16.
-These 128 bits are stored in 16 bytes, both for packed and unpacked sets.
-If the host-type of the base-type is integer, then the
-number of bits depends on the i-option.
-The programmer may specify how many bits to allocate for these sets.
-The default is 16, the maximum is 32767.
-The effective number of bits is rounded up to the next multiple of 16, or up
-to 8 if the number of bits is less than or equal to 8.
-Note that the use of set-constructors for sets with more than 256 elements
-is far less efficient than for smaller sets.
-.IT 6.7.2.2
-The predefined constant maxint shall be of integer-type and shall denote
-an implementation-defined value, that satisfies the following conditions:
-.sp 1
-.in +5
-.ti -4
-(a)~All integral values in the closed interval from -maxint to +maxint
-shall be values in the integer-type.
-.ti -4
-(b)~Any monadic operation performed on an integer value in this interval
-shall be correctly performed according to the mathematical rules for
-integer arithmetic.
-.ti -4
-(c)~Any dyadic integer operation on two integer values in this same interval
-shall be correctly performed according to the mathematical rules for
-integer arithmetic, provided that the result is also in this interval.
-.ti -4
-(d)~Any relational operation on two integer values in this same interval
-shall be correctly performed according to the mathematical rules for
-integer arithmetic.
-.in -5
-.IS
-The representation of integers in EM is a \fIn\fP*8-bit word using
-two's complement arithmetic.
-Where \fIn\fP is called wordsize.
-The compiler can only generate code for EM with wordsize 2.
-Thus always:
-.EQ
-     maxint = 32767
-.EN
-Because the number -32768 may be used to indicate 'undefined', the
-range of available integers depends on the EM implementation:
-.I1
-\*(ON-32767..+32767.
-.br
-\*(OF-32768..+32767.
-.I2
--32768..+32767.
-.IE
-.IT 6.9.4.2
-The default TotalWidth values for integer, Boolean and real types
-shall be implementation-defined.
-.IS
-The defaults are:
-     integer    6
-     Boolean    5
-     real      13
-.IT 6.9.4.5.1
-ExpDigits, the number of digits written in an exponent part of a real,
-shall be implementation-defined.
-.IS
-ExpDigits is defined as
-.EQ
-     ceil(log10(log10(2 ** epemax)))
-.EN
-For the current implementations this evaluates to 2.
-.IT 6.9.4.5.1
-The character written as part of the representation of
-a real to indicate the beginning of the exponent part shall be
-implementation-defined, either 'E' or 'e'.
-.IS
-The exponent part starts with 'e'.
-.IT 6.9.4.6
-The case of the characters written as representation of the
-Boolean values shall be implementation-defined.
-.IS
-The representations of true and false are 'true' and 'false'.
-.IT 6.9.6
-The effect caused by the standard procedure page
-on a text file shall be implementation-defined.
-.IS
-The ASCII character form feed FF (12) is written.
-.IT 6.10
-The binding of the variables denoted by the program-parameters
-to entities external to the program shall be implementation-defined if
-the variable is of a file-type.
-.IS
-The program parameters must be files and all, except input and output,
-must be declared as such in the program block.
-.PP
-The program parameters input and output, if specified, will correspond
-with the UNIX streams 'standard input' and 'standard output'.
-.PP
-The other program parameters will be mapped to the argument strings
-provided by the caller of this program.
-The argument strings are supposed to be path names of the files to be
-opened or created.
-The order of the program parameters determines the mapping:
-the first parameter is mapped onto the first argument string etc.
-Note that input and output are ignored in this mapping.
-.PP
-The mapping is recalculated each time a program parameter
-is opened for reading or writing by a call to the standard procedures
-reset or rewrite.
-This gives the programmer the opportunity to manipulate the list
-of string arguments using the external procedures argc, argv and argshift
-available in libpc [7].
-.IT 6.10
-The effect of an explicit use of reset or rewrite
-on the standard textfiles input or output shall be implementation-defined.
-.IS
-The procedures reset and rewrite are no-ops
-if applied to input or output.
-.CH "Implementation-dependent features"
-For each implementation-dependent feature mentioned in the ISO standard draft,
-we give the section number, the quotation from that section and the way
-this feature is treated by the Ack-Pascal system.
-First we quote the definition of 'implementation-dependent':
-.DS
-Those parts of the language which may differ between processors,
-and for which there need not be a definition for a particular processor.
-.DE
-.IT 5.1.1
-The method for reporting errors or warnings shall be implementation-dependent.
-.IS
-The error handling is treated in a following chapter.
-.IE
-.IT 6.1.4
-Other implementation-dependent directives may be defined.
-.IS
-Except for the required directive 'forward' the Ack-Pascal compiler recognizes
-only one directive: 'extern'.
-This directive tells the compiler that the procedure block of this
-procedure will not be present in the current program.
-The code for the body of this procedure must be included at a later
-stage of the compilation process.
-.PP
-This feature allows one to build libraries containing often used routines.
-These routines do not have to be included in all the programs using them.
-Maintenance is much simpler if there is only one library module to be
-changed instead of many Pascal programs.
-.PP
-Another advantage is that these library modules may be written in a different
-language, for instance C or the EM assembly language.
-This is useful if you want to use some specific EM instructions not generated
-by the Pascal compiler. Examples are the system call routines and some
-floating point conversion routines.
-Another motive could be the optimization of some time-critical program parts.
-.PP
-The use of external routines, however, is dangerous.
-The compiler normally checks for the correct number and type of parameters
-when a procedure is called and for the result type of functions.
-If an external routine is called these checks are not sufficient,
-because the compiler can not check whether the procedure heading of the
-external routine as given in the Pascal program matches the actual routine
-implementation.
-It should be the loader's task to check this.
-However, the current loaders are not that smart.
-Another solution is to check at run time, at least the number of words
-for parameters. Some EM implementations check this:
-.I1
-\*(ALthe number of words passed as parameters is checked, but this will not catch all faulty cases.
-.br
-\*(ONnot checked.
-.I2
-not checked.
-.IE
-.PP
-For those who wish the use the interface between C and Pascal we
-give an incomplete list of corresponding formal parameters in C and Pascal.
-.sp 1
-.ta 8 37
-.nf
-	Pascal	C
-	a:integer	int a
-	a:char	int a
-	a:boolean	int a
-	a:real	double a
-	a:^type	type *a
-	var a:type	type *a
-	procedure a(pars)	struct {
-		     void (*a)() ;
-		     char *static_link ;
-		}
-	function a(pars):type	struct {
-		     type (*a)() ;
-		     char *static_link ;
-		}
-.fi
-The Pascal runtime system uses the following algorithm when calling
-function/procedures passed as parameters.
-.nf
-.ta 8 16
-	if ( static_link ) (*a)(static_link,pars) ;
-	else               (*a)(pars) ;
-.fi
-.IT 6.7.2.1
-The order of evaluation of the operands of a dyadic operator
-shall be implementation-dependent.
-.IS
-Operands are always evaluated, so the program part
-.EQ
-     if (p<>nil) and (p^.value<>0) then
-.EN
-is probably incorrect.
-.PP
-The left-hand operand of a dyadic operator is almost always evaluated
-before the right-hand side.
-Some peculiar evaluations exist for the following cases:
-.IS
-.ti -3
-1.~\
-the modulo operation is performed by a library routine to
-check for negative values of the right operand.
-.IE
-.sp
-.ti -3
-2.~\
-the expression
-.EQ
-     set1 <= set2
-.EN
-where set1 and set2 are compatible set types is evaluated in the
-following steps:
-.IS
-.CS
-evaluate set2
-.CS
-evaluate set1
-.CS
-compute set2+set1
-.CS
-test set2 and set2+set1 for equality
-.IE
-This is the only case where the right-hand side is computed first.
-.sp
-.ti -3
-3.~\
-the expression
-.EQ
-     set1 >= set2
-.EN
-where set1 and set2 are compatible set types is evaluated in the following steps:
-.IS
-.CS
-evaluate set1
-.CS
-evaluate set2
-.CS
-compute set1+set2
-.CS
-test set1 and set1+set2 for equality
-.IE
-.IT 6.7.3
-The order of evaluation, accessing and binding
-of the actual-parameters for functions
-shall be implementation-dependent.
-.IS
-The order of evaluation is from right to left.
-.IT 6.8.2.2
-If access to the variable in an assignment-statement involves the indexing of an array
-and/or a reference to a field within a variant of a record
-and/or the de-referencing of a pointer-variable
-and/or a reference to a buffer-variable,
-the decision whether these actions precede or follow the evaluation
-of the expression shall be implementation-dependent.
-.IS
-The expression is evaluated first.
-.IT 6.8.2.3
-The order of evaluation and binding of the actual-parameters for procedures
-shall be implementation-dependent.
-.IS
-The same as for functions.
-.IT 6.9.6
-The effect of inspecting a text file to which the page
-procedure was applied during generation is
-implementation-dependent.
-.IS
-The formfeed character written by page is
-treated like a normal character, with ordinal value 12.
-.IT 6.10
-The binding of the variables denoted by the program-parameters
-to entities external to the program shall be implementation-dependent unless
-the variable is of a file-type.
-.IS
-Only variables of a file-type are allowed as program parameters.
-.IE
-.CH "Error handling"
-There are three classes of errors to be distinguished.
-In the first class are the error messages generated by the compiler.
-The second class consists of the occasional errors generated by the other
-programs involved in the compilation process.
-Errors of the third class are the errors as defined in the standard by:
-.DS
-An error is a violation by a program of the requirements of this standard
-such that detection normally requires execution of the program.
-.DE
-.SH "Compiler errors"
-The error messages (and the listing) are not generated by the compiler itself.
-The compiler only detects errors and writes the errors in condensed form on
-an intermediate file.
-Each error in condensed form contains:
-.IS
-.CS
-an optional error message parameter (identifier or number).
-.CS
-an error number
-.CS
-a line number
-.CS
-a column number.
-.IE
-Every time the compiler detects an error that does not have influence
-on the code produced by the compiler or on the syntax decisions, a warning
-messages is given.
-If only warnings are generated, compilation proceeds and probably results
-in a correctly compiled program.
-.PP
-The intermediate error file is read by the interface program
-\fIack\fP [4],
-that produces the error messages.
-It uses an other file, the error message file,
-to find an error script line.
-Whenever this error script line contains the character '%', the error messages
-parameter is substituted.
-For negative error numbers the message constructed is prepended with 'Warning: '.
-.PP
-Sometimes the compiler produces several errors for the same file position
-(line number, column number).
-Only the first of these messages is given, because the others are probably
-directly caused by the first one.
-If the first one is a warning while one of its successors for that position
-is a fatal message, then the warning is promoted to a fatal one.
-However, parameterized messages are always given.
-.PP
-The error messages and listing come in three flavors, selected by flags
-given to \fIack\fP [4]:
-.in +10
-.sp
-.ti -8
-default:no listing, one line per error giving the file name
-of the Pascal source file, the line number and the error messages.
-.sp
-.ti -8
--e:~~~~~for each erroneous line a listing of the line and its predecessor.
-The next line contains one or more characters '^' pointing to the
-places where an error is detected.
-For each error on that line a message follows.
-.sp
-.ti -8
--E:~~~~~same as for '-e', except that all source lines are listed,
-even if the program is perfect.
-.IE
-.IE
-.SH "Other errors detected at compilation time"
-Two main categories: file system problems and table overflow.
-Problems with the file system may be caused by protection (you may not read
-or create files) or by space problems (no space left on device; out of inodes;
-too many processes).
-Table overflow problems are often caused by peculiar source programs:
-very long procedures or functions, a lot of strings.
-Table overflow problems can sometimes be cured
-by giving a flag (-sl when producing e.out files) to \fIack\fP [4].
-.PP
-Extensive treatment of these errors is outside the scope of this manual.
-.SH "Runtime errors"
-Errors detected at run time cause an error message to be generated on the
-diagnostic output stream (UNIX file descriptor 2).
-The message consists of the name of the program followed by a message
-describing the error, possibly followed by the source line number.
-Unless the l-option is turned off, the compiler generates code to keep track
-of which source line causes which EM instructions to be generated.
-It depends on the EM implementation whether these LIN instructions
-are skipped or executed:
-.I1
-LIN instructions are always executed. The old line number is saved and
-restored whenever a procedure or function is called.
-All error messages contain this line number, except when the l-option
-was turned off.
-.I2
-same as above, but line numbers are not saved when procedures and functions
-are called.
-.IE
-For each error mentioned in the standard we give the section number,
-the quotation from that section and the way it is processed by the
-Pascal-compiler or runtime system.
-.PP
-For detected errors the corresponding message
-and trap number are given.
-Trap numbers are useful for exception-handling routines.
-Normally, each error causes the program to terminate.
-By using exception-handling routines one can
-ignore errors or perform alternate actions.
-Only some of the errors can be ignored
-by restarting the failing instruction.
-These errors are marked as non-fatal,
-all others as fatal.
-A list of errors with trap number between 0 and 63
-(EM errors) can be found in [2].
-Errors with trap number between 64 and 127 (Pascal errors) are listed in [8].
-.IT 6.4.3.3
-It shall be an error if any field-identifier defined within a variant
-is used in a field-designator unless the value of the tag-field
-is associated with that variant.
-.IS
-This error is not detected.
-Sometimes this feature is used to achieve easy type conversion.
-However, using record variants this way is dangerous, error prone and not portable.
-.IT 6.4.6
-It shall be an error if a value of type T2 must be
-assignment-compatible with type T1, while
-T1 and T2 are compatible ordinal-types and the value of
-type T2 is not in the closed interval specified by T1.
-.IS
-The compiler distinguishes between array-index expressions and the other
-places where assignment-compatibility is required.
-.PP
-Array subscripting is done using the EM array instructions.
-These instructions have three arguments: the array base address,
-the index and the address of the array descriptor.
-An array descriptor describes one dimension by three values:
-the element size, the lower bound on the index and the number of elements
-minus one.
-It depends on the EM implementation whether these bounds are checked:
-.I1
-\*(ONchecked (array bound error, trap 0, non-fatal).
-.br
-\*(OFnot checked
-.I2
-not checked.
-.IE
-The other places where assignment-compatibility is required are:
-.IS
-.CS
-assignment
-.CS
-value parameters
-.CS
-procedures read and readln
-.CS
-the final value of the for-statement
-.IE
-For these places the compiler generates an EM range check instruction, except
-when the r-option is turned off, or when the range of values of T2
-is enclosed in the range of T1.
-If the expression consists of a single variable and if that variable
-is of a subrange type,
-then the subrange type itself is taken as T2, not its host-type.
-Therefore, a range instruction is only generated if T1 is a subrange type
-and if the expression is a constant, an expression with two or more
-operands, or a single variable with a type not enclosed in T1.
-If a constant is assigned, then the EM optimizer removes the range check
-instruction, except when the value is out of bounds.
-.PP
-It depends on the EM implementation whether the range check instruction
-is executed or skipped:
-.I1
-\*(ONchecked (range bound error, trap 1, non-fatal).
-.br
-\*(OFskipped
-.I2
-skipped
-.IE
-.IT 6.4.6
-It shall be an error if a value of type T2 must be
-assignment-compatible with type T1, while T1 and T2 are compatible
-set-types and any member of the value of type T2
-is not in the closed interval specified by the base-type
-of the type T1.
-.IS
-This error is not detected.
-.IT 6.5.4
-It shall be an error if
-the pointer-variable has a nil-value or is undefined at the time
-it is de-referenced.
-.IS
-The EM definition does not specify the binary representation of pointer
-values, so that it is not possible to choose an otherwise illegal
-binary representation for the pointer value NIL.
-Rather arbitrary the compiler uses the integer value zero to represent NIL.
-For all current implementations this does not cause problems.
-.PP
-The size of pointers depends on the implementation and is
-preset in the compiler by \fIack\fP [4].
-The compiler can be instructed, by the p-option, to use
-any size for pointer objects.
-NIL is represented here by the appropriate number of zero words.
-.PP
-It depends on the EM implementation whether de-referencing of a pointer
-with value NIL causes an error:
-.I1
-\*(ONfor every de-reference the pointer value is checked to be legal.
-The value NIL is always illegal.
-Objects addressed by a NIL pointer always cause an error, except
-when they are part of some extraordinary sized structure
-(bad pointer, trap 22, fatal).
-.br
-\*(OFde-referencing for fetching will not cause
-an error to occur.
-However, if the pointer value is used for a store operation,
-a segmentation violation probably results (memory fault, trap 21, fatal).
-(Note: this is only true if the interpreter is executed with coinciding
-address spaces and protected text part. The interpreter must therefore
-be loaded with the '-n' option of the UNIX loader [5]).
-.I2
-de-referencing for a fetch operation will not cause an error.
-A store operation probably causes an error if the '-n' flag is
-specified to \fIack\fP [4] or ld [5] while loading your program.
-.IE
-Some implementations of EM initialize all memory cells for newly
-created variables with a constant that probably causes an error if that variable
-is not initialized with a value of its own type before use.
-For each implementation we give whether memory cells are initialized,
-with what value, and whether this value causes an error if de-referenced.
-.I1
-each memory word is initialized with the bit representation 1000000000000000,
-representing -32768 in 2's complement notation.
-For most small and medium sized programs this value will cause a segmentation
-violation (memory fault, trap 21, fatal).
-.I2
-no initialization.
-Whenever a pointer is de-referenced, without being properly initialized,
-a segmentation violation (memory fault, trap 21, fatal)
-or 'bus error' are possible.
-.IE
-.IT 6.5.5
-It shall be an error if the value of a file-variable f is altered
-while the buffer-variable is an actual variable parameter, or
-an element of the record-variable-list of a with-statement, or both.
-.IS
-This error is not detected
-.IT 6.5.5
-It shall be an error if the value of a file-variable f is altered
-by an assignment-statement which contains the buffer-variable f^ in
-its left-hand side.
-.IS
-This error is not detected.
-.IT 6.6.5.2
-It shall be an error if
-the stated pre-assertion does not hold immediately
-prior to any use of the file handling procedures
-rewrite, put, reset and get.
-.IS
-For each of these four operations the pre-assertions
-can be reformulated as:
-.sp
-rewrite(f):~no pre-assertion.
-.br
-put(f):~~~~~f is opened for writing and f^ is not undefined.
-.br
-reset(f):~~~f exists.
-.br
-get(f):~~~~~f is opened for reading and eof(f) is false.
-.sp
-The following errors are detected for these operations:
-.sp
-rewrite(f):
-.in +10
-.ti -5
-more args expected, trap 64, fatal:
-.br
-f is a program-parameter and the corresponding
-file name is not supplied by the caller of the program.
-.ti -5
-rewrite error, trap 101, fatal:
-.br
-the caller of the program lacks the necessary
-access rights to create the file in the file system
-or operating system problems like table overflow
-prevent creation of the file.
-.in -10
-.sp
-put(f):
-.in +10
-.ti -5
-file not yet open, trap 72, fatal:
-.br
-reset or rewrite are never applied to the file.
-The checks performed by the run time system are not foolproof.
-.ti -5
-not writable, trap 96, fatal:
-.br
-f is opened for reading.
-.ti -5
-write error, trap 104, fatal:
-.br
-probably caused by file system problems.
-For instance, the file storage is exhausted.
-Because IO is buffered to improve performance,
-it might happen that this error occurs if the
-file is closed.
-Files are closed whenever they are rewritten or reset, or on
-program termination.
-.in -10
-.sp
-reset(f):
-.in +10
-.ti -5
-more args expected, trap 64, fatal:
-.br
-same as for rewrite(f).
-.ti -5
-reset error, trap 100, fatal:
-.br
-f does not exist, or the caller has insufficient access rights, or
-operating system tables are exhausted.
-.in -10
-.sp
-get(f):
-.in +10
-.ti -5
-file not yet open, trap 72, fatal:
-.br
-as for put(f).
-.ti -5
-not readable, trap 97, fatal:
-.br
-f is opened for writing.
-.ti -5
-end of file, trap 98, fatal:
-.br
-eof(f) is true just before the call to get(f).
-.ti -5
-read error, trap 103, fatal:
-.br
-unlikely to happen. Probably caused by hardware problems
-or by errors elsewhere in your program that destroyed
-the file information maintained by  the run time system.
-.ti -5
-truncated, trap 99, fatal:
-.br
-the file is not properly formed by an integer
-number of file elements.
-For instance, the size of a file of integer is odd.
-.ti -5
-non-ASCII char read, trap 106, non-fatal:
-.br
-the character value of the next character-type
-file element is out of range (0..127).
-Only for text files.
-.in -10
-.IT 6.6.5.3
-It shall be an error to change any variant-part of a variable
-allocated by the form new(p,c1,...,cn) from the variant specified.
-.IS
-This error is not detected.
-.IT 6.6.5.3
-It shall be an error if a variable to be disposed had been allocated
-using the form new(p,c1,...,cn) with more variants specified than
-specified to dispose.
-.IS
-This error can cause more memory to be freed then was allocated.
-Dispose causes a fatal trap 73 when memory already on the free
-list is freed again.
-.IT 6.6.5.3
-It shall be an error if the variants of a variable to be disposed
-are different from those specified by the case-constants to dispose.
-.IS
-This error is not detected.
-.IT 6.6.5.3
-It shall be an error if the value of the pointer parameter of dispose has
-nil-value or is undefined.
-.IS
-The same comments apply as for de-referencing NIL or undefined pointers.
-.IT 6.6.5.3
-It shall be an error if a variable that is identified by the pointer parameter
-of dispose (or a component thereof) is currently either an actual
-variable parameter, or an element of the record-variable-list of a
-with-statement, or both.
-.IS
-This error is not detected.
-.IT 6.6.5.3
-It shall be an error if a referenced-variable created using the second form
-of new is used in its entirety
-as an operand in an expression, or as the variable in an assignment-statement
-or as an actual-parameter.
-.IS
-This error is not detected.
-.IT 6.6.6.2
-It shall be an error if the mathematical defined result of an
-arithmetic function would fall outside the set of values
-of the indicated result.
-.IS
-Except for the errors for undefined arguments,
-the following errors may occur for the arithmetic functions:
-.in +16
-.ti -11
-abs(x):~~~~none.
-.ti -11
-sqr(x):~~~~real underflow, trap 5, non-fatal;
-.br
-real overflow, trap 4, non-fatal
-.ti -11
-sin(x):~~~~real underflow, trap 5, non-fatal
-.ti -11
-cos(x):~~~~real underflow, trap 5, non-fatal
-.ti -11
-exp(x):~~~~error in exp, trap 65, non-fatal (if x>10000);
-.br
-real underflow, trap 5, non-fatal;
-.br
-real overflow, trap 4, non-fatal
-.ti -11
-ln(x):~~~~~error in ln, trap 66, non-fatal ( if x<=0)
-.ti -11
-sqrt(x):~~~error in sqrt, trap 67, non-fatal (if x<0)
-.ti -11
-arctan(x):~real underflow, trap 5, non-fatal;
-.br
-real overflow, trap 4, non-fatal
-.in -16
-.IE
-.IT 6.6.6.2
-It shall be an error if x in ln(x) is not greater than zero.
-.IS
-See above.
-.IT 6.6.6.2
-It shall be an error if x in sqrt(x) is negative.
-.IS
-See above.
-.IT 6.6.6.2
-It shall be an error if
-the integer value of trunc(x) does not exist.
-.IS
-This error is detected (conversion error, trap 10, non-fatal).
-.IT 6.6.6.2
-It shall be an error if
-the integer value of round(x) does not exist.
-.IS
-This error is detected (conversion error, trap 10, non-fatal).
-.IT 6.6.6.2
-It shall be an error if
-the integer value of ord(x) does not exist.
-.IS
-This error can not occur, because the compiler will not allow
-such ordinal types.
-.IT 6.6.6.2
-It shall be an error if
-the character value of chr(x) does not exist.
-.IS
-Except when the r-option is turned off, the compiler generates an EM
-range check instruction. The effect of this instruction depends on the
-EM implementation as described before.
-.IT 6.6.6.2
-It shall be an error if the value of succ(x) does not exist.
-.IS
-Same comments as for chr(x).
-.IT 6.6.6.2
-It shall be an error if the value of pred(x) does not exist.
-.IS
-Same comments as for chr(x).
-.IT 6.6.6.5
-It shall be an error if
-f in eof(f) is undefined.
-.IS
-This error is detected (file not yet open, trap 72, fatal).
-.IT 6.6.6.5
-It shall be an error if
-f in eoln(f) is undefined, or if eof(f) is true at that time.
-.IS
-The following errors may occur:
-.IS
-file not yet open, trap 72, fatal;
-.br
-not readable, trap 97, fatal;
-.br
-end of file, trap 98, fatal.
-.IE
-.IT 6.7.1
-It shall be an error if any variable or function used as an operand in an expression is
-undefined at the time of its use.
-.IS
-Detection of undefined operands is only possible if there is at least one bit
-representation that is not allowed as legal value.
-The set of legal values depends on the type of the operand.
-To detect undefined operands, all newly created variables must be assigned
-a value illegal for the type of the created variable.
-The compiler itself does not generate code to initialize newly created variables.
-Instead, the compiler generates code to allocate some new memory cells.
-It is up to the EM implementation to initialize these memory cells.
-However, the EM machine does not know the types of the variables for which
-memory cells are allocated.
-Therefore, the best an EM implementation can do is to initialize with a value
-that is illegal for the most common types of operands.
-.PP
-For all current EM implementations we will describe whether memory cells
-are initialized, which value is used to initialize, for each operand type
-whether that value is illegal, and for all operations on all operand
-types whether that value is detected as undefined.
-.I1
-\*(ONnew memory words are initialized with -32768.
-Assignment of this value is always allowed. Errors may occur
-whenever undefined operands are used in operations.
-.br
-.ul
-integer:
--32768 is illegal. All arithmetic operations (except unary +) cause
-an error (undefined integer, trap 8, non-fatal).
-Relational operations do not, except for IN when the left operand is undefined.
-Printing of -32768 using write is allowed.
-.br
-.ul
-real:
-the bit representation of a real, caused by initializing the constituent
-memory words with -32768, is illegal.
-All arithmetic and relational operations (except unary +) cause an error
-(real undefined, trap 9, non-fatal).
-Printing causes the same error.
-.br
-.ul
-char:
-the value -32768 is illegal. For objects of type 'packed array[] of char'
-half the characters will have the value chr(0), which is legal, and the
-others will have the value chr(128), outside the valid ASCII range.
-The relational operators, however, do not cause an error.
-.br
-.ul
-Boolean:
-the value -32768 is illegal. For objects of type 'packed array[] of boolean'
-half the booleans will have the value false, while the others have the value v,
-where ord(v) = 128, naturally illegal.
-However, the Boolean and relational operations do not cause an error.
-.br
-.ul
-set:
-undefined operands of type set can not be distinguished from
-properly initialized ones.
-The set and relational operations, therefore, can never cause an error.
-However, if one forgets to initialize a set of character, then spurious
-characters like '/', '?', 'O', '_' and 'o' appear.
-.sp
-\*(OFnew memory cells are initialized with -32768.
-The only cases where this value causes an error are when
-an undefined operand of type real is used in an arithmetic or relational
-operation (except unary +) or when an undefined real is used as an
-argument to a standard function.
-.I2
-Newly created memory cells are not initialized and therefore
-they have a random value.
-.IT 6.7.1
-It shall be an error if
-the value of any member denoted by any member-designator of the
-set-constructor is outside the implementation-defined limits.
-.IS
-This error is detected (set bound error, trap 2, non-fatal).
-.IT 6.7.1
-It shall be an error if
-the possible types of an set-constructor do not permit it
-to assume a suitable type.
-.IS
-The compiler allocates as many bits as are necessary to store all
-elements of the host-type of the base-type of the set, not the
-base-type itself.
-Therefore, all possible errors can be detected at compile time.
-.IT 6.7.2.2
-It shall be an error if j is zero in 'i div j'.
-.IS
-It depends on the EM implementation whether this error is detected:
-.I1
-\*(ONdetected (divide by 0, trap 6, non-fatal).
-.br
-\*(OFnot detected.
-.I2
-not detected.
-.IE
-.IT 6.7.2.2
-It shall be an error if
-j is zero or negative in i MOD j.
-.IS
-This error is detected (only positive j in 'i mod j', trap 71, non-fatal).
-.IT 6.7.2.2
-It shall be an error if the result of any operation on integer
-operands is not performed according to the mathematical
-rules for integer arithmetic.
-.IS
-The reaction depends on the EM implementation:
-.I1
-\*(ONerror detected if
-.EQ
-     (result >= 32768) or (result < -32768).
-.EN
-(integer overflow, trap 3, non-fatal).
-Note that if the result is -32768 the use of this value in further operations
-may cause an error.
-.br
-\*(OFnot detected.
-.I2
-not detected.
-.IT 6.8.3.5
-It shall be an error if none of the case-constants is equal to the value of the
-case-index upon entry to the case-statement.
-.IS
-This error is detected (case error, trap 20, fatal).
-.IT 6.8.3.9
-It shall be an error if the final-value of a for-statement is not
-assignment-compatible with the control-variable when the
-initial-value is assigned to the control-variable.
-.IS
-It is detected if the control variable leaves
-its allowed range of values while stepping
-from initial to final value.
-This is equivalent with the requirements if the
-for-statement is not terminated before
-the final value is reached.
-.IT 6.9.2
-It shall be an error if the sequence of characters read looking for an integer does not
-form a signed-integer as specified in 6.1.5.
-.IS
-This error is detected (digit expected, trap 105, non-fatal).
-.IT 6.9.2
-It shall be an error if the sequence of characters read looking for a real does not
-form a signed-number as specified in 6.1.5.
-.IS
-This error is detected (digit expected, trap 105, non-fatal).
-.IT 6.9.2
-It shall be an error if read is applied to f while f is undefined or
-not opened for reading.
-.IS
-This error is detected (see get(f)).
-.IT 6.9.4
-It shall be an error if write is applied to f while f is undefined or
-not opened for writing.
-.IS
-This error is detected (see put(f)).
-.IT 6.9.4
-It shall be an error if TotalWidth or FracDigits as specified in
-write or writeln procedure calls are less than one.
-.IS
-This error is not detected. Moreover, it is considered an extension to
-allow zero or negative values.
-.IT 6.9.6
-It shall be an error if page is applied to f while f is undefined or
-not opened for writing.
-.IS
-This error is detected (see put(f)).
-.CH "Extensions to the standard"
-.IS
-.ti -3
-1.~\
-Separate compilation.
-.sp
-The compiler is able to (separately) compile a collection of declarations,
-procedures and functions to form a library.
-The library may be linked with the main program, compiled later.
-The syntax of these modules is
-.EQ
-     module = [constant-definition-part]
-              [type-definition-part]
-              [var-declaration-part]
-              [procedure-and-function-declaration-part]
-.EN
-The compiler accepts a program or a module:
-.EQ
-     unit = program | module
-.EN
-All variables declared outside a module must be imported
-by parameters, even the files input and output.
-Access to a variable declared in a module is only possible
-using the procedures and functions declared in that same module.
-By giving the correct procedure/function heading followed by the
-directive 'extern' you may use procedures and functions declared in
-other units.
-.sp
-.ti -3
-2.~\
-Assertions.
-.sp
-The Ack-Pascal compiler recognizes an additional statement, the assertion.
-Assertions can be used as an aid in debugging and documentation.
-The syntax is:
-.EQ
-     assertion = 'assert' Boolean-expression
-.EN
-An assertion is a simple-statement, so
-.EQ
-     simple-statement = [assignment-statement |
-                         procedure-statement |
-                         goto-statement |
-                         assertion
-                        ]
-.EN
-An assertion causes an error if the Boolean-expression is false.
-That is its only purpose.
-It does not change any of the variables, at least it should not.
-Therefore, do not use functions with side-effects in the Boolean-expression.
-If the a-option is turned off, then assertions are skipped by the
-compiler. 'assert' is not a word-symbol (keyword) and may be used as identifier.
-However, assignment to a variable and calling of a procedure with that name will be impossible.
-.sp
-.ti -3
-3.~\
-Additional procedures.
-.sp
-Three additional standard procedures are available:
-.IS
-.IS
-.ti -8
-halt:~~~a call of this procedure is equivalent to jumping to the
-end of your program. It is always the last statement executed.
-The exit status of the program may be supplied
-as optional argument.
-.ti -8
-release:
-.ti -8
-mark:~~~for most applications it is sufficient to use the heap as second stack.
-Mark and release are suited for this type of use, more suited than dispose.
-mark(p), with p of type pointer, stores the current value of the
-heap pointer in p. release(p), with p initialized by a call
-of mark(p), restores the heap pointer to its old value.
-All the heap objects, created by calls of new between the call of
-mark and the call of release, are removed and the space they used
-can be reallocated.
-Never use mark and release together with dispose!
-.sp
-.in -10
-.ti -3
-4.~\
-UNIX interfacing.
-.sp
-If the c-option is turned on, then some special features are available
-to simplify an interface with the UNIX environment.
-First of all, the compiler allows you to use a different type
-of string constants.
-These string constants are delimited by double quotes ('"').
-To put a double quote into these strings, you must repeat the double quote,
-like the single quote in normal string constants.
-These special string constants are terminated by a zero byte (chr(0)).
-The type of these constants is a pointer to a packed array of characters,
-with lower bound 1 and unknown upper bound.
-.br
-Secondly, the compiler predefines a new type identifier 'string' denoting
-this just described string type.
-.PP
-The only thing you can do with these features is declaration of
-constants and variables of type 'string'.
-String objects may not be allocated on the heap and string pointers
-may not be de-referenced.
-Still these strings are very useful in combination with external routines.
-The procedure write is extended to print these zero-terminated strings correctly.
-.sp
-.ti -3
-5.~\
-Double length (32 bit) integers.
-.sp
-If the d-option is turned on, then the additional type 'long' is known to the compiler.
-Long variables have integer values in the range -2147483647..+2147483647.
-Long constants may be declared.
-It is not allowed to form subranges of type long.
-All operations allowed on integers are also
-allowed on longs and are indicated by the same
-operators: '+', '-', '*', '/', 'div', 'mod'.
-The procedures read and write have been extended to handle long arguments correctly.
-The default width for longs is 11.
-The standard procedures 'abs' and 'sqr' have been extended to work on long arguments.
-Conversion from integer to long, long to real,
-real to long and long to integer are automatic, like the conversion from integer to real.
-These conversions may cause a
-.IS
-conversion error, trap 10, non-fatal
-.IE
-This last error is only detected in implementation 1, with 'test on'.
-Note that all current implementations use target
-machine floating point instructions
-to perform some of the long operations.
-.sp
-.ti -3
-6.~\
-Underscore as letter.
-.sp
-The character '_' may be used in forming identifiers, if the u-option is turned on.
-.sp
-.ti -3
-7.~\
-Zero field width in write.
-.sp
-Zero or negative TotalWidth arguments to write
-are allowed.
-No characters are written for character, string or Boolean type arguments then.
-A zero or negative FracDigits argument for fixed-point representation of reals causes the
-fraction and the character '.' to be suppressed.
-.sp
-.ti -3
-8.~\
-Alternate symbol representation.
-.sp
-The comment delimiters '(*' and '*)' are recognized and treated like '{' and '}'.
-The other alternate representations of symbols are not recognized.
-.sp
-.ti -3
-9.~\
-Pre-processing.
-.sp
-If the very first character of a file containing a Pascal
-program is the sharp ('#', ASCII 23(hex)) the file is preprocessed
-in the same way as C programs.
-Lines beginning with a '#' are taken as preprocessor command lines
-and not fed to the Pascal compiler proper.
-C style comments, /*......*/, are removed by the C preprocessor,
-thus C comments inside Pascal programs are also removed when they
-are fed through the preprocessor.
-.CH "Deviations from the standard"
-Ack-Pascal deviates from the (March 1980) standard proposal in the following ways:
-.IS
-.ti -3
-1.~\
-Only the first 8 characters of identifiers are significant,
-as requested by all standard proposals prior to March 1980.
-In that proposal, however, the sentence
-.DS
-"A conforming program should not have its meaning altered
-by the truncation of its identifiers to eight characters
-or the truncation of its labels to four digits."
-.DE
-is missing.
-.sp
-.ti -3
-2.~\
-The character sequences 'procedur', 'procedur8', 'functionXyZ' etc. are
-all erroneously classified as the word-symbols 'procedure' and 'function'.
-.sp
-.ti -3
-3.~\
-Standard procedures and functions are not allowed as parameters in Ack-Pascal,
-conforming to all previous standard proposals.
-You can obtain the same result with negligible loss of performance
-by declaring some user routines like:
-.EQ
-     function sine(x:real):real;
-     begin
-         sine:=sin(x)
-     end;
-.EN
-.sp
-.ti -3
-4.~\
-The scope of identifiers and labels should start at the beginning of the block
-in which these identifiers or labels are declared.
-The Ack-Pascal compiler, as most other one pass compilers, deviates in this respect,
-because the scope of variables and labels start
-at their defining-point.
-.CH "Compiler options"
-Some options of the compiler may be controlled by using "{$....}".
-Each option consists of a lower case letter followed by +, - or an unsigned
-number.
-Options are separated by commas.
-The following options exist:
-.in 8
-.sp
-.ti -8
-a~+/-~~~\
-this option switches assertions on and off.
-If this option is on, then code is included to test these assertions
-at run time. Default +.
-.sp
-.ti -8
-c~+/-~~~\
-this option, if on, allows you to use C-type string constants
-surrounded by double quotes.
-Moreover, a new type identifier 'string' is predefined.
-Default -.
-.sp
-.ti -8
-d~+/-~~~\
-this option, if on, allows you to use variables of type 'long'.
-Default -.
-.sp
-.ti -8
-f~<num>~\
-the size of reals can be changed by this option. <num> should be specified in 8-bit bytes.
-The default in most implementations is 8, but other values can
-occur.
-.sp
-.ti -8
-i~<num>~\
-with this flag the setsize for a set of integers can be
-manipulated.
-The number must be the number of bits per set.
-The default value is 16, just fitting in one word on the PDP and many other minis.
-.sp
-.ti -8
-l~+/-~~~\
-if + then code is inserted to keep track of the source line number.
-When this flag is switched on and off, an incorrect line number may appear
-if the error occurs in a part of your program for which this flag is off.
-These same line numbers are used for the profile, flow and count options
-of the EM interpreter em [6].
-Default +.
-.sp
-.ti -8
-p~<num>~the size of pointers can be changed by this option. <num> should be specified in bytes.
-Default 2 in most implementations.
-.sp
-.ti -8
-r~+/-~~~\
-if + then code is inserted to check subrange variables against
-lower and upper subrange limits.
-Default +.
-.sp
-.ti -8
-s~+/-~~~\
-if + then the compiler will hunt for places in your program
-where non-standard features are used, and for each place found
-it will generate a warning. Default -.
-.sp
-.ti -8
-t~+/-~~~\
-if + then each time a procedure is entered, the routine 'procentry'
-is called.
-The compiler checks this flag just before the first symbol that follows the
-first 'begin' of the body of the procedure.
-Also, when the procedure exits, then the procedure 'procexit' is called
-if the t flag is on just before the last 'end' of the procedure body.
-Both 'procentry' and 'procexit' have a packed array of 8 characters as a parameter.
-Default procedures are present in the run time library.
-Default -.
-.sp
-.ti -8
-u~+/-~~~\
-if + then the character '_' is treated like a lower case letter,
-so that it may be used in identifiers.
-Procedure and function identifiers starting with an underscore may cause problems,
-because they may collide with library routine names.
-Default -.
-.in 0
-.sp
-Seven of these flags (c, d, f, i, p, s and u) are only effective when they appear
-before the 'program' symbol. The others may be switched on and off.
-.PP
-A second method of passing options to the compiler ia available.
-This method uses the file on which the compact EM code will be written.
-The compiler starts reading from this file scanning for options
-in the same format as used normally, except for the comment delimiters and
-the dollar sign.
-All options found on the file override the options set in your program.
-Note that the compact code file must always exist before the compiler is called.
-.PP
-The user interface program \fIack\fP[4]
-takes care of creating this file normally
-and also writes one of its options onto this file.
-The user can specify, for instance, without changing any character in its
-Pascal program, that the compiler must include code for
-procedure/function tracing.
-.PP
-Another very powerful debugging tool is the knowledge that inaccessible
-statements and useless tests are removed by the EM optimizer.
-For instance, a statement like:
-.sp
-.nf
-        if debug then
-          writeln('initialization done');
-.fi
-.sp
-is completely removed by the optimizer if debug is a constant with
-value false.
-The first line is removed if debug is a constant with value true.
-Of course, if debug is a variable nothing can be removed.
-.PP
-A disadvantage of Pascal, the lack of preinitialized data, can be
-diminished by making use of the possibilities of the EM optimizer.
-For instance, initializing an array of reserved words is sometimes
-optimized into 3 EM instructions. To maximize this effect you must initialize
-variables as much as possible in order of declaration and array entries
-in order of decreasing index.
-.CH "References"
-.in +5
-.ti -5
-[1]~~\
-ISO standard proposal ISO/TC97/SC5-N462, dated February 1979.
-The same proposal, in slightly modified form, can be found in:
-A.M.Addyman e.a., "A draft description of Pascal",
-Software, practice and experience, May 1979.
-An improved version, received March 1980,
-is followed as much as possible for the
-current Ack-Pascal.
-.sp
-.ti -5
-[2]~~\
-A.S.Tanenbaum, J.W.Stevenson, Hans van Staveren, E.G.Keizer,
-"Description of a machine architecture for use with block structured languages",
-Informatica rapport IR-81.
-.sp
-.ti -5
-[3]~~\
-W.S.Brown, S.I.Feldman, "Environment parameters and basic functions
-for floating-point computation",
-Bell Laboratories CSTR #72.
-.sp
-.ti -5
-[4]~~\
-UNIX manual ack(I).
-.sp
-.ti -5
-[5]~~\
-UNIX manual ld(I).
-.sp
-.ti -5
-[6]~~\
-UNIX manual em(I).
-.sp
-.ti -5
-[7]~~\
-UNIX manual libpc(VII)
-.sp
-.ti -5
-[8]~~\
-UNIX manual pc_prlib(VII)

+ 0 - 506
doc/peep.doc

@@ -1,506 +0,0 @@
-.\" $Header$
-.TL
-Internal documentation on the peephole optimizer
-.br
-from the Amsterdam Compiler Kit
-.NH 1
-Introduction
-.PP
-Part of the Amsterdam Compiler Kit is a program to do
-peephole optimization on an EM program.
-The optimizer scans the program to match patterns from a table
-and if found makes the optimization from the table,
-and with the result of the optimization
-it tries to find yet another optimization
-continuing until no more optimizations are found.
-.PP
-Furthermore it does some optimizations that can not be called
-peephole optimizations for historical reasons,
-like branch chaining and the deletion of unreachable code.
-.PP
-The peephole optimizer consists of three parts
-.IP 1)
-A driving table
-.IP 2)
-A program translating the table to internal format
-.IP 3)
-C code compiled with the table to make the optimizer proper
-.PP
-In this document the table format, internal format and 
-data structures in the optimizer will be explained,
-plus a hint on what the code does where it might not be obvious.
-It is a simple program mostly.
-.NH 1
-Table format
-.PP
-The driving table consists of pattern/replacement pairs,
-in principle one per line,
-although a line starting with white space is considered
-a continuation line for the previous.
-The general format is:
-.DS
-optimization : pattern ':' replacement '\en'
-.sp
-pattern : EMlist optional_boolean_expression
-.sp
-replacement : EM_plus_operand_list
-.DE
-Example of a simple one
-.DS
-loc stl $1==0 : zrl $2
-.DE
-There is no real limit for the length of the pattern or the replacement,
-the replacement might even be longer than the pattern,
-and expressions can be made arbitrarily complicated.
-.PP
-The expressions in the table are made of the following pieces:
-.IP -
-Integer constants
-.IP -
-$\fIn\fP, standing for the operand of the \fIn\fP'th EM
-instruction in the pattern,
-undefined if that instruction has no operand.
-.IP -
-w, standing for the wordsize of the code optimized.
-.IP -
-p, for the pointersize.
-.IP -
-defined(expr), true if expression is defined
-.IP -
-samesign(expr,expr), true if expressions have the same sign.
-.IP -
-sfit(expr,expr), ufit(expr,expr),
-true if the first expression fits signed or unsigned in the number
-of bits given in the second expression.
-.IP -
-rotate(expr,expr),
-first expression rotated left the number of bits given by the second expression.
-.IP -
-notreg(expr),
-true if the local with the expression as number is not a candidate to put
-in a register.
-.IP -
-rom(\fIn\fP,expr), contents of the rom descriptor at index expr that
-is associated with the global label that should be the argument of
-the \fIn\fP'th EM instruction.
-Undefined if such a thing does not exist.
-.PP
-The usual arithmetic operators may be used on integer values,
-if any operand is undefined the expression is undefined,
-except for the defined() function above.
-An undefined expression used for its truth value is false.
-All arithmetic on local label operands is forbidden,
-only things allowed are tests for equality.
-Arithmetic on global labels makes sense,
-i.e. one can add a global label and a constant,
-but not two global labels.
-.PP
-In the table one can use five additional EM instructions in patterns.
-These are:
-.IP lab
-Stands for a local label
-.IP LLP
-Load Local Pointer, translates into a 
-.B lol
-or into a 
-.B ldl
-depending on the relationship between wordsize and pointersize.
-.IP LEP
-Load External Pointer, translates into a 
-.B loe
-or into a 
-.B lde .
-.IP SLP
-Store Local Pointer,
-.B stl
-or 
-.B sdl .
-.IP SEP
-Store External Pointer,
-.B ste
-or
-.B sde .
-.PP
-There is only one peephole optimizer,
-so the substitutions to be made for the last four instructions
-are made at run time before the first optimizations are made.
-.NH 1
-Internal format
-.PP
-The translating program,
-.I mktab
-converts the table into an array of bytes where all
-patterns follow unaligned.
-Format of a pattern is:
-.IP 1)
-One byte for high byte of hash value,
-will be explained later on.
-.IP 2)
-Two bytes for the index of the next pattern in a chain.
-.IP 3)
-An integer\u*\d,
-.FS
-* An integer is encoded as a byte when less than 255,
-otherwise as a byte containing 255 followed by two
-bytes with the real value.
-.FE
-pattern length.
-.IP 4)
-The list of pattern opcodes, one per byte.
-.IP 5)
-An integer expression index, 0 if not used.
-.IP 6)
-An integer, replacement length.
-.IP 7)
-A list of pairs consisting of a one byte opcode and an integer
-expression index.
-.PP
-The expressions are kept in an array of triples,
-implementing a binary tree.
-The
-.I mktab
-program tries to minimize the number of triples by reusing
-duplicates and even reverses the operands of commutative operators
-when doing so would spare a triple.
-.NH 1
-A tour through the sources
-.PP
-Now we will walk through the sources and note things of interest.
-.NH 2
-The header files
-.PP
-The header files are the place where data structures and options reside.
-.NH 3
-alloc.h
-.PP
-In the header file alloc.h several defines can be used to select various
-kinds of core allocation schemes.
-This is important on small machines like the PDP-11 since a complete
-procedure must be in core at the same space,
-and the peephole optimizer should not be the limiting factor in
-determining the maximum size of procedures if possible.
-Options are:
-.IP -
-USEMALLOC, standard malloc() and free() are used instead of the own
-core allocation package.
-Not recommended unless the own package does not work on some bizarre
-machine.
-.IP -
-COREDEBUG, prints large amounts of information about core management.
-Better not define it unless you change the code and it stops working.
-.IP -
-SEPID, if you define this you will get an extra procedure that will
-go through a lot of work to scrape the last bytes together if the
-system won't provide more.
-This is not a good idea if memory is scarce and code and data reside
-in the same spaces, since the room used by the procedure might well
-be more than the room saved.
-.IP -
-STACKROOM, number of shorts used in stack space.
-This is used if memory is scarce and stack space and data space are
-different.
-On the PDP-11 a UNIX process starts with an 8K stack segment which
-cannot be transferred to the data segment.
-Under these conditions one can use a lot of the stack space for storage.
-.NH 3
-assert.h
-.PP
-Just defines the assert macro.
-When compiled with -DNDEBUG all asserts will be off.
-.NH 3
-ext.h
-.PP
-Gives external definitions of variables used by more than one module.
-.NH 3
-line.h
-.PP
-Defines the structures used to keep instructions,
-one structure per line of EM code,
-and the structure to keep arguments of pseudos,
-one structure per argument.
-Both structures essentially contain a pointer to the next,
-a type,
-and a union containing information depending on the type.
-Core is allocated only for the part of the union used.
-.PP
-The 
-.I
-struct line
-.R
-has a very compact encoding for small integers,
-they are encoded in the type field.
-On the PDP-11 this gives a line structure of only 4 bytes for most
-instructions.
-.NH 3
-lookup.h
-.PP
-Contains definition of the struct used for symbol table management,
-global labels and procedure names are kept in one table.
-.NH 3
-optim.h
-.PP
-If one defines the DIAGOPT option in this header file,
-for every optimization performed a number is written on stderr.
-The number gives the number of the pattern in the table
-or one of the four special numbers in this header file.
-.NH 3
-param.h
-.PP
-Contains one settable option,
-LONGOFF.
-If this is not defined the optimizer can only optimize programs
-with wordsize 2 and pointersize 2.
-Set this only if it must be run on a Z80 or something pathetic like that.
-.PP
-Other defines here should not be touched.
-.NH 3
-pattern.h
-.PP
-Contains defines of indices in a pattern,
-definition of the expression triples,
-definitions of the various expression operators
-and definition of the result struct where expression results are put.
-.PP
-This header file is the main one that is also included by
-.I mktab .
-.NH 3
-proinf.h
-.PP
-This one contains definitions 
-for the local label table structs
-and for the struct where all information for one procedure is kept.
-This is in one struct so it can be saved easily when recursive
-procedures have to be resolved.
-.NH 3
-types.h
-.PP
-Collection of typedefs to be used by almost all modules.
-.NH 2
-The C code itself.
-.PP
-The C code will now be the center of our attention.
-We will make a walk through the sources and we will try
-to follow the sources in a logical order.
-So we will start at
-.NH 3
-main.c
-.PP
-The main.c module contains the main() function.
-Here nothing spectacular happens,
-only thing of interest is the handling of flags:
-.IP -L
-This is an instruction to the peephole optimizer to perform
-one of its auxiliary functions, the generation of a library module.
-This makes the peephole optimizer write its output on a temporary file,
-and at the end making the real output by first generating a list
-of exported symbols and then copying the temporary file behind it.
-.IP -n
-Disables all optimization.
-Only thing the optimizer does now is filling in the blank after the
-.I END
-pseudo and resolving recursive procedures.
-.PP
-The place where main() is left is the call to getlines() which brings
-us to
-.NH 3
-getline.c
-.PP
-This module reads the EM code and constructs a list of 
-.I
-struct line
-.R
-records,
-linked together backwards,
-i.e. the first instruction read is the last in the list.
-Pseudos are handled here also,
-for most pseudos this just means that a chain of argument records
-is linked into the linked line list but some pseudos get special attention:
-.IP exc
-This pseudo is acted upon right away.
-Lines read are shuffled around according to instruction.
-.IP mes
-Some messages are acted upon.
-These are:
-.RS
-.IP ms_err 8
-The input is drained, just in case it is a pipe.
-After that the optimizer exits.
-.IP ms_opt
-The do not optimize flag is set.
-Acts just like -n on the command line.
-.IP ms_emx
-The word- and pointersize are read,
-complain if we are not able to handle this.
-.IP ms_reg
-We take notice of the offset of this local.
-See also comments in the description of peephole.c
-.RE
-.IP pro
-A new procedure starts, if we are already in one save the status,
-else process collected input.
-Collect information about this procedure and if already in a procedure
-call getlines() recursively.
-.IP end
-Process collected input.
-.PP
-The phrase "process collected input" is used twice,
-which brings us to
-.NH 3
-process.c
-.PP
-This module contains the entry point process() which is called at any
-time the collected input must be processed.
-It calls a variety of other routines to get the real work done.
-Routines in this module are in chronological order:
-.IP symknown 12
-Marks all symbols seen until now as known,
-i.e. it is now known whether their scope is local or global.
-This information is used again during output.
-.IP symvalue
-Runs through the chain of pseudos to give values to data labels.
-This needs an extra pass.
-It cannot be done during the getlines pass, since an
-.B exc
-pseudo could destroy things.
-Nor can it be done during the backward pass since it is impossible
-to do good fragment numbering backward.
-.IP checklocs
-Checks whether all local labels referenced are defined.
-It needs to be sure about this since otherwise the
-semi global optimizations made cannot work.
-.IP relabel
-This routine finds the final destination for each label in the procedure.
-Labels followed by unconditional branches or other labels are marked during
-the peephole fase and this leeds to chains of identical labels.
-These chains are followed here, and in the local label table each label
-has associated with it its replacement label, after this procedure is run.
-Care is taken in this routine to prevent a loop in the program to
-cause the optimizer to loop.
-.IP cleanlocals
-This routine empties the local label table after everything
-is processed.
-.PP
-But before this can all be done,
-the backward linked list of instructions first has to be reversed,
-so here comes
-.NH 3
-backward.c
-.PP
-The routine backward has a number of functions:
-.IP -
-It reverses the backward linked list, making two forward linked lists,
-one for the instructions and one for the pseudos.
-.IP -
-It notes the last occurrence of data labels in the backward linked list
-and puts it in the global symbol table.
-This is of course the first occurence in the procedure.
-This information is needed to decide whether the symbols are global
-or local to this module.
-.IP -
-It decides about the fragment boundaries of data blocks.
-Fragments are numbered backwards starting at 3.
-This is done to be able to make the type of an expression
-containing a symbol equal to its fragment.
-This type can then not clash with the types integer and local label.
-.IP -
-It allocates a rom buffer to every data label with a rom behind
-it, if that rom contains only plain integers at the start.
-.PP
-The first thing done after process() has called backward() and some
-of its own little routines is a call to the real routine,
-the one that does the work the program was written for
-.NH 3
-peephole.c
-.PP
-The first routines in peephole.c 
-implement a linked list for the offsets of local variables
-that are candidates for a register implementation.
-Several patterns use the notreg() function,
-since it is forbidden to combine a load of that variable
-with the load of another and
-it is not allowed to take the address of that variable.
-.PP
-The routine peephole hashes the patterns the first time it is called
-after which it doesn't do much more than calling optimize.
-But first hashpatterns().
-.PP
-The patterns are hashed at run time of the optimizer because of
-the
-.B LLP ,
-.B LEP ,
-.B SLP 
-and
-.B SEP
-instructions added to the instruction set in this optimizer.
-These are first replaced everywhere in the table by the correct
-replacement after which the first three instructions of the
-pattern are hashed and the pattern is linked into one of the
-256 linked lists.
-There is a define CHK_HASH in this module that you
-can set if you do not trust the randomness of the hashing
-function.
-.PP
-The attention now shifts to optimize().
-This routine calls  basicblock() for every piece of code between two labels.
-It also notes which labels have another label or a branch behind them
-so the relabel() routine from process.c can do something with that.
-.PP
-Basicblock() keeps making passes over its basic block
-until no more optimizations are found.
-This might be inefficient if there is a long basicblock with some
-deep recursive optimization in one part of it.
-The entire basic block is then scanned a lot of times just for
-that one piece.
-The alternative is backing up after making an optimization and running
-through the same code again, but that is difficult
-in a single linked list.
-.PP
-It hashes instructions and calls trypat() for every pattern that has
-a full hash value match,
-i.e. lower byte and upper byte equal.
-Longest pattern is tried first.
-.PP
-Trypat() checks length and opcodes of the pattern.
-If correct it fills the iargs[] array with argument values
-and calculates the expression.
-If that is also correct the work shifts to tryrepl().
-.PP
-Tryrepl() generates the list of replacement instructions,
-links it into the list and returns true.
-Why then the name tryrepl() if it always succeeds?
-Well, there is a mechanism in the optimizer,
-unused until today that makes it possible to do optimizations that cannot
-be described by the table.
-It is possible to give a number as a replacement which will cause the
-optimizer to call a routine special() to do some work.
-This routine might decide not to do an optimization and return false.
-.PP
-The last routine that is called from process() is putline()
-to write the optimized code, bringing us to
-.NH 3
-putline.c
-.PP
-The major part of putline.c is the standard set of routines
-that makes EM compact code.
-The extra functions performed are:
-.IP -
-For every occurence of a global symbol it might be necessary to
-output a 
-.B exa ,
-.B exp ,
-.B ina
-or 
-.B inp
-pseudo instruction.
-That task is performed.
-.IP -
-The
-.B lin
-instructions are optimized here,
-.B lni
-instructions added for 
-.B lin
-instructions and superfluous
-.B lin
-instructions deleted.
-

+ 0 - 133
doc/regadd.doc

@@ -1,133 +0,0 @@
-.\" $Header$
-.TL
-Addition of register variables to an existing table.
-.NH 1
-Introduction
-.PP
-This is a short description of the newest feature in the
-table driven code generator for the Amsterdam Compiler Kit.
-It describes how to add register variables to an existing table.
-This assumes you have the distribution of October 1983 or later.
-It is not clear whether you should read this when starting with
-a table for a new machine,
-or whether you should wait till the table is well debugged already.
-.NH 1
-Modifications to the table itself.
-.NH 2
-Register section
-.PP
-You can add just before the properties of the register one
-of the following:
-.IP - 2
-regvar
-.IP -
-regvar ( pointer )
-.IP -
-regvar ( loop )
-.IP -
-regvar ( float )
-.LP
-All register variables of one type must be of the same size,
-and they may have no subregisters.
-.NH 2
-Codesection
-.PP
-.IP - 2
-Two pseudo functions are added to the list allowed inside expressions:
-.RS
-.IP 1) 3
-inreg ( expr ) has as a parameter the offset of a local,
-and returns 0,1 or 2:
-.RS
-.IP 2: 3
-if the variable is in a register.
-.IP 1:
-if the variable could be in a register but isn't.
-.IP 0:
-if the variable cannot be in a register.
-.RE
-.IP 2)
-regvar ( expr ) returns the register associated with the variable.
-Undefined if it is not in a register.
-So regvar ( expr ) is defined if and only if inreg (expr ) == 2.
-.RE
-.IP -
-It is now possible to remove() a register expression,
-this is of course needed for a store into a register local.
-.IP -
-The return out of a procedure may now involve register restores,
-so the special word 'return' in the table will invoke a user defined
-function.
-.NH 1
-Modifications to mach.c
-.PP
-If register variables are used in a table, the program
-.I cgg
-will define the word REGVARS during compilation of the sources.
-So the following functions described here should be bracketed
-by #ifdef REGVARS and #endif.
-.IP - 2
-regscore(off,size,typ,freq,totyp) long off;
-.br
-This function should assign a score to a register variable,
-the score should preferably be the estimated number of bytes
-gained when it is put in a register.
-Off and size are the offset and size of the variable,
-typ is the type, that is reg_any, reg_pointer, reg_loop or reg_float.
-Freq is the number of times it occurs statically, and totyp
-is the type of the register it is planned to go into.
-.br
-Keep in mind that the gain should be net, that is the cost for
-register save/restore sequences and the cost of initialisation
-in the case of parameters should already be included.
-.IP -
-i_regsave()
-.br
-This function is called at the start of a procedure, just before
-register saves are done.
-It can be used to initialise some variables if needed.
-.IP -
-f_regsave()
-.br
-This function is called at end of the register save sequence.
-It can be used to do the real saving if multiple register move
-instructions are available.
-.IP -
-regsave(regstr,off,size) char *regstr; long off;
-.br
-Should either do the real saving or set up a table to have
-it done by f_regsave.
-Note that initialisation of parameters should also be done,
-or planned here.
-.IP -
-regreturn()
-.br
-Should restore saved registers and return.
-The function result is already in the function return area by now.
-.NH 1
-Examples
-.PP
-Here are some examples out of the PDP 11 table
-.DS
-lol inreg($1)==2| |		| regvar($1)			| |
-
-lil inreg($1)==2| |		| {regdef2, regvar($1)}		| |
-
-stl inreg($1)==2| xsource2 |
-			remove(regvar($1))
-			move(%[1],regvar($1))              |       | |
-
-inl inreg($1)==2| |     remove(regvar($1))
-			"inc %(regvar($1)%)"
-			setcc(regvar($1))          |       | |
-.DE
-.NH 1
-Afterthoughts.
-.PP
-At the time of this writing the tables for the PDP 11 and the M68000 and
-the VAX are converted, in all cases the two byte wordsize versions.
-No big problems have occurred, but experience has shown that it is
-necessary to check your table carefully for all patterns with locals in them
-because if you forget one code will be generated by that one coderule
-to use the memoryslot the local is not in.
-

+ 0 - 897
doc/toolkit.doc

@@ -1,897 +0,0 @@
-.\" $Header$
-.RP
-.ND
-.nr LL 78m
-.tr ~
-.ds as *
-.TL
-A Practical Tool Kit for Making Portable Compilers
-.AU
-Andrew S. Tanenbaum
-Hans van Staveren
-E. G. Keizer
-Johan W. Stevenson
-.AI
-Mathematics Dept.
-Vrije Universiteit
-Amsterdam, The Netherlands
-.AB
-The Amsterdam Compiler Kit is an integrated collection of programs designed to
-simplify the task of producing portable (cross) compilers and interpreters.
-For each language to be compiled, a program (called a front end) 
-must be written to
-translate the source program into a common intermediate code.
-This intermediate code can be optimized and then either directly interpreted
-or translated to the assembly language of the desired target machine.
-The paper describes the various pieces of the tool kit in some detail, as well
-as discussing the overall strategy.
-.sp
-Keywords: Compiler, Interpreter, Portability, Translator
-.sp
-CR Categories: 4.12, 4.13, 4.22
-.sp 12
-Author's present addresses:
-  A.S. Tanenbaum, H. van Staveren, E.G. Keizer: Mathematics
-     Dept., Vrije Universiteit, Postbus 7161, 1007 MC Amsterdam,
-     The Netherlands
-
-  J.W. Stevenson: NV Philips, S&I, T&M, Building TQ V5, Eindhoven,
-     The Netherlands
-.AE
-.NH 1
-Introduction
-.PP
-As more and more organizations acquire many micro- and minicomputers,
-the need for portable compilers is becoming more and more acute.
-The present situation, in which each hardware vendor provides its own
-compilers -- each with its own deficiencies and extensions, and none of them
-compatible -- leaves much to be desired.
-The ideal situation would be an integrated system containing a family
-of (cross) compilers, each compiler accepting a standard source language and
-producing code for a wide variety of target machines.
-Furthermore, the compilers should be compatible, so programs written in
-one language can call procedures written in another language.
-Finally, the system should be designed so as to make adding new languages
-and new machines easy.
-Such an integrated system is being built at the Vrije Universiteit.
-Its design and implementation is the subject of this article.
-.PP
-Our compiler building system, which is called the "Amsterdam Compiler Kit"
-(ACK), can be thought of as a "tool kit."
-It consists of a number of parts that can be combined to form compilers
-(and interpreters) with various properties.
-The tool kit is based on an idea (UNCOL) that was first suggested in 1960
-[7], but which never really caught on then.
-The problem which UNCOL attempts to solve is how to make a compiler for
-each of
-.I N
-languages on
-.I M
-different machines without having to write 
-.I N
-x
-.I M
-programs.
-.PP
-As shown in Fig. 1, the UNCOL approach is to write
-.I N
-"front ends," each
-of which translates one source language to a common intermediate language,
-UNCOL (UNiversal Computer Oriented Language), and
-.I M
-"back ends," each
-of which translates programs in UNCOL to a specific machine language.
-Under these conditions, only
-.I N
-+
-.I M
-programs must be written to provide all
-.I N
-languages on all
-.I M
-machines, instead of 
-.I N
-x
-.I M
-programs.
-.PP
-Various researchers have attempted to design a suitable UNCOL
-[2,8], but none of these have become popular.
-It is our belief that previous attempts have failed because they have been
-too ambitious, that is, they have tried to cover all languages
-and all machines using a single UNCOL.
-Our approach is more modest: we cater only to algebraic languages
-and machines whose memory consists of 8-bit bytes, each with its own address.
-Typical languages that could be handled include
-Ada, ALGOL 60, ALGOL 68, BASIC, C, FORTRAN,
-Modula, Pascal, PL/I, PL/M, PLAIN, and RATFOR,
-whereas COBOL, LISP, and SNOBOL would be less efficient.
-Examples of machines that could be included are the Intel 8080 and 8086,
-Motorola 6800, 6809, and 68000, Zilog Z80 and Z8000, DEC PDP-11 and VAX,
-and IBM 370 but not the Burroughs 6700, CDC Cyber, or Univac 1108 (because
-they are not byte-oriented).
-With these restrictions, we believe the old UNCOL idea can be used as the
-basis of a practical compiler-building system.
-.KF
-.sp 15P
-.ce 1
-Fig. 1.  The UNCOL model.
-.sp
-.KE
-.NH 1
-An Overview of the Amsterdam Compiler Kit
-.PP
-The tool kit consists of eight components:
-.sp
-  1. The preprocessor.
-  2. The front ends.
-  3. The peephole optimizer.
-  4. The global optimizer.
-  5. The back end.
-  6. The target machine optimizer.
-  7. The universal assembler/linker.
-  8. The utility package.
-.sp
-.PP
-A fully optimizing compiler,
-depicted in Fig. 2, has seven cascaded phases.
-Conceptually, each component reads an input file and writes a
-transformed output file to be used as input to the next component.
-In practice, some components may use temporary files to allow multiple
-passes over the input or internal intermediate files.
-.KF
-.sp 12P
-.ce 1
-Fig. 2.  Structure of the Amsterdam Compiler Kit.
-.sp
-.KE
-.PP
-In the following paragraphs we will briefly describe each component.
-After this overview, we will look at all of them again in more detail.
-A program to be compiled is first fed into the (language independent)
-preprocessor, which provides a simple macro facility,
-and similar textual facilties.
-The preprocessor's output is a legal program in one of the programming
-languages supported, whereas the input is a program possibly augmented
-with macros, etc.
-.PP
-This output goes into the appropriate front end, whose job it is to
-produce intermediate code.
-This intermediate code (our UNCOL) is the machine language for a simple
-stack machine called EM (Encoding Machine).
-A typical front end might build a parse tree from the input, and then
-use the parse tree to generate EM code, which is similar to reverse Polish.
-In order to perform this work, the front end has to maintain tables of
-declared variables, labels, etc., determine where to place the
-data structures in memory, and so on.
-.PP
-The EM code generated by the front end is fed into the peephole optimizer,
-which scans it with a window of a few instructions, replacing certain
-inefficient code sequences by better ones.
-Such a search is important because EM contains instructions to handle
-numerous important special cases efficiently
-(e.g., incrementing a variable by 1).
-It is our strategy to relieve the front ends of the burden of hunting for
-special cases because there are many front ends and only one peephole
-optimizer.
-By handling the special cases in the peephole optimizer, 
-the front ends become simpler, easier to write and easier to maintain.
-.PP
-Following the peephole optimizer is a global optimizer [5], which
-unlike the peephole optimizer, examines the program as a whole.
-It builds a data flow graph to make possible a variety of 
-global optimizations,
-among them, moving invariant code out of loops, avoiding redundant
-computations, live/dead analysis and eliminating tail recursion.
-Note that the output of the global optimizer is still EM code.
-.PP
-Next comes the back end, which differs from the front ends in a
-fundamental way.
-Each front end is a separate program, whereas the back end is a single
-program that is driven by a machine dependent driving table.
-The driving table for a specific machine tells how the EM code is mapped
-onto the machine's assembly language.
-Although a simple driving table might just macro expand each EM instruction
-into a sequence of target machine instructions, a much more sophisticated
-translation strategy is normally used, as described later.
-For speed, the back end does not actually read in the driving table at run time.
-Instead, the tables are compiled along with the back end in advance, resulting
-in one binary program per machine.
-.PP
-The output of the back end is a program in the assembly language of some
-particular machine.
-The next component in the pipeline reads this program and performs peephole
-optimization on it.
-The optimizations performed here involve idiosyncracies
-of the target machine that cannot be performed in the machine-independent
-EM-to-EM peephole optimizer.
-Typically these optimizations take advantage of special instructions or special
-addressing modes.
-.PP
-The optimized target machine assembly code then goes into the final
-component in the pipeline, the universal assembler/linker.
-This program assembles the input to object format, extracting routines from
-libraries and including them as needed.
-.PP
-The final component of the tool kit is the utility package, which contains
-various test programs, interpreters for EM code, 
-EM libraries, conversion programs, and other aids for the implementer and
-user.
-.NH 1
-The Preprocessor
-.PP
-The function of the preprocessor is to extend all the programming languages
-by adding certain generally useful facilities to them in a uniform way.
-One of these is a simple macro system, in which the user can give names to
-character strings.
-The names can be used in the program, with the knowledge that they will be
-macro expanded prior to being input to the front end.
-Macros can be used for named constants, expanding short "procedures"
-in line, etc.
-.PP
-Another useful facility provided by the preprocessor is the ability to
-include compile-time libraries.
-On large projects, it is common to have all the declarations and definitions
-gathered together in a few files that are textually included in the programs
-by instructing the preprocessor to read them in, thus fooling the front end
-into thinking that they were part of the source program.
-.PP
-A third feature of the preprocessor is conditional compilation.
-The input program can be split up into labeled sections.
-By setting flags, some of the sections can be deleted by the preprocessor,
-thus allowing a family of slightly different programs to be conveniently stored
-on a single file.
-.NH 1
-The Front Ends
-.PP
-A front end is a program that converts input in some source language to a
-program in EM.
-At present, front ends 
-exist or are in preparation for Pascal, C, and Plain, and are being considered
-for Ada, ALGOL 68, FORTRAN 77, and Modula 2.
-Each of the present front ends is independent of all the other ones,
-although a general-purpose, table-driven front end is conceivable, provided
-one can devise a way to express the semantics of the source language in the
-driving tables.
-The Pascal front end uses a top-down parsing algorithm (recursive descent),
-whereas the C and Plain front ends are bottom-up.
-.PP
-All front ends, independent of the language being compiled,
-produce a common intermediate code called EM, which is
-the assembly language for a simple stack machine.
-The EM machine is based on a memory architecture
-containing a stack for local variables, a (static) data area for variables
-declared in the outermost block and global to the whole program, and a heap
-for dynamic data structures.
-In some ways EM resembles P-code [6], but is more general, since it is
-intended for a wider class of languages than just Pascal.
-.PP
-The EM instruction set has been described elsewhere
-[9,10,11]
-so we will only briefly summarize it here.
-Instructions exist to:
-.sp
-  1. Load a variable or constant of some length onto the stack.
-  2. Store the top item on the stack in memory.
-  3. Add, subtract, multiply, divide, etc. the top two stack items.
-  4. Examine the top one or two stack items and branch conditionally.
-  5. Call procedures and return from them.
-.sp
-.PP
-Loads and stores come in several variations, corresponding to the most common
-programming language semantics, for example, constants, simple variables,
-fields of a record, elements of an array, and so on.
-Distinctions are also made between variables local to the current block
-(i.e., stack frame), those in the outermost block (static storage), and those
-at intermediate lexicographic levels, which are accessed by following the
-static chain at run time.
-.PP
-All arithmetic instructions have a type (integer, unsigned, real,
-pointer, or set) and an
-operand length, which may either be explicit or may be popped from the stack
-at run time.
-Monadic branch instructions pop an item from the stack and branch if it is
-less than zero, less than or equal to zero, etc.
-Dyadic branch instructions pop two items, compare them, and branch accordingly.
-.PP
-In addition to these basic EM instructions, there is a collection of special
-purpose instructions (e.g., to increment a local variable), which are typically
-produced from the simple ones by the peephole optimizer.
-Although the complete EM instruction set contains nearly 150 instructions,
-only about 60 of them are really primitive; the rest are simply abbreviations
-for commonly occurring EM instruction sequences.
-.PP
-Of particular interest is the way object sizes are parametrized.
-The front ends allow the user to indicate how many bytes an integer, real, etc.
-should occupy.
-Given this information, the front ends can allocate memory, determining 
-the placement of variables within the stack frame.
-Sizes for primitive types are restricted to 8, 16, 32, 64, etc. bits.
-The front ends are also parametrized by the target machine's word length
-and address size so they can tell, for example, how many "load" instructions
-to generate to move a 32-bit integer.
-In the examples used henceforth,
-we will assume a 16-bit word size and 16-bit integers.
-.PP
-Since only byte-addressable target machines are permitted,
-it is nearly
-always possible to implement any requested sizes on any target machine.
-For example, the designer of the back end tables for the Z80 should provide
-code for 8-, 16-, and 32-bit arithmetic.
-In our view, the Pascal, C, or Plain programmer specifies what lengths 
-are needed,
-without reference to the target machine,
-and the back end provides it.
-This approach greatly enhances portability.
-While it is true that doing all arithmetic using 32-bit integers on the Z80
-will not be terribly fast, we feel that if that is what the programmer needs,
-it should be possible to implement it.
-.PP
-Like all assembly languages, EM has not only machine instructions, but also
-pseudoinstructions.
-These are used to indicate the start and end of each procedure, allocate
-and initialize storage for data, and similar functions.
-One particularly important pseudoinstruction is the one that is used to
-transmit information to the back end for optimization purposes.
-It can be used to suggest variables that are good candidates to assign to
-registers, delimit the scope of loops, indicate that certain variables 
-contain a useful value (next operation is a load) or not (next operation is
-a store), and various other things.
-.NH 1
-The Peephole Optimizer
-.PP
-The peephole optimizer reads in unoptimized EM programs and writes out
-optimized ones.
-Both the input and output are expressed in a highly compact code, rather than
-in ASCII, to reduce the i/o time, which would otherwise dominate the CPU
-time.
-The program itself is table driven, and is, by and large, ignorant of the
-semantics of EM.
-The knowledge of EM is contained in a
-language- and machine-independent table consisting of about 400
-pattern-replacement pairs.
-We will briefly describe the kinds of optimizations it performs below;
-a more complete discussion can be found in [9].
-.PP
-Each line in the driving table describes one optimization, consisting of a
-pattern part and a replacement part.
-The pattern part is a series of one or more EM instructions and a boolean
-expression.
-The replacement part is a series of EM instructions with operands.
-A typical optimization might be:
-.sp
-  LOL  LOC  ADI  STL  ($1 = $4) and ($2 = 1) and ($3 = 2) ==> INL $1
-.sp
-where the text prior to the ==> symbol is the pattern and the text after it is
-the replacement.
-LOL loads a local variable onto the stack, LOC loads a constant onto the stack,
-ADI is integer addition, and STL is store local.
-The pattern specifies that four consecutive EM instructions are present, with
-the indicated opcodes, and that furthermore the operand of the first 
-instruction (denoted by $1) and the fourth instruction (denoted by $4) are the
-same, the constant pushed by LOC is 1, and the size of the integers added by
-ADI is 2 bytes.
-(EM instructions have at most one operand, so it is not necessary to specify
-the operand number.)
-Under these conditions, the four instructions can be replaced by a single INL
-(increment local) instruction whose operand is equal to that of LOL.
-.PP
-Although the optimizations cover a wide range, the main ones
-can be roughly divided into the following categories.
-\fIConstant folding\fR
-is used to evaluate constant expressions, such as 2*3~+~7 at
-compile time instead of run time.
-\fIStrength reduction\fR
-is used to replace one operation, such as multiply, by
-another, such as shift.
-\fIReordering of expressions\fR
-helps in cases like -K/5, which can be better
-evaluated as K/-5, because the former requires
-a division and a negation, whereas the latter requires only a division.
-\fINull instructions\fR
-include resetting the stack pointer after a call with 0 parameters,
-offsetting zero bytes to access the
-first element of a record, or jumping to the next instruction.
-\fISpecial instructions\fR
-are those like INL, which deal with common special cases
-such as adding one to a variable or comparing something to zero.
-\fIGroup moves\fR
-are useful because a sequence
-of consecutive moves can often be replaced with EM code
-that allows the back end to generate a loop instead of in line code.
-\fIDead code elimination\fR
-is a technique for removing unreachable statements, possibly made unreachable
-by previous optimizations.
-\fIBranch chain compression\fR
-can be applied when a branch instruction jumps to another branch instruction.
-The first branch can jump directly to the final destination instead of
-indirectly.
-.PP
-The last two optimizations logically belong in the global optimizer but are
-in the local optimizer for historical reasons (meaning that the local
-optimizer has been the only optimizer for many years and the optimizations were
-easy to do there).
-.NH 1
-The Global Optimizer
-.PP
-In contrast to the peephole optimizer, which examines the EM code a few lines
-at a time through a small window, the global optimizer examines the 
-program's large scale structure.
-Three distinct types of optimizations can be found here:
-.sp
-  1. Interprocedural optimizations.
-  2. Intraprocedural optimizations.
-  3. Basic block optimizations.
-.sp
-We will now look at each of these in turn.
-.PP
-Interprocedural optimizations are those spanning procedure boundaries.
-The most important one is deciding to expand procedures in line,
-especially short procedures that occur in loops and pass several parameters.
-If it takes more time or memory to pass the parameters than to do the work,
-the program can be improved by eliminating the procedure.
-The inverse optimization -- discovering long common code sequences and
-turning them into a procedure -- is also possible, but much more difficult.
-Like much of the global optimizer's work, the decision to make or not make
-a certain program transformation is a heuristic one, based on knowledge of
-how the back end works, how most target machines are organized, etc.
-.PP
-The heart of the global optimizer is its analysis of individual
-procedures.
-To perform this analysis, the optimizer must locate the basic blocks,
-instruction sequences which can be entered only at the top and exited
-only at the bottom.
-It then constructs a data flow graph, with the basic blocks as nodes and
-jumps between blocks as arcs.
-.PP
-From the data flow graph, many important properties of the program can be
-discovered and exploited.
-Chief among these is the presence of loops, indicated by cycles in the graph.
-One important optimization is looking for code that can be moved outside the
-loop, either prior to it or subsequent to it.
-Such code motion saves execution time, although it does not save memory.
-Unrolling loops is also possible and desirable in some cases.
-.PP
-Another area in which global analysis of loops is especially important is
-in register allocation. 
-While it is true that EM does not have any registers to allocate,
-the optimizer can easily collect information to allow the
-back end to allocate registers wisely.
-For example, the global optimizer can collect static frequency-of-use
-and live/dead information about variables.
-(A variable is dead at some point in the program if its current value is
-not needed, i.e., the next reference to it overwrites it rather than
-reading it; if the current value will eventually be used, the variable is
-live.)
-If two variables are never simultaneously live over some interval of code
-(e.g., the body of a loop), they can be packed into a single variable,
-which, if used often enough, may warrant being assigned to a register.
-.PP
-Many loops involve arrays: this leads to other optimizations.
-If an array is accessed sequentially, with each iteration using the next
-higher numbered element, code improvement is often possible.
-Typically, a pointer to the bottom element of each array can be set up
-prior to the loop.
-Within the loop the element is accessed indirectly via the pointer, which is
-also incremented by the element size on each iteration.
-If the target machine has an autoincrement addressing mode and the pointer
-is assigned to a register, an array access can often be done in a single
-instruction.
-.PP
-Other intraprocedural optimizations include removing tail recursion
-(last statement is a recursive call to the procedure itself),
-topologically sorting the basic blocks to minimize the number of branch
-instructions, and common subexpression recognition.
-.PP
-The third general class of optimizations done by the global optimizer is
-improving the structure of a basic block.
-For the most part these involve transforming arithmetic or boolean
-expressions into forms that are likely to result in better target code.
-As a simple example, A~+~B*C can be converted to B*C~+~A.
-The latter can often
-be handled by loading B into a register, multiplying the register by C, and
-then adding in A, whereas the former may involve first putting A into a
-temporary, depending on the details of the code generation table.
-Another example of this kind of basic block optimization is transforming
--B~+~A~<~0 into the equivalent, but simpler, A~<~B.
-.NH 1
-The Back End
-.PP
-The back end reads a stream of EM instructions and generates assembly code
-for the target machine.
-Although the algorithm itself is machine independent, for each target
-machine a machine dependent driving table must be supplied.
-The driving table effectively defines the mapping of EM code to target code.
-.PP
-It will be convenient to think of the EM instructions being read as a
-stream of tokens.
-For didactic purposes, we will concentrate on two kinds of tokens:
-those that load something onto the stack, and those that perform some operation
-on the top one or two values on the stack.
-The back end maintains at compile time a simulated stack whose behavior
-mirrors what the stack of a hardware EM machine would do at run time.
-If the current input token is a load instruction, a new entry is pushed onto
-the simulated stack.
-.PP
-Consider, as an example, the EM code produced for the statement K~:=~I~+~7.
-If K and I are
-2-byte local variables, it will normally be LOL I; LOC 7; ADI~2; STL K.
-Initially the simulated stack is empty.
-After the first token has been read and processed, the simulated stack will
-contain a stack token of type MEM with attributes telling that it is a local,
-giving its address, etc.
-After the second token has been read and processed, the top two tokens on the
-simulated stack will be CON (constant) on top and MEM directly underneath it.
-.PP
-At this point the back end reads the ADI~2 token and
-looks in the driving table to find a line or lines that define the
-action to be taken for ADI~2.
-For a typical multiregister machine, instructions will exist to add constants
-to registers, but not to memory.
-Consequently, the driving table will not contain an entry for ADI~2 with stack
-configuration CON, MEM.
-.PP
-The back end is now faced with the problem of how to get from its
-current stack configuration, CON, MEM, which is not listed, to one that is
-listed.
-The table will normally contain rules (which we call "coercions")
-for converting between CON, REG, MEM, and similar tokens.
-Therefore the back end attempts to "coerce" the stack into a configuration
-that
-.I is
-present in the table.
-A typical coercion rule might tell how to convert a MEM into
-a REG, namely by performing the actions of allocating a
-register and emitting code to move the memory word to that register.
-Having transformed the compile-time stack into a configuration allowed for
-ADI~2, the rule can be carried out.
-A typical rule 
-for ADI~2 might have stack configuration REG, MEM
-and would emit code to add the MEM to the REG, leaving the stack
-with a single REG token instead of the REG and MEM tokens present before the
-ADI~2.
-.PP
-In general, there will be more than one possible coercion path.
-Assuming reasonable coercion rules for our example,
-we might be able to convert
-CON MEM into CON REG by loading the variable I into a register.
-Alternatively, we could coerce CON to REG by loading the constant into a register.
-The first coercion path does the add by first loading I into a register and
-then adding 7 to it.
-The second path first loads 7 into a register and then adds I to it.
-On machines with a fast LOAD IMMEDIATE instruction for small constants
-but no fast ADD IMMEDIATE, or vice
-versa, one code sequence will be preferable to the other.
-.PP
-In fact, we actually have more choices than suggested above.
-In both coercion paths a register must be allocated.
-On many machines, not every register can be used in every operation, so the
-choice may be important.
-On some machines, for example, the operand of a multiply must be in an odd
-register.
-To summarize, from any state (i.e., token and stack configuration), a
-variety of choices can be made, leading to a variety of different target
-code sequences.
-.PP
-To decide which of the various code sequences to emit, the back end must have
-some information about the time and memory cost of each one.
-To provide this information, each rule in the driving table, including
-coercions, specifies both the time and memory cost of the code emitted when
-the rule is applied.
-The back end can then simply try each of the legal possibilities (including all
-the possible register allocations) to find the cheapest one.
-.PP
-This situation is similar to that found in a chess or other game-playing
-program, in which from any state a finite number of moves can be made.
-Just as in a chess program, the back end can look at all the "moves" that can
-be made from each state reachable from the original state, and thus find the
-sequence that gives the minimum cost to a depth of one.
-More generally, the back end can evaluate all paths corresponding to accepting
-the next
-.I N
-input tokens, find the cheapest one, and then make the first move along
-that path, precisely the way a chess program would.
-.PP
-Since the back end is analogous to both a parser and a chess playing program,
-some clarifying remarks may be helpful.
-First, chess programs and the back end must do some look ahead, whereas the
-parser for a well-designed grammar can usually suffice with one input token
-because grammars are supposed to be unambiguous.
-In contrast, many legal mappings
-from a sequence of EM instructions to target code may exist.
-Second, like a parser but unlike a chess program, the back end has perfect
-information -- it does not have to contend with an unpredictable opponent's
-moves.
-Third, chess programs normally make a static evaluation of the board and
-label the
-.I nodes
-of the tree with the resulting scores.
-The back end, in contrast, associates costs with
-.I arcs
-(moves) rather than nodes (states).
-However, the difference is not essential, since it could 
-also label each node with the cumulative cost from the root to that node.
-.PP
-As mentioned above, the cost field in the table contains
-.I both
-the time and memory costs for the code emitted.
-It should be clear that the back end could use either one
-or some linear combination of them as the scoring function for evaluating moves.
-A user can instruct the compiler to optimize for time or for memory or
-for, say,  0.3 x time + 0.7 x memory.
-Thus the same compiler can provide a wide range of performance options to
-the user.
-The writer of the back end table can take advantage of this flexibility by
-providing several code sequences with different tradeoffs for each EM
-instruction (e.g., in line code vs. call to a run time routine).
-.PP
-In addition to the time-space tradeoffs, by specifying the depth of search
-parameter,
-.I N ,
-the user can effectively also tradeoff compile time vs. object
-code quality, for whatever code metric has been chosen.
-In summary, by combining the properties of a parser and a game playing program,
-it is possible to make a code generator that is table driven,
-highly flexible, and has the ability to produce good code from a
-stack machine intermediate code.
-.NH 1
-The Target Machine Optimizer
-.PP
-In the model of Fig 2., the peephole optimizer comes before the global
-optimizer.
-It may happen that the code produced by the global optimizer can also
-be improved by another round of peephole optimization.
-Conceivably, the system could have been designed to iterate peephole and
-global optimizations until no more of either could be performed.
-.PP
-However, both of these optimizations are done on the machine independent
-EM code.
-Neither is able to take advantage of the peculiarities and idiosyncracies with
-which most target machines are well endowed.
-It is the function of the final 
-optimizer to do any (peephole) optimizations that still remain.
-.PP
-The algorithm used here is the same as in the EM peephole optimizer.
-In fact, if it were not for the differences between EM syntax, which is
-very restricted, and target assembly language syntax,
-which is less so, precisely the same program could be used for both.
-Nevertheless, the same ideas apply concerning patterns and replacements, so
-our discussion of this optimizer will be restricted to one example.
-.PP
-To see what the target optimizer might do, consider the
-PDP-11 instruction sequence sub #2,r0;  mov (r0),x.
-First 2 is subtracted from register 0, then the word pointed to by it
-is moved to x.
-The PDP-11 happens to have an addressing mode to perform this sequence in
-one instruction: mov -(r0),x.
-Although it is conceivable that this instruction could be included in the
-back end driving table for the PDP-11, it is awkward to do so because it
-can occur in so many contexts.
-It is much easier to catch things like this in a separate program.
-.NH 1
-The Universal Assembler/Linker
-.PP
-Although assembly languages for different machines may appear very different
-at first glance, they have a surprisingly large intersection.
-We have been able to construct an assembler/linker that is almost entirely
-independent of the assembly language being processed.
-To tailor the program to a specific assembly language, it is necessary to
-supply a table giving the list of instructions, the bit patterns required for
-each one, and the language syntax.
-The machine independent part of the assembler/linker is then compiled with the
-table to produce an assembler and linker for a particular target machine.
-Experience has shown that writing the necessary table for a new machine can be
-done in less than a week.
-.PP
-To enforce a modicum of uniformity, we have chosen to use a common set of
-pseudoinstructions for all target machines.
-They are used to initialize memory, allocate uninitialized memory, determine the
-current segment, and similar functions found in most assemblers.
-.PP
-The assembler is also a linker.
-After assembling a program, it checks to see if there are any
-unsatisfied external references.
-If so, it begins reading the libraries to find the necessary routines, including
-them in the object file as it finds them.
-This approach requires libraries to be maintained in assembly language form,
-but eliminates the need for inventing a language to express relocatable
-object programs in a machine independent way.
-It also simplifies the assembler, since producing absolute object code is
-easier than producing relocatable object code.
-Finally, although assembly language libraries may be somewhat larger than
-relocatable object module libraries, the loss in speed due to having more
-input may be more than compensated for by not having to pass an intermediate
-file between the assembler and linker.
-.NH 1
-The Utility Package
-.PP
-The utility package is a collection of programs designed to aid the
-implementers of new front ends or new back ends.
-The most useful ones are the test programs.
-For example, one test set, EMTEST, systematically checks out a back end by
-executing an ever larger subset of the EM instructions.
-It starts out by testing LOC, LOL and a few of the other essential instructions.
-If these appear to work, it then tries out new instructions one at a time,
-adding them to the set of instructions "known" to work as they pass the tests.
-.PP
-Each instruction is tested with a variety of operands chosen from values 
-where problems can be expected.
-For example, on target machines which have 16-bit index registers but only
-allow 8-bit displacements, a fundamentally different algorithm may be needed
-for accessing
-the first few bytes of local variables and those with offsets of thousands.
-The test programs have been carefully designed to thoroughly test all relevant
-cases.
-.PP
-In addition to EMTEST, test programs in Pascal, C, and other languages are also
-available.
-A typical test is:
-.sp
-   i := 9; \fBif\fP i + 250 <> 259 \fBthen\fP error(16);
-.sp
-Like EMTEST, the other test programs systematically exercise all features of the
-language being tested, and do so in a way that makes it possible to pinpoint
-errors precisely.
-While it has been said that testing can only demonstrate the presence of errors
-and not their absence, our experience is that 
-the test programs have been invaluable in debugging new parts of the system
-quickly.
-.PP
-Other utilities include programs to convert
-the highly compact EM code produced by front ends to ASCII and vice versa,
-programs to build various internal tables from human writable input formats,
-a variety of libraries written in or compiled to EM to make them portable,
-an EM assembler, and EM interpreters for various machines.
-.PP
-Interpreting the EM code instead of translating it to target machine language
-is useful for several reasons.
-First, the interpreters provide extensive run time diagnostics including
-an option to list the original source program (in Pascal, C, etc.) with the
-execution frequency or execution time for each source line printed in the
-left margin.
-Second, since an EM program is typically about one-third the size of a
-compiled program, large programs can be executed on small machines.
-Third, running the EM code directly makes it easier to pinpoint errors in 
-the EM output of front ends still being debugged.
-.NH 1
-Summary and Conclusions
-.PP
-The Amsterdam Compiler Kit is a tool kit for building
-portable (cross) compilers and interpreters.
-The main pieces of the kit are the front ends, which convert source programs
-to EM code, optimizers, which improve the EM code, and back ends, which convert
-the EM code to target assembly language.
-The kit is highly modular, so writing one front end
-(and its associated runtime routines)
-is sufficient to implement
-a new language on a dozen or more machines, and writing one back end table
-and one universal assembler/linker table is all that is needed to bring up all
-the previously implemented languages on a new machine.
-In this manner, the contents, and hopefully the usefulness, of the toolkit
-will increase in time.
-.PP
-We believe the principal lesson to be learned from our work is that the old
-UNCOL idea is basically a sound way to produce compilers, provided suitable
-restrictions are placed on the source languages and target machines.
-We also believe that although compilers produced by this technology may not
-be equal to the very best handcrafted compilers,
-in terms of object code quality, they are certainly
-competitive with many existing compilers.
-However, when one factors in the cost of producing the compiler,
-the possible slight loss in performance may be more than compensated for by the
-large decrease in production cost.
-As a consequence of our work and similar work by other researchers [1,3,4],
-we expect integrated compiler building kits to become increasingly popular
-in the near future.
-.PP
-The toolkit is now available for various computers running the
-.UX
-operating system.
-For information, contact the authors.
-.NH 1
-References
-.LP
-.nr r 0 1
-.in +4
-.ti -4
-\fB~\n+r.\fR Graham, S.L.
-Table-Driven Code Generation.
-.I "Computer~13" ,
-8 (August 1980), 25-34.
-.PP
-A discussion of systematic ways to do code generation,
-in particular, the idea of having a table with templates that match parts of
-the parse tree and convert them into machine instructions.
-.sp 2
-.ti -4
-\fB~\n+r.\fR Haddon, B.K., and Waite, W.M.
-Experience with the Universal Intermediate Language Janus.
-.I "Software Practice & Experience~8" ,
-5 (Sept.-Oct. 1978), 601-616.
-.PP
-An intermediate language for use with ALGOL 68, Pascal, etc. is described.
-The paper discusses some problems encountered and how they were dealt with.
-.sp 2
-.ti -4
-\fB~\n+r.\fR Johnson, S.C.
-A Portable Compiler: Theory and Practice.
-.I "Ann. ACM Symp. Prin. Prog. Lang." ,
-Jan. 1978.
-.PP
-A cogent discussion of the portable C compiler.
-Particularly interesting are the author's thoughts on the value of
-computer science theory.
-.sp 2
-.ti -4
-\fB~\n+r.\fR Leverett, B.W., Cattell, R.G.G, Hobbs, S.O., Newcomer, J.M.,
-Reiner, A.H., Schatz, B.R., and Wulf, W.A.
-An Overview of the Production-Quality Compiler-Compiler Project.
-.I Computer~13 ,
-8 (August 1980), 38-49.
-.PP
-PQCC is a system for building compilers similar in concept but differing in
-details from the Amsterdam Compiler Kit.
-The paper describes the intermediate representation used and the code generation
-strategy.
-.sp 2
-.ti -4
-\fB~\n+r.\fR Lowry, E.S., and Medlock, C.W.
-Object Code Optimization.
-.I "Commun.~ACM~12",
-(Jan. 1969), 13-22.
-.PP
-A classic paper on global object code optimization.
-It covers data flow analysis, common subexpressions, code motion, register
-allocation and other techniques.
-.sp 2
-.ti -4
-\fB~\n+r.\fR Nori, K.V., Ammann, U., Jensen, K., Nageli, H.
-The Pascal P Compiler Implementation Notes.
-Eidgen. Tech. Hochschule, Zurich, 1975.
-.PP
-A description of the original P-code machine, used to transport the Pascal-P
-compiler to new computers.
-.sp 2
-.ti -4
-\fB~\n+r.\fR Steel, T.B., Jr. UNCOL: the Myth and the Fact. in
-.I "Ann. Rev. Auto. Prog."
-Goodman, R. (ed.), vol 2., (1960), 325-344.
-.PP
-An introduction to the UNCOL idea by its originator.
-.sp 2
-.ti -4
-\fB~\n+r.\fR Steel, T.B., Jr.
-A First Version of UNCOL.
-.I "Proc. Western Joint Comp. Conf." ,
-(1961), 371-377.
-.PP
-The first detailed proposal for an UNCOL.  By current standards it is a
-primitive language, but it is interesting for its historical perspective.
-.sp 2
-.ti -4
-\fB~\n+r.\fR Tanenbaum, A.S., van Staveren, H., and Stevenson, J.W.
-Using Peephole Optimization on Intermediate Code.
-.I "ACM Trans. Prog. Lang. and Sys. 3" ,
-1 (Jan. 1982) pp. 21-36.
-.PP
-A detailed description of a table-driven peephole optimizer.
-The driving table provides a list of patterns to match as well as the
-replacement text to use for each successful match.
-.sp 2
-.ti -4
-\fB\n+r.\fR Tanenbaum, A.S., Stevenson, J.W., Keizer, E.G., and van Staveren, H.
-Description of an Experimental Machine Architecture for use with Block
-Structured Languages.
-Informatica Rapport 81, Vrije Universiteit, Amsterdam, 1983.
-.PP
-The defining document for EM.
-.sp 2
-.ti -4
-\fB\n+r.\fR Tanenbaum, A.S.
-Implications of Structured Programming for Machine Architecture.
-.I "Comm. ACM~21" ,
-3 (March 1978), 237-246.
-.PP
-The background and motivation for the design of EM.
-This early version emphasized the idea of interpreting the intermediate
-code (then called EM-1) rather than compiling it.

+ 0 - 303
doc/v7bugs.doc

@@ -1,303 +0,0 @@
-.\" $Header$
-.wh 0 hd
-.wh 60 fo
-.de hd
-'sp 5
-..
-.de fo
-'bp
-..
-.nr e 0 1
-.de ER
-.br
-.ne 20
-.sp 2
-.in 5
-.ti -5
-ERROR \\n+e:
-..
-.de PS
-.sp
-.nf
-.in +5
-..
-.de PE
-.sp
-.fi
-.in -5
-..
-.sp 3
-.ce
-UNIX version 7 bugs
-.sp 3
-This document describes the UNIX version 7 errors fixed at the
-Vrije Universiteit, Amsterdam.
-Several of these are discovered at the VU.
-Others are quoted from a list of bugs distributed by BellLabs.
-.sp
-For each error the differences between the original and modified
-source files are given,
-as well as a test program.
-.ER
-C optimizer bug for unsigned comparison
-.sp
-The following C program caused an IOT trap, while it should not
-(compile with 'cc -O prog.c'):
-.PS
-unsigned	i = 0;
-
-main() {
-	register j;
-
-	j = -1;
-	if (i > 40000)
-		abort();
-}
-.PE
-BellLabs suggests to make the following patch in c21.c:
-.PS
-/* modified /usr/src/cmd/c/c21.c */
-
-189		if (r==0) {
-190	/* next 2 lines replaced as indicated by
-191	 * Bell Labs bug distribution ( v7optbug )
-192			p->back->back->forw = p->forw;
-193			p->forw->back = p->back->back;
-194	  End of lines changed */
-195			if (p->forw->op==CBR
-196			  || p->forw->op==SXT
-197			  || p->forw->op==CFCC) {
-198				p->back->forw = p->forw;
-199				p->forw->back = p->back;
-200			} else {
-201				p->back->back->forw = p->forw;
-202				p->forw->back = p->back->back;
-203			}
-204	/* End of new lines */
-205			decref(p->ref);
-206			p = p->back->back;
-207			nchange++;
-208		} else if (r>0) {
-.PE
-Use the previous program to test before and after the modification.
-.ER
-The loader fails for large data or text portions
-.sp
-The loader 'ld' produces a "local symbol botch" error
-for the following C program.
-.PS
-int	big1[10000] = {
-	1
-};
-int	big2[10000] = {
-	2
-};
-
-main() {
-	printf("loader is fine\\n");
-}
-.PE
-We have made the following fix:
-.PS
-/* original /usr/src/cmd/ld.c */
-
-113	struct {
-114		int	fmagic;
-115		int	tsize;
-116		int	dsize;
-117		int	bsize;
-118		int	ssize;
-119		int	entry;
-120		int	pad;
-121		int	relflg;
-122	} filhdr;
-
-/* modified /usr/src/cmd/ld.c */
-
-113	/*
-114	 * The original Version 7 loader had problems loading large
-115	 * text or data portions.
-116	 * Why not include <a.out.h> ???
-117	 * then they would be declared unsigned
-118	 */
-119	struct {
-120		int	fmagic;
-121		unsigned	tsize;		/* not int !!! */
-122		unsigned	dsize;		/* not int !!! */
-123		unsigned	bsize;		/* not int !!! */
-124		unsigned	ssize;		/* not int !!! */
-125		unsigned	entry;		/* not int !!! */
-126		unsigned	pad;		/* not int !!! */
-127		unsigned	relflg;		/* not int !!! */
-128	} filhdr;
-.PE
-.ER
-Floating point registers
-.sp
-When a program is swapped to disk if it needs more memory,
-then the floating point registers were not saved, so that
-it may have different registers when it is restarted.
-A small assembly program demonstrates this for the status register.
-If the error is not fixed, then the program generates an IOT error.
-A "memory fault" is generated if all is fine.
-.PS
-start:	ldfps	$7400
-1:	stfps	r0
-	mov	r0,-(sp)
-	cmp	r0,$7400
-	beq	1b
-	4
-.PE
-You have to dig into the kernel to fix it.
-The following patch will do:
-.PS
-/* original /usr/sys/sys/slp.c */
-
-563		a2 = malloc(coremap, newsize);
-564		if(a2 == NULL) {
-565			xswap(p, 1, n);
-566			p->p_flag |= SSWAP;
-567			qswtch();
-568			/* no return */
-569		}
-
-/* modified /usr/sys/sys/slp.c */
-
-590		a2 = malloc(coremap, newsize);
-591		if(a2 == NULL) {
-592	#ifdef FPBUG
-593			/*
-594			 * copy floating point register and status,
-595			 * but only if you must switch processes
-596			 */
-597			if(u.u_fpsaved == 0) {
-598				savfp(&u.u_fps);
-599				u.u_fpsaved = 1;
-600			}
-601	#endif
-602			xswap(p, 1, n);
-603			p->p_flag |= SSWAP;
-604			qswtch();
-605			/* no return */
-606		}
-.PE
-.ER
-Floating point registers.
-.sp
-A similar problem arises when a process forks.
-The child will have random floating point registers as is
-demonstrated by the following assembly language program.
-The child process will die by an IOT trap and the father prints
-the message "child failed".
-.PS
-exit	= 1.
-fork	= 2.
-write	= 4.
-wait	= 7.
-
-start:	ldfps	$7400
-	sys	fork
-	br	child
-	sys	wait
-	tst	r1
-	bne	bad
-	stfps	r2
-	cmp	r2,$7400
-	beq	start
-	4
-child:	stfps	r2
-	cmp	r2,$7400
-	beq	ex
-	4
-bad:	clr	r0
-	sys	write;mess;13.
-ex:	clr	r0
-	sys	exit
-
-	.data
-mess:	<child failed\\n>
-.PE
-The same file slp.c should be patched as follows:
-.PS
-/* original /usr/sys/sys/slp.c */
-
-499		/*
-500		 * When the resume is executed for the new process,
-501		 * here's where it will resume.
-502		 */
-503		if (save(u.u_ssav)) {
-504			sureg();
-505			return(1);
-506		}
-507		a2 = malloc(coremap, n);
-508		/*
-509		 * If there is not enough core for the
-510		 * new process, swap out the current process to generate the
-511		 * copy.
-512		 */
-
-/* modified /usr/sys/sys/slp.c */
-
-519		/*
-520		 * When the resume is executed for the new process,
-521		 * here's where it will resume.
-522		 */
-523		if (save(u.u_ssav)) {
-524			sureg();
-525			return(1);
-526		}
-527	#ifdef FPBUG
-528		/* copy the floating point registers and status to child */
-529		if(u.u_fpsaved == 0) {
-530			savfp(&u.u_fps);
-531			u.u_fpsaved = 1;
-532		}
-533	#endif
-534		a2 = malloc(coremap, n);
-535		/*
-536		 * If there is not enough core for the
-537		 * new process, swap out the current process to generate the
-538		 * copy.
-539		 */
-.PE
-.ER
-/usr/src/libc/v6/stat.c
-.sp
-Some system calls are changed from version 6 to version 7.
-A library of system call entries, that make a version 6 UNIX look like
-a version 7 system, is provided to enable you to run some
-useful version 7 utilities, like 'tar', on UNIX-6.
-The entry for 'stat' contained two bugs:
-the 24-bit file size was incorrectly converted to 32 bits
-(sign extension of bit 15)
-and the uid/gid fields suffered from sign extension.
-.sp
-Transferring your files from version 6 to version 7 using 'tar'
-will fail for all files for which
-.sp
-	( (size & 0100000) != 0 )
-.sp
-These two errors are fixed if stat.c is modified as follows:
-.PS
-/* original /usr/src/libc/v6/stat.c */
-
-11		char  os_size0;
-12		short os_size1;
-13		short os_addr[8];
-
-49		buf->st_nlink = osbuf.os_nlinks;
-50		buf->st_uid = osbuf.os_uid;
-51		buf->st_gid = osbuf.os_gid;
-52		buf->st_rdev = 0;
-
-/* modified /usr/src/libc/v6/stat.c */
-
-11		char  os_size0;
-12		unsigned os_size1;
-13		short os_addr[8];
-
-49		buf->st_nlink = osbuf.os_nlinks;
-50		buf->st_uid = osbuf.os_uid & 0377;
-51		buf->st_gid = osbuf.os_gid & 0377;
-52		buf->st_rdev = 0;
-.PE

+ 0 - 753
doc/val.doc

@@ -1,753 +0,0 @@
-.\" $Header$
-.ll 72
-.wh 0 hd
-.wh 60 fo
-.de hd
-'sp 5
-..
-.de fo
-'bp
-..
-.tr ~
-.               PARAGRAPH
-.de PP
-.sp
-..
-.               CHAPTER
-.de CH
-.br
-.ne 15
-.sp 3
-.in 0
-\\fB\\$1\\fR
-.in 5
-.PP
-..
-.               SUBCHAPTER
-.de SH
-.br
-.ne 10
-.sp
-.in 5
-\\fB\\$1\\fR
-.in 10
-.PP
-..
-.               INDENT START
-.de IS
-.sp
-.in +5
-..
-.               INDENT END
-.de IE
-.in -5
-.sp
-..
-.               DOUBLE INDENT START
-.de DS
-.sp
-.in +5
-.ll -5
-..
-.               DOUBLE INDENT END
-.de DE
-.ll +5
-.in -5
-.sp
-..
-.               EQUATION START
-.de EQ
-.sp
-.nf
-..
-.               EQUATION END
-.de EN
-.fi
-.sp
-..
-.               TEST
-.de TT
-.ti -5
-Test~\\$1:~
-.br
-..
-.               IMPLEMENTATION 1
-.de I1
-.br
-Implementation~1:
-..
-.               IMPLEMENTATION 2
-.de I2
-.br
-Implementation~2:
-..
-.de CS
-.br
-~-~\\
-..
-.br
-.fi
-.sp 5
-.ce
-\fBPascal Validation Suite Report\fR
-.CH "Pascal processor identification"
-The ACK-Pascal compiler produces code for an EM machine
-as defined in [1].
-It is up to the implementor of the EM machine whether errors like
-integer overflow, undefined operand and range bound error are recognized or not.
-Therefore it depends on the EM machine implementation whether these errors
-are recognized in Pascal programs or not.
-The validation suite results of all known implementations are given.
-.PP
-There does not (yet) exist a hardware EM machine.
-Therefore, EM programs must be interpreted, or translated into
-instructions for a target machine.
-The following implementations currently exist:
-.IS
-.I1
-an interpreter running on a PDP-11 (using UNIX).
-The normal mode of operation for this interpreter is to check
-for undefined integers, overflow, range errors etc.
-.sp
-.I2
-a translator into PDP-11 instructions (using UNIX).
-Less checks are performed than in the interpreter, because the translator
-is intended to speed up the execution of well-debugged programs.
-.IE
-.CH "Test Conditions"
-Tester: E.G. Keizer
-.br
-Date: October 1983
-.br
-Validation Suite version: 3.0
-.PP
-The final test run is made with a slightly
-modified validation suite.
-.SH "Erroneous programs"
-Some test did not conform to the standard proposal of February 1979.
-It is this version of the standard proposal that is used
-by the authors of the validation suite.
-.IS
-.TT 6.6.3.7-4
-The semicolon between high and integer on line 17 is replaced
-by a colon.
-.sp
-.TT 6.7.2.2-13
-The div operator on line 14 replaced by mod.
-.CH "Conformance tests"
-Number of tests passed = 150
-.br
-Number of tests failed = 6
-.SH "Details of failed tests"
-.IS
-.TT 6.1.2-1
-Character sequences starting with the 8 characters 'procedur'
-or 'function' are
-erroneously classified as the word-symbols 'procedure' and 'function'.
-.sp
-.TT 6.1.3-2
-Identifiers identical in the first eight characters, but
-differing in ninth or higher numbered characters are treated as
-identical.
-.sp
-.TT 6.5.1-1
-ACK-Pascal requires all formal program parameters to be
-declared with type \fIfile\fP.
-.sp
-.TT 6.6.6.5-1
-Gives run-time error eof seen at call to eoln.
-A have a hunch that this is a error in the suit.
-.sp
-.TT 6.6.4.1-1
-Redefining the names of some standard procedures leads to incorrect
-behaviour of the runtime system.
-In this case it crashes without a sensible error message.
-.sp
-.TT 6.9.3.5.1-1
-This test can not be translated by our compiler because two
-non-identical variables are used in the same block with the same first eight
-characters.
-The test passed after replacement of one of those names.
-.IE
-.CH "Deviance tests"
-Number of deviations correctly detected = 120
-.br
-Number of tests not detecting deviations = 20
-.SH "Details of deviations"
-The following tests are compiled without a proper error
-indication although they do
-not conform to the standard.
-.IS
-.TT 6.1.6-5
-ACK-Pascal allows labels in the range 0..32767.
-A warning is produced when testing for deviations from the
-standard.
-.sp
-.TT 6.1.8-5
-A missing space between a number and a word symbol is not
-detected.
-.sp
-.TT 6.2.2-8
-.TT 6.3-6
-.TT 6.4.1-3
-.TT 6.6.1-3
-.TT 6.6.1-4
-Undetected scope error. The scope of an identifier should start at the
-beginning of the block in which it is declared.
-In the ACK-Pascal compiler the scope starts just after the declaration,
-however.
-.sp
-.TT 6.4.3.3-7
-The values of fields from one variant are accessible from
-another variant.
-The correlation is exact.
-.sp
-.TT 6.6.3.3-4
-The passing as a variable parameter of the selector of a
-variant part is not detected.
-A runtime error is produced because the variant selector is not
-initialized.
-.sp
-.TT 6.8.2.4-2
-.TT 6.8.2.4-3
-.TT 6.8.2.4-4
-.TT 6.8.2.4-5
-.TT 6.8.2.4-6
-The ACK-Pascal compiler does not restrict the places from where
-you may jump to a label by means of a goto-statement.
-.sp
-.TT 6.8.3.9-5
-.TT 6.8.3.9-6
-.TT 6.8.3.9-7
-.TT 6.8.3.9-16
-There are no errors produced for assignments to a variable
-in use as control-variable of a for-statement.
-.TT 6.8.3.9-8
-.TT 6.8.3.9-9
-Use of a controlled variable after leaving the loop without
-intervening initialization is not detected.
-.IE
-.CH "Error handling"
-The results depend on the EM implementation.
-.sp
-Number of errors correctly detected =
-.in +5
-.I1
-32
-.I2
-17
-.in -5
-Number of errors not detected =
-.in +5
-.I1
-21
-.I2
-36
-.in -5
-Number of errors incorrectly detected =
-.in +5
-.I1
-2
-.I2
-2
-.in -5
-.SH "Details of errors not detected"
-The following test fails because the ACK-Pascal compiler only
-generates a warning that does not prevent to run the tests.
-.IS
-.TT 6.6.2-8
-A warning is produced if there is no assignment to a function-identifier.
-.IE
-With this test the ACK-Pascal compiler issues an error message for a legal
-construct not directly related to the error to be detected.
-.IS
-.TT 6.5.5-2
-Program does not compile.
-Buffer variable of text file is not allowed as variable
-parameter.
-.IE
-The following errors are not detected at all.
-.IS
-.TT 6.2.1-11
-.I2
-The use of an undefined integer is not caught as an error.
-.sp
-.TT 6.4.3.3-10
-.TT 6.4.3.3-11
-.TT 6.4.3.3-12
-.TT 6.4.3.3-13
-The notion of 'current variant' is not implemented, not even if a tagfield
-is present.
-.sp
-.TT 6.4.5-15
-.TT 6.4.6-9
-.TT 6.4.6-10
-.TT 6.4.6-11
-.TT 6.5.3.2-2
-.I2
-Subrange bounds are not checked.
-.sp
-.TT 6.4.6-12
-.TT 6.4.6-13
-.TT 6.7.2.4-4
-If the base-type of a set is a subrange, then the set elements are not checked
-against the bounds of the subrange.
-Only the host-type of this subrange-type is relevant for ACK-Pascal.
-.sp
-.TT 6.5.4-1
-.I2
-Nil pointers are not detected.
-.sp
-.TT 6.5.4-2
-.I2
-Undefined pointers are not detected.
-.sp
-.TT 6.5.5-3
-Changing the file position while the window is in use as actual variable
-parameter or as an element of the record variable list of a with-statement
-is not detected.
-.sp
-.TT 6.6.2-9
-An undefined function result is not detected,
-because it is never used in an expression.
-.sp
-.TT 6.6.5.3-6
-.TT 6.6.5.3-7
-Disposing a variable while it is in use as actual variable parameter or
-as an element of the record variable list of a with-statement is not detected.
-.sp
-.TT 6.6.5.3-8
-.TT 6.6.5.3-9
-.TT 6.6.5.3-10
-It is not detected that a record variable, created with the variant form
-of new, is used as an operand in an expression or as the variable in an
-assignment or as an actual value parameter.
-.sp
-.TT 6.6.5.3-11
-Use of a variable that is not reinitialized after a dispose is
-not detected.
-.sp
-.TT 6.6.6.4-4
-.TT 6.6.6.4-5
-.TT 6.6.6.4-7
-.I2
-There are no range checks for pred, succ and chr.
-.sp
-.TT 6.6.6.5-6
-ACK-Pascal considers a rewrite of a file as a defining
-occurence.
-.sp
-.TT 6.7.2.2-8
-.TT 6.7.2.2-9
-.TT 6.7.2.2-10
-.TT 6.7.2.2-12
-.I2
-Division by 0 or integer overflow is not detected.
-.sp
-.TT 6.8.3.9-18
-The use of the some control variable in two nested for
-statements in not detected.
-.sp
-.TT 6.8.3.9-19
-Access of a control variable after leaving the loop results in
-the final-value, although an error should be produced.
-.sp
-.TT 6.9.3.2-3
-The program stops with a file not open error.
-The rewrite before the write is missing in the program.
-.sp
-.TT 6.9.3.2-4
-.TT 6.9.3.2-5
-Illegal FracDigits values are not detected.
-.CH "Implementation dependence"
-Number of tests run = 14
-.br
-Number of tests incorrectly handled = 0
-.SH "Details of implementation dependence"
-.IS
-.TT 6.1.9-5
-Alternate comment delimiters are implemented
-.sp
-.TT 6.1.9-6
-The equivalent symbols @ for ^, (. for [ and .) for ] are not
-implemented.
-.sp
-.TT 6.4.2.2-10
-Maxint = 32767
-.sp
-.TT 6.4.3.4-5
-Only elements with non-negative ordinal value are allowed in sets.
-.sp
-.TT 6.6.6.1-1
-Standard procedures and functions are not allowed as parameters.
-.sp
-.TT 6.6.6.2-11
-Details of the machine characteristics regarding real numbers:
-.IS
-.nf
-beta =       2
-t =         56
-rnd =        1
-ngrd =       0
-machep =   -56
-negep =    -56
-iexp =       8
-minexp =  -128
-maxexp =   127
-eps =     1.387779e-17
-epsneg =  1.387779e-17
-xmin =    2.938736e-39
-xmax =    1.701412e+38
-.fi
-.IE
-.sp
-.TT 6.7.2.3-3
-.TT 6.7.2.3-4
-All operands of boolean expressions are evaluated.
-.sp
-.TT 6.8.2.2-1
-.TT 6.8.2.2-2
-The expression in an assignment statement is evaluated
-before the variable selection if this involves pointer
-dereferencing or array indexing.
-.sp
-.TT 6.8.2.3-2
-Actual parameters are evaluated in reverse order.
-.sp
-.TT 6.9.3.2-6
-The default width for integer, Boolean and real are 6, 5 and 13.
-.sp
-.TT 6.9.3.5.1-2
-The number of digits written in an exponent is 2.
-.sp
-.TT 6.9.3.6-1
-The representations of true and false are (~true) and (false).
-The parenthesis serve to indicate width.
-.IE
-.CH "Quality measurement"
-Number of tests run = 60
-.br
-Number of tests handled incorrectly = 1
-.SH "Results of tests"
-Several test perform operations on reals on indicate the error
-introduced by these operations.
-For each of these tests the following two quality measures are extracted:
-.sp
-.in +5
-maxRE:~~maximum relative error
-.br
-rmsRE:~~root-mean-square relative error
-.in -5
-.sp 2
-.IS
-.TT 1.2-1
-.I1
-25 thousand Whetstone instructions per second.
-.I2
-169 thousand Whetstone instructions per second.
-.sp
-.TT 1.2-2
-The value of (TRUEACC-ACC)*2^56/100000 is 1.4 .
-This is well within the bounds specified in [3].
-.br
-The GAMM measure is:
-.I1
-238 microseconds
-.I2
-26.3 microseconds.
-.sp
-.TT 1.2-3
-The number of procedure calls calculated in this test exceeds
-the maximum integer value.
-The program stops indicating overflow.
-.sp
-.TT 6.1.3-3
-The number of significant characters for identifiers is 8.
-.sp
-.TT 6.1.5-8
-There is no maximum to the line length.
-.sp
-.TT 6.1.5-9
-The error message "too many digits" is given for numbers larger
-than maxint.
-.sp
-.TT 6.1.5-10
-.TT 6.1.5-11
-.TT 6.1.5-12
-Normal values are allowed for real constants and variables.
-.sp
-.TT 6.1.7-14
-A reasonably large number of strings is allowed.
-.sp
-.TT 6.1.8-6
-No warning is given for possibly unclosed comments.
-.sp
-.TT 6.2.1-12
-.TT 6.2.1-13
-.TT 6.2.1-14
-.TT 6.2.1-15
-.TT 6.5.1-2
-Large lists of declarations are possible in each block.
-.sp
-.TT 6.4.3.2-6
-An 'array[integer] of' is not allowed.
-.sp
-.TT 6.4.3.2-7
-.TT 6.4.3.2-8
-Large values are allowed for arrays and indices.
-.sp
-.TT 6.4.3.3-14
-Large amounts of case-constant values are allowed in variants.
-.sp
-.TT 6.4.3.3-15
-Large amounts of record sections can appear in the fixed part of
-a record.
-.sp
-.TT 6.4.3.3-16
-Large amounts of variants are allowed in a record.
-.TT 6.4.3.4-4
-Size and speed of Warshall's algorithm depend on the
-implementation of EM:
-.IS
-.I1
-.br
-size: 122 bytes
-.br
-speed: 5.2 seconds
-.sp
-.I2
-.br
-size: 196 bytes
-.br
-speed: 0.7 seconds
-.IE
-.TT 6.5.3.2-3
-Deep nesting of array indices is allowed.
-.sp
-.TT 6.5.3.2-4
-.TT 6.5.3.2-5
-Arrays can have at least 8 dimensions.
-.sp
-.TT 6.6.1-8
-Deep static nesting of procedure is allowed.
-.sp
-.TT 6.6.3.1-6
-Large amounts of formal parameters are allowed.
-.sp
-.TT 6.6.5.3-12
-Dispose is fully implemented.
-.sp
-.TT 6.6.6.2-6
-Test sqrt(x): no errors.
-The error is within acceptable bounds.
-.in +5
-maxRE:~~2~**~-55.50
-.br
-rmsRE:~~2~**~-57.53
-.in -5
-.sp
-.TT 6.6.6.2-7
-Test arctan(x): may cause underflow or overflow errors.
-The error is within acceptable bounds.
-.in +5
-.br
-maxRE:~~2~**~-55.00
-.br
-rmsRE:~~2~**~-56.36
-.in -5
-.sp
-.TT 6.6.6.2-8
-Test exp(x): may cause underflow or overflow errors.
-The error is not within acceptable bounds.
-.in +5
-maxRE:~~2~**~-50.03
-.br
-rmsRE:~~2~**~-51.03
-.in -5
-.sp
-.TT 6.6.6.2-9
-Test sin(x): may cause underflow errors.
-The error is not within acceptable bounds.
-.in +5
-maxRE:~~2~**~-38.20
-.br
-rmsRE:~~2~**~-43.68
-.in -5
-.sp
-Test cos(x): may cause underflow errors.
-The error is not within acceptable bounds.
-.in +5
-maxRE:~~2~**~-41.33
-.br
-rmsRE:~~2~**~-46.62
-.in -5
-.sp
-.TT 6.6.6.2-10
-Test ln(x):
-The error is not within acceptable bounds.
-.in +5
-maxRE:~~2~**~-54.05
-.br
-rmsRE:~~2~**~-55.77
-.in -5
-.sp
-.TT 6.7.1-3
-.TT 6.7.1-4
-.TT 6.7.1-5
-Complex nested expressions are allowed.
-.sp
-.TT 6.7.2.2-14
-Test real division:
-The error is within acceptable bounds.
-.in +5
-maxRE:~~0
-.br
-rmsRE:~~0
-.in -5
-.sp
-.TT 6.7.2.2-15
-Operations of reals in the integer range are exact.
-.sp
-.TT 6.7.3-1
-.TT 6.8.3.2-1
-.TT 6.8.3.4-2
-.TT 6.8.3.5-15
-.TT 6.8.3.7-4
-.TT 6.8.3.8-3
-.TT 6.8.3.9-20
-.TT 6.8.3.10-7
-Static deep nesting of function calls,
-compound statements, if statements, case statements, repeat
-loops, while loops, for loops and with statements is possible.
-.sp
-.TT 6.8.3.2-2
-Large amounts of statements are allowed in a compound
-statement.
-.sp
-.TT 6.8.3.5-12
-The compiler requires case constants to be compatible with
-the case selector.
-.sp
-.TT 6.8.3.5-13
-.TT 6.8.3.5-14
-Large case statements are possible.
-.sp
-.TT 6.9-2
-Recursive IO on the same file is well-behaved.
-.sp
-.TT 6.9.1-6
-The reading of real values from a text file is done with
-sufficient accuracy.
-.in +5
-maxRE:~~2~**~-54.61
-.br
-rmsRE:~~2~**~-56.32
-.in -5
-.sp
-.TT 6.9.1-7
-.TT 6.9.2-2
-.TT 6.9.3-3
-.TT 6.9.4-2
-Read, readln, write and writeln may have large amounts of
-parameters.
-.sp
-.TT 6.9.1-8
-The loss of precision for reals written on a text file and read
-back is:
-.in +5
-maxRE:~~2~**~-53.95
-.br
-rmsRE:~~2~**~-55.90
-.in -5
-.sp
-.TT 6.9.3-2
-File IO buffers without trailing marker are correctly flushed.
-.sp
-.TT 6.9.3.5.2-2
-Reals are written with sufficient accuracy.
-.in +5
-maxRE:~~0
-.br
-rmsRE:~~0
-.in -5
-.IE
-.CH "Level 1 conformance tests"
-Number of test passed = 4
-.br
-Number of tests failed = 1
-.SH "Details of failed tests"
-.IS
-.TT 6.6.3.7-4
-An expression indicated by parenthesis whose
-value is a conformant array is not allowed.
-.IE
-.CH "Level 1 deviance tests"
-Number of deviations correctly detected = 4
-.br
-Number of tests not detecting deviations = 0
-.IE
-.CH "Level 1 error handling"
-The results depend on the EM implementation.
-.sp
-Number of errors correctly detected =
-.in +5
-.I1
-1
-.I2
-0
-.in -5
-Number of errors not detected =
-.in +5
-.I1
-0
-.I2
-1
-.in -5
-.SH "Details of errors not detected"
-.IS
-.TT 6.6.3.7-9
-.I2
-Subrange bounds are not checked.
-.IE
-.CH "Level 1 quality measurement"
-Number of tests run = 1
-.SH "Results of test"
-.IS
-.TT 6.6.3.7-10
-Large conformant arrays are allowed.
-.IE
-.CH "Extensions"
-Number of tests run = 3
-.SH Details of test failed
-.IS
-.TT 6.1.9-7
-The alternative relational operators are not allowed.
-.sp
-.TT 6.1.9-8
-The alternative symbols for colon, semicolon and assignment are
-not allowed.
-.sp
-.TT 6.8.3.5-16
-The otherwise selector in case statements is not allowed.
-.IE
-.CH "References"
-.ti -5
-[1]~~\
-A.S.Tanenbaum, E.G.Keizer, J.W.Stevenson, Hans van Staveren,
-"Description of a machine architecture for use with block structured
-languages",
-Informatica rapport IR-81.
-.ti -5
-[2]~~\
-ISO standard proposal ISO/TC97/SC5-N462, dated February 1979.
-The same proposal, in slightly modified form, can be found in:
-A.M.Addyman e.a., "A draft description of Pascal",
-Software, practice and experience, May 1979.
-An improved version, received March 1980,
-is followed as much as possible for the
-current ACK-Pascal.
-.ti -5
-[3]~~\
-B. A. Wichman and J du Croz,
-A program to calculate the GAMM measure, Computer Journal,
-November 1979.

+ 0 - 19
emtest/Makefile

@@ -1,19 +0,0 @@
-tested:		last
-	set -x ;\
-		for i in `awk '{for(i=\$$1;i<=127;i++)print i}' last ` ;\
-		do \
-		  echo $$i; \
-		  echo $$i >last; \
-		  select $$i tests > test.e; \
-		  ack test.e; \
-		  a.out \
-		  : ok; \
-		done
-		rm -f test.e a.out
-		>tested
-
-last:		tests test.h select
-		echo 0 >last
-
-select:		select.c
-		cc -O -n -o select select.c

+ 0 - 136
emtest/READ_ME

@@ -1,136 +0,0 @@
-This directory contains test programs for EM implementations.
-The test programs are all part of the file "tests".
-Each individual test program looks like:
-
-	TEST 004: test ...
-	 ...		; data declarations etc.
-	MAIN nlocal
-	 ...		; part of the body of MAIN
-	PROC
-	 ...		; subroutines used by this test
-
-The PROC part is optional, so the smallest test program looks like:
-
-	TEST 000: null test
-	MAIN 0
-
-The keywords used by "select", like TEST, MAIN, PROC, HOL, OK and ERRLAB,
-all consist of upper case letters and start in column one.
-A convention for test numbers is to use 3 digit numbers, possibly left
-padded with zero's.
-
-A program, called "select", is provided to combine a range of tests
-into a single test program.
-"Select" expects a range as argument, like 0-127, or -127, or 0-.
-Tests that have a TEST number in that range are included.
-"Select" also expects the file from which the tests should
-be selected as an argument.
-If no argument is given, or only a range argument, select expects
-the tests to slect from on standard input.
-
-To prevent name clashes, some rules must be obeyed:
-   - data label names, procedure names and instruction label numbers
-     must be unique over all tests. A good habit is to use the
-     three digit test number as suffix.
-   - only keyword of "select" may start with uppercase letters in column
-     one, to allow for expansion in the future.
-   - because only a single 'hol' pseudo is allowed, "select" must
-     generate the 'hol' pseudo. An individual test may request
-     some 'hol' space by a special HOL line, starting in column one
-     and followed by a single number, the number of bytes needed.
-     This number must consists of digits only, no constant symbols,
-     because "select" must compute the maximum, so before the
-     preprocessor has replaced the constant symbols by their values.
-   - a similar problem is caused by the number of bytes of local
-     storage for 'main'. An individual test may specify the number
-     of bytes it needs as parameter to the MAIN line.
-     Again, the number must consist of digits only.
-
-Test programs print a sequence of integers greater than 1.
-This sequence is terminated by the number 1 as soon as an error is detected.
-If all tests are performed correctedly the number 0 is printed.
-
-To allow test programs to print integers without the full machinery of
-conversion and i/o routines, the EM instruction 'nop' is used.
-Each time this instruction is executed, the current line number as
-maintained by the 'lin' instruction must be printed, followed by a
-newline, at least during debugging.
-
-The following abbrevation may be used in test programs:
-
-	OK	->	lin n
-			nop
-
-Numbers are automatically assigned in order of static appearance.
-As soon as an error is detected you must branch to label 1, by instructions
-like 'bra *1' and 'zne *1'.
-Label 1 is automatically provided in the main routine.
-If you jump to label 1 in a subroutine, then that subroutine must
-end with ERRLAB, like in:
-
-	PROC
-	 pro $test,0
-	 ...
-	 bra *1
-	 ...
-	 ret 0
-	ERRLAB
-	 end
-
-An option to "select" is to generate 'fil' instructions whenever a
-new test starts.
-This is useful if 'nop' prints the 'fil' string as well as the 'lin' number.
-This 'f' option is on by default, off if a '-f' flag is given.
-
-The EM file generated by "select" includes "test.h".
-"test.h" may contain definitions of the following symbols:
-	W2S:	the size of double precision integers, if implemented.
-	FS:	the size of single precision floats, if implemented.
-	F2S:	the size of double precision floats, if implemented.
-The value of these symbols, if defined, must be the size of the object involved.
-
-Two other symbols are used:
-	EM_PSIZE:	pointer size
-	EM_WSIZE:	word size
-The machine dependent translation program, like 8086 and vax2, give
-definitions of these symbols while calling the EM encode program.
-Because these size names occur quite often, they may be abbreviated:
-	WS	->	EM_WSIZE
-	PS	->	EM_PSIZE
-
-Before running the tests in the file "tests", it is wise to test
-the necessary basic functions with some simple tests like
-
-	TEST 000: null
-	MAIN 0
-and
-	TEST 001: ok
-	MAIN 0
-	OK
-and
-	TEST 998: error
-	MAIN 0
-	 bra *1
-and
-	TEST 999: test lni
-	MAIN 0
-	 lin 1
-	 lni
-	 loe 0
-	 loc 2
-	 bne *1
-	OK
-The first two of these are part of "tests" as well. The last two are
-not included in "tests" intensionally, because they would fail.
-The last tests fails because it references the ABS block which is
-inaccessable after an 'hol' pseudo.
-Proceed as follows for each of these basic tests:
- - make a file called 'basic' containing the test
- - run select:
-	select basic >basic.e
- - compile by
-	machine basic.e
- - and load and run
-
-   where machine should be replaced by the name of program
-   used to compile EM programs for the current machine.

+ 0 - 1
emtest/last

@@ -1 +0,0 @@
-0

+ 0 - 10
emtest/ok

@@ -1,10 +0,0 @@
-trap "" 1 2
-
-while read x
-do
-	case $x in
-	0)	exit 0;;
-	bad)	exit 1;;
-	esac
-done
-exit 1

+ 0 - 249
emtest/select.c

@@ -1,249 +0,0 @@
-/*
- * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
- *
- *          This product is part of the Amsterdam Compiler Kit.
- *
- * Permission to use, sell, duplicate or disclose this software must be
- * obtained in writing. Requests for such permissions may be sent to
- *
- *      Dr. Andrew S. Tanenbaum
- *      Wiskundig Seminarium
- *      Vrije Universiteit
- *      Postbox 7161
- *      1007 MC Amsterdam
- *      The Netherlands
- *
- */
-
-#include	<stdio.h>
-#include	<assert.h>
-#include	<signal.h>
-
-#define	LINSIZ	100
-
-int	sigs[] = {
-	SIGHUP,
-	SIGINT,
-	SIGQUIT,
-	SIGTERM,
-	0
-};
-
-char	*prog;
-char	line[LINSIZ];
-int	nlocals	= 0;
-int	nhol	= 0;
-int	nerrors	= 0;
-int	oknum	= 2;
-int	fflag	= 1;
-int	low	= 0;
-int	high	= 999;
-
-FILE	*file1;
-FILE	*file2;
-FILE	*file3;
-char	name1[] = "/usr/tmp/f1XXXXXX";
-char	name2[] = "/usr/tmp/f2XXXXXX";
-char	name3[] = "/usr/tmp/f3XXXXXX";
-
-stop() {
-	unlink(name1);
-	unlink(name2);
-	unlink(name3);
-	exit(nerrors);
-}
-
-main(argc,argv) char **argv; {
-	register *p;
-	register char *s;
-
-	prog = *argv++; --argc;
-	mktemp(name1);
-	mktemp(name2);
-	mktemp(name3);
-	for (p = sigs; *p; p++)
-		if (signal(*p, stop) == SIG_IGN)
-			signal(*p, SIG_IGN);
-	while (argc > 0 && argv[0][0] == '-') {
-		switch (argv[0][1]) {
-		case 'f':
-			fflag ^= 1;
-			break;
-		case '0': case '1': case '2': case '3': case '4':
-		case '5': case '6': case '7': case '8': case '9':
-			high = atoi(&argv[0][1]);
-			break;
-		default:
-			usage();
-			break;
-		}
-		argc--;
-		argv++;
-	}
-	if (argc > 0 && argv[0][0] >= '0' && argv[0][0] <= '9') {
-		s = argv[0];
-		do
-			low = low*10 + *s++ - '0';
-		while (*s >= '0' && *s <= '9');
-		if (*s == 0)
-			high = low;
-		else if (*s++ == '-') {
-			high = atoi(s);
-			if (high == 0)
-				high = 999;
-		} else
-			fatal("bad range %s", argv[0]);
-		argc--;
-		argv++;
-	}
-	if (argc > 1)
-		usage();
-	if (argc == 1 && freopen(argv[0], "r", stdin) == NULL)
-		fatal("cannot open %s", argv[0]);
-	if ((file1 = fopen(name1, "w")) == NULL)
-		fatal("cannot create %s", name1);
-	if ((file2 = fopen(name2, "w")) == NULL)
-		fatal("cannot create %s", name2);
-	if ((file3 = fopen(name3, "w")) == NULL)
-		fatal("cannot create %s", name3);
-	if (getline())
-		while (select())
-			;
-	fclose(file1);
-	fclose(file2);
-	fclose(file3);
-	combine();
-	stop();
-}
-
-select() {
-	register FILE *f;
-	int i;
-
-	if (sscanf(line, "TEST %d", &i) != 1)
-		fatal("bad test identification(%s)", line);
-	if (i < low || i > high) {
-		while (getline())
-			if (line[0] == 'T')
-				return(1);
-		return(0);
-	}
-	fprintf(file2, "; %s\n", line);
-	if (fflag) {
-		fprintf(file1, ".%03d\n", i);
-		fprintf(file1, " con \"tst%03d\"\n", i);
-		fprintf(file2, " fil .%03d\n", i);
-	}
-	f = file1;
-	while (getline()) {
-		switch (line[0]) {
-		case 'T':
-			return(1);
-		case 'M':
-			if (sscanf(line, "MAIN%d", &i) != 1 || i%4 != 0)
-				break;
-			if (i > nlocals)
-				nlocals = i;
-			f = file2;
-			continue;
-		case 'P':
-			if (strcmp(line, "PROC") != 0)
-				break;
-			f = file3;
-			continue;
-		case 'H':
-			if (f != file1 ||
-			    sscanf(line, "HOL%d", &i) != 1 ||
-			    i%4 != 0)
-				break;
-			if (i > nhol)
-				nhol = i;
-			continue;
-		case 'O':
-			if (strcmp(line, "OK") != 0)
-				break;
-			fprintf(f, " lin %d\n nop\n", oknum++);
-			continue;
-		case 'E':
-			if (f != file3 || strcmp(line, "ERRLAB") != 0)
-				break;
-			fprintf(f, "1\n lin 1\n nop\n loc 1\n loc 1\n mon\n");
-			continue;
-		default:
-			putline(f);
-			continue;
-		}
-		fatal("bad line (%s)", line);
-	}
-	return(0);
-}
-
-combine() {
-
-	printf("#define WS EM_WSIZE\n");
-	printf("#define PS EM_PSIZE\n");
-	printf("#include \"test.h\"\n");
-	printf(" mes 2,WS,PS\n");
-	printf(" mes 1\n");
-	printf(" mes 4,300\n");
-	if (nhol)
-		printf(" hol %d,0,0\n", nhol);
-	copy(name1);
-	printf(" exp $m_a_i_n\n");
-	printf(" pro $m_a_i_n,%d\n", nlocals);
-	printf(" loc 123\n");
-	printf(" loc -98\n");
-	copy(name2);
-	printf(" loc -98\n");
-	printf(" bne *1\n");
-	printf(" loc 123\n");
-	printf(" bne *1\n");
-	printf(" lin 0\n");
-	printf(" nop\n");
-	printf(" loc 0\n");
-	printf(" ret WS\n");
-	printf("1\n");
-	printf(" lin 1\n");
-	printf(" nop\n");
-	printf(" loc 1\n");
-	printf(" ret WS\n");
-	printf(" end\n");
-	copy(name3);
-}
-
-copy(s) char *s; {
-	if (freopen(s, "r", stdin) == NULL)
-		fatal("cannot reopen %s", s);
-	while (getline())
-		putline(stdout);
-}
-
-getline() {
-	register len;
-
-	if (fgets(line, LINSIZ, stdin) == NULL)
-		return(0);
-	len = strlen(line);
-	if (line[len-1] != '\n')
-		fatal("line too long(%s)", line);
-	line[len-1] = 0;
-	return(1);
-}
-
-putline(f) FILE *f; {
-	fprintf(f, "%s\n", line);
-}
-
-fatal(s, a1, a2, a3, a4) char *s; {
-	fprintf(stderr, "%s: ", prog);
-	fprintf(stderr, s, a1, a2, a3, a4);
-	fprintf(stderr, " (fatal)\n");
-	nerrors++;
-	stop();
-}
-
-usage() {
-	fprintf(stderr, "usage: %s -f [[low]-[high]] [testcollection]\n", prog);
-	nerrors++;
-	stop();
-}

+ 0 - 28
emtest/test.e

@@ -1,28 +0,0 @@
-#define WS EM_WSIZE
-#define PS EM_PSIZE
-#include "test.h"
- mes 2,WS,PS
- mes 1
- mes 4,300
-.000
- con "tst000"
- exp $m_a_i_n
- pro $m_a_i_n,0
- loc 123
- loc -98
-; TEST 000: empty
- fil .000
- loc -98
- bne *1
- loc 123
- bne *1
- lin 0
- nop
- loc 0
- ret WS
-1
- lin 1
- nop
- loc 1
- ret WS
- end

+ 0 - 0
emtest/test.h


+ 0 - 3605
emtest/tests

@@ -1,3605 +0,0 @@
-TEST 000: empty
-MAIN 0
-TEST 001: OK
-MAIN 0
-OK
-TEST 002: test loc, bne
-MAIN 0
- loc 0
- loc 0
- bne *1
-OK
- loc 1
- loc 1
- bne *1
-OK
- loc -1
- loc -1
- bne *1
-OK
- loc 127
- loc 127
- bne *1
-OK
- loc -127
- loc -127
- bne *1
-OK
- loc -128
- loc -128
- bne *1
-OK
-#if WS > 1
- loc 255
- loc 255
- bne *1
-OK
- loc 256
- loc 256
- bne *1
-OK
- loc 257
- loc 257
- bne *1
-OK
- loc 32767
- loc 32767
- bne *1
-OK
- loc -32767
- loc -32767
- bne *1
-OK
- loc -32768
- loc -32768
- bne *1
-OK
-#endif WS > 1
-#if WS > 2
- loc 65535
- loc 65535
- bne *1
-OK
- loc 65536
- loc 65536
- bne *1
-OK
- loc 65537
- loc 65537
- bne *1
-OK
- loc 2147483647
- loc 2147483647
- bne *1
-OK
- loc -2147483647
- loc -2147483647
- bne *1
-OK
- loc -2147483648
- loc -2147483648
- bne *1
-OK
-#endif WS > 2
-TEST 003: test signed and unsigned loc
-MAIN 0
-#if WS == 1
- loc 128
- loc -128
- bne *1
-OK
- loc 129
- loc -127
- bne *1
-OK
- loc 255
- loc -1
- bne *1
-OK
-#endif
-#if WS == 2
- loc 32768
- loc -32768
- bne *1
-OK
- loc 32769
- loc -32767
- bne *1
-OK
- loc 65535
- loc -1
- bne *1
-OK
-#endif
-#if WS == 4
- loc 2147483648
- loc -2147483648
- bne *1
-OK
- loc 2147483649
- loc -2147483647
- bne *1
-OK
- loc 4294967295
- loc -1
- bne *1
-OK
-#endif
-TEST 004: test lol, stl
-MAIN 8
- loc 95
- stl -4
- lol -4
- loc 95
- bne *1
-OK
- lol 0
- stl -4
- loc 125
- stl -8
- loc 125
- lol -8
- bne *1
-OK
- lol 0
- lol -4
- bne *1
-OK
-TEST 005: test loe, ste
-HOL 8
-MAIN 0
- loc 95
- ste 4
- loe 4
- loc 95
- bne *1
-OK
- loc 125
- ste 0
- loc 125
- loe 0
- bne *1
-OK
- loc 95
- ste 0
- loe 4
- loe 0
- bne *1
-OK
-TEST 006: test named global data: con, rom, bss
-a006
- bss 4,0,0
-b006
- con 35
-c006
- bss 4,0,1
-d006
- bss 4,35,1
-e006
- rom 57
-MAIN 0
- loc 0
- loe c006
- bne *1
-OK
- loe b006
- ste a006
- loe d006
- loe a006
- bne *1
-OK
- loe e006
- ste b006
- loc 57
- loe b006
- bne *1
-OK
-TEST 007: test lal, lil
-MAIN 12
- lal -8
-#if WS == PS
- stl -4
-#endif
-#if WS*2 == PS
- sdl -4
-#endif
- loc 117
- stl -8
- lil -4
- loc 117
- bne *1
-OK
-TEST 008: test sil
-MAIN 12
- loc 29
- stl -8
- lal -8
-#if WS == PS
- stl -4
-#endif
-#if WS*2 == PS
- sdl -4
-#endif
- loc 110
- sil -4
- lol -8
- loc 110
- bne *1
-OK
-TEST 009: test lof
-MAIN 20
- lal -16
- loc 120
- stl -12
- lof 4
- loc 120
- bne *1
-OK
-TEST 010: test stf
-MAIN 20
- loc 180
- lal -16
- stf 8
- lol -8
- loc 180
- bne *1
-OK
-TEST 011: test loi WS
-MAIN 20
- loc 140
- stl -12
- lal -12
- loi WS
- loc 140
- bne *1
-OK
-TEST 012: test loi 1, sti 1
-MAIN 20
-#if WS > 1
- loc 519
- lal -10
- sti 1
- lal -10
- loi 1
- loc 7
- bne *1
-OK
-#endif
-TEST 013: test loi 2*WS
-MAIN 20
- loc 77
- stl -12
- loc 119
- stl -12+WS
- lal -12
- loi 2*WS
- loc 77
- bne *1
- loc 119
- bne *1
-OK
-TEST 014: test loi 4*WS
-MAIN 20
- loc 150
- stl -16+(3*WS)
- loc 152
- stl -16+(2*WS)
- loc 154
- stl -16+WS
- loc 156
- stl -16
- lal -16
- loi 4*WS
- loc 156
- bne *1
- loc 154
- bne *1
- loc 152
- bne *1
- loc 150
- bne *1
-OK
-TEST 015: test los WS with 1 
-MAIN 20
- loc 7
- lal -10
- sti 1
- lal -10
- loc 1
- los WS
- loc 7
- bne *1
-OK
-TEST 016: test los WS with 2 
-MAIN 20
-#if WS == 1
- loc 77
- loc 78
- stl -12
- stl -11
- lal -12
- loc 2
- los WS
- loc 78
- bne *1
- loc 77
- bne *1
-#endif
-#if WS > 1
- loc 777
- stl -12
- lal -12
- loc 2
- los WS
- loc 777
- bne *1
-#endif
-OK
-TEST 017: test los WS with 4 
-MAIN 20
-#if WS == 1
- loc 14
- loc 15
- loc 16
- loc 17
- lal -12
- sti 4
- lal -12
- loc 4
- los WS
- loc 17
- bne *1
- loc 16
- bne *1
- loc 15
- bne *1
- loc 14
- bne *1
-#endif
-#if WS == 2
- loc 3001
- loc 3002
- stl -12
- stl -10
- lal -12
- loc 4
- los WS
- loc 3002
- bne *1
- loc 3001
- bne *1
-#endif
-#if WS > 2
- loc 123001
- stl -12
- lal -12
- loc 4
- los WS
- loc 123001
- bne *1
-#endif
-OK
-TEST 018: test ldl
-MAIN 20
- loc 77
- stl -12
- loc 123
- stl -12+WS
- ldl -12
- loc 77
- bne *1
- loc 123
- bne *1
-OK
-TEST 019: test lde
-HOL 20
-MAIN 0
- loc 70
- ste 12
- loc 71
- ste 12+WS
- lde 12
- loc 70
- bne *1
- loc 71
- bne *1
-OK
-TEST 020: test ldf
-MAIN 20
- loc 123
- loc 77
- sdl -4
- lal -9
- ldf 5
- loc 77
- bne *1
- loc 123
- bne *1
-OK
-TEST 021: test ldf
-MAIN 20
- loc 75
- stl -12
- loc 77
- stl -12+WS
- lal -20
- ldf 8
- loc 75
- bne *1
- loc 77
- bne *1
-OK
-TEST 022: test sdl
-MAIN 20
- loc 30
- loc 31
- sdl -12
- lol -12+WS
- loc 30
- bne *1
- lol -12
- loc 31
- bne *1
-OK
-TEST 023: test sde
-HOL 20
-MAIN 0
- loc 40
- loc 41
- sde 16
- loe 16
- loc 41
- bne *1
- loe 16+WS
- loc 40
- bne *1
-OK
-TEST 024: test sdf
-HOL 20
-MAIN 0
- loc 51
- loc 50
- lae 6
- sdf 10
- loe 16
- loc 50
- bne *1
- loc 51
- loe 16+WS
- bne *1
-OK
-TEST 025: test sti 1
-MAIN 20
- loc 4136
- lal -11
- sti 1
- loc 1034
- lal -10
- sti 1
- lal -10
- loi 1
- loc 10
- bne *1
- lal -11
- loi 1
- loc 40
- bne *1
-OK
-TEST 026: test sti 1 and lol
-MAIN 0
- loc 257
- stl -12+WS
- loc 514
- stl -12-WS
- loc 50
- lal -12
- sti 1
-#if WS > 1
- loc -50
- lal -11
- sti 1
-#endif
-#if WS > 2
- loc 49
- lal -10
- sti 1
- loc -49
- lal -9
- sti 1
-#endif
- loc 257
- lol -12+WS
- bne *1
- loc 514
- lol -12-WS
- bne *1
-OK
-TEST 027: test sti 2
-MAIN 20
-#if WS == 1
- ldc 90
-#else
- loc 90
-#endif
- lal -12
- sti 2
-#if WS != 2
- lal -12
- loi 2
-#else
- lol -12
-#endif
-#if WS == 1
- ldc 90
-#else
- loc 90
-#endif
- bne *1
-OK
-TEST 028: test sti 4
-MAIN 20
-#if WS == 1
- loc 100
- loc 101
-#endif
-#if WS <= 2
- loc 102
-#endif
- loc 103
- lal -14
- sti 4
- lol -14
- loc 103
- bne *1
-OK
-TEST 029: test sts WS with 1
-MAIN 20
- loc 57
- lal -13
- sti 1
- loc 123
- lal -11
- sti 1
- loc 20
- lal -12
- loc 1
- sts WS
- lal -12
- loi 1
- loc 20
- bne *1
- lal -11
- loi 1
- loc 123
- bne *1
- lal -13
- loi 1
- loc 57
- bne *1
-OK
-TEST 030: test sts WS with WS
-MAIN 20
- loc 210
- lal -12
- loc WS
- sts WS
- lol -12
- loc 210
- bne *1
-OK
-TEST 031: test sts WS with 4
-MAIN 20
-#if WS == 1
- loc 100
- loc 101
-#endif
-#if WS <= 2
- loc 102
-#endif
- loc 103
- lal -14
- loc 4
- sts WS
- lol -14
- loc 103
- bne *1
-OK
-TEST 032: test adi WS
-MAIN 0
- loc 1
- loc 1
- adi WS
- loc 2
- bne *1
-OK
- loc 5
- loc -6
- adi WS
- loc -1
- bne *1
-OK
-#if WS >= 2
- loc -1007
- loc +999
- adi WS
- loc -8
- bne *1
-OK
- loc -1300
- loc +1405
- adi WS
- loc 105
- bne *1
-OK
- loc -30000
- loc -20
- adi WS
- loc -30020
- bne *1
-OK
-#endif
-#if WS >= 4
- loc -100007
- loc +99999
- adi WS
- loc -8
- bne *1
-OK
- loc -1300
- loc +140567
- adi WS
- loc 139267
- bne *1
-OK
- loc -30000000
- loc -20
- adi WS
- loc -30000020
- bne *1
-OK
-#endif
-TEST 033: test sbi WS
-MAIN 0
- loc 1
- loc 1
- sbi WS
- loc 0
- bne *1
-OK
- loc 5
- loc -6
- sbi WS
- loc +11
- bne *1
-OK
-#if WS >= 2
- loc -1007
- loc +999
- sbi WS
- loc -2006
- bne *1
-OK
- loc -1300
- loc +1405
- sbi WS
- loc -2705
- bne *1
-OK
- loc -30000
- loc -20
- sbi WS
- loc -29980
- bne *1
-OK
-#endif
-#if WS >= 4
- loc -100007
- loc +99999
- sbi WS
- loc -200006
- bne *1
-OK
- loc -1300
- loc +140567
- sbi WS
- loc -141867
- bne *1
-OK
- loc -30000000
- loc -20
- sbi WS
- loc -29999980
- bne *1
-OK
-#endif
-TEST 034: test mli WS
-MAIN 0
- loc 5
- loc 9
- mli WS
- loc 45
- bne *1
-OK
- loc 0
- loc 10
- mli WS
- loc 0
- bne *1
-OK
-#if WS > 1
- loc -99
- loc 7
- mli WS
- loc -693
- bne *1
-OK
- loc -100
- loc -90
- mli WS
- loc 9000
- bne *1
-OK
-#endif
-#if WS > 2
- loc 123456
- loc 200
- mli WS
- loc 24691200
- bne *1
-OK
-#endif
-TEST 035: test dvi WS
-MAIN 0
- loc 15
- loc 5
- dvi WS
- loc 3
- bne *1
-OK
- loc 100
- loc -7
- dvi WS
- loc -14
- bne *1
-OK
- loc -100
- loc 7
- dvi WS
- loc -14
- bne *1
-OK
-#if WS >= 2
- loc -1000
- loc -201
- dvi WS
- loc 4
- bne *1
-OK
-#endif
-#if WS >= 4
- loc 1234567
- loc -100
- dvi WS
- loc -12345
- bne *1
-OK
-#endif
-TEST 036: test rmi WS
-MAIN 0
- loc 100
- loc 7
- rmi WS
- loc 2
- bne *1
-OK
- loc -100
- loc 7
- rmi WS
- loc -2
- bne *1
-OK
- loc 100
- loc -7
- rmi WS
- loc 2
- bne *1
-OK
- loc -100
- loc -7
- rmi WS
- loc -2
- bne *1
-OK
-#if WS >= 2
- loc -1000
- loc -201
- rmi WS
- loc -196
- bne *1
-OK
-#endif
-#if WS >= 4
- loc 1234567
- loc -100
- rmi WS
- loc 67
- bne *1
-OK
-#endif
-TEST 037: test ngi WS
-MAIN 0
- loc 100
- ngi WS
- loc -100
- bne *1
-OK
- loc -100
- ngi WS
- loc 100
- bne *1
-OK
-TEST 038: test sli,slu WS
-MAIN 0
- loc 5
- loc 3
- sli WS
- loc 40
- bne *1
-OK
- loc -2
- loc 4
- sli WS
- loc -32
- bne *1
-OK
- loc 5
- loc 3
- slu WS
- loc 40
- bne *1
-OK
- loc -2
- loc 4
- slu WS
- loc -32
- bne *1
-OK
-TEST 039: test sri,sru WS
-MAIN 0
- loc 64
- loc 5
- sri WS
- loc 2
- bne *1
-OK
- loc -3
- loc 2
- sri WS
- loc -1
- bne *1
-OK
- loc -16
- loc 3
- sri WS
- loc -2
- bne *1
-OK
- loc 64
- loc 5
- sru WS
- loc 2
- bne *1
-OK
- loc -3
- loc 2
- sru WS
-#if WS == 1
- loc 63
-#endif
-#if WS == 2
- loc 16383
-#endif
-#if WS == 4
- loc 1073741823
-#endif
- bne *1
-OK
-TEST 040: test rol WS
-MAIN 0
- loc 1
- loc 3
- rol WS
- loc 8
- bne *1
-OK
-#if WS > 1
- loc 16384
- loc WS * 8 - 1
- rol WS
- loc 8192
- bne *1
-OK
- loc -2
- loc WS * 8 - 1
- rol WS
-#if WS == 2
- loc 32767
-#endif
-#if WS == 4
-  loc 2147483647
-#endif
- bne *1
-OK
- loc -28671
- loc 0
- rol WS
- loc -28671
- bne *1
-OK
-#endif
-TEST 041: test ror WS
-MAIN 0
- loc 4
- loc 5
- ror WS
-#if WS == 1
- loc 32
-#endif
-#if WS == 2
- loc 8192
-#endif
-#if WS == 4
- loc 536870912
-#endif
- bne *1
-OK
-#if WS == 2
- loc 32767
- loc 15
- ror WS
- loc -2
- bne *1
-OK
-#endif
- loc -28
- loc 0
- ror WS
- loc -28
- bne *1
-OK
-TEST 042: test inc
-MAIN 0
- loc 20
- inc
- loc 21
- bne *1
-OK
- loc -50
- inc
- loc -49
- bne *1
-OK
-TEST 043: test dec
-MAIN 0
- loc 66
- dec
- loc 65
- bne *1
-OK
- loc -44
- dec
- loc -45
- bne *1
-OK
-TEST 044: test adp
-MAIN 20
- lal -10
- adp -2
- lal -12
- cmp
- zne *1
-OK
- loc 519
- lal -11
- sti 1
- lal -12
- adp 1
- loi 1
- loc 7
- bne *1
-OK
-TEST 045: test inn WS
-MAIN 0
- loc 8
- loc 3
- inn WS
- loc 1
- bne *1
-OK
- loc 8
- loc 4
- inn WS
- loc 0
- bne *1
-OK
- loc 2
- loc -5
- inn WS
- loc 0
- bne *1
-OK
- loc -5
- loc 3
- inn WS
- loc 1
- bne *1
-OK
-TEST 046: test inn ?
-MAIN 0
- loc 8
- loc 3
- loc WS
- inn ?
- loc 1
- bne *1
-OK
- loc 8
- loc 4
- loc WS
- inn ?
- loc 0
- bne *1
-OK
- loc 2
- loc -5
- loc WS
- inn ?
- loc 0
- bne *1
-OK
- loc -5
- loc 3
- loc WS
- inn ?
- loc 1
- bne *1
-OK
-TEST 047: test set
-MAIN 0
- loc 3
- set WS
- loc 8
- bne *1
-OK
- loc 6
- set 2*WS
- loc 64
- bne *1
- loc 0
- bne *1
-OK
- loc 0
- set 4*WS
- loc 1
- bne *1
- loc 0
- bne *1
- loc 0
- bne *1
- loc 0
- bne *1
-OK
-TEST 048: test set ?
-MAIN 0
- loc 3
- loc WS
- set ?
- loc 8
- bne *1
-OK
- loc 6
- loc 2*WS
- set ?
- loc 64
- bne *1
- loc 0
- bne *1
-OK
- loc 0
- loc 4*WS
- set ?
- loc 1
- bne *1
- loc 0
- bne *1
- loc 0
- bne *1
- loc 0
- bne *1
-OK
-TEST 049: test aar 
-a049
- rom 5,2,4
-b049
- con 5,2,1
-MAIN 20
- lal -12
- loc 5
- lae a049
- aar WS
- lal -12
- cmp
- zne *1
-OK
- lal -11
- loc 7
- lae b049
- aar WS
- lal -9
- cmp
- zne *1
-OK
-TEST 050: test aar ?
-a050
- rom 5,2,4
-b050
- con 5,2,1
-MAIN 20
- lal -12
- loc 5
- lae a050
- loc WS
- aar ?
- lal -12
- cmp
- zne *1
-OK
- lal -11
- loc 7
- lae b050
- loc WS
- aar ?
- lal -9
- cmp
- zne *1
-OK
-TEST 051: test lar
-a051
- rom 5,2,2*WS
-b051
- con 5,2,1
-MAIN 20
- loc 40
- loc 41
- sdl -12+(2*WS)
- lal -12
- loc 6
- lae a051
- lar WS
- loc 41
- bne *1
- loc 40
- bne *1
-OK
- loc 42
- lal -9
- sti 1
- lal -11
- loc 7
- lae b051
- lar WS
- lal -9
- loi 1
- bne *1
-OK
-TEST 052: test lar ?
-a052
- rom 5,2,2*WS
-b052
- con 5,2,1
-MAIN 20
- loc 40
- loc 41
- sdl -12+(2*WS)
- lal -12
- loc 6
- lae a052
- loc WS
- lar ?
- loc 41
- bne *1
- loc 40
- bne *1
-OK
- loc 42
- lal -9
- sti 1
- lal -11
- loc 7
- lae b052
- loc WS
- lar ?
- lal -9
- loi 1
- bne *1
-OK
-TEST 053: test sar
-a053
- rom 5,2,3*WS
-b053
- con 5,2,1
-MAIN 28	: assert WS <= 8
- loc 39
- loc 40
- loc 41
- lal -28
- loc 6
- lae a053
- sar WS
- lal -28+(3*WS)
- loi 3*WS
- loc 41
- bne *1
- loc 40
- bne *1
- loc 39
- bne *1
-OK
- loc -2
- lal -11
- loc 7
- lae b053
- sar WS
- lal -9
- loi 1
- loc 254
- bne *1
-OK
-TEST 054: test sar ?
-a054
- rom 5,2,3*WS
-b054
- con 5,2,1
-MAIN 28
- loc 39
- loc 40
- loc 41
- lal -28
- loc 6
- lae a054
- loc WS
- sar ?
- lal -28+(3*WS)
- loi 3*WS
- loc 41
- bne *1
- loc 40
- bne *1
- loc 39
- bne *1
-OK
- loc -2
- lal -11
- loc 7
- lae b054
- loc WS
- sar ?
- lal -9
- loi 1
- loc 254
- bne *1
-OK
-TEST 055: test tlt
-MAIN 0
- loc 1
- tlt
- loc 0
- bne *1
-OK
- loc 0
- tlt
- loc 0
- bne *1
-OK
- loc -3
- tlt
- loc 1
- bne *1
-OK
-TEST 056: test tle
-MAIN 0
- loc 8
- tle
- loc 0
- bne *1
-OK
- loc 0
- tle
- loc 1
- bne *1
-OK
- loc -19
- tle
- loc 1
- bne *1
-OK
-TEST 057: test teq
-MAIN 0
- loc 17
- teq
- loc 0
- bne *1
-OK
- loc 0
- teq
- loc 1
- bne *1
-OK
- loc -100
- teq
- loc 0
- bne *1
-OK
-TEST 058: test tne
-MAIN 0
- loc 76
- tne
- loc 1
- bne *1
-OK
- loc 0
- tne
- loc 0
- bne *1
-OK
- loc -99
- tne
- loc 1
- bne *1
-OK
-TEST 059: test tge
-MAIN 0
- loc 14
- tge
- loc 1
- bne *1
-OK
- loc 0
- tge
- loc 1
- bne *1
-OK
- loc -76
- tge
- loc 0
- bne *1
-OK
-TEST 060: test tgt
-MAIN 0
- loc 20
- tgt
- loc 1
- bne *1
-OK
- loc 0
- tgt
- loc 0
- bne *1
-OK
- loc -66
- tgt
- loc 0
- bne *1
-OK
-TEST 061: test cmi WS
-MAIN 0
- loc 10
- loc 20
- cmi WS
- tlt
- loc 1
- bne *1
-OK
- loc 20
- loc 10
- cmi WS
- tgt
- loc 1
- bne *1
-OK
- loc 44
- loc 44
- cmi WS
- loc 0
- bne *1
-OK
-TEST 062: test cmp, adp, cmu
-MAIN 20
- lal -5
- lal -2
- cmp
- tlt
- loc 1
- bne *1
-OK
- lal -2
- lal -5
- cmp
- tle
- loc 0
- bne *1
-OK
- lal -2
- lal -2
- cmp
- loc 0
- bne *1
-OK
- lal -5
- adp 3
- lal -2
- cmp
- loc 0
- bne *1
-OK
- lal -5
- adp 4
- lal -2
- cmp
- tge
- loc 1
- bne *1
-OK
- loc 6
- loc 6
- cmu WS
- loc 0
- bne *1
-OK
- loc 17
- loc 27
- cmu WS
- tlt
- loc 1
- bne *1
-OK
- loc 17
- loc 6
- loc 27
- loc 6
- cmu 2*WS
- tlt
- loc 1
- bne *1
-OK
- loc 6
- loc 27
- loc 6
- loc 17
- cmu 2*WS
- tgt
- loc 1
- bne *1
-OK
-TEST 063: test cms
-MAIN 0
- loc 6
- loc -10
- loc -125
- loc 30
- loc 6
- loc -10
- loc -126
- loc 30
- loc 4*WS
- cms
- tne
- loc 1
- bne *1
-OK
-TEST 064: test blt
-MAIN 0
- loc 3
- loc 4
- blt *1064
- bra *1
-1064
- loc 4
- loc 3
- blt *1
- loc -5
- loc -4
- blt *2064
- bra *1
-2064
- loc -4
- loc -5
- blt *1
- loc 4
- loc 4
- blt *1
-OK
-TEST 065: test ble
-MAIN 0
- loc 3
- loc 4
- ble *1065
- bra *1
-1065
- loc 4
- loc 3
- ble *1
- loc -99
- loc -5
- ble *2065
- bra *1
-2065
- loc -99
- loc -99
- ble *3065
- bra *1
-3065
- loc 100
- loc -100
- ble *1
-OK
-TEST 066: test beq
-MAIN 0
- loc 3
- loc 3
- beq *1066
- bra *1
-1066
- loc 3
- loc 4
- beq *1
- loc -18
- loc -17
- beq *1
- loc 0
- loc 0
- beq *2066
- bra *1
-2066
-OK
-TEST 067: test bne
-MAIN 0
- loc 50
- loc 50
- bne *1
- loc 50
- loc 51
- bne *1067
- bra *1
-1067
- loc 0
- loc 0
- bne *1
-OK
-TEST 068: test bge
-MAIN 0
- loc 100
- loc 101
- bge *1
- loc 101
- loc 100
- bge *1068
- bra *1
-1068
- loc -100
- loc -99
- bge *1
- loc -100
- loc 100
- bge *1
- loc 0
- loc 0
- bge *2068
- bra *1
-2068
- loc 50
- loc 50
- bge *3068
- bra *1
-3068
-OK
-TEST 069: test bgt
-MAIN 0
- loc 3
- loc 10
- bgt *1
- loc 10
- loc 3
- bgt *1069
- bra *1
-1069
- loc -100
- loc -50
- bgt *1
- loc -100
- loc 50
- bgt *1
- loc 5
- loc 5
- bgt *1
-OK
-TEST 070: test zlt
-MAIN 0
- loc 4
- zlt *1
- loc -4
- zlt *1070
- bra *1
-1070
- loc 0
- zlt *1
-OK
-TEST 071: test zle
-MAIN 0
- loc 4
- zle *1
- loc -4
- zlt *1071
- bra *1
-1071
- loc 0
- zle *2071
- bra *1
-2071
-OK
-TEST 072: test zeq
-MAIN 0
- loc 4
- zeq *1
- loc -4
- zeq *1
- loc 0
- zeq *1072
- bra *1
-1072
-OK
-TEST 073: test zne
-MAIN 0
- loc 4
- zne *1073
- bra *1
-1073
- loc -4
- zne *2073
- bra *1
-2073
- loc 0
- zne *1
-OK
-TEST 074: test zge
-MAIN 0
- loc 4
- zge *1074
- bra *1
-1074
- loc -4
- zge *1
- loc 0
- zge *2074
- bra *1
-2074
-OK
-TEST 075: test zgt
-MAIN 0
- loc 4
- zgt *1075
- bra *1
-1075
- loc -4
- zgt *1
- loc 0
- zgt *1
-OK
-TEST 076: test asp
-MAIN 12
- loc 104
- loc 4
- loc 5
- loc 6
- asp 2*WS
- stl -4
- loc 104
- bne *1
-OK
-TEST 077: test cal
-HOL 12
-MAIN 0
- cal $p077
- loe 4
- loc 34
- bne *1
-OK
-PROC
- pro $p077,0
- loc 34
- ste 4
- ret 0
- end
-TEST 078: test cai
-HOL 12
-MAIN 0
- lpi $p078
- cai
- loe 4
- loc 34
- bne *1
-OK
-PROC
- pro $p078,0
- loc 34
- ste 4
- ret 0
- end
-TEST 079: test ads WS
-MAIN 20
- lal -6
- loc -2
- ads WS
- lal -8
- cmp
- zne *1
-OK
- lal -6
- loc 2
- ads WS
- lal -4
- cmp
- zne *1
-OK
-; test adp
- lal -5
- adp 1
- lal -4
- cmp
- zne *1
-OK
-TEST 080: test sbs
-HOL 12
-MAIN 20
- lal -4
- lal -6
- sbs WS
- loc 2
- bne *1
-OK
- lae 7
- lae 10
- sbs WS
- loc -3
- bne *1
-OK
-TEST 081: test lor
-#define	LB	0
-#define	SP	1
-MAIN 20
- lor LB
- lxl 0
- cmp
- zne *1
-OK
- loc 31
- lor SP
- loi WS
- bne *1
-OK
- lor SP
- lal -12
- sti PS
- asp -4
- lor SP
- lal -8
- sti PS
- asp 4
- lal -12
- loi PS
- lal -8
- loi PS
- sbs WS
- loc 4
- bne *1
-OK
-TEST 082: test ass WS
-#define	SP	1
-MAIN 20
- loc 104
- loc 50
- loc 60
- loc 2*WS
- ass WS
- loc 104
- bne *1
-OK
- lor SP
- lal -8
- sti PS
- loc -18
- ass WS
- lor SP
- lal -4
- sti PS
- loc 18
- ass WS
- lal -8
- loi PS
- lal -4
- loi PS
- sbs WS
- loc 18
- bne *1
-OK
-TEST 083: test blm
-HOL 40
-MAIN 32
- loc 61
- ste 12
- loc 0
- stl -4
- lae 12
- lal -4
- blm WS
- lol -4
- loc 61
- bne *1
-OK
- loc 44
- loc 43
- loc 42
- loc 41
- lal -20
- sti 4*WS
- lal -20
- lae 8
- blm 4*WS
- loe 8
- loc 41
- bne *1
- loe 8+WS
- loc 42
- bne *1
- loe 8+(2*WS)
- loc 43
- bne *1
- loe 8+(3*WS)
- loc 44
- bne *1
-OK
-TEST 084: test bls WS
-HOL 40
-MAIN 32
- loc 55
- stl -8+WS
- loc 56
- stl -8
- lal -8
- lae 20
- loc 2*WS
- bls WS
- loe 20
- loc 56
- bne *1
- loe 20+WS
- loc 55
- bne *1
-OK
-TEST 085: test dup
-MAIN 0
- loc 199
- dup WS
- bne *1
-OK
- loc 130
- loc 150
- dup 2*WS
- loc 150
- bne *1
- loc 130
- bne *1
- loc 150
- bne *1
- loc 130
- bne *1
-OK
-; test dus WS
- loc 400
- loc 399
- loc 2*WS
- dus WS
- loc 399
- bne *1
- loc 400
- bne *1
- loc 399
- bne *1
- loc 400
- bne *1
-OK
-TEST 087: test rck
-a087
- con 10,14
-MAIN 12
- loc 10
- lae a087
- rck WS
- inc
- lae a087
- rck WS
- inc
- lae a087
- rck WS
- inc
- lae a087
- rck WS
- inc
- lae a087
- rck WS
- stl -4
-OK
-TEST 088: test csa
-MAIN 20
-a088
- con *1088,4,2,*3088,*2088,*4088
- zrl -8
- loc 4
-5088
- inc
- dup WS
- lae a088
- csa WS
- bra *1
-3088
- bra *1
-2088
- lol -8
- loc 3
- adi WS
- stl -8
- bra *5088
-1088
- inl -8
- bra *6088
-4088
- lol -8
- loc 2
- adi WS
- stl -8
- bra *5088
-6088
- loc 7
- bne *1
-OK
- lol -8
- loc 6
- bne *1
-OK
-TEST 089: test csb
-MAIN 20
-b089
- rom *1089,3,-1,*3089,0,*2089,1,*4089
- loc -1
- zrl -12
-5089
- inc
- dup WS
- lae b089
- csb WS
- bra *1
-3089
- bra *1
-2089
- lol -12
- loc 3
- adi WS
- stl -12
- bra *5089
-1089
- inl -12
- bra *6089
-4089
- lol -12
- loc 2
- adi WS
- stl -12
- bra *5089
-6089
- loc 2
- bne *1
-OK
- lol -12
- loc 6
- bne *1
-OK
-TEST 090: now test loi again, because it is so tricky
-MAIN 20
- loc 256
- lal -3
- sti 1
- loc 1
- lal -4
- sti 1
- loc 517
- lal -5
- sti 1
- loc 2
- lal -6
- sti 1
- loc 1030
- lal -8
- sti 2
- loc 4
- lal -9
- sti 1
- lal -3
- loi 1
- loc 0 
- bne *1
-OK
- lal -3
- adp -1
- loi 1
- loc 1
- bne *1
-OK
- lal -3
- adp -2
- loi 1
- loc 5
- bne *1
-OK
- lal -3
- adp -3
- loi 1
- loc 2
- bne *1
-OK
- lal -4
- adp -4
- loi 2
- loc 1030
- bne *1
-OK
- lal -6
- adp -3
- loi 1
- loc 4
- bne *1
-OK
-TEST 091: now test sti 1 again
-MAIN 12
- loc 3
- loc 2
- loc 1
- loc 7
- loc 8
- loc 10
- lal -4
- sti 1
- lal -4
- adp -1
- sti 1
- lal -4
- adp -2
- sti 1
- lal -4
- adp -3
- sti 1
- lal -4
- adp -4
- sti 1
- lal -4
- adp -5
- sti 1
- lal -4
- loi 1
- loc 10
- bne *1
-OK
- lal -6
- loi 1
- loc 7
- bne *1
-OK
- lal -8
- loi 1
- loc 2
- bne *1
-OK
-TEST 092: test ldc and cii
-MAIN 0
-#ifdef W2S
- ldc 0
- bne *1
-OK
- ldc 1
- loc 1
- loc WS
- loc W2S
- cii
- cmi W2S
- zne *1
-OK
- ldc -1
- loc -1
- loc WS
- loc W2S
- cii
- cmi W2S
- zne *1
-OK
- loc -1
- ldc -1
- loc W2S
- loc WS
- cii
- cmi WS
- zne *1
-OK
-#if WS == 1
- ldc -128
- loc -128
-#endif
-#if WS == 2
- ldc -32768
- loc -32768
-#endif
-#if WS == 4
- ldc -2147483648
- loc -2147483648
-#endif
- loc WS
- loc W2S
- cii
- cmi W2S
- zne *1
-OK
- ldc -1
- loc -1
- bne *1
-OK
- loc -1
- bne *1
-OK
- ldc 1
- zeq *1092
-; low order part on top of stack
- loc 0
- bne *1
-OK
- bra *2092
-; high order part on top of stack
-1092
- loc 1
- bne *1
-OK
-2092
-#endif
-TEST 093: test cii
-MAIN 0
- loc 123
- dup WS
- loc WS
- dup WS
- cii
- bne *1
-OK
-#ifdef W2S
- loc 0
- loc WS
- loc W2S
- cii
- loc 0
- bne *1
- loc 0
- bne *1
-OK
-; dynamically determine format of doubles
- loc 1
- loc WS
- loc W2S
- cii
- zeq *1093
-; low order part on top of stack
- loc 0
- bne *1
-OK
- loc -3
- loc WS
- loc W2S
- cii
- loc -3
- bne *1
- loc -1
- bne *1
-OK
- bra *2093
-; high order part on top of stack
-1093
- loc 1
- bne *1
-OK
- loc -3
- loc WS
- loc W2S
- cii
- loc -1
- bne *1
- loc -3
- bne *1
-OK
-2093
-#endif
-TEST 094: test adi W2S
-MAIN 0
-#ifdef W2S
- ldc 1
- ldc 1
- adi W2S
- ldc 2
- cmi W2S
- zne *1
-OK
- ldc 5
- ldc -6
- adi W2S
- ldc -1
- cmi W2S
- zne *1
-OK
- ldc -1007
- ldc +999
- adi W2S
- ldc -8
- cmi W2S
- zne *1
-OK
- ldc -1300
- ldc +1405
- adi W2S
- ldc 105
- cmi W2S
- zne *1
-OK
- ldc -30000
- ldc -20
- adi W2S
- ldc -30020
- cmi W2S
- zne *1
-OK
-#if WS >= 2
- ldc -100007
- ldc +99999
- adi W2S
- ldc -8
- cmi W2S
- zne *1
-OK
- ldc -1300
- ldc +140567
- adi W2S
- ldc 139267
- cmi W2S
- zne *1
-OK
- ldc -30000000
- ldc -20
- adi W2S
- ldc -30000020
- cmi W2S
- zne *1
-OK
-#endif
-#endif
-TEST 095: test sbi W2S
-MAIN 0
-#ifdef W2S
- ldc 1
- ldc 1
- sbi W2S
- ldc 0
- cmi W2S
- zne *1
-OK
- ldc 5
- ldc -6
- sbi W2S
- ldc +11
- cmi W2S
- zne *1
-OK
- ldc -1007
- ldc +999
- sbi W2S
- ldc -2006
- cmi W2S
- zne *1
-OK
- ldc -1300
- ldc +1405
- sbi W2S
- ldc -2705
- cmi W2S
- zne *1
-OK
- ldc -30000
- ldc -20
- sbi W2S
- ldc -29980
- cmi W2S
- zne *1
-OK
-#if WS >= 2
- ldc -100007
- ldc +99999
- sbi W2S
- ldc -200006
- cmi W2S
- zne *1
-OK
- ldc -1300
- ldc +140567
- sbi W2S
- ldc -141867
- cmi W2S
- zne *1
-OK
- ldc -30000000
- ldc -20
- sbi W2S
- ldc -29999980
- cmi W2S
- zne *1
-OK
-#endif
-#endif
-TEST 096: test mli W2S
-MAIN 0
-#ifdef W2S
- ldc 5
- ldc 9
- mli W2S
- ldc 45
- cmi W2S
- zne *1
-OK
- ldc 0
- ldc 10
- mli W2S
- ldc 0
- cmi W2S
- zne *1
-OK
- ldc -99
- ldc 7
- mli W2S
- ldc -693
- cmi W2S
- zne *1
-OK
- ldc -100
- ldc -90
- mli W2S
- ldc 9000
- cmi W2S
- zne *1
-OK
-#if WS >= 2
- ldc 123456
- ldc 200
- mli W2S
- ldc 24691200
- cmi W2S
- zne *1
-OK
-#endif
-#endif
-TEST 097: test dvi W2S
-MAIN 0
-#ifdef W2S
- ldc 15
- ldc 5
- dvi W2S
- ldc 3
- cmi W2S
- zne *1
-OK
- ldc 100
- ldc -7
- dvi W2S
- ldc -14
- cmi W2S
- zne *1
-OK
- ldc -100
- ldc 7
- dvi W2S
- ldc -14
- cmi W2S
- zne *1
-OK
- ldc -1000
- ldc -201
- dvi W2S
- ldc 4
- cmi W2S
- zne *1
-OK
-#if WS >= 2
- ldc 1234567
- ldc -100
- dvi W2S
- ldc -12345
- cmi W2S
- zne *1
-OK
-#endif
-#endif
-TEST 098: test rmi W2S
-MAIN 0
-#ifdef W2S
- ldc 100
- ldc 7
- rmi W2S
- ldc 2
- cmi W2S
- zne *1
-OK
- ldc -100
- ldc 7
- rmi W2S
- ldc -2
- cmi W2S
- zne *1
-OK
- ldc 100
- ldc -7
- rmi W2S
- ldc 2
- cmi W2S
- zne *1
-OK
- ldc -100
- ldc -7
- rmi W2S
- ldc -2
- cmi W2S
- zne *1
-OK
- ldc -1000
- ldc -201
- rmi W2S
- ldc -196
- cmi W2S
- zne *1
-OK
-#if WS >= 4
- ldc 1234567
- ldc -100
- rmi W2S
- ldc 67
- cmi W2S
- zne *1
-OK
-#endif
-#endif
-TEST 099: test and
-MAIN 0
- loc 68
- loc 65
- and WS
- loc 64
- bne *1
-OK
- loc 17
- loc 34
- loc 3
- loc 36
- and 2*WS
- loc 32
- bne *1
- loc 1
- bne *1
-OK
- loc 17
- loc 34
- loc 68
- loc -120
- loc 1
- loc 37
- loc 12
- loc -127
- and 4*WS
- loc -128
- bne *1
- loc 4
- bne *1
- loc 32
- bne *1
- loc 1
- bne *1
-OK
-TEST 100: test ior
-MAIN 0
- loc 68
- loc 65
- ior WS
- loc 69
- bne *1
-OK
- loc 17
- loc 34
- loc 3
- loc 36
- ior 2*WS
- loc 38
- bne *1
- loc 19
- bne *1
-OK
- loc 17
- loc 34
- loc 68
- loc -120
- loc 1
- loc 37
- loc 12
- loc -127
- ior 4*WS
- loc -119
- bne *1
- loc 76
- bne *1
- loc 39
- bne *1
- loc 17
- bne *1
-OK
-TEST 101: test xor
-MAIN 0
- loc 68
- loc 65
- xor WS
- loc 5
- bne *1
-OK
- loc 17
- loc 34
- loc 3
- loc 36
- xor 2*WS
- loc 6
- bne *1
- loc 18
- bne *1
-OK
- loc 17
- loc 34
- loc 68
- loc -120
- loc 1
- loc 37
- loc 12
- loc -127
- xor 4*WS
- loc 9
- bne *1
- loc 72
- bne *1
- loc 7
- bne *1
- loc 16
- bne *1
-OK
-TEST 102: test com
-MAIN 0
- loc 68
- com WS
- loc -69
- bne *1
-OK
- loc 17
- loc 34
- com 2*WS
- loc -35
- bne *1
- loc -18
- bne *1
-OK
- loc 17
- loc 34
- loc 68
- loc -120
- com 4*WS
- loc 119
- bne *1
- loc -69
- bne *1
- loc -35
- bne *1
- loc -18
- bne *1
-OK
-TEST 103: test sli,slu W2S
-MAIN 0
-#ifdef W2S
- ldc 5
- loc 3
- sli W2S
- ldc 40
- cmi W2S
- zne *1
-OK
- ldc -2
- loc 4
- sli W2S
- ldc -32
- cmi W2S
- zne *1
-OK
- ldc 5
- loc 3
- slu W2S
- ldc 40
- cmi W2S
- zne *1
-OK
- ldc -2
- loc 4
- slu W2S
- ldc -32
- cmi W2S
- zne *1
-OK
-#endif
-TEST 104: test sri,sru W2S
-MAIN 0
-#ifdef W2S
- ldc 64
- loc 5
- sri W2S
- ldc 2
- cmi W2S
- zne *1
-OK
- ldc -3
- loc 2
- sri W2S
- ldc -1
- cmi W2S
- zne *1
-OK
- ldc -16
- loc 3
- sri W2S
- ldc -2
- cmi W2S
- zne *1
-OK
- ldc 64
- loc 5
- sru W2S
- ldc 2
- cmi W2S
- zne *1
-OK
- ldc -3
- loc 2
- sru W2S
-#if W2S == 2
- ldc 16383
-#endif
-#if W2S == 4
- ldc 1073741823
-#endif
- cmi W2S
- zne *1
-OK
-#endif
-TEST 105: common test of double arithmetic
-MAIN 0
-#ifdef W2S
- ldc 1000
- ldc 10
- mli W2S
- ldc 4
- dvi W2S
- ldc 1500
- adi W2S
- ldc 2856
- sbi W2S
- ldc 100
- rmi W2S
- ldc 44
- cmi W2S
- zne *1
-OK
-#endif
-TEST 106: test cmi W2S
-MAIN 0
-#if W2S==2
- ldc 64
- ldc 4
- mli W2S
- ldc 63
- ldc 4
- mli W2S
- cmi W2S
- tge
- loc 1
- bne *1
-OK
-#endif
-#if W2S==4
- ldc 16384
- ldc 4
- mli W2S
- ldc 16383
- ldc 4
- mli W2S
- cmi W2S
- tge
- loc 1
- bne *1
-OK
-#endif
-TEST 107: test cii W2S -> WS
-MAIN 0
-#ifdef W2S
- ldc 100
- loc W2S
- loc WS
- cii
- loc 100
- bne *1
-OK
- ldc 5000
- ldc -6
- mli W2S
- ldc 1000
- dvi W2S
- loc W2S
- loc WS
- cii
- loc -30
- bne *1
-OK
-#endif
-TEST 108: test cif, cfi, adf FS
-MAIN 0
-#ifdef FS
- loc 100
- loc WS
- loc FS
- cif
- loc 44
- loc WS
- loc FS
- cif
- adf FS
- loc FS
- loc WS
- cfi
- loc 144
- bne *1
-OK
- loc 65
- loc WS
- loc FS
- cif
- loc -65
- loc WS
- loc FS
- cif
- adf FS
- loc FS
- loc WS
- cfi
- loc 0
- bne *1
-OK
-#endif
-TEST 109: test cdf, cfd
-MAIN 0
-#ifdef FS
-#ifdef W2S
- loc 55
- loc WS
- loc W2S
- cii
- loc W2S
- loc FS
- cif
- loc 55
- loc WS
- loc FS
- cif
- cmf FS
- zne *1
-OK
- loc 24
- loc WS
- loc FS
- cif
- loc FS
- loc W2S
- cfi
- loc W2S
- loc WS
- cii
- loc 24
- bne *1
-OK
- loc 57
- loc WS
- loc FS
- cif
- loc FS
- loc W2S
- cfi
- loc W2S
- loc WS
- cii
- loc 57
- bne *1
-OK
- loc 40
- loc WS
- loc W2S
- cii
- loc W2S
- loc FS
- cif
- loc FS
- loc WS
- cfi
- loc 40
- bne *1
-OK
-#endif
-#endif
-TEST 110: test sbf FS
-MAIN 0
-#ifdef FS
- loc 100
- loc WS
- loc FS
- cif
- loc 50
- loc WS
- loc FS
- cif
- sbf FS
- loc FS
- loc WS
- cfi
- loc 50
- bne *1
-OK
- loc 32
- loc WS
- loc FS
- cif
- loc 101
- loc WS
- loc FS
- cif
- sbf FS
- loc -69
- loc WS
- loc FS
- cif
- cmf FS
- zne *1
-OK
-#endif
-TEST 111: test mlf FS
-MAIN 0
-#ifdef FS
- loc 4
- loc WS
- loc FS
- cif
- loc 20
- loc WS
- loc FS
- cif
- mlf FS
- loc FS
- loc WS
- cfi
- loc 80
- bne *1
-OK
- loc -12
- loc WS
- loc FS
- cif
- loc -9
- loc WS
- loc FS
- cif
- mlf FS
- loc FS
- loc WS
- cfi
- loc 108
- bne *1
-OK
-#endif
-TEST 112: test dvf FS
-MAIN 0
-#ifdef FS
- loc 45
- loc WS
- loc FS
- cif
- loc 9
- loc WS
- loc FS
- cif
- dvf FS
- loc 5
- loc WS
- loc FS
- cif
- cmf FS
- zne *1
-OK
- loc -60
- loc WS
- loc FS
- cif
- loc 7
- loc WS
- loc FS
- cif
- dvf FS
- loc FS
- loc WS
- cfi
- loc -8
- bne *1
-OK
-#endif
-TEST 113: test fractions using FS floating arithmetic
-MAIN 0
-#ifdef FS
- loc 7
- loc WS
- loc FS
- cif
- loc 2
- loc WS
- loc FS
- cif
- dvf FS
- loc FS
- loc WS
- cfi
- loc 3
- bne *1
-OK
- loc -7
- loc WS
- loc FS
- cif
- loc 2
- loc WS
- loc FS
- cif
- dvf FS
- loc FS
- loc WS
- cfi
- loc -3
- bne *1
-OK
- loc 11
- loc WS
- loc FS
- cif
- loc 2
- loc WS
- loc FS
- cif
- dvf FS
- loc 5
- loc WS
- loc FS
- cif
- mlf FS
- loc 4
- loc WS
- loc FS
- cif
- mlf FS
- loc 110
- loc WS
- loc FS
- cif
- cmf FS
- zne *1
-OK
-#endif
-TEST 114: test cif, cfi, adf F2S
-MAIN 0
-#ifdef F2S
- loc 10
- loc WS
- loc F2S
- cif
- loc 44
- loc WS
- loc F2S
- cif
- adf F2S
- loc F2S
- loc WS
- cfi
- loc 54
- bne *1
-OK
- loc 65
- loc WS
- loc F2S
- cif
- loc -65
- loc WS
- loc F2S
- cif
- adf F2S
- loc F2S
- loc WS
- cfi
- loc 0
- bne *1
-OK
-#endif
-TEST 115: test cif, cfi W2S F2S
-MAIN 0
-#ifdef F2S
-#ifdef W2S
- loc 55
- loc WS
- loc W2S
- cii
- loc W2S
- loc F2S
- cif
- loc 55
- loc WS
- loc F2S
- cif
- cmf F2S
- zne *1
-OK
- loc 24
- loc WS
- loc F2S
- cif
- loc F2S
- loc W2S
- cfi
- loc W2S
- loc WS
- cii
- loc 24
- bne *1
-OK
- loc 57
- loc WS
- loc F2S
- cif
- loc F2S
- loc W2S
- cfi
- loc W2S
- loc WS
- cii
- loc 57
- bne *1
-OK
- loc 41
- loc WS
- loc W2S
- cii
- loc W2S
- loc F2S
- cif
- loc F2S
- loc WS
- cfi
- loc 41
- bne *1
-OK
-#endif
-#endif
-TEST 116: test sbf F2S
-MAIN 0
-#ifdef F2S
- loc 100
- loc WS
- loc F2S
- cif
- loc 50
- loc WS
- loc F2S
- cif
- sbf F2S
- loc F2S
- loc WS
- cfi
- loc 50
- bne *1
-OK
- loc 32
- loc WS
- loc F2S
- cif
- loc 101
- loc WS
- loc F2S
- cif
- sbf F2S
- loc -69
- loc WS
- loc F2S
- cif
- cmf F2S
- zne *1
-OK
-#endif
-TEST 117: test fmu F2S
-MAIN 0
-#ifdef F2S
- loc 4
- loc WS
- loc F2S
- cif
- loc 20
- loc WS
- loc F2S
- cif
- mlf F2S
- loc F2S
- loc WS
- cfi
- loc 80
- bne *1
-OK
- loc -20
- loc WS
- loc F2S
- cif
- loc -6
- loc WS
- loc F2S
- cif
- mlf F2S
- loc F2S
- loc WS
- cfi
- loc 120
- bne *1
-OK
-#endif
-TEST 118: test dvf F2S
-MAIN 0
-#ifdef F2S
- loc 45
- loc WS
- loc F2S
- cif
- loc 9
- loc WS
- loc F2S
- cif
- dvf F2S
- loc 5
- loc WS
- loc F2S
- cif
- cmf F2S
- zne *1
-OK
- loc -60
- loc WS
- loc F2S
- cif
- loc 7
- loc WS
- loc F2S
- cif
- dvf F2S
- loc F2S
- loc WS
- cfi
- loc -8
- bne *1
-OK
-#endif
-TEST 119: test fractions using F2S floating arithmetic
-MAIN 0
-#ifdef F2S
- loc 7
- loc WS
- loc F2S
- cif
- loc 2
- loc WS
- loc F2S
- cif
- dvf F2S
- loc F2S
- loc WS
- cfi
- loc 3
- bne *1
-OK
- loc -7
- loc WS
- loc F2S
- cif
- loc 2
- loc WS
- loc F2S
- cif
- dvf F2S
- loc F2S
- loc WS
- cfi
- loc -3
- bne *1
-OK
- loc 11
- loc WS
- loc F2S
- cif
- loc 2
- loc WS
- loc F2S
- cif
- dvf F2S
- loc 5
- loc WS
- loc F2S
- cif
- mlf F2S
- loc 4
- loc WS
- loc F2S
- cif
- mlf F2S
- loc 110
- loc WS
- loc F2S
- cif
- cmf F2S
- zne *1
-OK
-#endif
-TEST 120: test cal
-HOL 12
-MAIN 0
- loc 0
- ste 4
- cal $p120
- loe 4
- loc 34
- bne *1
-OK
-PROC
- pro $p120,0
- loc 34
- ste 4
- ret 0
- end
-TEST 121: test cal
-MAIN 0
- cal $p121
- lfr WS
- loc 7
- bne *1
-OK
-PROC
- pro $p121,0
- loc 7
- ret WS
- end
-TEST 122: test cal
-MAIN 0
- loc 7
- cal $p122
- asp WS
- lfr WS
- loc 7
- bne *1
-OK
-PROC
- pro $p122,0
- lol 0
- ret WS
- end
-TEST 123: test cal
-MAIN 4
- loc 7
- stl -4
- lor 0
- cal $p123
- asp PS
- lfr WS
- loc 7
- bne *1
-OK
- lxl 0
- cal $p123
- asp PS
- lfr WS
- loc 7
- bne *1
-OK
-PROC
- pro $p123,0
- lxl 1
- lof -4
- ret WS
- end
-TEST 124: test cal
-MAIN 0
- loc 7
- cal $p124
- asp WS
-PROC
- pro $p124,0
- lol 0
- loc 7
- bne *1
-OK
- ret 0
-ERRLAB
- end
-TEST 125: test cal
-MAIN 4
- loc 10
- stl -WS
- loc 90
- lxl 0
- cal $p1125
- asp PS+WS
-OK
-PROC
- pro $p1125,WS
- lol PS
- loc 90
- bne *1
-OK
- loc 11
- stl -WS
- loc 21
- loc 91
- lxl 0
- cal $p2125
- asp PS+WS
- lfr WS
-OK
- loc 82
- bne *1
-OK
- loc 21
- bne *1
-OK
- ret 0
-ERRLAB
- end
- pro $p2125,0
- lol PS
- loc 91
- bne *1
-OK
- loc 12
- loc 92
- lxl 0
- cal $p3125
- asp PS+WS
- lfr WS+WS
-OK
- loc 86
- bne *1
- loc 83
- bne *1
-OK
- loc 12
- bne *1
-OK
- lal PS
- loi WS
- loc 91
- bne *1
-OK
- loc 82
- ret WS
-ERRLAB
- end
- pro $p3125,WS
- lol PS
- loc 92
- bne *1
-OK
- loc 13
- stl -WS
- lxa 0
- adp PS
- loi WS
- loc 92
- bne *1
-OK
- lxa 1
- adp PS
- loi WS
- loc 91
- bne *1
-OK
- lxa 2
- adp PS
- loi WS
- loc 90
- bne *1
-OK
- lxl 2
- lof -WS
- loc 11
- bne *1
-OK
- lxl 3
- adp -WS
- loi WS
- loc 10
- bne *1
-OK
- loc 83
- lxl 1
- cal $p4125
- asp PS
- lxl 2
- cal $p5125
- asp PS
- lxl 3
- cal $p6125
- asp PS
- lfr WS
- ret WS+WS
-ERRLAB
- end
- pro $p4125,0
- lxa 1
- adp PS
- loi WS
- loc 91
- bne *1
-OK
- ret 0
-ERRLAB
- end
- pro $p5125,0
- lxa 1
- adp PS
- loi WS
- loc 90
- bne *1
-OK
- ret 0
-ERRLAB
- end
- pro $p6125,0
- lxl 1
- adp -WS
- loi WS
- loc 10
- bne *1
-OK
- loc 86
- ret WS
-ERRLAB
- end
-TEST 126: test bra
-MAIN 0
- bra *0126
- bra *1
-9126
- bra *8126
-0126
- bra *6126
- bra *1
-1126
- bra *5126
- bra *1
-2126
- bra *4126
- bra *1
-3126
- bra *7126
- bra *1
-4126
- bra *3126
- bra *1
-5126
- bra *2126
- bra *1
-6126
- bra *1126
- bra *1
-7126
- bra *9126
- bra *1
-8126
-OK
-TEST 127: test ret and lfr
-a127
- bss 4,0,0
-MAIN 0
-; return nothing
- loc 123
- cal $retw0
- loc 123
- bne *1
-OK
-; return single word
- cal $retw1
- lfr WS
- loc 45
- bne *1
-OK
-; return single pointer
- cal $retp1
- lfr PS
- lae a127
- cmp
- zne *1
-OK
-; return procedure instance identifier (two pointers)
-; this value may not be disturbed by ASP
- lxl 0
- cal $retp2
- asp PS
- lfr 2*PS
- lpi $retp2
- cmp
- zne *1
- lxl 0
- cmp
- zne *1
-OK
-; same as above but with ASS instead of ASP
- lxl 0
- cal $retp2
- loc PS
- ass WS
- lfr 2*PS
- lpi $retp2
- cmp
- zne *1
- lxl 0
- cmp
- zne *1
-OK
-PROC
- pro $retw0,0
- ret 0
- end
- pro $retw1,0
- loc 45
- ret WS
- end
- pro $retp1,0
- lae a127
- ret PS
- end
- pro $retp2,0
- lxl 1
- lpi $retp2
- ret 2*PS
- end

+ 0 - 26
etc/Makefile

@@ -1,26 +0,0 @@
-d=..
-h=$d/h
-c=$d/util/data
-
-FILES= \
-$h/em_spec.h \
-$h/em_pseu.h \
-$h/em_mnem.h \
-$c/em_flag.c \
-$c/em_pseu.c \
-$c/em_mnem.c
-
-$(FILES):       em_table
-		new_table $h $c
-
-install:	$(FILES)
-
-opr:
-		make pr ^ opr
-pr:
-		@pr Makefile em_table new_table pop_push traps
-
-clean:
-		-rm -f *.old
-
-cmp :           # do nothing

+ 0 - 175
etc/em_table

@@ -1,175 +0,0 @@
-magic	173
-fmnem	1
-nmnem	149
-fpseu	150
-npseu	30
-filb0	180
-nilb0	60
-fcst0	0
-zcst0	120
-ncst0	240
-fspec	240
-nspec	16
-ilb1	240
-ilb2	241
-dlb1	242
-dlb2	243
-dnam	244
-cst2	245
-cst4	246
-cst8	247
-doff	248
-pnam	249
-scon	250
-icon	251
-ucon	252
-fcon	253
-cend	255
-
-bss	0
-con	1
-end	2
-exa	3
-exc	4
-exp	5
-hol	6
-ina	7
-inp	8
-mes	9
-pro	10
-rom	11
-
-aar	w-	-p-a-p+p
-adf	w-	-a-a+a
-adi	w-	-a-a+a
-adp	f-	-p+p
-ads	w-	-a-p+p
-adu	w-	-a-a+a
-and	w-	-a-a+a
-asp	f-	-a
-ass	w-	-a-x
-beq	bc	-w-w
-bge	bc	-w-w
-bgt	bc	-w-w
-ble	bc	-w-w
-blm	z-	-p-p
-bls	w-	-a-p-p
-blt	bc	-w-w
-bne	bc	-w-w
-bra	bt	0
-cai	-p	-p
-cal	pp	0
-cff	--	-w-w-y+x
-cfi	--	-w-w-y+x
-cfu	--	-w-w-y+x
-cif	--	-w-w-y+x
-cii	--	-w-w-y+x
-ciu	--	-w-w-y+x
-cmf	w-	-a-a+w
-cmi	w-	-a-a+w
-cmp	--	-p-p+w
-cms	w-	-a-a+w
-cmu	w-	-a-a+w
-com	w-	-a-a+a
-csa	wt	-p-a
-csb	wt	-p-a
-cuf	--	-w-w-y+x
-cui	--	-w-w-y+x
-cuu	--	-w-w-y+x
-dch	--	-p+p
-dec	--	-w+w
-dee	g-	0
-del	l-	0
-dup	s-	-a+a+a
-dus	w-	-a-x+x+x
-dvf	w-	-a-a+a
-dvi	w-	-a-a+a
-dvu	w-	-a-a+a
-exg	w-	-a-a+a+a
-fef	w-	-a+a+w
-fif	w-	-a-a+a+a
-fil	g-	0
-gto	gt	-p-?
-inc	--	-w+w
-ine	g-	0
-inl	l-	0
-inn	w-	-w-a+w
-ior	w-	-a-a+a
-lae	g-	+p
-lal	l-	+p
-lar	w-	-p-a-p+?
-ldc	d-	+d
-lde	g-	+d
-ldf	f-	-p+d
-ldl	l-	+d
-lfr	s-	+a
-lil	l-	+w
-lim	--	+w
-lin	n-	0
-lni	--	0
-loc	c-	+w
-loe	g-	+w
-lof	f-	-p+w
-loi	o-	-p+a
-lol	l-	+w
-lor	r-	+p
-los	w-	-a-p+x
-lpb	--	-p+p
-lpi	p-	+p
-lxa	n-	+p
-lxl	n-	+p
-mlf	w-	-a-a+a
-mli	w-	-a-a+a
-mlu	w-	-a-a+a
-mon	--	-?+?
-ngf	w-	-a+a
-ngi	w-	-a+a
-nop	--	0
-rck	w-	-p-a+a
-ret	zt	-a-?
-rmi	w-	-a-a+a
-rmu	w-	-a-a+a
-rol	w-	-w-a+a
-ror	w-	-w-a+a
-rtt	-t	-?
-sar	w-	-p-a-p-?
-sbf	w-	-a-a+a
-sbi	w-	-a-a+a
-sbs	w-	-p-p+a
-sbu	w-	-a-a+a
-sde	g-	-d
-sdf	f-	-p-d
-sdl	l-	-d
-set	w-	-w+a
-sig	--	-p-p+p+p
-sil	l-	-w
-sim	--	-w
-sli	w-	-w-a+a
-slu	w-	-w-a+a
-sri	w-	-w-a+a
-sru	w-	-w-a+a
-ste	g-	-w
-stf	f-	-p-w
-sti	o-	-p-a
-stl	l-	-w
-str	r-	-p
-sts	w-	-a-p-x
-teq	--	-w+w
-tge	--	-w+w
-tgt	--	-w+w
-tle	--	-w+w
-tlt	--	-w+w
-tne	--	-w+w
-trp	-p	-w+?
-xor	w-	-a-a+a
-zeq	bc	-w
-zer	w-	+a
-zge	bc	-w
-zgt	bc	-w
-zle	bc	-w
-zlt	bc	-w
-zne	bc	-w
-zre	g-	0
-zrf	w-	+a
-zrl	l-	0
-

+ 0 - 352
etc/ip_spec.t

@@ -1,352 +0,0 @@
-aar mwPo 1 34
-adf sP 1 35
-adi mwPo 2 36
-adp 2 38
-adp mPo 2 39
-adp sP 1 41
-adp sN 1 42
-ads mwPo 1 43
-and mwPo 1 44
-asp mwPo 5 45
-asp swP 1 50
-beq 2 51
-beq sP 1 52
-bge sP 1 53
-bgt sP 1 54
-ble sP 1 55
-blm sP 1 56
-blt sP 1 57
-bne sP 1 58
-bra 2 59
-bra sN 2 60
-bra sP 2 62
-cal mPo 28 64
-cal sP 1 92
-cff - 93
-cif - 94
-cii - 95
-cmf sP 1 96
-cmi mwPo 2 97
-cmp - 99
-cms sP 1 100
-csa mwPo 1 101
-csb mwPo 1 102
-dec - 103
-dee sw 1 104
-del swN 1 105
-dup mwPo 1 106
-dvf sP 1 107
-dvi mwPo 1 108
-fil 2 109
-inc - 110
-ine w2 111
-ine sw 1 112
-inl mwN 3 113
-inl swN 1 116
-inn sP 1 117
-ior mwPo 1 118
-ior sP 1 119
-lae 2 120
-lae sw 7 121
-lal P2 128
-lal N2 129
-lal mP 1 130
-lal mN 1 131
-lal swP 1 132
-lal swN 2 133
-lar mwPo 1 135
-ldc mP 1 136
-lde w2 137
-lde sw 1 138
-ldl mP 1 139
-ldl swN 1 140
-lfr mwPo 2 141
-lfr sP 1 143
-lil swN 1 144
-lil swP 1 145
-lil mwP 2 146
-lin 2 148
-lin sP 1 149
-lni - 150
-loc 2 151
-loc mP 34 0
-loc mN 1 152
-loc sP 1 153
-loc sN 1 154
-loe w2 155
-loe sw 5 156
-lof 2 161
-lof mwPo 4 162
-lof sP 1 166
-loi 2 167
-loi mPo 1 168
-loi mwPo 4 169
-loi sP 1 173
-lol wP2 174
-lol wN2 175
-lol mwP 4 176
-lol mwN 8 180
-lol swP 1 188
-lol swN 1 189
-lxa mPo 1 190
-lxl mPo 2 191
-mlf sP 1 193
-mli mwPo 2 194
-rck mwPo 1 196
-ret mwP 2 197
-ret sP 1 199
-rmi mwPo 1 200
-sar mwPo 1 201
-sbf sP 1 202
-sbi mwPo 2 203
-sdl swN 1 205
-set sP 1 206
-sil swN 1 207
-sil swP 1 208
-sli mwPo 1 209
-ste w2 210
-ste sw 3 211
-stf 2 214
-stf mwPo 2 215
-stf sP 1 217
-sti mPo 1 218
-sti mwPo 4 219
-sti sP 1 223
-stl wP2 224
-stl wN2 225
-stl mwP 2 226
-stl mwN 5 228
-stl swN 1 233
-teq - 234
-tgt - 235
-tlt - 236
-tne - 237
-zeq 2 238
-zeq sP 2 239
-zer sP 1 241
-zge sP 1 242
-zgt sP 1 243
-zle sP 1 244
-zlt sP 1 245
-zne sP 1 246
-zne sN 1 247
-zre w2 248
-zre sw 1 249
-zrl mwN 2 250
-zrl swN 1 252
-zrl wN2 253
-aar e2 0
-aar e- 1
-adf e2 2
-adf e- 3
-adi e2 4
-adi e- 5
-ads e2 6
-ads e- 7
-adu e2 8
-adu e- 9
-and e2 10
-and e- 11
-asp ew2 12
-ass e2 13
-ass e- 14
-bge e2 15
-bgt e2 16
-ble e2 17
-blm e2 18
-bls e2 19
-bls e- 20
-blt e2 21
-bne e2 22
-cai e- 23
-cal e2 24
-cfi e- 25
-cfu e- 26
-ciu e- 27
-cmf e2 28
-cmf e- 29
-cmi e2 30
-cmi e- 31
-cms e2 32
-cms e- 33
-cmu e2 34
-cmu e- 35
-com e2 36
-com e- 37
-csa e2 38
-csa e- 39
-csb e2 40
-csb e- 41
-cuf e- 42
-cui e- 43
-cuu e- 44
-dee ew2 45
-del ewP2 46
-del ewN2 47
-dup e2 48
-dus e2 49
-dus e- 50
-dvf e2 51
-dvf e- 52
-dvi e2 53
-dvi e- 54
-dvu e2 55
-dvu e- 56
-fef e2 57
-fef e- 58
-fif e2 59
-fif e- 60
-inl ewP2 61
-inl ewN2 62
-inn e2 63
-inn e- 64
-ior e2 65
-ior e- 66
-lar e2 67
-lar e- 68
-ldc e2 69
-ldf e2 70
-ldl ewP2 71
-ldl ewN2 72
-lfr e2 73
-lil ewP2 74
-lil ewN2 75
-lim e- 76
-los e2 77
-los e- 78
-lor esP 1 79
-lpi e2 80
-lxa e2 81
-lxl e2 82
-mlf e2 83
-mlf e- 84
-mli e2 85
-mli e- 86
-mlu e2 87
-mlu e- 88
-mon e- 89
-ngf e2 90
-ngf e- 91
-ngi e2 92
-ngi e- 93
-nop e- 94
-rck e2 95
-rck e- 96
-ret e2 97
-rmi e2 98
-rmi e- 99
-rmu e2 100
-rmu e- 101
-rol e2 102
-rol e- 103
-ror e2 104
-ror e- 105
-rtt e- 106
-sar e2 107
-sar e- 108
-sbf e2 109
-sbf e- 110
-sbi e2 111
-sbi e- 112
-sbs e2 113
-sbs e- 114
-sbu e2 115
-sbu e- 116
-sde e2 117
-sdf e2 118
-sdl ewP2 119
-sdl ewN2 120
-set e2 121
-set e- 122
-sig e- 123
-sil ewP2 124
-sil ewN2 125
-sim e- 126
-sli e2 127
-sli e- 128
-slu e2 129
-slu e- 130
-sri e2 131
-sri e- 132
-sru e2 133
-sru e- 134
-sti e2 135
-sts e2 136
-sts e- 137
-str esP 1 138
-tge e- 139
-tle e- 140
-trp e- 141
-xor e2 142
-xor e- 143
-zer e2 144
-zer e- 145
-zge e2 146
-zgt e2 147
-zle e2 148
-zlt e2 149
-zne e2 150
-zrf e2 151
-zrf e- 152
-zrl ewP2 153
-dch e- 154
-exg esP 1 155
-exg e2 156
-exg e- 157
-lpb e- 158
-gto e2 159
-ldc 4 0
-lae 4 1
-lal P4 2
-lal N4 3
-lde w4 4
-ldf 4 5
-ldl wP4 6
-ldl wN4 7
-lil wP4 8
-lil wN4 9
-loc 4 10
-loe w4 11
-lof 4 12
-lol wP4 13
-lol wN4 14
-lpi 4 15
-adp 4 16
-asp w4 17
-beq 4 18
-bge 4 19
-bgt 4 20
-ble 4 21
-blm 4 22
-blt 4 23
-bne 4 24
-bra 4 25
-cal 4 26
-dee w4 27
-del wP4 28
-del wN4 29
-fil 4 30
-gto 4 31
-ine w4 32
-inl wP4 33
-inl wN4 34
-lin 4 35
-sde 4 36
-sdf 4 37
-sdl wP4 38
-sdl wN4 39
-sil wP4 40
-sil wN4 41
-ste w4 42
-stf 4 43
-stl wP4 44
-stl wN4 45
-zeq 4 46
-zge 4 47
-zgt 4 48
-zle 4 49
-zlt 4 50
-zne 4 51
-zre w4 52
-zrl wP4 53
-zrl wN4 54

+ 0 - 71
etc/new_table

@@ -1,71 +0,0 @@
-h=${1-.}
-d=${2-.}
-
-set `grep fpseu em_table`
-p=$2
-set `grep fmnem em_table`
-m=$2
-
-ed - em_table <<'A' > X
-1,/^$/g/	/s// /gp
-A
-
-ed - em_table <<'A' | awk '{print $1,$2+'$p'}' > Y
-1,/^$/d
-1,/^$/g/	/s// /gp
-A
-
-ed - em_table <<'A' | awk '{print $0,'$m'+i++}' > Z
-1,/^$/d
-1,/^$/d
-1,/^$/g/	/s// /gp
-A
-
-i=`wc -l <Y`
-echo 'lpseu' `expr $i + $p - 1` >>X
-i=`wc -l <Z`
-echo 'lmnem' `expr $i + $m - 1` >>X
-
-ed - X <<'A' > $h/em_spec.h
-g/^/s//#define sp_/p
-A
-
-ed - Y <<'A' > $h/em_pseu.h
-g/\(.*\) \(.*\)/s//#define ps_\1 \2/p
-A
-
-ed - Z <<'A' > $h/em_mnem.h
-g/ .* /s// /
-g/\(.*\) \(.*\)/s//#define op_\1 \2/p
-A
-
-(
-echo 'char em_pseu[][4] = {'
-ed - Y <<'A'
-g/\(...\).*/s//	"\1",/p
-A
-echo '};'
-) > $d/em_pseu.c
-
-(
-echo 'char em_mnem[][4] = {'
-ed - Z <<'A'
-g/\(...\).*/s//	"\1",/p
-A
-echo '};'
-) > $d/em_mnem.c
-
-(
-echo '#include	<em_flag.h>
-char em_flag[] = {'
-ed - Z <<'A' | tr a-z A-Z
-g/^... /s///
-g/ .*/s///
-g/\(.\)\(.\)/s//PAR_\1 | FLO_\2/
-g/-/s//NO/g
-g/.*/s//	&,/p
-A
-echo '};'
-) > $d/em_flag.c
-
-rm X Y Z

+ 0 - 289
etc/pc_errors

@@ -1,289 +0,0 @@
-non-standard feature used
-identifier '%s' declared twice
-end of file encountered
-bad line directive
-unsigned real: digit of fraction expected
-unsigned real: digit of exponent expected
-unsigned real: too many digits (>72)
-unsigned integer: too many digits (>72)
-unsigned integer: overflow (>32767)
-string constant: must not exceed one line
-string constant: at least one character expected
-string constant: double quotes not allowed (see c option)
-string constant: too long (>72 chars)
-bad character
-identifier '%s' not declared
-location counter overflow: arrays too big
-location counter overflow: arrays too big
-arraysize too big
-variable '%s' never used
-variable '%s' never assigned
-the files contained in '%s' are not closed automatically
-constant expected
-constant: only integers and reals may be signed
-constant: out of bounds
-simple type expected
-enumerated type: element identifier expected
-enumerated type: ',' or ')' expected
-enumerated type: ',' expected
-enumerated type: ')' expected
-subrange type: type must be scalar, but not real
-subrange type: '..' expected
-subrange type: type of lower and upper bound incompatible
-subrange type: lower bound exceeds upper bound
-array type: '[' expected
-conformant array: low bound identifier expected
-conformant array: '..' expected
-conformant array: high bound identifier expected
-conformant array: ':' expected
-conformant array: index type identifier expected
-array type: index type not bounded
-array type: index separator or ']' expected
-array type: index separator expected
-array type: ']' expected
-array type: 'of' expected
-record variant part: tag type identifier expected
-record variant part: tag type identifier expected
-record variant part: type must be bounded
-record variant part: 'of' expected
-record variant: type of case label and tag incompatible
-record variant: multiple defined case label
-record variant: ',' or ':' expected
-record variant: ',' expected
-record variant: ':' expected
-record variant: '(' expected
-record variant: ')' expected
-record variant part: ';' or end of variant list expected
-record variant part: ';' expected
-record variant part: end of variant list expected
-record variant part: there must be a variant for each tag value
-field list: record section expected
-record section: field identifier expected
-record section: ',' or ':' expected
-record section: ',' expected
-record section: ':' expected
-field list: ';' or end of record section list expected
-field list: ';' expected
-field list: end of record section list expected
-type expected
-type: simple and pointer type may not be packed
-pointer type: type identifier expected
-pointer type: type identifier expected
-record type: 'end' expected
-set type: 'of' expected
-set type: too many elements in set
-set type: bad subrange of integer
-set of integer: the i option dictates the number of bits (default 16)
-set type: base type not bounded
-file type: 'of' expected
-file type: files within files not allowed
-var parameter: type identifier or conformant array expected
-var parameter: type identifier expected
-label declaration: unsigned integer expected
-label declaration: label '%i' multiple declared
-label declaration: ',' or ';' expected
-label declaration: ',' expected
-label declaration: ';' expected
-const declaration: constant identifier expected
-const declaration: '=' expected
-const declaration: ';' expected
-const declaration: constant identifier or 'type', 'var', 'procedure', 'function' or 'begin' expected
-type declaration: type identifier expected
-type declaration: '=' expected
-type declaration: ';' expected
-type declaration: type identifier or 'var', 'procedure', 'function' or 'begin' expected
-var declaration: var identifier expected
-var declaration: ',' or ':' expected
-var declaration: ',' expected
-var declaration: ':' expected
-var declaration: ';' expected
-var declaration: var identifier or 'procedure', 'function' or 'begin' expected
-parameter list: 'var','procedure','function' or identifier expected
-parameter list: parameter identifier expected
-parameter list: ',' or ':' expected
-parameter list: ',' expected
-parameter list: ':' expected
-parameter list: type identifier expected
-parameter list: ';' or ')' expected
-parameter list: ';' expected
-proc/func declaration: proc/func identifier expected
-proc/func declaration: previous declaration of '%s' was not forward
-proc/func declaration: parameter list expected
-parameterlist: ')' expected
-func declaration: ':' expected
-func declaration: result type identifier expected
-func declaration: result type must be scalar, subrange or pointer
-proc/func declaration: ';' expected
-proc/func declaration: block or directive expected
-proc/func declaration: '%s' unknown directive
-proc/func declaration: '%s' again forward declared
-proc/func declaration: ';' expected
-indexed variable: '[' only allowed following array variables
-indexed variable: index type not compatible with declaration
-indexed variable: ',' or ']' expected
-indexed variable: ',' expected
-assignment: standard function not allowed as destination
-assignment: cannot store the function result
-assignment: formal parameter function not allowed as destination
-assignment: function identifier may not be de-referenced
-variable: '[', '.', '^' or end of variable expected
-indexed variable: ']' expected
-field designator: field identifier expected
-field designator: '.' only allowed following record variables
-field designator: no field '%s' in this record
-referenced variable: '^' not allowed following zero-terminated strings
-referenced variable: '^' only allowed following pointer or file variables
-variable: var or field identifier expected
-call: too many actual parameters supplied
-call: proc/func identifier expected
-call: standard proc/func may not be used as parameter
-call: parameter lists of actual and formal proc/func incompatible
-call: type of actual and formal value parameter not compatible
-call: array parameter not conformable
-call: type of actual and formal variable parameter not similar
-call: packed elements not allowed as variable parameter
-call: ',' or ')' expected
-call: too few actual parameters supplied
-read(ln): type must be integer, char or real
-write(ln): type must be integer, char, real, string or boolean
-write(ln): ':', ',' or ')' expected
-write(ln): field width must be integer
-write(ln): ':', ',' or ')' expected
-write(ln): precision must be integer
-write(ln): precision may only be specified for reals
-read/write: too few actual parameters supplied
-read/write: standard input/output not mentioned in program heading
-read/write: ',' or ')' expected
-read/write: type of parameter not the same as that of the file elements
-read/write: parameter list expected
-readln/writeln: standard input/output not mentioned in program heading
-readln/writeln: only allowed on text files
-new/dispose: C-type strings not allowed here
-new/dispose: ',' or ')' expected
-new/dispose: too many actual parameters supplied
-new/dispose: type of tagfield value is incompatible with declaration
-call: '(' or end of call expected
-standard proc/func: parameter list expected
-standard input/output not mentioned in program heading
-file variable expected
-pointer variable expected
-pack: ',' expected
-pack: ',' expected
-unpack: ',' expected
-unpack: ',' expected
-standard proc/func: parameter type incompatible with specification
-eoln/page: text file variable expected
-pack/unpack: array types are incompatible
-pack/unpack: only for arrays
-abs: integer or real expected
-sqr: integer or real expected
-ord: type must be scalar or subrange, but not real
-pred/succ: type must be scalar or subrange, but not real
-trunc/round: real argument required
-call: ')' expected
-expression: left and right operand are incompatible
-set: incompatible elements
-set: base type must be bounded or of type integer
-set: base type upper bound exceeds maximum set element number
-set: element out of range
-set: ']' or element list expected
-set: '..', ',' or ']' expected
-set: ',' or ']' expected
-set: ',' expected
-factor expected
-factor: ')' expected
-factor: type of factor must be boolean
-set: ']' expected
-term: multiplying operator or end of term expected
-term: '*' only defined for integers, reals and sets
-term: '/' only defined for integers and reals
-term: 'div' only defined for integers
-term: 'mod' only defined for integers
-term: 'and' only defined for booleans
-simple expression: only integers and reals may be signed
-simple expression: adding operator or end of simple expression expected
-simple expression: '+' only defined for integers, reals and sets
-simple expression: '-' only defined for integers, reals and sets
-simple expression: 'or' only defined for booleans
-expression: relational operator or end of expression expected
-expression: set expected
-expression: left operand of 'in' not compatible with base type of right operand
-expression: only '=' and '<>' allowed on pointers
-expression: '<' and '>' not allowed on sets
-expression: comparison of arrays only allowed for strings
-expression: comparison of records not allowed
-expression: comparison of files not allowed
-assignment: ':=' expected
-assignment: left and right hand side incompatible
-goto statement: unsigned integer expected
-goto statement: label '%i' not declared
-if statement: type of expression must be boolean
-if statement: 'then' expected
-if statement: 'else' or end of if statement expected
-case statement: type must be scalar or subrange, but not real
-case statement: 'of' expected
-case statement: incompatible case label
-case statement: multiple defined case label
-case statement: ',' or ':' expected
-case statement: ',' expected
-case statement: ':' expected
-case statement: ';' or 'end' expected
-case statement: ';' expected
-case statement: 'end' expected
-repeat statement: ';' or 'until' expected
-repeat statement: ';' expected
-repeat statement: 'until' expected
-repeat statement: type of expression must be boolean
-while statement: type of expression must be boolean
-while statement: 'do' expected
-for statement: type of bound and control variable incompatible
-for statement: control variable expected
-for statement: control variable must be local
-for statement: type must be scalar or subrange, but not real
-for statement: ':=' expected
-for statement: 'to' or 'downto' expected
-for statement: upper bound not assignment compatible
-for statement: 'do' expected
-with statement: record variable expected
-with statement: ',' or 'do' expected
-with statement: ',' expected
-with statement: 'do' expected
-assertion: type of expression must be boolean
-statement expected
-label '%i' not declared
-label '%i' multiple defined
-statement: ':' expected
-unlabeled statement expected
-compound statement: ';' or 'end' expected
-compound statement: ';' expected
-compound statement: 'end' expected
-case statement: 'end' expected
-body: ';' or 'end' expected
-body: ';' expected
-body: label '%i' declared, but never defined
-program parameter '%s' not declared
-function '%s' never assigned
-block: declaration or body expected
-block: 'const', 'type', 'var', 'procedure', 'function' or 'begin' expected
-block: 'type', 'var', 'procedure', 'function' or 'begin' expected
-block: 'var', 'procedure', 'function' or 'begin' expected
-block: 'procedure', 'function' or 'begin' expected
-block: unsatisfied forward proc/func declaration(s)
-block: 'begin' expected
-block: 'end' expected
-program heading: 'program' expected
-program heading: program identifier expected
-program heading: file identifier list expected
-program heading: file identifier expected
-program heading: ',' or ')' expected
-program heading: ',' expected
-program heading: maximum number of file arguments exceeded (12)
-program heading: ')' expected
-program heading: ';' expected
-program: '.' expected
-'program' expected
-module: 'const', 'type', 'var', 'procedure' or 'function' expected
-module: 'type', 'var', 'procedure' or 'function' expected
-module: 'var', 'procedure' or 'function' expected
-module: 'procedure' or 'function' expected
-garbage at end of program

+ 0 - 107
etc/pc_rt_errors

@@ -1,107 +0,0 @@
-array bound error
-range bound error
-set bound error
-integer overflow
-real overflow
-real underflow
-divide by 0
-divide by 0.0
-undefined integer
-real undefined
-conversion error
-error 11
-error 12
-error 13
-error 14
-error 15
-stack overflow
-heap error
-illegal instruction
-odd or zero byte count
-case error
-memory fault
-bad pointer
-bad program counter
-bad external address
-bad monitor call
-bad line number
-error 27
-error 28
-error 29
-error 30
-error 31
-error 32
-error 33
-error 34
-error 35
-error 36
-error 37
-error 38
-error 39
-error 40
-error 41
-error 42
-error 43
-error 44
-error 45
-error 46
-error 47
-error 48
-error 49
-error 50
-error 51
-error 52
-error 53
-error 54
-error 55
-error 56
-error 57
-error 58
-error 59
-error 60
-error 61
-error 62
-error 63
-more args expected
-error in exp
-error in ln
-error in sqrt
-assertion failed
-array bound error in pack
-array bound error in unpack
-only positive j in 'i mod j'
-file not yet open
-dispose error
-error 74
-error 75
-error 76
-error 77
-error 78
-error 79
-error 80
-error 81
-error 82
-error 83
-error 84
-error 85
-error 86
-error 87
-error 88
-error 89
-error 90
-error 91
-error 92
-error 93
-error 94
-error 95
-not writable
-not readable
-end of file
-truncated
-reset error
-rewrite error
-close error
-read error
-write error
-digit expected
-non-ASCII char read

+ 0 - 15
etc/pop_push

@@ -1,15 +0,0 @@
-description of third column of em_table:
-
-	-: pop item indicated by next character
-	+: push item indicated by next character
-	0: no effect on the stack
-
-characters describing items:
-
-	w: target machine word (1, 2 or 4)
-	d: double target machine word (2, 4 or 8)
-	p: target machine address
-	a: item with size specified in argument
-	x: item with size specified by top item of stack
-	y: item with size specified by second item on stack
-	?: one or more items of unknown size

+ 0 - 28
etc/traps

@@ -1,28 +0,0 @@
-~ Array bound error
-~ Range bound error
-~ Set bound error
-~ Integer overflow
-~ Floating overflow
-~ Floating underflow
-~ Divide by 0
-~ Divide by 0.0
-~ Integer undefined
-~ Floating undefined
-~ Conversion error
-
-
-
-
-
-* Stack overflow
-* Heap overflow
-* Illegal instruction
-* Illegal odd or zero argument
-* Case error
-* Addressing non existent memory
-* Bad pointer used
-* Program counter out of range
-* Bad argument of LAE
-* Bad monitor call
-* Argument of LIN too high
-* Bad GTO descriptor

+ 0 - 32
first/ckpath

@@ -1,32 +0,0 @@
-rm -f ../bin/x_tpath x_tpath
-echo "echo $$" >../bin/x_tpath
-rm -f x_tpath
-chmod +x ../bin/x_tpath
-case x`(x_tpath) 2>/dev/null`
-in
-x$$)	
-	STAT=0 ;;
-x)
-	(cd ../bin ; echo Sorry, `pwd` is not in your shell PATH" ($PATH)")
-	STAT=1 ;;
-*)
-	echo "Sorry, there is something wrong with your PATH ($PATH)" ;;
-esac
-echo "echo l_$$" >x_tpath
-chmod +x x_tpath
-case x`(x_tpath) 2>/dev/null`
-in
-xl_$$)
-	;;
-x)
-	(cd ../bin ; echo Sorry, . is not in your shell PATH" ($PATH)")
-	STAT=2 ;;
-x$$)	
-	echo Sorry, . is not in your PATH" ($PATH)" or after the ACK bin directory
-	STAT=3 ;;
-*)
-	echo "Sorry, there is something wrong with your PATH ($PATH)"
-	STAT=4 ;;
-esac
-rm -f ../bin/x_tpath x_tpath
-exit $STAT

+ 0 - 7
first/did_first

@@ -1,7 +0,0 @@
-if (ack_sys ) >/dev/null 2>&1
-then
-	exit 0
-else
-	echo "You need to run 'first' first"
-	exit 1
-fi

+ 0 - 7
first/em_path.h.src

@@ -1,7 +0,0 @@
-/* Intended as a common directory for ALL temporary files */
-#define TMP_DIR		"/usr/tmp"
-
-/* Access to the ACK tree and parts thereof */
-#define EM_DIR		"/usr/em"	/* The root directory for EM stuff */
-#define RTERR_PATH	"etc/pc_rt_errors"
-#define ACK_PATH	"lib/descr"

+ 0 - 133
first/first

@@ -1,133 +0,0 @@
-: check $PATH first
-if sh ckpath
-then :
-else
-	exit 1
-fi
-: set ACK HOME Directory in ../h/em_path.h
-rm -f em_path.h
-sed -e "/^#define[ 	]*EM_DIR/s@\".*\"@\"`cd .. ; pwd`\"@" <../h/em_path.h >em_path.h
-if cmp ../h/em_path.h em_path.h >/dev/null 2>&1
-then
-	: Don't touch ../h/em_path.h, it's already correct
-else
-	rm -f ../h/em_path.h
-	if mv em_path.h ../h >/dev/null 2>&1
-	then : success
-	else
-		echo "Sorry, can't replace ../h/em_path.h"
-		exit 7
-	fi
-fi
-: remove non-system as and ld from descr files
-if (ack_sys) >/dev/null 2>&1
-then
-	: echo Your system is: `ack_sys`.
-else
-	echo -n "Give me the name of your system, the current choice is:
-pdp_v7		PDP11 with sep I/D and version 7
-vax_bsd4_1a	VAX11 with BSD4.1a
-vax_bsd4_1c	VAX11 with BSD4.1c
-vax_bsd4_2	VAX11 with BSD4.2
-pc_ix		IBM PC with PC/IX
-m68_unisoft	Motorola 68000 with Unisoft UNIX
-m68_pmds	Philips PMDS
-ANY		Neither of the above
-
-system type: "
-	if read SYSNAME
-	then
-		echo echo "$SYSNAME" >../bin/ack_sys
-		chmod +x ../bin/ack_sys
-		case `ack_sys` in
-		pdp_v7|vax_bsd4_1[ac]|vax_bsd4_2|pc_ix|m68_unisoft|m68_pmds) ;;
-		*)	echo None of the software especially intended for
-the named systems will work ;;
-		esac
-	else
-		echo Sorry, got EOF when reading system name.
-		exit 8
-	fi
-fi
-echo -n "Your system is `ack_sys`, are you satisfied with that? (y/n) "
-if read YESNO
-then
-	case $YESNO in
-	j*|y*)	;;
-	n*)	echo Ok, I will give you another chance....
-		rm -f ../bin/ack_sys
-		exec sh $0
-		;;
-	*)	echo "I do not understand your answer ($YESNO). Bye"
-		exit 9
-		;;
-	esac
-else
-	echo Sorry, got EOF when reading your answer.
-	exit 9
-fi
-: "Take action according to the system used"
-: 'Prevent the use of the system assembler on for certain systems'
-case `ack_sys` in
-vax_bsd*)	RMD=pdp ;;
-pdp_*)		RMD="vax2 vax4" ;;
-*)		RMD="pdp vax2 vax4" ;;
-esac
-for i in $RMD
-do
-(	cd ../lib/$i
-	if grep '^name as$' descr >/dev/null 2>&1
-		then
-cp descr descr.orig
-ed - descr <<'ABC'
-/^name as$/;/^end$/d
-/^name ld$/;/^end$/d
-w
-q
-ABC
-	fi
-)
-done
-: 'Set the default machine in ../h/local.h'
-case `ack_sys` in
-pdp_v7)		ACM=pdp ;;
-vax_bsd4_1[ac]) ACM=vax2 ;;
-vax_bsd4_2)	ACM=vax2 ;;
-pc_ix)		ACM=ix ;;
-m68_unisoft)	ACM=m68k2 ;;
-m68_pmds) 	ACM=pmds ;;
-esac
-rm -f local.h
-sed /ACKM/s/'".*"'/'"'$ACM'"'/ <../h/local.h >local.h
-if cmp -s ../h/local.h local.h
-then :
-else
-	cp local.h ../h
-	rm -f local.h
-fi
-echo "Your default machine to compile for is $ACM"
-case `ack_sys` in
-vax_bsd4_*)
-	echo 'Installing the include directory in lib/vax2'
-	( cd ../lib/vax2 ; sh fetch_inc )
-	echo Done
-	case `ack_sys` in
-	vax_bsd4_1a)	VERS=BSD41a ;;
-	vax_bsd4_1c)	VERS=BSD41c ;;
-	vax_bsd4_2)	VERS=BSD42 ;;
-	*)		echo "Unknown VAX BSD version, look at mach/vax[24]/libem"
-			break ;;
-	esac
-	for i in vax2 vax4
-	do (
-		cd ../mach/$i/libem
-		ed - system.h <<ABC
-g/^#/s/.*/\/* & *\//
-/$VERS/s/^.*#/#/
-/$VERS/s/*\/.*$//
-w
-q
-ABC
-	) done
-	echo 'mach/vax[24]/libem/system.h reflects your BSD version.'
-esac

+ 0 - 7
first/local.h.src

@@ -1,7 +0,0 @@
-/* collection of options, selected by including or excluding 'defines' */
-
-/* Version number of the EM object code */
-#	define	VERSION		3	/* 16 bits number */
-
-/* The default machine used by ack, acc, apc */
-#	define	ACKM		"vax2"

+ 0 - 10
h/Makefile

@@ -1,10 +0,0 @@
-install cmp:
-
-opr:
-	make pr | opr
-
-pr:
-	@pr Makefile *.h
-
-clean:
-	-rm -f *.old

+ 0 - 12
h/arch.h

@@ -1,12 +0,0 @@
-#define	ARMAG	0177545
-struct	ar_hdr {
-	char	ar_name[14];
-	long	ar_date;
-	char	ar_uid;
-	char	ar_gid;
-	int	ar_mode;
-	long	ar_size;
-};
-
-#define AR_TOTAL	26
-#define AR_SIZE		22

+ 0 - 1
h/as_spec.h

@@ -1 +0,0 @@
-#define as_magic        (sp_magic|(14<<8))

+ 0 - 29
h/bc_io.h

@@ -1,29 +0,0 @@
-#include <stdio.h>
-
-/* $Header$ */
-
-/* BASIC file io definitions */
-
-extern FILE *_chanrd;
-extern FILE *_chanwr;
-extern int   _chann;
-/* BASIC file descriptor table */
-/* Channel assignment:
-   -1		terminal IO
-    0		data file
-    1-15	user files
-*/
-
-/* FILE MODES:*/
-#define 	IMODE	1
-#define		OMODE	2
-#define		RMODE	3
-
-typedef struct {
-	char	*fname;
-	FILE	*fd;
-	int	pos;
-	int	mode;	
-	int	reclength;
-	}Filedesc;
-extern Filedesc	 _fdtable[16];

+ 0 - 17
h/bc_string.h

@@ -1,17 +0,0 @@
-#
-
-/* $Header$ */
-
-/* Strings are allocated in a fixed string descriptor table 
-** This mechanism is used to avoid string copying as much as possible
-*/
-
-typedef struct{
-	char	*strval;
-	int	strcount;
-	int	strlength;
-	} String;
-
-String *_newstr() ;
-
-#define MAXSTRING 1024

+ 0 - 156
h/cg_pattern.h

@@ -1,156 +0,0 @@
-/* offsets of interesting fields in EM-pattern */
-
-#define PO_HASH         0
-#define PO_NEXT         1
-#define PO_MATCH        3
-
-#define ILLHASH 0177777
-
-/* Escapes in printstrings */
-
-#define PR_TOK          '\001'
-#define PR_TOKFLD       '\002'
-#define PR_EMINT        '\003'
-#define PR_EMSTR        '\004'
-#define PR_ALLREG       '\005'
-#define PR_SUBREG       '\006'
-/*
- * In case this list gets longer remember to keep out printable nonprintables
- * like \t \n \r and the like.
- */
-
-/* Commands for codegenerator, in low order 5 bits of byte */
-
-#define DO_NEXTEM       0
-#define DO_MATCH        1
-#define DO_XMATCH	2
-#define DO_XXMATCH	3
-#define DO_REMOVE       4
-#define DO_DEALLOCATE   5
-#define DO_REALLOCATE   6
-#define DO_ALLOCATE     7
-#define DO_LOUTPUT      8
-#define DO_ROUTPUT      9
-#define DO_MOVE         10
-#define DO_ERASE        11
-#define DO_TOKREPLACE   12
-#define DO_EMREPLACE    13
-#define DO_COST         14
-#define DO_RETURN       15
-#define DO_COERC        16
-#define DO_PRETURN	17
-#define DO_RREMOVE	18
-
-typedef struct instance {
-	int in_which;
-#               define IN_COPY          1
-#               define IN_RIDENT        2
-#               define IN_ALLOC         3
-#               define IN_DESCR         4
-#		define IN_REGVAR	5
-	int in_info[TOKENSIZE+1];
-} inst_t,*inst_p;
-
-typedef struct {
-	int     c_size;                 /* index in enode-table */
-	int     c_time;                 /* dito */
-} cost_t,*cost_p;
-
-typedef struct {
-	int m_set1;             /* number of tokenexpr in move: from */
-	int m_expr1;            /* optional expression */
-	int m_set2;             /* number of tokenexpr in move: to */
-	int m_expr2;            /* optional expression */
-	int m_cindex;           /* code index to really do it */
-	cost_t m_cost;          /* associated cost */
-} move_t, *move_p;
-
-typedef struct {
-	int set_size;
-	short set_val[SETSIZE];
-} set_t,*set_p;
-
-struct exprnode {
-	short ex_operator;
-	short ex_lnode;
-	short ex_rnode;
-};
-typedef struct exprnode node_t;
-typedef struct exprnode *node_p;
-
-typedef struct {        /* to stack coercions */
-	int c1_texpno;          /* token expression number */
-	int c1_expr;		/* boolean expression */
-	int c1_prop;		/* property of register needed */
-	int c1_codep;           /* code index */
-	cost_t c1_cost;		/* cost involved */
-} c1_t,*c1_p;
-
-#ifdef MAXSPLIT
-typedef struct {        /* splitting coercions */
-	int c2_texpno;          /* token expression number */
-	int c2_nsplit;          /* split factor */
-	int c2_repl[MAXSPLIT];  /* replacement instances */
-	int c2_codep;           /* code index */
-} c2_t,*c2_p;
-#endif MAXSPLIT
-
-typedef struct {        /* one to one coercions */
-	int c3_texpno;          /* token expression number */
-	int c3_prop;            /* property of register needed */
-	int c3_repl;            /* replacement instance */
-	int c3_codep;           /* code index */
-} c3_t,*c3_p;
-
-/*
- * contents of .ex_operator
- */
-
-#define EX_TOKFIELD     0
-#define EX_ARG          1
-#define EX_CON          2
-#define EX_ALLREG       3
-#define EX_SAMESIGN     4
-#define EX_SFIT         5
-#define EX_UFIT         6
-#define EX_ROM          7
-#define EX_NCPEQ        8
-#define EX_SCPEQ        9
-#define EX_RCPEQ        10
-#define EX_NCPNE        11
-#define EX_SCPNE        12
-#define EX_RCPNE        13
-#define EX_NCPGT        14
-#define EX_NCPGE        15
-#define EX_NCPLT        16
-#define EX_NCPLE        17
-#define EX_OR2          18
-#define EX_AND2         19
-#define EX_PLUS         20
-#define EX_CAT          21
-#define EX_MINUS        22
-#define EX_TIMES        23
-#define EX_DIVIDE       24
-#define EX_MOD          25
-#define EX_LSHIFT       26
-#define EX_RSHIFT       27
-#define EX_NOT          28
-#define EX_COMP         29
-#define EX_COST         30
-#define EX_STRING       31
-#define EX_DEFINED      32
-#define EX_SUBREG       33
-#define EX_TOSTRING     34
-#define EX_UMINUS       35
-#define EX_REG          36
-#define EX_LOWW		37
-#define EX_HIGHW	38
-#define EX_INREG	39
-#define EX_REGVAR	40
-
-
-
-#define getint(a,b) \
-	if ((a=((*(b)++)&BMASK)) >= 128) {\
-		a = ((a-128)<<BSHIFT) | (*(b)++&BMASK); \
-	}

+ 0 - 154
h/cgg_cg.h

@@ -1,154 +0,0 @@
-/* $Header$ */
-
-/* offsets of interesting fields in EM-pattern */
-
-#define PO_HASH         0
-#define PO_NEXT         1
-#define PO_MATCH        3
-
-#define ILLHASH 0177777
-
-
-/* Commands for codegenerator, in low order 5 bits of byte */
-
-#define DO_NEXTEM       0
-#define DO_MATCH        1
-#define DO_XMATCH	2
-#define DO_XXMATCH	3
-#define DO_REMOVE       4
-#define DO_DEALLOCATE   5
-#define DO_REALLOCATE   6
-#define DO_ALLOCATE     7
-#define DO_MOVE         10
-#define DO_ERASE        11
-#define DO_TOKREPLACE   12
-#define DO_EMREPLACE    13
-#define DO_COST         14
-#define DO_RETURN       15
-#define DO_COERC        16
-#define DO_PRETURN	17
-#define DO_RREMOVE	18
-#define DO_INSTR	19
-#define DO_TEST		20
-#define DO_DLINE	21
-#define DO_SETCC	22
-
-#ifndef MAXATT
-#define MAXATT TOKENSIZE
-#endif
-
-typedef struct instance {
-	short in_which;
-#               define IN_COPY          1
-#		define IN_MEMB		2
-#               define IN_RIDENT        3
-#               define IN_ALLOC         4
-#               define IN_DESCR         5
-#               define IN_S_DESCR       6
-#               define IN_D_DESCR       7
-	short in_info[MAXATT+1];
-} inst_t,*inst_p;
-
-typedef struct set {
-	short set_size;
-	short set_val[SETSIZE];
-} set_t,*set_p;
-
-typedef struct {
-	short m_set1;           /* number of tokenexpr in move: from */
-	short m_expr1;          /* optional expression */
-	short m_set2;           /* number of tokenexpr in move: to */
-	short m_expr2;          /* optional expression */
-	short m_cindex;         /* code index to really do it */
-} move_t, *move_p;
-
-typedef struct {
-	short t_set;		/* number of tokenexpr in test */
-	short t_expr;		/* optional expression */
-	short t_cindex;		/* code index to really do it */
-} test_t, *test_p;
-
-struct exprnode {
-	short ex_operator;
-	short ex_lnode;
-	short ex_rnode;
-};
-typedef struct exprnode node_t;
-typedef struct exprnode *node_p;
-
-/*
- * contents of .ex_operator
- */
-
-#define EX_TOKFIELD     0
-#define EX_ARG          1
-#define EX_CON          2
-#define EX_ALLREG       3
-#define EX_SAMESIGN     4
-#define EX_SFIT         5
-#define EX_UFIT         6
-#define EX_ROM          7
-#define EX_NCPEQ        8
-#define EX_SCPEQ        9
-#define EX_RCPEQ        10
-#define EX_NCPNE        11
-#define EX_SCPNE        12
-#define EX_RCPNE        13
-#define EX_NCPGT        14
-#define EX_NCPGE        15
-#define EX_NCPLT        16
-#define EX_NCPLE        17
-#define EX_OR2          18
-#define EX_AND2         19
-#define EX_PLUS         20
-#define EX_CAT          21
-#define EX_MINUS        22
-#define EX_TIMES        23
-#define EX_DIVIDE       24
-#define EX_MOD          25
-#define EX_LSHIFT       26
-#define EX_RSHIFT       27
-#define EX_NOT          28
-#define EX_COMP         29
-#define EX_STRING       31
-#define EX_DEFINED      32
-#define EX_SUBREG       33
-#define EX_TOSTRING     34
-#define EX_UMINUS       35
-#define EX_REG          36
-#define EX_LOWW		37
-#define EX_HIGHW	38
-#define EX_INREG	39
-#define EX_REGVAR	40
-
-
-typedef struct {        /* to stack coercions */
-	short c1_texpno;        /* token expression number */
-	short c1_expr;		/* boolean expression */
-	short c1_prop;		/* property of register needed */
-	short c1_codep;         /* code index */
-} c1_t,*c1_p;
-
-#ifdef MAXSPLIT
-typedef struct {        /* splitting coercions */
-	short c2_texpno;        /* token expression number */
-	short c2_expr;		/* optional boolean expression */
-	short c2_nsplit;        /* split factor */
-	short c2_repl[MAXSPLIT];/* replacement instances */
-	short c2_codep;         /* code index */
-} c2_t,*c2_p;
-#endif MAXSPLIT
-
-typedef struct {        /* one to one coercions */
-	short c3_texpno;        /* token expression number */
-	short c3_expr;		/* boolean expression */
-	short c3_prop;          /* property of register needed */
-	short c3_repl;          /* replacement instance */
-	short c3_codep;         /* code index */
-} c3_t,*c3_p;
-
-
-#define getint(a,b) \
-	if ((a=((*(b)++)&BMASK)) >= 128) {\
-		a = ((a-128)<<BSHIFT) | (*(b)++&BMASK); \
-	}

+ 0 - 30
h/em_abs.h

@@ -1,30 +0,0 @@
-#define LINO_AD         0
-#define FILN_AD         4
-
-#define LINO            (*(int    *)(_hol0()+LINO_AD))
-#define FILN            (*(char  **)(_hol0()+FILN_AD))
-
-#define EARRAY          0
-#define ERANGE          1
-#define ESET            2
-#define EIOVFL          3
-#define EFOVFL          4
-#define EFUNFL          5
-#define EIDIVZ          6
-#define EFDIVZ          7
-#define EIUND           8
-#define EFUND           9
-#define ECONV           10
-
-#define ESTACK          16
-#define EHEAP           17
-#define EILLINS         18
-#define EODDZ           19
-#define ECASE           20
-#define EMEMFLT         21
-#define EBADPTR         22
-#define EBADPC          23
-#define EBADLAE         24
-#define EBADMON         25
-#define EBADLIN         26
-#define EBADGTO         27

+ 0 - 12
h/em_ego.h

@@ -1,12 +0,0 @@
-/*
- * The various different hints as given after a mes ms_ego
- *
- * Yet to be stabilized
- */
-
-#define ego_live    0	/* ,offset,size,regno */
-#define ego_dead    1	/* ,offset,size,regno */
-#define ego_assoc   2	/* ,offset,size,regno */
-#define ego_unass   3	/* ,offset,size,regno */
-#define ego_init    4	/* ,offset,size,regno */
-#define ego_update  5	/* ,offset,size,regno */

+ 0 - 25
h/em_flag.h

@@ -1,25 +0,0 @@
-/* flags */
-#define	EM_PAR	0017	/* parameter type */
-#define	EM_FLO	0060	/* flow information */
-
-/* types */
-#define PAR_NO	0000	/* no parameter */
-#define PAR_C	0001	/* constant */
-#define PAR_D	0002	/* double word constant */
-#define PAR_N	0003	/* numeric (>=0) */
-#define PAR_F	0004	/* address offset */
-#define PAR_L	0005	/* addressing locals/parameters */
-#define PAR_G	0006	/* addressing globals */
-#define	PAR_W	0007	/* size: word multiple, fits word, possibly indirect */
-#define PAR_S	0010	/* size: word multiple */
-#define PAR_Z	0011	/* size: zero or word multiple */
-#define PAR_O	0012	/* size: word multiple or word fraction */
-#define PAR_P	0013	/* procedure name */
-#define PAR_B	0014	/* branch: instruction label */
-#define PAR_R	0015	/* register number (0,1,2) */
-
-/* flow */
-#define	FLO_NO	0000	/* straight on */
-#define	FLO_C	0020	/* conditional branch */
-#define	FLO_P	0040	/* procedure: call and return */
-#define	FLO_T	0060	/* terminate: no return */

+ 0 - 21
h/em_mes.h

@@ -1,21 +0,0 @@
-/*
- * mnemonics for the message numbers in EM
- */
-
-#define	ms_err	 0	/* Compilation error occurred, ignore rest of module */
-#define	ms_opt	 1	/* Disable optimization please                       */
-#define	ms_emx	 2	/* Wordsize and pointersize assumed                  */
-#define	ms_reg	 3	/* Hint for possible register usage from frontend    */
-#define	ms_src	 4	/* Number of source lines in this module             */
-#define	ms_flt	 5	/* Floating point used                               */
-#define	ms_com	 6	/* Comment to be retained in compact code            */
-#define	ms_ret	 7	/* Reserved                                          */
-#define ms_ext	 8	/* List of exported symbols from this library module */
-#define ms_par	 9	/* Number of bytes of parameters accessed            */
-#define ms_ego	10	/* Hint from EM Global Optimizer                     */
-#define ms_gto	11	/* Dangerous procedure, uses nonlocal goto	     */
-
-/*
- * for details about ms_reg, see em_reg.h
- * for details about ms_ego, see em_ego.h
- */

+ 0 - 8
h/em_ptyp.h

@@ -1,8 +0,0 @@
-#define	ptyp(x)		(1<<(x-sp_fspec))
-
-#define	cst_ptyp	0000140
-#define	sym_ptyp	0000034
-#define	arg_ptyp	0000574
-#define	con_ptyp	0036000
-#define	val_ptyp	0037777
-#define	any_ptyp	0137777

+ 0 - 10
h/em_reg.h

@@ -1,10 +0,0 @@
-/*
- * mes ms_reg,offset,size,type,priority
- *
- * Here are the defines for type
- */
-
-#define reg_any		0	/* Unspecified type */
-#define reg_loop	1	/* loop control variable */
-#define reg_pointer	2	/* pointer variable */
-#define reg_float	3	/* floating point variable */

+ 0 - 120
h/out.h

@@ -1,120 +0,0 @@
-/* $Header$ */
-/*
- * output format for ACK assemblers
- */
-#ifndef ushort
-#define ushort	unsigned short
-#endif ushort
-
-struct outhead {
-	ushort 	oh_magic;	/* magic number */
-	ushort 	oh_stamp;	/* version stamp */
-	ushort	oh_flags;	/* several format flags */
-	ushort	oh_nsect;	/* number of outsect structures */
-	ushort	oh_nrelo;	/* number of outrelo structures */
-	ushort	oh_nname;	/* number of outname structures */
-	long	oh_nemit;	/* sum of all os_flen */
-	long	oh_nchar;	/* size of string area */
-};
-
-#define O_MAGIC	0x0201		/* magic number of output file */
-#define	O_STAMP	0		/* version stamp */
-
-#ifdef JOHAN
-#define	HF_BREV	0x0001		/* high order byte lowest address */
-#define	HF_WREV	0x0002		/* high order word lowest address */
-#endif JOHAN
-#define	HF_LINK	0x0004		/* unresolved references left */
-#define	HF_8086	0x0008		/* os_base specially encoded */
-
-struct outsect {
-	long 	os_base;	/* startaddress in machine */
-	long	os_size;	/* section size in machine */
-	long	os_foff;	/* startaddress in file */
-	long	os_flen;	/* section size in file */
-	long	os_lign;	/* section alignment */
-};
-
-struct outrelo {
-	char	or_type;	/* type of reference */
-	char	or_sect;	/* referencing section */
-	ushort	or_nami;	/* referenced symbol index */
-	long	or_addr;	/* referencing address */
-};
-
-struct outname {
-	union {
-	  char	*on_ptr;	/* symbol name (in core) */
-	  long	on_off;		/* symbol name (in file) */
-	}	on_u;
-#define on_mptr	on_u.on_ptr
-#define on_foff	on_u.on_off
-	ushort	on_type;	/* symbol type */
-	ushort	on_desc;	/* debug info */
-	long	on_valu;	/* symbol value */
-};
-
-/*
- * relocation type bits
- */
-#define RELSZ	0x07		/* relocation length */
-#define RELO1	   1		/* 1 byte */
-#define RELO2	   2		/* 2 bytes */
-#define RELO4	   4		/* 4 bytes */
-#define RELPC	0x08		/* pc relative */
-#ifndef JOHAN
-#define RELBR	0x10		/* High order byte lowest address. */
-#define RELWR	0x20		/* High order word lowest address. */
-#endif JOHAN
-
-/*
- * section type bits and fields
- */
-#define S_TYP	0x007F		/* undefined, absolute or relative */
-#define S_EXT	0x0080		/* external flag */
-#define S_ETC	0x7F00		/* for symbolic debug, bypassing 'as' */
-
-/*
- * S_TYP field values
- */
-#define S_UND	0x0000		/* undefined item */
-#define S_ABS	0x0001		/* absolute item */
-#define S_MIN	0x0002		/* first user section */
-#define S_MAX	S_TYP		/* last user section */
-
-/*
- * S_ETC field values
- */
-#define S_SCT	0x0100		/* section names */
-#define S_LIN	0x0200		/* hll source line item */
-#define S_FIL	0x0300		/* hll source file item */
-#define S_MOD	0x0400		/* ass source file item */
-#ifndef JOHAN
-#define S_COM	0x1000		/* Common name. */
-#endif JOHAN
-
-/*
- * structure format strings
- */
-#define SF_HEAD		"22222244"
-#define SF_SECT		"44444"
-#define SF_RELO		"1124"
-#define SF_NAME		"4224"
-
-/*
- * structure sizes (bytes in file; add digits in SF_*)
- */
-#define SZ_HEAD		20
-#define SZ_SECT		20
-#define SZ_RELO		8
-#define SZ_NAME		12
-
-/*
- * file access macros
- */
-#define BADMAGIC(x)	((x).oh_magic!=O_MAGIC)
-#define OFF_SECT(x)	SZ_HEAD
-#define OFF_EMIT(x)	(OFF_SECT(x) + ((long)(x).oh_nsect * SZ_SECT))
-#define OFF_RELO(x)	(OFF_EMIT(x) + (x).oh_nemit)
-#define OFF_NAME(x)	(OFF_RELO(x) + ((long)(x).oh_nrelo * SZ_RELO))
-#define OFF_CHAR(x)	(OFF_NAME(x) + ((long)(x).oh_nname * SZ_NAME))

+ 0 - 22
h/pc_err.h

@@ -1,22 +0,0 @@
-#define	EARGC	64
-#define	EEXP	65
-#define	ELOG	66
-#define	ESQT	67
-#define	EASS	68
-#define	EPACK	69
-#define	EUNPACK	70
-#define	EMOD	71
-#define	EBADF	72
-#define	EFREE	73
-
-#define	EWRITEF	96
-#define	EREADF	97
-#define	EEOF	98
-#define	EFTRUNC	99
-#define	ERESET	100
-#define	EREWR	101
-#define	ECLOSE	102
-#define	EREAD	103
-#define	EWRITE	104
-#define	EDIGIT	105
-#define	EASCII	106

+ 0 - 19
h/pc_file.h

@@ -1,19 +0,0 @@
-#define	WRBIT	0100000
-#define	TXTBIT	040000
-#define	EOFBIT	020000
-#define	ELNBIT	010000
-#define	WINDOW	04000
-#define	MAGIC	0252
-
-struct file {
-	char	*ptr;
-	unsigned flags;
-	char	*fname;
-	int	ufd;
-	int	size;
-	int	count;
-	int	buflen;
-	char	bufadr[512];
-};
-
-#define	EXTFL(z)	((struct file *)(_hbase + _extfl[z]))

+ 0 - 21
h/pc_size.h

@@ -1,21 +0,0 @@
-/* fundamental */
-#define	sz_byte	1
-#define	sz_bool	1
-#define	sz_char	1
-
-/* fixed for the time being */
-#define	sz_word	2
-#define	sz_int	2
-#define	sz_long	4
-
-/* variable (see pc.c) */
-#define	sz_addr	sizes[0]
-#define	sz_real	sizes[1]
-#define	sz_head	sizes[2]
-#define	sz_buff	sizes[3]
-#define	sz_mset	sizes[4]
-#define	sz_iset	sizes[5]
-
-#define	sz_last	5
-
-#define	sz_proc	2*sz_addr

+ 0 - 25
h/ranlib.h

@@ -1,25 +0,0 @@
-/* $Header$ */
-
-#ifndef SYMDEF
-#	define SYMDEF	"__.SYMDEF"
-#endif SYMDEF
-
-/*
- * Structure of the SYMDEF table of contents for an archive.
- * SYMDEF begins with a long giving the number of ranlib
- * structures that immediately follow, and then continues with a string
- * table consisting of a long giving the number of bytes of
- * strings that follow and then the strings themselves.
- */
-struct ranlib {
-	union {
-	  char	*ran__ptr;	/* symbol name (in core) */
-	  long	ran__off;	/* symbol name (in file) */
-	}	ran_u;
-#define ran_ptr ran_u.ran__ptr
-#define ran_off ran_u.ran__off
-	long	ran_pos;	/* library member is at this position */
-};
-
-#define SZ_RAN	8
-#define SF_RAN	"44"

+ 0 - 1
include/_tail_cc/setjmp.h

@@ -1 +0,0 @@
-typedef char jmp_buf[256];

+ 0 - 42
include/_tail_mon/errno.h

@@ -1,42 +0,0 @@
-/*
- * Error codes
- */
-
-#define	EPERM	1
-#define	ENOENT	2
-#define	ESRCH	3
-#define	EINTR	4
-#define	EIO	5
-#define	ENXIO	6
-#define	E2BIG	7
-#define	ENOEXEC	8
-#define	EBADF	9
-#define	ECHILD	10
-#define	EAGAIN	11
-#define	ENOMEM	12
-#define	EACCES	13
-#define	EFAULT	14
-#define	ENOTBLK	15
-#define	EBUSY	16
-#define	EEXIST	17
-#define	EXDEV	18
-#define	ENODEV	19
-#define	ENOTDIR	20
-#define	EISDIR	21
-#define	EINVAL	22
-#define	ENFILE	23
-#define	EMFILE	24
-#define	ENOTTY	25
-#define	ETXTBSY	26
-#define	EFBIG	27
-#define	ENOSPC	28
-#define	ESPIPE	29
-#define	EROFS	30
-#define	EMLINK	31
-#define	EPIPE	32
-
-/* math software */
-#define	EDOM	33
-#define	ERANGE	34
-
-#define EQUOT	35

+ 0 - 21
include/_tail_mon/signal.h

@@ -1,21 +0,0 @@
-#define NSIG 17
-
-#define	SIGHUP	1	/* hangup */
-#define	SIGINT	2	/* interrupt */
-#define	SIGQUIT	3	/* quit */
-#define	SIGILL	4	/* illegal instruction (not reset when caught) */
-#define	SIGTRAP	5	/* trace trap (not reset when caught) */
-#define	SIGIOT	6	/* IOT instruction */
-#define	SIGEMT	7	/* EMT instruction */
-#define	SIGFPE	8	/* floating point exception */
-#define	SIGKILL	9	/* kill (cannot be caught or ignored) */
-#define	SIGBUS	10	/* bus error */
-#define	SIGSEGV	11	/* segmentation violation */
-#define	SIGSYS	12	/* bad argument to system call */
-#define	SIGPIPE	13	/* write on a pipe with no one to read it */
-#define	SIGALRM	14	/* alarm clock */
-#define	SIGTERM	15	/* software termination signal from kill */
-
-int	(*signal())();
-#define	SIG_DFL	(int (*)())0
-#define	SIG_IGN	(int (*)())1

+ 0 - 34
lang/basic/lib/LIST

@@ -1,34 +0,0 @@
-tail_bc.a
-abs.c
-asc.c
-asrt.c
-atn.c
-chr.c
-conversion.c
-hlt.c
-mki.c
-oct.c
-peek.c
-power.c
-exp.c
-log.c
-print.c
-io.c
-random.c
-read.c
-return.c
-sgn.c
-sin.c
-fif.e
-sqt.c
-fef.e
-stop.c
-string.c
-salloc.c
-swap.c
-trace.c
-write.c
-file.c
-error.c
-trap.c
-setline.e

+ 0 - 10
lang/basic/lib/abs.c

@@ -1,10 +0,0 @@
-/* $Header$ */
-
-long _abl(i) long i;
-{
-	return( i>=0?i:-i);
-}
-double _abr(f) double f;
-{	
-	return( f>=0.0?f: -f);
-}

+ 0 - 11
lang/basic/lib/asc.c

@@ -1,11 +0,0 @@
-#include "bc_string.h"
-
-/* $Header$ */
-
-int _asc(str)
-String *str;
-{
-	if(str==0 || str->strval==0)
-		error(3);
-	return( *str->strval);
-}

+ 0 - 9
lang/basic/lib/asrt.c

@@ -1,9 +0,0 @@
-/* $Header$ */
-
-asrt(b)
-{
-	if(!b){
-		printf("ASSERTION ERROR\n");
-		abort();
-	}
-}

+ 0 - 93
lang/basic/lib/atn.c

@@ -1,93 +0,0 @@
-/*
- * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
- *
- *          This product is part of the Amsterdam Compiler Kit.
- *
- * Permission to use, sell, duplicate or disclose this software must be
- * obtained in writing. Requests for such permissions may be sent to
- *
- *      Dr. Andrew S. Tanenbaum
- *      Wiskundig Seminarium
- *      Vrije Universiteit
- *      Postbox 7161
- *      1007 MC Amsterdam
- *      The Netherlands
- *
- */
-
-/* $Header$ */
-
-/* Author: J.W. Stevenson */
-
-/*
-	floating-point arctangent
-
-	atan returns the value of the arctangent of its
-	argument in the range [-pi/2,pi/2].
-
-	there are no error returns.
-
-	coefficients are #5077 from Hart & Cheney. (19.56D)
-*/
-
-
-static double sq2p1	= 2.414213562373095048802e0;
-static double sq2m1	=  .414213562373095048802e0;
-static double pio2	= 1.570796326794896619231e0;
-static double pio4	=  .785398163397448309615e0;
-static double p4	=  .161536412982230228262e2;
-static double p3	=  .26842548195503973794141e3;
-static double p2	=  .11530293515404850115428136e4;
-static double p1	=  .178040631643319697105464587e4;
-static double p0	=  .89678597403663861959987488e3;
-static double q4	=  .5895697050844462222791e2;
-static double q3	=  .536265374031215315104235e3;
-static double q2	=  .16667838148816337184521798e4;
-static double q1	=  .207933497444540981287275926e4;
-static double q0	=  .89678597403663861962481162e3;
-
-/*
-	xatan evaluates a series valid in the
-	range [-0.414...,+0.414...].
-*/
-
-static double
-xatan(arg)
-double arg;
-{
-	double argsq;
-	double value;
-
-	argsq = arg*arg;
-	value = ((((p4*argsq + p3)*argsq + p2)*argsq + p1)*argsq + p0);
-	value = value/(((((argsq + q4)*argsq + q3)*argsq + q2)*argsq + q1)*argsq + q0);
-	return(value*arg);
-}
-
-static double
-satan(arg)
-double arg;
-{
-	if(arg < sq2m1)
-		return(xatan(arg));
-	else if(arg > sq2p1)
-		return(pio2 - xatan(1/arg));
-	else
-		return(pio4 + xatan((arg-1)/(arg+1)));
-}
-
-
-/*
-	atan makes its argument positive and
-	calls the inner routine satan.
-*/
-
-double
-_atn(arg)
-double arg;
-{
-	if(arg>0)
-		return(satan(arg));
-	else
-		return(-satan(-arg));
-}

+ 0 - 17
lang/basic/lib/chr.c

@@ -1,17 +0,0 @@
-#include "bc_string.h"
-
-/* $Header$ */
-
-String *_chr(i)
-int i;
-{
-	String	*s;
-	char	buf[2];
-
-	if( i<0 || i>127)
-		error(3);
-	buf[0]=i;
-	buf[1]=0;
-	s= _newstr(buf);
-	return(s);
-}

+ 0 - 40
lang/basic/lib/conversion.c

@@ -1,40 +0,0 @@
-/* $Header$ */
-
-int _cint(f) double f;
-{
-	int r;
-	if( f<-32768 || f>32767) error(4);
-	if(f<0)
-		r= f-0.5;
-	else	r= f+0.5;
-	return(r);
-}
-
-double _trunc(f)
-double f;
-{
-	long d;
-	d=f;
-	f=d;
-	return( f );
-}
-
-double _fcint(f) double f;
-{
-	long r;
-	if(f<0){
-		r= -f;
-		r= -r -1;
-	}else	r= f;
-	f=r;
-	return(f);
-}
-int _fix(f)
-double f;
-{
-	int r;
-
-	if( f<-32768.0 || f>32767.0) error(4);
-	r= _sgn(f) * _fcint((f>0.0? f : -f));
-	return(r);
-}

+ 0 - 63
lang/basic/lib/error.c

@@ -1,63 +0,0 @@
-/* $Header$ */
-
-/* error takes an error value in the range of 0-255 */
-/* and generates a trap */
-
-char *errortable[255]={
-/* 0  */	"",
-/* 1  */	"RETURN without GOSUB",
-/* 2  */	"Out of data",
-/* 3  */	"Illegal function call",
-/* 4  */	"Overflow",
-/* 5  */	"Out of memory",
-/*  6 */	"Undefined line ",
-/*  7 */	"Subscript out of range",
-/*  8 */	"Redimensioned array",
-/*  9 */	"Division by zero",
-/* 10 */	"Illegal indirect",
-/* 11 */	"Type mismatch",
-/* 12 */	"Out of string space",
-/* 13 */	"String too long",
-/* 14 */	"String formula too complex",
-/* 15 */	"Can't continue",
-/* 16 */	"Undefined user function",
-/* 17 */	"No resume",
-/* 18 */	"Resume without error",
-/* 19 */	"Unprintable error",
-/* 20 */	"Missing operand",
-/* 21 */	"Line buffer overflow",
-/* 22 */	"FOR without NEXT",
-/* 23 */	"WHILE without WEND",
-/* 24 */	"WEND without WHILE",
-/* 25 */	"Field overflow",
-/* 26 */	"Internal error",
-/* 27 */	"Bad file number",
-/* 28 */	"File not found",
-/* 29 */	"Bad file mode",
-/* 30 */	"File already open",
-/* 31 */	"Disk IO error",
-/* 32 */	"File already exists",
-/* 33 */	"Disk full",
-/* 34 */	"Input past end",
-/* 35 */	"Bad record number",
-/* 36 */	"Bad file name",
-/* 37 */	"Direct statement in file",
-/* 38 */	"Too many files",
-/* 39 */	"File not open",
-/* 40 */	"Syntax error in data",
-0
-};
-
-error(index)
-int	index;
-{
-	extern int _errsym;
-	extern int _erlsym;
-
-	_setline();
-	if( index<0 || index >40 )
-		printf("LINE %d:ERROR %d: Unprintable error\n",_erlsym,index);
-	else 	printf("LINE %d:ERROR %d: %s\n",_erlsym,index,errortable[index]);
-	_errsym= index;
-	_trap();
-}

Some files were not shown because too many files changed in this diff