594 Commits

Author SHA1 Message Date
David Given
2be9641058 Rename branch.
--HG--
branch : unlabeled-2.17.1-branch
2015-06-18 23:39:29 +02:00
em
195fdb4816 Added some xtra output for Henk Schouten's debugger.
--HG--
branch : unlabeled-2.17.1
1985-02-26 15:05:51 +00:00
cvs2hg
a7c6fa501b fixup commit for branch 'unlabeled-2.17.1'
--HG--
branch : unlabeled-2.17.1
1985-02-19 13:41:31 +00:00
keie
408dacc2aa The stacking pattern for ldc C and 4 with highw(c)==0 was incorrect.
The effect was that rand() from libcc/gen always returned
a 0.
1985-02-19 13:41:30 +00:00
bal
7397122695 p_use->u_ext field deleted from showptable() 1985-02-19 11:16:11 +00:00
bal
abcbc93b5d Dependencies for .m files added. 1985-02-19 11:13:13 +00:00
keie
de6ce0fe74 Added a default in the ANY case for system type. 1985-02-19 10:31:20 +00:00
keie
b449b94b48 Removed nascom from linked list. 1985-02-18 23:06:13 +00:00
keie
7d85a4c0b3 Added link to 6805. 1985-02-18 23:01:05 +00:00
bal
66ab97d2b0 bug fixed: lifetime of an item was too short; it should also cover
any live/dead message prior to its initial live-message.
1985-02-18 15:14:22 +00:00
keie
241a7de970 The PDP 11 needs -i, Vax'en ignore it. 1985-02-18 12:45:31 +00:00
keie
41d580c9cf Added some comment. 1985-02-18 01:06:58 +00:00
keie
ec46d547c4 Made use of apc and acc where assuming results
can be run on own system explicit.
1985-02-18 01:03:51 +00:00
keie
daa47964a5 Changed "name of system" into "type of system". 1985-02-18 00:12:12 +00:00
keie
ee63833f41 Basic also needs libc.a. 1985-02-17 22:47:40 +00:00
keie
445d52de66 Moved retar from ret.s to trp.s.
trp.s needed it and is behind ret.s in the library.
When ret.s is loaded, it calls (via unknown) trp.s so
inclusion in trp.s should work.
1985-02-17 22:31:10 +00:00
keie
b82c00e153 Added a line for
loc loc cuu $1==$1, because write.e contained the line
loc 2
loc 2
ciu
and the cg failed to translate.
1985-02-17 22:03:44 +00:00
keie
972692cb1c Further refinement. 1985-02-17 22:01:03 +00:00
em
bbfb511322 Added .align 2. Prevents end of bss to be odd.
Especially important for malloc, it distinguishes between
odd and even word pointers.
1985-02-17 01:12:36 +00:00
cvs2hg
3f3bddef8f fixup commit for tag 'dist2' 1985-02-17 00:57:20 +00:00
keie
9f45dd0650 Added .align 2.
Especially important for malloc.
1985-02-17 00:57:19 +00:00
keie
43a2b60360 *** empty log message *** 1985-02-16 22:09:05 +00:00
keie
14875e6ca5 *** empty log message *** 1985-02-16 16:48:18 +00:00
em
d32de5df93 Now chooses between Vax and Pdp conversion. 1985-02-16 15:58:34 +00:00
keie
eeb944f6e3 The assembler is used for both 2/4 and 4/4. 1985-02-16 15:49:03 +00:00
em
ca28f34c8e *** empty log message *** 1985-02-15 23:13:04 +00:00
em
625c309fa6 1985-02-15 23:12:16 +00:00
em
9f3928cd3a Adapted to -DNOFLOAT. 1985-02-15 23:11:30 +00:00
em
a65f05f29f Adapted to NOFLOAT. 1985-02-15 23:10:04 +00:00
em
6a6a84a274 *** empty log message *** 1985-02-15 23:00:46 +00:00
em
4f80e81ee7 *** empty log message *** 1985-02-15 22:53:13 +00:00
em
eb2b9d0bac Removed one error. 1985-02-15 14:37:35 +00:00
em
792d315beb Program was adapted with NOFLOAT flag. 1985-02-15 14:23:34 +00:00
em
04e454d3c6 Added RCS id.
Adapted to use the NOFLOAT cpp flag.
1985-02-15 14:20:04 +00:00
bal
a1c2dadb2a Compare group (cmp,cmi,cmu,cms,cmf) added as cheap operators. 1985-02-15 13:18:57 +00:00
em
b6381fad79 The cho worked incorrectly, thereby causing the whole test to fail. 1985-02-13 00:41:16 +00:00
em
c9eb48d373 Removed the use of float from the test.
Using int's in sqrt gives the same result.
1985-02-12 23:27:23 +00:00
em
67d635ccd4 1985-02-12 23:07:22 +00:00
em
f37307bc06 A slightly different message. 1985-02-12 23:07:05 +00:00
keie
2a4335787e Adfded RCS id. 1985-02-12 14:37:52 +00:00
keie
1b5278f3d4 As left by Hans v. Staveren. 1985-02-12 14:32:20 +00:00
keie
815b0e0f0f *** empty log message *** 1985-02-12 14:20:30 +00:00
keie
70c000b03e Now using the same em.c as in m68k2/int.
The interpreters are moved from pdp/pdp_int (or some such)
to lib/int22.
1985-02-12 13:11:27 +00:00
keie
f59262745e Initial revision 1985-02-12 12:54:44 +00:00
keie
cc4f8a793a Initial revision 1985-02-12 12:28:49 +00:00
keie
52fee02e94 Adapted to run on 4/4 machines. 1985-02-11 14:33:04 +00:00
keie
fee336890b Placed a few dot on e few i's. 1985-02-11 14:32:02 +00:00
keie
0b6744bb91 The default for any machine is without, double length
integer arithmetic and without floating point.
1985-02-11 11:17:35 +00:00
bal
e704ddc158 restructured. 1985-02-11 10:52:49 +00:00
bal
f7699474b8 The binaries of the phases of ego are now put in a single directory. 1985-02-11 10:07:47 +00:00
bal
6909adbf9c Macros newcflpx and oldcflpx added. 1985-02-11 09:52:11 +00:00
bal
156775643e Include files and declaration of em_flag added. 1985-02-11 09:51:02 +00:00
bal
d41c902b12 Memory allocation/deallocation for extends changed. 1985-02-11 09:48:32 +00:00
keie
43f003e959 Removed a few typos. 1985-02-08 16:54:34 +00:00
keie
ba1e51e914 Deleted a line with a statement unknown to this compiler. 1985-02-08 15:41:19 +00:00
keie
66875f1bde Looks more reasonanle now. 1985-02-08 13:21:23 +00:00
keie
8a7ee2ea50 Now calling trace with the current line number as parameter. 1985-02-08 13:18:26 +00:00
keie
e9850f2691 Improved. 1985-02-08 13:12:51 +00:00
keie
0122bc2dd7 *** empty log message *** 1985-02-07 22:59:50 +00:00
keie
c0085c2dd4 A list without double entries, for the moment supposing
that trp,etc always gets loaded, so will be there when .dvu needs it.
1985-02-07 22:51:12 +00:00
keie
00d75279e7 d2 contains the remainder of dvu i.s.o. d3. 1985-02-07 22:26:11 +00:00
keie
c0d87aaa16 *** empty log message *** 1985-02-07 22:06:32 +00:00
keie
3c7fcfe81a Initial revision 1985-02-07 17:43:43 +00:00
keie
4ff7e05f7e Initial revision 1985-02-07 17:18:06 +00:00
keie
3df42a584c *** empty log message *** 1985-02-07 15:58:40 +00:00
keie
9c93cbdfaa *** empty log message *** 1985-02-07 15:33:13 +00:00
em
1b36afae36 Added a line about the presence of out.std 1985-02-06 21:31:51 +00:00
em
0ff3a17f5e Initial revision 1985-02-06 21:25:27 +00:00
keie
d7abe0e8b6 Initial revision 1985-02-06 21:06:03 +00:00
garde
20986fd6ea monitor calls open, close and ioctl removed. 1985-02-06 16:56:41 +00:00
garde
293dfd2c64 Initial revision 1985-02-06 16:50:52 +00:00
em
e1b8023da1 *** empty log message *** 1985-02-05 14:52:52 +00:00
em
52d0f32e32 Copied from vax2, takes its info on which files
to use in which order from LIST.
1985-02-05 14:52:02 +00:00
em
c8e426ffb8 This one is made with lorder|tsort. 1985-02-05 14:51:17 +00:00
em
b70b6ba980 The first one, Duk's order. 1985-02-05 14:50:24 +00:00
em
c90c70bb84 Now fetching sedf from this directory instead of
from the cg source directory.
1985-02-05 11:44:40 +00:00
keie
a50f8ebe1c Placed the include files in {EM_HOME}/h/bc_..... 1985-02-04 22:18:16 +00:00
keie
da898f1325 *** empty log message *** 1985-02-04 14:31:17 +00:00
keie
1e38fa0573 *** empty log message *** 1985-02-04 14:26:13 +00:00
keie
5a6676cc53 Prevent the existence of pem2[24].p to frustate the ln and thus
the whole exercise.
1985-02-04 02:53:18 +00:00
keie
987ed39adb Added an entry "distr" to make tables1.c and tables1.h. 1985-02-03 23:50:51 +00:00
keie
3d4a5efe99 The creation of the library is now done by the process of creating
the distribution directory.
1985-02-03 23:23:50 +00:00
keie
46f5004866 Tail_em.s.a is now extracted from the RCS directory by the
distribution making process in em/distr2.
1985-02-03 23:21:24 +00:00
keie
df168727a6 The effect of the .distr entry is now done by the
mktree process from /usr/em/distr2.
1985-02-03 23:18:06 +00:00
em
2cc4735151 Added libmon to libraries to be translated. 1985-02-02 18:06:37 +00:00
em
dd7e9436a2 *** empty log message *** 1985-02-01 22:12:31 +00:00
garde
8e154eb826 Many, many improvements made, ususually small ones.
For example: many em-patterns have got alternative code-rules.
1985-02-01 12:51:56 +00:00
keie
ca219d89e9 Now using ../../proto/libg/Makefile. 1985-02-01 12:38:08 +00:00
keie
26999bb517 To avoid conflict while compiling with acc itself the word
size of the target machine is now defined as TEM_WSIZE.
1985-02-01 12:32:46 +00:00
keie
103659cd7b Added an entry to create a doc.pr suitable for printing
on a straightforward line printer.
1985-01-31 22:38:00 +00:00
keie
626ae9760f Added a reference to MES 11 in 11.1.4.4 at the non-local goto. 1985-01-31 15:15:20 +00:00
keie
dcd8451347 1- Zero is deleted as a possible argument to LOI and STI.
Allowing that was an oversight.
2- Message number 10 is reserved for global optimizer output.
3- Message number 11 must be used by GTO destinations.
1985-01-31 15:10:16 +00:00
keie
882906b3c3 Added a few sentences about the capability of ack to
preprocess Pascal programs and one restriction that imposes
on programs using it.
1985-01-31 14:50:15 +00:00
keie
f586956618 Zero is deleted as a possible argument to LOI and STI.
Allowing that was an oversight.
1985-01-31 14:03:56 +00:00
keie
6459b0bf5f Zero is deleted as a possible argument to LOI and STI.
Allowing that was an oversight.
1985-01-31 13:58:09 +00:00
keie
1f56b2aa4c 1 - Changed incorrect execution line for callc/modc
2 - Added several sources to 'pr' entry, for printing.
1985-01-31 10:53:59 +00:00
bal
d1c0d1db13 Bugs fixed for the following patterns:
lol loc 255 and 2  (byte order was wrong)
loc x beq , 0 < x < 128  (was 0 < x < 256)
loc x bne (idem).
These bugs were introduced in version 2.2.
1985-01-30 16:34:14 +00:00
bal
b99ce86e16 register save costs changed: they are now linearly dependent on
the number of registers to be saved (for time).
1985-01-30 15:43:02 +00:00
bal
bec394f7bd Entry for LOI changed from CLASS1 to CLASS12. 1985-01-30 14:49:03 +00:00
bal
db19d06f61 CLASS12 added for the LOI instruction. A "LOI n", n < wordsize,
loads wordsize bytes, not n bytes.
1985-01-30 14:47:49 +00:00
ceriel
e936aea1e1 Added -DCPM to the flags. 1985-01-30 12:37:10 +00:00
bal
31eab814f2 Debugging procedure print_allocs now writes to stderr. 1985-01-30 10:52:33 +00:00
bal
7f9dd27dc8 bug fixed: assemble_allocs() did generate whole_procedure allocations.
These allocations were initialized with a very low profit. Consequently
account_regsave rejected these allocations.
Solution: repl_allocs() updates the al_profits field of the
whole_procedure allocation.
1985-01-30 10:47:47 +00:00
bal
387191a2c7 bug fixed: oldmap(lmap,llength) was sometimes called when no new map
had to be allocated for the current (data-) unit.
1985-01-28 11:38:06 +00:00
em
cf3d3ad287 Also remove all *.e and *.d files when cleaning up. 1985-01-25 16:19:13 +00:00
keie
1bc30e42eb Strings in rom are initialized with usage count 9999.
decstr does not touch these at all.
1985-01-25 14:40:51 +00:00
keie
e271d9bbb8 Strings in rom are initialized with usage count 9999 i.s.o. 1.
String with that usage count are not touched any way at all.
1985-01-25 14:34:50 +00:00
bal
a49f2d23f7 Number of address registers decreased from 5 to 4. 1985-01-25 13:24:12 +00:00
keie
3c5d3c55af Added an entry called distr.
This make the formatted install.pr to be put on the distribution tape.
1985-01-25 11:28:55 +00:00
keie
6d344b6702 The program name is used to set the name
of the file were the contents of data statements are written.
The filename is extracted from the path and the suffix (if present)
is replaced by .d.
1985-01-25 11:04:18 +00:00
keie
8fa5a7b668 The parametrs passed to the call to opnchn when initializing are now
correct string descriptors.
Programs with data statements used to crash with TRAP TYPE 11.
1985-01-25 09:57:04 +00:00
keie
d12fef6c05 The non-flag arguments are now passed by position.
The order is :  (bem) input output program-name.
1985-01-25 09:55:28 +00:00
em
ed1ee8a3b4 Removed test18 because it is in essence a busy loop. 1985-01-24 22:34:31 +00:00
em
3bb153d6bb Added executable files to list of those to cleanup. 1985-01-24 21:27:32 +00:00
em
df08133a04 Added entry "clean" for cleanup. 1985-01-24 21:25:57 +00:00
keie
06087a6bc3 *** empty log message *** 1985-01-24 17:39:54 +00:00
keie
fd4d46036a Added ranlib commends. 1985-01-24 16:16:32 +00:00
keie
1e3ec09984 Some minor changes. 1985-01-24 15:34:23 +00:00
em
58c5d2d8ac Changed the line numbered 19 into a line numbered 190.
This seemed the correct thing to do.
1985-01-24 11:34:12 +00:00
em
410800127c *** empty log message *** 1985-01-24 11:27:36 +00:00
bal
1732114593 bug fixed: the "incr" parameter of sbrk() is a 2-byte integer,
not a 4-byte integer.
1985-01-23 16:31:51 +00:00
bal
66eabbcddf parameter of fscanf changed from "%d" to "%hd" to read a short. 1985-01-23 16:28:58 +00:00
bal
468401cb81 core allocation macros added. 1985-01-23 16:27:47 +00:00
bal
cac6ffd8c2 ovfl_harmful and arrbound_harmful turned into ints 1985-01-23 16:25:29 +00:00
bal
d32d4e6ba0 Interface of tmplocal() changed: second parameter is a long now 1985-01-23 16:23:15 +00:00
bal
5cad6f6aa7 interface with tmplocal() changed: second parameter is a long now. 1985-01-23 16:18:33 +00:00
bal
e46c49e291 bug fixed in get_instrs(): instr should be an int rather than a Celem_t. 1985-01-23 16:16:49 +00:00
bal
5a95c31414 bug fixed in last_mnem(): test on nil-pointer.
bug fixed in try_tail(): add line "if(l1==0||l2==0) return FALSE".
1985-01-23 16:13:57 +00:00
bal
f487f26e00 bug fixed in last_line() : assert(l!=0) should be assert(lines!=0). 1985-01-23 16:12:21 +00:00
bal
e95492dfb0 bug fixed in routine get_ca_lines(): test on nil-pointer. 1985-01-23 16:10:43 +00:00
bal
fefe15a844 init_regcnt renamed initregcnt to avoid name conflict.
bug fixed in routine fits_in(): test on nil-pointer.
routine choose_location(): interface with tmplocal() changed, second
parameter now is a long, so a cast is added.
1985-01-23 16:07:09 +00:00
bal
3d2c33e277 rules for itemtab.h and makeitems added. 1985-01-23 15:50:17 +00:00
bal
2ea3be322d clean_items renamed cleanitems to avoid name conflict.
clean_timeset renamed cleantimeset to avoid name conflict.
bugs fixed: calls to fscanf() with a pointer-to-short as argument
should provide a "%hd" instead of "%d".
1985-01-23 15:45:58 +00:00
garde
a849b751a9 src1 and src2 extended.
Errors in 'pat loc cmi teq' and 'pat loc cmi tne' recovered.
Second stack-pattern for 'pat zlt' and 'pat zge' added.
Patterns for 'lil loc adi sil', 'lil inc sil', 'lil dec sil'
and 'sil lil' added.
1985-01-22 19:55:11 +00:00
em
ea337060ec User defined trap handling routine is called with calls instruction.
A message is printed if there is no routine at all.
1985-01-22 15:20:19 +00:00
em
33c81637db Added `movl r3,ap' to restore the argument pointer before returning
vi jmp (r0).
1985-01-22 13:10:35 +00:00
em
8bdec01d71 Now using opder recommanded by 'lorder'. 1985-01-22 02:17:13 +00:00
keie
7556180ab3 Printf does not return a truth value for failure.
These -incorrect- tests were replaced by calls to ferror.
1985-01-21 23:58:07 +00:00
keie
09000449a4 Added declaration of _newstr. 1985-01-21 23:57:44 +00:00
keie
68644410fb Added correct declaration of salloc, thereby preventing incorrect conversions.
Removed now unnecessary casts from salloc to (char *).
Added a cast to (char *) for the argument of sfree in the second call.
1985-01-21 23:56:10 +00:00
keie
c2e988c3d5 1 - Changed argument from int to unsigned.
2 - The test for a failed malloc is changed from comparison to -1
    to comparison to 0.
1985-01-21 23:54:46 +00:00
keie
d4a597912f Tests for EOF returned by stdio routines need the full int width. 1985-01-21 23:53:41 +00:00
keie
682e5d9b8a Removed casts made superfluous by adding newstr to string.h 1985-01-21 23:53:01 +00:00
keie
f7027ba7e4 Test for EOF returned by stdio routines have to use the full int width. 1985-01-21 23:52:19 +00:00
keie
52a627589a Removed cast made superfluous by added newstr to string.h 1985-01-21 23:51:33 +00:00
keie
5fc9fdf795 Added test for outcome of request for more core.
If no more core is available a fatal error message is produced.
1985-01-21 23:48:06 +00:00
em
08c8edf314 Changed #define's of newlbss of cst_fmt. 1985-01-21 16:40:02 +00:00
em
603f82a578 Bug fix: redefined a Local local causing an INTERNAL ERROR from as. 1985-01-21 15:49:22 +00:00
keie
8f81c858f8 Due to an 8 character identifier length limitation the identifier
"strcompare" is changed into "strcomp".
1985-01-21 14:52:34 +00:00
keie
6a21488f0c Due to an 8 character identifiers limitation calls in EM
the identifier "randomize" was changed into "randomi".
1985-01-21 14:51:29 +00:00
keie
374ac8b21c Due to an 8 character identifiers limitation on EM calls to
"setchannel" were changed into "setchan" and the identifier
"seektable" is replaced by "seektab".
1985-01-21 14:50:12 +00:00
keie
770f321ea8 Changed calls to "setrandom" into calls to "setrand" and
calls to "randomize" inro calls to "randomi" to avoid
problems with routines compiled by C.
1985-01-21 14:48:16 +00:00
keie
decda89fba Added a few /*NOSTRICT*/ comments to indicate awareness of lint complaints. 1985-01-21 14:30:55 +00:00
keie
ff46181ae0 1 - Changed the defintion of a local 's' into 'Sym' to avoid naming conflict.
2 - Added .integer, .Sptr and .cptr at appropiate places to uses of yylval.
3 - Removed unnecessary casts.
4 - Added a few /*NOSTRICT*/ comments to indicate awareness of lint
    complaints.
1985-01-21 14:26:29 +00:00
keie
dbb0d46ac2 1 - Added comment to indicate awareness of lint complaints.
2 - Added/Removed some casts used with core allocation/deallocation.
1985-01-21 14:23:49 +00:00
keie
d53ef52028 Changed the argument of salloc from an int into an unsigned.
Just to shut up lint.
1985-01-21 14:22:07 +00:00
keie
a91ff9e04b Added a declaration of gosublabel. 1985-01-21 14:21:52 +00:00
keie
56a8cd53b6 Added a few comments to indicate awareness of lint complaints. 1985-01-21 14:20:11 +00:00
keie
0c2aee4835 1 - Removed definition of POINTERSIZE.
2 - Defined void as int, some compilers don't know void.
3 - Added declarations of the routines proclabel, salloc, strcpy, strcat, malloc.
1985-01-21 14:18:47 +00:00
garde
cd78a1a27a case 8 and case 6 deleted in switch of function 'prolog' 1985-01-21 14:17:11 +00:00
keie
309bbef3ea Now using a union for YYSTYPE and typed (non-)terminals.
Changed values $n(intvalue) to ival in definition of filelist.
Changed one asp,$n(midparms) into several asp,...SIZE in the definition
that uses MIDSYM.
1985-01-21 14:15:06 +00:00
keie
71cbd2c92f 1 added lint entry.
2 changed calls to cc into $(CC)
1985-01-21 14:14:22 +00:00
em
cb49888304 To have a file preprocessed, it must start with a # in column o1.
The RCSid is replaced to accomplish this.
1985-01-21 12:56:09 +00:00
em
9479f61318 Now using correct RCS identification 1985-01-21 12:47:04 +00:00
em
8d02182e12 Renaming due to 8 character C compiler limit. 1985-01-21 12:37:26 +00:00
em
aef211ad4e Used a correct definition of malloc. 1985-01-21 12:35:53 +00:00
em
a33d0e8e14 Replaced RCSid so that file starts with # in column 0 so it gets preprocessed. 1985-01-21 12:28:59 +00:00
em
4f40987ff0 Corrected type; forgot closing ". 1985-01-21 12:14:59 +00:00
em
ccfa0db0de Removed #define IDFIRST because fmt_id() replaces it. 1985-01-21 12:09:44 +00:00
em
6ac5841c7f Initial revision 1985-01-18 16:06:21 +00:00
em
f9c86fc6f6 Routines are now called with calls instead of jsb. We use ap as argument
pointer register. EM_BSIZE is required to be a constant.
1985-01-18 15:39:07 +00:00
em
a4ca3054f0 Changed label generators and added fmt_id(). 1985-01-18 15:36:51 +00:00
em
10ce06ff2b Routines are called with calls instead of jsb. EM_BSIZE is required to
be a constant.
1985-01-18 15:33:44 +00:00
duk
8d87404836 Initial revision 1985-01-18 14:30:03 +00:00
bal
2d8dcaa2df Initial revision 1985-01-18 09:59:09 +00:00
garde
d8d2068664 Initial revision 1985-01-17 14:31:34 +00:00
duk
e1ef16649c Initial revision 1985-01-17 14:20:52 +00:00
em
6512a304a0 Checking in Martin's changes. 1985-01-17 14:10:27 +00:00
keie
e75b8772ca Added some documentation for the interface between C and Pascal.
This was necessary because the format of Pascal and C procedure
pointers differ from now on.
1985-01-17 13:22:49 +00:00
keie
d19105ef78 Added the test program for the C<=>Pascal interface. 1985-01-17 12:43:51 +00:00
keie
f9b105e07a *** empty log message *** 1985-01-17 12:43:04 +00:00
bal
218ce4596e The EM runtime routines are reentrant now, so the remark about
reentrancy is removed from this file.
1985-01-17 10:39:33 +00:00
bal
8f7a447719 Bug fixed: a0 is changed by call to _brk, so it should be saved & restored. 1985-01-17 10:33:23 +00:00
keie
14a9b13fd3 Added RCS id. 1985-01-11 17:03:53 +00:00
keie
d72ad93216 Allows optional second argument.
This is the name of the destination file. The destination directory
is determined by compare.
1985-01-11 16:46:02 +00:00
keie
081413cfda 1 - Allows 2 arguments, 1 - name of source in current directory.
2 - name of destination file(!path), default arg 1.
2 - Make the necessary dirctory.
3 - runs ranlib if "ar t ... | grep SYMDEF succeeds.
1985-01-11 16:43:56 +00:00
keie
f0d34942e3 Added RCS id. 1985-01-11 16:28:30 +00:00
keie
959138af97 The previous fix produced an array in which the values were one off.
This has been fixed.
1985-01-11 13:42:51 +00:00
keie
c61ea7ee53 *** empty log message *** 1985-01-11 13:20:36 +00:00
keie
22e4268cc7 The recursive call of setp1 initialized elements 0...ASIZE.
This is out of bounds and now altered into 0..ASIZE-1.
1985-01-11 13:17:26 +00:00
keie
e2c5191f0c *** empty log message *** 1985-01-11 13:13:56 +00:00
sater
7f0def8861 RREMOVE section updated. 1985-01-11 09:44:34 +00:00
sater
dac2f97109 extra define added to aid in generation of DO_RREMOVE 1985-01-11 09:42:17 +00:00
sater
3a528a7324 code was added to generate DO_RREMOVE 1985-01-11 09:41:47 +00:00
sater
3534869cb5 code was added to cause generation of DO_RREMOVE in some cases 1985-01-11 09:41:13 +00:00
sater
e9b6045b5a diffs were applied to make default register property at stacking rule
-1 instead of 0.
1985-01-11 09:40:40 +00:00
sater
a1a8fd99a0 Optional register property in stacking rules must be -1 when absent.
Fixed this.
1985-01-10 16:30:09 +00:00
duk
d7fb9edfe2 Maybe some minor changes. 1985-01-10 13:35:39 +00:00
duk
58126396af Added call to trap signals. 1985-01-10 13:24:36 +00:00
duk
55017702e2 Header and section table now allocated statically. 1985-01-10 13:22:04 +00:00
duk
7d312abd59 Inline expansion of index_adjust() and compute_origins().
Section table now allocated statically.
1985-01-10 13:19:47 +00:00
duk
ba826bad5c Added routine to check signals. 1985-01-10 13:17:22 +00:00
sater
4ba6e7a39c *** empty log message *** 1985-01-08 15:34:54 +00:00
sater
f838dd1047 Initial revision 1985-01-08 15:28:26 +00:00
keie
6aaff51b39 *** empty log message *** 1985-01-08 13:52:58 +00:00
duk
f532b58045 Added provisions for copying everything after the string area into the
resulting object file. Because this is most likely symbolic debugging
information, these are parametrized by #ifdef SYMDBUG.
1985-01-08 11:54:57 +00:00
keie
576688fc10 *** empty log message *** 1985-01-08 11:48:43 +00:00
sater
72b83cca59 *** empty log message *** 1985-01-08 09:59:28 +00:00
keie
5edf93d2de *** empty log message *** 1985-01-07 15:54:38 +00:00
keie
dd0951f114 *** empty log message *** 1985-01-07 15:43:50 +00:00
keie
5779a88371 *** empty log message *** 1985-01-07 14:39:27 +00:00
keie
22c95138aa *** empty log message *** 1985-01-07 14:26:46 +00:00
keie
d0268a4ec1 *** empty log message *** 1985-01-07 14:15:47 +00:00
keie
112211eb3b *** empty log message *** 1985-01-07 13:57:25 +00:00
keie
d0444e3a04 15-5-83 EGK
The coercion from rm1 to register contained
                allocate(%[1],GENREG).
                The %[1] here is incorrect and has been removed.
16-5-83         EGK
                The word before the movb was cleared by a xor.
                Now we clear the upper byte after the movb.
                This allows the %[1] to be added to the allocate.
1985-01-07 13:51:36 +00:00
keie
9beb72e69b *** empty log message *** 1985-01-07 13:49:31 +00:00
keie
5fedca22ad *** empty log message *** 1985-01-07 13:37:12 +00:00
keie
b4ad7c46da *** empty log message *** 1985-01-07 13:08:48 +00:00
sater
c2229e5c60 Initial revision 1985-01-04 14:05:25 +00:00
sater
11b3f3aa8a added entries for cg,ncg and cgg 1985-01-04 14:04:10 +00:00
sater
79411cb4b3 added entry for ncg.doc 1985-01-04 13:57:11 +00:00
sater
dd8505531b Initial revision 1985-01-04 13:55:07 +00:00
keie
26f38cada3 *** empty log message *** 1985-01-01 22:33:43 +00:00
keie
c235c1a93d *** empty log message *** 1985-01-01 22:27:02 +00:00
keie
d16efbab98 *** empty log message *** 1985-01-01 22:19:09 +00:00
keie
57115f49cc Take precautions against an already existing march. 1985-01-01 21:32:02 +00:00
keie
5e8a571801 *** empty log message *** 1985-01-01 19:56:08 +00:00
keie
006c4b7a49 *** empty log message *** 1985-01-01 19:42:53 +00:00
keie
5662050ad3 Initial revision 1985-01-01 19:30:24 +00:00
keie
6a08d40d15 1 - Added void.
2 - Data and function pointers have the same size.
1985-01-01 19:24:34 +00:00
keie
fe6eed6c76 Added RCS identification. 1985-01-01 18:35:40 +00:00
keie
0ebd337637 *** empty log message *** 1985-01-01 18:34:12 +00:00
bal
ffb167e8b2 lay-out enhanced; flags (CFLAGS etc.) inherited from central Makefile;
entry for compiling this phase with ack -O created.
1984-12-21 14:41:47 +00:00
keie
6860747f3e Adapted to new tree structure. 1984-12-21 14:23:10 +00:00
sater
18dbfc024e Routine was wrong, leaving things on the stack in the one bit case,
the inclusion of slu in this routine was bogus.
It is never called anyway, so slu is taken out.
1984-12-20 15:17:05 +00:00
keie
e129db8343 1 - Added RCS id.
2 - Used two argument [feature] of install.
1984-12-20 14:26:14 +00:00
keie
b2b1167d7a See the logfile of mach/m68k2/libem/Makefile. 1984-12-20 14:21:35 +00:00
keie
6c9e4c84f0 The definition if the symbols, end, endbss etc, is moved
from a library to a file. This to avoid 2 libraries in this
directory.
1984-12-20 14:13:48 +00:00
keie
6b38714690 Added line for m68k interpreters manual. 1984-12-18 17:26:42 +00:00
keie
80d385c291 *** empty log message *** 1984-12-18 17:22:29 +00:00
keie
37d01caabd 1 - signal did not clear the stack properly.
2 - lseek did not return correct.
1984-12-18 17:12:12 +00:00
keie
7b39ce2cfa Traps now work as documented. 1984-12-18 17:11:35 +00:00
keie
53a88ccd69 1 - Human readable profile and count.
2 - Length of last table is now 64.
1984-12-18 17:09:36 +00:00
keie
2d4614ca5a Profile, count, flow in non-local goto corrected. 1984-12-18 17:08:54 +00:00
keie
246f45c867 1 - Improved line number updating when returning from library routines.
2 - Line 234, 0xD must be #0x1C, crashed at error handling for
    incorrect return size.
1984-12-18 17:07:23 +00:00
keie
b544d3b401 Replaced clr by the faster mov #0, (for d registers). 1984-12-18 17:06:36 +00:00
keie
5f41dcd958 1 - Indexed addressing mode gave unwanted sign extends.
They are replaced by additions.
2 - Added pointer checks.
3 - Completed parametrization of addresses of locals.

1984-12-18 17:04:24 +00:00
keie
9ea83d0838 Finishing profile tables. 1984-12-18 16:59:51 +00:00
keie
45e2eea414 1 - length of last table
2 - human readable profile and count output.
1984-12-18 16:58:30 +00:00
keie
8b60227186 Added pointer checks. 1984-12-18 16:58:11 +00:00
keie
f0a6c2fbcf Altered 1980 in 1984. 1984-12-18 16:57:56 +00:00
keie
8636bd025e Added machines to be sent with the second distribution to the LNTABLES. 1984-12-18 15:28:19 +00:00
keie
4d8c88e7b1 The first version, copied from 6800. 1984-12-18 15:13:56 +00:00
keie
b4faacec8c The first version, copied from 6809. 1984-12-18 15:13:55 +00:00
keie
eb15231cf4 Don't rely on cpp to be in the $PATH, call it from em/lib. 1984-12-18 13:12:30 +00:00
keie
cf947cedd3 Added Ack distribution Makefile names. 1984-12-18 13:12:03 +00:00
keie
e3bf7b5dc7 Removed the need for as in lib/m68k4.
The as in lib/m68k2 is now used directly.
1984-12-17 17:20:57 +00:00
keie
a5e9c4f8d1 *** empty log message *** 1984-12-17 15:52:04 +00:00
keie
8c874d4632 Run $RANLIB if the shell variable is set. 1984-12-17 15:50:02 +00:00
sater
d267037189 *** empty log message *** 1984-12-17 15:13:39 +00:00
sater
ea8e311e5a Changed descr to use recently developed 8080/cg. 1984-12-17 14:36:16 +00:00
keie
3ab2889451 Added 6500 documentation. 1984-12-17 11:38:36 +00:00
keie
c693044013 *** empty log message *** 1984-12-17 11:35:39 +00:00
keie
3b3d3f16b4 Adapted to new library. 1984-12-17 11:21:11 +00:00
keie
4f071008c8 *** empty log message *** 1984-12-17 11:11:37 +00:00
keie
d77b2081c0 Now using LIST. 1984-12-17 11:06:48 +00:00
keie
b097fe72a7 *** empty log message *** 1984-12-17 11:03:13 +00:00
keie
66d68121c8 Added F_DUM(Author of change-- Henry Bal). 1984-12-17 10:45:27 +00:00
keie
5060a9fcd6 *** empty log message *** 1984-12-17 10:44:08 +00:00
bal
523457f6ee Initial revision 1984-12-14 15:57:39 +00:00
bal
6babe9fccd Initial revision 1984-12-14 15:52:15 +00:00
bal
ad815f1061 Initial revision 1984-12-14 15:41:14 +00:00
keie
aa0f76a6cd Removed entries for pmds. 1984-12-14 13:45:42 +00:00
keie
c39e619032 Added Basic library and Revision number. 1984-12-10 15:14:00 +00:00
keie
4a2c2d89a0 Added revision number. 1984-12-10 14:57:51 +00:00
keie
468cdfd3eb 1 - Added Basic library.
2 - Added revision number.
1984-12-10 14:41:49 +00:00
keie
83f3de1555 Initial revision 1984-12-10 14:41:30 +00:00
keie
ef7ea116cd Added Basic library. 1984-12-10 14:29:51 +00:00
keie
f4ab1bb6e6 Initial revision 1984-12-10 14:28:41 +00:00
bal
98989fd9ca Initial revision 1984-12-10 13:36:12 +00:00
keie
9932e38ab2 Removed the definition of the NEEDS variable. 1984-12-10 12:49:56 +00:00
keie
0b9b183085 *** empty log message *** 1984-12-08 00:50:27 +00:00
keie
4cc2986757 This makefile was copied from ../../m68k2/dl.
The now irrelevant entries are removed.
1984-12-08 00:45:55 +00:00
keie
9f850cbb2d Comparing shouldn't stop when one compare fails. 1984-12-08 00:40:04 +00:00
keie
24204bca9f Added entries for pr and opr. 1984-12-08 00:28:16 +00:00
keie
1e651a534a Adapted to new install + compare, added anties for cmp, clean, opr and pr. 1984-12-08 00:17:39 +00:00
keie
1b210a8104 *** empty log message *** 1984-12-07 17:32:33 +00:00
keie
a0f184e3d1 Improved "make pr". 1984-12-07 17:14:43 +00:00
keie
9b6c26ad14 An efficiency change only. 1984-12-07 16:52:09 +00:00
keie
89a757d6f9 Added cmp entry. 1984-12-07 16:45:26 +00:00
keie
518e817345 This one works, the previous one didn't. 1984-12-07 16:42:59 +00:00
keie
f9fa5df654 install now allows a source and destination name. 1984-12-07 16:38:13 +00:00
keie
9e4b9fddab Now use prototype makefile from ../../proto. 1984-12-07 15:22:22 +00:00
ceriel
7f12f20be6 Removed a reference to a non existing Makefile ( in the lib directory). 1984-12-07 15:21:25 +00:00
bal
9019141137 Bug fixed in optimizing two adjacent basic blocks. 1984-12-07 14:19:53 +00:00
keie
af75a28622 Changed access path of em h directory. 1984-12-07 14:01:33 +00:00
keie
c744b44b48 Changed access path of en h directory. 1984-12-07 14:01:11 +00:00
keie
80d4c7ca2f Initial revision 1984-12-07 13:41:58 +00:00
keie
c2d3d6ce4a Initial revision 1984-12-07 10:42:27 +00:00
keie
47f5e79d96 The path lib/ack is changed into lib/descr.
The name ack, used as a file name was a bit overloaded.
1984-12-06 11:08:40 +00:00
ceriel
2c7c97051b Changed so that the installation process will continue if LLgen
is not present yet.
Also added Makefile to the "make pr" entry.
1984-12-06 10:39:28 +00:00
keie
0d5c765070 Repaired a few minor bugs. 1984-12-04 21:57:22 +00:00
keie
01d4011dd6 I hope this version is correct. 1984-12-04 21:48:14 +00:00
keie
7f3328678f Initial revision 1984-12-04 21:38:13 +00:00
sater
d9fe7e9cf0 Initial revision 1984-12-04 15:33:28 +00:00
bal
4e461a9860 Initial revision 1984-12-04 15:04:44 +00:00
bal
3cdaf9f4ba WORDLENGTH now defined in automatically generated file wordlen.h
Generate this file from makewlen.c
1984-12-04 15:04:01 +00:00
bal
0d0e2d2d22 WORDLENGTH now defined in automatically generated file worlen.h 1984-12-04 15:03:22 +00:00
bal
8d659c015f Bug fixed: fill_item() should initialize item->it_desirable to TRUE. 1984-12-04 14:41:20 +00:00
keie
695a914eb3 Added tail_m and tail_ln. 1984-12-04 13:31:03 +00:00
bal
9b72991e27 regsave_cost() return void instead of short. 1984-12-04 13:04:27 +00:00
bal
8db2c12881 regsave_cost() returns void instead of short. 1984-12-04 13:03:49 +00:00
keie
7e8d898bcb Initial revision 1984-12-03 23:20:13 +00:00
keie
550e4d3cee Adapted to use the files in the library directory dedicated to the pmds. 1984-12-03 22:55:26 +00:00
keie
271b83ecb3 Initial revision 1984-12-03 22:02:45 +00:00
bal
ee3ef338db Comment closer ("*/") added to description of getlines(). 1984-12-03 12:12:37 +00:00
ceriel
7e3e49082c Increased MAXPATLEN to 8000. 1984-11-30 11:14:18 +00:00
bal
0778ce4a9a Macros for B_DIST, B_USECNT and B_MARK removed, as these fields are
no longer used.
Declarations of nrinstrs and instrmap marked "extern" to satisfy ack compiler.
1984-11-30 10:52:05 +00:00
bal
7351e38ed5 Declaration of items[] made static to avoid name conflict with ra_items.c
Core allocation macros added.
1984-11-30 10:50:27 +00:00
bal
bac0efbedb Declaration of items[] made static to avoid name conflict with ra.c 1984-11-30 10:49:09 +00:00
bal
302608566a routines getcall(), get_text() and getcc() move from get.c to this file
routines putactuals(), putcall(), and putcc() move from put.c to this file
get.h, put.h, stdio.h, em_mnem.h and em_pseu.h included
1984-11-30 10:30:22 +00:00
bal
c814b9523d several data structures added (moved from types.h).
core allocation macros added.
1984-11-30 10:28:35 +00:00
bal
39891edd12 Declarations for iv and code_info added (moved from types.h).
core allocation macros added.
1984-11-30 10:27:05 +00:00
bal
90df1e5b9a core allocation macros added 1984-11-30 10:25:21 +00:00
bal
1e69d3458c declaration for sym,num and prc added (moved from types.h) 1984-11-30 10:24:21 +00:00
bal
6988358e29 ic.h included before ic_lookup.h 1984-11-30 10:23:34 +00:00
bal
49137da06b Lots of procedures removed (turned into macro in alloc.h or
moved to one specific phase).
1984-11-30 10:15:24 +00:00
bal
594a5bb49b Lots of data structures removed and made local to one specific phase. 1984-11-30 10:14:30 +00:00
bal
e5a282c621 Lots of procedure newxxx() and oldxxx() turned into macros.
Lots of such procedures removed and made local to one specific phase.
1984-11-30 10:12:37 +00:00
bal
4ab54c85a8 As getbblocks() was moved to cf.c, em_flag.h need no longer
be included.; also, the declaration for em_flag[] was removed.
1984-11-30 10:10:41 +00:00
em
7ac377c750 The routine salloc crashed on a 2/4 system.
Malloc was nor declared as "char *", but by default as int.
1984-11-30 00:16:29 +00:00
em
ad104f9164 I removed the unused integer deftype.
Its name collided with an array in symbols.c.
1984-11-29 17:27:00 +00:00
em
1b8f41d3b2 The definitions of lastline, currline and firstline are made
extern in graph.h. The space reserving declaration is made in
graph.c.
1984-11-29 17:26:44 +00:00
bal
b532117b2b -O flag removed 1984-11-29 16:25:08 +00:00
bal
bda5c8409c macros newlvbx and oldlvbx added. 1984-11-29 15:10:11 +00:00
em
f6da80afd8 The first line should contain the distribution library name. 1984-11-29 15:03:41 +00:00
bal
8a15a3f597 macros newlocal() and oldlocal() moved to alloc.h 1984-11-29 14:40:31 +00:00
em
ae1e81adb1 *** empty log message *** 1984-11-29 14:22:02 +00:00
bal
0c0c3b7892 -O flag removed from CFLAGS 1984-11-29 13:33:33 +00:00
bal
b0de601d5b -O removed from CFLAGS 1984-11-29 13:31:22 +00:00
bal
7767012a6e il_aux.h included (which now contains getcall(),putcall() etc.
routines that were peviously in get.c and put.c).
1984-11-29 11:08:15 +00:00
bal
bd06330739 stdio.h included (required by new interface to get.h). 1984-11-29 11:06:23 +00:00
bal
84ed8ee7ef routines getcall(), get_text() and getcc() move from get.c to this file
routines putactuals(), putcall(), and putcc() move from put.c to this file
get.h, put.h, stdio.h, em_mnem.h and em_pseu.h included
1984-11-29 11:03:19 +00:00
bal
f3e35f5432 routine getbblocks (plus its auxiliary routines) moved from get.c
to this file; core allocation macros newcfbx() and oldcfbx() added.
1984-11-29 10:51:16 +00:00
bal
edcb838b98 newnametable() move from alloc.c to this file,
get_ca_lines moved from get.c to this file,
em_pseu.h and em_mes.h included (needed by get_ca_lines).
1984-11-29 10:31:44 +00:00
bal
c17a52c09d stdio.h included (required by new get.h interface),
macros's newlocal() and oldlocal() added, replacing routines in
alloc.c with same name.
1984-11-29 10:25:21 +00:00
bal
0032ebfeda getbblocks(), getcall(), getcc() and get_text() removed,
get_ca_lines() removed,
curinp,lastbid,lastlabid exported
getbyte(),getshort(),getoff(),read_line and getlines() exported.
1984-11-29 10:18:53 +00:00
bal
582a0cc2aa getbblocks() removed (now local to CF phase),
getcall(),getcc() and get_text removed (now local to IL),
get_ca_lines() removed (now local to CA),
current input file "f" renamed "curinp" and exported,
getbyte (macro), getshort() and getoff() exported
read_line() and getlines() exported,
lastbid and lastlabid exported.
1984-11-29 10:15:23 +00:00
bal
dd5ceb7b97 putcall an putcc removed,
curoutp, outbyte,outshort and outoff exported.
1984-11-29 10:11:37 +00:00
bal
470826f0c9 putcall and putcc removed (make local to IL phase)
current output file renamed "curoutp" and exported
outbyte, outshort and outoff exported.
1984-11-29 10:09:15 +00:00
bal
1cb39eff7e cleaned up 1984-11-28 09:26:44 +00:00
em
90c1dc7c06 Installed basic compiler in ACK tree. 1984-11-27 23:59:28 +00:00
em
39c37e9571 1 - Added RCS identification.
2 - Changed the file name parseparams.c into parsepar.c, the original
    name was too long for RCS under BSD4.1
3 - Adapted to ACK standard Makefile format(cmp,install,...)
4 - Included more dependencies.
1984-11-27 23:53:31 +00:00
em
3ceada5482 Added basic.doc. 1984-11-27 23:51:07 +00:00
em
3cab14d65e Added RCS identification. 1984-11-27 23:48:38 +00:00
em
7efc02574d *** empty log message *** 1984-11-27 23:46:32 +00:00
em
9f872a7ea0 Removed conflict between rcs_id in basic.yacc and lex.c. 1984-11-27 23:41:46 +00:00
em
ea5498cd99 Now using ACK default tmp directory from em_path.h. 1984-11-27 23:21:41 +00:00
em
455cd930ec Added RCS identification. 1984-11-27 23:13:28 +00:00
em
335d55ff4a The version of basic copied from Martin Kerstens directory. 1984-11-27 22:23:55 +00:00
em
4301dfb7bf The version of basic copied from Martin Kerstens directory. 1984-11-27 22:11:59 +00:00
bal
502a7a86af Initial revision 1984-11-27 16:16:36 +00:00
bal
30ca0afe49 cleaned up 1984-11-27 15:52:23 +00:00
bal
ad383cbdc0 stack_change was renamed stack_chg 1984-11-27 15:43:14 +00:00
bal
165965eadc Initial revision 1984-11-27 15:40:13 +00:00
bal
a6d53a6bcd "ivars" was renamed "ivvars" to avoid name conflict with sr_expr.c 1984-11-27 15:30:34 +00:00
bal
df200afd46 cleaned up 1984-11-27 15:04:04 +00:00
bal
9c3a416acd cleaned up; dependecies added. 1984-11-27 14:53:00 +00:00
bal
9e38bfa060 cleaned up. 1984-11-27 14:25:02 +00:00
bal
2d6eff961f cleaned up. use CC. 1984-11-27 14:23:20 +00:00
bal
0981b8857b getoff() moved to front (was called before being defined)
declaration char *pseudo[] changed to char *pseudo[5] to suppress warining
1984-11-27 14:21:55 +00:00
bal
69bdddd9ba "cc" replaced by $(CC) 1984-11-27 12:59:18 +00:00
keie
4a36e98f5c Treatment of -R flag is altered.
1 - if recognized by mapflag and not by Ack internally no
    complaint is given.
2 - If recognized by both mapflag and internally:
       -R....-.... : effectuate only mapflag command
       otherwise   : effectuate both.
3 - If not recognized at all, give a warning message and
    pass the flag to the linker.
1984-11-26 17:14:17 +00:00
keie
3c2c03165b This manual page was not included in the first distribution.
This version is hacked from the VU-Pascal distribution.
1984-11-26 15:56:57 +00:00
bal
c4b4a08720 Initial revision 1984-11-26 15:15:07 +00:00
bal
6d481ce4d6 Initial revision 1984-11-26 15:04:22 +00:00
bal
6a9e49f683 Initial revision 1984-11-26 14:51:59 +00:00
bal
1833451151 Initial revision 1984-11-26 14:35:32 +00:00
bal
9f778655a6 Initial revision 1984-11-26 14:14:55 +00:00
bal
f01e1431b0 Initial revision 1984-11-26 14:07:17 +00:00
bal
415ae7e922 Initial revision 1984-11-26 13:58:05 +00:00
bal
7b798175ad Initial revision 1984-11-26 13:43:22 +00:00
sater
5481dd47a9 added documentation for the fmt_id and fmt_ilb macros 1984-11-26 11:09:11 +00:00
sater
0a00b80726 Added support for the fmt_id and fmt_ilb macros 1984-11-26 10:50:46 +00:00
sater
6a4dc794a2 In the RREMOVE section of this file, the field e_con of the
expression union was used in stead of e_reg.
Fixed. Checked all other occurrances, are correct.
1984-11-20 16:56:26 +00:00
sater
7c07f91e1c The constant 512 slipped in instead of BUFSIZ.
Changed.
1984-11-20 10:22:12 +00:00
keie
36c1f227ea Added a check for non-ascii characters in the description files. 1984-11-15 14:24:35 +00:00
ceriel
1fe1bc8c09 Forgotten to close a file. This is corrected. 1984-11-12 18:05:20 +00:00
keie
4e7f357a26 Added rcs identification. 1984-11-08 12:08:31 +00:00
keie
9f776924d6 Added a P for a specification of lal on line 51.
This missing letter caused lal -1 to be mapped on the opcode
for lal 0.
1984-11-08 11:11:31 +00:00
keie
cb84476be0 Added a check. Minis & shorties need an N or P argument. 1984-11-08 11:09:56 +00:00
bal
d07b17ca5c The routine con_float now generates a dummy floating point constant
and gives a warning, instead of generating a fatal error + abort.
1984-11-06 12:50:21 +00:00
bal
58c679c94c Patterns for floating point instruction and for LFR 8 and RET 8 added.
Each such instruction now results in a call to a library routine.
At present, all these routines generate an Illegal EM Instruction trap,
but anyone wishing to implement floating point for the 6502 can
do so without changing the back end table.
1984-11-06 12:47:26 +00:00
em
e2e78ccd0a The line with the user message for failure missed the call to echo. 1984-11-06 10:02:25 +00:00
bal
0d5a4693a7 make install also make a tail_mon now. 1984-11-05 15:58:11 +00:00
bal
95dd252a5b arguments for asld changed. several libraries added. 1984-11-05 15:29:48 +00:00
bal
87c5817216 program for be is {LIB}/cg instead of {LIB}/be 1984-11-05 15:13:20 +00:00
keie
b6cfa32faa *** empty log message *** 1984-11-05 15:11:19 +00:00
bal
b9ebdc1a07 em_head renamed head_em; em_tail renamed tail_em
installs tail_em rather than comparing it
1984-11-05 15:06:49 +00:00
em
73b651052e Added an example with segment prefixes. 1984-11-05 15:02:32 +00:00
em
6913efe107 Adapted to new tree shape for libraries and binaries. 1984-11-05 14:42:17 +00:00
em
3e7b7990f2 *** empty log message *** 1984-11-05 12:05:46 +00:00
em
9c66801439 *** empty log message *** 1984-11-05 11:55:15 +00:00
keie
2976b590af The flag -LIB was missing in the call to the shell-procedure
compmodule. Thus the generated libraries could not be effectively
used by our assembler/linker.
1984-11-05 11:37:23 +00:00
bal
a837112d99 Negation of negative operand with inc/dec added in certain cases.
Don't know effect for sure, author has left.
Added rcsid.
1984-11-02 11:09:46 +00:00
bal
13685d4bc0 Initial revision 1984-11-02 10:13:29 +00:00
sater
45887f2b72 Name of error file was wrong, it was the runtime error file instead
of the compile time error file.
1984-11-01 09:30:36 +00:00
ceriel
4d48191bcc The input routine used to skip space. This "feature" has been removed
because it is also used to read strings, in which space is significant.
1984-10-31 15:26:09 +00:00
keie
fedaa3267a Adapted to make use of ../../compare and ../../install. 1984-10-26 12:58:15 +00:00
keie
3d4feae541 Initial revision 1984-10-26 12:54:35 +00:00
keie
88b487cd7b Adapted to make use of ../../compare and ../../install. 1984-10-26 11:48:51 +00:00
keie
90a899316e Initial revision 1984-10-26 11:48:13 +00:00
keie
08632dc7bd *** empty log message *** 1984-10-26 11:47:56 +00:00
keie
ae27a86236 Adapted to make use of ../../compare and ../../install. 1984-10-26 11:04:10 +00:00
keie
fd0066f3a6 *** empty log message *** 1984-10-26 11:01:40 +00:00
keie
1092994a09 Initial revision 1984-10-26 11:00:08 +00:00
ceriel
da7230a8eb Running makedepend again gave a difference. 1984-10-26 10:31:22 +00:00
ceriel
1ca93d7aa1 removed the "depend" emtry, added a "distr" entry, which should be used
before a distribution is made.
Also added the -DNORCSID flag to the lint-options.
1984-10-26 10:25:55 +00:00
keie
9d8dd3f989 Adapted to use ../../install and ../../compare and hide knowledge
about final destination of libraries.
1984-10-26 10:25:32 +00:00
ceriel
c5345aaaba Added a "distr" entry, which will be propagated to the src directory. 1984-10-26 10:24:48 +00:00
keie
fd23647c1c Adapted to make use of ../../compare. 1984-10-26 10:21:18 +00:00
keie
4724e96474 Adapted to make use of ../../install and ../../compare. 1984-10-26 10:20:29 +00:00
keie
8df0cf17d6 Initial revision 1984-10-26 10:20:28 +00:00
keie
37730ff9ca *** empty log message *** 1984-10-26 10:19:56 +00:00
keie
a1e7cc26f4 *** empty log message *** 1984-10-26 10:12:57 +00:00
keie
137fa9ebce Adapted to use install in ../.. 1984-10-25 14:28:56 +00:00
keie
0cacc96ed8 Now using the compare script in ../.. 1984-10-25 14:28:19 +00:00
keie
4a20e17a9b Initial revision 1984-10-25 14:28:18 +00:00
keie
3bfc57ecd0 *** empty log message *** 1984-10-25 14:24:43 +00:00
keie
86d96452a3 Altered the installation procedure.
The libraries etc. are now installed in lib/m68k2 using install in ../..
1984-10-25 14:22:53 +00:00
keie
e88028dcb9 Altered to make use of ../../install and ../../compare. 1984-10-25 14:19:58 +00:00
keie
1e1fc36653 Initial revision 1984-10-25 14:19:57 +00:00
keie
cdebe97db8 *** empty log message *** 1984-10-25 14:15:27 +00:00
keie
08545984f4 Now making use of ../../install and ../../compare. 1984-10-25 14:10:00 +00:00
keie
b8e156100f Adapted to make use of compare in ../.. 1984-10-25 11:40:16 +00:00
keie
9109aaaada Adapted to make use of install and compare in ../.. 1984-10-25 11:39:39 +00:00
keie
b51fa518be *** empty log message *** 1984-10-25 11:39:38 +00:00
keie
c2b1975015 Adapted to make use of install and compare in ../.. 1984-10-25 11:27:08 +00:00
keie
ca89e47aa4 *** empty log message *** 1984-10-25 11:25:22 +00:00
keie
26ba8cc8fd Removed the definition of LIBDIR, it is superfluous. 1984-10-25 11:16:31 +00:00
keie
c94c590501 Adapted to make use of install and compare in ../.. 1984-10-25 11:16:30 +00:00
keie
38a943d27a Initial revision 1984-10-25 11:15:20 +00:00
keie
916b1b016e Moved the include directory from mach/ibm/include to lib/ibm/include. 1984-10-25 11:00:06 +00:00
keie
a72cc54578 Adapted to use compare in ../.. 1984-10-25 10:46:32 +00:00
keie
9b6418c324 Adapted to compare in ../.. 1984-10-25 10:45:22 +00:00
keie
e03e8c7607 Initial revision 1984-10-25 10:45:21 +00:00
keie
2cb8aae438 *** empty log message *** 1984-10-23 15:29:53 +00:00
keie
533d2bb940 Initial revision 1984-10-23 15:29:30 +00:00
keie
828b4d62c9 We have only one copy of the script for compare and install now
they are present in ../..
1984-10-23 15:14:17 +00:00
sater
7e31dee840 changed EM_WSIZE to TEM_WSIZE 1984-10-23 15:10:15 +00:00
sater
a4a5fc4bfa changed references to EM_?SIZE to TEM_?SIZE 1984-10-23 15:04:24 +00:00
sater
62f42d18f7 changed EM_WSIZE to TEM_WSIZE 1984-10-23 15:02:03 +00:00
sater
be9b72e273 added -h and -c flags, to change names of tables.h and tables.c respectively
now also takes an argument instead of stdin.
EM_BSIZE is now compulsory again.
Constants EM_?SIZE are passed on to cg with a T prepended (T for target)
1984-10-23 13:39:15 +00:00
sater
79ea4bdea3 Changed to use -h flag to cgg and better way of preserving old tables.h
if not changed. Nice huh, Andy?
1984-10-23 13:29:41 +00:00
sater
ab0db1c5fb added rcsid(again). Who took that away? 1984-10-16 13:45:16 +00:00
sater
5d5a09a5d0 added code to generate code for ACK assembler.
Works if ACK_ASS is defined.
1984-10-16 13:31:44 +00:00
ceriel
9eb72b6ee8 Had forgotten to initialise the line number on which a nonterminal
symbol occurred first.
1984-10-12 14:19:34 +00:00
ceriel
f1a2fdaa43 No changes 1984-10-11 21:35:58 +00:00
ceriel
bdc67c3332 The former version gave a fatal error message at the first undefined
nonterminal. The new version checks all nonterminals
1984-10-11 10:35:01 +00:00
ceriel
a33d4cdbba The routine findpath did not work. It used the same static buffer for
several calls. Now it uses alloc.
1984-10-09 11:43:19 +00:00
em
94e069fde1 Initial revision 1984-10-09 10:36:29 +00:00
ceriel
c89acc55c7 added "#ifdef NORCSID" 1984-10-09 10:16:33 +00:00
ceriel
d068cf64b3 Added some comments and removed some Lint complaints 1984-10-09 10:13:46 +00:00
ceriel
774ce1ecc3 Initial revision 1984-10-09 09:47:14 +00:00
ceriel
dd1bcb3f60 The routine LLmessage did not insert tokens properly.
This is corrected now.
1984-10-09 09:33:37 +00:00
ceriel
317ab99ecf Changed RCSid 1984-10-08 17:11:03 +00:00
ceriel
474d9d6e0f Added RCSid. 1984-10-08 16:21:03 +00:00
ceriel
a9a0339ec1 Adapted the libpath routine to use EM_DIR from ../../../h/em_path.h 1984-10-08 15:58:23 +00:00
ceriel
27dcc7efc6 Added entry for LLgen. 1984-10-08 15:20:54 +00:00
ceriel
58b1dd5b6d Initial revision 1984-10-08 15:19:18 +00:00
ceriel
82d5bad777 Added entry for LLgen documentation. 1984-10-08 15:00:23 +00:00
ceriel
a7c0f30307 Initial revision 1984-10-08 14:51:38 +00:00
ceriel
de22c41214 Initial revision 1984-10-08 14:24:19 +00:00
ceriel
a21f936651 Initial revision 1984-10-08 14:14:53 +00:00
keie
6cbb37051b Initial revision 1984-10-08 14:11:42 +00:00
keie
550d1fa79e New installation procedure:
1 - New place for binaries and libraries in the ACK tree.
2 - The ranlib action is moved to ../../install which tries it at
    every action.
1984-10-08 14:09:28 +00:00
bal
46dc90f366 bug fixed: generate "add.l #65536,a1" rather than "lea 65536(a1),a1".
The latter form is only generated for constants that fit in a word.
1984-10-08 12:45:38 +00:00
keie
8958cb6faf Altered the test path lib/n_ack into the normal path ACK_PATH. 1984-10-05 15:07:47 +00:00
keie
b5fa0675b6 Added a priority associated with each phase. Paths with the highest
total priority have preference.
1984-10-05 13:34:38 +00:00
keie
8e680a6467 1 - Added some debugging for linker flags.
2 - Setting of NEEDS and RTS is moved to main.c.
3 - Added recognition of -Rphase:[-]number for dynamic priority setting.
1984-10-05 13:31:40 +00:00
keie
c4434ccbce 1 - Most flags used by ack itself are now also passed to the phases
for recognition with mapflag.
2 - A few bugs are removed in connection with argument passing to the
    linker (unrecognized flags and libraries).
3 - The setting of RTS, HEAD and TAIL is done directly after the
    path determination for each file.
1984-10-05 13:28:56 +00:00
keie
1b251d6ab0 Removed the defines needed by util/ack/em_pc.c.
These defaults are now provided in lib/ack/fe.
1984-10-04 11:11:30 +00:00
keie
5376af0d04 1 - Added RCS identification.
2 - Removed the default for compiler and error file pathname.
    These are now always supplied by the callee.
1984-10-04 11:08:42 +00:00
keie
00bd62d942 Corrected a small bug in the pc mapflags. 1984-10-04 10:54:11 +00:00
keie
0abe5e195e 1- Added RCS identification.
2- The pathnames of the Pascal compiler and Compile time-error file
   are now always explicitly passed to em_pc.
1984-10-04 10:47:03 +00:00
keie
4c0687f68b Altered to reflect the changes in em_path.h.
Now dynamically concatenes EM_DIR and error path.
1984-10-04 10:42:13 +00:00
keie
42be23b631 Altered the description of EM_HOME in em_path.h to that of
EM_DIR.
1984-10-02 16:24:59 +00:00
sater
13d6e6815e added missing cast at call to regsave, in ms_gto case 1984-10-02 11:17:57 +00:00
sater
92aecb175c changed definition of myalloc to extern 1984-10-02 10:31:06 +00:00
sater
a3f62d0255 added external definition for myalloc() 1984-10-02 10:30:44 +00:00
keie
080555fffd Bug removed: the trailing zero at the end of a growstring was not
explicitly written in doassign(trans.c).
Only luck kept the program together.
1984-10-01 17:42:56 +00:00
keie
083dccb299 Nill pointers are not allowed in CSA descriptors any more. 1984-10-01 16:05:17 +00:00
keie
1bea1c6883 Null pointer are not allowed any more for in-bound indeces in the CSA
table.
1984-10-01 14:54:09 +00:00
keie
6da6316680 Initial revision 1984-09-25 16:33:15 +00:00
keie
523134a5dc Added National semiconductor assembler. 1984-09-25 16:32:45 +00:00
em
abb1fce8ff 1 - A few minor syntactic changes.
2 - Altered the description of strings as initializers. (sequence of U1's).
1984-09-25 11:06:29 +00:00
keie
6010f7b584 Made the buffer long enough for the machine state on most machines. 1984-09-24 15:18:20 +00:00
keie
a88bca3670 Initial revision 1984-09-24 15:18:07 +00:00
keie
95510f8b4c Initial revision 1984-09-24 14:10:23 +00:00
em
2c4b17e464 Compile-time option GLOBAL_OPT defined. If set, the resulting
peephole optimizer will be suitable for optimizing the output of
the global optimizer. In particular, it doesn't change the register
messages.
1984-09-14 10:25:07 +00:00
keie
c97e1a7bc2 1 - The prop keyword with is flags is now obsolete. Its function is
taken over by several other keywords: stdin, stdout, prep, optimizer,
    combiner and linker.
2 - The search order is changed. First {EM}/lib/{M}/descr, then
    {EM}/lib/ack/{M}, finally {M}.
1984-09-13 14:40:09 +00:00
keie
c93761cadc The t_do bits are not set by this module. The t_next entry is used
to see whether the scan for this phase is already done.
t_do is now set in add_inputs(files.c).
1984-09-13 14:35:02 +00:00
keie
aa4bae59e0 1 - The t_do flags is now set by add_inputs(files.c).
2 - Recognize the fact that it is possible to start a combiner without
    input files.
3 - Removed -d flag. Overflow for -v (>2) now ends up in debug.
    -v may be followed by a number indicating the increment.
1984-09-13 11:07:46 +00:00
keie
527726167a 1 - The outfile entry is only used when the output file must not be thrown
away.
2 - If a combiner has no named input file (only libs+flags) then issue
    a warning message and make up a name.
1984-09-13 11:04:00 +00:00
bal
68a6231d11 pem did not generate a register message for var-parameters of
array- or record type. The routine "treewalk" is modified.
It generates a register message for every var-parameter, even
if it has its noreg-flag set.
1984-09-12 13:21:43 +00:00
bal
ebed9d4804 unlk a6 added to restr(). 1984-09-11 15:44:14 +00:00
keie
5895758914 Added ego, basic and callname conventions. 1984-09-10 17:34:04 +00:00
keie
3c300d3e1c No comment. 1984-09-10 16:51:02 +00:00
keie
8443ef3f8d Combiners (ego, linkers) now use a list of path's(ack.h) to indicate
their input files.
Unmatched flags are now sent to the linker.
1984-09-10 16:48:57 +00:00
keie
1188f0e810 1 - A transformation is succesfull when
a - a stopsuffix is indicated and met,
    b - the last transformation is included in the transformation path.
2 - Maintains a 'cash' of best paths for all transformation to be executed.
1984-09-10 16:46:13 +00:00
keie
1dba1f5328 The input file names of the linker are to be found in a different place. 1984-09-10 16:45:12 +00:00
keie
20100c69c7 1 - added keywords callname and outfile. See manual.
2 - multiple combiners are allowed now.
3 - A different search mechanism is used for finding descriptor files.
1984-09-10 16:42:55 +00:00
keie
c504e2e22a 1 - callname recognition is moved to rmach.c.
2 - The overall scheme is altered.
	first, all input files are processed until a combining phase is met.
	then, all the combining phases are executed, the resulting files
	are again processed until a combiner (or final) phase is met.
3 - The EM_DIR shell variable can be used to set ack's idea of the EM
    home directory.
1984-09-10 16:37:11 +00:00
keie
31f96c6850 1 - The names of temporary files are now Ack'hex''unique'.'suffix'.
'hex' is the pid of the current invocation of ack in hex.
    'unique' is a tail unique to this invocation.
2 - The outfile field is used to indicate default naming, can be ovrrriden
    by the -o flag.
3 - Added handling for phases with multiple inputs (ego, linker).
1984-09-10 16:33:03 +00:00
keie
6eda6ac320 The role of the combiner is -partially- assumed by the linker.
Linker arguments are now part of the transformation structure.
Temp file nameing is changed.
1984-09-10 16:30:47 +00:00
keie
384bb7f6c4 Naming of the tempname is changed (see files.c). 1984-09-10 16:29:37 +00:00
keie
4c265a7cc6 Initial revision 1984-09-03 13:49:40 +00:00
sater
2bf16c5b2f Variable nregvars had a name clash with the array nregvar[] in the
file tables.c. That was different in the 8'th character (!"#$%&'()_).
These variables should actually be static.
1984-08-23 17:07:53 +00:00
keie
0d48be448f We do not use the missing " trick anymore.
The root directory of the EM tree is in the name EM_DIR, the
root directory for tempfiles is in TMP_DIR.
All other path's are relative to EM_DIR.
1984-08-23 13:33:11 +00:00
keie
f6b59970f6 The ACK tree on the vax has as default machine 'vax2'. 1984-08-23 13:27:14 +00:00
keie
1d463f136a The missing trailing " trick is now also used for TMP_DIR. 1984-08-23 13:26:44 +00:00
keie
773f0aa626 The ms_gto is added. This is a trick used to indicate procedures
jumped to with gto.
1984-08-23 13:25:44 +00:00
keie
621f9f4ea9 *** empty log message *** 1984-08-23 13:20:59 +00:00
keie
198da9e822 Initial revision 1984-08-23 13:18:14 +00:00
keie
5db647e661 Initial revision 1984-08-23 13:00:32 +00:00
sater
3744019c53 increased MAXNODES in small memory mode 1984-08-23 12:25:24 +00:00
sater
5689e6ab64 Increased the amount of information passed through error routines
to printf. The routine badassert, running on a 2/4 machine lost it's
last argument on the way.
Anyone know of a better way to solve this problem?
1984-08-17 15:35:28 +00:00
keie
4759d84bdd Added comment. 1984-08-17 14:57:31 +00:00
keie
c2f189c855 Added RCS identification. 1984-08-17 14:44:24 +00:00
sater
822b1c557c Revised to include rcsid of pattern file in binary opt 1984-08-16 16:08:39 +00:00
sater
744bc6845d enlarged string table in big memory case 1984-08-16 13:34:59 +00:00
sater
ce098c78cb added patterns to prevent stacking in *p++ cases 1984-08-15 16:05:54 +00:00
sater
d1b3479a55 added patterns to remove some more dup's 1984-08-15 16:04:19 +00:00
sater
e682a47599 added patterns for inc/dec/adp of local and external offsetted
This makes the getc() macro from C very efficient, among others
1984-08-15 14:31:54 +00:00
sater
eebcf1b22c added patterns to remove as many dup's as possible. 1984-08-15 14:23:42 +00:00
sater
b31c9f4a4a added definition of malloc().
Program crashed on 2/4 machines
1984-08-08 10:54:04 +00:00
sater
e41876f32a reworked patterns for autoincrement stores, now that peephole optimizer
rearranged it.
1984-08-07 10:22:49 +00:00
sater
eff0f36a5d added patterns for *p++ local and external p
added pattern to remove some badly placed dups
1984-08-03 16:37:15 +00:00
sater
6f8e6faa1f added setcc calls to some incrementing ops
added patterns for indirect local and external increments
added patterns for loe ine and such
1984-08-03 16:33:40 +00:00
sater
59fa458a20 removed some superfluous patterns.
Were special cases not needed with the general case.
1984-08-03 13:16:59 +00:00
sater
ff9d23e4ec A move from a nonreg to a reg did not have the effect that all
registers clashing with the destination were erased. Erase added.
1984-08-02 16:31:25 +00:00
keie
93672962a1 The name "unix" is now predefined for preprocessor usage. 1984-08-02 14:13:04 +00:00
sater
afc577b6c7 When building the parameter list for a pf-call, the line number
for the exchanges war remembered at the wrong time.
This caused:
	foo(3,'string')
to cause an external identifier for the string. Fixed.
1984-07-31 09:39:35 +00:00
keie
fe922d190d String initializer handling is changed.
Strings are now considered to be sequences of xU1's.
No alignment is done before or after the string other than the
alignment done for names and segment type switches.
1984-07-30 14:42:33 +00:00
bal
6e519cf02b bug fixed: added "fprintf(codefile,""rts\n");" to restr() 1984-07-30 12:47:54 +00:00
bal
f2e52892ac bugs fixed (syntax errors, patterns moved to front,
"ldl ldl adp sdl sti" requires DATAREG instead of ANY1 on
fakestack)
1984-07-30 11:16:41 +00:00
bal
233b4aeee4 patterns added to generate autoincrement and to generate
a "move X,d0" instead of a "move X,-(sp)" before storing into X
1984-07-27 16:53:19 +00:00
sater
d90f26a8c5 added rcsid 1984-07-27 10:28:48 +00:00
sater
0b07016f0b added PR* routines 1984-07-26 13:15:21 +00:00
sater
5894adfd67 Changed procedure prolog to use PR* routines. 1984-07-26 13:05:22 +00:00
keie
14a3683f85 *** empty log message *** 1984-07-23 11:49:00 +00:00
sater
eebc753306 removed all calls to blm~ from table
duplicated some patterns for in[lc] to deal with de[lc]
extra rule for adi 2 to deal with source1 cleverly
1984-07-23 11:29:59 +00:00
sater
978dd0191a removed blm.s, not used by table anymore 1984-07-20 16:20:54 +00:00
sater
5b20e4fed2 edited to make reentrant, no more globals in use 1984-07-20 16:20:28 +00:00
sater
c2f383773d added copyright notice 1984-07-20 13:54:36 +00:00
sater
ebc7a50d8f added rcsid
adapted to new archive updating style, with LIST and march and all that
1984-07-20 11:32:47 +00:00
sater
98c1d6868f Initial revision 1984-07-20 11:25:31 +00:00
sater
c99e75a01b added rcsid 1984-07-20 11:25:18 +00:00
sater
bb4210de79 added copyright notice 1984-07-20 11:20:12 +00:00
sater
b410ca7f8c removed copyright notice, wasn't really *written* by us. 1984-07-20 11:07:12 +00:00
sater
25a8908e26 added rcsid 1984-07-20 11:03:31 +00:00
sater
597d25decd Initial revision 1984-07-20 10:44:57 +00:00
sater
eb823929a1 A sti 8 of a regdef8 token went into panic mode. Fixed. 1984-07-20 10:32:48 +00:00
sater
ef248ee65e to check long >= 0 or long < 0 it is enough to test high order word. Added.
anding and oring of long constants is much better now
dvu 2 and rmu 2 by positive constants is now done inline.
1984-07-19 16:50:27 +00:00
sater
e20ab23a4b added rcsid 1984-07-19 15:03:30 +00:00
sater
5fb767966b Initial revision 1984-07-19 15:01:43 +00:00
sater
3b991bd1ce Archive made with archiver in environment ASAR if set, arch otherwise 1984-07-19 14:55:12 +00:00
sater
15e9fd8cd5 removed #ifdef UNTESTED around logical instructions without arguments,
seems they were used ( which implicitly means tested ) after all
1984-07-19 14:03:49 +00:00
sater
73d8f05fb5 Initial revision 1984-07-19 13:52:18 +00:00
sater
3ca5d2fcb6 added rcsid 1984-07-19 13:34:12 +00:00
sater
8483d153f2 changed name from comparchentry to compmodule 1984-07-19 13:22:36 +00:00
sater
b95f4c8bfd Initial revision 1984-07-19 13:20:15 +00:00
sater
801226a45c old code put back, now register handling is different again
actually old code never was removed, due to a misunderstanding
about comment conventions.
1984-07-19 13:12:03 +00:00
sater
f16fdf4e7f makefile adapted to new style archive handling, RCS and all that 1984-07-19 13:11:36 +00:00
sater
d082a2b0a2 a setl instruction was changed to a setd
setl was just plain wrong
1984-07-19 13:09:53 +00:00
sater
d5aa088876 Initial revision 1984-07-19 12:51:00 +00:00
bal
8defe7ce53 rcsid added 1984-07-19 11:50:29 +00:00
bal
69584eb0ca Initial revision 1984-07-19 11:50:28 +00:00
sater
1eade4ac9d Initial revision 1984-07-19 11:50:18 +00:00
bal
da4092cbdf New implementation of GTO (without register save masks)
several optimizations added
1984-07-19 11:15:28 +00:00
bal
c1fd560106 New implementation of GTO (without register save masks) 1984-07-19 11:07:15 +00:00
bal
17caf7129e rcsid added
several optimizations added
1984-07-19 11:02:06 +00:00
bal
a520ccdbbc rcsid added
clr.w -(sp) generated in prolog if register save mask is 0
1984-07-19 10:57:19 +00:00
bal
eeeff10a51 Initial revision 1984-07-19 10:03:10 +00:00
bal
c75693c35a Initial revision 1984-07-19 09:37:24 +00:00
sater
e1aef765a0 added patterns for ldc adi/ldc sbi with zero high order word
added patterns for *--p with p register
added patterns to generate cmpb to compare two bytes.
added patterns to use regvar to index global array
added patterns for lol inl
added patterns for external pointer increment/decrement
1984-07-18 16:47:24 +00:00
sater
2943d957bb The patterns to change a cii to cuu when dealing with a known positive
quantity was technically wrong. Changed to generate a cui.
1984-07-18 15:54:25 +00:00
sater
ec992b001c added definition of index, to keep compiler happy 1984-07-18 14:14:46 +00:00
sater
8304ce5eae removed recursive comments
removed NC with sti rules
added rule to reverse operands of adi 2
added rule to convert loc sbi to loc adi
added loc slu -> loc sli rule
added local++ rule
added rule for asping xsource2
added rule for csb when nothing on stack
1984-07-18 13:39:24 +00:00
sater
8af636a3c1 added rcsid
changed instruction label format to allow more than 256 procedures
1984-07-18 13:32:11 +00:00
sater
3169067979 changed instruction label format to allow more than 256 procedures 1984-07-18 13:28:01 +00:00
sater
a241500a91 added rcsid
converted to recognize and generate new 0%o format
1984-07-18 13:14:18 +00:00
sater
0473678491 added patterns for unsigned shifting
added patterns to delay additive operations until after multiplicative,
  this can be useful for some register machines
1984-07-18 11:05:28 +00:00
sater
fc59a0d703 Improved error handling on unterminated strings 1984-07-18 11:04:58 +00:00
232 changed files with 303 additions and 61495 deletions

View File

@@ -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
*
*/

View File

@@ -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 ) \
)

View File

@@ -1,40 +0,0 @@
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)
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) $? >$@
regadd.$(SUF): regadd.doc
$(NROFF) $(MS) $? >$@
install.$(SUF): install.doc
$(NROFF) $(MS) $? >$@
pcref.$(SUF): pcref.doc
$(NROFF) $? >$@
peep.$(SUF): peep.doc
$(NROFF) $(MS) $? >$@
val.$(SUF): val.doc
$(NROFF) $? >$@
toolkit.$(SUF): toolkit.doc
$(NROFF) $(MS) $? >$@
install cmp:
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

View File

@@ -1,419 +0,0 @@
.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

1837
doc/cg.doc

File diff suppressed because it is too large Load Diff

View File

@@ -1,317 +0,0 @@
.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.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 the two
pointer types 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)
Two different pointer types exist: pointers to data and
pointers to functions.
The latter type is twice as large as the former.
Pointers to functions use the same format as Pascal procedure
parameters, thereby allowing C to use Pascal procedure
parameters and vice-versa.
The extra information passed indicates the scope level of the
procedure.
.PT (b)
The size of pointers to data is a multiple of
(or equal to) the size of an \fIint\fP.
.PT (c)
The following relations exist for the sizes of the types
mentioned:
.br
.ti +5
\fIchar<=short<=int<=long\fP
.PT (d)
Objects of type \fIchar\fP use one 8-bit byte of storage,
although several bytes are allocated sometimes.
.PT (e)
All sizes are in multiples of bytes.
.PT (f)
Most EM implementations use 4 bytes for floats and 8 bytes
for doubles, but exceptions to this rule occur.
.IE
.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 data pointers the \fIlong\fP is converted to an
\fIint\fP before the operation is performed.
.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 size of a data pointer.
Conversions altering the size of the address expression are not allowed.
.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.
Note that pointers to functions have
twice the size of pointers to data.
When converting data pointers to an integral type or vice-versa,
the pointers is seen as an unsigned with the same size a data-pointer.
When converting function pointers to anything else the static link part
of the pointer is discarded,
the resulting value is treated as if it were a data pointer.
When converting a data pointer or object of integral type to a function pointer
a static link with the value 0 is added to complete the function pointer.
.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).

View File

@@ -1,28 +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
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

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -1,756 +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 object is the wordsize unless
the indicator is followed by an integer specifying the
object'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 (").
Semecolon'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.
Strings are padded with zeroes up to a multiple of the wordsize.
.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.
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 objects are aligned on a multiple of their size or the wordsize
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.
.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.
.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

View File

@@ -1,164 +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.
If the index is out of bounds or if the fetched pointer is 0,
then fetch the default instruction pointer.
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

View File

@@ -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.

File diff suppressed because it is too large Load Diff

View File

@@ -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") ;
}

View File

@@ -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

View File

@@ -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.

View File

@@ -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

View File

@@ -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 -

File diff suppressed because it is too large Load Diff

View File

@@ -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() ;
}

View File

@@ -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-- ;
}

View File

@@ -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.

View File

@@ -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

View File

@@ -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" }

View File

@@ -1,61 +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.
.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.

File diff suppressed because it is too large Load Diff

View File

@@ -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.

View File

@@ -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

View File

@@ -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.

View File

@@ -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.

View File

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

View File

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

View File

@@ -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

View File

@@ -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.

View File

@@ -1,622 +0,0 @@
.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_HOME in em_path.h should be altered to
specify the root
directory for the Compiler Kit distribution on your system.
The trailing " in the definition of EM_HOME is intentionally
missing!
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_HOME/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_HOME/mach/vax2/cg and
EM_HOME/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_HOME/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.

File diff suppressed because it is too large Load Diff

View File

@@ -1,505 +0,0 @@
.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.

View File

@@ -1,132 +0,0 @@
.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.

View File

@@ -1,896 +0,0 @@
.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.

View File

@@ -1,302 +0,0 @@
.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

View File

@@ -1,752 +0,0 @@
.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.

View File

@@ -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 m 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

View File

@@ -1,44 +0,0 @@
# $Header$
d=../../..
h=$d/h
PEM=$d/lib/pc_pem
PEM_OUT=$d/lib/pc_pem.out
HEAD=$h/em_spec.h $h/em_pseu.h $h/em_mnem.h $h/em_mes.h $h/pc_size.h
LDFLAG=-i
all: pem pem.out
pem.out: pem.m
apc -mint --t -o pem.out pem.m
pem: pem.m
apc $(LDFLAG) -o pem pem.m
# pem.m is system dependent and may NOT be distributed
pem.m: pem.p $(HEAD)
-rm -f pem.m
-if apc -I$h -O -c.m pem.p ; then :; else \
acc -o move move.c ; move ; rm -f move move.[oskm] ; \
fi
cmp: pem
cmp pem $(PEM)
install: pem
cp pem $(PEM)
distr:
ln pem.p pem22.p ; apc -mpdp -c.m -I$h pem22.p ; rm -f pem22.p
ln pem.p pem24.p ; apc -mvax2 -c.m -I$h pem24.p ; rm -f pem24.p
clean:
-rm -f pem pem.out *.[os] *.old
pr:
@pr pem.p
xref:
xref pem.p^pr -h "XREF PEM.P"
opr:
make pr ^ opr

View File

@@ -1,20 +0,0 @@
/* A program to move the file pem??.m to pem.m */
/* Called when "apc pem.p" fails. It is assumed that the binary
file is incorrect in that case and has to be created from the compact
code file.
This program selects the correct compact code file for each combination
of word and pointer size.
It will return an error code if the move failed
*/
main(argc) {
char copy[100] ;
if ( argc!=1 ) {
printf("No arguments allowed\n") ;
exit(1) ;
}
sprintf(copy,"cp pem%d%d.m pem.m", EM_WSIZE, EM_PSIZE) ;
printf("%s\n",copy) ;
return system(copy) ;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,34 +0,0 @@
# $Header$
all: testC testI
testI:
# int t1.p; em
int t2.p; em
int t3.p; em e.out f1 f2 f3 f4 f5 f6
int t4.p; em
int t5.p; em
int tstenc.p; em
int tstgto.p; em
rm -f e.out f?
testC:
apc t1.p; a.out
apc t2.p; a.out
apc t3.p; a.out f1 f2 f3 f4 f5 f6
apc t4.p; a.out
apc t5.p; a.out
apc tstenc.p; a.out
apc tstgto.p; a.out
rm -f a.out f?
install cmp:
clean:
-rm -f [ea].out f?
opr:
make pr | opr
pr:
@pr t[12345].p tstenc.p

View File

@@ -1,226 +0,0 @@
{ $Header$ }
procedure machar (var ibeta , it , irnd , ngrd , machep , negep , iexp,
minexp , maxexp : integer ; var eps , epsneg , xmin , xmax : real ) ;
var trapped:boolean;
procedure encaps(procedure p; procedure q(i:integer)); extern;
procedure trap(i:integer); extern;
procedure catch(i:integer);
const underflo=5;
begin if i=underflo then trapped:=true else trap(i) end;
procedure work;
var
{ This subroutine is intended to determine the characteristics
of the floating-point arithmetic system that are specified
below. The first three are determined according to an
algorithm due to M. Malcolm, CACM 15 (1972), pp. 949-951,
incorporating some, but not all, of the improvements
suggested by M. Gentleman and S. Marovich, CACM 17 (1974),
pp. 276-277. The version given here is for single precision.
Latest revision - October 1, 1976.
Author - W. J. Cody
Argonne National Laboratory
Revised for Pascal - R. A. Freak
University of Tasmania
Hobart
Tasmania
ibeta is the radix of the floating-point representation
it is the number of base ibeta digits in the floating-point
significand
irnd = 0 if the arithmetic chops,
1 if the arithmetic rounds
ngrd = 0 if irnd=1, or if irnd=0 and only it base ibeta
digits participate in the post normalization shift
of the floating-point significand in multiplication
1 if irnd=0 and more than it base ibeta digits
participate in the post normalization shift of the
floating-point significand in multiplication
machep is the exponent on the smallest positive floating-point
number eps such that 1.0+eps <> 1.0
negeps is the exponent on the smallest positive fl. pt. no.
negeps such that 1.0-negeps <> 1.0, except that
negeps is bounded below by it-3
iexp is the number of bits (decimal places if ibeta = 10)
reserved for the representation of the exponent of
a floating-point number
minexp is the exponent of the smallest positive fl. pt. no.
xmin
maxexp is the exponent of the largest finite floating-point
number xmax
eps is the smallest positive floating-point number such
that 1.0+eps <> 1.0. in particular,
eps = ibeta**machep
epsneg is the smallest positive floating-point number such
that 1.0-eps <> 1.0 (except that the exponent
negeps is bounded below by it-3). in particular
epsneg = ibeta**negep
xmin is the smallest positive floating-point number. in
particular, xmin = ibeta ** minexp
xmax is the largest finite floating-point number. in
particular xmax = (1.0-epsneg) * ibeta ** maxexp
note - on some machines xmax will be only the
second, or perhaps third, largest number, being
too small by 1 or 2 units in the last digit of
the significand.
}
i , iz , j , k , mx : integer ;
a , b , beta , betain , betam1 , one , y , z , zero : real ;
begin
irnd := 1 ;
one := ( irnd );
a := one + one ;
b := a ;
zero := 0.0 ;
{
determine ibeta,beta ala Malcolm
}
while ( ( ( a + one ) - a ) - one = zero ) do begin
a := a + a ;
end ;
while ( ( a + b ) - a = zero ) do begin
b := b + b ;
end ;
ibeta := trunc ( ( a + b ) - a );
beta := ( ibeta );
betam1 := beta - one ;
{
determine irnd,ngrd,it
}
if ( ( a + betam1 ) - a = zero ) then irnd := 0 ;
it := 0 ;
a := one ;
repeat begin
it := it + 1 ;
a := a * beta ;
end until ( ( ( a + one ) - a ) - one <> zero ) ;
{
determine negep, epsneg
}
negep := it + 3 ;
a := one ;
for i := 1 to negep do begin
a := a / beta ;
end ;
while ( ( one - a ) - one = zero ) do begin
a := a * beta ;
negep := negep - 1 ;
end ;
negep := - negep ;
epsneg := a ;
{
determine machep, eps
}
machep := negep ;
while ( ( one + a ) - one = zero ) do begin
a := a * beta ;
machep := machep + 1 ;
end ;
eps := a ;
{
determine ngrd
}
ngrd := 0 ;
if(( irnd = 0) and((( one + eps) * one - one) <> zero)) then
ngrd := 1 ;
{
determine iexp, minexp, xmin
loop to determine largest i such that
(1/beta) ** (2**(i))
does not underflow
exit from loop is signall by an underflow
}
i := 0 ;
betain := one / beta ;
z := betain ;
trapped:=false;
repeat begin
y := z ;
z := y * y ;
{
check for underflow
}
i := i + 1 ;
end until trapped;
i := i - 1;
k := 1 ;
{
determine k such that (1/beta)**k does not underflow
first set k = 2 ** i
}
for j := 1 to i do begin
k := k + k ;
end ;
iexp := i + 1 ;
mx := k + k ;
if ( ibeta = 10 ) then begin
{
for decimal machines only }
iexp := 2 ;
iz := ibeta ;
while ( k >= iz ) do begin
iz := iz * ibeta ;
iexp := iexp + 1 ;
end ;
mx := iz + iz - 1 ;
end;
trapped:=false;
repeat begin
{
loop to construct xmin
exit from loop is signalled by an underflow
}
xmin := y ;
y := y * betain ;
k := k + 1 ;
end until trapped;
k := k - 1;
minexp := - k ;
{ determine maxexp, xmax
}
if ( ( mx <= k + k - 3 ) and ( ibeta <> 10 ) ) then begin
mx := mx + mx ;
iexp := iexp + 1 ;
end;
maxexp := mx + minexp ;
{ adjust for machines with implicit leading
bit in binary significand and machines with
radix point at extreme right of significand
}
i := maxexp + minexp ;
if ( ( ibeta = 2 ) and ( i = 0 ) ) then maxexp := maxexp - 1 ;
if ( i > 20 ) then maxexp := maxexp - 3 ;
xmax := one - epsneg ;
if ( xmax * one <> xmax ) then xmax := one - beta * epsneg ;
xmax := ( xmax * betain * betain * betain ) / xmin ;
i := maxexp + minexp + 3 ;
if ( i > 0 ) then begin
for j := 1 to i do begin
xmax := xmax * beta ;
end ;
end;
end;
begin
trapped:=false;
encaps(work,catch);
end;

View File

@@ -1,677 +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
}
program t1(input,output);
{ This program can be used to test out PASCAL compilers }
const
rcsversion='$Header$';
ONE=1; TWO=2; TEN=10; FIFTY=50; MINONE=-1;
#ifndef NOFLOAT
RR1=1.0; RR1H=1.5; RR2=2.0; RR3=3.0; RR4=4.0; RRMINONE=-1.0;
#endif
yes=true; no=false;
kew='q';
#ifndef NOFLOAT
eps = 2.0e-7; { This constant is machine dependent }
#endif
type wavelength = (red,blue,yellow,purple,white,gray,pink,black,fuchia,maple,
violet,darkred,darkblue,darkyellow,darkwhite,darkpink,darkblack);
ww2= 1939..1945;
#ifndef NOFLOAT
tp2= record c1:char; i,j:integer; p:boolean; x:real end;
#else
tp2= record c1:char; i,j:integer; p:boolean end;
#endif
single= array [0..0] of integer;
spectrum= set of wavelength;
np = ^node;
node = record val:integer; next: np end;
var t,pct,ect:integer;
i,j,k,l,m:integer;
#ifndef NOFLOAT
x,y,z:real;
#endif
p,q,r:boolean;
c1,c2,c3:char;
sr1,sr2,sr3: 1939..1945;
bar: packed array[0..3] of 0..255;
color,hue,tint: wavelength;
grat:spectrum;
a1: array [-10..+10] of integer;
#ifndef NOFLOAT
a2: array [ww2] of real;
#endif
a3: array[wavelength] of boolean;
a4: array[(mouse,house)] of char;
a5: array[50..52,(bat,cat),boolean,ww2] of integer;
a6: packed array[0..10,0..3,0..3] of char;
r1,r2: tp2;
#ifndef NOFLOAT
r3: packed record c1:char; i,j:integer; p:boolean; x:real end;
#else
r3: packed record c1:char; i,j:integer; p:boolean end;
#endif
colors: set of wavelength;
beasts: set of (pig,cow,chicken,farmersdaughter);
bits: set of 0..1;
p1: ^integer;
p2: ^tp2;
p3: ^single;
p4: ^spectrum;
head,tail: np;
procedure e(n:integer);
begin
ect := ect + 1;
writeln(' Error', n:3,' in test ', t)
end;
function inc(k:integer):integer; begin inc := k+1 end;
{************************************************************************}
procedure tst1;
{ Arithmetic on constants }
begin t:=1; pct := pct + 1;
if 1+1 <> 2 then e(1);
if ONE+ONE <> TWO then e(2);
if ONE+MINONE <> 0 then e(3);
if ONE-TWO <> MINONE then e(4);
if TWO-MINONE <> 3 then e(5);
if TWO*TWO <> 4 then e(6);
if 100*MINONE <> -100 then e(7);
if 50*ONE <> 50 then e(8);
if 50*9 <> 450 then e(9);
if 50*TEN <> 500 then e(10);
if 60 div TWO <> 30 then e(11);
if FIFTY div TWO <> 25 then e(12);
if -2 div 1 <> -2 then e(13);
if -3 div 1 <> -3 then e(14);
if -3 div 2 <> -1 then e(15);
if ((1+2+3) * (2+3+4) * (3+5+5)) div 2 <> ((3 * ((5+3+2)*10)+51)*6) div 6
then e(16);
if (1000*2 + 5*7 + 13) div 8 <> 2*2*2*2*4*4 then e(17);
if (1 * 2 * 3 * 4 * 5 * 6 * 7) div 5040 <>
5040 div 7 div 6 div 5 div 4 div 3 div 2 then e(18);
if -(-(-(-(-(-(-(-(-(1))))))))) <> -1 then e(19);
if -1 -1 -1 -1 -1 <> -5 then e(20);
if - 1 <> -(((((((((((((1))))))))))))) then e(21);
if -4 * (-5) <> 20 then e(22);
if (9999-8) mod 97 <> 309 mod 3 then e(23);
if 2<1 then e(24);
if 2 <= 1 then e(25);
if 2 = 3 then e(26);
if 2 <> 2 then e(27);
if 2 >= 3 then e(28);
if 2 > 3 then e(29);
if 2+0 <> 2 then e(30);
if 2-0 <> 2 then e(31);
if 2*0 <> 0 then e(32);
if 0+2 <> 2 then e(33);
if 0-2 <> -2 then e(34);
if 0*2 <> 0 then e(35);
if 0 div 1 <> 0 then e(36);
if -0 <> 0 then e(37);
if 0 - 0 <> 0 then e(38);
if 0 * 0 <> 0 then e(39);
end;
{************************************************************************}
procedure tst2;
{ Arithmetic on global integer variables }
begin t:=2; pct := pct + 1;
i:=1; j:=2; k:=3; l:=4; m:=10;
if i+j <> k then e(1);
if i+k <> l then e(2);
if j-k <> -i then e(3);
if j*(j+k) <> m then e(4);
if -m <> -(k+k+l) then e(5);
if i div i <> 1 then e(6);
if m*m div m <> m then e(7);
if 10*m <> 100 then e(8);
if m*(-10) <> -100 then e(9);
if j div k <> 0 then e(10);
if 100 div k <> 33 then e(11);
if i+j*k+l+m mod j + 50 div k <> 27 then e(12);
if j*k*m div 6 <> 10 then e(13);
if (k>4) or (k>=4) or (k=4) then e(14);
if (m<j) or (m<=j) or (m=j) then e(15);
if k <> i+j then e(16);
if j < i then e(17);
if j <= i then e(18);
if j = i then e(19);
if j <> j then e(20);
if i >= j then e(21);
if i > j then e(22);
end;
#ifndef NOFLOAT
{************************************************************************}
procedure tst3;
{ Real arithmetic }
begin t:=3; pct := pct + 1;
if abs(1.0+1.0-2.0) > eps then e(1);
if abs(1e10-1e10) > eps then e(2);
if abs(RR1+RR1H+RR2+RR3+RR4+RRMINONE-10.5) > eps then e(3);
if abs(1.0e-1 * 1.0e1 - 100e-2) > eps then e(4);
if abs(10.0/3.0*3.0/10.0-100e-2) > eps then e(5);
if 0.0e0 <> 0 then e(6);
if abs(32767.0-32767.0) > eps then e(7);
if abs(1.0+2+5+3.0e0+5.0e+0+140e-1-30.000)/100 > eps then e(8);
if abs(-1+(-1)+(-1.0)+(-1e0)+(-1e+0)+(-1e-0) + ((((6)))) ) > eps then e(9);
x:=1.50; y:=3.00; z:= 0.10;
if abs(5*y*z-x) > eps then e(10);
if abs(y*y*y/z*x-405) > eps then e(11);
x:=1.1; y:= 1.2;
if y<x then e(12);
if y <= x then e(13);
if y = x then e(14);
if x <> x then e(15);
if x >= y then e(16);
if x >y then e(17);
end;
#endif
{************************************************************************}
procedure tst4;
{ Boolean expressions }
begin t:=4; pct := pct + 1;
if not yes = true then e(1);
if not no = false then e(2);
if yes = no then e(3);
if not true = not false then e(4);
if true and false then e(5);
if false or false then e(6);
p:=true; q:=true; r:=false;
if not p then e(7);
if r then e(8);
if p and r then e(9);
if p and not q then e(10);
if not p or not q then e(11);
if (p and r) or (q and r) then e(12);
if p and q and r then e(13);
if (p or q) = r then e(14);
end;
{************************************************************************}
procedure tst5;
{ Characters, Subranges, Enumerated types }
begin t:=5; pct := pct + 1;
if 'q' <> kew then e(1);
c1 := 'a'; c2 := 'b'; c3 := 'a';
if c1 = c2 then e(2);
if c1 <> c3 then e(3);
sr1:=1939; sr2:=1945; sr3:=1939;
if sr1=sr2 then e(4);
if sr1<>sr3 then e(5);
color := yellow; hue := blue; tint := yellow;
if color = hue then e(6);
if color <> tint then e(7);
end;
{************************************************************************}
procedure tst6;
{ Global arrays }
var i,j,k:integer;
begin t:=6; pct := pct + 1;
for i:= -10 to 10 do a1[i] := i*i;
if (a1[-10]<>100) or (a1[9]<>81) then e(1);
#ifndef NOFLOAT
for i:=1939 to 1945 do a2[i]:=i-1938.5;
if (abs(a2[1939]-0.5) > eps) or (abs(a2[1945]-6.5) > eps) then e(2);
#endif
color := yellow;
a3[blue] := true; a3[yellow] := true;
if (a3[blue]<>true) or (a3[yellow]<>true) then e(3);
a3[blue] := false; a3[yellow] := false;
if (a3[blue]<>false) or (a3[yellow]<>false) then e(4);
a4[mouse]:='m'; a4[house]:='h';
if (a4[mouse] <> 'm') or (a4[house]<>'h' ) then e(5);
for i:=1939 to 1945 do a5[51,bat,false,i]:=300+i;
if a5[51,bat,false,1940] <> 2240 then e(6);
for i:=50 to 52 do a5[i,cat,true,1943]:=200+i;
if (a5[50,cat,true,1943] <> 250) or (a5[52,cat,true,1943] <> 252) then e(7);
for i:= -10 to 10 do a1[i]:= 0;
for i:= 0 to 10 do a1[i div 2 + i div 2]:= i+1;
if(a1[0]<>2) or (a1[5]<>0) or (a1[8]<>10) then e(8);
for i:= 0 to 10 do
for j:= 0 to 3 do
for k:= 0 to 3 do
if ( (i+j+k) div 2) * 2 = i+j+k then a6[i,j,k]:='e' else a6[i,j,k]:='o';
if (a6[2,2,2]<>'e') or (a6[2,2,3]<>'o') or (a6[0,3,1]<>'e') then e(9);
end;
#ifndef NOFLOAT
{************************************************************************}
procedure tst7;
{ Global records }
begin t:=7; pct := pct + 1;
r1.c1:='x'; r1.i:=40; r1.j:=50; r1.p:=true; r1.x:=3.0;
c1:='a'; i:=0; j:=0; p:=false; x:=100.0;
if (r1.c1<>'x') or (r1.i<>40) or (r1.p<>true) or (r1.x<>3.0) then e(1);
r2:=r1;
if (r2.c1<>'x') or (r2.i<>40) or (r2.p<>true) or (r2.x<>3.0) then e(2);
i:=r1.i; p:=r1.p; c1:=r1.c1; x:=r1.x;
if (c1<>'x') or (i<>40) or (p<>true) or (x<>3.0) then e(3);
r3.c1:='x'; r3.i:=40; r3.j:=50; r3.p:=true; r3.x:=3.0;
if (r3.c1<>'x') or (r3.i<>40) or (r3.p<>true) or (r3.x<>3.0) then e(4);
end;
#else
{************************************************************************}
procedure tst7;
{ Global records }
begin t:=7; pct := pct + 1;
r1.c1:='x'; r1.i:=40; r1.j:=50; r1.p:=true;
c1:='a'; i:=0; j:=0; p:=false;
if (r1.c1<>'x') or (r1.i<>40) or (r1.p<>true) then e(1);
r2:=r1;
if (r2.c1<>'x') or (r2.i<>40) or (r2.p<>true) then e(2);
i:=r1.i; p:=r1.p; c1:=r1.c1;
if (c1<>'x') or (i<>40) or (p<>true) then e(3);
r3.c1:='x'; r3.i:=40; r3.j:=50; r3.p:=true;
if (r3.c1<>'x') or (r3.i<>40) or (r3.p<>true) then e(4);
end;
#endif
{************************************************************************}
procedure tst8;
{ Global sets }
begin t:=8; pct := pct + 1;
colors := [];
colors := colors + [];
if colors <> [] then e(1);
colors := colors + [red];
if colors <> [red] then e(2);
colors := colors + [blue];
if colors <> [red,blue] then e(3);
if colors <> [blue,red] then e(4);
colors := colors - [red];
if colors <> [blue] then e(5);
beasts := [chicken] + [chicken,pig];
if beasts <> [pig,chicken] then e(6);
beasts := [] - [farmersdaughter] + [cow] - [cow];
if beasts <> [] then e(7);
bits := [0] + [1] - [0];
if bits <> [1] then e(8);
bits := [] + [] + [] -[] + [0] + [] + [] - [0];
if bits <> [] then e(9);
if not ([] <= [red]) then e(10);
if [red] >= [blue] then e(11);
if [red] <= [blue] then e(12);
if [red] = [blue] then e(13);
if not ([red] <= [red,blue]) then e(14);
if not ([red,blue] <= [red,yellow,blue]) then e(15);
if not ([blue,yellow] >= [blue] + [yellow]) then e(16);
grat := [ red,blue,yellow,purple,white,gray,pink,black,fuchia,maple,
violet,darkred,darkblue,darkyellow,darkwhite,darkpink,darkblack];
if grat<>[red,blue,yellow,purple,white,gray,pink,black,fuchia,maple,violet,
darkred,darkblue,darkyellow,darkwhite,darkpink,darkblack] then e(17);
if not ([10] <= [10]) then e(18);
end;
{************************************************************************}
procedure tst9;
{ Global pointers }
begin t:=9; pct := pct + 1;
new(p1); new(p2); new(p3); new(p4);
p1^ := 1066;
if p1^ <> 1066 then e(1);
p2^.i := 1215;
if p2^.i <> 1215 then e(2);
p3^[0]:= 1566;
if p3^[0] <> 1566 then e(3);
p4^ := [red];
if p4^ <> [red] then e(4);
end;
{************************************************************************}
procedure tst10;
{ More global pointers }
var i:integer;
begin t:=10; pct := pct + 1;
head := nil;
for i:= 1 to 100 do
begin new(tail); tail^.val:=100+i; tail^.next :=head; head:= tail end;
if (tail^.val<>200) or (tail^.next^.val<>199) then e(1);
if tail^.next^.next^.next^.next^.next^.next^.next^.next^.val<> 192 then e(2);
tail^.next^.next^.next^.val := 30;
if tail^.next^.next^.next^.val <> 30 then e(3);
end;
{************************************************************************}
procedure tst11;
{ Arithmetic on local integer variables }
var i,j,k,l,m:integer;
begin t:=11; pct := pct + 1;
i:=1; j:=2; k:=3; l:=4; m:=10;
if i+j <> k then e(1);
if i+k <> l then e(2);
if j-k <> -i then e(3);
if j*(j+k) <> m then e(4);
if -m <> -(k+k+l) then e(5);
if i div i <> 1 then e(6);
if m*m div m <> m then e(7);
if 10*m <> 100 then e(8);
if m*(-10) <> -100 then e(9);
if j div k <> 0 then e(10);
if 100 div k <> 33 then e(11);
if i+j*k+l+m mod j + 50 div k <> 27 then e(12);
if j*k*m div 6 <> 10 then e(13);
if (k>4) or (k>=4) or (k=4) then e(14);
if (m<j) or (m<=j) or (m=j) then e(15);
if k <> i+j then e(16);
end;
#ifndef NOFLOAT
{************************************************************************}
procedure tst12;
{ Real arithmetic on locals }
var x,y,z:real;
begin t:=12; pct := pct + 1;
x:=1.50; y:=3.00; z:= 0.10;
if abs(5*y*z-x) > eps then e(10);
if abs(y*y*y/z*x-405) > eps then e(11);
x:=1.1; y:= 1.2;
if y<x then e(12);
if y <= x then e(13);
if y = x then e(14);
if x <> x then e(15);
if x >= y then e(16);
if x >y then e(17);
end;
#endif
{************************************************************************}
procedure tst13;
{ Boolean expressions using locals }
var pp,qq,rr:boolean;
begin t:=13; pct := pct + 1;
if not yes = true then e(1);
if not no = false then e(2);
if yes = no then e(3);
if not true = not false then e(4);
if true and false then e(5);
if false or false then e(6);
pp:=true; qq:=true; rr:=false;
if not pp then e(7);
if rr then e(8);
if pp and rr then e(9);
if pp and not qq then e(10);
if not pp or not qq then e(11);
if (pp and rr) or (qq and rr) then e(12);
if pp and qq and rr then e(13);
if (pp or qq) = rr then e(14);
end;
{************************************************************************}
procedure tst14;
{ Characters, Subranges, Enumerated types using locals }
var cc1,cc2,cc3:char;
sr1,sr2,sr3: 1939..1945;
color,hue,tint: (ochre,magenta);
begin t:=14; pct := pct + 1;
if 'q' <> kew then e(1);
cc1 := 'a'; cc2 := 'b'; cc3 := 'a';
if cc1 = cc2 then e(2);
if cc1 <> cc3 then e(3);
sr1:=1939; sr2:=1945; sr3:=1939;
if sr1=sr2 then e(4);
if sr1<>sr3 then e(5);
bar[0]:=200; bar[1]:=255; bar[2]:=255; bar[3]:=203;
if (bar[0]<>200) or (bar[1]<>255) or (bar[2]<>255) or (bar[3]<>203) then e(6);
color := ochre; hue:=magenta; tint := ochre;
if color = hue then e(7);
if color <> tint then e(8);
end;
{************************************************************************}
procedure tst15;
{ Local arrays }
type colour = (magenta,ochre);
var aa1: array [-10..+10] of integer;
#ifndef NOFLOAT
aa2: array [ww2] of real;
#endif
aa3: array[colour] of boolean;
aa4: array[(mouse,house,louse)] of char;
aa5: array[50..52,(bat,cat),boolean,ww2] of integer;
aa6: packed array[0..10,0..3,0..3] of char;
i,j,k:integer;
begin t:=15; pct := pct + 1;
for i:= -10 to 10 do aa1[i] := i*i;
if (aa1[-10]<>100) or (aa1[9]<>81) then e(1);
#ifndef NOFLOAT
for i:=1939 to 1945 do aa2[i]:=i-1938.5;
if (abs(aa2[1939]-0.5) > eps) or (abs(aa2[1945]-6.5) > eps) then e(2);
#endif
aa3[magenta] := true; aa3[ochre] := true;
if (aa3[magenta]<>true) or (aa3[ochre]<>true) then e(3);
aa3[magenta] := false; aa3[ochre] := false;
if (aa3[magenta]<>false) or (aa3[ochre]<>false) then e(4);
aa4[mouse]:='m'; aa4[house]:='h'; aa4[louse]:='l';
if (aa4[mouse] <> 'm') or (aa4[house]<>'h' ) or (aa4[louse]<>'l') then e(5);
for i:=1939 to 1945 do aa5[51,bat,false,i]:=300+i;
if aa5[51,bat,false,1940] <> 2240 then e(6);
for i:=50 to 52 do aa5[i,cat,true,1943]:=200+i;
if (aa5[50,cat,true,1943] <> 250) or (aa5[52,cat,true,1943] <> 252) then e(7);
for i:= -10 to 10 do aa1[i]:= 0;
for i:= 0 to 10 do aa1[i div 2 + i div 2]:= i+1;
if(aa1[0]<>2) or (aa1[5]<>0) or (aa1[8]<>10) then e(8);
for i:= 0 to 10 do
for j:= 0 to 3 do
for k:= 0 to 3 do
if ( (i+j+k) div 2) * 2 = i+j+k then aa6[i,j,k]:='e' else aa6[i,j,k]:='o';
if (aa6[2,2,2]<>'e') or (aa6[2,2,3]<>'o') or (aa6[0,3,1]<>'e') then e(9);
end;
#ifndef NOFLOAT
{************************************************************************}
procedure tst16;
{ Local records }
var r1,r2: tp2;
r3: packed record c1:char; i,j:integer; p:boolean; x:real end;
begin t:=16; pct := pct + 1;
r1.c1:='x'; r1.i:=40; r1.j:=50; r1.p:=true; r1.x:=3.0;
c1:='a'; i:=0; j:=0; p:=false; x:=100.0;
if (r1.c1<>'x') or (r1.i<>40) or (r1.p<>true) or (r1.x<>3.0) then e(1);
r2:=r1;
if (r2.c1<>'x') or (r2.i<>40) or (r2.p<>true) or (r2.x<>3.0) then e(2);
i:=r1.i; p:=r1.p; c1:=r1.c1; x:=r1.x;
if (c1<>'x') or (i<>40) or (p<>true) or (x<>3.0) then e(3);
r3.c1:='x'; r3.i:=40; r3.j:=50; r3.p:=true; r3.x:=3.0;
if (r3.c1<>'x') or (r3.i<>40) or (r3.p<>true) or (r3.x<>3.0) then e(4);
end;
#else
{************************************************************************}
procedure tst16;
{ Local records }
var r1,r2: tp2;
r3: packed record c1:char; i,j:integer; p:boolean end;
begin t:=16; pct := pct + 1;
r1.c1:='x'; r1.i:=40; r1.j:=50; r1.p:=true;
c1:='a'; i:=0; j:=0; p:=false;
if (r1.c1<>'x') or (r1.i<>40) or (r1.p<>true) then e(1);
r2:=r1;
if (r2.c1<>'x') or (r2.i<>40) or (r2.p<>true) then e(2);
i:=r1.i; p:=r1.p; c1:=r1.c1;
if (c1<>'x') or (i<>40) or (p<>true) then e(3);
r3.c1:='x'; r3.i:=40; r3.j:=50; r3.p:=true;
if (r3.c1<>'x') or (r3.i<>40) or (r3.p<>true) then e(4);
end;
#endif
{************************************************************************}
procedure tst17;
{ Local sets }
var colors: set of (pink,green,orange,red);
beasts: set of (pig,cow,chicken,farmersdaughter);
bits: set of 0..1;
begin t:=17; pct := pct + 1;
colors := [];
colors := colors + [];
if colors <> [] then e(1);
colors := colors + [pink];
if colors <> [pink] then e(2);
colors := colors + [green];
if colors <> [pink,green] then e(3);
if colors <> [green,pink] then e(4);
colors := colors - [pink,orange];
if colors <> [green] then e(5);
beasts := [chicken] + [chicken,pig];
if beasts <> [pig,chicken] then e(6);
beasts := [] - [farmersdaughter] + [cow] - [cow];
if beasts <> [] then e(7);
bits := [0] + [1] - [0];
if bits <> [1] then e(8);
bits := [] + [] + [] + [0] + [] + [0];
if bits <> [0] then e(9);
if ord(red) <> 3 then e(10);
end;
{************************************************************************}
procedure tst18;
{ Local pointers }
type rainbow = set of (pink,purple,chartreuse);
var p1: ^integer;
p2: ^tp2;
p3: ^single;
p4: ^rainbow;
begin t:=18; pct := pct + 1;
new(p1); new(p2); new(p3); new(p4);
p1^ := 1066;
if p1^ <> 1066 then e(1);
p2^.i := 1215;
if p2^.i <> 1215 then e(2);
p3^[0]:= 1566;
if p3^[0] <> 1566 then e(3);
p4^ := [pink] + [purple] + [purple,chartreuse] - [purple];
if p4^ <> [pink,chartreuse] then e(4);
end;
{************************************************************************}
procedure tst19;
var head,tail: np; i:integer;
begin t:=19; pct := pct + 1;
head := nil;
for i:= 1 to 100 do
begin new(tail); tail^.val:=100+i; tail^.next :=head; head:= tail end;
if (tail^.val<>200) or (tail^.next^.val<>199) then e(1);
if tail^.next^.next^.next^.next^.next^.next^.next^.next^.val<> 192 then e(2);
tail^.next^.next^.next^.val := 30;
if tail^.next^.next^.next^.val <> 30 then e(3);
end;
#ifndef NOFLOAT
{************************************************************************}
procedure tst20;
{ Mixed local and global }
var li:integer;
lx:real;
begin t:=20; pct := pct + 1;
li:=6; i:=li; if i<>6 then e(1);
i:=6; li:=i; if li <> 6 then e(2);
lx := 3.5; x:=lx; if x <> 3.5 then e(3);
x:= 4.5; lx:= x; if lx <> 4.5 then e(4);
end;
#else
{************************************************************************}
procedure tst20;
{ Mixed local and global }
var li:integer;
begin t:=20; pct := pct + 1;
li:=6; i:=li; if i<>6 then e(1);
i:=6; li:=i; if li <> 6 then e(2);
end;
#endif
{************************************************************************}
{ Main Program }
begin ect := 0; pct := 0;
#ifndef NOFLOAT
tst1; tst2; tst3; tst4; tst5; tst6; tst7; tst8;
tst9; tst10; tst11; tst12; tst13; tst14; tst15; tst16;
tst17; tst18; tst19; tst20;
#else
tst1; tst2; tst4; tst5; tst6; tst7; tst8;
tst9; tst10; tst11; tst13; tst14; tst15; tst16;
tst17; tst18; tst19; tst20;
#endif
write('Program t1:',pct:3,' tests completed.');
writeln('Number of errors = ',ect:0);
end.

View File

@@ -1,739 +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
}
program t2(input,output);
{ This program can be used to test out PASCAL compilers }
const
rcsversion='$Header$';
kew='q';
#ifndef NOFLOAT
eps = 2.0e-7; { This constant is machine dependent }
#endif
type wavelength = (red,blue,yellow);
tp2= record c1:char; i,j:integer; p:boolean; x:real end;
single= array [0..0] of integer;
spectrum= set of wavelength;
np= ^node;
node = record val:integer; next: np end;
var t,pct,ect:integer;
i,j,k,l:integer;
#ifndef NOFLOAT
w,x,y,z:real;
#endif
p:boolean;
d:char;
color: wavelength;
head: np;
function twice(k:integer):integer; begin twice := 2*k end;
function inc(k:integer):integer; begin inc := k+1 end;
procedure e(n:integer);
begin
ect := ect + 1;
writeln(' Error', n:3,' in test ', t)
end;
{************************************************************************}
procedure tst21;
{ Test things packed }
var i:integer; c:char;
r1: packed record c:char; b:boolean; i:integer end;
r2: packed record c:char; i:integer; b:boolean; j:integer end;
#ifndef NOFLOAT
r3: packed record c:char; r:real end;
#else
r3: packed record c:char end;
#endif
r4: packed record i:0..10; j:integer end;
r5: packed record x:array[1..3] of char; i:integer end;
r6: packed record x: packed array[1..3] of char; i:integer end;
r7: packed record c:char; x:packed array[1..3] of char end;
r8: packed record c:char; x:packed array[1..3] of integer end;
r9: record x:packed record c:char; i:integer end; i:integer; c:char end;
r10:packed record a:0..100; b:0..100; c:char; d:char end;
a1: packed array[1..3] of char;
a2: packed array[1..3] of integer;
#ifndef NOFLOAT
a3: packed array[1..7] of real;
#endif
a4: packed array[1..7] of array[1..11] of char;
a5: packed array[1..5] of array[1..11] of integer;
a6: packed array[1..9] of packed array[1..11] of char;
a7: packed array[1..3] of packed array[1..5] of integer;
begin t:=21; pct := pct + 1;
#ifndef NOFLOAT
i:=4; x:=3.5; c:='x'; p:=true;
#else
i:=4; c:='x'; p:=true;
#endif
r1.c:='a'; r1.b:=true; r1.i:=i; p:=r1.b; j:=r1.i;
r2.c:=c; r2.i:=i; r2.b:=p; r2.j:=i; j:=r2.i; j:=r2.j;
#ifndef NOFLOAT
r3.c:=c; r3.r:=x; y:=r3.r;
#else
r3.c:=c;
#endif
r4.i:=i; r4.j:=i; j:=r4.i; j:=r4.j;
r5.x[i-2]:=c; r5.i:=i; j:=r5.i;
r6.x[i-1]:=c; r6.i:=i; j:=r6.i;
r7.c:=c; r7.x[i-1]:=c; d:=r7.c; d:=r7.x[i-1];
r8.c:=c; r8.x[i-1]:=5; j:=r8.x[i-1];
r9.x.c:=c; r9.x.i:=i; r9.c:=c; j:=r9.x.i;
if (r1.c <> 'a') or (r1.b <> true) or (r1.i <> 4) then e(1);
if (r2.c<>'x') or (r2.i<>4) or (r2.b<>p) or (r2.j<>4) then e(2);
#ifndef NOFLOAT
if (r3.c<>'x') or (r3.r<>3.5) then e(3);
#else
if (r3.c<>'x') then e(3);
#endif
if (r4.i<>4) or (r4.j<>4) then e(4);
if (r5.x[2]<>'x') or (r5.i<>4) then e(5);
if (r6.x[3]<>'x') or (r6.i<>4) then e(6);
if (r7.c<>'x') or (r7.x[3]<>'x') or (c<>d) then e(7);
if (r8.c<>'x') or (r8.x[3]<>5) then e(8);
if (r9.x.c<>'x') or (r9.x.i<>4) or (r9.c<>'x') then e(9);
#ifndef NOFLOAT
i:=4; a1[i-1]:=c; a2[i-1]:=i; a3[i]:=x;
#else
i:=4; a1[i-1]:=c; a2[i-1]:=i;
#endif
a4[i][i+1]:=c;
a5[i][i+1]:=i; j:=a5[i][i+1];
a6[i][i+1]:=c;
a7[i-1][i+1]:=i; j:=a7[i-1][i+1];
if a1[i-1] <> 'x' then e(10);
if a2[i-1] <> 4 then e(11);
#ifndef NOFLOAT
if a3[i] <> 3.5 then e(12);
#endif
if a4[i][i+1] <> 'x' then e(13);
if a5[i][i+1] <> 4 then e(14);
if a6[i][i+1] <> 'x' then e(15);
if a7[i-1][i+1] <> 4 then e(16);
i:=75; c:='s';
r10.a:=i; r10.b:=i+1; r10.c:='x'; r10.d:=c;
if (r10.a<>i) or (r10.b<>76) or (r10.c<>'x') or (r10.d<>'s') then e(17);
i:=r10.a; if i<>75 then e(18);
i:=r10.b; if i<>76 then e(19);
c:=r10.c; if c<>'x'then e(20);
c:=r10.d; if c<>'s'then e(21);
end;
{************************************************************************}
procedure tst22;
{ References to intermediate lexical levels }
type wavelength = (pink,green,orange);
ww2= 1939..1945;
#ifndef NOFLOAT
tp2= record c1:char; i,j:integer; p:boolean; x:real end;
#else
tp2= record c1:char; i,j:integer; p:boolean end;
#endif
single= array [0..0] of integer;
spectrum= set of wavelength;
pnode = ^node;
node = record val:integer; next: pnode end;
vec1 = array[-10..+10] of integer;
var j,k,m:integer;
#ifndef NOFLOAT
x,y,z:real;
#endif
p,q,r:boolean;
c1,c2,c3:char;
sr1,sr2,sr3: 1939..1945;
color,hue,tint: wavelength;
a1: vec1;
#ifndef NOFLOAT
a2: array [ww2] of real;
#endif
a3: array[wavelength] of boolean;
a4: array[(mouse,house)] of char;
a5: array[50..52,(bat,cat,rat),boolean,ww2] of integer;
a6: packed array[0..10,0..3,0..3] of char;
r1,r2: tp2;
#ifndef NOFLOAT
r3: packed record c1:char; i,j:integer; p:boolean; x:real end;
#else
r3: packed record c1:char; i,j:integer; p:boolean end;
#endif
colors: spectrum;
beasts: set of (pig,chicken,farmersdaughter);
bits: set of 0..1;
p1: ^integer;
p2: ^tp2;
p3: ^single;
p4: ^spectrum;
tail: np;
procedure tst2201;
{ Arithmetic on intermediate level integer variables }
begin t:=2201; pct := pct + 1;
i:=1; j:=2; k:=3; l:=4; m:=10;
if i+j <> k then e(1);
if i+k <> l then e(2);
if j-k <> -i then e(3);
if j*(j+k) <> m then e(4);
if -m <> -(k+k+l) then e(5);
if i div i <> 1 then e(6);
if m*m div m <> m then e(7);
if 10*m <> 100 then e(8);
if m*(-10) <> -100 then e(9);
if j div k <> 0 then e(10);
if 100 div k <> 33 then e(11);
if i+j*k+l+m mod j + 50 div k <> 27 then e(12);
if j*k*m div 6 <> 10 then e(13);
if (k>4) or (k>=4) or (k=4) then e(14);
if (m<j) or (m<=j) or (m=j) then e(15);
if k <> i+j then e(16);
end;
#ifndef NOFLOAT
procedure tst2202;
{ Real arithmetic using intermediate level variables }
begin t:=2202; pct := pct + 1;
x:=1.50; y:=3.00; z:= 0.10;
if abs(5*y*z-x) > eps then e(10);
if abs(y*y*y/z*x-405) > eps then e(11);
x:=1.1; y:= 1.2;
if y<x then e(12);
if y <= x then e(13);
if y = x then e(14);
if x <> x then e(15);
if x >= y then e(16);
if x >y then e(17);
end;
#endif
procedure tst2203;
{ Boolean expressions using intermediate level varibales }
begin t:=2203; pct := pct + 1;
p:=true; q:=true; r:=false;
if not p then e(7);
if r then e(8);
if p and r then e(9);
if p and not q then e(10);
if not p or not q then e(11);
if (p and r) or (q and r) then e(12);
if p and q and r then e(13);
if (p or q) = r then e(14);
end;
procedure tst2204;
{ Characters, Subranges, Enumerated types using intermediate level vars }
begin t:=2204; pct := pct + 1;
if 'q' <> kew then e(1);
c1 := 'a'; c2 := 'b'; c3 := 'a';
if c1 = c2 then e(2);
if c1 <> c3 then e(3);
sr1:=1939; sr2:=1945; sr3:=1939;
if sr1=sr2 then e(4);
if sr1<>sr3 then e(5);
color := orange; hue := green; tint := orange;
if color = hue then e(6);
if color <> tint then e(7);
end;
procedure tst2205;
{ Intermediate level arrays }
var i,l,o:integer;
begin t:=2205; pct := pct + 1;
for i:= -10 to 10 do a1[i] := i*i;
if (a1[-10]<>100) or (a1[9]<>81) then e(1);
#ifndef NOFLOAT
for i:=1939 to 1945 do a2[i]:=i-1938.5;
if (abs(a2[1939]-0.5) > eps) or (abs(a2[1945]-6.5) > eps) then e(2);
#endif
color := orange;
a3[green] := true; a3[orange] := true;
if (a3[green]<>true) or (a3[orange]<>true) then e(3);
a3[green] := false; a3[orange] := false;
if (a3[green]<>false) or (a3[orange]<>false) then e(4);
a4[mouse]:='m'; a4[house]:='h';
if (a4[mouse] <> 'm') or (a4[house]<>'h' ) then e(5);
for i:=1939 to 1945 do a5[51,bat,false,i]:=300+i;
if a5[51,bat,false,1940] <> 2240 then e(6);
for i:=50 to 52 do a5[i,cat,true,1943]:=200+i;
if (a5[50,cat,true,1943] <> 250) or (a5[52,cat,true,1943] <> 252) then e(7);
for i:= -10 to 10 do a1[i]:= 0;
for i:= 0 to 10 do a1[i div 2 + i div 2]:= i+1;
if(a1[0]<>2) or (a1[5]<>0) or (a1[8]<>10) then e(8);
for i:= 0 to 10 do
for l:= 0 to 3 do
for o:= 0 to 3 do
if ( (i+l+o) div 2) * 2 = i+l+o then a6[i,l,o]:='e' else a6[i,l,o]:='o';
if (a6[2,2,2]<>'e') or (a6[2,2,3]<>'o') or (a6[0,3,1]<>'e') then e(9);
end;
#ifndef NOFLOAT
procedure tst2206;
{ Intermediate level records }
begin t:=2206; pct := pct + 1;
r1.c1:='x'; r1.i:=40; r1.j:=50; r1.p:=true; r1.x:=3.0;
c1:='a'; i:=0; j:=0; p:=false; x:=100.0;
if (r1.c1<>'x') or (r1.i<>40) or (r1.p<>true) or (r1.x<>3.0) then e(1);
r2:=r1;
if (r2.c1<>'x') or (r2.i<>40) or (r2.p<>true) or (r2.x<>3.0) then e(2);
i:=r1.i; p:=r1.p; c1:=r1.c1; x:=r1.x;
if (c1<>'x') or (i<>40) or (p<>true) or (x<>3.0) then e(3);
r3.c1:='x'; r3.i:=40; r3.j:=50; r3.p:=true; r3.x:=3.0;
if (r3.c1<>'x') or (r3.i<>40) or (r3.p<>true) or (r3.x<>3.0) then e(4);
end;
#else
procedure tst2206;
{ Intermediate level records }
begin t:=2206; pct := pct + 1;
r1.c1:='x'; r1.i:=40; r1.j:=50; r1.p:=true;
c1:='a'; i:=0; j:=0; p:=false;
if (r1.c1<>'x') or (r1.i<>40) or (r1.p<>true) then e(1);
r2:=r1;
if (r2.c1<>'x') or (r2.i<>40) or (r2.p<>true) then e(2);
i:=r1.i; p:=r1.p; c1:=r1.c1;
if (c1<>'x') or (i<>40) or (p<>true) then e(3);
r3.c1:='x'; r3.i:=40; r3.j:=50; r3.p:=true;
if (r3.c1<>'x') or (r3.i<>40) or (r3.p<>true) then e(4);
end;
#endif
procedure tst2207;
{ Intermediate level sets }
begin t:=2207; pct := pct + 1;
colors := [];
colors := colors + [];
if colors <> [] then e(1);
colors := colors + [pink];
if colors <> [pink] then e(2);
colors := colors + [green];
if colors <> [pink,green] then e(3);
if colors <> [green,pink] then e(4);
colors := colors - [pink];
if colors <> [green] then e(5);
beasts := [chicken] + [chicken,pig];
if beasts <> [pig,chicken] then e(6);
beasts := [] - [farmersdaughter];
if beasts <> [] then e(7);
bits := [0] + [1] - [0];
if bits <> [1] then e(8);
end;
procedure tst2208;
{ Pointers }
begin t:=2208; pct := pct + 1;
new(p1); new(p2); new(p3); new(p4);
p1^ := 1066;
if p1^ <> 1066 then e(1);
p2^.i := 1215;
if p2^.i <> 1215 then e(2);
p3^[0]:= 1566;
if p3^[0] <> 1566 then e(3);
p4^ := [pink];
if p4^ <> [pink] then e(4);
end;
procedure tst2209;
var i:integer;
begin t:=2209; pct := pct + 1;
head := nil;
for i:= 1 to 100 do
begin new(tail); tail^.val:=100+i; tail^.next :=head; head:= tail end;
if (tail^.val<>200) or (tail^.next^.val<>199) then e(1);
if tail^.next^.next^.next^.next^.next^.next^.next^.next^.val<> 192 then e(2);
tail^.next^.next^.next^.val := 30;
if tail^.next^.next^.next^.val <> 30 then e(3);
end;
begin t:=22; pct:=pct+1;
#ifndef NOFLOAT
tst2201; tst2202; tst2203; tst2204; tst2205; tst2206;
#else
tst2201; tst2203; tst2204; tst2205; tst2206;
#endif
tst2207; tst2208; tst2209;
end;
{************************************************************************}
procedure tst25;
{ Statement sequencing }
label 0,1,2,3;
procedure tst2501;
begin t:=2501;
goto 0;
e(1);
end;
begin t:=25; pct:=pct+1;
tst2501;
e(1);
0:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
i:=0;
1: if i>10 then goto 3 else goto 2;
e(2);
2: i:=i+1; goto 1;
e(3);
3:
end;
{************************************************************************}
procedure tst26;
{ More data structures }
type x = array[1..5] of integer;
ta = array [1..5] of array [1..5] of x;
tb = array [1..5] of record p1: ^x; p2: ^x end;
tr = record c: record b: record a: integer end end end ;
var low,i,j,k:integer; a:ta; b:tb; r:tr; hi:integer;
procedure tst2601(w:ta; x:tb; y:tr);
var i,j,k: integer;
begin t:=2601; pct:=pct+1;
for i:= 1 to 5 do for j:= 1 to 5 do for k:=1 to 5 do
if w[i][j][k] <> i*i + 7*j + k then e(1);
if (x[1].p1^[1] <> -9) or (x[2].p2^[4]<> -39) then e(2);
if y.c.b.a <> 102 then e(3);
end;
begin t:=26; pct:=pct+1;
low := 1000; hi := 1001;
for i:= 1 to 5 do for j:=1 to 5 do for k:= 1 to 5 do a[i][j][k] :=i*i+7*j+k;
new(b[1].p1); new(b[2].p2);
b[1].p1^[1] := -9; b[2].p2^[4] := -39;
r.c.b.a := 102;
tst2601(a,b,r);
t:=26;
if(low <> 1000) or (hi <> 1001) then e(1);
end;
{************************************************************************}
procedure tst27;
{ Assignments }
begin t:=27; pct := pct+1;
i:=3; j:=2; k:= -100;
l:= 1+(i*(j+(i*(j+(i*(j+(i*(3+j*(i*1+j*2)))))))));
if l <> 1456 then e(1);
l:= ((((((((((((((((((((((((((((((((0))))))))))))))))))))))))))))))));
if l <> 0 then e(2);
l:=(((i*j)+(3*i)-5) div 10)*(((i*j)+(3*i)-5) div 10)*(((i*j)+(3*i)-5) div 10)
+ (((i*j)+(3*i)-5) div 10)*(((i*j)+(3*i)-5) div 10)*(((i*j)+(3*i)-5) div 10);
if l <> 2 then e(3);
l:=((j+j) div 4) * ((j+j) div 4) * ((j+j) div 4)* (j div 3 + j div 4 + 3)+
((j+j) div 4) * ((j+j) div 4) * ((j+j) div 4)* (j div 3 + j div 4 + 3);
if l <> 6 then e(4);
i:=j*j*j*j*j*j*j*j*j*j*j*j*j*j - 16383;
if i <>1 then e(5);
l:=(i+(i+(i+(i+(i+(i+(i+(i+(i+(i+(i+(i+(i+(i+(i+(i))))))))))))))));
if l <> 16 then e(6);
l:= (((((((((((((((((j)+j)+j)+j)+j)+j)+j)+j)+j)+j)+j)+j)+j)+j)+j)+j)+j);
if l <> 34 then e(7);
l:= (-(-(-(-(-(-(-(-(-(j))))))))));
if l <> -2 then e(8);
#ifndef NOFLOAT
x:= 0.1; y:=0.2; z:=0.3;
w:=(((((x+y)/z)*2.0)+(((x+y)/z)*2.0)+(((x+y)/z)*2.0)+(((x+y)/z)*2.0))*
((((x+y)/z)*2.0)+(((x+y)/z)*2.0)+(((x+y)/z)*2.0)+(((x+y)/z)*2.0))*
((((x+y)/z)*2.0)+(((x+y)/z)*2.0)+(((x+y)/z)*2.0)+(((x+y)/z)*2.0))*
((((x+y)/z)*2.0)+(((x+y)/z)*2.0)+(((x+y)/z)*2.0)+(((x+y)/z)*2.0))*
((((x+y)/z)*2.0)+(((x+y)/z)*2.0)+(((x+y)/z)*2.0)+(((x+y)/z)*2.0)))-1;
if abs(w-32767) > 0.0001 then e(9);
i:= trunc(100*y+0.5); if i <> 20 then e(10);
i:= 32767; w:=i; if w <> 32767 then e(11);
#endif
end;
{************************************************************************}
procedure tst28;
{ Calls }
var i:integer;
function ack(m,n:integer):integer;
begin if m=0
then ack := n+1
else if n=0
then ack := ack(m-1,1)
else ack := ack(m-1,ack(m,n-1))
end;
procedure fib(a:integer; var b:integer); { Fibonacci nrs }
var i,j:integer;
begin
if (a=1) or (a=2) then b:=1 else
begin fib(a-1,i); fib(a-2,j); b:=i+j end
end;
begin t:=28; pct:= pct+1;
if ack(2,2) <> 7 then e(1);
if ack(3,3) <> 61 then e(2);
if ack(3,5) <> 253 then e(3);
if ack(2,100) <> 203 then e(4);
fib(10,i); if i <> 55 then e(5);
fib(20,i); if i <> 6765 then e(6);
end;
{************************************************************************}
procedure tst29;
{ Loops }
var i,l:integer; p:boolean;
begin t:= 29; pct:=pct+1;
j:=5;
k:=0; for i:=1 to j do k:=k+1; if k<>5 then e(1);
k:=0; for i:=5 to j do k:=k+1; if k<>1 then e(2);
k:=0; for i:=6 to j do k:=k+1; if k<>0 then e(3);
k:=0; for i:=-1 downto -j do k:=k+1; if k<>5 then e(4);
k:=0; for i:=-5 downto -j do k:=k+1; if k<>1 then e(5);
k:=0; for i:=-6 downto j do k:=k+1; if k<>0 then e(6);
k:=0; for i:=1 downto 10 do k:=k+1; if k<>0 then e(7);
k:=0; for l:=1 to j do k:=k+1; if k<>5 then e(8);
k:=0; for l:=5 to j do k:=k+1; if k<>1 then e(9);
k:=0; for l:=6 to j do k:=k+1; if k<>0 then e(10);
k:=0; for l:=-1 downto -j do k:=k+1; if k<>5 then e(11);
k:=0; for l:=-5 downto -j do k:=k+1; if k<>1 then e(12);
k:=0; for l:=-6 downto j do k:=k+1; if k<>0 then e(13);
k:=0; for l:=1 downto 10 do k:=k+1; if k<>0 then e(14);
k:=0; for p:= true downto false do k:=k+1; if k<>2 then e(15);
k:=0; for p:= false to true do k:=k+1; if k<>2 then e(16);
k:=0; while k<0 do k:=k+1; if k<>0 then e(17);
k:=0; repeat k:=k+1; until k>0; if k<> 1 then e(18);
k:=0; repeat k:=k+1; until k > 15; if k <> 16 then e(18);
k:=0; while k<=10 do k:=k+1; if k<> 11 then e(19);
end;
{************************************************************************}
procedure tst30;
{ case statements }
begin t:=30; pct:=pct+1;
i:=3; k:=0;
case i*i-7 of
0: k:=0; 1: k:=0; 2: k:=1; 3,4: k:=0
end;
if k<>1 then e(1);
color := red; k:=0;
case color of
red: k:=1; blue: k:=0; yellow: k:=0
end;
if k<>1 then e(2);
k:=0;
case color of
red,blue: k:=1; yellow: k:=0
end;
if k<>1 then e(3);
end;
#ifndef NOFLOAT
{************************************************************************}
procedure tst31;
{ with statements }
var ra: record i:integer; x:real; p:tp2; q:single;
a2: record a3: tp2 end
end;
rb: record j: integer; y:real; pp:tp2; qq:single end;
begin t:=31; pct:=pct+1;
i:=0; x:=0;
ra.i:=-3006; ra.x:=-6000.23; ra.q[0]:=35; ra.p.i:=20;
with ra do
begin if (i<>-3006) or (x<>-6000.23) or (q[0]<>35)
or (p.i<>20) then e(2);
i:=300; x:= 200.5; q[0]:=35; p.i:=-10
end;
if (ra.i<>300) or (ra.x<>200.5) or (ra.q[0]<>35) or (ra.p.i<>-10) then e(3);
with ra.p do if i <> -10 then e(4);
i:= -23;
ra.a2.a3.i := -909;
with ra do if a2.a3.i <> -909 then e(5);
with ra.a2 do if a3.i <> -909 then e(6);
with ra.a2.a3 do if i <> -909 then e(7);
with ra.a2 do i:=5;
if (i<>5) or (ra.a2.a3.i <> -909) then e(8);
with ra.a2.a3 do i:= 6;
if i<>5 then e(9);
if ra.a2.a3.i <> 6 then e(10);
with ra,rb do
begin x:=3.5; y:=6.5; i:=3; j:=9 end;
if (ra.x<>3.5) or (rb.y<>6.5) or (ra.i<>3) or (rb.j<>9) then e(11);
end;
#else
{************************************************************************}
procedure tst31;
{ with statements }
var ra: record i:integer; p:tp2; q:single;
a2: record a3: tp2 end
end;
rb: record j: integer; pp:tp2; qq:single end;
begin t:=31; pct:=pct+1;
#ifndef NOFLOAT
i:=0; x:=0;
#else
i:=0;
#endif
ra.i:=-3006; ra.q[0]:=35; ra.p.i:=20;
with ra do
begin if (i<>-3006) or (q[0]<>35)
or (p.i<>20) then e(2);
i:=300; q[0]:=35; p.i:=-10
end;
if (ra.i<>300) or (ra.q[0]<>35) or (ra.p.i<>-10) then e(3);
with ra.p do if i <> -10 then e(4);
i:= -23;
ra.a2.a3.i := -909;
with ra do if a2.a3.i <> -909 then e(5);
with ra.a2 do if a3.i <> -909 then e(6);
with ra.a2.a3 do if i <> -909 then e(7);
with ra.a2 do i:=5;
if (i<>5) or (ra.a2.a3.i <> -909) then e(8);
with ra.a2.a3 do i:= 6;
if i<>5 then e(9);
if ra.a2.a3.i <> 6 then e(10);
with ra,rb do
begin i:=3; j:=9 end;
if (ra.i<>3) or (rb.j<>9) then e(11);
end;
#endif
{************************************************************************}
procedure tst32;
{ Standard procedures }
begin t:=32; pct:=pct+1;
if abs(-1) <> 1 then e(1);
i:= -5; if abs(i) <> 5 then e(2);
#ifndef NOFLOAT
x:=-2.0; if abs(x) <> 2.0 then e(3);
#endif
if odd(5) = false then e(4);
if odd(4) then e(5);
if sqr(i) <> 25 then e(6);
if succ(i) <> -4 then e(7);
if succ(red) <> blue then e(8);
if pred(blue) <> red then e(9);
if ord(red) <> 0 then e(10);
if ord(succ(succ(red))) <> 2 then e(11);
if chr(ord(chr(ord(chr(ord('u')))))) <> 'u' then e(12);
if ord(chr(ord(chr(ord(chr(50)))))) <> 50 then e(13);
#ifndef NOFLOAT
if abs(trunc(5.2)-5.0) > eps then e(14);
if abs(sin(3.1415926536)) > 10*eps then e(15);
if abs(exp(1.0)-2.7182818) > 0.0001 then e(16);
if abs(ln(exp(1.0))- 1.0) > 3*eps then e(17);
if abs(sqrt(25.0)-5.0) > eps then e(18);
if abs(arctan(1.0) - 3.1415926535/4.0) > 0.0001 then e(19);
if abs(ln(arctan(1)*4) - 1.144729886) > 0.000001 then e(20);
if abs(sin(1) - 0.841470985 ) > 0.000001 then e(21);
if abs(cos(1) - 0.540302306) > 0.000001 then e(22);
if abs(sqrt(2) - 1.4142135623) > 0.000001 then e(23);
if abs(sqrt(10) - 3.1622776601) > 0.000001 then e(24);
if abs(sqrt(1000.0) - 31.622776602) > 0.00001 then e(25);
#endif
end;
{***************************************************************************}
procedure tst33;
{ Functions }
var i,j,k,l,m: integer;
begin t:=33; pct := pct+1;
i:=1; j:=2; k:=3; l:=4; m:=10;
if twice(k) <> m-l then e(1);
if twice(1) <> 2 then e(2);
if twice(k+1) <> twice(l) then e(3);
if twice(twice(twice(inc(twice(inc(3)))))) <> 72 then e(4);
if twice(inc(j+twice(inc(twice(i+1+inc(k)+inc(k))+twice(2)))))<>106
then e(5);
if twice(1) + twice(2) * twice(3) <> 26 then e(6);
if 3 <> 0 + twice(1) + 1 then e(7);
if 0 <> 0 * twice(m) then e(8);
end;
{**********************************************************************}
{ Main Program }
begin ect := 0; pct := 0;
tst21; tst22; tst25; tst26; tst27; tst28; tst29; tst30; tst31; tst32; tst33;
write('Program t2:',pct:3,' tests completed.');
writeln('Number of errors = ',ect:0);
end.

View File

@@ -1,333 +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
}
{$i64 : sets of integers contain 64 bits}
program t3(input,output,f1,f2,f3,f4,f5,f6);
{ The Berkeley and EM-1 compilers both can handle this program }
const rcsversion='$Header$';
type wavelength = (red,blue,yellow,q1,q2,q3,q4,q5,q6,q7,q8,q9,q10,q11,
pink,green,orange);
spectrum= set of wavelength;
bit = 0..1;
tp3= packed record c1:char; i:integer; p:boolean; x:real end;
tp4= record c1:char; i:integer; p:boolean; x:real end;
vec1 = array [-10..+10] of integer;
vrec = record case t:boolean of false:(r:real); true:(b:bit) end;
var t,pct,ect:integer;
i,j,k,l:integer;
x,y: real;
p:boolean;
c2:char;
a1: vec1;
c: array [1..20] of char;
r3: tp3;
r4: tp4;
vr: vrec;
colors: spectrum;
letters,cset:set of char;
f1: text;
f2: file of spectrum;
f3: file of tp3;
f4: file of tp4;
f5: file of vec1;
f6: file of vrec;
procedure e(n:integer);
begin
ect := ect + 1;
writeln(' Error', n:3,' in test ', t)
end;
{************************************************************************}
procedure tst34;
{ Global files }
var i:integer; c1:char;
begin t:=34; pct := pct + 1;
rewrite(f1);
if not eof(f1) then e(1);
write(f1,'abc',20+7:2,'a':2); writeln(f1);
write(f1,'xyz');
i:=-3000; write(f1,i:5);
reset(f1);
if eof(f1) or eoln(f1) then e(2);
for i:=1 to 17 do read(f1,c[i]);
if(c[1]<>'a') or (c[3]<>'c') or (c[5]<>'7') or (c[8]<>' ') or
(c[12]<>'-') or (c[13]<>'3') or (c[16]<>'0') then e(3);
if not eof(f1) then e(4);
rewrite(f1);
for i:= 32 to 127 do write(f1,chr(i));
reset(f1); p:= false;
for i:= 32 to 127 do begin read(f1,c1); if ord(c1) <> i then p:=true end;
if p then e(5);
rewrite(f1);
for c1 := 'a' to 'z' do write(f1,c1);
reset(f1); p:= false;
for c1 := 'a' to 'z' do begin read(f1,c2); if c2 <> c1 then p:=true end;
if p then e(6);
end;
procedure tst36;
var i,j:integer;
begin t:=36; pct:=pct+1;
rewrite(f2); rewrite(f3); rewrite(f4); rewrite(f5); rewrite(f6);
colors := []; f2^ := colors; put(f2);
colors := [red]; f2^ := colors; put(f2);
colors := [red,blue]; f2^ := colors; put(f2);
colors := [yellow,blue]; f2^ := colors; put(f2);
reset(f2);
colors := f2^; get(f2); if colors <> [] then e(4);
colors := f2^; get(f2); if colors <> [red] then e(5);
colors := f2^; get(f2); if colors <> [blue,red] then e(6);
colors := f2^; get(f2); if colors <> [blue,yellow] then e(7);
r3.c1:='w'; r3.i:= -100; r3.x:=303.56; r3.p:=true; f3^:=r3; put(f3);
r3.c1:='y'; r3.i:= -35; r3.x:=26.32; f3^:=r3; put(f3);
r3.c1:='q'; r3.i:= +29; r3.x:=10.00; f3^:=r3; put(f3);
r3.c1:='j'; r3.i:= 8; r3.x:=10000; f3^:=r3; put(f3);
for i:= 1 to 1000 do begin f3^ := r3; put(f3) end;
reset(f3);
r3 := f3^; get(f3);
if (r3.c1<>'w') or (r3.i<>-100) or (r3.x<>303.56) then e(8);
r3 := f3^; get(f3);
if (r3.c1<>'y') or (r3.i<> -35) or (r3.x<> 26.32) then e(9);
r3 := f3^; get(f3);
if (r3.c1<>'q') or (r3.i<> 29) or (r3.x<> 10.00) then e(10);
r3 := f3^; get(f3);
if (r3.c1<>'j') or (r3.i<> 8) or (r3.x<> 10000) then e(11);
r4.c1:='w'; r4.i:= -100; r4.x:=303.56; r4.p:=true; f4^:=r4; put(f4);
r4.c1:='y'; r4.i:= -35; r4.x:=26.32; f4^:=r4; put(f4);
r4.c1:='q'; r4.i:= +29; r4.x:=10.00; f4^:=r4; put(f4);
r4.c1:='j'; r4.i:= 8; r4.x:=10000; f4^:=r4; put(f4);
for i:= 1 to 1000 do begin f4^ := r4; put(f4) end;
reset(f4);
r4 := f4^; get(f4);
if (r4.c1<>'w') or (r4.i<>-100) or (r4.x<>303.56) then e(12);
r4 := f4^; get(f4);
if (r4.c1<>'y') or (r4.i<> -35) or (r4.x<> 26.32) then e(13);
r4 := f4^; get(f4);
if (r4.c1<>'q') or (r4.i<> 29) or (r4.x<> 10.00) then e(13);
r4 := f4^; get(f4);
if (r4.c1<>'j') or (r4.i<> 8) or (r4.x<> 10000) then e(14);
for j:= 1 to 100 do
begin for i:= -10 to +10 do a1[i] := i*j; f5^ := a1; put(f5); end;
reset(f5);
for j:= 1 to 99 do
begin a1:=f5^; get(f5); for i:= -10 to +10 do if a1[i]<> i*j then e(14) end;
vr.t:=false;
for i:= 1 to 1000 do begin vr.r:=i+0.5; f6^:=vr; put(f6) ; p:=true; end;
reset(f6); p:=false;
for i:= 1 to 999 do
begin vr:=f6^; get(f6); if vr.r <> i+0.5 then p:=true end;
if p then e(15);
rewrite(f6);
if not eof(f6) then e(16);
for i:= 1 to 1000 do begin vr.b:=i mod 2; f6^:=vr; put(f6) end;
reset(f6);
if eof(f6) then e(17);
p:=false;
for i:= 1 to 1000 do
begin vr:=f6^; get(f6); if vr.b <> i mod 2 then p:=true end;
if not eof(f6) then e(18);
if p then e(19);
rewrite(f1);
f1^:=chr(10);
put(f1);
reset(f1);
if ord(f1^) <> 32 then e(20);
rewrite(f1);
x:=0.0625; write(f1,x:6:4, x:6:2);
reset(f1); read(f1,y); if y <> 0.0625 then e(21);
reset(f1); for i:= 1 to 12 do begin c[i]:= f1^; get(f1) end;
if (c[1]<>'0') or (c[2]<>'.') or (c[4]<>'6') then e(22);
if (c[7]<>' ') or (c[9]<>'0') or (c[10]<>'.') or (c[12]<>'6') then e(23);
end;
{************************************************************************}
procedure tst35;
{ Local files }
var g1: text;
g2: file of spectrum;
g3: file of tp4;
g4: file of vec1;
i,j:integer;
begin t:=35; pct := pct + 1;
rewrite(g1); rewrite(g2); rewrite(g3); rewrite(g4);
if (not (eof(g1) and eof(g4))) then e(1);
writeln(g1,'abc', 20+7:2,'a':2);
write(g1,'xyz');
reset(g1);
if eof(g1) or eoln(g1) then e(2);
read(g1,c[1]); read(g1,c[2]); read(g1,c[3],c[4],c[5],c[6],c[7]);
if (c[1]<>'a') or (c[3]<>'c') or (c[4]<>'2') or (c[7]<>'a') then e(3);
if not eoln(g1) then e(4)
else readln(g1);
for i:=1 to 2 do read(g1,c[8+i]);
if c[10]<>'y' then e(5);
if eof(g1) or eoln(g1) then e(6);
colors := []; g2^ := colors; put(g2);
colors := [pink]; g2^ := colors; put(g2);
colors := [pink,green]; g2^ := colors; put(g2);
colors := [orange,green]; g2^ := colors; put(g2);
reset(g2);
colors := g2^; get(g2); if colors <> [] then e(7);
colors := g2^; get(g2); if colors <> [pink] then e(8);
colors := g2^; get(g2); if colors <> [green,pink] then e(9);
colors := g2^; get(g2); if colors <> [green,orange] then e(10);
r4.c1:='w'; r4.i:= -100; r4.x:=303.56; g3^:=r4; put(g3);
r4.c1:='y'; r4.i:= -35; r4.x:=26.32; g3^:=r4; put(g3);
r4.c1:='q'; r4.i:= +29; r4.x:=10.00; g3^:=r4; put(g3);
r4.c1:='j'; r4.i:= 8; r4.x:=10000; g3^:=r4; put(g3);
for i:= 1 to 1000 do begin g3^ := r4; put(g3) end;
reset(g3);
if eof(g3) then e(11);
r4 := g3^; get(g3);
if (r4.c1<>'w') or (r4.i<>-100) or (r4.x<>303.56) then e(12);
r4 := g3^; get(g3);
if (r4.c1<>'y') or (r4.i<> -35) or (r4.x<> 26.32) then e(13);
r4 := g3^; get(g3);
if (r4.c1<>'q') or (r4.i<> 29) or (r4.x<> 10.00) then e(14);
r4 := g3^; get(g3);
if (r4.c1<>'j') or (r4.i<> 8) or (r4.x<> 10000) then e(15);
for j:= 1 to 100 do
begin for i:= -10 to +10 do a1[i] := i*j; g4^ := a1; put(g4) end;
reset(g4);
for j:= 1 to 100 do
begin a1:=g4^; get(g4); for i:= -10 to +10 do if a1[i]<>i*j then e(16) end;
if not eof(g2) then e(17);
colors:=[q1,q2,q3,q4,q5,q6,q7,q8,q9,q10,q11];
end;
{***********************************************************************}
procedure tst37;
{ Intermediate level files }
var g1: text;
g2: file of spectrum;
g3: file of tp4;
g4: file of vec1;
procedure tst3701;
var i,j:integer;
begin t:=3701; pct := pct + 1;
rewrite(g1); rewrite(g2); rewrite(g3); rewrite(g4);
if (not (eof(g1) and eof(g4))) then e(1);
writeln(g1,'abc', 20+7:2,'a':2);
write(g1,'xyz');
reset(g1);
if eof(g1) or eoln(g1) then e(2);
read(g1,c[1]); read(g1,c[2]); read(g1,c[3],c[4],c[5],c[6],c[7]);
if (c[1]<>'a') or (c[3]<>'c') or (c[4]<>'2') or (c[7]<>'a') then e(3);
if not eoln(g1) then e(4)
else readln(g1);
for i:=1 to 2 do read(g1,c[8+i]);
if c[10]<>'y' then e(5);
if eof(g1) or eoln(g1) then e(6);
colors := []; g2^ := colors; put(g2);
colors := [pink]; g2^ := colors; put(g2);
colors := [pink,green]; g2^ := colors; put(g2);
colors := [orange,green]; g2^ := colors; put(g2);
reset(g2);
colors := g2^; get(g2); if colors <> [] then e(7);
colors := g2^; get(g2); if colors <> [pink] then e(8);
colors := g2^; get(g2); if colors <> [green,pink] then e(9);
colors := g2^; get(g2); if colors <> [green,orange] then e(10);
r4.c1:='w'; r4.i:= -100; r4.x:=303.56; g3^:=r4; put(g3);
r4.c1:='y'; r4.i:= -35; r4.x:=26.32; g3^:=r4; put(g3);
r4.c1:='q'; r4.i:= +29; r4.x:=10.00; g3^:=r4; put(g3);
r4.c1:='j'; r4.i:= 8; r4.x:=10000; g3^:=r4; put(g3);
for i:= 1 to 1000 do begin g3^ := r4; put(g3) end;
reset(g3);
if eof(g3) then e(11);
r4 := g3^; get(g3);
if (r4.c1<>'w') or (r4.i<>-100) or (r4.x<>303.56) then e(12);
r4 := g3^; get(g3);
if (r4.c1<>'y') or (r4.i<> -35) or (r4.x<> 26.32) then e(13);
r4 := g3^; get(g3);
if (r4.c1<>'q') or (r4.i<> 29) or (r4.x<> 10.00) then e(14);
r4 := g3^; get(g3);
if (r4.c1<>'j') or (r4.i<> 8) or (r4.x<> 10000) then e(15);
for j:= 1 to 100 do
begin for i:= -10 to +10 do a1[i] := i*j; g4^ := a1; put(g4) end;
reset(g4);
for j:= 1 to 100 do
begin a1:=g4^; get(g4); for i:= -10 to +10 do if a1[i]<>i*j then e(16) end;
end;
begin t:=37; pct := pct+1;
tst3701;
t:=37;
if not eof(g2) then e(1);
end;
{***********************************************************************}
procedure tst38;
{ Advanced set theory }
begin t:=38; pct := pct + 1;
if [50] >= [49,51] then e(1);
if [10] <= [9,11] then e(2);
if not ([50] <= [49..51]) then e(3);
i:=1; j:=2; k:=3; l:=5;
if [i] + [j] <> [i,j] then e(4);
if [i] + [j] <> [i..j] then e(5);
if [j..i] <> [] then e(6);
if [j..l] + [j..k] <> [2,3,4,5] then e(7);
if ([1..k, l..8] + [10]) * [k..7, 2, l] <> [2,3,l..7] then e(8);
if [i..9] - [j..l] <> [1,l+1..k*k] then e(9);
if [k..j] <> [i..j] * [k..l] then e(10);
if not ([k..10] <= [i..15]) then e(11);
if not ([k-1..k*l] <= [i..15]) then e(12);
letters := ['a','b', 'z'];
if letters <> ['a', 'b', 'z'] then e(13);
cset := ['a'] + ['b', 'c', 'z'] - ['c','d'];
if cset <> letters then e(14);
cset := ['a'..'e'];
if cset <> ['a', 'b', 'c', 'd', 'e'] then e(15);
cset := ['a'..'z', '0'..'9', '+','-','*','/','.',':','(',')','{','}'];
if not ('+' in cset) or not ('.' in cset) or not ('}' in cset) then e(16);
letters := ['a'..'z' , '0'..'9'];
if letters >= cset then e(17);
end;
{***********************************************************************}
{ Main program }
begin ect:=0; pct:=0;
tst34; tst35; tst36; tst37; tst38;
write('Program t3:',pct:3,' tests completed.');
writeln('Number of errors = ',ect:0);
end.

View File

@@ -1,411 +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
}
program t4(input,output);
{ Tests for the EM-1 compiler }
const rcsversion='$Header$';
type vec = array[1..1000] of integer;
spectrum = set of (red,blue,yellow);
#ifndef NOFLOAT
tp2 = record c1:char;i,j:integer; p:boolean; x:real end;
#else
tp2 = record c1:char;i,j:integer; p:boolean end;
#endif
cmat = array[0..3,0..7] of ^spectrum;
single = array [0..0] of integer;
np = ^node;
node = record val: integer; next: np end;
var t,ect,pct:integer;
r1: tp2;
pt1,pt2: ^vec;
pt3:^integer;
mk: ^integer;
i,j: integer;
procedure e(n:integer);
begin
ect := ect + 1;
writeln(' Error', n:3,' in test ', t)
end;
function inc(k:integer):integer; begin inc := k+1 end;
function twice(k:integer):integer; begin twice := 2*k end;
function decr(k:integer):integer; begin decr := k-1 end;
procedure tst40;
{ Mark and Release }
var i:integer;
procedure grab;
var i:integer;
begin
for i:=1 to 10 do new(pt1);
for i:=1 to 1000 do new(pt3);
end;
begin t:= 40; pct:=pct+1;
for i:=1 to 10 do
begin
mark(mk);
new(pt2);
grab;
release(mk)
end;
end;
procedure tst41;
{ Empty sets }
begin t:=41; pct := pct + 1;
if red in [] then e(1);
if ([] <> []) then e(2);
if not ([] = []) then e(3);
if not([] <=[]) then e(4);
if not ( [] >= []) then e(5);
end;
{************************************************************************}
procedure tst42;
{ Record variants. These tests are machine dependent }
var s:record b:boolean; case t:boolean of false:(c:char);true:(d:cmat) end;
w: packed record
case z:boolean of
false: (x:array[0..20] of integer);
true: (a,b,c,d,e,f,g,h,i,j,k,l:char)
end;
y: record
case z:boolean of
false: (x:array[0..20] of integer);
true: (a,b,c,d,e,f,g,h,i,j,k,l:char)
end;
i:integer;
begin t:=42; pct:=pct+1;
s.t:=false; s.c:='x'; if s.c <> 'x' then e(1);
for i:=0 to 20 do begin w.x[i]:=-1; y.x[i]:=-1 end;
w.a:=chr(0); w.f:=chr(0);
y.a:=chr(0); y.f:=chr(0);
if (ord(w.a) <> 0) or (ord(w.b) <> 255) then e(3);
if (ord(w.c) <> 255) or (ord(w.d)<>255) then e(4);
if (ord(w.e) <> 255) or (ord(w.f) <> 0) then e(5);
if ord(y.a) <> 0 then e(6);
if ord(y.f) <> 0 then e(7);
end;
{************************************************************************}
procedure tst43;
{ Procedure and function parameters }
function incr(k:integer):integer; begin incr := k+1 end;
function double(k:integer):integer; begin double := 2*k end;
function eval(function f(a:integer):integer; a:integer):integer;
begin eval:=f(a) end;
function apply(function f(a:integer):integer; a:integer):integer;
begin apply:=eval(f,a) end;
procedure x1(function f(a:integer):integer; a:integer; var r:integer);
procedure x2(function g(c:integer):integer; b:integer; var s:integer);
begin s:=apply(g,b); end;
begin x2(f, a+a, r) end;
procedure p0(procedure p(x:integer); i,j:integer);
begin
if j=0 then p(i) else p0(p,i+j,j-1)
end;
procedure p1(a,b,c,d:integer);
var k:integer;
procedure p2(x:integer);
begin k:= x*x end;
begin k:=0;
p0(p2,a,b);
if k <> c then e(d);
end;
begin t:=43; pct := pct+1;
i:=10; j:=20;
if incr(0) <> 1 then e(1);
if decr(i) <> 9 then e(2);
if double(i+j) <> 60 then e(3);
if incr(double(j)) <> 41 then e(4);
if decr(double(incr(double(i)))) <> 41 then e(5);
if incr(incr(incr(incr(incr(5))))) <> 10 then e(6);
if eval(incr,i) <> 11 then e(7);
if eval(decr,3) <> 2 then e(8);
if incr(eval(double,15)) <> 31 then e(9);
if apply(incr,3) <> 4 then e(10);
x1(double,i,j); if j <> 40 then e(11);
x1(incr,i+3,j); if j <> 27 then e(12);
p1(3,5,324,13);
p1(10,4,400,14);
p1(1,8,1369,15);
j:=1;
if inc(incr(twice(double(inc(incr(twice(double(j)))))))) <> 26 then e(13);
end;
{************************************************************************}
procedure tst44;
{ Value parameters }
type ww2 = array[-10..+10] of tp2;
arra = array[-10..+10] of integer;
reca = record k:single; s:spectrum end;
pa = np;
#ifndef NOFLOAT
var l1:integer; xr:real; xb:boolean; xc:char; xar:cmat; xnode:pa;
#else
var l1:integer; xb:boolean; xc:char; xar:cmat; xnode:pa;
#endif
vec1: arra; vec2: ww2;
s2:spectrum; rec1: reca;
zero:0..0;
#ifndef NOFLOAT
procedure tst4401(pl1:integer; pxr:real; pxb:boolean; pxc:char;
#else
procedure tst4401(pl1:integer; pxb:boolean; pxc:char;
#endif
pxar:cmat; pxnode:pa; pxtp2:tp2;
pvec1:arra; pvec2:ww2; prec1:reca;
ps1,ps2:spectrum; psin:single; i,j:integer);
begin t:=4401; pct:=pct+1;
if pl1<>29 then e(1);
#ifndef NOFLOAT
if pxr<>-0.31 then e(2);
#endif
if pxb <> false then e(3);
if pxc <> 'k' then e(4);
if (pxar[1,1]^<>[red,blue]) or (pxar[2,2]^ <> [yellow]) then e(5);
if (pxnode^.val <> 105) or (pxnode^.next^.val <> 106) then e(6);
#ifndef NOFLOAT
if (pxtp2.c1 <> 'w') or (pxtp2.x <> 20.3) then e(7);
#else
if (pxtp2.c1 <> 'w') then e(7);
#endif
if pvec1[10] <> -996 then e(8);
#ifndef NOFLOAT
if pvec2[zero].x <> -300 then e(9);
#endif
if (prec1.k[zero] <> -421) or (prec1.s <> []) then e(10);
if (ps1<>[]) or (ps2<>[red]) then e(11);
if psin[zero] <> -421 then e(12);
if i <> -421 then e(13);
if j <> 106 then e(14);
pl1:=0; pxc:=' '; pxb:=true;
pxar[1,1]^:=[]; pxar[2,2]^:=[];
pxnode^.val:=0; pxnode^.next^.val:=1;
pxtp2.c1:=' ';
pvec1[10]:=0;
#ifndef NOFLOAT
pvec2[zero].x:=0;
#endif
prec1.k[zero]:=0;
psin[0]:=0; i:=0; j:=0;
end;
begin t:=44; pct:=pct+1;
zero:=0;
#ifndef NOFLOAT
l1:=29; xr:=-0.31; xb:=false; xc:='k';
#else
l1:=29; xb:=false; xc:='k';
#endif
new(xar[1,1]); xar[1,1]^ := [red,blue];
new(xar[2,2]); xar[2,2]^ := [yellow];
new(xar[1,2]); xar[1,2]^ := [yellow];
new(xnode); xnode^.val :=105;
new(xnode^.next); xnode^.next^.val :=106;
#ifndef NOFLOAT
r1.c1:='w'; r1.x:=20.3;
vec1[10] := -996; vec2[zero].x := -300;
#else
r1.c1:='w';
vec1[10] := -996;
#endif
rec1.k[zero]:=-421; rec1.s :=[];
s2:=[red];
#ifndef NOFLOAT
tst4401(l1, xr, xb, xc, xar, xnode, r1, vec1, vec2, rec1,
#else
tst4401(l1, xb, xc, xar, xnode, r1, vec1, vec2, rec1,
#endif
[], s2, rec1.k, rec1.k[zero], xnode^.next^.val);;
t:=44;
if l1<>29 then e(1);
#ifndef NOFLOAT
if xr<> -0.31 then e(2);
#endif
if xb <> false then e(3);
if xc <> 'k' then e(4);
if (xar[1,1]^ <> []) or (xar[2,2]^ <> []) then e(5);
if xar[1,2]^ <> [yellow] then e(6);
if (xnode^.val <> 0) or (xnode^.next^.val <> 1) then e(7);
#ifndef NOFLOAT
if (r1.c1 <> 'w') or (r1.x <> 20.3) then e(8);
#else
if (r1.c1 <> 'w') then e(8);
#endif
if vec1[10] <> -996 then e(9);
#ifndef NOFLOAT
if vec2[zero].x <> -300 then e(10);
#endif
if (rec1.k[zero] <> -421) or (rec1.s <> []) then e(11);
if s2 <> [red] then e(12);
end;
{************************************************************************}
procedure tst45;
{ Var parameters }
type ww2 = array[-10..+10] of tp2;
arra = array[-10..+10] of integer;
reca = record k:single; s:spectrum end;
pa = np;
#ifndef NOFLOAT
var l1:integer; xr:real; xb:boolean; xc:char; xar:cmat; xnode:pa;
#else
var l1:integer; xb:boolean; xc:char; xar:cmat; xnode:pa;
#endif
vec1: arra; vec2: ww2;
s1,s2:spectrum; rec1: reca;
zero:0..0;
#ifndef NOFLOAT
procedure tst4501(var pl1:integer; var pxr:real; var pxb:boolean; var pxc:char;
#else
procedure tst4501(var pl1:integer; var pxb:boolean; var pxc:char;
#endif
var pxar:cmat; var pxnode:pa; var pxtp2:tp2;
var pvec1:arra; var pvec2:ww2; var prec1:reca;
var ps1,ps2:spectrum; var psin:single; var i,j:integer);
begin t:=4501; pct:=pct+1;
if pl1<>29 then e(1);
#ifndef NOFLOAT
if pxr<>-0.31 then e(2);
#endif
if pxb <> false then e(3);
if pxc <> 'k' then e(4);
if (pxar[1,1]^<>[red,blue]) or (pxar[2,2]^ <> [yellow]) then e(5);
if (pxnode^.val <> 105) or (pxnode^.next^.val <> 106) then e(6);
#ifndef NOFLOAT
if (pxtp2.c1 <> 'w') or (pxtp2.x <> 20.3) then e(7);
#else
if (pxtp2.c1 <> 'w') then e(7);
#endif
if pvec1[10] <> -996 then e(8);
#ifndef NOFLOAT
if pvec2[zero].x <> -300 then e(9);
#endif
if (prec1.k[zero] <> -421) or (prec1.s <> []) then e(10);
if (ps1<>[]) or (ps2<>[red]) then e(11);
if psin[zero] <> -421 then e(12);
if i <> -421 then e(13);
if j <> 106 then e(14);
#ifndef NOFLOAT
pl1:=0; pxr:=0; pxc:=' '; pxb:=true;
#else
pl1:=0; pxc:=' '; pxb:=true;
#endif
pxar[1,1]^:=[]; pxar[2,2]^:=[];
pxnode^.val:=0; pxnode^.next^.val:=1;
pxtp2.c1:=' ';
#ifndef NOFLOAT
pxtp2.x := 0;
#endif
pvec1[10]:=0;
#ifndef NOFLOAT
pvec2[zero].x:=0;
#endif
prec1.k[zero]:=0;
psin[0]:=0; i:=223; j:=445;
end;
begin t:=45; pct:=pct+1;
zero:=0;
#ifndef NOFLOAT
l1:=29; xr:=-0.31; xb:=false; xc:='k';
#else
l1:=29; xb:=false; xc:='k';
#endif
new(xar[1,1]); xar[1,1]^ := [red,blue];
new(xar[2,2]); xar[2,2]^ := [yellow];
new(xar[1,2]); xar[1,2]^ := [yellow];
new(xnode); xnode^.val :=105;
new(xnode^.next); xnode^.next^.val :=106;
#ifndef NOFLOAT
r1.c1:='w'; r1.x:=20.3;
vec1[10] := -996; vec2[zero].x := -300;
#else
r1.c1:='w';
vec1[10] := -996;
#endif
rec1.k[zero]:=-421; rec1.s :=[];
s1:=[]; s2:=[red];
#ifndef NOFLOAT
tst4501(l1, xr, xb, xc, xar, xnode, r1, vec1, vec2, rec1,
#else
tst4501(l1, xb, xc, xar, xnode, r1, vec1, vec2, rec1,
#endif
s1, s2, rec1.k, rec1.k[zero], xnode^.next^.val);;
t:=45;
if l1<>0 then e(1);
#ifndef NOFLOAT
if xr<> 0 then e(2);
#endif
if xb <> true then e(3);
if xc <> ' ' then e(4);
if (xar[1,1]^ <> []) or (xar[2,2]^ <> []) then e(5);
if xar[1,2]^ <> [yellow] then e(6);
if (xnode^.val <> 0) or (xnode^.next^.val <> 445) then e(7);
#ifndef NOFLOAT
if (r1.c1 <> ' ') or (r1.x <> 0) then e(8);
#else
if (r1.c1 <> ' ') then e(8);
#endif
if vec1[10] <> 0 then e(9);
#ifndef NOFLOAT
if vec2[zero].x <> 0 then e(10);
#endif
if (rec1.k[zero] <> 223) or (rec1.s <> []) then e(11);
if (s1 <> []) or (s2 <> [red]) then e(12);
end;
begin ect:=0; pct:=0;
tst40; tst41; tst42; tst43; tst44; tst45;
write('Program t4:',pct:3,' tests completed.');
writeln('Number of errors = ',ect:0);
end.

View File

@@ -1,13 +0,0 @@
{$i1000}
program test(output);
const rcsversion='$Header$';
var b:false..true;
i:integer;
s:set of 0..999;
begin
b:=true; if not b then writeln('error 1');
s:=[0,100,200,300,400,500,600,700,800,900];
for i:=0 to 999 do
if (i in s) <> (i mod 100=0) then
writeln('error 2');
end.

View File

@@ -1,66 +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
}
program tstenc(output);
const rcsversion='$Header$';
trapno=150;
var level:integer;
beenhere:boolean;
e:integer;
procedure trap(erno:integer); extern;
procedure encaps(procedure p;procedure q(erno:integer)); extern;
procedure p1;
label 1;
var plevel:integer;
procedure p2;
var plevel:integer;
begin plevel:=3 ; trap(trapno) ;
writeln('executing unreachable code in p2') ; e:=e+1 ;
end;
procedure q2(no:integer);
var qlevel:integer;
begin qlevel:=-3 ;
if no<>trapno then
begin writeln('wrong trapno ',no,' in q2'); e:=e+1 end ;
if plevel<>2 then
begin writeln('wrong level ',plevel,' in q2'); e:=e+1 end ;
trap(trapno) ;
goto 1;
writeln('executing unreachable code in q2') ; e:=e+1 ;
end;
begin plevel:=2 ; encaps(p2,q2) ;
writeln('executing unreachable code in p1'); e:=e+1;
1: if plevel<>2 then
begin writeln('wrong level ', plevel, 'in p1') ; e:=e+1 end ;
beenhere:=true ;
end; { body of p1 }
procedure q1(no:integer);
var qlevel:integer;
begin qlevel:=-2 ;
if no<>trapno then
begin writeln('wrong trapno ',no,' in q1'); e:=e+1 end ;
if level<>1 then
begin writeln('wrong level ',level,' in q1'); e:=e+1 end ;
end;
begin
level:=1 ;
e:=0 ;
beenhere:=false ;
encaps(p1,q1);
if not beenhere then
begin writeln('illegaly skipped code in p1') ; e:=e+1 end;
if e=0 then writeln('encaps OK')
end.

View File

@@ -1,75 +0,0 @@
program tstgto(output);
type int=integer;
pint=^integer;
var ga0,ga1,ga2,ga3,ga4,ga5:int;
gp0,gp1,gp2,gp3,gp4,gp5:pint;
procedure level0(a1,a2:int;p1,p2:pint);
label 1;
var a3,a4,a5:int;p3,p4,p5:pint;
procedure level1(a1,a2:int;p1,p2:pint);
var a3,a4,a5:int;p3,p4,p5:pint;
procedure level2(a1,a2:int;p1,p2:pint);
var a3,a4,a5:int;p3,p4,p5:pint;
begin
a1:= -5;a2:=a1;a3:=a2;a4:=a3;a5:=a4;
a1:= -4;a2:=a1;a3:=a2;a4:=a3;
a1:= -3;a2:=a1;a3:=a2;
a1:= -2;a2:=a1;
a1:=a5+a5;a1:= -1;
p1:=gp0;p2:=p1;p3:=p2;p4:=p3;p5:=p4;
p1:=gp1;p2:=p1;p3:=p2;p4:=p3;
p1:=gp2;p2:=p1;p3:=p2;
p1:=gp3;p2:=p1;
p1:=p5;p1:=gp4;
goto 1;
end; { level 2 }
begin
a1:=ga4;a2:=a1;a3:=a2;a4:=a3;a5:=a4;
a1:=ga3;a2:=a1;a3:=a2;a4:=a3;
a1:=ga2;a2:=a1;a3:=a2;
a1:=ga1;a2:=a1;
a1:=ga0;
p1:=gp4;p2:=p1;p3:=p2;p4:=p3;p5:=p4;
p1:=gp3;p2:=p1;p3:=p2;p4:=p3;
p1:=gp2;p2:=p1;p3:=p2;
p1:=gp1;p2:=p1;
p1:=gp0;
level2(a5,a4,p5,p4);
writeln('Error, goto failed');
end; { level 1 }
begin
a1:=ga5;a2:=a1;a3:=a2;a4:=a3;a5:=a4;
a1:=ga4;a2:=a1;a3:=a2;a4:=a3;
a1:=ga3;a2:=a1;a3:=a2;
a1:=ga2;a2:=a1;
a1:=ga1;
p1:=gp5;p2:=p1;p3:=p2;p4:=p3;p5:=p4;
p1:=gp4;p2:=p1;p3:=p2;p4:=p3;
p1:=gp3;p2:=p1;p3:=p2;
p1:=gp2;p2:=p1;
p1:=gp1;
level1(a5,a4,p5,p4);
writeln('Error, goto failed');
1:
if (a1 <> ga1) then writeln('level0:a1 has wrong value');
if (a2 <> ga2) then writeln('level0:a2 has wrong value');
if (a3 <> ga3) then writeln('level0:a3 has wrong value');
if (a4 <> ga4) then writeln('level0:a4 has wrong value');
if (a5 <> ga5) then writeln('level0:a5 has wrong value');
if (p1 <> gp1) then writeln('level0:p1 has wrong value');
if (p2 <> gp2) then writeln('level0:p2 has wrong value');
if (p3 <> gp3) then writeln('level0:p3 has wrong value');
if (p4 <> gp4) then writeln('level0:p4 has wrong value');
if (p5 <> gp5) then writeln('level0:p5 has wrong value');
end; { level 0 }
begin
ga0:=0;ga1:=1;ga2:=2;ga3:=3;ga4:=4;ga5:=5;
new(gp0);new(gp1);new(gp2);new(gp3);new(gp4);new(gp5);
level0(ga5,ga4,gp5,gp4);
end.

View File

@@ -1,27 +0,0 @@
var w=2
var p=2
var s=2
var l=4
var f=4
var d=8
var NAME=m6500
var M=6500
var LIB=mach/6500/lib/tail_
var RT=mach/6500/lib/head_
var INCLUDES=-I{EM}/include -I/usr/include
name be
from .m
to .s
program {EM}/lib/{M}_be
args <
prop >
need .e
end
name asld
from .s.a
to a.out
program {EM}/lib/{M}_as
mapflag -l* LNAME={EM}/{LIB}*
args (.e:{HEAD}={EM}/{RT}em) -o > (.e:{TAIL}={EM}/{LIB}em)
prop C
end

View File

@@ -1,31 +0,0 @@
var w=2
var i=2
var p=2
var s=2
var l=4
var f=4
var d=8
var NAME=m6809
var M=6809
var LIB=mach/6809/lib/tail_
var RT=mach/6809/lib/head_
var INCLUDES=-I{EM}/include -I/usr/include
name be
from .m
to .s
program {EM}/lib/{M}_be
args <
prop >
need .e
end
name asld
from .s.a
to a.out
program {EM}/lib/{M}_as
mapflag -l* LNAME={EM}/{LIB}*
args (.e:{HEAD}={EM}/{RT}em) \
({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) (.e:{TAIL}={EM}/{LIB}em)
prop C
end

View File

@@ -1,25 +0,0 @@
var w=2
var p=2
var s=2
var l=4
var f=4
var d=4
var M=cpm
var NAME=CPM
var LIB=mach/z80/int/lib/tail_
var RT=mach/z80/int/lib/head_
var SIZE_F=-sm
var INCLUDES=-I{EM}/include -I/usr/include
name asld
from .k.m.a
to e.out
program {EM}/lib/em_ass
mapflag -l* LNAME={EM}/{LIB}*
mapflag -+* ASS_F={ASS_F?} -+*
mapflag --* ASS_F={ASS_F?} --*
mapflag -s* SIZE_F=-s*
args {ASS_F?} ({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)
prop C
end

View File

@@ -1,60 +0,0 @@
# (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
name cpp
# no from, it's governed by the P property
to .i
program {EM}/lib/cpp
mapflag -I* CPP_F={CPP_F?} -I*
mapflag -U* CPP_F={CPP_F?} -U*
mapflag -D* CPP_F={CPP_F?} -D*
args {CPP_F?} {INCLUDES?} -D{NAME} -DEM_WSIZE={w} -DEM_PSIZE={p} \
-DEM_SSIZE={s} -DEM_LSIZE={l} -DEM_FSIZE={f} -DEM_DSIZE={d} <
prop >P
end
name cem
from .c
to .k
program {EM}/lib/em_cem
mapflag -p CEM_F={CEM_F?} -Xp
mapflag -L CEM_F={CEM_F?} -l
args -Vw{w}i{w}p{p}f{f}s{s}l{l}d{d} {CEM_F?}
prop <>p
rts .c
need .c
end
name pc
from .p
to .k
program {EM}/lib/em_pc
mapflag -p PC_F={PC_F?} -p
mapflag -w PC_F={PC_F?} -w
mapflag -E PC_F={PC_F?} -E
mapflag -e PC_F={PC_F?} -e
mapflag -{*} PC_F={PC_F?} -\{*}
mapflag -L PC_F={PC_F?} -\{l-}
args -Vw{w}p{p}f{d}l{l} {PC_F?} < > {SOURCE}
prop m
rts .p
need .p
end
name encode
from .e
to .k
program {EM}/lib/em_encode
args <
prop >m
end
name opt
from .k
to .m
program {EM}/lib/em_opt
mapflag -LIB OPT_F={OPT_F?} -L
args {OPT_F?} <
prop >O
end
name decode
from .k.m
to .e
program {EM}/lib/em_decode
args <
prop >
end

View File

@@ -1,35 +0,0 @@
var w=2
var p=2
var s=2
var l=4
var f=4
var d=8
var NAME=i8086
var M=i86
var LIB=mach/i86/lib/tail_
var LIBIBM=mach/ibm/lib/tail_
var RT=mach/i86/lib/head_
var RTIBM=mach/ibm/lib/head_
var INCLUDES=-I{EM}/include -I{EM}/mach/ibm/include
name be
from .m
to .s
program {EM}/lib/{M}_cg
args <
prop >
need .e
end
name asld
from .s.a
to a.out
program {EM}/lib/{M}_as
mapflag -l* LNAME={EM}/{LIB}*
mapflag -i IFILE={EM}/{RT}i
args {IFILE?} (.e:{HEAD}={EM}/{RTIBM}em) \
({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) \
(.e:{TAIL}={EM}/{LIBIBM}em) \
(.c.p:{TAIL}={EM}/{LIBIBM}mon) \
(.e:{TAIL}={EM}/{LIBIBM}em.vend)
prop C
end

View File

@@ -1,34 +0,0 @@
var w=2
var p=4
var s=2
var l=4
var f=4
var d=8
var NAME=m68k2
var M=m68k2
var LIBDIR=mach/m68k2/lib
var LIB=mach/m68k2/lib/tail_
var RT=mach/m68k2/lib/head_
var INCLUDES=-I{EM}/include -I/usr/include
name be
from .m
to .s
program {EM}/lib/{M}_cg
args <
prop >
need .e
end
name asld
from .s.a
to a.out
program {EM}/lib/{M}_as
mapflag -l* LNAME={EM}/{LIB}*
args (.e:{HEAD}={EM}/{RT}em) \
({RTS}:.c={EM}/{RT}cc) ({RTS}:.p={EM}/{RT}pc) -o > < \
(.p.c:{TAIL}={EM}/{LIBDIR}/sys1.s) (.p:{TAIL}={EM}/{LIBDIR}/sys2.s) \
(.c:{TAIL}={EM}/{LIBDIR}/write.s) \
(.p:{TAIL}={EM}/{LIB}pc) (.c:{TAIL}={EM}/{LIB}cc.1s {EM}/{LIB}cc.2g) \
(.c:{TAIL}={EM}/{LIB}mon {EM}/{LIB}fake) \
(.e:{TAIL}={EM}/{LIB}em.rt {EM}/{LIB}em.vend)
prop Cm
end

View File

@@ -1,28 +0,0 @@
var w=1
var p=2
var s=1
var l=2
var f=4
var d=8
var NAME=nascom
var M=z80a
var LIB=mach/z80a/lib/tail_
var RT=mach/z80a/lib/head_
var INCLUDES=-I{EM}/include -I/usr/include
name be
from .m
to .s
program {EM}/lib/{M}_be
args <
prop >
need .e
end
name asld
from .s.a
to a.out
program {EM}/lib/{M}_as
mapflag -l* LNAME={EM}/{LIB}*
args (.e:{HEAD}={EM}/{RT}em) ({RTS}:.c={EM}/{RT}cc) -o > \
(.e:{TAIL}={EM}/{LIB}em.1 {EM}/{LIB}em.2)
prop C
end

View File

@@ -1,32 +0,0 @@
var w=2
var p=2
var s=2
var l=4
var f=4
var d=8
var NAME=i8086
var M=i86
var LIB=mach/i86/lib/tail_
var RT=mach/i86/lib/head_
var INCLUDES=-I{EM}/include -I/usr/include
name be
from .m
to .s
program {EM}/lib/{M}_cg
args <
prop >
need .e
end
name asld
from .s.a
to a.out
program {EM}/lib/{M}_as
mapflag -l* LNAME={EM}/{LIB}*
mapflag -i IFILE={EM}/{RT}i
args {IFILE?} (.e:{HEAD}={EM}/{RT}em) \
({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.e:{TAIL}={EM}/{LIB}netio) (.c.p.e:{TAIL}={EM}/{LIB}alo) \
(.c.p:{TAIL}={EM}/{LIB}mon) (.e:{TAIL}={EM}/{LIB}em)
prop C
end

View File

@@ -1,33 +0,0 @@
var w=2
var p=2
var s=2
var l=4
var f=4
var d=8
var NAME=i8086
var M=i86
var LIB=mach/i86/lib/tail_
var ALIB=mach/i86/lib/sat_tail_
var RT=mach/i86/lib/head_
var ART=mach/i86/lib/sat_head_
var INCLUDES=-I{EM}/include -I/usr/include
name be
from .m
to .s
program {EM}/lib/{M}_cg
args <
prop >
need .e
end
name asld
from .s.a
to a.out
program {EM}/lib/{M}_as
mapflag -l* LNAME={EM}/{LIB}*
args (.e:{HEAD}={EM}/{ART}em) \
({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}/{ALIB}mon) (.c.p.e:{TAIL}={EM}/{LIB}alo) \
(.e:{TAIL}={EM}/{LIB}em)
prop C
end

View File

@@ -1,27 +0,0 @@
var w=2
var p=2
var s=2
var l=4
var f=4
var d=8
var M=int
var NAME=int22
var LIB=mach/int/lib/tail_
var RT=mach/int/lib/head_
var SIZE_FLAG=-sm
var INCLUDES=-I{EM}/include -I/usr/include
name asld
from .k.m.a
to e.out
program {EM}/lib/em_ass
mapflag -l* LNAME={EM}/{LIB}*
mapflag -+* ASS_F={ASS_F?} -+*
mapflag --* ASS_F={ASS_F?} --*
mapflag -s* SIZE_FLAG=-s*
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)
prop C
end

View File

@@ -1,27 +0,0 @@
var w=2
var p=2
var s=2
var l=4
var f=4
var d=8
var NAME=i8080
var M=8080
var LIB=mach/8080/lib/tail_
var RT=mach/8080/lib/head_
var INCLUDES=-I{EM}/include -I/usr/include
name be
from .m
to .s
program {EM}/lib/{M}_be
args <
prop >
need .e
end
name asld
from .s.a
to a.out
program {EM}/lib/{M}_as
mapflag -l* LNAME={EM}/{LIB}*
args ({RTS}:.c={EM}/{RT}cc) -o > <
prop C
end

View File

@@ -1,32 +0,0 @@
var w=2
var p=2
var s=2
var l=4
var f=4
var d=8
var NAME=i8086
var M=i86
var LIB=mach/i86/lib/tail_
var RT=mach/i86/lib/head_
var INCLUDES=-I{EM}/include -I/usr/include
name be
from .m
to .s
program {EM}/lib/{M}_cg
args <
prop >
need .e
end
name asld
from .s.a
to a.out
program {EM}/lib/{M}_as
mapflag -l* LNAME={EM}/{LIB}*
mapflag -i IFILE={EM}/{RT}i
args {IFILE?} (.e:{HEAD}={EM}/{RT}em) \
({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.e:{TAIL}={EM}/{LIB}alo) (.c.p:{TAIL}={EM}/{LIB}mon) \
(.e:{TAIL}={EM}/{LIB}em)
prop C
end

View File

@@ -1,30 +0,0 @@
var w=2
var p=4
var s=2
var l=4
var f=4
var d=8
var NAME=m68k2
var M=m68k2
var LIB=mach/m68k2/lib/tail_
var RT=mach/m68k2/lib/head_
var INCLUDES=-I{EM}/include -I/usr/include
name be
from .m
to .s
program {EM}/lib/{M}_cg
args <
prop >
need .e
end
name asld
from .s.a
to a.out
program {EM}/lib/{M}_as
mapflag -l* LNAME={EM}/{LIB}*
args (.e:{HEAD}={EM}/{RT}em) \
({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) \
(.e:{TAIL}={EM}/{LIB}em.rt {EM}/{LIB}mon {EM}/{LIB}em.vend)
prop Cm
end

View File

@@ -1,34 +0,0 @@
var w=4
var p=4
var s=2
var l=4
var f=4
var d=8
var NAME=m68k4
var M=m68k4
var LIBDIR=mach/m68k4/lib
var LIB=mach/m68k4/lib/tail_
var RT=mach/m68k4/lib/head_
var INCLUDES=-I{EM}/include -I/usr/include
name be
from .m
to .s
program {EM}/lib/{M}_cg
args <
prop >
need .e
end
name asld
from .s.a
to a.out
program {EM}/lib/{M}_as
mapflag -l* LNAME={EM}/{LIB}*
args (.e:{HEAD}={EM}/{RT}em) \
({RTS}:.c={EM}/{RT}cc) ({RTS}:.p={EM}/{RT}pc) -o > < \
(.p.c:{TAIL}={EM}/{LIBDIR}/sys1.s) (.p:{TAIL}={EM}/{LIBDIR}/sys2.s) \
(.c:{TAIL}={EM}/{LIBDIR}/write.s) \
(.p:{TAIL}={EM}/{LIB}pc) (.c:{TAIL}={EM}/{LIB}cc.1s {EM}/{LIB}cc.2g) \
(.c:{TAIL}={EM}/{LIB}mon {EM}/{LIB}fake) \
(.e:{TAIL}={EM}/{LIB}em.rt {EM}/{LIB}em.vend)
prop Cm
end

View File

@@ -1,38 +0,0 @@
var w=2
var p=2
var s=2
var l=4
var f=4
var d=8
var M=pdp
var NAME=pdp
var LIB=mach/pdp/lib/tail_
var RT=mach/pdp/lib/head_
var INCLUDES=-I{EM}/include -I/usr/include
name be
from .m
to .s
program {EM}/lib/{M}_cg
args <
prop >
need .e
end
name as
from .s
to .o
program /bin/as
args - -o > <
prop m
end
name ld
from .o.a
to a.out
program /bin/ld
mapflag -l* LNAME={EM}/{LIB}*
args (.e:{HEAD}={EM}/{RT}em) \
({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) \
(.e:{TAIL}={EM}/{LIB}em) (.c.p:{TAIL}=/lib/libc.a)
prop C
end

View File

@@ -1,32 +0,0 @@
var w=2
var p=4
var s=2
var l=4
var f=4
var d=8
var NAME=m68k2
var M=m68k2
var LIB=mach/m68k2/lib/tail_
var RT=mach/m68k2/lib/head_
var INCLUDES=-I{EM}/include -I/usr/include
name be
from .m
to .o
program {EM}/lib/{M}_cg
args <
prop >
need .e
end
name asld
from .o.s.a
to a.out
program {EM}/lib/{M}_as
mapflag -l* LNAME={EM}/{LIB}*
mapflag -i
mapflag -n
args (.e:{HEAD}={EM}/{RT}em.pmds) \
({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) \
(.e:{TAIL}={EM}/{LIB}em.rt {EM}/{LIB}mon.pmds {EM}/{LIB}em.vend)
prop Cm
end

View File

@@ -1,44 +0,0 @@
var w=4
var p=4
var s=2
var l=4
var f=4
var d=8
var M=vax4
var NAME=vax4
var LIB=mach/vax4/lib/tail_
var RT=mach/vax4/lib/head_
var INCLUDES=-I{EM}/include -I/usr/include
name be
from .m
to .s
program {EM}/lib/{M}_cg
args <
prop >
need .e
end
name asopt
from .s
to .so
program /bin/sed
args -f {EM}/mach/vax4/cg/sedf
prop O<>
end
name as
from .s.so
to .o
program /bin/as
args - -o > <
prop m
end
name ld
from .o.a
to a.out
program /bin/ld
mapflag -l* LNAME={EM}/{LIB}*
args (.e:{HEAD}={EM}/{RT}em) \
({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) (.e:{TAIL}={EM}/{LIB}em)
prop C
end

View File

@@ -1,31 +0,0 @@
var w=2
var p=2
var s=2
var l=4
var f=4
var d=8
var NAME=z80
var M=z80
var LIB=mach/z80/lib/tail_
var RT=mach/z80/lib/head_
var INCLUDES=-I{EM}/include -I/usr/include
name be
from .m
to .s
program {EM}/lib/{M}_cg
args <
prop >
need .e
end
name asld
from .s.a
to a.out
program {EM}/lib/{M}_as
mapflag -l* LNAME={EM}/{LIB}*
mapflag -i IFILE={EM}/{RT}i
args {IFILE?} (.e:{HEAD}={EM}/{RT}em) \
({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) \
(.p.c:{TAIL}={EM}/{LIB}mon) (.e:{TAIL}={EM}/{LIB}em)
prop C
end

View File

@@ -1,31 +0,0 @@
var w=2
var p=2
var s=2
var l=4
var f=4
var d=8
var NAME=z8000
var M=z8000
var LIB=mach/z8000/lib/tail_
var RT=mach/z8000/lib/head_
var INCLUDES=-I{EM}/include -I/usr/include
name be
from .m
to .s
program {EM}/lib/{M}_cg
args <
prop >
need .e
end
name asld
from .s.a
to a.out
program {EM}/lib/{M}_as
mapflag -l* LNAME={EM}/{LIB}*
mapflag -i IFILE={EM}/{RT}i
args {IFILE?} (.e:{HEAD}={EM}/{RT}em) \
({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) \
(.p.c:{TAIL}={EM}/{LIB}mon) (.e:{TAIL}={EM}/{LIB}em)
prop C
end

View File

@@ -1,178 +0,0 @@
# $Header$
PREFLAGS=-I../../../h -I. -DNDEBUG
PFLAGS=
CFLAGS=$(PREFLAGS) $(PFLAGS) -O
LDFLAGS=-i $(PFLAGS)
LINTOPTS=-hbxac
LIBS=../../../lib/em_data.a
CDIR=../../proto/cg
CFILES=$(CDIR)/codegen.c $(CDIR)/compute.c $(CDIR)/equiv.c $(CDIR)/fillem.c \
$(CDIR)/gencode.c $(CDIR)/glosym.c $(CDIR)/main.c $(CDIR)/move.c \
$(CDIR)/nextem.c $(CDIR)/reg.c $(CDIR)/regvar.c $(CDIR)/salloc.c \
$(CDIR)/state.c $(CDIR)/subr.c $(CDIR)/var.c
OFILES=codegen.o compute.o equiv.o fillem.o gencode.o glosym.o main.o\
move.o nextem.o reg.o regvar.o salloc.o state.o subr.o var.o
all:
make tables.c
make cg
cg: tables.o $(OFILES)
cc $(LDFLAGS) $(OFILES) tables.o $(LIBS) -o cg
tables.o: tables.c
cc -c $(PREFLAGS) -I$(CDIR) tables.c
codegen.o: $(CDIR)/codegen.c
cc -c $(CFLAGS) $(CDIR)/codegen.c
compute.o: $(CDIR)/compute.c
cc -c $(CFLAGS) $(CDIR)/compute.c
equiv.o: $(CDIR)/equiv.c
cc -c $(CFLAGS) $(CDIR)/equiv.c
fillem.o: $(CDIR)/fillem.c
cc -c $(CFLAGS) $(CDIR)/fillem.c
gencode.o: $(CDIR)/gencode.c
cc -c $(CFLAGS) $(CDIR)/gencode.c
glosym.o: $(CDIR)/glosym.c
cc -c $(CFLAGS) $(CDIR)/glosym.c
main.o: $(CDIR)/main.c
cc -c $(CFLAGS) $(CDIR)/main.c
move.o: $(CDIR)/move.c
cc -c $(CFLAGS) $(CDIR)/move.c
nextem.o: $(CDIR)/nextem.c
cc -c $(CFLAGS) $(CDIR)/nextem.c
reg.o: $(CDIR)/reg.c
cc -c $(CFLAGS) $(CDIR)/reg.c
regvar.o: $(CDIR)/regvar.c
cc -c $(CFLAGS) $(CDIR)/regvar.c
salloc.o: $(CDIR)/salloc.c
cc -c $(CFLAGS) $(CDIR)/salloc.c
state.o: $(CDIR)/state.c
cc -c $(CFLAGS) $(CDIR)/state.c
subr.o: $(CDIR)/subr.c
cc -c $(CFLAGS) $(CDIR)/subr.c
var.o: $(CDIR)/var.c
cc -c $(CFLAGS) $(CDIR)/var.c
install: all
../install cg
cmp: all
-../compare cg
tables.c: table
-mv tables.h tables.h.save
../../../lib/cpp -P table | ../../../lib/cgg > debug.out
-if cmp -s tables.h.save tables.h; then mv tables.h.save tables.h; else exit 0; fi
-if cmp -s /dev/null tables.h; then mv tables.h.save tables.h; else exit 0; fi
lint: $(CFILES)
lint $(LINTOPTS) $(PREFLAGS) $(CFILES)
clean:
rm -f *.o tables.c tables.h debug.out cg tables.h.save
codegen.o: $(CDIR)/assert.h
codegen.o: $(CDIR)/data.h
codegen.o: $(CDIR)/equiv.h
codegen.o: $(CDIR)/extern.h
codegen.o: $(CDIR)/param.h
codegen.o: $(CDIR)/result.h
codegen.o: $(CDIR)/state.h
codegen.o: tables.h
codegen.o: $(CDIR)/types.h
compute.o: $(CDIR)/assert.h
compute.o: $(CDIR)/data.h
compute.o: $(CDIR)/extern.h
compute.o: $(CDIR)/glosym.h
compute.o: $(CDIR)/param.h
compute.o: $(CDIR)/result.h
compute.o: tables.h
compute.o: $(CDIR)/types.h
equiv.o: $(CDIR)/assert.h
equiv.o: $(CDIR)/data.h
equiv.o: $(CDIR)/equiv.h
equiv.o: $(CDIR)/extern.h
equiv.o: $(CDIR)/param.h
equiv.o: $(CDIR)/result.h
equiv.o: tables.h
equiv.o: $(CDIR)/types.h
fillem.o: $(CDIR)/assert.h
fillem.o: $(CDIR)/data.h
fillem.o: $(CDIR)/extern.h
fillem.o: mach.c
fillem.o: mach.h
fillem.o: $(CDIR)/param.h
fillem.o: $(CDIR)/regvar.h
fillem.o: $(CDIR)/result.h
fillem.o: tables.h
fillem.o: $(CDIR)/types.h
gencode.o: $(CDIR)/assert.h
gencode.o: $(CDIR)/data.h
gencode.o: $(CDIR)/extern.h
gencode.o: $(CDIR)/param.h
gencode.o: $(CDIR)/result.h
gencode.o: tables.h
gencode.o: $(CDIR)/types.h
glosym.o: $(CDIR)/glosym.h
glosym.o: $(CDIR)/param.h
glosym.o: tables.h
glosym.o: $(CDIR)/types.h
main.o: $(CDIR)/param.h
move.o: $(CDIR)/assert.h
move.o: $(CDIR)/data.h
move.o: $(CDIR)/extern.h
move.o: $(CDIR)/param.h
move.o: $(CDIR)/result.h
move.o: tables.h
move.o: $(CDIR)/types.h
nextem.o: $(CDIR)/assert.h
nextem.o: $(CDIR)/data.h
nextem.o: $(CDIR)/extern.h
nextem.o: $(CDIR)/param.h
nextem.o: $(CDIR)/result.h
nextem.o: tables.h
nextem.o: $(CDIR)/types.h
reg.o: $(CDIR)/assert.h
reg.o: $(CDIR)/data.h
reg.o: $(CDIR)/extern.h
reg.o: $(CDIR)/param.h
reg.o: $(CDIR)/result.h
reg.o: tables.h
reg.o: $(CDIR)/types.h
regvar.o: $(CDIR)/assert.h
regvar.o: $(CDIR)/data.h
regvar.o: $(CDIR)/extern.h
regvar.o: $(CDIR)/param.h
regvar.o: $(CDIR)/regvar.h
regvar.o: $(CDIR)/result.h
regvar.o: tables.h
regvar.o: $(CDIR)/types.h
salloc.o: $(CDIR)/assert.h
salloc.o: $(CDIR)/data.h
salloc.o: $(CDIR)/extern.h
salloc.o: $(CDIR)/param.h
salloc.o: $(CDIR)/result.h
salloc.o: tables.h
salloc.o: $(CDIR)/types.h
state.o: $(CDIR)/assert.h
state.o: $(CDIR)/data.h
state.o: $(CDIR)/extern.h
state.o: $(CDIR)/param.h
state.o: $(CDIR)/result.h
state.o: $(CDIR)/state.h
state.o: tables.h
state.o: $(CDIR)/types.h
subr.o: $(CDIR)/assert.h
subr.o: $(CDIR)/data.h
subr.o: $(CDIR)/extern.h
subr.o: $(CDIR)/param.h
subr.o: $(CDIR)/result.h
subr.o: tables.h
subr.o: $(CDIR)/types.h
var.o: $(CDIR)/data.h
var.o: $(CDIR)/param.h
var.o: $(CDIR)/result.h
var.o: tables.h
var.o: $(CDIR)/types.h

View File

@@ -1,72 +0,0 @@
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,".short\t%d\n",(int) l);
fprintf(codefile,".short\t%d\n",(int) (l >> 16));
}
con_float() {
fatal("no reals");
}
prolog(nlocals) full nlocals; {
fprintf(codefile,"\tjsr Pro\n");
if (nlocals == 0)
return;
else
fprintf(codefile,
"\tldx #[%d].h\n\tlda #[%d].l\n\tjsr Lcs\n",
nlocals, 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,".define %s\n",argstr) ;
break ;
}
}
default :
while ( getarg(any_ptyp) != sp_cend ) ;
break ;
}
}
char *segname[] = {
".text", /* SEGTXT */
".data", /* SEGCON */
".data", /* SEGROM */
".bss" /* SEGBSS */
};

View File

@@ -1,24 +0,0 @@
#define ex_ap(y) fprintf(codefile,".extern %s\n",y)
#define in_ap(y) /* nothing */
#define newilb(x) fprintf(codefile,"%s:\n",x)
#define newdlb(x) fprintf(codefile,"%s:\n",x)
#define dlbdlb(x,y) fprintf(codefile,"%s = %s\n",x,y)
#define newlbss(l,x) fprintf(codefile,"%s: .space\t%d\n",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,".word\t%d\n",x)
#define con_ilb(x) fprintf(codefile,".word\t%s\n",x)
#define con_dlb(x) fprintf(codefile,".word\t%s\n",x)
#define modhead ""
#define id_first '_'
#define BSS_INIT 0

File diff suppressed because it is too large Load Diff

View File

@@ -1,178 +0,0 @@
# $Header$
PREFLAGS=-I../../../h -I. -DNDEBUG
PFLAGS=
CFLAGS=$(PREFLAGS) $(PFLAGS) -O
LDFLAGS=-i $(PFLAGS)
LINTOPTS=-hbxac
LIBS=../../../lib/em_data.a
CDIR=../../proto/cg
CFILES=$(CDIR)/codegen.c $(CDIR)/compute.c $(CDIR)/equiv.c $(CDIR)/fillem.c \
$(CDIR)/gencode.c $(CDIR)/glosym.c $(CDIR)/main.c $(CDIR)/move.c \
$(CDIR)/nextem.c $(CDIR)/reg.c $(CDIR)/regvar.c $(CDIR)/salloc.c \
$(CDIR)/state.c $(CDIR)/subr.c $(CDIR)/var.c
OFILES=codegen.o compute.o equiv.o fillem.o gencode.o glosym.o main.o\
move.o nextem.o reg.o regvar.o salloc.o state.o subr.o var.o
all:
make tables.c
make cg
cg: tables.o $(OFILES)
cc $(LDFLAGS) $(OFILES) tables.o $(LIBS) -o cg
tables.o: tables.c
cc -c $(PREFLAGS) -I$(CDIR) tables.c
codegen.o: $(CDIR)/codegen.c
cc -c $(CFLAGS) $(CDIR)/codegen.c
compute.o: $(CDIR)/compute.c
cc -c $(CFLAGS) $(CDIR)/compute.c
equiv.o: $(CDIR)/equiv.c
cc -c $(CFLAGS) $(CDIR)/equiv.c
fillem.o: $(CDIR)/fillem.c
cc -c $(CFLAGS) $(CDIR)/fillem.c
gencode.o: $(CDIR)/gencode.c
cc -c $(CFLAGS) $(CDIR)/gencode.c
glosym.o: $(CDIR)/glosym.c
cc -c $(CFLAGS) $(CDIR)/glosym.c
main.o: $(CDIR)/main.c
cc -c $(CFLAGS) $(CDIR)/main.c
move.o: $(CDIR)/move.c
cc -c $(CFLAGS) $(CDIR)/move.c
nextem.o: $(CDIR)/nextem.c
cc -c $(CFLAGS) $(CDIR)/nextem.c
reg.o: $(CDIR)/reg.c
cc -c $(CFLAGS) $(CDIR)/reg.c
regvar.o: $(CDIR)/regvar.c
cc -c $(CFLAGS) $(CDIR)/regvar.c
salloc.o: $(CDIR)/salloc.c
cc -c $(CFLAGS) $(CDIR)/salloc.c
state.o: $(CDIR)/state.c
cc -c $(CFLAGS) $(CDIR)/state.c
subr.o: $(CDIR)/subr.c
cc -c $(CFLAGS) $(CDIR)/subr.c
var.o: $(CDIR)/var.c
cc -c $(CFLAGS) $(CDIR)/var.c
install: all
../install cg
cmp: all
-../compare cg
tables.c: table
-mv tables.h tables.h.save
../../../lib/cpp -P table | ../../../lib/cgg > debug.out
-if cmp -s tables.h.save tables.h; then mv tables.h.save tables.h; else exit 0; fi
-if cmp -s /dev/null tables.h; then mv tables.h.save tables.h; else exit 0; fi
lint: $(CFILES)
lint $(LINTOPTS) $(PREFLAGS) $(CFILES)
clean:
rm -f *.o tables.c tables.h debug.out cg tables.h.save
codegen.o: $(CDIR)/assert.h
codegen.o: $(CDIR)/data.h
codegen.o: $(CDIR)/equiv.h
codegen.o: $(CDIR)/extern.h
codegen.o: $(CDIR)/param.h
codegen.o: $(CDIR)/result.h
codegen.o: $(CDIR)/state.h
codegen.o: tables.h
codegen.o: $(CDIR)/types.h
compute.o: $(CDIR)/assert.h
compute.o: $(CDIR)/data.h
compute.o: $(CDIR)/extern.h
compute.o: $(CDIR)/glosym.h
compute.o: $(CDIR)/param.h
compute.o: $(CDIR)/result.h
compute.o: tables.h
compute.o: $(CDIR)/types.h
equiv.o: $(CDIR)/assert.h
equiv.o: $(CDIR)/data.h
equiv.o: $(CDIR)/equiv.h
equiv.o: $(CDIR)/extern.h
equiv.o: $(CDIR)/param.h
equiv.o: $(CDIR)/result.h
equiv.o: tables.h
equiv.o: $(CDIR)/types.h
fillem.o: $(CDIR)/assert.h
fillem.o: $(CDIR)/data.h
fillem.o: $(CDIR)/extern.h
fillem.o: mach.c
fillem.o: mach.h
fillem.o: $(CDIR)/param.h
fillem.o: $(CDIR)/regvar.h
fillem.o: $(CDIR)/result.h
fillem.o: tables.h
fillem.o: $(CDIR)/types.h
gencode.o: $(CDIR)/assert.h
gencode.o: $(CDIR)/data.h
gencode.o: $(CDIR)/extern.h
gencode.o: $(CDIR)/param.h
gencode.o: $(CDIR)/result.h
gencode.o: tables.h
gencode.o: $(CDIR)/types.h
glosym.o: $(CDIR)/glosym.h
glosym.o: $(CDIR)/param.h
glosym.o: tables.h
glosym.o: $(CDIR)/types.h
main.o: $(CDIR)/param.h
move.o: $(CDIR)/assert.h
move.o: $(CDIR)/data.h
move.o: $(CDIR)/extern.h
move.o: $(CDIR)/param.h
move.o: $(CDIR)/result.h
move.o: tables.h
move.o: $(CDIR)/types.h
nextem.o: $(CDIR)/assert.h
nextem.o: $(CDIR)/data.h
nextem.o: $(CDIR)/extern.h
nextem.o: $(CDIR)/param.h
nextem.o: $(CDIR)/result.h
nextem.o: tables.h
nextem.o: $(CDIR)/types.h
reg.o: $(CDIR)/assert.h
reg.o: $(CDIR)/data.h
reg.o: $(CDIR)/extern.h
reg.o: $(CDIR)/param.h
reg.o: $(CDIR)/result.h
reg.o: tables.h
reg.o: $(CDIR)/types.h
regvar.o: $(CDIR)/assert.h
regvar.o: $(CDIR)/data.h
regvar.o: $(CDIR)/extern.h
regvar.o: $(CDIR)/param.h
regvar.o: $(CDIR)/regvar.h
regvar.o: $(CDIR)/result.h
regvar.o: tables.h
regvar.o: $(CDIR)/types.h
salloc.o: $(CDIR)/assert.h
salloc.o: $(CDIR)/data.h
salloc.o: $(CDIR)/extern.h
salloc.o: $(CDIR)/param.h
salloc.o: $(CDIR)/result.h
salloc.o: tables.h
salloc.o: $(CDIR)/types.h
state.o: $(CDIR)/assert.h
state.o: $(CDIR)/data.h
state.o: $(CDIR)/extern.h
state.o: $(CDIR)/param.h
state.o: $(CDIR)/result.h
state.o: $(CDIR)/state.h
state.o: tables.h
state.o: $(CDIR)/types.h
subr.o: $(CDIR)/assert.h
subr.o: $(CDIR)/data.h
subr.o: $(CDIR)/extern.h
subr.o: $(CDIR)/param.h
subr.o: $(CDIR)/result.h
subr.o: tables.h
subr.o: $(CDIR)/types.h
var.o: $(CDIR)/data.h
var.o: $(CDIR)/param.h
var.o: $(CDIR)/result.h
var.o: tables.h
var.o: $(CDIR)/types.h

View File

@@ -1,171 +0,0 @@
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
/*
* (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: Hans van Staveren
*/
/*
* machine dependent back end routines for the PDP-11
*/
/* #define REGPATCH /* save all registers in markblock */
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,"\t%o;%o\n",(int)(l>>16),(int)l);
}
con_float() {
double f;
register short *p,i;
if (argval != 4 && argval != 8)
fatal("bad fcon size");
f = atof(str);
p = (short *) &f;
i = *p++;
if (argval == 8) {
fprintf(codefile,"\t%o;%o;",i,*p++);
i = *p++;
}
fprintf(codefile,"\t%o;%o\n",i,*p++);
}
#ifdef REGVARS
char Rstring[10] = "RT";
regscore(off,size,typ,score,totyp) long off; {
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); /* estimated # of words of profit */
}
i_regsave() {
Rstring[2] = 0;
}
f_regsave() {}
regsave(regstr,off,size) char *regstr; long off; {
fprintf(codefile,"/ Local %ld into %s\n",off,regstr);
#ifndef REGPATCH
fprintf(codefile,"mov %s,-(sp)\n",regstr);
#endif
strcat(Rstring,regstr);
if (off>=0)
fprintf(codefile,"mov 0%lo(r5),%s\n",off,regstr);
}
regreturn() {
#ifdef REGPATCH
fprintf(codefile,"jmp eret\n");
#else
fprintf(codefile,"jmp %s\n",Rstring);
#endif
}
#endif
prolog(nlocals) full nlocals; {
#ifdef REGPATCH
fprintf(codefile,"mov r2,-(sp)\nmov r4,-(sp)\n");
#endif
fprintf(codefile,"mov r5,-(sp)\nmov sp,r5\n");
if (nlocals == 0)
return;
if (nlocals == 2)
fprintf(codefile,"tst -(sp)\n");
else
fprintf(codefile,"sub $0%o,sp\n",nlocals);
}
dlbdlb(as,ls) string as,ls; {
if (strlen(as)+strlen(ls)+2<sizeof(labstr)) {
strcat(ls,":");
strcat(ls,as);
} else
fatal("too many consecutive labels");
}
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\n",argstr) ;
break ;
}
}
default :
while ( getarg(any_ptyp) != sp_cend ) ;
break ;
}
}
char *segname[] = {
".text", /* SEGTXT */
".data", /* SEGCON */
".data", /* SEGROM */
".bss" /* SEGBSS */
};

View File

@@ -1,24 +0,0 @@
/* $Header$ */
#define ex_ap(y) fprintf(codefile,".globl %s\n",y)
#define in_ap(y) /* nothing */
#define newplb(x) fprintf(codefile,"%s:\n",x)
#define newilb(x) fprintf(codefile,"%s:\n",x)
#define newdlb(x) fprintf(codefile,"%s:\n",x)
#define newlbss(l,x) fprintf(codefile,"%s:.=.+0%o\n",l,x);
#define cst_fmt "$0%o"
#define off_fmt "0%o"
#define ilb_fmt "I%02x%x"
#define dlb_fmt "_%d"
#define hol_fmt "hol%d"
#define hol_off "0%o+hol%d"
#define con_cst(x) fprintf(codefile,"0%o\n",x)
#define con_ilb(x) fprintf(codefile,"%s\n",x)
#define con_dlb(x) fprintf(codefile,"%s\n",x)
#define id_first '_'
#define BSS_INIT 0

View File

@@ -1,130 +0,0 @@
#include <stdio.h>
/*
* (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: Hans van Staveren
*/
char buf[512];
main() {
register n,sa;
register char *p;
sa=0;
for (;;) {
getline(buf);
if (n=stackadjust()) {
sa += n;
continue;
}
if (nullinstruction())
continue;
if (sa) {
if (buf[0]=='t' && buf[1]=='s' && buf[2]=='t' && buf[3]==' ') {
sa -= 2;
buf[0]='m';
buf[1]='o';
buf[2]='v';
strcat(buf,",(sp)+");
} else if (buf[0]=='m' && buf[1]=='o' && buf[2]=='v' &&
buf[3]==' ' && (p=index(&buf[5],','))!=0 &&
p[1]=='-' && p[2]=='(' && p[3]=='s') {
sa -= 2;
p[1]=' ';
}
}
switch(sa) {
case 0:break;
case 2:puts("tst (sp)+");sa=0;break;
case 4:puts("cmp (sp)+,(sp)+");sa=0;break;
case 6:puts("add $6.,sp");sa=0;break;
}
puts(buf);
}
}
getline(buf) register char *buf; {
register c;
while ((c=getchar())==' ' || c=='\t')
;
if (c==EOF)
exit(0);
do *buf++=c;
while ((c=getchar())!='\n');
*buf=0;
}
stackadjust() {
if (buf[0]=='t' &&
buf[1]=='s' &&
buf[2]=='t' &&
buf[3]==' ' &&
buf[4]=='(' &&
buf[5]=='s' &&
buf[6]=='p' &&
buf[7]==')' &&
buf[8]=='+') return(2);
if (buf[0]=='c' &&
buf[1]=='m' &&
buf[2]=='p' &&
buf[3]==' ' &&
buf[4]=='(' &&
buf[5]=='s' &&
buf[6]=='p' &&
buf[7]==')' &&
buf[8]=='+' &&
buf[9]==',' &&
buf[10]=='(' &&
buf[11]=='s' &&
buf[12]=='p' &&
buf[13]==')' &&
buf[14]=='+') return(4);
if (buf[0]=='a' &&
buf[1]=='d' &&
buf[2]=='d' &&
buf[3]==' ' &&
buf[4]=='$' &&
buf[5]=='6' &&
buf[6]=='.' &&
buf[7]==',' &&
buf[8]=='s' &&
buf[9]=='p' &&
buf[10]==0) return(6);
return(0);
}
nullinstruction() {
register char *p;
if (buf[4]=='$' && buf[5]=='0' && buf[6]=='.' && buf[7]==',') {
p=index(buf,'-');
if (p!=0 && p[1]=='(')
return(0);
p=index(buf,'+');
if (p!=0 && p[-1]==')')
return(0);
if (buf[0]=='b' && buf[1]=='i' && (buf[2]=='s' || buf[2]=='c'))
return(1);
if (buf[0]=='a' && buf[1]=='d' && buf[2]=='d')
return(1);
if (buf[0]=='s' && buf[1]=='u' && buf[2]=='b')
return(1);
}
return(0);
}

View File

@@ -34,8 +34,8 @@
*
*/
/* #define REGPATCH /* save all registers in link block */
/* #define UNTESTED /* include untested rules */
/* #define REGPATCH \* save all registers in link block */
/* #define UNTESTED \* include untested rules */
#ifdef REGPATCH
#define SL 8
@@ -48,7 +48,7 @@
#define NC nocoercions:
/* options */
/* #define DORCK /* rck is expanded instead of thrown away */
/* #define DORCK \* rck is expanded instead of thrown away */
#define REGVARS /* use register variables */
EM_WSIZE=2
@@ -361,6 +361,8 @@ lol stf inreg($1)!=2 | xsource2 |
move(%[1],{regind2,%[a],tostring($2)}) | | |
lae lol ads sti $3==2 && inreg($2)==2 | |
| {regconst2, regvar($2), $1} | sti $4 |
lae lol ads loi $3==2 && inreg($2)==2 | |
| {regconst2, regvar($2), $1} | loi $4 |
#endif
sti $1==2 | REG xsource2 |
INDSTORE
@@ -383,50 +385,50 @@ sti $1==2 | REG xsource2 |
sti $1==1 | REG source1or2 |
INDSTORE
move(%[2],{regdef1,%[1]}) | | |
... | NC regconst2 source1or2 |
... | regconst2 source1or2 |
INDSTORE
move(%[2],{regind1,%[1.reg],%[1.ind]}) | | |
... | NC ADDR_EXTERNAL source1or2 |
... | ADDR_EXTERNAL source1or2 |
INDSTORE
move(%[2],{relative1,%[1.ind]}) | | |
... | NC ADDR_LOCAL source1or2 |
... | ADDR_LOCAL source1or2 |
INDSTORE
move(%[2],{regind1, lb, tostring(%[1.ind])}) | | |
... | NC relative2 source1or2 |
... | relative2 source1or2 |
INDSTORE
move(%[2],{reldef1,%[1.ind]}) | | |
... | NC regind2 source1or2 |
... | regind2 source1or2 |
INDSTORE
move(%[2],{reginddef1,%[1.reg],%[1.ind]}) | | |
sti $1==4 | NC dadres2 FLT_REG |
sti $1==4 | dadres2 FLT_REG |
INDSTORE
"movfo %[2],*%[1]"
samecc | | |
... | NC dadres2 ftolong |
... | dadres2 ftolong |
INDSTORE
"setl\nmovfi %[2.reg],*%[1]\nseti"
samecc | | |
... | NC regconst2 FLT_REG |
... | regconst2 FLT_REG |
INDSTORE
"movfo %[2],%[1.ind](%[1.reg])"
samecc | | |
... | NC regconst2 ftolong |
... | regconst2 ftolong |
INDSTORE
"setl\nmovfi %[2.reg],%[1.ind](%[1.reg])\nseti"
samecc | | |
... | NC ADDR_LOCAL FLT_REG |
... | ADDR_LOCAL FLT_REG |
INDSTORE
"movfo %[2],%[1.ind](r5)"
samecc | | |
... | NC ADDR_LOCAL ftolong |
... | ADDR_LOCAL ftolong |
INDSTORE
"setl\nmovfi %[2.reg],%[1.ind](r5)\nseti"
samecc | | |
... | NC ADDR_EXTERNAL FLT_REG |
... | ADDR_EXTERNAL FLT_REG |
INDSTORE
"movfo %[2],%[1.ind]"
samecc | | |
... | NC ADDR_EXTERNAL ftolong |
... | ADDR_EXTERNAL ftolong |
INDSTORE
"setl\nmovfi %[2.reg],%[1.ind]\nseti"
samecc | | |
@@ -438,22 +440,29 @@ sti $1==4 | NC dadres2 FLT_REG |
"mov (sp)+,(%[1])+"
"mov (sp)+,(%[1])"
erase(%[1]) | | | (4,2040)
sti $1==8 | NC dadres2 DBL_REG |
sti $1==8 | dadres2 DBL_REG |
INDSTORE
"movf %[2],*%[1]"
samecc | | |
... | NC regconst2 DBL_REG |
... | regconst2 DBL_REG |
INDSTORE
"movf %[2],%[1.ind](%[1.reg])"
samecc | | |
... | NC ADDR_LOCAL DBL_REG |
... | ADDR_LOCAL DBL_REG |
INDSTORE
"movf %[2],%[1.ind](r5)"
samecc | | |
... | NC ADDR_EXTERNAL DBL_REG |
... | ADDR_EXTERNAL DBL_REG |
INDSTORE
"movf %[2],%[1.ind]"
samecc | | |
... | SCR_REG regdef8 |
INDSTORE
"mov (%[2.reg]),(%[1])+"
"mov 2(%[2.reg]),(%[1])+"
"mov 4(%[2.reg]),(%[1])+"
"mov 6(%[2.reg]),(%[1])"
erase(%[1]) | | |
... | SCR_REG regind8 |
INDSTORE
"mov %[2.ind](%[2.reg]),(%[1])+"
@@ -558,8 +567,13 @@ adi $1==2 | NC SCR_REG CONST2 | | {regconst2,%[1],tostring(%[2.num])} | |
... | NC SCR_REG regconst2 |
"add %[2.reg],%[1]" erase(%[1]) |
{regconst2,%[1],%[2.ind]} | | (2,450)
... | NC CONST2+ADDR_EXTERNAL+ADDR_LOCAL+regconst2 SCR_REG |
| %[1] %[2] | adi 2 |
... | NC source2-REG CONST2+ADDR_EXTERNAL+ADDR_LOCAL |
allocate(%[1],REG=%[1]) | %[2] %[a] | adi 2 |
... | NC source1 CONST2+ADDR_EXTERNAL+ADDR_LOCAL |
allocate(%[1],REG={CONST2, 0})
"bisb %[1],%[a]" | %[2] %[a] | adi 2 |
... | NC regconst2 CONST2 | |
{regconst2,%[1.reg],
tostring(%[2.num])+"+"+%[1.ind]} | |
@@ -587,6 +601,16 @@ adi $1==2 | NC SCR_REG CONST2 | | {regconst2,%[1],tostring(%[2.num])} | |
... | source2 SCR_REG |
"add %[1],%[2]"
setcc(%[2]) erase(%[2]) | %[2] | | (2,450)+%[1]
ldc adi $2==4 && highw(1)==0 | SCR_REG SCR_REG |
"add $$%(loww(1)%),%[2]"
"adc %[1]"
erase(%[1]) erase(%[2]) | %[2] %[1] | |
ldc adi $2==4 | SCR_REG SCR_REG |
"add $$%(loww(1)%),%[2]"
"adc %[1]"
"add $$%(highw(1)%),%[1]"
erase(%[1]) erase(%[2]) | %[2] %[1] | |
adi $1==4 | SCR_REG SCR_REG source2 source2 |
"add %[4],%[2]"
"adc %[1]"
@@ -617,6 +641,7 @@ adi !defined($1)| source2 |
move(%[1],r0)
"jsr pc,adi~" | | |
#endif
loc sbi $2==2 | | | | loc 0-$1 adi 2 |
sbi $1==2 | source2 SCR_REG |
"sub %[1],%[2]"
setcc(%[2]) erase(%[2]) | %[2] | | (2,450)+%[1]
@@ -624,6 +649,15 @@ sbi $1==2 | source2 SCR_REG |
"sub %[2],%[1]"
"neg %[1]"
setcc(%[1]) erase(%[1]) | %[1] | | (4,750)+%[2]
ldc sbi $2==4 && highw(1)==0 | SCR_REG SCR_REG |
"sub $$%(loww(1)%),%[2]"
"sbc %[1]"
erase(%[1]) erase(%[2]) | %[2] %[1] | |
ldc sbi $2==4 | SCR_REG SCR_REG |
"sub $$%(loww(1)%),%[2]"
"sbc %[1]"
"sub $$%(highw(1)%),%[1]"
erase(%[1]) erase(%[2]) | %[2] %[1] | |
sbi $1==4 | source2-REG source2-REG SCR_REG SCR_REG |
"sub %[2],%[4]"
"sbc %[3]"
@@ -768,6 +802,11 @@ mlu !defined($1)| source2 |
move(%[1],r0)
"jsr pc,mlu~" | | |
#endif
loc dvu $1>0 && $1<=32767 && $2==2 | source2 |
allocate(%[1],REG_PAIR)
move(%[1],%[a.2])
"clr %[a.1]"
"div $$$1,%[a.1]" | %[a.1] | |
dvu $1==2 | | remove(all)
"jsr pc,dvu2~" | r0 | |
dvu $1==4 | | remove(all)
@@ -778,6 +817,11 @@ dvu !defined($1)| source2 |
move(%[1],r0)
"jsr pc,dvu~" | | |
#endif
loc rmu $1>0 && $1<=32767 && $2==2 | source2 |
allocate(%[1],REG_PAIR)
move(%[1],%[a.2])
"clr %[a.1]"
"div $$$1,%[a.1]" | %[a.2] | |
rmu $1==2 | | remove(all)
"jsr pc,rmu2~" | r1 | |
rmu $1==4 | | remove(all)
@@ -789,6 +833,7 @@ rmu !defined($1)| source2 |
"jsr pc,rmu~" | | |
#endif
slu | | | | sli $1 |
loc slu | | | | loc $1 sli $2 |
sru $1==2 | SCR_REG xsource2 |
allocate(%[2],REG_PAIR)
move(%[2],%[a.2])
@@ -1007,7 +1052,11 @@ lil ngi sil $1==$3 && $2==2 && inreg($1)==2 | |
INDSTORE
"neg *%(regvar($1)%)" | | |
lil inc sil $1==$3 && inreg($1)==2 | | INDSTORE
"inc *%(regvar($1)%)" | | |
"inc *%(regvar($1)%)"
setcc({regdef2, regvar($1)}) | | |
lil dec sil $1==$3 && inreg($1)==2 | | INDSTORE
"dec *%(regvar($1)%)"
setcc({regdef2, regvar($1)}) | | |
lol adi stl $2==2 && $1==$3 && inreg($1)==2 | source2 |
remove(regvar($1))
"add %[1],%(regvar($1)%)"
@@ -1020,23 +1069,74 @@ lol lol adp stl loi $1==$2 && $2==$4 && inreg($1)==2 && $3==2 && $5==2 | |
allocate(REG)
remove(regvar($1))
"mov (%(regvar($1)%))+,%[a]" | %[a] | |
lol lol adp stl sti $1==$2 && $2==$4 && inreg($1)==2 && $3==1 && $5==1 | source1or2|
lol sti lol adp stl $1==$3 && $3==$5 && inreg($1)==2 && $2==1 && $4==1 | source1or2|
remove(regvar($1))
"movb %[1],(%(regvar($1)%))+" | | |
lol lol adp stl sti $1==$2 && $2==$4 && inreg($1)==2 && $3==2 && $5==2 | source2 |
sil lol adp stl $1==$2 && $2==$4 && inreg($1)==2 && $3==2 | source2 |
remove(regvar($1))
"mov %[1],(%(regvar($1)%))+" | | |
lol lol adp stl $1==$2 && $2==$4 && inreg($1)==2 | |
allocate(REG=regvar($1)) | %[a]
| lol $2 adp $3 stl $2 |
lol lol adp stl $1==$2 && $2==$4 | |
allocate(REG={LOCAL2, $1, 2}) | %[a]
| lol $2 adp $3 stl $2 |
lol inl $1==$2 && inreg($1)==2 | |
allocate(REG=regvar($1)) | %[a]
| inl $2 |
lol inl $1==$2 | |
allocate(REG={LOCAL2, $1, 2}) | %[a]
| inl $2 |
lol del $1==$2 && inreg($1)==2 | |
allocate(REG=regvar($1)) | %[a]
| del $2 |
lol del $1==$2 | |
allocate(REG={LOCAL2, $1, 2}) | %[a]
| del $2 |
lol adp stl $1==$3 && $2==1 && inreg($1)==2 | |
remove(regvar($1))
"inc %(regvar($1)%)"
erase(regvar($1)) | | |
lol adp stl $1==$3 && $2==0-1 && inreg($1)==2 | |
remove(regvar($1))
"dec %(regvar($1)%)"
erase(regvar($1)) | | |
lol adp stl $1==$3 && inreg($1)==2 | |
remove(regvar($1))
"add $$$2,%(regvar($1)%)"
erase(regvar($1)) | | |
lil lil adp sil $2==$4 && inreg($1)==2 | |
allocate(REG={regdef2, regvar($1)})
| %[a] | lil $2 adp $3 sil $2 |
lil adp sil $1==$3 && $2==1 && inreg($1)==2 | |
INDSTORE
"inc *%(regvar($1)%)" | | |
lil adp sil $1==$3 && $2==0-1 && inreg($1)==2 | |
INDSTORE
"dec *%(regvar($1)%)" | | |
lil adp sil $1==$3 && inreg($1)==2 | |
INDSTORE
"add $$$2,*%(regvar($1)%)" | | |
lol lof inc lol stf $1==$4 && $2==$5 && inreg($1)==2 | |
INDSTORE
"inc $2(%(regvar($1)%))"
setcc({regind2, regvar($1), tostring($2)}) | | |
lol lof dec lol stf $1==$4 && $2==$5 && inreg($1)==2 | |
INDSTORE
"dec $2(%(regvar($1)%))"
setcc({regind2, regvar($1), tostring($2)}) | | |
lol lof adp lol stf $1==$4 && $2==$5 && inreg($1)==2 && $3==1 | |
INDSTORE
"inc $2(%(regvar($1)%))"
setcc({regind2, regvar($1), tostring($2)}) | | |
lol lof adp lol stf $1==$4 && $2==$5 && inreg($1)==2 && $3==0-1 | |
INDSTORE
"dec $2(%(regvar($1)%))"
setcc({regind2, regvar($1), tostring($2)}) | | |
lol lof adp lol stf $1==$4 && $2==$5 && inreg($1)==2 | |
INDSTORE
"add $3,$2(%(regvar($1)%))"
setcc({regind2, regvar($1), tostring($2)}) | | |
#endif
lol loc sbi stl $1==$4 && $3==2 | |
remove(indordef)
@@ -1051,7 +1151,11 @@ lol ngi stl $1==$3 && $2==2 | |
lil ngi sil $1==$3 && $2==2 | | INDSTORE
"neg *$1(r5)" | | |
lil inc sil $1==$3 | | INDSTORE
"inc *$1(r5)" | | |
"inc *$1(r5)"
setcc({reginddef2, lb, tostring($1)}) | | |
lil dec sil $1==$3 | | INDSTORE
"dec *$1(r5)"
setcc({reginddef2, lb, tostring($1)}) | | |
lol adi stl $2==2 && $1==$3 | source2 |
remove(indordef)
remove(locals, %[ind] <= $1 && %[ind]+%[size] > $1)
@@ -1062,19 +1166,121 @@ lol adp stl $1==$3 && $2==1 | |
remove(locals, %[ind] <= $1 && %[ind]+%[size] > $1)
"inc $1(r5)"
setcc({LOCAL2,$1,2}) | | |
lol adp stl $1==$3 && $2==0-1 | |
remove(indordef)
remove(locals, %[ind] <= $1 && %[ind]+%[size] > $1)
"dec $1(r5)"
setcc({LOCAL2,$1,2}) | | |
lol adp stl $1==$3 | |
remove(indordef)
remove(locals, %[ind] <= $1 && %[ind]+%[size] > $1)
"add $$$2,$1(r5)"
setcc({LOCAL2,$1,2}) | | |
lil lil adp sil $2==$4 | |
allocate(REG={reginddef2, lb, tostring($1)})
| %[a] | lil $2 adp $3 sil $2 |
lil adp sil $1==$3 && $2==1 | |
INDSTORE
"inc *$1(r5)"
setcc({LOCAL2,$1,2}) | | |
lil adp sil $1==$3 && $2==0-1 | |
INDSTORE
"dec *$1(r5)"
setcc({LOCAL2,$1,2}) | | |
lil adp sil $1==$3 | |
INDSTORE
"add $$$2,*$1(r5)"
setcc({LOCAL2,$1,2}) | | |
loe adi ste $2==2 && $1==$3 | source2 |
remove(posextern)
"add %[1],$1"
setcc({relative2,$1}) | | |
loe adp ste $1==$3 && $2==1 | |
remove(posextern)
"inc $1"
setcc({relative2,$1}) | | |
loe adp ste $1==$3 && $2==0-1 | |
remove(posextern)
"dec $1"
setcc({relative2,$1}) | | |
loe adp ste $1==$3 | |
remove(posextern)
"add $$$2,$1"
setcc({relative2,$1}) | | |
loe loi loe loi adp loe sti $3==$6 && $2==2 && $4==2 && $7==2 | |
allocate(REG={reldef2, $1})
| %[a] | loe $3 loi $4 adp $5 loe $6 sti $7 |
loe loi adp loe sti $1==$4 && $2==2 && $5==2 && $3==1 | |
INDSTORE
"inc *$1"
setcc({reldef2,$1}) | | |
loe loi adp loe sti $1==$4 && $2==2 && $5==2 && $3==0-1 | |
INDSTORE
"dec *$1"
setcc({reldef2,$1}) | | |
loe loi adp loe sti $1==$4 && $2==2 && $5==2 | |
INDSTORE
"add $$$3,*$1"
setcc({reldef2,$1}) | | |
lol lof inc lol stf $1==$4 && $2==$5 | |
INDSTORE
allocate(REG={LOCAL2, $1, 2})
"inc $2(%[a])"
setcc({regind2, %[a], tostring($2)}) | | |
lol lof dec lol stf $1==$4 && $2==$5 | |
INDSTORE
allocate(REG={LOCAL2, $1, 2})
"dec $2(%[a])"
setcc({regind2, %[a], tostring($2)}) | | |
lol lof adp lol stf $1==$4 && $2==$5 && $3==1 | |
INDSTORE
allocate(REG={LOCAL2, $1, 2})
"inc $2(%[a])"
setcc({regind2, %[a], tostring($2)}) | | |
lol lof adp lol stf $1==$4 && $2==$5 && $3==0-1 | |
INDSTORE
allocate(REG={LOCAL2, $1, 2})
"dec $2(%[a])"
setcc({regind2, %[a], tostring($2)}) | | |
lol lof adp lol stf $1==$4 && $2==$5 | |
INDSTORE
allocate(REG={LOCAL2, $1, 2})
"add $3,$2(%[a])"
setcc({regind2, %[a], tostring($2)}) | | |
loe lof inc loe stf $1==$4 && $2==$5 | |
INDSTORE
allocate(REG={relative2, $1})
"inc $2(%[a])"
setcc({regind2, %[a], tostring($2)}) | | |
loe lof dec loe stf $1==$4 && $2==$5 | |
INDSTORE
allocate(REG={relative2, $1})
"dec $2(%[a])"
setcc({regind2, %[a], tostring($2)}) | | |
loe lof adp loe stf $1==$4 && $2==$5 && $3==1 | |
INDSTORE
allocate(REG={relative2, $1})
"inc $2(%[a])"
setcc({regind2, %[a], tostring($2)}) | | |
loe lof adp loe stf $1==$4 && $2==$5 && $3==0-1 | |
INDSTORE
allocate(REG={relative2, $1})
"dec $2(%[a])"
setcc({regind2, %[a], tostring($2)}) | | |
loe lof adp loe stf $1==$4 && $2==$5 | |
INDSTORE
allocate(REG={relative2, $1})
"add $3,$2(%[a])"
setcc({regind2, %[a], tostring($2)}) | | |
loe ine $1==$2 | |
allocate(REG={relative2, $1}) | %[a]
| ine $2 |
loe dee $1==$2 | |
allocate(REG={relative2, $1}) | %[a]
| dee $2 |
loe loe adp ste $1==$2 && $2==$4 | |
allocate(REG={relative2, $1}) | %[a]
| loe $2 adp $3 ste $2 |
#ifdef REGVARS
lol ior stl $2==2 && $1==$3 && inreg($1)==2 | source2 |
remove(regvar($1))
@@ -1207,6 +1413,7 @@ loc loc ciu | | | | loc $1 loc $2 cuu |
loc loc cui | | | | loc $1 loc $2 cuu |
loc loc cuu $1==2 && $2==4 | | | {CONST2,0} | |
loc loc cuu $1==4 && $2==2 | source2 | | | |
loc loc cuu $1==$2 | | | | |
loc loc cfi | | | | loc $1 loc $2 cfu |
loc loc cfu $1==4 && $2==2 | FLT_REG | | {ftoint,%[1]} | |
loc loc cfu $1==4 && $2==4 | FLT_REG | | {ftolong,%[1]} | |
@@ -1295,17 +1502,25 @@ and $1==2 | CONST2 SCR_REG |
"bic %[1],%[2]"
setcc(%[2])
erase(%[1]) erase(%[2]) | %[2] | | (4,600)
ldc and $2==4 && highw(1)==0 | source2 SCR_REG |
"bic $$%(~loww(1)%),%[2]"
erase(%[2]) | %[2] {CONST2, 0} | |
ldc and $2==4 && highw(1)==0-1 | source2 SCR_REG |
"bic $$%(~loww(1)%),%[2]"
erase(%[2]) | %[2] %[1] | |
ldc and $2==4 | SCR_REG SCR_REG |
"bic $$%(~highw(1)%),%[1]"
"bic $$%(~loww(1)%),%[2]"
erase(%[1]) erase(%[2]) | %[2] %[1] | |
and defined($1) | | remove(all)
move({CONST2,$1}, r0)
"jsr pc,and~"
erase(r0) | | |
#ifdef UNTESTED
and !defined($1)| source2 |
remove(all)
move(%[1],r0)
"jsr pc,and~"
erase(r0) | | |
#endif
ior $1==2 | SCR_REG source2 |
"bis %[2],%[1]"
setcc(%[1])
@@ -1314,6 +1529,16 @@ ior $1==2 | SCR_REG source2 |
"bis %[1],%[2]"
setcc(%[2])
erase(%[2]) | %[2] | | (2,450)+%[1]
ldc ior $2==4 && highw(1)==0 | source2 SCR_REG |
"bis $$%(loww(1)%),%[2]"
erase(%[2]) | %[2] %[1] | |
ldc ior $2==4 && highw(1)==0-1 | source2 SCR_REG |
"bis $$%(loww(1)%),%[2]"
erase(%[2]) | {CONST2, 0-1} %[1] | |
ldc ior $2==4 | SCR_REG SCR_REG |
"bis $$%(highw(1)%),%[1]"
"bis $$%(loww(1)%),%[2]"
erase(%[1]) erase(%[2]) | %[2] %[1] | |
ior $1==8 | NC source2 source2 source2 source2 |
remove(all)
"bis %[1],(sp)"
@@ -1334,7 +1559,6 @@ ior defined($1) | | remove(all)
"1:\tbis (sp)+,(%[a])+"
"sob %[b],1b"
erase(%[a]) erase(%[b]) | | | (12,2100+$1*975)
#ifdef UNTESTED
ior !defined($1)| SCR_REG |
remove(all)
allocate(REG=%[1])
@@ -1343,7 +1567,6 @@ ior !defined($1)| SCR_REG |
"1:\tbis (sp)+,(%[a])+"
"sob %[1],1b"
erase(%[1]) erase(%[a]) | | |
#endif
xor $1==2 | REG SCR_REG |
"xor %[1],%[2]"
setcc(%[2])
@@ -1356,13 +1579,11 @@ xor defined($1) | | remove(all)
move({CONST2,$1},r0)
"jsr pc,xor~"
erase(r0) | | |
#ifdef UNTESTED
xor !defined($1)| source2 |
remove(all)
move(%[1],r0)
"jsr pc,xor~"
erase(r0) | | |
#endif
com $1==2 | SCR_REG |
"com %[1]"
setcc(%[1])
@@ -1373,7 +1594,6 @@ com defined($1) | | remove(all)
"1:\tcom (%[b])+"
"sob %[a],1b"
erase(%[a]) | | | (10,1800+$1*825)
#ifdef UNTESTED
com !defined($1)| SCR_REG |
remove(all)
allocate(REG)
@@ -1382,7 +1602,6 @@ com !defined($1)| SCR_REG |
"1:\tcom (%[a])+"
"sob %[1],1b"
erase(%[1]) | | |
#endif
rol $1==2 | CONST2 SCR_ODD_REG |
"ashc $$%(%[1.num]-16%),%[2]"
setcc(%[2])
@@ -1586,6 +1805,10 @@ cmi $1==2 | source2 SCR_REG |
"neg %[1]"
setcc(%[1])
erase(%[1]) | %[1] | |
ldc cmi zlt highw(1)==0 && loww(1)==0 && $2==4 | source2 source2 |
| %[1] | zlt $3 |
ldc cmi zge highw(1)==0 && loww(1)==0 && $2==4 | source2 source2 |
| %[1] | zge $3 |
cmi $1==4 | | remove(all)
"jsr pc,cmi4~" | r0 | |
#ifdef UNTESTED
@@ -2065,11 +2288,19 @@ ble | source2 source2 |
remove(all)
"cmp %[2],%[1]"
"jle $1" | | |
beq | source2 source2 |
beq | NC source1 source1 |
remove(all)
"cmpb %[2],%[1]"
"jeq $1" | | |
... | source2 source2 |
remove(all)
"cmp %[2],%[1]"
"jeq $1" | | |
bne | source2 source2 |
bne | NC source1 source1 |
remove(all)
"cmpb %[2],%[1]"
"jne $1" | | |
... | source2 source2 |
remove(all)
"cmp %[2],%[1]"
"jne $1" | | |
@@ -2218,11 +2449,27 @@ cmf zge $1==8 | DBL_REG double8 |
"cmpf %[1],%[2]\ncfcc"
"jle $2" | | |
and zeq $1==2 | source2 source2 |
and zeq $1==2 | source1 source1or2 |
remove(all)
"bitb %[1],%[2]"
"jeq $2" | | |
... | source1or2 source1 |
remove(all)
"bitb %[1],%[2]"
"jeq $2" | | |
... | source2 source2 |
remove(all)
"bit %[1],%[2]"
"jeq $2" | | |
and zne $1==2 | source2 source2 |
and zne $1==2 | source1 source1or2 |
remove(all)
"bitb %[1],%[2]"
"jne $2" | | |
... | source1or2 source1 |
remove(all)
"bitb %[1],%[2]"
"jne $2" | | |
... | source2 source2 |
remove(all)
"bit %[1],%[2]"
"jne $2" | | |
@@ -2282,7 +2529,8 @@ ret | | remove(all)
* Group 15 : Miscellaneous instructions *
************************************************/
asp $1==2 | | remove(all)
asp $1==2 | NC xsource2 | | | |
... | | remove(all)
"tst (sp)+" | | |
asp $1==4 | | remove(all)
"cmp (sp)+,(sp)+" | | |
@@ -2319,19 +2567,18 @@ blm | SCR_REG SCR_REG |
allocate(REG={CONST2,$1/2})
"1:mov (%[2])+,(%[1])+\nsob %[a],1b"
erase(%[1]) erase (%[2]) erase(%[a]) | | |
bls $1==2 | source2 |
remove(all)
move(%[1],r0)
"jsr pc,blm~"
erase(r01) | | |
bls $1==2 | SCR_REG SCR_REG SCR_REG |
"asr %[1]\nbeq 2f"
"1:mov (%[3])+,(%[2])+\nsob %[1],1b\n2:"
erase(%[1]) erase (%[2]) erase(%[3]) | | |
#ifdef UNTESTED
bls !defined($1)| source2 source2 |
bls !defined($1)| source2 SCR_REG SCR_REG SCR_REG |
remove(all)
"cmp %[1],$$2"
"beq 1f;jmp unknown~;1:"
move(%[2],r0)
"jsr pc,blm~"
erase(r01) | | |
"asr %[2]\nbeq 2f"
"1:mov (%[4])+,(%[3])+\nsob %[2],1b\n2:"
erase(%[2]) erase (%[3]) erase(%[4]) | | |
#endif
lae csa $2==2 | source2 |
remove(all)
@@ -2352,11 +2599,16 @@ csa !defined($1)| source2 |
"mov (sp)+,r1"
"jmp csa~" | | |
#endif
lae csb $2==2 | source2 |
lae csb $2==2 | NC source2 |
remove(all)
move(%[1],r1)
move({ADDR_EXTERNAL,$1},r0)
"jmp csb~" | | |
... | |
remove(all)
move({ADDR_EXTERNAL,$1},r0)
"mov (sp)+,r1"
"jmp csb~" | | |
csb $1==2 | |
remove(all)
@@ -2403,8 +2655,10 @@ gto | | remove(all)
"jmp gto~" | | |
fil | | "mov $$$1,hol0+4" | | |
lim | | | { relative2, "trpim~"} | |
lin | | "mov $$$1,hol0" | | |
lni | | "inc hol0" | | |
lin | | "mov $$$1,hol0"
"jsr pc,_u_LiB" | | |
lni | | "inc hol0"
"jsr pc,_u_LiB" | | |
lor $1==0 | | | lb | |
lor $1==1 | | remove(all)
allocate(REG)

View File

@@ -1,178 +0,0 @@
# $Header$
PREFLAGS=-I../../../h -I. -DNDEBUG
PFLAGS=
CFLAGS=$(PREFLAGS) $(PFLAGS) -O
LDFLAGS=-i $(PFLAGS)
LINTOPTS=-hbxac
LIBS=../../../lib/em_data.a
CDIR=../../proto/cg
CFILES=$(CDIR)/codegen.c $(CDIR)/compute.c $(CDIR)/equiv.c $(CDIR)/fillem.c \
$(CDIR)/gencode.c $(CDIR)/glosym.c $(CDIR)/main.c $(CDIR)/move.c \
$(CDIR)/nextem.c $(CDIR)/reg.c $(CDIR)/regvar.c $(CDIR)/salloc.c \
$(CDIR)/state.c $(CDIR)/subr.c $(CDIR)/var.c
OFILES=codegen.o compute.o equiv.o fillem.o gencode.o glosym.o main.o\
move.o nextem.o reg.o regvar.o salloc.o state.o subr.o var.o
all:
make tables.c
make cg
cg: tables.o $(OFILES)
cc $(LDFLAGS) $(OFILES) tables.o $(LIBS) -o cg
tables.o: tables.c
cc -c $(PREFLAGS) -I$(CDIR) tables.c
codegen.o: $(CDIR)/codegen.c
cc -c $(CFLAGS) $(CDIR)/codegen.c
compute.o: $(CDIR)/compute.c
cc -c $(CFLAGS) $(CDIR)/compute.c
equiv.o: $(CDIR)/equiv.c
cc -c $(CFLAGS) $(CDIR)/equiv.c
fillem.o: $(CDIR)/fillem.c
cc -c $(CFLAGS) $(CDIR)/fillem.c
gencode.o: $(CDIR)/gencode.c
cc -c $(CFLAGS) $(CDIR)/gencode.c
glosym.o: $(CDIR)/glosym.c
cc -c $(CFLAGS) $(CDIR)/glosym.c
main.o: $(CDIR)/main.c
cc -c $(CFLAGS) $(CDIR)/main.c
move.o: $(CDIR)/move.c
cc -c $(CFLAGS) $(CDIR)/move.c
nextem.o: $(CDIR)/nextem.c
cc -c $(CFLAGS) $(CDIR)/nextem.c
reg.o: $(CDIR)/reg.c
cc -c $(CFLAGS) $(CDIR)/reg.c
regvar.o: $(CDIR)/regvar.c
cc -c $(CFLAGS) $(CDIR)/regvar.c
salloc.o: $(CDIR)/salloc.c
cc -c $(CFLAGS) $(CDIR)/salloc.c
state.o: $(CDIR)/state.c
cc -c $(CFLAGS) $(CDIR)/state.c
subr.o: $(CDIR)/subr.c
cc -c $(CFLAGS) $(CDIR)/subr.c
var.o: $(CDIR)/var.c
cc -c $(CFLAGS) $(CDIR)/var.c
install: all
../install cg
cmp: all
-../compare cg
tables.c: table
-mv tables.h tables.h.save
../../../lib/cpp -P table | ../../../lib/cgg > debug.out
-if cmp -s tables.h.save tables.h; then mv tables.h.save tables.h; else exit 0; fi
-if cmp -s /dev/null tables.h; then mv tables.h.save tables.h; else exit 0; fi
lint: $(CFILES)
lint $(LINTOPTS) $(PREFLAGS) $(CFILES)
clean:
rm -f *.o tables.c tables.h debug.out cg tables.h.save
codegen.o: $(CDIR)/assert.h
codegen.o: $(CDIR)/data.h
codegen.o: $(CDIR)/equiv.h
codegen.o: $(CDIR)/extern.h
codegen.o: $(CDIR)/param.h
codegen.o: $(CDIR)/result.h
codegen.o: $(CDIR)/state.h
codegen.o: tables.h
codegen.o: $(CDIR)/types.h
compute.o: $(CDIR)/assert.h
compute.o: $(CDIR)/data.h
compute.o: $(CDIR)/extern.h
compute.o: $(CDIR)/glosym.h
compute.o: $(CDIR)/param.h
compute.o: $(CDIR)/result.h
compute.o: tables.h
compute.o: $(CDIR)/types.h
equiv.o: $(CDIR)/assert.h
equiv.o: $(CDIR)/data.h
equiv.o: $(CDIR)/equiv.h
equiv.o: $(CDIR)/extern.h
equiv.o: $(CDIR)/param.h
equiv.o: $(CDIR)/result.h
equiv.o: tables.h
equiv.o: $(CDIR)/types.h
fillem.o: $(CDIR)/assert.h
fillem.o: $(CDIR)/data.h
fillem.o: $(CDIR)/extern.h
fillem.o: mach.c
fillem.o: mach.h
fillem.o: $(CDIR)/param.h
fillem.o: $(CDIR)/regvar.h
fillem.o: $(CDIR)/result.h
fillem.o: tables.h
fillem.o: $(CDIR)/types.h
gencode.o: $(CDIR)/assert.h
gencode.o: $(CDIR)/data.h
gencode.o: $(CDIR)/extern.h
gencode.o: $(CDIR)/param.h
gencode.o: $(CDIR)/result.h
gencode.o: tables.h
gencode.o: $(CDIR)/types.h
glosym.o: $(CDIR)/glosym.h
glosym.o: $(CDIR)/param.h
glosym.o: tables.h
glosym.o: $(CDIR)/types.h
main.o: $(CDIR)/param.h
move.o: $(CDIR)/assert.h
move.o: $(CDIR)/data.h
move.o: $(CDIR)/extern.h
move.o: $(CDIR)/param.h
move.o: $(CDIR)/result.h
move.o: tables.h
move.o: $(CDIR)/types.h
nextem.o: $(CDIR)/assert.h
nextem.o: $(CDIR)/data.h
nextem.o: $(CDIR)/extern.h
nextem.o: $(CDIR)/param.h
nextem.o: $(CDIR)/result.h
nextem.o: tables.h
nextem.o: $(CDIR)/types.h
reg.o: $(CDIR)/assert.h
reg.o: $(CDIR)/data.h
reg.o: $(CDIR)/extern.h
reg.o: $(CDIR)/param.h
reg.o: $(CDIR)/result.h
reg.o: tables.h
reg.o: $(CDIR)/types.h
regvar.o: $(CDIR)/assert.h
regvar.o: $(CDIR)/data.h
regvar.o: $(CDIR)/extern.h
regvar.o: $(CDIR)/param.h
regvar.o: $(CDIR)/regvar.h
regvar.o: $(CDIR)/result.h
regvar.o: tables.h
regvar.o: $(CDIR)/types.h
salloc.o: $(CDIR)/assert.h
salloc.o: $(CDIR)/data.h
salloc.o: $(CDIR)/extern.h
salloc.o: $(CDIR)/param.h
salloc.o: $(CDIR)/result.h
salloc.o: tables.h
salloc.o: $(CDIR)/types.h
state.o: $(CDIR)/assert.h
state.o: $(CDIR)/data.h
state.o: $(CDIR)/extern.h
state.o: $(CDIR)/param.h
state.o: $(CDIR)/result.h
state.o: $(CDIR)/state.h
state.o: tables.h
state.o: $(CDIR)/types.h
subr.o: $(CDIR)/assert.h
subr.o: $(CDIR)/data.h
subr.o: $(CDIR)/extern.h
subr.o: $(CDIR)/param.h
subr.o: $(CDIR)/result.h
subr.o: tables.h
subr.o: $(CDIR)/types.h
var.o: $(CDIR)/data.h
var.o: $(CDIR)/param.h
var.o: $(CDIR)/result.h
var.o: tables.h
var.o: $(CDIR)/types.h

View File

@@ -1,7 +0,0 @@
/* $Header$ */
#ifndef NDEBUG
#define assert(x) if(!(x)) badassertion("x",__FILE__,__LINE__)
#else
#define assert(x) /* nothing */
#endif

View File

@@ -1,672 +0,0 @@
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include "assert.h"
#include "param.h"
#include "tables.h"
#include "types.h"
#include <cg_pattern.h>
#include "data.h"
#include "result.h"
#include "state.h"
#include "equiv.h"
#include "extern.h"
/*
* (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: Hans van Staveren
*/
#define SHORTCUT /* Stop searching at distance 0 */
#if NREGS >= MAXRULE
#define MAXPOS NREGS
#else
#define MAXPOS MAXRULE
#endif
#define MAXPATTERN 5
#define MAXREPLLEN 5 /* Max length of EM-replacement, should come from boot */
byte startupcode[] = { DO_NEXTEM };
byte *nextem();
unsigned costcalc();
unsigned docoerc();
unsigned stackupto();
string tostring();
#ifdef NDEBUG
#define DEBUG()
#else
#include <stdio.h>
#define DEBUG(string) {if(Debug) fprintf(stderr,"%-*d%s\n",4*level,level,string);}
#endif
#define BROKE() {assert(origcp!=startupcode);DEBUG("BROKE");goto doreturn;}
#define CHKCOST() {if (totalcost>=costlimit) BROKE();}
unsigned codegen(codep,ply,toplevel,costlimit,forced) byte *codep; unsigned costlimit; {
#ifndef NDEBUG
byte *origcp=codep;
static int level=0;
#endif
unsigned totalcost = 0;
byte *bp;
int n;
unsigned mindistance,dist;
register i;
int cindex;
int npos,npos2,pos[MAXPOS],pos2[MAXPOS];
#ifdef STONSTACK
state_t state;
#define SAVEST savestatus(&state)
#define RESTST restorestatus(&state)
#define FREEST /* nothing */
#else
state_p state;
#define SAVEST state=savestatus()
#define RESTST restorestatus(state)
#define FREEST freestatus(state)
#endif
unsigned mincost,t;
int texpno,nodeno;
token_p tp;
tkdef_p tdp;
int tinstno;
struct reginfo *rp,**rpp;
token_t token,mtoken,token2;
int propno;
int exactmatch;
int j;
int decision;
int stringno;
result_t result;
cost_t cost;
int size,lsize,repllen;
int tokexp[MAXPATTERN];
int nregneeded;
token_p regtp[MAXCREG];
c3_p regcp[MAXCREG];
rl_p regls[MAXCREG];
c3_p cp,findcoerc();
int sret;
token_t reptoken[MAXREPLLEN];
int emrepllen,eminstr;
int inscoerc=0;
int stackpad;
struct perm *tup,*ntup,*besttup,*tuples();
#ifndef NDEBUG
level++;
DEBUG("Entering codegen");
#endif
for (;;) {
switch( (*codep++)&037 ) {
default:
assert(FALSE);
/* NOTREACHED */
case DO_NEXTEM:
DEBUG("NEXTEM");
tokpatlen = 0;
nallreg=0;
if (toplevel) {
garbage_collect();
totalcost=0;
} else {
if (--ply <= 0)
goto doreturn;
}
if (stackheight>MAXFSTACK-7)
totalcost += stackupto(&fakestack[6],ply,toplevel);
bp = nextem(toplevel);
if (bp == 0) {
/*
* No pattern found, can be pseudo or error
* in table.
*/
if (toplevel) {
codep--;
DEBUG("pseudo");
dopseudo();
} else
goto doreturn;
} else {
#ifndef NDEBUG
chkregs();
#endif
n = *bp++;
assert(n>0 && n<=MAXRULE);
if (n>1) {
mindistance = MAXINT; npos=0;
for(i=0;i<n;i++) {
getint(cindex,bp);
dist=distance(cindex);
#ifndef NDEBUG
if (Debug)
fprintf(stderr,"distance of pos %d is %u\n",i,dist);
#endif
if (dist<=mindistance) {
if (dist<mindistance) {
#ifdef SHORTCUT
if(dist==0)
goto gotit;
#endif
npos=0;
mindistance = dist;
}
pos[npos++] = cindex;
}
}
assert(mindistance<MAXINT);
if (npos>1) {
/*
* More than 1 tokenpattern is a candidate.
* Decision has to be made by lookahead.
*/
SAVEST;
mincost = costlimit-totalcost+1;
for(i=0;i<npos;i++) {
t=codegen(&coderules[pos[i]],ply,FALSE,mincost,0);
#ifndef NDEBUG
if (Debug)
fprintf(stderr,"mincost %u,cost %u,pos %d\n",mincost,t,i);
#endif
if (t<mincost) {
mincost = t;
cindex = pos[i];
}
RESTST;
}
FREEST;
if (totalcost+mincost>costlimit) {
totalcost += mincost;
BROKE();
}
} else {
cindex = pos[0];
}
} else {
getint(cindex,bp);
}
gotit:
/*
* Now cindex contains the code-index of the best candidate
* so proceed to use it.
*/
codep = &coderules[cindex];
}
break;
case DO_COERC:
DEBUG("COERC");
tokpatlen=1;
inscoerc=1;
break;
case DO_XXMATCH:
DEBUG("XXMATCH");
case DO_XMATCH:
DEBUG("XMATCH");
tokpatlen=(codep[-1]>>5)&07;
for (i=0;i<tokpatlen;i++)
getint(tokexp[i],codep);
tokexp[i]=0;
break; /* match already checked by distance() */
case DO_MATCH:
DEBUG("MATCH");
tokpatlen=(codep[-1]>>5)&07;
for(i=0;i<tokpatlen;i++)
getint(tokexp[i],codep);
tokexp[i] = 0;
tp = &fakestack[stackheight-1];
i=0;
while (i<tokpatlen && tp>=fakestack) {
size=tsize(tp);
while (i<tokpatlen && (lsize=ssize(tokexp[i]))<=size) {
size -= lsize;
i++;
}
if (i<tokpatlen && size!=0) {
totalcost += stackupto(tp,ply,toplevel);
CHKCOST();
break;
}
tp--;
}
tp = &fakestack[stackheight-1];
i=0;
while (i<tokpatlen && tp >= fakestack) {
size = tsize(tp);
lsize= ssize(tokexp[i]);
if (size != lsize) { /* find coercion */
#ifdef MAXSPLIT
sret = split(tp,&tokexp[i],ply,toplevel);
if (sret==0) {
#endif MAXSPLIT
totalcost += stackupto(tp,ply,toplevel);
CHKCOST();
break;
#ifdef MAXSPLIT
}
i += sret;
#endif MAXSPLIT
} else
i += 1;
tp--;
}
nextmatch:
tp = &fakestack[stackheight-1];
i=0; nregneeded = 0;
while (i<tokpatlen && tp>=fakestack) {
if (!match(tp,&machsets[tokexp[i]],0)) {
cp = findcoerc(tp, &machsets[tokexp[i]]);
if (cp==0) {
for (j=0;j<nregneeded;j++)
regtp[j] -= (tp-fakestack+1);
totalcost += stackupto(tp,ply,toplevel);
CHKCOST();
break;
} else {
if (cp->c3_prop==0) {
totalcost+=docoerc(tp,cp,ply,toplevel,0);
CHKCOST();
} else {
assert(nregneeded<MAXCREG);
regtp[nregneeded] = tp;
regcp[nregneeded] = cp;
regls[nregneeded] = curreglist;
nregneeded++;
}
}
}
i++; tp--;
}
if (tokpatlen>stackheight) {
stackpad = tokpatlen-stackheight;
for (j=stackheight-1;j>=0;j--)
fakestack[j+stackpad] = fakestack[j];
for (j=0;j<stackpad;j++)
fakestack[j].t_token=0;
stackheight += stackpad;
for (j=0;j<nregneeded;j++)
regtp[j] += stackpad;
tp = &fakestack[stackpad-1];
while (i<tokpatlen && tp>=fakestack) {
cp = findcoerc((token_p) 0, &machsets[tokexp[i]]);
if (cp==0) {
assert(!toplevel);
for (j=0;j<nregneeded;j++)
myfree(regls[j]);
totalcost=INFINITY;
BROKE();
}
if (cp->c3_prop==0) {
totalcost+=docoerc(tp,cp,ply,toplevel,0);
CHKCOST();
} else {
assert(nregneeded<MAXCREG);
regtp[nregneeded] = tp;
regcp[nregneeded] = cp;
regls[nregneeded] = curreglist;
nregneeded++;
}
i++; tp--;
}
} else
stackpad=0;
assert(i==tokpatlen);
if (nregneeded==0)
break;
SAVEST;
mincost=costlimit-totalcost+1;
tup = tuples(regls,nregneeded);
besttup=0;
for (; tup != 0; tup = ntup) {
ntup = tup->p_next;
for (i=0,t=0;i<nregneeded && t<mincost; i++)
t += docoerc(regtp[i],regcp[i],ply,FALSE,tup->p_rar[i]);
if (t<mincost)
t += codegen(codep,ply,FALSE,mincost-t,0);
if (t<mincost) {
mincost = t;
besttup = tup;
} else
myfree(tup);
RESTST;
}
FREEST;
for (i=0;i<nregneeded;i++)
myfree(regls[i]);
if (totalcost+mincost>costlimit) {
if (besttup)
myfree(besttup);
if (stackpad!=tokpatlen) {
if (stackpad) {
if (costlimit<MAXINT) {
totalcost = costlimit+1;
BROKE();
}
for (i=0;i<stackheight-stackpad;i++)
fakestack[i] = fakestack[i+stackpad];
stackheight -= stackpad;
totalcost += stackupto(&fakestack[stackheight-1],ply,toplevel);
} else
totalcost += stackupto(fakestack,ply,toplevel);
CHKCOST();
goto nextmatch;
}
totalcost += mincost;
BROKE();
}
for (i=0;i<nregneeded;i++)
totalcost += docoerc(regtp[i],regcp[i],ply,toplevel,besttup->p_rar[i]);
myfree(besttup);
break;
case DO_REMOVE:
DEBUG("REMOVE");
if (codep[-1]&32) {
getint(texpno,codep);
getint(nodeno,codep);
} else {
getint(texpno,codep);
nodeno=0;
}
for (tp= &fakestack[stackheight-tokpatlen-1];tp>=&fakestack[0];tp--)
if (match(tp,&machsets[texpno],nodeno)) {
/* investigate possible coercion to register */
totalcost += stackupto(tp,ply,toplevel);
CHKCOST();
break;
}
for (rp=machregs+2;rp<machregs+NREGS;rp++)
if (match(&rp->r_contents,&machsets[texpno],nodeno))
rp->r_contents.t_token=0;
break;
case DO_RREMOVE: /* register remove */
getint(nodeno,codep);
result=compute(&enodes[nodeno]);
assert(result.e_typ==EV_REG);
for (tp= &fakestack[stackheight-tokpatlen-1];tp>=&fakestack[0];tp--)
if (tp->t_token==-1) {
if(tp->t_att[0].ar==result.e_v.e_con)
goto gotone;
} else {
tdp = &tokens[tp->t_token];
for(i=0;i<TOKENSIZE;i++)
if (tdp->t_type[i]==EV_REG &&
tp->t_att[i].ar==result.e_v.e_con)
goto gotone;
}
break;
gotone:
/* investigate possible coercion to register */
totalcost += stackupto(tp,ply,toplevel);
CHKCOST();
break;
case DO_DEALLOCATE:
DEBUG("DEALLOCATE");
getint(tinstno,codep);
instance(tinstno,&token);
if (token.t_token==-1)
chrefcount(token.t_att[0].ar,-1,TRUE);
else {
tdp= &tokens[token.t_token];
for (i=0;i<TOKENSIZE;i++)
if (tdp->t_type[i]==EV_REG)
chrefcount(token.t_att[i].ar,-1,TRUE);
}
break;
case DO_REALLOCATE:
DEBUG("REALLOCATE");
for(rp=machregs;rp<machregs+NREGS;rp++)
if(rp->r_tcount) {
rp->r_refcount -= rp->r_tcount;
rp->r_tcount = 0;
}
break;
case DO_ALLOCATE:
DEBUG("ALLOCATE");
if (codep[-1]&32) {
getint(propno,codep);
getint(tinstno,codep);
} else {
getint(propno,codep);
tinstno=0;
}
instance(tinstno,&token);
if (!forced) {
do {
npos=exactmatch=0;
for(rpp=reglist[propno];rp= *rpp; rpp++)
if (getrefcount(rp-machregs)==0) {
pos[npos++] = rp-machregs;
if (eqtoken(&rp->r_contents,&token))
exactmatch++;
}
/*
* Now pos[] contains all free registers with desired
* property. If none then some stacking has to take place.
*/
if (npos==0) {
if (stackheight<=tokpatlen) {
if (!toplevel) {
totalcost = INFINITY;
BROKE();
} else {
fatal("No regs available");
}
}
totalcost += stackupto( &fakestack[0],ply,toplevel);
CHKCOST();
}
} while (npos==0);
if (!exactmatch) {
npos2=npos;
for(i=0;i<npos;i++)
pos2[i]=pos[i];
} else {
/*
* Now we are reducing the number of possible registers.
* We take only one equally likely register out of every
* equivalence class as given by set of properties.
*/
mtoken = token;
npos2=0;
for(i=0;i<npos;i++)
if (eqtoken(&machregs[pos[i]].r_contents,&mtoken)) {
pos2[npos2++] = pos[i];
for(j=0;j<npos2-1;j++)
if (eqregclass(pos2[j],pos[i])) {
npos2--;
break;
}
}
}
/*
* Now pos2[] contains all possibilities to try, if more than
* one, lookahead is necessary.
*/
token2.t_token= -1;
for (i=1;i<TOKENSIZE;i++)
token2.t_att[i].aw=0;
if (npos2==1)
decision=pos2[0];
else {
SAVEST;
mincost=costlimit-totalcost+1;
for(j=0;j<npos2;j++) {
chrefcount(pos2[j],1,FALSE);
token2.t_att[0].ar=pos2[j];
allreg[nallreg++] = pos2[j];
if (token.t_token != 0)
t=move(&token,&token2,ply,FALSE,mincost);
else {
t = 0;
erasereg(pos2[j]);
}
if (t<mincost)
t += codegen(codep,ply,FALSE,mincost-t,0);
if (t<mincost) {
mincost=t;
decision=pos2[j];
}
RESTST;
}
FREEST;
if (totalcost+mincost>costlimit) {
totalcost = INFINITY;
BROKE();
}
}
} else {
decision = forced;
if (getrefcount(decision)!=0) {
totalcost = INFINITY;
BROKE();
}
token2.t_token = -1;
}
chrefcount(decision,1,FALSE);
token2.t_att[0].ar=decision;
if (token.t_token != 0) {
totalcost+=move(&token,&token2,ply,toplevel,MAXINT);
CHKCOST();
} else
erasereg(decision);
allreg[nallreg++]=decision;
break;
case DO_LOUTPUT:
DEBUG("LOUTPUT");
getint(stringno,codep);
getint(nodeno,codep);
if (toplevel) {
gencode(codestrings[stringno]);
genexpr(nodeno);
}
break;
case DO_ROUTPUT:
DEBUG("ROUTPUT");
i=((codep[-1]>>5)&07);
do {
getint(stringno,codep);
if (toplevel) {
gencode(codestrings[stringno]);
gennl();
}
} while (i--);
break;
case DO_MOVE:
DEBUG("MOVE");
getint(tinstno,codep);
instance(tinstno,&token);
getint(tinstno,codep);
instance(tinstno,&token2);
totalcost += move(&token,&token2,ply,toplevel,costlimit-totalcost+1);
CHKCOST();
break;
case DO_ERASE:
DEBUG("ERASE");
getint(nodeno,codep);
result=compute(&enodes[nodeno]);
assert(result.e_typ==EV_REG);
erasereg(result.e_v.e_reg);
break;
case DO_TOKREPLACE:
DEBUG("TOKREPLACE");
assert(stackheight>=tokpatlen);
repllen=(codep[-1]>>5)&07;
for(i=0;i<repllen;i++) {
getint(tinstno,codep);
instance(tinstno,&reptoken[i]);
tref(&reptoken[i],1);
}
for(i=0;i<tokpatlen;i++) {
if (!inscoerc)
tref(&fakestack[stackheight-1],-1);
stackheight--;
}
for (i=0;i<repllen;i++) {
assert(stackheight<MAXFSTACK);
fakestack[stackheight++] = reptoken[i];
}
for(i=0;i<nallreg;i++)
chrefcount(allreg[i],-1,FALSE);
break;
case DO_EMREPLACE:
DEBUG("EMREPLACE");
emrepllen=(codep[-1]>>5)&07;
j=emp-emlines;
if (emrepllen>j) {
assert(nemlines+emrepllen-j<MAXEMLINES);
for (i=nemlines;i>=0;i--)
emlines[i+emrepllen-j] = emlines[i];
nemlines += emrepllen-j;
emp += emrepllen-j;
}
emp -= emrepllen;
for (i=0;i<emrepllen;i++) {
getint(eminstr,codep);
getint(nodeno,codep);
emp[i].em_instr = eminstr;
result = compute(&enodes[nodeno]);
switch(result.e_typ) {
default:
assert(FALSE);
case 0:
emp[i].em_optyp = OPNO;
emp[i].em_soper = 0;
break;
case EV_INT:
emp[i].em_optyp = OPINT;
emp[i].em_soper = tostring(result.e_v.e_con);
emp[i].em_u.em_ioper = result.e_v.e_con;
break;
case EV_STR:
emp[i].em_optyp = OPSYMBOL;
emp[i].em_soper = result.e_v.e_str;
break;
}
}
if (!toplevel)
ply += emrepllen;
break;
case DO_COST:
DEBUG("COST");
getint(cost.c_size,codep);
getint(cost.c_time,codep);
totalcost += costcalc(cost);
CHKCOST();
break;
#ifdef REGVARS
case DO_PRETURN:
if (toplevel) {
swtxt();
regreturn(); /* in mach.c */
}
break;
#endif
case DO_RETURN:
DEBUG("RETURN");
assert(origcp!=startupcode);
doreturn:
#ifndef NDEBUG
level--;
#endif
return(totalcost);
}
}
}

View File

@@ -1,364 +0,0 @@
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include "assert.h"
#include "param.h"
#include "tables.h"
#include "types.h"
#include <cg_pattern.h>
#include "data.h"
#include "result.h"
#include "glosym.h"
#include "extern.h"
/*
* (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: Hans van Staveren
*/
#define LLEAF 01
#define LDEF 02
#define RLEAF 04
#define RDEF 010
#define LLDEF LLEAF|LDEF
#define RLDEF RLEAF|RDEF
char opdesc[] = {
0, /* EX_TOKFIELD */
0, /* EX_ARG */
0, /* EX_CON */
0, /* EX_ALLREG */
LLDEF|RLDEF, /* EX_SAMESIGN */
LLDEF|RLDEF, /* EX_SFIT */
LLDEF|RLDEF, /* EX_UFIT */
0, /* EX_ROM */
LLDEF|RLDEF, /* EX_NCPEQ */
LLDEF|RLDEF, /* EX_SCPEQ */
LLDEF|RLDEF, /* EX_RCPEQ */
LLDEF|RLDEF, /* EX_NCPNE */
LLDEF|RLDEF, /* EX_SCPNE */
LLDEF|RLDEF, /* EX_RCPNE */
LLDEF|RLDEF, /* EX_NCPGT */
LLDEF|RLDEF, /* EX_NCPGE */
LLDEF|RLDEF, /* EX_NCPLT */
LLDEF|RLDEF, /* EX_NCPLE */
LLDEF, /* EX_OR2 */
LLDEF, /* EX_AND2 */
LLDEF|RLDEF, /* EX_PLUS */
LLDEF|RLDEF, /* EX_CAT */
LLDEF|RLDEF, /* EX_MINUS */
LLDEF|RLDEF, /* EX_TIMES */
LLDEF|RLDEF, /* EX_DIVIDE */
LLDEF|RLDEF, /* EX_MOD */
LLDEF|RLDEF, /* EX_LSHIFT */
LLDEF|RLDEF, /* EX_RSHIFT */
LLDEF, /* EX_NOT */
LLDEF, /* EX_COMP */
0, /* EX_COST */
0, /* EX_STRING */
LLEAF, /* EX_DEFINED */
0, /* EX_SUBREG */
LLDEF, /* EX_TOSTRING */
LLDEF, /* EX_UMINUS */
0, /* EX_REG */
0, /* EX_LOWW */
0, /* EX_HIGHW */
LLDEF, /* EX_INREG */
LLDEF, /* EX_REGVAR */
};
string salloc(),strcpy(),strcat();
string mycat(s1,s2) string s1,s2; {
register string s;
s=salloc(strlen(s1)+strlen(s2));
strcpy(s,s1);
strcat(s,s2);
return(s);
}
string mystrcpy(s) string s; {
register string r;
r=salloc(strlen(s));
strcpy(r,s);
return(r);
}
char digstr[21][15];
string tostring(n) word n; {
char buf[25];
if (n>=-20 && n<=20 && (n&1)==0) {
if (digstr[(n>>1)+10][0]==0)
sprintf(digstr[(n>>1)+10],WRD_FMT,n);
return(digstr[(n>>1)+10]);
}
sprintf(buf,WRD_FMT,n);
return(mystrcpy(buf));
}
result_t undefres= {EV_UNDEF};
result_t compute(node) node_p node; {
result_t leaf1,leaf2,result;
token_p tp;
int desc;
long mask,tmp;
int i,tmpreg;
glosym_p gp;
desc=opdesc[node->ex_operator];
if (desc&LLEAF) {
leaf1 = compute(&enodes[node->ex_lnode]);
if (desc&LDEF && leaf1.e_typ==EV_UNDEF)
return(undefres);
}
if (desc&RLEAF) {
leaf2 = compute(&enodes[node->ex_rnode]);
if (desc&RDEF && leaf2.e_typ==EV_UNDEF)
return(undefres);
}
result.e_typ=EV_INT;
switch(node->ex_operator) {
default: assert(FALSE);
case EX_TOKFIELD:
if (node->ex_lnode!=0)
tp = &fakestack[stackheight-node->ex_lnode];
else
tp = curtoken;
switch(result.e_typ = tokens[tp->t_token].t_type[node->ex_rnode-1]) {
default:
assert(FALSE);
case EV_INT:
result.e_v.e_con = tp->t_att[node->ex_rnode-1].aw;
break;
case EV_STR:
result.e_v.e_str = tp->t_att[node->ex_rnode-1].as;
break;
case EV_REG:
result.e_v.e_reg = tp->t_att[node->ex_rnode-1].ar;
break;
}
return(result);
case EX_ARG:
return(dollar[node->ex_lnode-1]);
case EX_CON:
result.e_typ = EV_INT;
result.e_v.e_con = ((long) node->ex_rnode << 16) | ((long)node->ex_lnode&0xffff);
return(result);
case EX_REG:
result.e_typ = EV_REG;
result.e_v.e_reg = node->ex_lnode;
return(result);
case EX_ALLREG:
result.e_typ = EV_REG;
result.e_v.e_reg = allreg[node->ex_lnode-1];
#if MAXMEMBERS!=0
if (node->ex_rnode!=0)
result.e_v.e_reg = machregs[result.e_v.e_reg].
r_members[node->ex_rnode-1];
#endif
return(result);
case EX_SAMESIGN:
assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
result.e_typ = EV_INT;
if (leaf1.e_v.e_con>=0)
result.e_v.e_con= leaf2.e_v.e_con>=0;
else
result.e_v.e_con= leaf2.e_v.e_con<0;
return(result);
case EX_SFIT:
assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
mask = 0xFFFFFFFFL;
for (i=0;i<leaf2.e_v.e_con-1;i++)
mask &= ~(1<<i);
tmp = leaf1.e_v.e_con&mask;
result.e_v.e_con = tmp==0||tmp==mask;
return(result);
case EX_UFIT:
assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
mask = 0xFFFFFFFFL;
for (i=0;i<leaf2.e_v.e_con;i++)
mask &= ~(1<<i);
result.e_v.e_con = (leaf1.e_v.e_con&mask)==0;
return(result);
case EX_ROM:
assert(node->ex_rnode>=0 &&node->ex_rnode<MAXROM);
leaf2=dollar[node->ex_lnode];
if (leaf2.e_typ != EV_STR)
return(undefres);
gp = lookglo(leaf2.e_v.e_str);
if (gp == (glosym_p) 0)
return(undefres);
if ((gp->gl_rom[MAXROM]&(1<<node->ex_rnode))==0)
return(undefres);
result.e_v.e_con = gp->gl_rom[node->ex_rnode];
return(result);
case EX_LOWW:
result.e_v.e_con = saveemp[node->ex_lnode].em_u.em_loper&0xFFFF;
return(result);
case EX_HIGHW:
result.e_v.e_con = saveemp[node->ex_lnode].em_u.em_loper>>16;
return(result);
case EX_NCPEQ:
assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
result.e_v.e_con = leaf1.e_v.e_con==leaf2.e_v.e_con;
return(result);
case EX_SCPEQ:
assert(leaf1.e_typ == EV_STR && leaf2.e_typ == EV_STR);
result.e_v.e_con = !strcmp(leaf1.e_v.e_str,leaf2.e_v.e_str);
return(result);
case EX_RCPEQ:
assert(leaf1.e_typ == EV_REG && leaf2.e_typ == EV_REG);
result.e_v.e_con = leaf1.e_v.e_reg==leaf2.e_v.e_reg;
return(result);
case EX_NCPNE:
assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
result.e_v.e_con = leaf1.e_v.e_con!=leaf2.e_v.e_con;
return(result);
case EX_SCPNE:
assert(leaf1.e_typ == EV_STR && leaf2.e_typ == EV_STR);
result.e_v.e_con = strcmp(leaf1.e_v.e_str,leaf2.e_v.e_str);
return(result);
case EX_RCPNE:
assert(leaf1.e_typ == EV_REG && leaf2.e_typ == EV_REG);
result.e_v.e_con = leaf1.e_v.e_reg!=leaf2.e_v.e_reg;
return(result);
case EX_NCPGT:
assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
result.e_v.e_con = leaf1.e_v.e_con>leaf2.e_v.e_con;
return(result);
case EX_NCPGE:
assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
result.e_v.e_con = leaf1.e_v.e_con>=leaf2.e_v.e_con;
return(result);
case EX_NCPLT:
assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
result.e_v.e_con = leaf1.e_v.e_con<leaf2.e_v.e_con;
return(result);
case EX_NCPLE:
assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
result.e_v.e_con = leaf1.e_v.e_con<=leaf2.e_v.e_con;
return(result);
case EX_OR2:
assert(leaf1.e_typ == EV_INT);
if (leaf1.e_v.e_con==0)
return(compute(&enodes[node->ex_rnode]));
return(leaf1);
case EX_AND2:
assert(leaf1.e_typ == EV_INT);
if (leaf1.e_v.e_con!=0)
return(compute(&enodes[node->ex_rnode]));
return(leaf1);
case EX_PLUS:
assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
result.e_v.e_con=leaf1.e_v.e_con+leaf2.e_v.e_con;
return(result);
case EX_CAT:
assert(leaf1.e_typ == EV_STR && leaf2.e_typ == EV_STR);
result.e_typ = EV_STR;
result.e_v.e_str = mycat(leaf1.e_v.e_str,leaf2.e_v.e_str);
return(result);
case EX_MINUS:
assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
result.e_v.e_con = leaf1.e_v.e_con - leaf2.e_v.e_con;
return(result);
case EX_TIMES:
assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
result.e_v.e_con = leaf1.e_v.e_con * leaf2.e_v.e_con;
return(result);
case EX_DIVIDE:
assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
result.e_v.e_con = leaf1.e_v.e_con / leaf2.e_v.e_con;
return(result);
case EX_MOD:
assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
result.e_v.e_con = leaf1.e_v.e_con % leaf2.e_v.e_con;
return(result);
case EX_LSHIFT:
assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
result.e_v.e_con = leaf1.e_v.e_con << leaf2.e_v.e_con;
return(result);
case EX_RSHIFT:
assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
result.e_v.e_con = leaf1.e_v.e_con >> leaf2.e_v.e_con;
return(result);
case EX_NOT:
assert(leaf1.e_typ == EV_INT);
result.e_v.e_con = !leaf1.e_v.e_con;
return(result);
case EX_COMP:
assert(leaf1.e_typ == EV_INT);
result.e_v.e_con = ~leaf1.e_v.e_con;
return(result);
case EX_COST:
if (node->ex_rnode==0)
return(compute(&enodes[tokens[node->ex_lnode].t_cost.c_size]));
else
return(compute(&enodes[tokens[node->ex_lnode].t_cost.c_time]));
case EX_STRING:
result.e_typ = EV_STR;
result.e_v.e_str = codestrings[node->ex_lnode];
return(result);
case EX_DEFINED:
result.e_v.e_con=leaf1.e_typ!=EV_UNDEF;
return(result);
case EX_SUBREG:
result.e_typ = EV_REG;
tp= &fakestack[stackheight-node->ex_lnode];
assert(tp->t_token == -1);
tmpreg= tp->t_att[0].ar;
#if MAXMEMBERS!=0
if (node->ex_rnode)
tmpreg=machregs[tmpreg].r_members[node->ex_rnode-1];
#endif
result.e_v.e_reg=tmpreg;
return(result);
case EX_TOSTRING:
assert(leaf1.e_typ == EV_INT);
result.e_typ = EV_STR;
result.e_v.e_str = tostring(leaf1.e_v.e_con);
return(result);
#ifdef REGVARS
case EX_INREG:
assert(leaf1.e_typ == EV_INT);
i = isregvar((long) leaf1.e_v.e_con);
if (i<0)
result.e_v.e_con = 0;
else if (i==0)
result.e_v.e_con = 1;
else
result.e_v.e_con = 2;
return(result);
case EX_REGVAR:
assert(leaf1.e_typ == EV_INT);
i = isregvar((long) leaf1.e_v.e_con);
if (i<=0)
return(undefres);
result.e_typ = EV_REG;
result.e_v.e_reg=i;
return(result);
#endif
case EX_UMINUS:
assert(leaf1.e_typ == EV_INT);
result.e_v.e_con = -leaf1.e_v.e_con;
return(result);
}
}

View File

@@ -1,54 +0,0 @@
/* $Header$ */
typedef struct {
int t_token; /* kind of token, -1 for register */
union {
word aw; /* integer type */
string as; /* string type */
int ar; /* register type */
} t_att[TOKENSIZE];
} token_t,*token_p;
struct reginfo {
int r_repr; /* index in string table */
int r_size; /* size in bytes */
#if MAXMEMBERS!=0
int r_members[MAXMEMBERS]; /* register contained within this reg */
short r_clash[REGSETSIZE]; /* set of clashing registers */
#endif
int r_refcount; /* Times in use */
token_t r_contents; /* Current contents */
int r_tcount; /* Temporary count difference */
};
#if MAXMEMBERS!=0
#define clash(a,b) ((machregs[a].r_clash[(b)>>4]&(1<<((b)&017)))!=0)
#else
#define clash(a,b) ((a)==(b))
#endif
typedef struct {
int t_size; /* size in bytes */
cost_t t_cost; /* cost in bytes and time */
byte t_type[TOKENSIZE]; /* types of attributes, TT_??? */
int t_format; /* index of formatstring */
} tkdef_t,*tkdef_p;
struct emline {
int em_instr;
int em_optyp;
string em_soper;
union {
word em_ioper;
long em_loper;
} em_u;
};
#define OPNO 0
#define OPINT 1
#define OPSYMBOL 2
typedef struct {
int rl_n; /* number in list */
int rl_list[NREGS];
} rl_t,*rl_p;

View File

@@ -1,105 +0,0 @@
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include "assert.h"
#include "equiv.h"
#include "param.h"
#include "tables.h"
#include "types.h"
#include <cg_pattern.h>
#include "data.h"
#include "result.h"
#include "extern.h"
/*
* (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: Hans van Staveren
*/
extern string myalloc();
int rar[MAXCREG];
rl_p *lar;
int maxindex;
int regclass[NREGS];
struct perm *perms;
struct perm *
tuples(regls,nregneeded) rl_p *regls; {
int class=0;
register i,j;
/*
* First compute equivalence classes of registers.
*/
for (i=0;i<NREGS;i++) {
regclass[i] = class++;
if (getrefcount(i) == 0) {
for (j=0;j<i;j++) {
if (eqregclass(i,j) &&
eqtoken(&machregs[i].r_contents,
&machregs[j].r_contents)) {
regclass[i] = regclass[j];
break;
}
}
}
}
/*
* Now create tuples through a recursive function
*/
maxindex = nregneeded;
lar = regls;
perms = 0;
permute(0);
return(perms);
}
permute(index) {
register struct perm *pp;
register rl_p rlp;
register i,j;
if (index == maxindex) {
for (pp=perms; pp != 0; pp=pp->p_next) {
for (i=0; i<maxindex; i++)
if (regclass[rar[i]] != regclass[pp->p_rar[i]])
goto diff;
for (i=0; i<maxindex; i++)
for (j=0; j<i; j++)
if (clash(rar[i],rar[j]) !=
clash(pp->p_rar[i],pp->p_rar[j]))
goto diff;
return;
diff: ;
}
pp = (struct perm *) myalloc(sizeof ( *pp ));
pp->p_next = perms;
for (i=0; i<maxindex; i++)
pp->p_rar[i] = rar[i];
perms = pp;
} else {
rlp=lar[index];
for (i=rlp->rl_n-1; i>=0; i--) {
rar[index] = rlp->rl_list[i];
permute(index+1);
}
}
}

View File

@@ -1,8 +0,0 @@
/* $Header$ */
#define MAXCREG 4
struct perm {
struct perm *p_next;
int p_rar[MAXCREG];
};

View File

@@ -1,49 +0,0 @@
/* $Header$ */
extern int maxply; /* amount of lookahead allowed */
extern int stackheight; /* # of tokens on fakestack */
extern token_t fakestack[]; /* fakestack itself */
extern int nallreg; /* number of allocated registers */
extern int allreg[]; /* array of allocated registers */
extern token_p curtoken; /* pointer to current token */
extern result_t dollar[]; /* Values of $1,$2 etc.. */
extern int nemlines; /* # of EM instructions in core */
extern struct emline emlines[]; /* EM instructions itself */
extern struct emline *emp; /* pointer to current instr */
extern struct emline *saveemp; /* pointer to start of pattern */
extern int tokpatlen; /* length of current stackpattern */
extern rl_p curreglist; /* side effect of findcoerc() */
#ifndef NDEBUG
extern int Debug; /* on/off debug printout */
#endif
/*
* Next descriptions are external declarations for tables created
* by bootgram.
* All definitions are to be found in tables.c (Not for humans)
*/
extern byte coderules[]; /* pseudo code for cg itself */
extern char stregclass[]; /* static register class */
extern struct reginfo machregs[]; /* register info */
extern tkdef_t tokens[]; /* token info */
extern node_t enodes[]; /* expression nodes */
extern string codestrings[]; /* table of strings */
extern set_t machsets[]; /* token expression table */
extern inst_t tokeninstances[]; /* token instance description table */
extern move_t moves[]; /* move descriptors */
extern byte pattern[]; /* EM patterns */
extern int pathash[256]; /* Indices into previous */
extern c1_t c1coercs[]; /* coercions type 1 */
#ifdef MAXSPLIT
extern c2_t c2coercs[]; /* coercions type 2 */
#endif MAXSPLIT
extern c3_t c3coercs[]; /* coercions type 3 */
extern struct reginfo **reglist[]; /* lists of registers per property */
#define eqregclass(r1,r2) (stregclass[r1]==stregclass[r2])
#ifdef REGVARS
extern int nregvar[]; /* # of register variables per type */
extern int *rvnumbers[]; /* lists of numbers */
#endif

View File

@@ -1,648 +0,0 @@
#ifndef NORCSID
static char rcsid2[] = "$Header$";
#endif
#include <stdio.h>
#include "assert.h"
#include <em_spec.h>
#include <em_pseu.h>
#include <em_flag.h>
#include <em_ptyp.h>
#include <em_mes.h>
#include "mach.h"
#include "param.h"
#include "tables.h"
#include "types.h"
#include <cg_pattern.h>
#include "data.h"
#include "result.h"
#ifdef REGVARS
#include "regvar.h"
#include <em_reg.h>
#endif
#include "extern.h"
/*
* (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: Hans van Staveren
*/
#ifndef newplb /* retrofit for older mach.h */
#define newplb newilb
#endif
/* segment types for switchseg() */
#define SEGTXT 0
#define SEGCON 1
#define SEGROM 2
#define SEGBSS 3
long con();
#define get8() getc(emfile)
#define MAXSTR 256
FILE *emfile;
extern FILE *codefile;
int nextispseu,savetab1;
int opcode;
int offtyp;
long argval;
int dlbval;
char str[MAXSTR],argstr[32],labstr[32];
int strsiz;
int holno=0;
int procno=0;
int curseg= -1;
int part_size=0;
word part_word=0;
int endofprog=0;
#ifdef REGVARS
int regallowed=0;
#endif
extern char em_flag[];
extern short em_ptyp[];
extern long atol();
extern double atof();
#define sp_cstx sp_cst2
string tostring();
string holstr();
string strarg();
string mystrcpy();
long get32();
in_init(filename) char *filename; {
if ((emfile=freopen(filename,"r",stdin))==NULL)
error("Can't open %s",filename);
if (get16()!=sp_magic)
error("Bad format %s",filename);
}
in_finish() {
}
fillemlines() {
int t,i;
register struct emline *lp;
while ((emlines+nemlines)-emp<MAXEMLINES-5) {
assert(nemlines<MAXEMLINES);
if (nextispseu) {
emlines[nemlines].em_instr=0;
return;
}
lp = &emlines[nemlines++];
switch(t=table1()) {
default:
error("unknown instruction byte");
case sp_ilb1:
case sp_ilb2:
case sp_fpseu:
case sp_dlb1:
case sp_dlb2:
case sp_dnam:
nextispseu=1; savetab1=t;
nemlines--;
lp->em_instr = 0;
return;
case EOF:
nextispseu=1; savetab1=t;
endofprog=1;
nemlines--;
lp->em_instr = 0;
return;
case sp_fmnem:
lp->em_instr = opcode;
break;
}
i=em_flag[lp->em_instr-sp_fmnem] & EM_PAR;
if ( i == PAR_NO ) {
lp->em_optyp = OPNO;
lp->em_soper = 0;
continue;
}
t= em_ptyp[i];
t= getarg(t);
switch(i) {
case PAR_L:
assert(t == sp_cstx);
if (argval >= 0)
argval += EM_BSIZE;
lp->em_optyp = OPINT;
lp->em_u.em_ioper = argval;
lp->em_soper = tostring((word) argval);
continue;
case PAR_G:
if (t != sp_cstx)
break;
lp->em_optyp = OPSYMBOL;
lp->em_soper = holstr((word) argval);
continue;
case PAR_B:
t = sp_ilb2;
break;
case PAR_D:
assert(t == sp_cstx);
lp->em_optyp = OPSYMBOL;
lp->em_soper = strarg(t);
lp->em_u.em_loper = argval;
continue;
}
lp->em_soper = strarg(t);
if (t==sp_cend)
lp->em_optyp = OPNO;
else if (t==sp_cstx) {
lp->em_optyp = OPINT;
lp->em_u.em_ioper = argval;
} else
lp->em_optyp = OPSYMBOL;
}
}
dopseudo() {
register b,t;
register full n;
register long save;
word romcont[MAXROM+1];
int nromwords;
int rombit,rommask;
unsigned dummy,stackupto();
if (nextispseu==0 || nemlines>0)
error("No table entry for %d",emlines[0].em_instr);
nextispseu=0;
switch(savetab1) {
case sp_ilb1:
case sp_ilb2:
swtxt();
dummy = stackupto(&fakestack[stackheight-1],maxply,TRUE);
cleanregs();
strarg(savetab1);
newilb(argstr);
return;
case sp_dlb1:
case sp_dlb2:
case sp_dnam:
strarg(savetab1);
savelab();
return;
case sp_fpseu:
break;
case EOF:
swtxt();
popstr(0);
tstoutput();
exit(0);
default:
error("Unknown opcode %d",savetab1);
}
switch (opcode) {
case ps_hol:
sprintf(labstr,hol_fmt,++holno);
case ps_bss:
getarg(cst_ptyp);
n = (full) argval;
t = getarg(val_ptyp);
save = argval;
getarg(cst_ptyp);
b = (int) argval;
argval = save;
bss(n,t,b);
break;
case ps_con:
switchseg(SEGCON);
dumplab();
con(getarg(val_ptyp));
while ((t = getarg(any_ptyp)) != sp_cend)
con(t);
break;
case ps_rom:
switchseg(SEGROM);
xdumplab();
nromwords=0;
rommask=0;
rombit=1;
t=getarg(val_ptyp);
while (t!=sp_cend) {
if (t==sp_cstx && nromwords<MAXROM) {
romcont[nromwords] = (word) argval;
rommask |= rombit;
}
nromwords++;
rombit <<= 1;
con(t);
t=getarg(any_ptyp);
}
if (rommask != 0) {
romcont[MAXROM]=rommask;
enterglo(labstr,romcont);
}
labstr[0]=0;
break;
case ps_mes:
getarg(ptyp(sp_cst2));
if (argval == ms_emx) {
getarg(ptyp(sp_cst2));
if (argval != EM_WSIZE)
fatal("bad word size");
getarg(ptyp(sp_cst2));
if (argval != EM_PSIZE)
fatal("bad pointer size");
if ( getarg(any_ptyp)!=sp_cend )
fatal("too many parameters");
#ifdef REGVARS
} else if (argval == ms_gto) {
getarg(ptyp(sp_cend));
if (!regallowed)
error("mes 3 not allowed here");
fixregvars(TRUE);
regallowed=0;
} else if (argval == ms_reg) {
long r_off;
int r_size,r_type,r_score;
struct regvar *linkreg();
if (!regallowed)
error("mes 3 not allowed here");
if(getarg(ptyp(sp_cst2)|ptyp(sp_cend)) == sp_cend) {
fixregvars(FALSE);
regallowed=0;
} else {
r_off = argval;
#ifdef EM_BSIZE
if (r_off >= 0)
r_off += EM_BSIZE;
#endif
getarg(ptyp(sp_cst2));
r_size = argval;
getarg(ptyp(sp_cst2));
r_type = argval;
if (r_type<reg_any || r_type>reg_float)
fatal("Bad type in register message");
if(getarg(ptyp(sp_cst2)|ptyp(sp_cend)) == sp_cend)
r_score = 0;
else {
r_score = argval;
if ( getarg(any_ptyp)!=sp_cend )
fatal("too many parameters");
}
tryreg(linkreg(r_off,r_size,r_type,r_score),r_type);
}
#endif
} else
mes((word)argval);
break;
case ps_exa:
strarg(getarg(sym_ptyp));
ex_ap(argstr);
break;
case ps_ina:
strarg(getarg(sym_ptyp));
in_ap(argstr);
break;
case ps_exp:
strarg(getarg(ptyp(sp_pnam)));
ex_ap(argstr);
break;
case ps_inp:
strarg(getarg(ptyp(sp_pnam)));
in_ap(argstr);
break;
case ps_pro:
switchseg(SEGTXT);
procno++;
strarg(getarg(ptyp(sp_pnam)));
newplb(argstr);
getarg(cst_ptyp);
prolog((full)argval);
#ifdef REGVARS
regallowed++;
#endif
break;
case ps_end:
getarg(cst_ptyp | ptyp(sp_cend));
cleanregs();
#ifdef REGVARS
unlinkregs();
#endif
tstoutput();
break;
default:
error("No table entry for %d",savetab1);
}
}
/* ----- input ----- */
int getarg(typset) {
register t,argtyp;
argtyp = t = table2();
if (t == EOF)
fatal("unexpected EOF");
t -= sp_fspec;
t = 1 << t;
if ((typset & t) == 0)
error("bad argument type %d",argtyp);
return(argtyp);
}
int table1() {
register i;
i = get8();
if (i < sp_fmnem+sp_nmnem && i >= sp_fmnem) {
opcode = i;
return(sp_fmnem);
}
if (i < sp_fpseu+sp_npseu && i >= sp_fpseu) {
opcode = i;
return(sp_fpseu);
}
if (i < sp_filb0+sp_nilb0 && i >= sp_filb0) {
argval = i - sp_filb0;
return(sp_ilb2);
}
return(table3(i));
}
int table2() {
register i;
i = get8();
if (i < sp_fcst0+sp_ncst0 && i >= sp_fcst0) {
argval = i - sp_zcst0;
return(sp_cstx);
}
return(table3(i));
}
int table3(i) {
word consiz;
switch(i) {
case sp_ilb1:
argval = get8();
break;
case sp_dlb1:
dlbval = get8();
break;
case sp_dlb2:
dlbval = get16();
break;
case sp_cst2:
i = sp_cstx;
case sp_ilb2:
argval = get16();
break;
case sp_cst4:
i = sp_cstx;
argval = get32();
break;
case sp_dnam:
case sp_pnam:
case sp_scon:
getstring();
break;
case sp_doff:
offtyp = getarg(sym_ptyp);
getarg(cst_ptyp);
break;
case sp_icon:
case sp_ucon:
case sp_fcon:
getarg(cst_ptyp);
consiz = (word) argval;
getstring();
argval = consiz;
break;
}
return(i);
}
int get16() {
register int l_byte, h_byte;
l_byte = get8();
h_byte = get8();
if ( h_byte>=128 ) h_byte -= 256 ;
return l_byte | (h_byte*256) ;
}
long get32() {
register long l;
register int h_byte;
l = get8();
l |= ((unsigned) get8())*256 ;
l |= get8()*256L*256L ;
h_byte = get8() ;
if ( h_byte>=128 ) h_byte -= 256 ;
return l | (h_byte*256L*256*256L) ;
}
getstring() {
register char *p;
register n;
getarg(cst_ptyp);
if (argval < 0 || argval > MAXSTR-1)
fatal("string/identifier too long");
strsiz = n = (int) argval;
p = str;
while (--n >= 0)
*p++ = get8();
*p++ = '\0';
}
char *strarg(t) {
register char *p;
switch (t) {
case sp_ilb1:
case sp_ilb2:
sprintf(argstr,ilb_fmt,procno,(int)argval);
break;
case sp_dlb1:
case sp_dlb2:
sprintf(argstr,dlb_fmt,dlbval);
break;
case sp_cstx:
sprintf(argstr,cst_fmt,(full)argval);
break;
case sp_dnam:
case sp_pnam:
p = argstr;
if (strsiz < 8 || str[0] == id_first)
*p++ = id_first;
sprintf(p,"%.*s",strsiz,str);
break;
case sp_doff:
strarg(offtyp);
for (p = argstr; *p; p++)
;
if (argval >= 0)
*p++ = '+';
sprintf(p,off_fmt,(full)argval);
break;
case sp_cend:
return("");
}
return(mystrcpy(argstr));
}
bss(n,t,b) full n; {
register long s;
if (n % EM_WSIZE)
fatal("bad BSS size");
if (b==0
#ifdef BSS_INIT
|| (t==sp_cstx && argval==BSS_INIT)
#endif BSS_INIT
) {
switchseg(SEGBSS);
newlbss(labstr,n);
labstr[0]=0;
return;
}
switchseg(SEGCON);
dumplab();
while (n > 0)
n -= (s = con(t));
if (s % EM_WSIZE)
fatal("bad BSS initializer");
}
long con(t) {
register i;
strarg(t);
switch (t) {
case sp_ilb1:
case sp_ilb2:
case sp_pnam:
part_flush();
con_ilb(argstr);
return((long)EM_PSIZE);
case sp_dlb1:
case sp_dlb2:
case sp_dnam:
case sp_doff:
part_flush();
con_dlb(argstr);
return((long)EM_PSIZE);
case sp_cstx:
con_part(EM_WSIZE,(word)argval);
return((long)EM_WSIZE);
case sp_scon:
for (i = 0; i < strsiz; i++)
con_part(1,(word) str[i]);
return((long)strsiz);
case sp_icon:
case sp_ucon:
if (argval > EM_WSIZE) {
part_flush();
con_mult((word)argval);
} else {
con_part((int)argval,(word)atol(str));
}
return(argval);
case sp_fcon:
part_flush();
con_float();
return(argval);
}
assert(FALSE);
/* NOTREACHED */
}
extern char *segname[];
swtxt() {
switchseg(SEGTXT);
}
switchseg(s) {
if (s == curseg)
return;
part_flush();
if ((curseg = s) >= 0)
fprintf(codefile,"%s\n",segname[s]);
}
savelab() {
register char *p,*q;
part_flush();
if (labstr[0]) {
dlbdlb(argstr,labstr);
return;
}
p = argstr;
q = labstr;
while (*q++ = *p++)
;
}
dumplab() {
if (labstr[0] == 0)
return;
assert(part_size == 0);
newdlb(labstr);
labstr[0] = 0;
}
xdumplab() {
if (labstr[0] == 0)
return;
assert(part_size == 0);
newdlb(labstr);
}
part_flush() {
/*
* Each new data fragment and each data label starts at
* a new target machine word
*/
if (part_size == 0)
return;
con_cst(part_word);
part_size = 0;
part_word = 0;
}
string holstr(n) word n; {
sprintf(str,hol_off,n,holno);
return(mystrcpy(str));
}
/* ----- machine dependent routines ----- */
#include "mach.c"

View File

@@ -1,194 +0,0 @@
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include "assert.h"
#include <stdio.h>
#include "param.h"
#include "tables.h"
#include "types.h"
#include <cg_pattern.h>
#include "data.h"
#include "result.h"
#include "extern.h"
/*
* (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: Hans van Staveren
*/
FILE *codefile;
out_init(filename) char *filename; {
#ifndef NDEBUG
static char stderrbuff[512];
if (Debug) {
codefile = stderr;
if (!isatty(2))
setbuf(stderr,stderrbuff);
} else {
#endif
if (filename == (char *) 0)
codefile = stdout;
else
if ((codefile=freopen(filename,"w",stdout))==NULL)
error("Can't create %s",filename);
#ifndef NDEBUG
}
#endif
}
out_finish() {
#ifndef NDEBUG
if (Debug)
fflush(stderr);
else
#endif
fclose(codefile);
}
tstoutput() {
if (ferror(codefile))
error("Write error on output");
}
gencode(code) register char *code; {
register c;
int tokno,fldno,insno,regno,subno;
register token_p tp;
swtxt();
while ((c= *code++)!=0) switch(c) {
default:
fputc(c,codefile);
break;
case PR_TOK:
tokno = *code++;
tp = &fakestack[stackheight-tokno];
if (tp->t_token==-1)
fprintf(codefile,"%s",codestrings[machregs[tp->t_att[0].ar].r_repr]);
else
prtoken(tp);
break;
case PR_TOKFLD:
tokno = *code++;
fldno = *code++;
tp = &fakestack[stackheight-tokno];
assert(tp->t_token != -1);
switch(tokens[tp->t_token].t_type[fldno-1]) {
default:
assert(FALSE);
case EV_INT:
fprintf(codefile,WRD_FMT,tp->t_att[fldno-1].aw);
break;
case EV_STR:
fprintf(codefile,"%s",tp->t_att[fldno-1].as);
break;
case EV_REG:
assert(tp->t_att[fldno-1].ar>0 && tp->t_att[fldno-1].ar<NREGS);
fprintf(codefile,"%s",codestrings[machregs[tp->t_att[fldno-1].ar].r_repr]);
break;
}
break;
case PR_EMINT:
insno = *code++;
fprintf(codefile,WRD_FMT,dollar[insno-1].e_v.e_con);
break;
case PR_EMSTR:
insno = *code++;
fprintf(codefile,"%s",dollar[insno-1].e_v.e_str);
break;
case PR_ALLREG:
regno = *code++;
subno = (*code++)&0377;
assert(regno>=1 && regno<=nallreg);
regno = allreg[regno-1];
#if MAXMEMBERS!=0
if (subno!=255) {
assert(subno>=1 && subno<=MAXMEMBERS);
regno = machregs[regno].r_members[subno-1];
assert(regno!=0);
}
#endif
fprintf(codefile,"%s",codestrings[machregs[regno].r_repr]);
break;
#if MAXMEMBERS!=0
case PR_SUBREG:
tokno = *code++;
subno = *code++;
tp = &fakestack[stackheight-tokno];
assert(tp->t_token == -1);
fprintf(codefile,"%s",codestrings[machregs[machregs[tp->t_att[0].ar].r_members[subno-1]].r_repr]);
break;
#endif
}
}
genexpr(nodeno) {
result_t result;
result= compute(&enodes[nodeno]);
switch(result.e_typ) {
default: assert(FALSE);
case EV_INT:
fprintf(codefile,WRD_FMT,result.e_v.e_con);
break;
case EV_REG:
fprintf(codefile,"%s", codestrings[machregs[result.e_v.e_reg].r_repr]);
break;
case EV_STR:
fprintf(codefile,"%s",result.e_v.e_str);
break;
}
}
gennl() {
fputc('\n',codefile);
}
prtoken(tp) token_p tp; {
register c;
register char *code;
register tkdef_p tdp;
tdp = &tokens[tp->t_token];
assert(tdp->t_format != -1);
code = codestrings[tdp->t_format];
while ((c = *code++) != 0) {
if (c>=' ' && c<='~')
fputc(c,codefile);
else {
assert(c>0 && c<=TOKENSIZE);
switch(tdp->t_type[c-1]) {
default:
assert(FALSE);
case EV_INT:
fprintf(codefile,WRD_FMT,tp->t_att[c-1].aw);
break;
case EV_STR:
fprintf(codefile,"%s",tp->t_att[c-1].as);
break;
case EV_REG:
fprintf(codefile,"%s",codestrings[machregs[tp->t_att[c-1].ar].r_repr]);
break;
}
}
}
}

View File

@@ -1,52 +0,0 @@
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include "param.h"
#include "tables.h"
#include "types.h"
#include "glosym.h"
/*
* (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: Hans van Staveren
*/
extern string myalloc();
glosym_p glolist= (glosym_p) 0;
enterglo(name,romp) string name; word *romp; {
register glosym_p gp;
register i;
gp = (glosym_p) myalloc(sizeof *gp);
gp->gl_next = glolist;
gp->gl_name = (string) myalloc(strlen(name)+1);
strcpy(gp->gl_name,name);
for (i=0;i<=MAXROM;i++)
gp->gl_rom[i] = romp[i];
glolist = gp;
}
glosym_p lookglo(name) string name; {
register glosym_p gp;
for (gp=glolist;gp != (glosym_p) 0; gp=gp->gl_next)
if (strcmp(gp->gl_name,name)==0)
return(gp);
return((glosym_p) 0);
}

View File

@@ -1,9 +0,0 @@
/* $Header$ */
typedef struct glosym {
struct glosym *gl_next;
string gl_name;
word gl_rom[MAXROM+1];
} glosym_t,*glosym_p;
glosym_p lookglo();

View File

@@ -1,84 +0,0 @@
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include "param.h"
/*
* (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: Hans van Staveren
*/
char *progname;
extern char startupcode[];
int maxply=1;
#ifndef NDEBUG
int Debug=0;
#endif
extern int endofprog;
main(argc,argv) char **argv; {
register unsigned n;
extern unsigned cc1,cc2,cc3,cc4;
unsigned ggd();
progname = argv[0];
while (--argc && **++argv == '-') {
switch(argv[0][1]) {
#ifndef NDEBUG
case 'd':
Debug=1; break;
#endif
case 'p':
maxply = atoi(argv[0]+2);
break;
case 'w': /* weight percentage for size */
n=atoi(argv[0]+2);
cc1 *= n;
cc2 *= 50;
cc3 *= (100-n);
cc4 *= 50;
n=ggd(cc1,cc2);
cc1 /= n;
cc2 /= n;
n=ggd(cc3,cc4);
cc3 /= n;
cc4 /= n;
break;
default:
error("Unknown flag %c",argv[0][1]);
}
}
if (argc < 1 || argc > 2)
error("Usage: %s EMfile [ asfile ]",progname);
in_init(argv[0]);
out_init(argv[1]);
codegen(startupcode,maxply,TRUE,MAXINT,0);
in_finish();
if (!endofprog)
error("Bombed out of codegen");
out_finish();
}
unsigned ggd(a,b) register unsigned a,b; {
register unsigned c;
do {
c = a%b; a=b; b=c;
} while (c!=0);
return(a);
}

View File

@@ -1,110 +0,0 @@
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include "assert.h"
#include "param.h"
#include "tables.h"
#include "types.h"
#include <cg_pattern.h>
#include "data.h"
#include "result.h"
#include "extern.h"
/*
* (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: Hans van Staveren
*/
unsigned costcalc();
move(tp1,tp2,ply,toplevel,maxcost) token_p tp1,tp2; unsigned maxcost; {
register move_p mp;
register unsigned t;
register struct reginfo *rp;
tkdef_p tdp;
int i;
unsigned codegen();
if (eqtoken(tp1,tp2))
return(0);
if (tp2->t_token == -1) {
if (tp1->t_token == -1) {
if (eqtoken(&machregs[tp1->t_att[0].ar].r_contents,
&machregs[tp2->t_att[0].ar].r_contents) &&
machregs[tp1->t_att[0].ar].r_contents.t_token!=0)
return(0);
if (tp1->t_att[0].ar!=1) { /* COCO reg; tmp kludge */
erasereg(tp2->t_att[0].ar);
machregs[tp2->t_att[0].ar].r_contents =
machregs[tp1->t_att[0].ar].r_contents ;
} else
machregs[tp1->t_att[0].ar].r_contents =
machregs[tp2->t_att[0].ar].r_contents ;
} else {
if (eqtoken(&machregs[tp2->t_att[0].ar].r_contents,tp1))
return(0);
machregs[tp2->t_att[0].ar].r_contents = *tp1;
}
for (rp=machregs;rp<machregs+NREGS;rp++) {
if (rp->r_contents.t_token == 0)
continue;
assert(rp->r_contents.t_token > 0);
tdp = &tokens[rp->r_contents.t_token];
for (i=0;i<TOKENSIZE;i++)
if (tdp->t_type[i] == EV_REG &&
clash(rp->r_contents.t_att[i].ar,tp2->t_att[0].ar)) {
erasereg(rp-machregs);
break;
}
}
} else if (tp1->t_token == -1) {
if (eqtoken(tp2,&machregs[tp1->t_att[0].ar].r_contents))
return(0);
machregs[tp1->t_att[0].ar].r_contents = *tp2;
}
/*
* If we arrive here the move must really be executed
*/
for (mp=moves;mp<moves+NMOVES;mp++) {
if (!match(tp1,&machsets[mp->m_set1],mp->m_expr1))
continue;
if (match(tp2,&machsets[mp->m_set2],mp->m_expr2))
break;
/*
* Correct move rule is found
*/
}
assert(mp<moves+NMOVES);
/*
* To get correct interpretation of things like %[1]
* in move code we stack tp2 and tp1. This little trick
* saves a lot of testing in other places.
*/
if (mp->m_cindex!=0) {
fakestack[stackheight] = *tp2;
fakestack[stackheight+1] = *tp1;
stackheight += 2;
t = codegen(&coderules[mp->m_cindex],ply,toplevel,maxcost,0);
if (t <= maxcost)
t += costcalc(mp->m_cost);
stackheight -= 2;
} else {
t = 0;
}
return(t);
}

View File

@@ -1,131 +0,0 @@
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include <em_spec.h>
#include <em_flag.h>
#include "assert.h"
#include "param.h"
#include "tables.h"
#include "types.h"
#include <cg_pattern.h>
#include "data.h"
#include "result.h"
#include "extern.h"
/*
* (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: Hans van Staveren
*/
#ifndef NDEBUG
#include <stdio.h>
extern char em_mnem[][4];
#endif
byte *trypat(bp,len) register byte *bp; {
register patlen,i;
result_t result;
getint(patlen,bp);
if (len == 3) {
if (patlen < 3)
return(0);
} else {
if (patlen != len)
return(0);
}
for(i=0;i<patlen;i++)
if (emp[i].em_instr != (*bp++&BMASK))
return(0);
for (i=0;i<patlen;i++)
if (emp[i].em_optyp==OPNO)
dollar[i].e_typ=EV_UNDEF;
else if ((dollar[i].e_typ=argtyp(emp[i].em_instr))==EV_INT)
dollar[i].e_v.e_con=emp[i].em_u.em_ioper;
else
dollar[i].e_v.e_str=emp[i].em_soper;
getint(i,bp);
if (i!=0) {
result = compute(&enodes[i]);
if (result.e_typ != EV_INT || result.e_v.e_con == 0)
return(0);
}
#ifndef NDEBUG
if (Debug) {
fprintf(stderr,"Matched:");
for (i=0;i<patlen;i++)
fprintf(stderr," %3.3s",em_mnem[emp[i].em_instr-sp_fmnem]);
fprintf(stderr,"\n");
}
#endif
saveemp = emp;
emp += patlen;
return(bp);
}
extern char em_flag[];
argtyp(mn) {
switch(em_flag[mn-sp_fmnem]&EM_PAR) {
case PAR_W:
case PAR_S:
case PAR_Z:
case PAR_O:
case PAR_N:
case PAR_L:
case PAR_F:
case PAR_R:
case PAR_C:
return(EV_INT);
default:
return(EV_STR);
}
}
byte *nextem(toplevel) {
register i;
short hash[3];
register byte *bp;
byte *cp;
int index;
register struct emline *ep;
if (toplevel) {
if (nemlines && emp>emlines) {
nemlines -= emp-emlines;
for (i=0,ep=emlines;i<nemlines;i++)
*ep++ = *emp++;
emp=emlines;
}
fillemlines();
}
hash[0] = emp[0].em_instr;
hash[1] = (hash[0]<<4) ^ emp[1].em_instr;
hash[2] = (hash[1]<<4) ^ emp[2].em_instr;
for (i=2;i>=0;i--) {
index = pathash[hash[i]&BMASK];
while (index != 0) {
bp = &pattern[index];
if ( bp[PO_HASH] == (hash[i]>>8))
if ((cp=trypat(&bp[PO_MATCH],i+1)) != 0)
return(cp);
index = (bp[PO_NEXT]&BMASK) | (bp[PO_NEXT+1]<<8);
}
}
return(0);
}

View File

@@ -1,19 +0,0 @@
/* $Header$ */
#define BMASK 0377
#define BSHIFT 8
#define TRUE 1
#define FALSE 0
#define MAXINT 32767
#define INFINITY (MAXINT+100)
#define MAXROM 3
/*
* Tunable constants
*/
#define MAXEMLINES 20
#define MAXFSTACK 20

View File

@@ -1,175 +0,0 @@
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include "assert.h"
#include "param.h"
#include "tables.h"
#include "types.h"
#include <cg_pattern.h>
#include "data.h"
#include "result.h"
#include "extern.h"
/*
* (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: Hans van Staveren
*/
chrefcount(regno,amount,tflag) {
register struct reginfo *rp;
register i;
rp= &machregs[regno];
#if MAXMEMBERS!=0
if (rp->r_members[0]==0) {
#endif
rp->r_refcount += amount;
if (tflag)
rp->r_tcount += amount;
assert(rp->r_refcount >= 0);
#if MAXMEMBERS!=0
} else
for (i=0;i<MAXMEMBERS;i++)
if (rp->r_members[i]!=0)
chrefcount(rp->r_members[i],amount,tflag);
#endif
}
getrefcount(regno) {
register struct reginfo *rp;
register i,maxcount;
rp= &machregs[regno];
#if MAXMEMBERS!=0
if (rp->r_members[0]==0)
#endif
return(rp->r_refcount);
#if MAXMEMBERS!=0
else {
maxcount=0;
for (i=0;i<MAXMEMBERS;i++)
if (rp->r_members[i]!=0)
maxcount=max(maxcount,getrefcount(rp->r_members[i]));
return(maxcount);
}
#endif
}
erasereg(regno) {
register struct reginfo *rp;
#if MAXMEMBERS==0
awayreg(regno);
#else
for (rp=machregs;rp<machregs+NREGS;rp++)
if (rp->r_clash[regno>>4]&(1<<(regno&017)))
awayreg(rp-machregs);
#endif
}
awayreg(regno) {
register struct reginfo *rp;
register tkdef_p tdp;
register i;
rp = &machregs[regno];
rp->r_contents.t_token = 0;
for (i=0;i<TOKENSIZE;i++)
rp->r_contents.t_att[i].aw = 0;
/* Now erase recursively all registers containing
* something using this one
*/
for (rp=machregs;rp<machregs+NREGS;rp++) {
if (rp->r_contents.t_token == -1) {
if (rp->r_contents.t_att[0].ar == regno)
erasereg(rp-machregs);
} else {
tdp= & tokens[rp->r_contents.t_token];
for (i=0;i<TOKENSIZE;i++)
if (tdp->t_type[i] == EV_REG &&
rp->r_contents.t_att[i].ar == regno) {
erasereg(rp-machregs);
break;
}
}
}
}
cleanregs() {
register struct reginfo *rp;
register i;
for (rp=machregs;rp<machregs+NREGS;rp++) {
rp->r_contents.t_token = 0;
for (i=0;i<TOKENSIZE;i++)
rp->r_contents.t_att[i].aw = 0;
}
}
#ifndef NDEBUG
inctcount(regno) {
register struct reginfo *rp;
register i;
rp = &machregs[regno];
#if MAXMEMBERS!=0
if (rp->r_members[0] == 0) {
#endif
rp->r_tcount++;
#if MAXMEMBERS!=0
} else {
for (i=0;i<MAXMEMBERS;i++)
if (rp->r_members[i] != 0)
inctcount(rp->r_members[i]);
}
#endif
}
chkregs() {
register struct reginfo *rp;
register token_p tp;
register tkdef_p tdp;
int i;
for (rp=machregs;rp<machregs+NREGS;rp++) {
assert(rp->r_tcount==0);
}
for (tp=fakestack;tp<fakestack+stackheight;tp++) {
if (tp->t_token == -1)
inctcount(tp->t_att[0].ar);
else {
tdp = &tokens[tp->t_token];
for (i=0;i<TOKENSIZE;i++)
if (tdp->t_type[i]==EV_REG)
inctcount(tp->t_att[i].ar);
}
}
#ifdef REGVARS
#include <em_reg.h>
for(i=reg_any;i<=reg_float;i++) {
int j;
for(j=0;j<nregvar[i];j++)
inctcount(rvnumbers[i][j]);
}
#endif REGVARS
for (rp=machregs;rp<machregs+NREGS;rp++) {
assert(rp->r_refcount==rp->r_tcount);
rp->r_tcount=0;
}
}
#endif

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