Delete 689 undead files.

These files "magically reappeared" after the conversion from CVS to
Mercurial.  The old CVS repository deleted these files but did not
record *when* it deleted these files.  The conversion resurrected these
files because they have no history of deletion.  These files were
probably deleted before year 1995.  The CVS repository begins to record
deletions around 1995.

These files may still appear in older revisions of this Mercurial
repository, when they should already be deleted.  There is no way to fix
this, because the CVS repository provides no dates of deletion.

See http://sourceforge.net/mailarchive/message.php?msg_id=29823032
This commit is contained in:
George Koehler
2012-09-20 22:26:32 -04:00
parent b6dfaefeff
commit 0131ca4d46
689 changed files with 0 additions and 68730 deletions

View File

@@ -1,6 +0,0 @@
PIC=pic
TBL=tbl
REFER=refer
../ceg.doc: ceg.tr ceg.ref
$(PIC) ceg.tr | $(REFER) -e -p ceg.ref | $(TBL) > $@

View File

@@ -1,284 +0,0 @@
.TL
Code Expander
.br
(proposal)
.SH
Introduction
.LP
The \fBcode expander\fR, \fBce\fR, is a program that translates EM-code to
objectcode. The main goal is to translate very fast. \fBce\fR is an instance
of the EM_CODE(3L)-interface. During execution of \fBce\fR, \fBce\fR will build
in core a machine independent objectfile ( NEW A.OUT(5L)). With \fBcv\fR or
with routines supplied by the user the machine independent objectcode will
be converted to a machine dependent object code. \fBce\fR needs
information about the targetmachine (e.g. the opcode's). We divide the
information into two parts:
.IP
- The description in assembly instructions of EM-code instructions.
.IP
- The description in objectcode of assembly instructions.
.LP
With these two tables we can make a \fBcode expander generator\fR which
generates a \fBce\fR. It is possible to put the information in one table
but that will probably introduce (propable) more bugs in the table. So we
divide and conquer. With this approach it is also possible to generate
assembly code ( rather yhan objectcode), wich is useful for debugging.
There is of course a link between the two tables, the link
consist of a restriction on the assembly format. Every assembly
instruction must have the following format:
.sp
INSTR ::= LABEL : MNEMONIC [ OPERAND ( "," OPERAND)* ]
.sp
.LP
\fBCeg\fR uses the following algorithm:
.IP \0\0a)
The assembly table will be converted to a (C-)routine assemble().
assemble() gets as argument a string, the assembler instruction,
and can use the MNEMONIC to execute the corresponding action in the
assembly table.
.IP \0\0b)
The routine assemble() can now be used to convert the EM-code table to
a set of C-routines, wich together form an instance of the
EM_CODE(3L).
.SH
The EM-instruction table
.LP
We use the following grammar:
.sp
.TS
center box ;
l.
TABLE ::= (ROW)*
ROW ::= C_instr ( SPECIAL | SIMPLE)
SPECIAL ::= ( CONDITION SIMPLE)+ 'default' SIMPLE
SIMPLE ::= '==>' ACTIONLIST | '::=' ACTIONLIST
ACTIONLIST ::= [ ACTION ( ';' ACTION)* ] '.'
ACTION ::= function-call | assembly-instruction
.TE
.LP
An example for the 8086:
.LP
.DS
C_lxl
$arg1 == 0 ==> "push bp".
$arg1 == 1 ==> "push EM_BSIZE(bp)".
default ==> "mov cx, $arg1";
"mov si, bp";
"1: mov si, EM_BSIZE(si);
"loop 1b"
"push si".
.DE
.sp
Some remarks:
.sp
* The C_instr is a function indentifier in the EM_CODE(3L)-interface.
.LP
* CONDITION is a "boolean" C-expression.
.LP
* The arguments of an EM-instruction can be used in CONDITION and in assembly
instructions. They are referred by $arg\fIi\fR. \fBceg\fR modifies the
arguments as follows:
.IP \0\0-
For local variables at positive offsets it increases this offset by EM_BSIZE
.IP \0\0-
It makes names en labels unique. The user must supply the formats (see mach.h).
.LP
* function-call is allowed to implement e.g. push/pop optimization.
For example:
.LP
.DS
C_adi
$arg1 == 2 ==> combine( "pop ax");
combine( "pop bx");
"add ax, bx";
save( "push ax").
default ==> arg_error( "C_adi", $arg1).
.DE
.LP
* The C-functions called in the EM-instructions table have to use the routine
assemble()/gen?(). "assembler-instr" is in fact assemble( "assembler-instr").
.LP
* \fBceg\fR takes care not only about the conversions of arguments but also
about
changes between segments. There are situation when one doesn't want
conversion of arguments. This can be done by using ::= in stead of ==>.
This is usefull when two C_instr are equivalent. For example:
.IP
C_slu ::= C_sli( $arg1)
.LP
* There are EM-CODE instructions wich are machine independent (e.g. C_open()).
For these EM_CODE instructions \fBceg\fR will generate \fIdefault\fR-
instructions. There is one exception: in the case of C_pro() the tablewriter
has to supply a function prolog().
.LP
* Also the EM-pseudoinstructions C_bss_\fIcstp\fR(), C_hol_\fIcstp\fR(),
C_con_\fIcstp\fR() and C_rom_\fIcstp\fR can be translated automaticly.
\fBceg\fR only has to know how to interpretate string-constants:
.DS
\&..icon $arg2 == 1 ==> gen1( (char) atoi( $arg1))
$arg2 == 2 ==> gen2( atoi( $arg1))
$arg2 == 4 ==> gen4( atol( $arg1))
\&..ucon $arg2 == 1 ==> gen1( (char) atoi( $arg1))
$arg2 == 2 ==> gen2( atoi( $arg1))
$arg2 == 4 ==> gen4( atol( $arg1))
\&..fcon ::= not_implemented( "..fcon")
.DE
.LP
* Still, life can be made easier for the tablewriter; For the routines wich
he/she didn't implement \fBceg\fR will generate a default instruction wich
generates an error-message. \fBceg\fR seems to generate :
.IP
C_xxx ::= not_implemented( "C_xxx")
.SH
The assembly table
.LP
How to map assembly on objectcode.
.LP
Each row in the table consists of two fields, one field for the assembly
instruction, the other field for the corresponding objectcode. The tablewriter
can use the following primitives to generate code for the machine
instructions :
.IP "\0\0gen1( b)\0\0:" 17
generates one byte in de machine independent objectfile.
.IP "\0\0gen2( w)\0\0:" 17
generates one word ( = two bytes), the table writer can change the byte
order by setting the flag BYTES_REVERSED.
.IP "\0\0gen4( l)\0\0:" 17
generates two words ( = four bytes), the table writer can change the word
order by setting the flag WORDS_REVERSED.
.IP "\0\0reloc( n, o, r)\0\0:" 17
generates relocation information for a label ( = name + offset +
relocationtype).
.LP
Besides these primitives the table writer may use his self written
C-functions. This allows the table writer e.g. to write functions to set
bitfields within a byte.
.LP
There are more or less two methods to encode the assembly instructions:
.IP \0\0a)
MNEMONIC and OPERAND('s) are encoded independently of each other. This can be
done when the target machine has an orthogonal instruction set (e.g. pdp-11).
.IP \0\0b)
MNEMONIC and OPERAND('s) together determine the opcode. In this case the
assembler often uses overloading: one MNEMONIC is used for several
different machine-instructions. For example : (8086)
.br
mov ax, bx
.br
mov ax, variable
.br
These instructions have different opcodes.
.LP
As the transformation MNEMONIC-OPCODE is not one to
one the table writer must be allowed to put restrictions on the operands.
This can be done with type declarations. For example:
.LP
.DS
mov dst:REG, src:MEM ==>
gen1( 0x8b);
modRM( op2.reg, op1);
.DE
.DS
mov dst:REG, src:REG ==>
gen1( 0x89);
modRM( op2.reg, op1);
.DE
.LP
modRM() is a function written by the tablewriter and is used to encode
the operands. This frees the table writer of endless typing.
.LP
The table writer has to do the "typechecking" by himself. But typechecking
is almost the same as operand decoding. So it's more efficient to do this
in one function. We now have all the tools to describe the function
assemble().
.IP
assemble() first calls the function
decode_operand() ( by the table writer written), with two arguments: a
string ( the operand) and a
pointer to a struct. The struct is declared by the table writer and must
consist of at least a field called type. ( the other fields in the struct can
be used to remember information about the decoded operand.) Now assemble()
fires a row wich is selected by mapping the MNEMONIC and the type of the
operands.
.br
In the second field of a row there may be references to other
fields in the struct (e.g. op2.reg in the example above).
.LP
We ignored one problem. It's possible when the operands are encoded, that
not everything is known. For example $arg\fIi\fR arguments in the
EM-instruction table get their value at runtime. This problem is solved by
introducing a function eval(). eval() has a string as argument and returns
an arith. The string consists of constants and/or $arg\fIi\fR's and the value
returned by eval() is the value of the string. To encode the $arg\fIi\fR's
in as few bytes as possible the table writer can use the statements %if,
%else and %endif. They can be used in the same manner as #if, #else and
#endif in C and result in a runtime test. An example :
.LP
.DS
-- Some rows of the assembly table
mov dst:REG, src:DATA ==>
%if sfit( eval( src), 8) /* does the immediate-data fit in 1 byte? */
R53( 0x16 , op1.reg);
gen1( eval( src));
%else
R53( 0x17 , op1.reg);
gen2( eval( src));
%endif
.LD
mov dst:REG, src:REG ==>
gen1( 0x8b);
modRM( op1.reg, op2);
.DE
.DS
-- The corresponding part in the function assemble() :
case MNEM_mov :
decode_operand( arg1, &op1);
decode_operand( arg2, &op2);
if ( REG( op1.type) && DATA( op2.type)) {
printf( "if ( sfit( %s, 8)) {\\\\n", eval( src));
R53( 0x16 , op1.reg);
printf( "gen1( %s)\\\\n", eval( arg2));
printf( "}\\\\nelse {\\\\n");
R53( 0x17 , op1.reg);
printf( "gen2( %s)\\\\n", eval( arg2));
printf( "}\\\\n");
}
else if ( REG( op1.type) && REG( op2.type)) {
gen1( 0x8b);
modRM( op1.reg, op2);
}
.DE
.DS
-- Some rows of the right part of the EM-instruction table are translated
-- in the following C-functions.
"mov ax, $arg1" ==>
if ( sfit( w, 8)) { /* w is the actual argument of C_xxx( w) */
gen1( 176); /* R53() */
gen1( w);
}
else {
gen1( 184);
gen2( w);
}
.LD
"mov ax, bx" ==>
gen1( 138);
gen1( 99); /* modRM() */
.DE
.SH
Restrictions
.LP
.IP \0\01)
The EM-instructions C_exc() is not implemented.
.IP \0\03)
All messages are ignored.

