fixup commit for tag 'distr2'
This commit is contained in:
118
doc/i80.doc
118
doc/i80.doc
@@ -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.
|
||||
|
||||
366
doc/ncg.doc
366
doc/ncg.doc
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user