|
@@ -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 |
|
|
|
- | | | |
|
|
|
- |_______________| |_______________|
|
|
|
-
|
|
|
-
|
|
|
-.I
|
|
|
- Relation between EM stack, real stack and fake stack.
|
|
|
-.R
|
|
|
-.DE
|
|
|
-.KE
|
|
|
+.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
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ 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 */
|
|
|
-
|
|
|
-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 */
|
|
|
+.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 */
|
|
|
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
|