View File

@@ -1,276 +0,0 @@
.TL
A prototype Code expander
.NH
Introduction
.PP
A program to be compiled with ACK is first fed into the preprocessor.
The output of the preprocessor goes into the appropiate front end,
whose job it is to produce EM. The EM code generated is
fed into the peephole optimizer, wich scans it with a window of few
instructions, replacing certain inefficient code sequences by better
ones. Following the peephole optimizer follows a backend wich produces
good assembly code. The assembly code goes into the assembler and the objectcode
then goes into the loader/linker, the final component in the pipeline.
.PP
For various applications this scheme is too slow. For example for testing
programs; In this case the program has to be translated fast and the
runtime of the objectcode may be slower. A solution is to build a code
expander ( \fBce\fR) wich translates EM code to objectcode. Of course this
has to
be done automaticly by a code expander generator, but to get some feeling
for the problem we started out to build prototypes.
We built two types of ce's. One wich tranlated EM to assembly, one
wich translated EM to objectcode.
.NH
EM to assembly
.PP
We made one for the 8086 and one for the vax4. These ce's are instances of the
EM_CODE(3L)-interface and produce for a single EM instruction a set
of assembly instruction wich are semantic equivalent.
We implemented in the 8086-ce push/pop-optimalization.
.NH
EM to objectcode
.PP
Instead of producing assembly code we tried to produce vax4-objectcode.
During execution of ce, ce builds in core a machine independent
objectfile ( NEW A.OUT(5L)) and just before dumping the tables this
objectfile is converted to a Berkly 4.2BSD a.out-file. We build two versions;
One with static memory allocation and one with dynamic memory allocation.
If the first one runs out of memory it will give an error message and stop,
the second one will allocate more memory and proceed with producing
objectcode.
.PP
The C-frontend calls the EM_CODE-interface. So after linking the frontend
and the ce we have a pipeline in a program saving a lot of i/o.
It is interesting to compare this C-compiler ( called fcemcom) with "cc -c".
fcemcom1 (the dynamic variant of fcemcom) is tuned in such a way, that
alloc() won't be called.
.NH 2
Compile time
.PP
fac.c is a small program that produces n! ( see below). foo.c is small program
that loops a lot.
.TS
center, box, tab(:);
c | c | c | c | c | c
c | c | n | n | n | n.
compiler : program : real : user : sys : object size
=
fcemcom : sort.c : 31.0 : 17.5 : 1.8 : 23824
fcemcom1 : : 59.0 : 21.2 : 3.3 :
cc -c : : 50.0 : 38.0 : 3.5 : 6788
_
fcemcom : ed.c : 37.0 : 23.6 : 2.3 : 41744
fcemcom1 : : 1.16.0 : 28.3 : 4.6 :
cc -c : : 1.19.0 : 54.8 : 4.3 : 11108
_
fcemcom : cp.c : 4.0 : 2.4 : 0.8 : 4652
fcemcom1 : : 9.0 : 3.0 : 1.0 :
cc -c : : 8.0 : 5.2 : 1.6 : 1048
_
fcemcom : uniq.c : 5.0 : 2.5 : 0.8 : 5568
fcemcom1 : : 9.0 : 2.9 : 0.8 :
cc -c : : 13.0 : 5.4 : 2.0 : 3008
_
fcemcom : btlgrep.c : 24.0 : 7.2 : 1.4 : 12968
fcemcom1 : : 23.0 : 8.1 : 1.2 :
cc -c : : 1.20.0 : 15.3 : 3.8 : 2392
_
fcemcom : fac.c : 1.0 : 0.1 : 0.5 : 216
fecmcom1 : : 2.0 : 0.2 : 0.5 :
cc -c : : 3.0 : 0.7 : 1.3 : 92
_
fcemcom : foo.c : 4.0 : 0.2 : 0.5 : 272
fcemcom1 : : 11.0 : 0.3 : 0.5 :
cc -c : : 7.0 : 0.8 : 1.6 : 108
.TE
.NH 2
Run time
.LP
Is the runtime very bad?
.TS
tab(:), box, center;
c | c | c | c | c
c | c | n | n | n.
compiler : program : real : user : system
=
fcem : sort.c : 22.0 : 17.5 : 1.5
cc : : 5.0 : 2.4 : 1.1
_
fcem : btlgrep.c : 1.58.0 : 27.2 : 4.2
cc : : 12.0 : 3.6 : 1.1
_
fcem : foo.c : 1.0 : 0.7 : 0.1
cc : : 1.0 : 0.4 : 0.1
_
fcem : uniq.c : 2.0 : 0.5 : 0.3
cc : : 1.0 : 0.1 : 0.2
.TE
.NH 2
quality object code
.LP
The runtime is very bad so its interesting to have look at the code which is
produced by fcemcom and by cc -c. I took a program which computes recursively
n!.
.DS
long fac();
main()
{
int n;
scanf( "%D", &n);
printf( "fac is %D\\\\n", fac( n));
}
long fac( n)
int n;
{
if ( n == 0)
return( 1);
else
return( n * fac( n-1));
}
.DE
.br
.br
.br
.br
.LP
"cc -c fac.c" produces :
.DS
fac: tstl 4(ap)
bnequ 7f
movl $1, r0
ret
7f: subl3 $1, 4(ap), r0
pushl r0
call $1, fac
movl r0, -4(fp)
mull3 -4(fp), 4(ap), r0
ret
.DE
.br
.br
.LP
"fcem fac.c fac.o" produces :
.DS
_fac: 0
42: jmp be
48: pushl 4(ap)
4e: pushl $0
54: subl2 (sp)+,(sp)
57: tstl (sp)+
59: bnequ 61
5b: jmp 67
61: jmp 79
67: pushl $1
6d: jmp ba
73: jmp b9
79: pushl 4(ap)
7f: pushl $1
85: subl2 (sp)+,(sp)
88: calls $0,_fac
8f: addl2 $4,sp
96: pushl r0
98: pushl 4(ap)
9e: pushl $4
a4: pushl $4
aa: jsb .cii
b0: mull2 (sp)+,(sp)
b3: jmp ba
b9: ret
ba: movl (sp)+,r0
bd: ret
be: jmp 48
.DE
.NH 1
Conclusions
.PP
comparing "cc -c" with "fcemcom"
.LP
.TS
center, box, tab(:);
c | c s | c | c s
^ | c s | ^ | c s
^ | c | c | ^ | c | c
l | n | n | n | n | n.
program : compile time : object size : runtime
:_::_
: user : sys :: user : sys
=
sort.c : 0.47 : 0.5 : 3.5 : 7.3 : 1.4
_
ed.c : 0.46 : 0.5 : 3.8 : : :
_
cp.c : 0.46 : 0.5 : 4.4 : : :
_
uniq.c : 0.46 : 0.4 : 1.8 : : :
_
btlgrep.c : 0.47 : 0.3 : 5.4 : 7.5 : 3.8
_
fac.c : 0.14 : 0.4 : 2.3 : 1.8 : 1.0
_
foo.c : 0.25 : 0.3 : 2.5 : 5.0 : 1.5
.TE
.PP
The results for fcemcom1 are almost identical; The only thing that changes
is that fcemcom1 is 1.2 slower than fcemcom. ( compile time) This is due to
to an another datastructure . In the static version we use huge array's for
the text- and
data-segment, the relocation information, the symboltable and stringarea.
In the dynamic version we use linked lists, wich makes it expensive to get
and to put a byte on a abritrary memory location. So it is probably better
to use realloc(), because in the most cases there will be enough memory.
.PP
The quality of the objectcode is very bad. The reason is that the frontend
generates bad code and expects the peephole-optimizer to improve the code.
This is also one of the main reasons that the runtime is very bad.
(e.g. the expensive "cii" with arguments 4 and 4 could be deleted.)
So its seems a good
idea to put a new peephole-optimizer between the frontend and the ce.
.PP
Using the peephole optimizer the ce would produce :
.DS
_fac: 0
pushl 4(ap)
tstl (sp)+
beqlu 1f
jmp 3f
1 : pushl $1
jmp 2f
3 : pushl 4(ap)
decl (sp)
calls $0,_fac
addl2 $4,sp
pushl r0
pushl 4(ap)
mull2 (sp)+,(sp)
movl (sp)+,r0
2 : ret
.DE
.PP
Bruce McKenzy already implemented it and made some improvements in the
source code of the ce. The compile-time is two to two and a half times better
and the
size of the objectcode is two to three times bigger.(comparing with "cc -c")
Still we could do better.
.PP
Using peephole- and push/pop-optimization ce could produce :
.DS
_fac: 0
tstl 4(ap)
beqlu 1f
jmp 2f
1 : pushl $1
jmp 3f
2 : decl 4(ap)
calls $0,_fac
addl2 $4,sp
mull3 4(ap), r0, -(sp)
movl (sp)+, r0
3 : ret
.DE
.PP
prof doesn't cooperate, so no profile information.
.PP

