fixup commit for tag 'distr2'

This commit is contained in:
cvs2hg
1987-08-26 13:58:31 +00:00
parent 0f4da3a208
commit ab5d79a8ce
268 changed files with 441 additions and 35277 deletions

View File

@@ -1,3 +1,4 @@
." $Header$
.RP
.TL
Back end table for the Intel 8080 micro-processor
@@ -96,11 +97,15 @@ The 8080 microprocessor provides five flip-flops used as condition flags
.br
The sign bit S is set (cleared) by certain instructions when the most significant
bit of the result of an operation equals one (zero).
.br
The zero bit Z is set (cleared) by certain operations when the
8-bit result of an operation equals (does not equal) zero.
.br
The parity bit P is set (cleared) if the 8-bit result of an
operation includes an even (odd) number of ones.
.br
C is the normal carry bit.
.br
AC is an auxiliary carry that indicates whether there has been a carry
out of bit 3 of the accumulator.
This auxiliary carry is used only by the DAA instruction, which
@@ -125,12 +130,14 @@ of register-pair HL.
.NH 3
Register addressing
.PP
With each instruction using register addressing,
With each intruction using register addressing,
only one register is specified (except for the MOV instruction),
although in many of them the accumulator is implied as
second operand.
Examples are CMP E, which compares register E with the accumulator,
and DCR B, which decrements register B.
.br
A few instructions deal with 16 bit register-pairs:
examples are DCX B, which decrements register-pair BC and the
PUSH and POP instructions.
@@ -166,7 +173,7 @@ The high order byte is stored at the highest address.
THE 8080 BACK END TABLE
.PP
The back end table is designed as described in [5].
For an overall design of a back end table I refer to this document.
So for an overall design of a back end table I refer to this document.
.br
This section deals with problems encountered in writing the
8080 back-end table.
@@ -178,30 +185,30 @@ Constant definitions
Word size (EM_WSIZE) and pointer size (EM_PSIZE) are both
defined as two bytes.
The hole between AB and LB (EM_BSIZE) is four bytes: only the
return address and the local base are saved.
return address and the localbase are saved.
.NH 2
Registers and their properties
.PP
All properties have the default size of two bytes, because one-byte
registers also cover two bytes when put on the real stack.
.sp 1
The next considerations led to the choice of register-pair BC
as local base.
Though saving the local base in memory would leave one more register-pair
The next considerations led to the choise of register-pair BC
as localbase.
Though saving the localbase in memory would leave one more register-pair
available as scratch register, it would slow down instructions
as 'lol' and 'stl' too much.
So a register-pair should be sacrificed as local base.
So a register-pair should be sacrificed as localbase.
Because a back-end without a free register-pair HL is completely
broken-winged, the only reasonable choices are BC and DE.
Though the choice between them might seem arbitrary at first sight,
broken-winged, the only reasonable choises are BC and DE.
Though the choise between them might seem arbitrary at first sight,
there is a difference between register-pairs BC and DE:
the instruction XCHG exchanges the contents of register-pairs DE and
HL.
When DE and HL are both heavily used on the fake-stack, this instruction
is very useful.
Since it won't be useful too often to exchange HL with the local base
is very usefull.
Since it won't be usefull too often to exchange HL with the localbase
and since an instruction exchanging BC and HL does not exist, BC is
chosen as local base.
chosen as localbase.
.sp 1
Many of the register properties are never mentioned in the
PATTERNS part of the table.
@@ -212,7 +219,7 @@ The properties really used in the PATTERNS part are:
the accumulator only
.IP reg:
any of the registers A, D, E, H or L. Of course the registers B and C which are
used as local base don't possess this property.
used as localbase don't possess this property.
When there is a single register on the fake-stack, its value
is always considered non-negative.
.IP dereg:
@@ -221,12 +228,12 @@ register-pair DE only
register-pair HL only
.IP hl_or_de:
register-pairs HL and DE both have this property
.IP local base:
.IP localbase:
used only once (i.e. in the EM-instruction 'str 0')
.PP
.sp 1
The stackpointer SP and the processor status word PSW have to be
defined explicitly because they are needed in some instructions
defined explicitely because they are needed in some instructions
(i.e. SP in LXI, DCX and INX and PSW in PUSH and POP).
.br
It doesn't matter that the processor status word is not just register A
@@ -245,6 +252,7 @@ Compared with many other back-end tables, there are only a small number of
different tokens (four).
Reasons are the limited addressing modes of the 8080 microprocessor,
no index registers etc.
.br
For example to translate the EM-instruction
.DS
lol 10
@@ -252,15 +260,16 @@ lol 10
the next 8080 instructions are generated:
.DS L
LXI H,10 /* load registers pair HL with value 10 */
DAD B /* add local base (BC) to HL */
DAD B /* add localbase (BC) to HL */
MOV E,M /* load E with byte pointed to by HL */
INX H /* increment HL */
MOV D,M /* load D with next byte */
.DE
Of course, instead of emitting code immediately, it could be postponed
Of course, instead of emitting code immmediately, it could be postponed
by placing something like a {LOCAL,10} on the fake-stack, but some day the above
mentioned code will have to be generated, so a LOCAL-token is
hardly useful.
hardly usefull.
.br
See also the comment on the load instructions.
.NH 2
Sets
@@ -286,13 +295,13 @@ In fact it usually takes 3 extra time periods when this register indirect mode
is used instead of register mode, but since the costs are not completely
orthogonal this results in small deficiencies for the DCR, INR and MOV
instructions.
Although it is not particularly useful these deficiencies are
Although it is not particularly usefull these deficiencies are
corrected in the INSTRUCTIONS part, by treating the register indirect
mode separately.
mode seperately.
.sp 1
The costs of the conditional call and return instructions really
depend on whether or not the call resp. return is actually made.
However, this is not important to the behaviour of the back end.
Unimportant.
.sp 1
Instructions not used in this table have been commented out.
Of course many of them are used in the library routines.
@@ -307,7 +316,7 @@ The TESTS section is only included to refrain
.B cgg
from complaining.
.NH 2
Stacking rules
Stackingrules
.PP
When, for example, the token {const2,10} has to be stacked while
no free register-pair is available, the next code is generated:
@@ -332,11 +341,12 @@ this instruction in fact exchanges the contents of these
register-pairs.
Before the coercion is carried out other appearances of DE and HL
on the fake-stack will be moved to the real stack, because in
the INSTRUCTION-part is told that XCHG destroys the contents
the INSTRUCTION-part is told that XCHG destroyes the contents
of both DE and HL.
.br
The coercion transposing one register-pair to another one by
emitting two MOV-instructions, will be used only if
one of the register-pairs is the local base.
one of the register-pairs is the localbase.
.NH 2
Patterns
.PP
@@ -351,7 +361,7 @@ gen lhld {label,$1} yields hl
.DE
the 'uses'-clause could have been omitted because
.B cgg
knows that LHLD destroys register-pair HL.
knows that LHLD destroyes register-pair HL.
.sp 1
Since there is only one register with property 'hlreg',
there is no difference between 'uses hlreg' (allocate a
@@ -359,7 +369,7 @@ register with property 'hlreg') and 'kills hlreg' (remove
all registers with property 'hlreg' from the fake-stack).
The same applies for the property 'dereg'.
.br
Consequently 'kills' is rarely used in this back-end table.
As a consequence 'kills' is rarely used in this back-end table.
.NH 3
Group 1: Load instructions
.PP
@@ -375,6 +385,7 @@ To refrain
.B cgg
from emitting the code for 'lol 10' again, an extra
pattern is included in the table for cases like this.
.br
The same applies for two consecutive 'loe'-s or 'lil'-s.
.sp 1
A bit tricky is 'lof'.
@@ -390,7 +401,7 @@ knows that HL is destroyed).
.sp 1
By lookahead,
.B cgg
can make a clever choice between the first and
can make a clever choise between the first and
second code rule of 'loi 4'.
The same applies for several other instructions.
.NH 3
@@ -404,12 +415,13 @@ Groups 3 and 4: Signed and unsigned integer arithmetic
Since the 8080 instruction set doesn't provide multiply and
divide instructions, special routines are made to accomplish these tasks.
.sp 1
Instead of providing four slightly differing routines for 16 bit signed or
Instead of providing four slighty differing routines for 16 bit signed or
unsigned division, yielding the quotient or the remainder,
the routines are merged.
This saves space and assembly time
when several variants are used in a particular program,
at the cost of a little speed.
.br
When the routine is called, bit 7 of register A indicates whether
the operands should be considered as signed or as unsigned integers,
and bit 0 of register A indicates whether the quotient or the
@@ -424,15 +436,14 @@ provided, because this one will usually be much faster.
.NH 3
Group 5: Floating point arithmetic
.PP
Floating point is not implemented.
Floating points are not implemented.
.br
Whenever an EM-instruction involving floating points is offered
to the code-generator, it calls the corresponding
library routine with the proper parameters.
Each floating point library routine calls 'eunimpl',
trapping with trap number 63.
to the code-generator, it generates the code 'call eunimpl',
which traps with trap number 63.
Some of the Pascal and C library routines output floating point
EM-instructions, so code has to be generated for them.
Of course this does not imply the code will ever be executed.
Of course this doesn't imply the code will ever be executed.
.NH 3
Group 12: Compare instructions
.PP
@@ -457,6 +468,7 @@ gen mov a,%1.2
but the current version of
.B cgg
doesn't approve this.
.br
In any case
.B cgg
chooses either DE or HL to store the result, using lookahead.
@@ -469,7 +481,7 @@ If only 2 bytes have to be returned, register-pair DE is used.
LIBRARY ROUTINES
.PP
Most of the library routines start with saving the return address
and the local base, so that the parameters are on the top of the stack
and the localbase, so that the parameters are on the top of the stack
and the registers B and C are available as scratch registers.
Since register-pair HL is needed to accomplish these tasks,
and also to restore everything just before the routine returns,
@@ -481,6 +493,7 @@ When a routine returns 2 bytes, they are usually returned in
registers-pair DE.
When it returns more than 2 bytes they are pushed onto the stack.
.br
It would have been possible to let the 32 bit arithmetic routines
return 2 bytes in DE and the remaining 2 bytes on the stack
(this often would have saved some space and execution time),
@@ -491,6 +504,7 @@ TRAPS
Whenever a trap, for example trying to divide by zero,
occurs in a program that originally was written in C or Pascal,
a special trap handler is called.
.br
This trap handler wants to write an appropriate error message on the
monitor.
It tries to read the message from a file (e.g. etc/pc_rt_errors in the
@@ -535,11 +549,11 @@ for example by downloading or
by storing it in ROM (Read Only Memory).
.sp 1
Depending on the characteristics of the particular 8080 based system, some
adaptations have to be made:
adaptions have to be made:
.IP 1) 10
In 'head_em': the base address, which is the address where the first
8080 instruction will be stored, and the initial value of the
stackpointer are set to 0x1000 and 0x8000 respectively.
stackpointer are set to 0x1000 and 0x8000 respectivally.
.br
Other systems require other values.
.IP 2)
@@ -560,12 +574,12 @@ If this is not the right way on your system, change it.
.IP 5)
In 'tail_em': the current version of the 8080 back-end has very limited I/O
capabilities, because it was tested on a system that
had no knowledge of files.
had no knowlegde of files.
So the implementation of the EM-instruction 'mon' is very simple;
it can only do the following things:
.RS
.IP Monitor\ call\ 1: 40
exit
Exit
.IP Monitor\ call\ 3:
read, always reads from the monitor.
.br
@@ -593,7 +607,7 @@ INTEL 8080 VERSUS ZILOG Z80 AND INTEL 8086
.NH 2
Introduction
.PP
At about the same time I developed the back end
At about the same time I develloped the back end
for the Intel 8080 and Intel 8085,
Frans van Haarlem did the same job for the Zilog z80 microprocessor.
Since the z80 processor is an extension of the 8080,
@@ -601,8 +615,8 @@ any machine code offered to a 8080 processor can be offered
to a z80 too.
The assembly languages are quite different however.
.br
During the developments of the back ends we have used
two micro-computers, both equipped with a z80 microprocessor.
During the devellopments of the back ends we have used
two micro-computers, both equiped with a z80 microprocessor.
Of course the output of the 8080 back end is assembled by an
8080 assembler. This should assure I have never used any of
the features that are potentially available in the z80 processor,
@@ -618,7 +632,7 @@ I have also involved the 8086 micro-processor in this measurements.
Differences between the 8080 and z80 processors
.PP
Except for some features that are less important concerning back ends,
there are two points where the z80 improves upon the 8080:
there are two points where the z80 improves the 8080:
.IP First, 18
the z80 has two additional index registers, IX and IY.
They are used as in
@@ -648,10 +662,11 @@ Special routines are included to jump to near locations, saving 1 byte.
Consequences for the 8080 and z80 back end
.PP
The most striking difference between the 8080 and z80 back ends
is the choice of the local base.
The writer of the z80 back end chose index register IY as local base,
is the choise of the localbase.
The writer of the z80 back end chose index register IY as localbase,
because this results in the cheapest coding of EM-instructions
like 'lol' and 'stl'.
.br
The z80 instructions that load local 10, for example
.DS
LD E,(IY+10)
@@ -664,7 +679,7 @@ Although the profit of the z80 might be not world-shocking,
it should be noted that as a side effect it may save some
pushing and popping since register pair HL is not used.
.sp 1
The choice of IY as local base has its drawbacks too.
The choise of IY as localbase has its drawbacks too.
The root of the problem is that it is not possible to add
IY to HL.
For the EM-instruction
@@ -684,7 +699,7 @@ This annoying push and pop instructions are also needed in some
other instructions, for instance in 'lol' when the offset
doesn't fit in one byte.
.sp 1
Beside the choice of the local base, I think there is no
Beside the choise of the localbase, I think there is no
fundamental difference between the 8080 and z80 back ends,
except of course that the z80 back end has register pair BC
and, less important, index register IX available as scratch registers.
@@ -700,6 +715,7 @@ some C programs and some Pascal programs.
Then I produced 8080, z80 and 8086 code for them.
Investigating the assembler listing I found the
lengths of the different parts of the generated code.
.br
I have checked two areas:
.IP 1) 8
the entire text part
@@ -726,7 +742,7 @@ The table below should be read as follows.
For all programs I have computed the ratio of the code-lengths
of the 8080, z80 and 8086.
The averages of all Pascal/C programs are listed in the table,
standardized to '100' for the 8080.
standarized to '100' for the 8080.
So the listed '107' indicates that the lengths
of the text parts of the z80 programs that originally were Pascal programs,
averaged 7 percent larger than in the corresponding 8080 programs.
@@ -744,7 +760,7 @@ averaged 7 percent larger than in the corresponding 8080 programs.
The most striking thing in this table is that the z80 back end appears
to produce larger code than the 8080 back end.
The reason is that the current z80 back end table is
not very sophisticated yet.
not very elaborate yet.
For instance it doesn't look for any EM-pattern longer than one.
So the table shows that the preparations in the 8080 back end table
to produce faster code (like recognizing special EM-patterns
@@ -752,7 +768,7 @@ and permitting one byte registers on the fake-stack)
was not just for fun, but really improved the generated code
significantly.
.sp 1
The table shows that the 8080 table is relatively better
The table shows that the 8080 table is relativelly better
when only the plain user program is considered instead of the entire text part.
This is not very surprising since the 8080 back end sometimes
uses library routines where the z80 and especially the 8086 don't.
@@ -781,7 +797,7 @@ An overview on the Amsterdam Compiler Kit.
.IP [3]
Tanenbaum, A.S., Stevenson, J.W., Keizer, E.G., and van Staveren, H.
.br
Description of an experimental machine architecture for use with block
Desciption of an experimental machine architecture for use with block
structured languages,
.br
Informatica report 81, Vrije Universiteit, Amsterdam, 1983.