View File

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

View File

@@ -1,55 +0,0 @@
REFS=-p refs.opt -p refs.stat -p refs.gen
INTRO=intro/intro?
OV=ov/ov?
IC=ic/ic?
CF=cf/cf?
IL=il/il?
SR=sr/sr?
CS=cs/cs?
SP=sp/sp?
UD=ud/ud?
LV=lv/lv?
CJ=cj/cj?
BO=bo/bo?
RA=ra/ra?
CA=ca/ca?
EGO=$(INTRO) $(OV) $(IC) $(CF) $(IL) $(SR) $(CS) $(SP) $(CJ) $(BO) \
$(UD) $(LV) $(RA) $(CA)
REFER=refer
TROFF=troff
TBL=tbl
TARGET=-Tlp
../ego.doc: refs.opt refs.stat refs.gen intro/head intro/tail $(EGO)
$(REFER) -sA+T -l4,2 $(REFS) intro/head $(EGO) intro/tail | $(TBL) > ../ego.doc
ego.f: refs.opt refs.stat refs.gen intro/head intro/tail $(EGO)
$(REFER) -sA+T -l4,2 $(REFS) intro/head $(EGO) intro/tail | $(TBL) | $(TROFF) $(TARGET) -ms > ego.f
intro.f: refs.opt refs.stat refs.gen intro/head intro/tail $(INTRO)
$(REFER) -sA+T -l4,2 $(REFS) intro/head $(INTRO) intro/tail | $(TBL) | $(TROFF) $(TARGET) -ms > intro.f
ov.f: refs.opt refs.stat refs.gen intro/head intro/tail $(OV)
$(REFER) -sA+T -l4,2 $(REFS) intro/head $(OV) intro/tail | $(TBL) | $(TROFF) $(TARGET) -ms > ov.f
ic.f: refs.opt refs.stat refs.gen intro/head intro/tail $(IC)
$(REFER) -sA+T -l4,2 $(REFS) intro/head $(IC) intro/tail | $(TBL) | $(TROFF) $(TARGET) -ms > ic.f
cf.f: refs.opt refs.stat refs.gen intro/head intro/tail $(CF)
$(REFER) -sA+T -l4,2 $(REFS) intro/head $(CF) intro/tail | $(TBL) | $(TROFF) $(TARGET) -ms > cf.f
il.f: refs.opt refs.stat refs.gen intro/head intro/tail $(IL)
$(REFER) -sA+T -l4,2 $(REFS) intro/head $(IL) intro/tail | $(TBL) | $(TROFF) $(TARGET) -ms > il.f
sr.f: refs.opt refs.stat refs.gen intro/head intro/tail $(SR)
$(REFER) -sA+T -l4,2 $(REFS) intro/head $(SR) intro/tail | $(TBL) | $(TROFF) $(TARGET) -ms > sr.f
cs.f: refs.opt refs.stat refs.gen intro/head intro/tail $(CS)
$(REFER) -sA+T -l4,2 $(REFS) intro/head $(CS) intro/tail | $(TBL) | $(TROFF) $(TARGET) -ms > cs.f
sp.f: refs.opt refs.stat refs.gen intro/head intro/tail $(SP)
$(REFER) -sA+T -l4,2 $(REFS) intro/head $(SP) intro/tail | $(TBL) | $(TROFF) $(TARGET) -ms > sp.f
cj.f: refs.opt refs.stat refs.gen intro/head intro/tail $(CJ)
$(REFER) -sA+T -l4,2 $(REFS) intro/head $(CJ) intro/tail | $(TBL) | $(TROFF) $(TARGET) -ms > cj.f
bo.f: refs.opt refs.stat refs.gen intro/head intro/tail $(BO)
$(REFER) -sA+T -l4,2 $(REFS) intro/head $(BO) intro/tail | $(TBL) | $(TROFF) $(TARGET) -ms > bo.f
ud.f: refs.opt refs.stat refs.gen intro/head intro/tail $(UD)
$(REFER) -sA+T -l4,2 $(REFS) intro/head $(UD) intro/tail | $(TBL) | $(TROFF) $(TARGET) -ms > ud.f
lv.f: refs.opt refs.stat refs.gen intro/head intro/tail $(LV)
$(REFER) -sA+T -l4,2 $(REFS) intro/head $(LV) intro/tail | $(TBL) | $(TROFF) $(TARGET) -ms > lv.f
ra.f: refs.opt refs.stat refs.gen intro/head intro/tail $(RA)
$(REFER) -sA+T -l4,2 $(REFS) intro/head $(RA) intro/tail | $(TBL) | $(TROFF) $(TARGET) -ms > ra.f
ca.f: refs.opt refs.stat refs.gen intro/head intro/tail $(CA)
$(REFER) -sA+T -l4,2 $(REFS) intro/head $(CA) intro/tail | $(TBL) | $(TROFF) $(TARGET) -ms > ca.f