View File

@@ -57,7 +57,7 @@ and the assembly code of the machine at hand.
.NH 1
What has changed since version 1 ?
.PP
This chapter can be skipped by anyone not familiar with the first version.
This section can be skipped by anyone not familiar with the first version.
It is not needed to understand the current version.
.PP
This paper describes the second version of the code generator system.
@@ -116,39 +116,40 @@ Alternatively one can think of the real stack as an infinite extension
at the bottom of the fake stack.
Both ways, the concatenation of the real stack and the fake stack
will be the stack as it would have been on a real EM machine (see figure).
.KF
.DS L
.ta 8 16 24 32 40 48 56 64 72
EM machine target machine
| | | |
| | | |
| | | |
| | | |
| | | real stack |
| | | | |
| | | | | growing
| EM stack | | | |
| | |_______________| \e|/
| | | |
| | | |
| | | |
| | | fake stack |
| | | |
|_______________| |_______________|
.TS
center;
cw(3.5c) cw(3c) cw(3.5c)
cw(3.5c) cw(3c) cw(3.5c)
|cw(3.5c)| cw(3c) |cw(3.5c)| .
EM machine target machine
.I
Relation between EM stack, real stack and fake stack.
.R
.DE
.KE
real stack
stack
grows
EM stack \s+2\(br\s0
\s+2\(br\s0
\s+2\(br\s0 _
\s+2\(br\s0
\s+2\(da\s0
fake stack
_ _
.T&
ci s s.
Relation between EM stack, real stack and fake stack.
.TE
During code generation tokens will be kept on the fake stack as long
as possible but when they are moved to the real stack,
by generating code for the push,
all tokens above\u*\d
all tokens above\v'-.25m'\(dg\v'.25m'
.FS
* in this document the stack is assumed to grow downwards,
\(dg in this document the stack is assumed to grow downwards,
although the top of the stack will mean the first element that will
be popped.
.FE
@@ -233,7 +234,7 @@ to register variables in the rest of this document.
.PP
The front ends generate messages to the back ends telling them which
local variables could go into registers.
The information given is the offset of the local, it's size and type
The information given is the offset of the local, its size and type
and a scoring number, roughly the number of times it occurs.
.PP
The decision which variable to put in which register is taken by the
@@ -297,8 +298,9 @@ at will to improve legibility.
Identifiers used in the table have the same syntax as C identifiers,
upper and lower case considered different, all characters significant.
Here is a list of reserved words; all of these are unavailable as identifiers.
.DS L
.ta 14 28 42 56
.TS
box;
l l l l l.
ADDR STACK from reg_any test
COERCIONS STACKINGRULES gen reg_float to
INSTRUCTIONS TESTS highw reg_loop ufit
@@ -309,7 +311,7 @@ PROPERTIES cost loww reusing
REGISTERS defined move rom
SETS exact pat samesign
SIZEFACTOR example proc sfit
.DE
.TE
C style comments are accepted.
.DS
/* this is a comment */
@@ -330,7 +332,7 @@ NAME=value
.DE
value being an integer or string.
Three constants must be defined here:
.IP EM_WSIZE 10
.IP EM_WSIZE 14
Number of bytes in a machine word.
This is the number of bytes
a \fBloc\fP instruction will put on the stack.
@@ -360,21 +362,21 @@ This is given as
FORMAT = string
.DE
The string must be a valid printf(III) format,
and defaults to "%d" or "%ld" depending on the wordsize of
the machine. For example on the PDP-11 one can use
and defaults to "%ld".
For example on the PDP-11 one can use
.DS
FORMAT= "0%o"
FORMAT= "0%lo"
.DE
to satisfy the old UNIX assembler that reads octal unless followed by
a period, and the ACK assembler that follows C conventions.
.PP
Tables under control of programs like
Tables under control of source code control systems like
.I sccs
or
.I rcs
can put their id-string here, for example
.DS
rcsid="$Header$"
rcsid="$\&Header$"
.DE
These strings, like all strings in the table, will eventually
end up in the binary code generator produced.
@@ -385,6 +387,7 @@ same order of magnitude.
This can be done as
.DS
SIZEFACTOR = C\d3\u/C\d4\u
.sp
TIMEFACTOR = C\d1\u/C\d2\u
.DE
Above numbers must be read as rational numbers.
@@ -403,24 +406,24 @@ It consists of a list of user-defined
identifiers optionally followed by the size
of the property in parentheses, default EM_WSIZE.
Example for the PDP-11:
.DS
.ta 8 16 24 32 40
PROPERTIES /* The header word for this section */
.TS
l l.
PROPERTIES /* The header word for this section */
GENREG /* All PDP registers */
REG /* Normal registers (allocatable) */
ODDREG /* All odd registers (allocatable) */
REGPAIR(4) /* Register pairs for division */
FLTREG(4) /* Floating point registers */
DBLREG(8) /* Same, double precision */
GENFREG(4) /* generic floating point */
GENDREG(8) /* Same, double precision */
FLTREGPAIR(8) /* register pair for modf */
DBLREGPAIR(16) /* Same, double precision */
LOCALBASE /* Guess what */
GENREG /* All PDP registers */
REG /* Normal registers (allocatable) */
ODDREG /* All odd registers (allocatable) */
REGPAIR(4) /* Register pairs for division */
FLTREG(4) /* Floating point registers */
DBLREG(8) /* Same, double precision */
GENFREG(4) /* generic floating point */
GENDREG(8) /* Same, double precision */
FLTREGPAIR(8) /* register pair for modf */
DBLREGPAIR(16) /* Same, double precision */
LOCALBASE /* Guess what */
STACKPOINTER
PROGRAMCOUNTER
.DE
.TE
Registers are allocated by asking for a property,
so if for some reason in later parts of the table
one particular register must be allocated it
@@ -438,22 +441,22 @@ Syntax:
<register> : ident [ '(' string ')' ] [ '=' ident [ '+' ident ] ]
.DE
Example for the PDP-11:
.DS L
.ta 8 16 24 32 40 48 56 64
.TS
l l.
REGISTERS
r0,r2,r4 : GENREG,REG.
r1,r3 : GENREG,REG,ODDREG.
r01("r0")=r0+r1 : REGPAIR.
fr0("r0"),fr1("r1"),fr2("r2"),fr3("r3") : GENFREG,FLTREG.
r0,r2,r4 : GENREG,REG.
r1,r3 : GENREG,REG,ODDREG.
r01("r0")=r0+r1 : REGPAIR.
fr0("r0"),fr1("r1"),fr2("r2"),fr3("r3") : GENFREG,FLTREG.
dr0("r0")=fr0,dr1("r1")=fr1,
dr2("r2")=fr2,dr3("r3")=fr3 : GENDREG,DBLREG.
dr2("r2")=fr2,dr3("r3")=fr3 : GENDREG,DBLREG.
fr01("r0")=fr0+fr1,fr23("r2")=fr2+fr3 : FLTREGPAIR.
dr01("r0")=dr0+dr1,dr23("r2")=dr2+dr3 : DBLREGPAIR.
lb("r5") : GENREG,LOCALBASE.
sp : GENREG,STACKPOINTER.
pc : GENREG,PROGRAMCOUNTER.
.DE
lb("r5") : GENREG,LOCALBASE.
sp : GENREG,STACKPOINTER.
pc : GENREG,PROGRAMCOUNTER.
.TE
.PP
The names in the left hand lists are names of registers as used
in the table.
@@ -525,20 +528,21 @@ Tokens should usually be declared for every addressing mode
of the machine at hand and for every size directly usable in
a machine instruction.
Example for the PDP-11 (incomplete):
.DS L
.TS
l l.
TOKENS
const2 = { INT num; } 2 cost(2,300) "$" num .
addr_local = { INT ind; } 2 .
addr_external = { ADDR off; } 2 "$" off.
const2 = { INT num; } 2 cost(2,300) "$" num .
addr_local = { INT ind; } 2 .
addr_external = { ADDR off; } 2 "$" off.
regdef2 = { GENREG reg; } 2 "*" reg.
regind2 = { GENREG reg; ADDR off; } 2 off "(" reg ")" .
reginddef2 = { GENREG reg; ADDR off; } 2 "*" off "(" reg ")" .
regdef2 = { GENREG reg; } 2 "*" reg.
regind2 = { GENREG reg; ADDR off; } 2 off "(" reg ")" .
reginddef2 = { GENREG reg; ADDR off; } 2 "*" off "(" reg ")" .
regconst2 = { GENREG reg; ADDR off; } 2 .
relative2 = { ADDR off; } 2 off .
reldef2 = { ADDR off; } 2 "*" off.
.DE
reldef2 = { ADDR off; } 2 "*" off.
.TE
.PP
Types allowed in the struct are ADDR, INT and all register properties.
The type ADDR means a string and an integer,
@@ -574,7 +578,7 @@ that can adjust the time/space tradeoff to all positions
from 100% time to 100% space.
.LP
By supplying different code rules in certain situations
it is possible to get a code generator that can adjust it's
it is possible to get a code generator that can adjust its
code to the need of the moment.
This is probably most useful with small machines,
experience has shown that on the larger micro's and mini's
@@ -620,21 +624,21 @@ in the remainder of the table,
but for clarity it is usually better not to.
.LP
Example for the PDP-11 (incomplete):
.DS L
.ta 8 16 24 32 40 48 56 64
.TS
l l.
SETS
src2 = GENREG + regdef2 + regind2 + reginddef2 + relative2 +
reldef2 + addr_external + const2 + LOCAL + ILOCAL +
autodec + autoinc .
dst2 = src2 - ( const2 + addr_external ) .
xsrc2 = src2 + ftoint .
src1 = regdef1 + regind1 + reginddef1 + relative1 + reldef1 .
dst1 = src1 .
src1or2 = src1 + src2 .
src4 = relative4 + regdef4 + DLOCAL + regind4 .
dst4 = src4 .
.DE
src2 = GENREG + regdef2 + regind2 + reginddef2 + relative2 +
\h'\w'= 'u'reldef2 + addr_external + const2 + LOCAL + ILOCAL +
\h'\w'= 'u'autodec + autoinc .
dst2 = src2 - ( const2 + addr_external ) .
xsrc2 = src2 + ftoint .
src1 = regdef1 + regind1 + reginddef1 + relative1 + reldef1 .
dst1 = src1 .
src1or2 = src1 + src2 .
src4 = relative4 + regdef4 + DLOCAL + regind4 .
dst4 = src4 .
.TE
Permissible in the set construction are all the usual set operators, i.e.
.IP +
set union
@@ -1154,9 +1158,10 @@ This can of course be done with
.DS
kills ALL
.DE
or by ending the stack pattern with the word STACK, which is equivalent,
or by ending the stack pattern with the word STACK,
if the stack pattern does not start with
.I exact .
The latter does not erase the contents of registers.
.PP
It is unfortunate that this part is still present in the table
but it is too much for now to let the
@@ -1248,7 +1253,7 @@ The author of
.I cgg
could not get
.I yacc
to be silent without it.
to accept his syntax without it.
Sorry about this.
.IP 2)
a
@@ -1366,20 +1371,19 @@ A list of examples for the PDP-11 is given here.
Far from being complete it gives examples of most kinds
of instructions.
.DS
.ta 8 16 24 32 40 48 56 64
pat loc yields {const2, $1}
.ta 7.5c
pat loc yields {const2, $1}
pat ldc yields {const2, loww($1)}
{const2, highw($1)}
pat ldc yields {const2, loww($1)} {const2, highw($1)}
.DE
These simple patterns just push one or more tokens onto the fake stack.
.DS
.ta 8 16 24 32 40 48 56 64
.ta 7.5c
pat lof
with REG yields {regind2,%1,$1}
with exact regconst2 yields {regind2,%1.reg,$1+%1.off}
with exact addr_external yields {relative2,$1+%1.off}
with exact addr_local yields {LOCAL, %1.ind + $1,2}
with REG yields {regind2,%1,$1}
with exact regconst2 yields {regind2,%1.reg,$1+%1.off}
with exact addr_external yields {relative2,$1+%1.off}
with exact addr_local yields {LOCAL, %1.ind + $1,2}
.DE
This pattern shows the possibility to do different things
depending on the fake stack contents,
@@ -1389,13 +1393,12 @@ not preceded by
that can always be taken after a coercion,
if necessary.
.DS
.ta 8 16 24 32 40 48 56 64
.ta 7.5c
pat lxl $1>3
uses REG={LOCAL, SL, 2},
REG={const2,$1-1}
uses REG={LOCAL, SL, 2}, REG={const2,$1-1}
gen 1:
move {regind2,%a, SL},%a
sob %b,{label,1b} yields %a
sob %b,{label,1b} yields %a
.DE
This rule shows register allocation with initialisation,
and the use of a temporary label.
@@ -1404,7 +1407,7 @@ of the static link,
that is pushed by the Pascal compiler as the last argument of
a function.
.DS
.ta 8 16 24 32 40 48 56 64
.ta 7.5c
pat stf
with regconst2 xsrc2
kills allexeptcon
@@ -1419,7 +1422,7 @@ part in a store instruction.
The set allexeptcon contains all tokens that can be the destination
of an indirect store.
.DS
.ta 8 16 24 32 40 48 56 64
.ta 7.5c
pat sde
with exact FLTREG
kills posextern
@@ -1445,51 +1448,52 @@ The third rule is taken by default,
resulting in two separate stores,
nothing better exists on the PDP-11.
.DS
.ta 8 16 24 32 40 48 56 64
.ta 7.5c
pat sbi $1==2
with src2 REG
gen sub %1,%2 yields %2
gen sub %1,%2 yields %2
with exact REG src2-REG
gen sub %2,%1
neg %1 yields %1
neg %1 yields %1
.DE
This rule for
.I sbi
has a normal first part,
and a hand optimized special case as it's second part.
and a hand optimized special case as its second part.
.DS
.ta 8 16 24 32 40 48 56 64
.ta 7.5c
pat mli $1==2
with ODDREG src2
gen mul %2,%1 yields %1
gen mul %2,%1 yields %1
with src2 ODDREG
gen mul %1,%2 yields %2
gen mul %1,%2 yields %2
.DE
This shows the general property for rules with commutative
operators,
heuristics or look ahead will have to decide which rule is the best.
.DS
.ta 8 16 24 32 40 48 56 64
.ta 7.5c
pat loc sli $1==1 && $2==2
with REG
gen asl %1 yields %1
gen asl %1 yields %1
.DE
A simple rule involving a longer EM-pattern,
to make use of a specialized instruction available.
.DS
.ta 8 16 24 32 40 48 56 64
.ta 7.5c
pat loc loc cii $1==1 && $2==2
with src1or2
uses reusing %1,REG
gen movb %1,%a yields %a
gen movb %1,%a yields %a
.DE
A somewhat more complicated example of the same.
Note the
.I reusing
clause.
.DS
.ta 8 16 24 32 40 48 56 64
pat loc loc loc cii $1>=0 && $2==2 && $3==4 leaving loc $1 loc 0
.ta 7.5c
pat loc loc loc cii $1>=0 && $2==2 && $3==4
leaving loc $1 loc 0
.DE
Shows a trivial example of EM-replacement.
This is a rule that could be done by the
@@ -1498,40 +1502,40 @@ if word order in longs was defined in EM.
On a `big-endian' machine the two replacement
instructions would be the other way around.
.DS
.ta 8 16 24 32 40 48 56 64
.ta 7.5c
pat and $1==2
with const2 REG
gen bic {const2,~%1.num},%2 yields %2
gen bic {const2,~%1.num},%2 yields %2
with REG const2
gen bic {const2,~%2.num},%1 yields %1
gen bic {const2,~%2.num},%1 yields %1
with REG REG
gen com %1
bic %1,%2 yields %2
bic %1,%2 yields %2
.DE
Shows the way you have to twist the table,
if an
.I and -instruction
is not available on your machine.
.DS
.ta 8 16 24 32 40 48 56 64
.ta 7.5c
pat set $1==2
with REG
uses REG={const2,1}
gen ash %1,%a yields %a
gen ash %1,%a yields %a
.DE
Shows the building of a word-size set.
.DS
.ta 8 16 24 32 40 48 56 64
.ta 7.5c
pat lae aar $2==2 && rom($1,3)==1 && rom($1,1)==0
leaving adi 2
leaving adi 2
pat lae aar $2==2 && rom($1,3)==1 && rom($1,1)!=0
leaving adi 2 adp 0-rom($1,1)
leaving adi 2 adp 0-rom($1,1)
.DE
Two rules showing the use of the rom pseudo function,
and some array optimalisation.
.DS
.ta 8 16 24 32 40 48 56 64
.ta 7.5c
pat bra
with STACK
gen jbr {label, $1}
@@ -1540,7 +1544,7 @@ A simple jump.
The stack pattern guarantees that everything will be stacked
before the jump is taken.
.DS
.ta 8 16 24 32 40 48 56 64
.ta 7.5c
pat cal
with STACK
gen jsr pc,{label, $1}
@@ -1548,9 +1552,9 @@ gen jsr pc,{label, $1}
A simple call.
Same comments as previous rule.
.DS
.ta 8 16 24 32 40 48 56 64
pat lfr $1==2 yields r0
pat lfr $1==4 yields r1 r0
.ta 7.5c
pat lfr $1==2 yields r0
pat lfr $1==4 yields r1 r0
.DE
Shows the return area conventions of the PDP-11 table.
At this point a reminder:
@@ -1560,7 +1564,7 @@ instruction, and some other instructions must leave
the function return area intact.
See the defining document for EM for exact information.
.DS
.ta 8 16 24 32 40 48 56 64
.ta 7.5c
pat ret $1==0
with STACK
gen mov lb,sp
@@ -1574,7 +1578,7 @@ In a table with register variables the
part would just contain
.I return .
.DS
.ta 8 16 24 32 40 48 56 64
.ta 7.5c
pat blm
with REG REG
uses REG={const2,$1/2}
@@ -1592,16 +1596,16 @@ It uses the marriage thesis from Hall,
a thesis from combinatorial mathematics,
to accomplish this.
.DS
.ta 8 16 24 32 40 48 56 64
.ta 7.5c
pat exg $1==2
with src2 src2 yields %1 %2
with src2 src2 yields %1 %2
.DE
This rule shows the exchanging of two elements on the fake stack.
.NH 2
Code rules using procedures
.PP
To start this chapter it must be admitted at once that the
word procedure is chosen here mainly for it's advertising
To start this section it must be admitted at once that the
word procedure is chosen here mainly for its advertising
value.
It more resembles a glorified goto but this of course can
not be admitted in the glossy brochures.
@@ -1660,12 +1664,12 @@ The string `*' can be used as an equivalent for `[1]'.
Just in case this is not clear, here is an example for
a procedure to increment/decrement a register.
.DS
.ta 8 16 24 32 40 48 56 64
.ta 7.5c
incop REG:rw:cc . /* in the INSTRUCTIONS part of course */
proc incdec
with REG
gen incop* %1 yields %1
gen incop* %1 yields %1
.DE
The procedure is called with parameter "inc" or "dec".
.PP
@@ -1676,18 +1680,18 @@ call <identifier> '(' string [ ',' string ] ')'
.DE
which leads to the following large example:
.DS
.ta 8 16 24 32 40 48 56 64
.ta 7.5c
proc bxx example beq
with src2 src2 STACK
gen cmp %2,%1
jxx* {label, $1}
pat blt call bxx("jlt")
pat ble call bxx("jle")
pat beq call bxx("jeq")
pat bne call bxx("jne")
pat bgt call bxx("jgt")
pat bge call bxx("jge")
pat blt call bxx("jlt")
pat ble call bxx("jle")
pat beq call bxx("jeq")
pat bne call bxx("jne")
pat bgt call bxx("jgt")
pat bge call bxx("jge")
.DE
.NH 2
Move definitions
@@ -1852,38 +1856,38 @@ The next part of the table defines the coercions that are possible
on the defined tokens.
Example for the PDP-11:
.DS
.ta 8 16 24 32 40 48 56 64
.ta 7.5c
COERCIONS
from STACK
uses REG
gen mov {autoinc,sp},%a yields %a
gen mov {autoinc,sp},%a yields %a
from STACK
uses DBLREG
gen movf {autoinc,sp},%a yields %a
gen movf {autoinc,sp},%a yields %a
from STACK
uses REGPAIR
gen mov {autoinc,sp},%a.1
mov {autoinc,sp},%a.2 yields %a
mov {autoinc,sp},%a.2 yields %a
.DE
These three coercions just deliver a certain type
of register by popping it from the real stack.
.DS
.ta 8 16 24 32 40 48 56 64
from LOCAL yields {regind2,lb,%1.ind}
.ta 7.5c
from LOCAL yields {regind2,lb,%1.ind}
from DLOCAL yields {regind4,lb,%1.ind}
from DLOCAL yields {regind4,lb,%1.ind}
from REG yields {regconst2, %1, 0}
from REG yields {regconst2, %1, 0}
.DE
These three are zero-cost rewriting rules.
.DS
.ta 8 16 24 32 40 48 56 64
.ta 7.5c
from regconst2 %1.off==1
uses reusing %1,REG=%1.reg
gen inc %a yields %a
gen inc %a yields %a
from regconst2
uses reusing %1,REG=%1.reg
@@ -1892,7 +1896,7 @@ gen add {addr_external, %1.off},%a yields %a
from addr_local
uses REG
gen mov lb,%a
add {const2, %1.ind},%a yields %a
add {const2, %1.ind},%a yields %a
.DE
The last three are three different cases of the coercion
register+constant to register.
@@ -1900,19 +1904,19 @@ Only in the last case is it always necessary to allocate
an extra register,
since arithmetic on the localbase is unthinkable.
.DS
.ta 8 16 24 32 40 48 56 64
.ta 7.5c
from xsrc2
uses reusing %1, REG=%1 yields %a
uses reusing %1, REG=%1 yields %a
from longf4
uses FLTREG=%1 yields %a
uses FLTREG=%1 yields %a
from double8
uses DBLREG=%1 yields %a
uses DBLREG=%1 yields %a
from src1
uses REG={const2,0}
gen bisb %1,%a yields %a
gen bisb %1,%a yields %a
.DE
These examples show the coercion of different
tokens to a register of the needed type.
@@ -1921,14 +1925,14 @@ ensure bytes are not sign-extended.
In EM it is defined that the result of a \fBloi\fP\ 1
instruction is an integer in the range 0..255.
.DS
.ta 8 16 24 32 40 48 56 64
from REGPAIR yields %1.2 %1.1
.ta 7.5c
from REGPAIR yields %1.2 %1.1
from regind4 yields {regind2,%1.reg,2+%1.off}
{regind2,%1.reg,%1.off}
from regind4 yields {regind2,%1.reg,2+%1.off}
{regind2,%1.reg,%1.off}
from relative4 yields {relative2,2+%1.off}
{relative2,%1.off}
from relative4 yields {relative2,2+%1.off}
{relative2,%1.off}
.DE
The last examples are splitting rules.
.PP
@@ -1953,7 +1957,7 @@ and TEM_PSIZE.
The type 'int' is used for things like counters that won't require
more than 16 bits precision.
The type 'word' is used among others to assemble datawords and
is of type 'long' if TEM_WSIZE>2.
is of type 'long'.
The type 'full' is used for addresses and is of type 'long' if
TEM_WSIZE>2 or TEM_PSIZE>2.
.PP
@@ -2082,25 +2086,25 @@ If omitted no initialization is assumed.
.NH 3
Example mach.h for the PDP-11
.DS L
.ta 8 16 24 32 40 48 56
.ta 4c
#define ex_ap(y) fprintf(codefile,"\et.globl %s\en",y)
#define in_ap(y) /* nothing */
#define newplb(x) fprintf(codefile,"%s:\en",x)
#define newilb(x) fprintf(codefile,"%s:\en",x)
#define newdlb(x) fprintf(codefile,"%s:\en",x)
#define dlbdlb(x,y) fprintf(codefile,"%s=%s\en",x,y)
#define dlbdlb(x,y) fprintf(codefile,"%s=%s\en",x,y)
#define newlbss(l,x) fprintf(codefile,"%s:.=.+%d.\en",l,x);
#define cst_fmt "$%d."
#define off_fmt "%d."
#define ilb_fmt "I%02x%x"
#define dlb_fmt "_%d"
#define hol_fmt "hol%d"
#define cst_fmt "$%d."
#define off_fmt "%d."
#define ilb_fmt "I%x_%x"
#define dlb_fmt "_%d"
#define hol_fmt "hol%d"
#define hol_off "%d.+hol%d"
#define hol_off "%ld.+hol%d"
#define con_cst(x) fprintf(codefile,"%d.\en",x)
#define con_cst(x) fprintf(codefile,"%ld.\en",x)
#define con_ilb(x) fprintf(codefile,"%s\en",x)
#define con_dlb(x) fprintf(codefile,"%s\en",x)
@@ -2153,7 +2157,7 @@ mes(w_mesno)
This function is called when a
.B mes
pseudo is seen that is not handled by the machine independent part.
Example below shows all you probably have to know about that.
The example below shows all you probably have to know about that.
.IP -
segname[]
.br
@@ -2212,7 +2216,7 @@ Example mach.c for the PDP-11
As an example of the sort of code expected,
the mach.c for the PDP-11 is presented here.
.DS L
.ta 8 16 24 32 40 48 56 64
.ta 0.5i 1i 1.5i 2i 2.5i 3i 3.5i 4i 4.5i
/*
* machine dependent back end routines for the PDP-11
*/
@@ -2678,7 +2682,7 @@ otherwise the register is marked empty.
.NH 4
DO_INSTR
.PP
This prints an instruction and it's operands.
This prints an instruction and its operands.
Only done on toplevel.
.NH 4
DO_MOVE