View File

@@ -1,37 +0,0 @@
HOME=../..
TBL=tbl
NROFF=nroff
SUF=pr
TARGET=-Tlp
head: ../em.$(SUF)
FILES = macr.nr title.nr intro.nr mem.nr ispace.nr dspace.nr mapping.nr \
types.nr descr.nr env.nr traps.nr mach.nr assem.nr \
app.int.nr app.codes.nr app.exam.nr cont.nr
IOP=$(HOME)/etc/ip_spec.t# # to construct itables from
../em.$(SUF): $(FILES) itables dispatdummy em.i Makefile
$(TBL) $(FILES) | $(NROFF) -mkun $(TARGET) > ../em.$(SUF)
app.codes.pr: app.codes.nr itables dispatdummy
itables: $(IOP) ip.awk
awk -f ip.awk $(IOP) | sed 's/-/\\-/g' | $(TBL) >itables
dispatdummy: $(IOP) mkdispatch
mkdispatch < $(IOP) > dispatdummy
sed -f dispat1.sed < dispatdummy | $(TBL) > dispat1
sed -f dispat2.sed < dispatdummy | $(TBL) > dispat2
sed -f dispat3.sed < dispatdummy | $(TBL) > dispat3
mkdispatch: mkdispatch.c
$(CC) -I$(HOME)/h -o mkdispatch mkdispatch.c $(HOME)/lib.bin/em_data.a
.SUFFIXES : .pr .nr
.nr.pr: ; $(TBL) macr.nr $*.nr | $(NROFF) -mkun >$@
clean:
rm -f *.pr itables *.out dispatdummy dispat? *.o mkdispatch

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +0,0 @@
.BP
.AP "EM INTERPRETER"
.nf
.ft CW
.lg 0
.nr x \w' '
.ta \nxu +\nxu +\nxu +\nxu +\nxu +\nxu +\nxu +\nxu +\nxu +\nxu
.so em.i
.ft P
.lg 1
.fi

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,32 +0,0 @@
CFLAGS=-O
HOME=../../..
install \
all: em emdmp tables
tables: mktables $(HOME)/etc/ip_spec.t
mktables $(HOME)/etc/ip_spec.t tables
mktables: mktables.c $(HOME)/h/em_spec.h $(HOME)/h/em_flag.h \
$(HOME)/lib.bin/em_data.a $(HOME)/h/ip_spec.h
$(CC) -I$(HOME)/h -O -o mktables mktables.c $(HOME)/lib.bin/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) -I$(HOME)/h -I$(HOME)/config -o emdmp -O emdmp.c
cmp:
pr:
@pr em.p mktables.c emdmp.c

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 16 ; 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

File diff suppressed because it is too large Load Diff

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,9 +0,0 @@
# $Header$
FP = frontpage
DOC = abstract contents chap1 chap2 chap3 chap4 chap5 chap6 chap7\
chap8 chap9 appendix_A appendix_B
../lint.doc: $(FP) $(DOC)
cat $(FP) $(DOC) > ../lint.doc

View File

@@ -1,18 +0,0 @@
EMHOME=../..
FILES= p0 p1 p2 p3 p4 p5 p6 p7 p8 p9
PIC=pic
EQN=eqn
TBL=tbl
TARGET=-Tlp
../occam.doc: p0 p1 p2 p3 p4 p5 p6 p7 p8 p9 channel.h.t channel.c.t
soelim $(FILES) | $(PIC) $(TARGET) | $(TBL) | $(EQN) $(TARGET) > $@
channel.h.t: $(EMHOME)/h/ocm_chan.h
ctot <$(EMHOME)/h/ocm_chan.h >channel.h.t
channel.c.t: channel.c
ctot <channel.c >channel.c.t
channel.c: $(EMHOME)/lang/occam/lib/tail_ocm.a
arch x $(EMHOME)/lang/occam/lib/tail_ocm.a channel.c

View File

@@ -1,10 +0,0 @@
# $Header$
REFER=refer
TBL=tbl
TARGET=-Tlp
PIC=pic
GRAP=grap
../sparc.doc: refs title intro 1 2 3 4 5 A B init
$(REFER) -sA+T '-l\", ' -p refs title intro 1 2 3 4 5 A B | $(GRAP) | $(PIC) | $(TBL) | soelim > $@

View File

@@ -1,8 +0,0 @@
# $Header$
REFER=refer
TBL=tbl
TARGET=-Tlp
../top.doc: top.n refs.top
$(REFER) -sA+T -l4,2 -p refs.top top.n | $(TBL) > $@