fixup commit for tag 'distr2'

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

View file

@ -1,35 +0,0 @@
cmp: # compile everything and compare
(cd etc ; make cmp )
(cd util ; make cmp )
(cd lang ; make cmp )
(cd mach ; make cmp )
install: # compile everything to machine code
(cd etc ; make install )
(cd util ; make install )
(cd lang/cem ; make install )
(cd mach ; make install )
(cd lang/pc ; make install )
clean: # remove all non-sources, except boot-files
(cd doc ; make clean )
(cd man ; make clean )
(cd h ; make clean )
(cd etc ; make clean )
(cd util ; make clean )
(cd lang ; make clean )
(cd mach ; make clean )
opr: # print all sources
make pr | opr
pr: # print all sources
@( pr Makefile ; \
(cd doc ; make pr ) ; \
(cd man ; make pr ) ; \
(cd h ; make pr ) ; \
(cd etc ; make pr ) ; \
(cd lang ; make pr ) ; \
(cd util ; make pr ) ; \
(cd mach ; make pr ) \
)

1
bin/em.pascal Executable file
View file

@ -0,0 +1 @@
exec /usr/em/doc/em.doc/int/em /usr/em/doc/em.doc/int/tables ${1-e.out} core

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

View file

@ -4,4 +4,4 @@
# define VERSION 3 /* 16 bits number */
/* The default machine used by ack, acc, apc */
# define ACKM "vax2"
# define ACKM "pdp"

120
h/out.h
View file

@ -1,120 +0,0 @@
/* $Header$ */
/*
* output format for ACK assemblers
*/
#ifndef ushort
#define ushort unsigned short
#endif ushort
struct outhead {
ushort oh_magic; /* magic number */
ushort oh_stamp; /* version stamp */
ushort oh_flags; /* several format flags */
ushort oh_nsect; /* number of outsect structures */
ushort oh_nrelo; /* number of outrelo structures */
ushort oh_nname; /* number of outname structures */
long oh_nemit; /* sum of all os_flen */
long oh_nchar; /* size of string area */
};
#define O_MAGIC 0x0201 /* magic number of output file */
#define O_STAMP 0 /* version stamp */
#ifdef JOHAN
#define HF_BREV 0x0001 /* high order byte lowest address */
#define HF_WREV 0x0002 /* high order word lowest address */
#endif JOHAN
#define HF_LINK 0x0004 /* unresolved references left */
#define HF_8086 0x0008 /* os_base specially encoded */
struct outsect {
long os_base; /* startaddress in machine */
long os_size; /* section size in machine */
long os_foff; /* startaddress in file */
long os_flen; /* section size in file */
long os_lign; /* section alignment */
};
struct outrelo {
char or_type; /* type of reference */
char or_sect; /* referencing section */
ushort or_nami; /* referenced symbol index */
long or_addr; /* referencing address */
};
struct outname {
union {
char *on_ptr; /* symbol name (in core) */
long on_off; /* symbol name (in file) */
} on_u;
#define on_mptr on_u.on_ptr
#define on_foff on_u.on_off
ushort on_type; /* symbol type */
ushort on_desc; /* debug info */
long on_valu; /* symbol value */
};
/*
* relocation type bits
*/
#define RELSZ 0x07 /* relocation length */
#define RELO1 1 /* 1 byte */
#define RELO2 2 /* 2 bytes */
#define RELO4 4 /* 4 bytes */
#define RELPC 0x08 /* pc relative */
#ifndef JOHAN
#define RELBR 0x10 /* High order byte lowest address. */
#define RELWR 0x20 /* High order word lowest address. */
#endif JOHAN
/*
* section type bits and fields
*/
#define S_TYP 0x007F /* undefined, absolute or relative */
#define S_EXT 0x0080 /* external flag */
#define S_ETC 0x7F00 /* for symbolic debug, bypassing 'as' */
/*
* S_TYP field values
*/
#define S_UND 0x0000 /* undefined item */
#define S_ABS 0x0001 /* absolute item */
#define S_MIN 0x0002 /* first user section */
#define S_MAX S_TYP /* last user section */
/*
* S_ETC field values
*/
#define S_SCT 0x0100 /* section names */
#define S_LIN 0x0200 /* hll source line item */
#define S_FIL 0x0300 /* hll source file item */
#define S_MOD 0x0400 /* ass source file item */
#ifndef JOHAN
#define S_COM 0x1000 /* Common name. */
#endif JOHAN
/*
* structure format strings
*/
#define SF_HEAD "22222244"
#define SF_SECT "44444"
#define SF_RELO "1124"
#define SF_NAME "4224"
/*
* structure sizes (bytes in file; add digits in SF_*)
*/
#define SZ_HEAD 20
#define SZ_SECT 20
#define SZ_RELO 8
#define SZ_NAME 12
/*
* file access macros
*/
#define BADMAGIC(x) ((x).oh_magic!=O_MAGIC)
#define OFF_SECT(x) SZ_HEAD
#define OFF_EMIT(x) (OFF_SECT(x) + ((long)(x).oh_nsect * SZ_SECT))
#define OFF_RELO(x) (OFF_EMIT(x) + (x).oh_nemit)
#define OFF_NAME(x) (OFF_RELO(x) + ((long)(x).oh_nrelo * SZ_RELO))
#define OFF_CHAR(x) (OFF_NAME(x) + ((long)(x).oh_nname * SZ_NAME))

View file

@ -1,25 +0,0 @@
/* $Header$ */
#ifndef SYMDEF
# define SYMDEF "__.SYMDEF"
#endif SYMDEF
/*
* Structure of the SYMDEF table of contents for an archive.
* SYMDEF begins with a long giving the number of ranlib
* structures that immediately follow, and then continues with a string
* table consisting of a long giving the number of bytes of
* strings that follow and then the strings themselves.
*/
struct ranlib {
union {
char *ran__ptr; /* symbol name (in core) */
long ran__off; /* symbol name (in file) */
} ran_u;
#define ran_ptr ran_u.ran__ptr
#define ran_off ran_u.ran__off
long ran_pos; /* library member is at this position */
};
#define SZ_RAN 8
#define SF_RAN "44"

View file

@ -1,29 +0,0 @@
# $Revision$
var w=2
var i=2
var p=2
var s=2
var l=4
var f=4
var d=8
var NAME=m6805
var M=6805
var LIB=lib/{M}/tail_
var RT=lib/{M}/head_
var INCLUDES=-I{EM}/include -I/usr/include
name asld
from .s.a
to .out
outfile a.out
program {EM}/lib/{M}/as
mapflag -l* LNAME={EM}/{LIB}*
mapflag -d* ASFL={ASFL?} -d*
args {ASFL?} (.e:{HEAD}={EM}/{RT}em) \
({RTS}:.b.c={EM}/{RT}cc) ({RTS}:.p={EM}/{RT}pc) -o > < \
(.p:{TAIL}={EM}/{LIB}pc) \
(.b:{TAIL}={EM}/{LIB}bc) \
(.b.c:{TAIL}={EM}/{LIB}cc.1s {EM}/{LIB}cc.2g) \
(.b.c.p:{TAIL}={EM}/{LIB}mon) \
(.e:{TAIL}={EM}/{LIB}em)
linker
end

View file

@ -1,40 +0,0 @@
# $Revision$
var w=2
var p=2
var s=2
var l=4
var f=4
var d=8
var NAME=i8086
var M=i86
var LIB=lib/i86/tail_
var LIBIBM=lib/ibm/tail_
var RT=lib/i86/head_
var RTIBM=lib/ibm/head_
var CPP_F=-Dunix
var INCLUDES=-I{EM}/include -I{EM}/lib/ibm/include
name be
from .m.g
to .s
program {EM}/lib/{M}/cg
args <
stdout
need .e
end
name asld
from .s.a
to .out
outfile a.out
program {EM}/lib/{M}/as
mapflag -l* LNAME={EM}/{LIB}*
mapflag -i IFILE={EM}/{RT}i
args {IFILE?} (.e:{HEAD}={EM}/{RTIBM}em) \
({RTS}:.b.c={EM}/{RT}cc) ({RTS}:.p={EM}/{RT}pc) -o > < \
(.p:{TAIL}={EM}/{LIB}pc) \
(.b:{TAIL}={EM}/{LIB}bc) \
(.b.c:{TAIL}={EM}/{LIB}cc.1s {EM}/{LIB}cc.2g) \
(.e:{TAIL}={EM}/{LIBIBM}em) \
(.b.c.p:{TAIL}={EM}/{LIBIBM}mon) \
(.e:{TAIL}={EM}/{LIBIBM}em.vend)
linker
end

View file

@ -1,39 +0,0 @@
# $Revision$
var w=2
var p=4
var s=2
var l=4
var f=4
var d=8
var NAME=m68k2
var M=m68k2
var LIBDIR=/lib/{M}
var LIB=lib/{M}/tail_
var RT=lib/{M}/head_
var INCLUDES=-I{EM}/include -I/usr/include
name be
from .m.g
to .s
program {EM}/lib/{M}/cg
args <
stdout
need .e
end
name asld
from .s.a
to .out
outfile a.out
program {EM}/lib/{M}/as
mapflag -l* LNAME={EM}/{LIB}*
args (.e:{HEAD}={EM}/{RT}em) \
({RTS}:.b.c={EM}/{RT}cc) ({RTS}:.p={EM}/{RT}pc) -o > < \
(.p.c.b:{TAIL}={EM}/{LIBDIR}/sys1.s) (.p:{TAIL}={EM}/{LIBDIR}/sys2.s) \
(.c:{TAIL}={EM}/{LIBDIR}/write.s) \
(.p:{TAIL}={EM}/{LIB}pc) \
(.b:{TAIL}={EM}/{LIB}bc) \
(.b.c:{TAIL}={EM}/{LIB}cc.1s {EM}/{LIB}cc.2g) \
(.b.c:{TAIL}={EM}/{LIB}mon {EM}/{LIB}fake) \
(.e:{TAIL}={EM}/{LIB}em.rt {EM}/{LIB}em.vend)
prep cond
linker
end

View file

@ -1,30 +0,0 @@
# $Revision$
var w=1
var p=2
var s=1
var l=2
var f=4
var d=8
var NAME=nascom
var M=z80a
var LIB=lib/{M}/tail_
var RT=lib/{M}/head_
var INCLUDES=-I{EM}/include -I/usr/include
name be
from .m.g
to .s
program {EM}/lib/{M}/be
args <
stdout
need .e
end
name asld
from .s.a
to .out
outfile a.out
program {EM}/lib/z80/as
mapflag -l* LNAME={EM}/{LIB}*
args (.e:{HEAD}={EM}/{RT}em) ({RTS}:.b.c={EM}/{RT}cc) -o > \
(.e:{TAIL}={EM}/{LIB}em.1 {EM}/{LIB}em.2)
linker
end

View file

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

View file

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

View file

@ -1,53 +0,0 @@
# $Header$
EM = ../../..
h = $(EM)/h
CDIR = $(EM)/mach/proto/nas
CPP = $(EM)/lib/cpp
DEF =
FFLAG =
CFLAGS = $(FFLAG) -O -I$h $(DEF)
YFLAGS = -d
LDFLAGS = $(FFLAG) -i
CSRC = $(CDIR)/comm3.c $(CDIR)/comm4.c $(CDIR)/comm5.c \
$(CDIR)/comm6.c $(CDIR)/comm7.c $(CDIR)/comm8.c
COBJ = $(CDIR)/comm3.o $(CDIR)/comm4.o $(CDIR)/comm5.o \
$(CDIR)/comm6.o $(CDIR)/comm7.o $(CDIR)/comm8.o
MACH = mach0.c mach1.c mach2.c mach3.c mach4.c mach5.c
COMM = $(CDIR)/comm0.h $(CDIR)/comm1.h $(CDIR)/comm2.y $(CSRC)
all: as
install:all
../../install as
cmp:
-../../compare as
clean:
rm -f *.o as as.[cy] y.tab.h
pr: $(MACH)
@pr -n $(MACH)
opr:
make pr | opr
as: $(COBJ) as.o
$(CC) $(LDFLAGS) $(COBJ) as.o -o as
as.y: $(CDIR)/comm2.y
$(CPP) -P -I$h $(DEF) $(CDIR)/comm2.y >as.y
@echo "expect 1 shift/reduce conflict"
lint: $(CSRC) as.c
lint $(CSRC) as.c
y.tab.h: as.c
$(COBJ): y.tab.h
$(COBJ) as.y: $(CDIR)/comm0.h mach0.c
$(COBJ) as.y: $(CDIR)/comm1.h mach1.c
as.y: mach2.c
comm3.o: mach3.c
as.y: mach4.c
comm8.o: mach5.c

View file

@ -1,53 +0,0 @@
# $Header$
EM = ../../..
h = $(EM)/h
CDIR = $(EM)/mach/proto/nas
CPP = $(EM)/lib/cpp
DEF =
FFLAG =
CFLAGS = $(FFLAG) -O -I$h $(DEF)
YFLAGS = -d
LDFLAGS = $(FFLAG) -i
CSRC = $(CDIR)/comm3.c $(CDIR)/comm4.c $(CDIR)/comm5.c \
$(CDIR)/comm6.c $(CDIR)/comm7.c $(CDIR)/comm8.c
COBJ = $(CDIR)/comm3.o $(CDIR)/comm4.o $(CDIR)/comm5.o \
$(CDIR)/comm6.o $(CDIR)/comm7.o $(CDIR)/comm8.o
MACH = mach0.c mach1.c mach2.c mach3.c mach4.c mach5.c
COMM = $(CDIR)/comm0.h $(CDIR)/comm1.h $(CDIR)/comm2.y $(CSRC)
all: as
install:all
../../install as
cmp:
-../../compare as
clean:
rm -f *.o as as.[cy] y.tab.h
pr: $(MACH)
@pr -n $(MACH)
opr:
make pr | opr
as: $(COBJ) as.o
$(CC) $(LDFLAGS) $(COBJ) as.o -o as
as.y: $(CDIR)/comm2.y
$(CPP) -P -I$h $(DEF) $(CDIR)/comm2.y >as.y
@echo "expect 1 shift/reduce conflict"
lint: $(CSRC) as.c
lint $(CSRC) as.c
y.tab.h: as.c
$(COBJ): y.tab.h
$(COBJ) as.y: $(CDIR)/comm0.h mach0.c
$(COBJ) as.y: $(CDIR)/comm1.h mach1.c
as.y: mach2.c
comm3.o: mach3.c
as.y: mach4.c
comm8.o: mach5.c

View file

@ -1,53 +0,0 @@
# $Header$
EM = ../../..
h = $(EM)/h
CDIR = $(EM)/mach/proto/nas
CPP = $(EM)/lib/cpp
DEF =
FFLAG =
CFLAGS = $(FFLAG) -O -I$h $(DEF)
YFLAGS = -d
LDFLAGS = $(FFLAG) -i
CSRC = $(CDIR)/comm3.c $(CDIR)/comm4.c $(CDIR)/comm5.c \
$(CDIR)/comm6.c $(CDIR)/comm7.c $(CDIR)/comm8.c
COBJ = $(CDIR)/comm3.o $(CDIR)/comm4.o $(CDIR)/comm5.o \
$(CDIR)/comm6.o $(CDIR)/comm7.o $(CDIR)/comm8.o
MACH = mach0.c mach1.c mach2.c mach3.c mach4.c mach5.c
COMM = $(CDIR)/comm0.h $(CDIR)/comm1.h $(CDIR)/comm2.y $(CSRC)
all: as
install:all
../../install as
cmp:
-../../compare as
clean:
rm -f *.o as as.[cy] y.tab.h
pr: $(MACH)
@pr -n $(MACH)
opr:
make pr | opr
as: $(COBJ) as.o
$(CC) $(LDFLAGS) $(COBJ) as.o -o as
as.y: $(CDIR)/comm2.y
$(CPP) -P -I$h $(DEF) $(CDIR)/comm2.y >as.y
@echo "expect 1 shift/reduce conflict"
lint: $(CSRC) as.c
lint $(CSRC) as.c
y.tab.h: as.c
$(COBJ): y.tab.h
$(COBJ) as.y: $(CDIR)/comm0.h mach0.c
$(COBJ) as.y: $(CDIR)/comm1.h mach1.c
as.y: mach2.c
comm3.o: mach3.c
as.y: mach4.c
comm8.o: mach5.c

View file

@ -1,53 +0,0 @@
# $Header$
EM = ../../..
h = $(EM)/h
CDIR = $(EM)/mach/proto/nas
CPP = $(EM)/lib/cpp
DEF =
FFLAG =
CFLAGS = $(FFLAG) -O -I$h $(DEF)
YFLAGS = -d
LDFLAGS = $(FFLAG) -i
CSRC = $(CDIR)/comm3.c $(CDIR)/comm4.c $(CDIR)/comm5.c \
$(CDIR)/comm6.c $(CDIR)/comm7.c $(CDIR)/comm8.c
COBJ = $(CDIR)/comm3.o $(CDIR)/comm4.o $(CDIR)/comm5.o \
$(CDIR)/comm6.o $(CDIR)/comm7.o $(CDIR)/comm8.o
MACH = mach0.c mach1.c mach2.c mach3.c mach4.c mach5.c
COMM = $(CDIR)/comm0.h $(CDIR)/comm1.h $(CDIR)/comm2.y $(CSRC)
all: as
install:all
../../install as
cmp:
-../../compare as
clean:
rm -f *.o as as.[cy] y.tab.h
pr: $(MACH)
@pr -n $(MACH)
opr:
make pr | opr
as: $(COBJ) as.o
$(CC) $(LDFLAGS) $(COBJ) as.o -o as
as.y: $(CDIR)/comm2.y
$(CPP) -P -I$h $(DEF) $(CDIR)/comm2.y >as.y
@echo "expect 1 shift/reduce conflict"
lint: $(CSRC) as.c
lint $(CSRC) as.c
y.tab.h: as.c
$(COBJ): y.tab.h
$(COBJ) as.y: $(CDIR)/comm0.h mach0.c
$(COBJ) as.y: $(CDIR)/comm1.h mach1.c
as.y: mach2.c
comm3.o: mach3.c
as.y: mach4.c
comm8.o: mach5.c

View file

@ -1,53 +0,0 @@
# $Header$
EM = ../../..
h = $(EM)/h
CDIR = $(EM)/mach/proto/nas
CPP = $(EM)/lib/cpp
DEF =
FFLAG =
CFLAGS = $(FFLAG) -O -I$h $(DEF)
YFLAGS = -d
LDFLAGS = $(FFLAG) -i
CSRC = $(CDIR)/comm3.c $(CDIR)/comm4.c $(CDIR)/comm5.c \
$(CDIR)/comm6.c $(CDIR)/comm7.c $(CDIR)/comm8.c
COBJ = $(CDIR)/comm3.o $(CDIR)/comm4.o $(CDIR)/comm5.o \
$(CDIR)/comm6.o $(CDIR)/comm7.o $(CDIR)/comm8.o
MACH = mach0.c mach1.c mach2.c mach3.c mach4.c mach5.c
COMM = $(CDIR)/comm0.h $(CDIR)/comm1.h $(CDIR)/comm2.y $(CSRC)
all: as
install:all
../../install as
cmp:
-../../compare as
clean:
rm -f *.o as as.[cy] y.tab.h
pr: $(MACH)
@pr -n $(MACH)
opr:
make pr | opr
as: $(COBJ) as.o
$(CC) $(LDFLAGS) $(COBJ) as.o -o as
as.y: $(CDIR)/comm2.y
$(CPP) -P -I$h $(DEF) $(CDIR)/comm2.y >as.y
@echo "expect 1 shift/reduce conflict"
lint: $(CSRC) as.c
lint $(CSRC) as.c
y.tab.h: as.c
$(COBJ): y.tab.h
$(COBJ) as.y: $(CDIR)/comm0.h mach0.c
$(COBJ) as.y: $(CDIR)/comm1.h mach1.c
as.y: mach2.c
comm3.o: mach3.c
as.y: mach4.c
comm8.o: mach5.c

View file

@ -1,53 +0,0 @@
# $Header$
EM = ../../..
h = $(EM)/h
CDIR = $(EM)/mach/proto/nas
CPP = $(EM)/lib/cpp
DEF =
FFLAG =
CFLAGS = $(FFLAG) -O -I$h $(DEF)
YFLAGS = -d
LDFLAGS = $(FFLAG) -i
CSRC = $(CDIR)/comm3.c $(CDIR)/comm4.c $(CDIR)/comm5.c \
$(CDIR)/comm6.c $(CDIR)/comm7.c $(CDIR)/comm8.c
COBJ = $(CDIR)/comm3.o $(CDIR)/comm4.o $(CDIR)/comm5.o \
$(CDIR)/comm6.o $(CDIR)/comm7.o $(CDIR)/comm8.o
MACH = mach0.c mach1.c mach2.c mach3.c mach4.c mach5.c
COMM = $(CDIR)/comm0.h $(CDIR)/comm1.h $(CDIR)/comm2.y $(CSRC)
all: as
install:all
../../install as
cmp:
-../../compare as
clean:
rm -f *.o as as.[cy] y.tab.h
pr: $(MACH)
@pr -n $(MACH)
opr:
make pr | opr
as: $(COBJ) as.o
$(CC) $(LDFLAGS) $(COBJ) as.o -o as
as.y: $(CDIR)/comm2.y
$(CPP) -P -I$h $(DEF) $(CDIR)/comm2.y >as.y
@echo "expect 1 shift/reduce conflict"
lint: $(CSRC) as.c
lint $(CSRC) as.c
y.tab.h: as.c
$(COBJ): y.tab.h
$(COBJ) as.y: $(CDIR)/comm0.h mach0.c
$(COBJ) as.y: $(CDIR)/comm1.h mach1.c
as.y: mach2.c
comm3.o: mach3.c
as.y: mach4.c
comm8.o: mach5.c

View file

@ -1,53 +0,0 @@
# $Header$
EM = ../../..
h = $(EM)/h
CDIR = $(EM)/mach/proto/nas
CPP = $(EM)/lib/cpp
DEF =
FFLAG =
CFLAGS = $(FFLAG) -O -I$h $(DEF)
YFLAGS = -d
LDFLAGS = $(FFLAG) -i
CSRC = $(CDIR)/comm3.c $(CDIR)/comm4.c $(CDIR)/comm5.c \
$(CDIR)/comm6.c $(CDIR)/comm7.c $(CDIR)/comm8.c
COBJ = $(CDIR)/comm3.o $(CDIR)/comm4.o $(CDIR)/comm5.o \
$(CDIR)/comm6.o $(CDIR)/comm7.o $(CDIR)/comm8.o
MACH = mach0.c mach1.c mach2.c mach3.c mach4.c mach5.c
COMM = $(CDIR)/comm0.h $(CDIR)/comm1.h $(CDIR)/comm2.y $(CSRC)
all: as
install:all
../../install as
cmp:
-../../compare as
clean:
rm -f *.o as as.[cy] y.tab.h
pr: $(MACH)
@pr -n $(MACH)
opr:
make pr | opr
as: $(COBJ) as.o
$(CC) $(LDFLAGS) $(COBJ) as.o -o as
as.y: $(CDIR)/comm2.y
$(CPP) -P -I$h $(DEF) $(CDIR)/comm2.y >as.y
@echo "expect 1 shift/reduce conflict"
lint: $(CSRC) as.c
lint $(CSRC) as.c
y.tab.h: as.c
$(COBJ): y.tab.h
$(COBJ) as.y: $(CDIR)/comm0.h mach0.c
$(COBJ) as.y: $(CDIR)/comm1.h mach1.c
as.y: mach2.c
comm3.o: mach3.c
as.y: mach4.c
comm8.o: mach5.c

View file

@ -12,7 +12,6 @@ csb.s
dup.s
dvi2.s
exg.s
flp.s
inn.s
ior.s
lar2.s

View file

@ -1,33 +0,0 @@
.define .adf4,.adf8,.sbf4,.sbf8,.mlf4,.mlf8,.dvf4,.dvf8
.define .ngf4,.ngf8,.fif4,.fif8,.fef4,.fef8
.define .zrf4,.zrf8
.define .cfi,.cif,.cuf,.cff,.cfu
.define .cmf4,.cmf8
! Floating point is not implemented
.adf4:
.adf8:
.sbf4:
.sbf8:
.mlf4:
.mlf8:
.dvf4:
.dvf8:
.ngf4:
.ngf8:
.fif4:
.fif8:
.fef4:
.fef8:
.zrf4:
.zrf8:
.cfi:
.cif:
.cuf:
.cff:
.cfu:
.cmf4:
.cmf8:
call eunimpl
ret

View file

@ -818,61 +818,15 @@ gen Call {label,".sri4"}
/* Group 5: Floating point arithmetic */
/********************************************/
pat adf $1==4
with STACK
gen Call {label,".adf4"}
/* Floating points are not supported */
pat adf $1==8
with STACK
gen Call {label,".adf8"}
pat sbf $1==4
with STACK
gen Call {label,".sbf4"}
pat sbf $1==8
with STACK
gen Call {label,".sbf8"}
pat mlf $1==4
with STACK
gen Call {label,".mlf4"}
pat mlf $1==8
with STACK
gen Call {label,".mlf8"}
pat dvf $1==4
with STACK
gen Call {label,".dvf4"}
pat dvf $1==8
with STACK
gen Call {label,".dvf8"}
pat ngf $1==4
with STACK
gen Call {label,".ngf4"}
pat ngf $1==8
with STACK
gen Call {label,".ngf8"}
pat fif $1==4
with STACK
gen Call {label,".fif4"}
pat fif $1==8
with STACK
gen Call {label,".fif8"}
pat fef $1==4
with STACK
gen Call {label,".fef4"}
pat fef $1==8
with STACK
gen Call {label,".fef8"}
pat adf gen Call {label,"eunimpl"}
pat sbf gen Call {label,"eunimpl"}
pat mlf gen Call {label,"eunimpl"}
pat dvf gen Call {label,"eunimpl"}
pat ngf gen Call {label,"eunimpl"}
pat fif gen Call {label,"eunimpl"}
pat fef gen Call {label,"eunimpl"}
/********************************************/
/* Group 6: Pointer arithmetic */
@ -965,13 +919,7 @@ pat zre
uses hlreg={const2,0}
gen shld {label,$1}
pat zrf $1==4
with STACK
gen Call {label,".zrf4"}
pat zrf $1==8
with STACK
gen Call {label,".zrf8"}
pat zrf gen Call {label,"eunimpl"}
pat zer $1==2 yields {const2,0}
@ -1087,26 +1035,12 @@ with STACK
uses areg={const1,0}
gen Call {label,".cii"}
pat cfi
with STACK
gen Call {label,".cfi"}
pat cif
with STACK
gen Call {label,".cif"}
pat cuf
with STACK
gen Call {label,".cuf"}
pat cff
with STACK
gen Call {label,".cff"}
pat cfu
with STACK
gen Call {label,".cfu"}
pat cfi gen Call {label,"eunimpl"}
pat cif gen Call {label,"eunimpl"}
pat cuf gen Call {label,"eunimpl"}
pat cff gen Call {label,"eunimpl"}
pat cfu gen Call {label,"eunimpl"}
/*****************************************/
/* Group 9: Logical instructions */
/*****************************************/
@ -1392,13 +1326,7 @@ with STACK
uses areg={const1,1}
gen Call {label,".cmi4"} yields de
pat cmf $1==4
with STACK
gen Call {label,".cmf4"}
pat cmf $1==8
with STACK
gen Call {label,".cmf8"}
pat cmf gen Call {label,"eunimpl"}
pat cmu $1==2
with hl_or_de hl_or_de

View file

@ -1,53 +0,0 @@
# $Header$
EM = ../../..
h = $(EM)/h
CDIR = $(EM)/mach/proto/nas
CPP = $(EM)/lib/cpp
DEF =
FFLAG =
CFLAGS = $(FFLAG) -O -I$h $(DEF)
YFLAGS = -d
LDFLAGS = $(FFLAG) -i
CSRC = $(CDIR)/comm3.c $(CDIR)/comm4.c $(CDIR)/comm5.c \
$(CDIR)/comm6.c $(CDIR)/comm7.c $(CDIR)/comm8.c
COBJ = $(CDIR)/comm3.o $(CDIR)/comm4.o $(CDIR)/comm5.o \
$(CDIR)/comm6.o $(CDIR)/comm7.o $(CDIR)/comm8.o
MACH = mach0.c mach1.c mach2.c mach3.c mach4.c mach5.c
COMM = $(CDIR)/comm0.h $(CDIR)/comm1.h $(CDIR)/comm2.y $(CSRC)
all: as
install:all
../../install as
cmp:
-../../compare as
clean:
rm -f *.o as as.[cy] y.tab.h
pr: $(MACH)
@pr -n $(MACH)
opr:
make pr | opr
as: $(COBJ) as.o
$(CC) $(LDFLAGS) $(COBJ) as.o -o as
as.y: $(CDIR)/comm2.y
$(CPP) -P -I$h $(DEF) $(CDIR)/comm2.y >as.y
@echo "expect 1 shift/reduce conflict"
lint: $(CSRC) as.c
lint $(CSRC) as.c
y.tab.h: as.c
$(COBJ): y.tab.h
$(COBJ) as.y: $(CDIR)/comm0.h mach0.c
$(COBJ) as.y: $(CDIR)/comm1.h mach1.c
as.y: mach2.c
comm3.o: mach3.c
as.y: mach4.c
comm8.o: mach5.c

View file

@ -1,53 +0,0 @@
# $Header$
EM = ../../..
h = $(EM)/h
CDIR = $(EM)/mach/proto/nas
CPP = $(EM)/lib/cpp
DEF =
FFLAG =
CFLAGS = $(FFLAG) -O -I$h $(DEF)
YFLAGS = -d
LDFLAGS = $(FFLAG) -i
CSRC = $(CDIR)/comm3.c $(CDIR)/comm4.c $(CDIR)/comm5.c \
$(CDIR)/comm6.c $(CDIR)/comm7.c $(CDIR)/comm8.c
COBJ = $(CDIR)/comm3.o $(CDIR)/comm4.o $(CDIR)/comm5.o \
$(CDIR)/comm6.o $(CDIR)/comm7.o $(CDIR)/comm8.o
MACH = mach0.c mach1.c mach2.c mach3.c mach4.c mach5.c
COMM = $(CDIR)/comm0.h $(CDIR)/comm1.h $(CDIR)/comm2.y $(CSRC)
all: as
install:all
../../install as
cmp:
-../../compare as
clean:
rm -f *.o as as.[cy] y.tab.h
pr: $(MACH)
@pr -n $(MACH)
opr:
make pr | opr
as: $(COBJ) as.o
$(CC) $(LDFLAGS) $(COBJ) as.o -o as
as.y: $(CDIR)/comm2.y
$(CPP) -P -I$h $(DEF) $(CDIR)/comm2.y >as.y
@echo "expect 1 shift/reduce conflict"
lint: $(CSRC) as.c
lint $(CSRC) as.c
y.tab.h: as.c
$(COBJ): y.tab.h
$(COBJ) as.y: $(CDIR)/comm0.h mach0.c
$(COBJ) as.y: $(CDIR)/comm1.h mach1.c
as.y: mach2.c
comm3.o: mach3.c
as.y: mach4.c
comm8.o: mach5.c

View file

@ -1,53 +0,0 @@
# $Header$
EM = ../../..
h = $(EM)/h
CDIR = $(EM)/mach/proto/nas
CPP = $(EM)/lib/cpp
DEF =
FFLAG =
CFLAGS = $(FFLAG) -O -I$h $(DEF)
YFLAGS = -d
LDFLAGS = $(FFLAG) -i
CSRC = $(CDIR)/comm3.c $(CDIR)/comm4.c $(CDIR)/comm5.c \
$(CDIR)/comm6.c $(CDIR)/comm7.c $(CDIR)/comm8.c
COBJ = $(CDIR)/comm3.o $(CDIR)/comm4.o $(CDIR)/comm5.o \
$(CDIR)/comm6.o $(CDIR)/comm7.o $(CDIR)/comm8.o
MACH = mach0.c mach1.c mach2.c mach3.c mach4.c mach5.c
COMM = $(CDIR)/comm0.h $(CDIR)/comm1.h $(CDIR)/comm2.y $(CSRC)
all: as
install:all
../../install as
cmp:
-../../compare as
clean:
rm -f *.o as as.[cy] y.tab.h
pr: $(MACH)
@pr -n $(MACH)
opr:
make pr | opr
as: $(COBJ) as.o
$(CC) $(LDFLAGS) $(COBJ) as.o -o as
as.y: $(CDIR)/comm2.y
$(CPP) -P -I$h $(DEF) $(CDIR)/comm2.y >as.y
@echo "expect 1 shift/reduce conflict"
lint: $(CSRC) as.c
lint $(CSRC) as.c
y.tab.h: as.c
$(COBJ): y.tab.h
$(COBJ) as.y: $(CDIR)/comm0.h mach0.c
$(COBJ) as.y: $(CDIR)/comm1.h mach1.c
as.y: mach2.c
comm3.o: mach3.c
as.y: mach4.c
comm8.o: mach5.c

View file

@ -23,19 +23,6 @@ static char rcsid[] = "$Header$";
* machine dependent back end routines for the Motorola 68000
*/
#define IEEEFLOAT
#ifdef IEEEFLOAT
#include "FP.h"
#include "trp.c"
#include "fcompact.c"
#include "dbl_extract.c"
#ifdef PRT_EXP_DEBUG
#include "prt_extend.c"
#endif
#endif IEEEFLOAT
con_part(sz,w) register sz; word w; {
while (part_size % sz)
@ -61,58 +48,24 @@ con_mult(sz) word sz; {
fprintf(codefile,".long %s\n",str);
}
#ifdef IEEEFLOAT
dbl_adjust(fl)
my_dbl *fl;
{
EXTEND buf;
con_float() {
/* special routine to strip SGL_BIAS */
dbl_extract(fl,&buf);
/* standard routine to add DBL_BIAS */
fcompact(&buf,fl,sizeof(double));
}
#endif IEEEFLOAT
con_float()
{
register word sz;
register long *l;
#ifdef IEEEFLOAT
register my_dbl *md;
#endif IEEEFLOAT
double d;
char mesg[128];
sz = argval;
if (sz!= 4 && sz!= 8) {
sprintf(mesg,"con_float(): bad fcon size %d %D\nstr: %s\n\0",
sz,sz,str);
fatal(mesg);
}
d = atof(str);
l = (long *) &d;
#ifdef IEEEFLOAT
if (sz == 8) {
/* ATOF() RETURNS THE PROPER FORMAT FOR A FLOAT */
/* BUT NOT FOR A DOUBLE. CORRECT THE FORMAT. */
md = (my_dbl *) &d;
dbl_adjust(md);
}
#endif IEEEFLOAT
while ( sz ) {
fprintf(codefile,"\t.word 0x%x,0x%x !float test %s\n",
(int)(*l)&0xFFFF,(int)(*l>>16)&0xFFFF,str);
sz -=4 ;
l++;
static int been_here;
if (argval != 4 && argval != 8)
fatal("bad fcon size");
fprintf(codefile,".long\t");
if (argval == 8)
fprintf(codefile,"F_DUM,");
fprintf(codefile,"F_DUM\n");
if ( !been_here++)
{
fprintf(stderr,"Warning : dummy float-constant(s)\n");
}
}
#ifdef REGVARS
regscore(off,size,typ,score,totyp)
long off;
{
@ -140,6 +93,8 @@ regscore(off,size,typ,score,totyp)
score -= 1; /* take save/restore into account */
return score;
}
struct regsav_t {
char *rs_reg; /* e.g. "a3" or "d5" */
long rs_off; /* offset of variable */
@ -148,10 +103,20 @@ struct regsav_t {
int regnr;
int nr_a_regs,nr_d_regs;
int TEM_BSIZE;
static long nlocals;
prolog(n)
{ nlocals = n; }
i_regsave()
{
regnr = 0;
nr_a_regs = 0;
nr_d_regs = 0;
TEM_BSIZE = 0;
}
#define MOVEM_LIMIT 2
@ -160,9 +125,11 @@ i_regsave()
* we simply use several move.l's.
*/
save()
{
register struct regsav_t *p;
int i;
if (regnr > MOVEM_LIMIT) {
fprintf(codefile,"movem.l ");
@ -173,16 +140,37 @@ save()
}
fprintf(codefile,",-(sp)\n");
} else {
for (p = regsav; p < &regsav[regnr]; p++) {
fprintf(codefile,"move.l %s,-(sp)\n",p->rs_reg);
/* Note that the order in which the registers are saved
* is important; it is used by gto.s.
*/
for (i = 0; i < nr_a_regs; i++) {
fprintf(codefile,"move.l a%d,-(sp)\n",5-i);
}
for (i = 0; i < nr_d_regs; i++) {
fprintf(codefile,"move.l d%d,-(sp)\n",7-i);
}
}
/* Push a mask that indicates which registers were saved */
assert(nr_d_regs < 8 && nr_a_regs < 8);
if (nr_d_regs == 0 && nr_a_regs == 0) {
fprintf(codefile,"clr.w -(sp)\n");
} else {
fprintf(codefile,"move.w #%d,-(sp)\n",
nr_d_regs + (nr_a_regs<<3));
}
/* Compute AB - LB */
TEM_BSIZE = 4 * (nr_d_regs + nr_a_regs) + 10;
/* allocate space for local variables */
fprintf(codefile,"tst.b -%D(sp)\nlink\ta6,#-%D\n",nlocals+40,nlocals);
/* initialise register-parameters */
for (p = regsav; p < &regsav[regnr]; p++) {
if (p->rs_off >= 0) {
fprintf(codefile,"move.%c %ld(a6),%s\n",
(p->rs_size == 4 ? 'l' : 'w'),
p->rs_off,
p->rs_off + TEM_BSIZE,
p->rs_reg);
}
}
@ -191,7 +179,10 @@ save()
restr()
{
register struct regsav_t *p;
int i;
fprintf(codefile,"unlk a6\n");
fprintf(codefile,"add.l #2,sp\n"); /* pop mask */
if (regnr > MOVEM_LIMIT) {
fprintf(codefile,"movem.l (sp)+,");
for (p = regsav; ;) {
@ -201,11 +192,13 @@ restr()
}
putc('\n',codefile);
} else {
for (p = &regsav[regnr-1]; p >= regsav; p--) {
fprintf(codefile,"move.l (sp)+,%s\n",p->rs_reg);
for (i = nr_d_regs - 1; i >= 0; i--) {
fprintf(codefile,"move.l (sp)+,d%d\n",7-i);
}
for (i = nr_a_regs - 1; i >= 0; i--) {
fprintf(codefile,"move.l (sp)+,a%d\n",5-i);
}
}
fprintf(codefile,"unlk a6\n");
fprintf(codefile,"rts\n");
}
@ -221,6 +214,12 @@ regsave(str,off,size)
{
assert (regnr < 9);
regsav[regnr].rs_reg = str;
if (str[0] == 'a') {
nr_a_regs++;
} else {
assert(str[0] == 'd');
nr_d_regs++;
}
regsav[regnr].rs_off = off;
regsav[regnr++].rs_size = size;
fprintf(codefile, "!Local %ld into %s\n",off,str);
@ -233,11 +232,15 @@ regreturn()
#endif
#ifndef REGVARS
prolog(nlocals) full nlocals; {
fprintf(codefile,"tst.b -%D(sp)\nlink\ta6,#-%D\n",nlocals+40,nlocals);
}
#endif
mes(type) word type ; {

View file

@ -1,4 +1,3 @@
"$Header$"
/*
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
*
@ -33,7 +32,6 @@
EM_WSIZE = 2
EM_PSIZE = 4
EM_BSIZE = 8
@ -114,8 +112,6 @@ ABS = {STRING addr;} 2 cost=(3,5) "%[addr]"
ABS1 = {STRING addr;} 2 cost=(3,5) "%[addr]"
IMMEDIATE = {INT cc;} 2 cost=(1,2) "#%[cc]"
LOCAL_ADDR = {INT off;} 4 /* not really addressable */
REGOFF_ADDR = {REGISTER reg;
INT off;} 4 /* not really addressable */
EXTERNAL_ADDR = {STRING off;} 4 cost=(4,4) "#%[off]"
INDEX_ADDR = {REGISTER reg,ireg;
INT di;} 4
@ -156,15 +152,13 @@ ALT_MEM = ALTERABLE * MEMORY
DATASCR = DATAREG * SCRATCH
ADDSCR = ADDREG * SCRATCH
MEM_ALL = ALL - DATAREG - DATAREG4 - ADDREG - IMMEDIATE - IMMEDIATE4
- LOCAL_ADDR -REGOFF_ADDR - EXTERNAL_ADDR - DOUBLE - DOUBLEZERO
- LOCAL_ADDR - EXTERNAL_ADDR - DOUBLE - DOUBLEZERO
ALL_ACCESSIBLE = IADDREG + IADDREG4 + IADDREG1 + INDEXED + INDEXED4
ANY1 = DISPL1 + ABS1 + IADDREG1
DATA_ALT1 = ANY1
DATA_ALT_1OR2 = DATA_ALT + DATA_ALT1
DATA_ALT_1OR2 = DATA_ALT + ANY1
REG4 = DATAREG4 + ADDREG
DATA4 = DATAREG4 + IADDREG4 + DISPL4 + INDEXED4 +
ABS4 + IMMEDIATE4 + DOUBLE
MEMORY4 = DATA4 - DATAREG4
@ -210,18 +204,13 @@ lil | | allocate(ADDREG = {DISPL4,LB,$1})| {IADDREG,%[a]} | |
lof | ADDREG | | {DISPL,%[1],$1} | |
... | nocoercions: EXTERNAL_ADDR | | {ABS,%[1.off]+"+"+tostring($1)} | |
... | nocoercions: LOCAL_ADDR | | {DISPL,LB,%[1.off]+$1} | |
... | nocoercions: REGOFF_ADDR | | {DISPL,%[1.reg],%[1.off]+$1} | |
ldf | ADDREG | | {DISPL4,%[1],$1} | |
... | nocoercions: EXTERNAL_ADDR | | {ABS4,%[1.off]+"+"+tostring($1)} | |
... | nocoercions: LOCAL_ADDR | | {DISPL4,LB,%[1.off]+$1} | |
... | nocoercions: REGOFF_ADDR | | {DISPL4,%[1.reg],%[1.off]+$1} | |
lal | | | {LOCAL_ADDR,$1} | |
| LOCAL_ADDR | allocate(ADDREG)
"lea %[1.off](a6),%[a]"
samecc | %[a] | |
| REGOFF_ADDR | allocate(ADDREG)
"lea %[1.off](%[1.reg]),%[a]"
samecc | %[a] | |
lae | | | {EXTERNAL_ADDR,$1} | |
| EXTERNAL_ADDR | allocate(ADDREG)
"lea %[1.off],%[a]"
@ -230,33 +219,17 @@ lae | | | {EXTERNAL_ADDR,$1} | |
/* For the lxl and lxa instructions we assume that the static link
* (i.e. a pointer to the LB of the lexically enclosing subprogram)
* is passed as zero-th actual parameter. The distance (in bytes)
* between LB and the zero-th parameter is the constant EM_BSIZE
* between LB and the zero-th parameter is the constant 8
*/
lxl $1 == 0 | | | LB | |
lxl $1 == 1 | | | {DISPL4,LB,8} | |
lxl $1>1 | |
allocate(ADDREG,DATAREG = {IMMEDIATE,$1-1})
"move.l a6,%[a]"
"1:"
"move.l 8(%[a]),%[a]"
"dbf %[b],1b"
erase(%[b]) | %[a] | |
lxa $1 == 0 | |
allocate(ADDREG = {IMMEDIATE4,8})
"add.l a6,%[a]"
erase(%[a]) | %[a] | |
lxa $1 > 0 | |
allocate(ADDREG, DATAREG = {IMMEDIATE,$1-1})
"move.l a6,%[a]"
"1:"
"move.l 8(%[a]),%[a]"
"dbf %[b],1b"
"add.l #8,%[a]"
erase(%[b]) | %[a] | |
lxl $1>=1 | STACK |
"move.w #$1,-(sp)"
"jsr .lxl" | A0 | |
lxa | STACK | "move.w #$1,-(sp)"
"jsr .lxa" | A0 | |
loi $1 == 1 | ADDREG | | {IADDREG1, %[1]} | |
... | nocoercions: LOCAL_ADDR | | {DISPL1,LB,%[1.off]} | |
... | nocoercions: REGOFF_ADDR | | {DISPL1,%[1.reg],%[1.off]} | |
... | nocoercions: EXTERNAL_ADDR | | {ABS1,%[1.off]} | |
loi $1 == 2 | ADDREG | | {IADDREG,%[1]} | |
loi $1 == 4 | ADDREG | | {IADDREG4,%[1]} | |
@ -272,9 +245,7 @@ lae loi $2 == 6 | | remove(ALL)
lae loi $2 == 8 | | remove(ALL)
"move.l $1+4,-(sp)"
"move.l $1,-(sp)" | | |
loi $1 == 6 | ADDREG | | {DISPL,%[1],4} {IADDREG4,%[1]} | |
loi $1 == 8 | ADDREG | | {DISPL4,%[1],4} {IADDREG4,%[1]} | |
loi $1 > 8 | ADDSCR | remove(ALL)
loi $1 > 4 | ADDSCR | remove(ALL)
allocate(DATAREG4= {IMMEDIATE4,$1/2-1})
"add.l #$1,%[1]"
"1:"
@ -328,12 +299,10 @@ lpi | | | {EXTERNAL_ADDR,$1} | |
#ifdef REGVARS
stl inreg($1)==2 | nocoercions: ANY | remove(regvar($1))
stl inreg($1)==2 | ANY | remove(regvar($1))
move(%[1],regvar($1)) | | |
... | STACK |
"move.w (sp)+,%(regvar($1)%)" | | |
#endif
stl | nocoercions: ANY | remove(DISPL,%[reg] == LB && %[dis] == $1)
stl | ANY | remove(DISPL,%[reg] == LB && %[dis] == $1)
remove(DISPL4,%[reg] == LB && (%[dis] == $1-2 ||
%[dis] == $1))
remove(DISPL1,%[reg] == LB && (%[dis] == $1 ||
@ -343,8 +312,6 @@ stl | nocoercions: ANY | remove(DISPL,%[reg] == LB && %[dis] == $1)
remove(DISPL1,%[reg] != LB)
remove(ALL_ACCESSIBLE)
move(%[1],{DISPL,LB,$1}) | | |
... | STACK |
"move.w (sp)+,$1(a6)" | | |
ste | ANY |
remove(ABS)
remove(ABS4)
@ -411,29 +378,6 @@ sti $1 == 1
... | nocoercions: LOCAL_ADDR ANY1 |
remove(MEM_ALL)
move(%[2],{DISPL1,LB,%[1.off]}) | | |
... | nocoercions: REGOFF_ADDR DATAREG |
remove(MEM_ALL)
move(%[2], {DISPL1,%[1.reg],%[1.off]}) | | |
... | nocoercions: REGOFF_ADDR IADDREG |
remove(MEM_ALL)
move({DISPL,%[2.reg],1}, {DISPL1,%[1.reg],%[1.off]}) | | |
... | nocoercions: REGOFF_ADDR DISPL |
remove(MEM_ALL)
move({DISPL,%[2.reg],%[2.dis]+1}, {DISPL1,%[1.reg],%[1.off]}) | | |
... | nocoercions: REGOFF_ADDR INDEXED |
remove(MEM_ALL)
move({INDEXED,%[2.reg],%[2.ireg],%[2.di]+1},
{DISPL1,%[1.reg],%[1.off]}) | | |
... | nocoercions: REGOFF_ADDR ABS |
remove(MEM_ALL)
move({ABS,%[2.addr]+"+1"}, {DISPL1,%[1.reg],%[1.off]}) | | |
... | nocoercions: REGOFF_ADDR IMMEDIATE |
remove(MEM_ALL)
move({IMMEDIATE,(%[2.cc]-((%[2.cc]>>8)<<8)+128)%256-128},
{DISPL1,%[1.reg],%[1.off]}) | | |
... | nocoercions: REGOFF_ADDR ANY1 |
remove(MEM_ALL)
move(%[2],{DISPL1,%[1.reg],%[1.off]}) | | |
... | nocoercions: EXTERNAL_ADDR DATAREG |
remove(MEM_ALL)
move(%[2], {ABS1,%[1.off]}) | | |
@ -471,13 +415,10 @@ sts $1 == 2 | | remove(ALL)
"jsr .sts"
| | |
#ifdef REGVARS
sdl inreg($1)==2 | nocoercions: ANY4 | remove(regvar($1))
sdl inreg($1)==2 | ANY4 | remove(regvar($1))
move (%[1],regvar($1)) | | |
... | STACK |
"move.l (sp)+,%(regvar($1)%)" | | |
#endif
sdl | nocoercions: ANY4 |
remove(DISPL,%[reg] == LB && (%[dis] == $1 || %[dis] == $1+2))
sdl | ANY4 | remove(DISPL,%[reg] == LB && (%[dis] == $1 || %[dis] == $1+2))
remove(DISPL4,%[reg] == LB && (%[dis] >= $1-2 &&
%[dis] <= $1+2))
remove(DISPL1,%[reg] == LB && (%[dis] >= $1 &&
@ -487,8 +428,6 @@ sdl | nocoercions: ANY4 |
remove(DISPL1,%[reg] != LB)
remove(ALL_ACCESSIBLE)
move(%[1],{DISPL4,LB,$1}) | | |
... | STACK |
"move.l (sp)+,$1(a6)" | | |
sde | ANY4 |
remove(ABS)
remove(ABS4)
@ -510,41 +449,6 @@ sdf | ADDREG ANY4 | remove(MEM_ALL)
* local variables that are not register-variables.
*/
ldl ldl adp sdl loi $1==$2 && $2==$4 && inreg($1)==2 && $3==1 && $5==1 | |
allocate(DATAREG={IMMEDIATE,0})
remove(regvar($1))
"move.b (%(regvar($1)%))+,%[a]" | %[a] | |
ldl ldl adp sdl loi $1==$2 && $2==$4 && inreg($1)==2 && $3==2 && $5==2 | |
allocate(DATAREG)
remove(regvar($1))
"move.w (%(regvar($1)%))+,%[a]" | %[a] | |
ldl ldl adp sdl sti $1==$2 && $2==$4 && inreg($1)==2 && $3==1 && $5==1 | DATAREG |
remove(regvar($1))
"move.b %[1],(%(regvar($1)%))+" | | |
ldl ldl adp sdl sti $1==$2 && $2==$4 && inreg($1)==2 && $3==2 && $5==2 | ANY |
remove(regvar($1))
"move.w %[1],(%(regvar($1)%))+" | | |
ldl ldl adp sdl $1==$2 && $2==$4 && inreg($1)==2 | |
allocate(ADDREG=regvar($1)) | %[a]
| ldl $2 adp $3 sdl $2 |
lol inl $1==$2 && inreg($1)==2 | |
allocate(DATAREG=regvar($1)) | %[a]
| inl $2 |
lol inl $1==$2 | |
allocate(DATAREG={DISPL,LB,$1}) | %[a]
| inl $2 |
lol del $1==$2 && inreg($1)==2 | |
allocate(DATAREG=regvar($1)) | %[a]
| del $2 |
lol del $1==$2 | |
allocate(DATAREG={DISPL,LB,$1}) | %[a]
| del $2 |
loe ine $1==$2 | |
allocate(DATAREG={ABS,$1}) | %[a]
| ine $2 |
loe dee $1==$2 | |
allocate(DATAREG={ABS,$1}) | %[a]
| dee $2 |
lol adi stl $1 == $3 && $2 == 2 && inreg($1)==2 | ANY |
remove(regvar($1))
@ -643,15 +547,14 @@ lol loc slu stl $1 == $4 && $2 == 1 && $3 == 2 && inreg($1)==2 | |
remove(regvar($1))
"asl.w #1,%(regvar($1)%)"
erase(regvar($1)) | | |
ldl ldl adp sdl $1 == $2 && $2 == $4 && inreg($1)==2 | |
remove(regvar($1))
allocate(ADDREG=regvar($1))
"add.l #$3,%(regvar($1)%)"
erase(regvar($1)) | %[a] | |
ldl adp sdl $1 == $3 && inreg($1)==2 | | remove(regvar($1))
"add.l #$2,%(regvar($1)%)"
erase(regvar($1)) | | |
ldl adp dup sdl loi inreg($1) == 2 && $1 == $4 && $3 == 4 && $5 == 4 | | | |
ldl $1 adp $2 sdl $1 ldl $1 loi 4 |
ldl loi ldl loi adp ldl sti $2==4&&$4==4&&$7==4&&$1==$3&&$1==$6&&inreg($1)==2
| | remove(MEM_ALL)
allocate(ADDREG = {IADDREG4,regvar($1)})
"add.l #$5,(%(regvar($1)%))" | %[a] | |
loc ldl ads sdl $2 == $4 && $3 == 2 && inreg($2)==2 | |
remove(regvar($2))
"add.l #$1,%(regvar($2)%)"
@ -666,12 +569,10 @@ ldc ldl ads sdl $2 == $4 && $3 == 4 && inreg($2)==2 | |
erase(regvar($2)) | | |
lil inc sil $1==$3 && inreg($1)==2 | |
remove(MEM_ALL)
"add.w #1,(%(regvar($1)%))"
setcc({IADDREG,regvar($1)}) | | |
"add.w #1,(%(regvar($1)%))" | | |
lil dec sil $1==$3 && inreg($1)==2 | |
remove(MEM_ALL)
"sub.w #1,(%(regvar($1)%))"
setcc({IADDREG,regvar($1)}) | | |
"sub.w #1,(%(regvar($1)%))" | | |
lol and stl $1 == $3 && $2 == 2 && inreg($1)==2 | ANY |
remove(regvar($1))
"and.w %[1],%(regvar($1)%)"
@ -866,24 +767,12 @@ lol ngi stl $1 == $3 && $2 == 4 | |
loe ngi ste $1 == $3 && $2 == 4 | |
remove(MEM_ALL)
"neg.l $1" | | |
loc sli $1 == 1 && $2 == 2 | DATASCR |
"add.w %[1],%[1]"
erase(%[1])
setcc(%[1]) | %[1] | |
loc sli $1 > 1 && $1 <= 8 && $2 == 2 | DATASCR |
loc sli $1 >= 1 && $1 <= 8 && $2 == 2 | DATASCR |
"asl.w #$1,%[1]"
erase(%[1]) | %[1] | |
loc sli $1 == 1 && $2 == 4 | DATASCR4 |
"add.l %[1],%[1]"
erase(%[1])
setcc(%[1]) | %[1] | |
loc sli $1 > 1 && $1 <= 8 && $2 == 4 | DATASCR4 |
loc sli $1 >= 1 && $1 <= 8 && $2 == 4 | DATASCR4 |
"asl.l #$1,%[1]"
erase(%[1]) | %[1] | |
lol loc sli ads inreg($1) == 2 && $2 == 1 && $3 == 2 && $4 == 2 | ADDSCR |
"add.w %(regvar($1)%),%[1]"
"add.w %(regvar($1)%),%[1]"
erase(%[1]) | %[1] | |
lol loc sli stl $1 == $4 && $2 == 1 && $3 == 2 | |
remove(MEM_ALL)
"asl.w #1, $1(a6)" | | |
@ -1035,78 +924,16 @@ adu | | | | adi $1 |
sbu | | | | sbi $1 |
slu | | | | sli $1 |
/* Floating point stuff */
adf $1==4 | |
remove(ALL)
"jsr .adf4" | | asp 8 lfr 4 |
adf $1==8 | |
remove(ALL)
"jsr .adf8" | | asp 16 lfr 4 loi 8 |
sbf $1==4 | |
remove(ALL)
"jsr .sbf4" | | asp 8 lfr 4 |
sbf $1==8 | |
remove(ALL)
"jsr .sbf8" | | asp 16 lfr 4 loi 8 |
mlf $1==4 | |
remove(ALL)
"jsr .mlf4" | | asp 8 lfr 4 |
mlf $1==8 | |
remove(ALL)
"jsr .mlf8" | | asp 16 lfr 4 loi 8 |
dvf $1==4 | |
remove(ALL)
"jsr .dvf4" | | asp 8 lfr 4 |
dvf $1==8 | |
remove(ALL)
"jsr .dvf8" | | asp 16 lfr 4 loi 8 |
ngf $1==4 | |
remove(ALL)
"jsr .ngf4" | | asp 4 lfr 4 |
ngf $1==8 | |
remove(ALL)
"jsr .ngf8" | | asp 16 lfr 4 loi 8 |
fif $1==4 | |
remove(ALL)
"jsr .fif4" | | asp 16 lfr 4 loi 8 |
fif $1==8 | |
remove(ALL)
"jsr .fif8" | | asp 16 lfr 4 loi 16 |
fef $1==4 | |
remove(ALL)
"jsr .fef4" | | asp 4 lfr 4 loi 8 |
fef $1==8 | |
remove(ALL)
"jsr .fef8" | | asp 8 lfr 4 loi 12 |
/* G R O U P VI : P O I N T E R A R I T H M E T I C */
adp $1 >= 1 && $1 <= 8
| nocoercions: EXTERNAL_ADDR | | {EXTERNAL_ADDR,%[1.off] + "+"
+ tostring($1)} | |
... | nocoercions: LOCAL_ADDR | | {LOCAL_ADDR,%[1.off]+$1} | |
... | nocoercions: REGOFF_ADDR | | {REGOFF_ADDR,%[1.reg],%[1.off]+$1} | |
... | nocoercions: ADDREG | | {REGOFF_ADDR,%[1],$1} | |
... | ADDSCR | "add.l #$1,%[1]"
adp $1 >= 1 && $1 <= 8 | ADDSCR | "add.l #$1,%[1]"
erase(%[1])
setcc(%[1]) | %[1] | |
adp $1 >= 0-32767 && $1 <= 32767
| nocoercions: EXTERNAL_ADDR | | {EXTERNAL_ADDR,%[1.off] + "+"
+ tostring($1)} | |
... | nocoercions: LOCAL_ADDR | | {LOCAL_ADDR,%[1.off]+$1} | |
... | nocoercions: REGOFF_ADDR | | {REGOFF_ADDR,%[1.reg],%[1.off]+$1} | |
... | nocoercions: ADDREG | | {REGOFF_ADDR,%[1],$1} | |
... | ADDSCR | "lea $1(%[1]),%[1]"
adp | ADDSCR | "lea $1(%[1]),%[1]"
erase(%[1])
setcc(%[1]) | %[1] | |
adp | nocoercions: EXTERNAL_ADDR | | {EXTERNAL_ADDR,%[1.off] + "+"
+ tostring($1)} | |
... | ADDSCR | "add.l #$1,%[1]"
erase(%[1])
setcc(%[1]) | %[1] | |
/* The next patterns are for efficient translation of "*p++" in C */
ldl ldl adp sdl $1 == $2 && $2 == $4 | |
allocate(ADDREG={DISPL4,LB,$1})
@ -1175,12 +1002,10 @@ inc | DATASCR | "add.w #1,%[1]"
#ifdef REGVARS
lil inc sil $1==$3 && inreg($1) == 2 | |
remove(MEM_ALL)
"add.w #1,(%(regvar($1)%))"
setcc({IADDREG,regvar($1)}) | | |
"add.w #1,(%(regvar($1)%))" | | |
lil dec sil $1==$3 && inreg($1) == 2 | |
remove(MEM_ALL)
"sub.w #1,(%(regvar($1)%))"
setcc({IADDREG,regvar($1)}) | | |
"sub.w #1,(%(regvar($1)%))" | | |
#endif
lil inc sil $1==$3 | | allocate(ADDREG={DISPL4,LB,$1})
remove(MEM_ALL)
@ -1293,7 +1118,6 @@ zer $1 > 12 | | remove(ALL)
"1:"
"clr -(sp)"
"dbf %[a],1b" | | |
zrf | | | | zer $1 |
@ -1343,88 +1167,6 @@ loc loc ciu $1==4 && $2==2 | DATAREG4 | | %[1.1] | |
loc loc cui $1==4 && $2==2 | DATAREG4 | | %[1.1] | |
... | ANY | | | |
/* Floating point stuff */
loc loc cif $1==2 && $2==4 | |
remove(ALL)
"move.w #$1,-(sp)"
"jsr .cif4" | | asp 4 lfr 4 |
loc loc cif $1==2 && $2==8 | |
remove(ALL)
"move.w #$1,-(sp)"
"jsr .cif8" | | asp 4 lfr 4 loi 8 |
loc loc cif $1==4 && $2==4 | |
remove(ALL)
"move.w #$1,-(sp)"
"jsr .cif4" | | asp 6 lfr 4 |
loc loc cif $1==4 && $2==8 | |
remove(ALL)
"move.w #$1,-(sp)"
"jsr .cif8" | | asp 6 lfr 4 loi 8 |
loc loc cuf $1==2 && $2==4 | |
remove(ALL)
"move.w #$1,-(sp)"
"jsr .cuf4" | | asp 4 lfr 4 |
loc loc cuf $1==2 && $2==8 | |
remove(ALL)
"move.w #$1,-(sp)"
"jsr .cuf8" | | asp 4 lfr 4 loi 8 |
loc loc cuf $1==4 && $2==4 | |
remove(ALL)
"move.w #$1,-(sp)"
"jsr .cuf4" | | asp 6 lfr 4 |
loc loc cuf $1==4 && $2==8 | |
remove(ALL)
"move.w #$1,-(sp)"
"jsr .cuf8" | | asp 6 lfr 4 loi 8 |
loc loc cfi $1==4 && $2==2 | |
remove(ALL)
"move.w #$1,-(sp)"
"move.w #$2,-(sp)"
"jsr .cfi" | | asp 8 lfr 2 |
loc loc cfi $1==4 && $2==4 | |
remove(ALL)
"move.w #$1,-(sp)"
"move.w #$2,-(sp)"
"jsr .cfi" | | asp 8 lfr 4 |
loc loc cfi $1==8 && $2==2 | |
remove(ALL)
"move.w #$1,-(sp)"
"move.w #$2,-(sp)"
"jsr .cfi" | | asp 12 lfr 2 |
loc loc cfi $1==8 && $2==4 | |
remove(ALL)
"move.w #$1,-(sp)"
"move.w #$2,-(sp)"
"jsr .cfi" | | asp 12 lfr 4 |
loc loc cfu $1==4 && $2==2 | |
remove(ALL)
"move.w #$1,-(sp)"
"move.w #$2,-(sp)"
"jsr .cfu" | | asp 8 lfr 2 |
loc loc cfu $1==4 && $2==4 | |
remove(ALL)
"move.w #$1,-(sp)"
"move.w #$2,-(sp)"
"jsr .cfu" | | asp 8 lfr 4 |
loc loc cfu $1==8 && $2==2 | |
remove(ALL)
"move.w #$1,-(sp)"
"move.w #$2,-(sp)"
"jsr .cfu" | | asp 12 lfr 2 |
loc loc cfu $1==8 && $2==4 | |
remove(ALL)
"move.w #$1,-(sp)"
"move.w #$2,-(sp)"
"jsr .cfu" | | asp 12 lfr 4 |
loc loc cff $1==8 && $2==4 | |
remove(ALL)
"jsr .cff4" | | asp 8 lfr 4 |
loc loc cff $1==4 && $2==8 | |
remove(ALL)
"jsr .cff8" | | asp 4 lfr 4 loi 8 |
/* G R O U P IX : L O G I C A L */
and defined($1) && $1 == 2 | ANY DATASCR |
@ -1435,11 +1177,6 @@ and defined($1) && $1 == 2 | ANY DATASCR |
"and %[2],%[1]"
setcc(%[1])
erase(%[1]) | %[1] | | (2,2)+%[2]
lol loc and $2 == 255 && inreg($1) < 2 && $3 == 2 | | | {DISPL1,LB,$1+1} | |
lal loi and lal sti $1 == $4 && $2 == 1 && $3 == 2 && $5 == 1 && inreg($1) < 2
| DATAREG |
remove(MEM_ALL)
"and.b %[1],$1(a6)" | | |
loc lol and stl $2 == $4 && $3 == 2 && inreg($2) < 2 | |
remove(MEM_ALL)
"and.w #$1,$2(a6)" | | | (6,10)
@ -1519,10 +1256,6 @@ ior defined($1) && $1 == 2 | ANY DATASCR |
"or %[2],%[1]"
erase(%[1])
setcc(%[1]) | %[1] | | (2,2)+%[2]
lal loi ior lal sti $1 == $4 && $2 == 1 && $3 == 2 && $5 == 1 && inreg($1) < 2
| DATAREG |
remove(MEM_ALL)
"or.b %[1],$1(a6)" | | |
loc lol ior stl $2 == $4 && $3 == 2 && inreg($2) < 2 | |
remove(MEM_ALL)
"or.w #$1,$2(a6)" | | | (6,10)
@ -1599,10 +1332,6 @@ xor defined($1) && $1 == 2 | DATAREG DATASCR |
"eor %[2],%[1]"
erase(%[1])
setcc(%[1]) | %[1] | | (2,2)+%[2]
lal loi xor lal sti $1 == $4 && $2 == 1 && $3 == 2 && $5 == 1 && inreg($1) < 2
| DATAREG |
remove(MEM_ALL)
"eor.b %[1],$1(a6)" | | |
lol loc xor stl $1 == $4 && $3 == 2 | |
remove(MEM_ALL)
"eor.w #$2,$1(a6)" | | | (6,10)
@ -1854,15 +1583,6 @@ cms !defined($1) | ANY | remove(ALL)
cmp | | remove(ALL)
"jsr .cmp"
| D1 | |
/* floating point */
cmf $1==4 | |
remove(ALL)
"jsr .cmf4" | | asp 8 lfr 2 |
cmf $1==8 | |
remove(ALL)
"jsr .cmf8" | | asp 16 lfr 2 |
cmi tlt and $1==2 && $3==2 | ANY DATAREG DATASCR |
"cmp %[1],%[2]"
@ -2245,22 +1965,22 @@ ldc cmi tgt loww(1)==0&&highw(1)==0 | DATA_ALT4 | allocate(DATAREG={IMMEDIATE,1}
"clr %[a]"
"1:"
erase(%[a]) | %[a] | |
cmi zlt $1==4 | ANY4 REG4 STACK |
cmi zlt $1==4 | ANY4 DATAREG4 STACK |
"cmp.l %[1],%[2]"
"blt $2" | | |
cmi zle $1==4 | ANY4 REG4 STACK |
cmi zle $1==4 | ANY4 DATAREG4 STACK |
"cmp.l %[1],%[2]"
"ble $2" | | |
cmi zeq $1==4 | ANY4 REG4 STACK |
cmi zeq $1==4 | ANY4 DATAREG4 STACK |
"cmp.l %[1],%[2]"
"beq $2" | | |
cmi zne $1==4 | ANY4 REG4 STACK |
cmi zne $1==4 | ANY4 DATAREG4 STACK |
"cmp.l %[1],%[2]"
"bne $2" | | |
cmi zge $1==4 | ANY4 REG4 STACK |
cmi zge $1==4 | ANY4 DATAREG4 STACK |
"cmp.l %[1],%[2]"
"bge $2" | | |
cmi zgt $1==4 | ANY4 REG4 STACK |
cmi zgt $1==4 | ANY4 DATAREG4 STACK |
"cmp.l %[1],%[2]"
"bgt $2" | | |
ldc cmi zlt loww(1)==0&&highw(1)==0 && $2==4 | DATA_ALT4 STACK |
@ -2506,21 +2226,6 @@ tgt | DATA_ALT | allocate(DATAREG={IMMEDIATE,1})
/* G R O U P XIII : B R A N C H */
bra | STACK | "bra $1" | | |
/* byte comparisons */
loc beq $1 >= 0 && $1 < 128 | nocoercions: DATA_ALT1 |
remove(ALL)
"cmp.b #$1,%[1]"
"beq $2" | | |
... | DATA_ALT STACK |
"cmp #$1,%[1]"
"beq $2" | | |
loc bne $1 >= 0 && $1 < 128 | nocoercions: DATA_ALT1 |
remove(ALL)
"cmp.b #$1,%[1]"
"bne $2" | | |
... | DATA_ALT STACK |
"cmp #$1,%[1]"
"bne $2" | | |
blt | IMMEDIATE DATA_ALT STACK | "cmp %[1],%[2]"
"blt $1" | | |
... | ANY DATAREG STACK | "cmp %[1],%[2]"
@ -2758,12 +2463,8 @@ dus $1 == 2 | DATASCR | remove(ALL)
exg | STACK | "move.w #$1,d0"
"jsr .exg" | | |
fil | | "move.l #$1,.filn" | | |
gto | STACK | allocate(ADDREG)
"lea $1,%[a]"
"move.l 4(%[a]),sp"
"move.l 8(%[a]),a6"
"move.l (%[a]),%[a]"
"jmp (%[a])" | | |
gto | STACK | "pea $1"
"jmp .gto" | | |
lin | | "move.w #$1,.lino" | | |
lni | | "add.w #1,.lino" | | |
mon | STACK | "jsr .mon" | | |
@ -2772,7 +2473,7 @@ lim | | | {ABS4,".trpim"} | |
lor $1 == 0 | | | LB | |
lor $1 == 1 | STACK | "move.l sp,-(sp)" | | |
lor $1 == 2 | | | {ABS4,".reghp"} | |
lpb | | | | adp 8 |
lpb | STACK | "jsr .lpb" | A0 | |
rck $1 == 2 | | remove(ALL)
"jsr .rck"
| | |
@ -2788,6 +2489,27 @@ str $1 == 2 | | remove(ALL)
trp | STACK | "jsr .trp" | | |
/* For several floating point instructions we generate an illegal
* instruction trap.
*/
adf | | | | loc 18 trp |
sbf | | | | loc 18 trp |
mlf | | | | loc 18 trp |
dvf | | | | loc 18 trp |
ngf | | | | loc 18 trp |
fef | | | | loc 18 trp |
fif | | | | loc 18 trp |
zrf | | | | loc 18 trp |
cfi | | | | loc 18 trp |
cif | | | | loc 18 trp |
cuf | | | | loc 18 trp |
cff | | | | loc 18 trp |
cfu | | | | loc 18 trp |
cmf | | | | loc 18 trp |
/* C O E R C I O N S */
@ -2858,7 +2580,6 @@ STACKS:
(ANY, , "move.w %[1],-(sp)" setcc(%[1]), (2,4) + %[1])
(EXTERNAL_ADDR, , "pea %[1.off]" nocc)
(LOCAL_ADDR, , "pea %[1.off](a6)" nocc)
(REGOFF_ADDR, , "pea %[1.off](%[1.reg])" nocc)
(INDEX_ADDR, , "pea %[1.di](%[1.reg],%[1.ireg].w)" nocc)
(IMMEDIATE4 %[cc] == 0, , "clr.l -(sp)")
(IMMEDIATE4, , "pea %[1.cc]" nocc)

View file

@ -1,106 +0,0 @@
static char rcsid[] = "$Header$";
#define MAXBYTE 24
#include <stdio.h>
char hex[] = "0123456789ABCDEF";
FILE *fp, *fopen();
char **s;
int bytes, bytcnt, checksum;
long pc;
main (argc,argv)
int argc;
char *argv[];
{
if (argc != 2) fatal ("usage: %s filename\n",argv[0]);
if ((fp = fopen (*++argv,"r")) == NULL)
fatal ("can't open %s\n",*argv);
else {
s = argv;
convert ();
fclose (fp);
}
}
convert ()
{
int c;
do
{
pc = getword ();
pc = (pc << 16) | getword ();
bytes = getword ();
while (bytes != 0)
{
bytcnt = (bytes < MAXBYTE) ? bytes : MAXBYTE;
bytes -= bytcnt;
checksum = 0;
if (pc > 0xffffL) S2record (); else S1record ();
}
c = getc (fp);
ungetc (c, fp);
}
while (c != EOF);
printf ("S9030000FC\n");
}
S2record ()
{
printf ("S2");
bytcnt += 4;
outbyte (bytcnt);
outbyte (pc);
record ();
}
S1record ()
{
printf ("S1");
bytcnt += 3;
outbyte (bytcnt);
record ();
}
record ()
{
outbyte (pc << 8);
outbyte (pc << 16);
while (bytcnt != 0)
{
outbyte (getbyte ());
pc ++;
}
outbyte (~checksum);
putchar ('\n');
putchar (0);
putchar (0);
}
outbyte (b)
int b;
{
checksum = (checksum + b) & 0377;
putchar (hex[(b>>4) & 017]);
putchar (hex[b & 017]);
-- bytcnt;
}
getword ()
{
int c;
c = getbyte ();
return ((getbyte () << 8) | c );
}
getbyte ()
{
int c;
if ((c = getc (fp)) == EOF) fatal ("end of %s\n",*s);
return (c);
}
fatal (s,a)
{
printf (s,a);
exit (-1);
}

View file

@ -2,6 +2,6 @@
.extern _times
.text
_times: move.w #0x2B,d0
move.l 4(sp),a0
move.w 4(sp),a0
trap #0
rts

View file

@ -2,20 +2,15 @@ tail_mon.a
exit.s
_exit.s
access.s
acct.s
alarm.s
chdir.s
chmod.s
chown.s
chroot.s
close.s
creat.s
dup.s
dup2.s
execl.s
execve.s
fork.s
ftime.s
getegid.s
getgid.s
getpid.s
@ -25,16 +20,12 @@ gtty.s
ioctl.s
kill.s
link.s
lock.s
lseek.s
mknod.s
mount.s
nice.s
open.s
pause.s
pipe.s
profil.s
ptrace.s
read.s
setgid.s
setuid.s
@ -43,10 +34,8 @@ stime.s
sync.s
time.s
times.s
umask.s
umount.s
unlink.s
utime.s
write.s
brk.s
wait.s
@ -54,4 +43,3 @@ fstat.s
signal.s
call.s
cleanup.s
errno.s

View file

@ -1,53 +0,0 @@
# $Header$
EM = ../../..
h = $(EM)/h
CDIR = $(EM)/mach/proto/nas
CPP = $(EM)/lib/cpp
DEF =
FFLAG =
CFLAGS = $(FFLAG) -O -I$h $(DEF)
YFLAGS = -d
LDFLAGS = $(FFLAG) -i
CSRC = $(CDIR)/comm3.c $(CDIR)/comm4.c $(CDIR)/comm5.c \
$(CDIR)/comm6.c $(CDIR)/comm7.c $(CDIR)/comm8.c
COBJ = $(CDIR)/comm3.o $(CDIR)/comm4.o $(CDIR)/comm5.o \
$(CDIR)/comm6.o $(CDIR)/comm7.o $(CDIR)/comm8.o
MACH = mach0.c mach1.c mach2.c mach3.c mach4.c mach5.c
COMM = $(CDIR)/comm0.h $(CDIR)/comm1.h $(CDIR)/comm2.y $(CSRC)
all: as
install:all
../../install as
cmp:
-../../compare as
clean:
rm -f *.o as as.[cy] y.tab.h
pr: $(MACH)
@pr -n $(MACH)
opr:
make pr | opr
as: $(COBJ) as.o
$(CC) $(LDFLAGS) $(COBJ) as.o -o as
as.y: $(CDIR)/comm2.y
$(CPP) -P -I$h $(DEF) $(CDIR)/comm2.y >as.y
@echo "expect 1 shift/reduce conflict"
lint: $(CSRC) as.c
lint $(CSRC) as.c
y.tab.h: as.c
$(COBJ): y.tab.h
$(COBJ) as.y: $(CDIR)/comm0.h mach0.c
$(COBJ) as.y: $(CDIR)/comm1.h mach1.c
as.y: mach2.c
comm3.o: mach3.c
as.y: mach4.c
comm8.o: mach5.c

View file

@ -1,53 +0,0 @@
# $Header$
EM = ../../..
h = $(EM)/h
CDIR = $(EM)/mach/proto/nas
CPP = $(EM)/lib/cpp
DEF =
FFLAG =
CFLAGS = $(FFLAG) -O -I$h $(DEF)
YFLAGS = -d
LDFLAGS = $(FFLAG) -i
CSRC = $(CDIR)/comm3.c $(CDIR)/comm4.c $(CDIR)/comm5.c \
$(CDIR)/comm6.c $(CDIR)/comm7.c $(CDIR)/comm8.c
COBJ = $(CDIR)/comm3.o $(CDIR)/comm4.o $(CDIR)/comm5.o \
$(CDIR)/comm6.o $(CDIR)/comm7.o $(CDIR)/comm8.o
MACH = mach0.c mach1.c mach2.c mach3.c mach4.c mach5.c
COMM = $(CDIR)/comm0.h $(CDIR)/comm1.h $(CDIR)/comm2.y $(CSRC)
all: as
install:all
../../install as
cmp:
-../../compare as
clean:
rm -f *.o as as.[cy] y.tab.h
pr: $(MACH)
@pr -n $(MACH)
opr:
make pr | opr
as: $(COBJ) as.o
$(CC) $(LDFLAGS) $(COBJ) as.o -o as
as.y: $(CDIR)/comm2.y
$(CPP) -P -I$h $(DEF) $(CDIR)/comm2.y >as.y
@echo "expect 1 shift/reduce conflict"
lint: $(CSRC) as.c
lint $(CSRC) as.c
y.tab.h: as.c
$(COBJ): y.tab.h
$(COBJ) as.y: $(CDIR)/comm0.h mach0.c
$(COBJ) as.y: $(CDIR)/comm1.h mach1.c
as.y: mach2.c
comm3.o: mach3.c
as.y: mach4.c
comm8.o: mach5.c

View file

@ -1,135 +0,0 @@
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include <stdio.h>
/*
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
*
* This product is part of the Amsterdam Compiler Kit.
*
* Permission to use, sell, duplicate or disclose this software must be
* obtained in writing. Requests for such permissions may be sent to
*
* Dr. Andrew S. Tanenbaum
* Wiskundig Seminarium
* Vrije Universiteit
* Postbox 7161
* 1007 MC Amsterdam
* The Netherlands
*
* Author: Hans van Staveren
*/
char buf[512];
char *index();
main() {
register n,sa;
register char *p;
sa=0;
for (;;) {
getline(buf);
if (n=stackadjust()) {
sa += n;
continue;
}
if (nullinstruction())
continue;
if (sa) {
if (buf[0]=='t' && buf[1]=='s' && buf[2]=='t' && buf[3]==' ') {
sa -= 2;
buf[0]='m';
buf[1]='o';
buf[2]='v';
strcat(buf,",(sp)+");
} else if (buf[0]=='m' && buf[1]=='o' && buf[2]=='v' &&
buf[3]==' ' && (p=index(&buf[5],','))!=0 &&
p[1]=='-' && p[2]=='(' && p[3]=='s') {
sa -= 2;
p[1]=' ';
}
}
switch(sa) {
case 0:break;
case 2:puts("tst (sp)+");sa=0;break;
case 4:puts("cmp (sp)+,(sp)+");sa=0;break;
case 6:puts("add $06,sp");sa=0;break;
}
puts(buf);
}
}
getline(buf) register char *buf; {
register c;
while ((c=getchar())==' ' || c=='\t')
;
if (c==EOF)
exit(0);
do *buf++=c;
while ((c=getchar())!='\n');
*buf=0;
}
stackadjust() {
if (buf[0]=='t' &&
buf[1]=='s' &&
buf[2]=='t' &&
buf[3]==' ' &&
buf[4]=='(' &&
buf[5]=='s' &&
buf[6]=='p' &&
buf[7]==')' &&
buf[8]=='+') return(2);
if (buf[0]=='c' &&
buf[1]=='m' &&
buf[2]=='p' &&
buf[3]==' ' &&
buf[4]=='(' &&
buf[5]=='s' &&
buf[6]=='p' &&
buf[7]==')' &&
buf[8]=='+' &&
buf[9]==',' &&
buf[10]=='(' &&
buf[11]=='s' &&
buf[12]=='p' &&
buf[13]==')' &&
buf[14]=='+') return(4);
if (buf[0]=='a' &&
buf[1]=='d' &&
buf[2]=='d' &&
buf[3]==' ' &&
buf[4]=='$' &&
buf[5]=='0' &&
buf[6]=='6' &&
buf[7]==',' &&
buf[8]=='s' &&
buf[9]=='p' &&
buf[10]==0) return(6);
return(0);
}
nullinstruction() {
register char *p;
if (buf[4]=='$' && buf[5]=='0' && buf[6]=='0' && buf[7]==',') {
p=index(buf,'-');
if (p!=0 && p[1]=='(')
return(0);
p=index(buf,'+');
if (p!=0 && p[-1]==')')
return(0);
if (buf[0]=='b' && buf[1]=='i' && (buf[2]=='s' || buf[2]=='c'))
return(1);
if (buf[0]=='a' && buf[1]=='d' && buf[2]=='d')
return(1);
if (buf[0]=='s' && buf[1]=='u' && buf[2]=='b')
return(1);
}
return(0);
}

View file

@ -1,21 +0,0 @@
MAKEFILE=../../proto/libg/Makefile
MACHDEF="MACH=pdp -Rbe-p2" "SUF=s" "ASAR=ar"
PCDEF="PREF=pc" "SUB=" "SRC=lang/pc/libpc"
LIBDIR=../lib
install:
make -f $(MAKEFILE) $(PCDEF) $(MACHDEF) cp
cmp:
make -f $(MAKEFILE) $(PCDEF) $(MACHDEF) all
cmp head_pc $(LIBDIR)/head_pc
cmp tail_pc $(LIBDIR)/tail_pc
clean:
-rm -f *.old *.[ce$(SUF)] tail* head*
opr:
make pr | opr
pr:
@pr Makefile

View file

@ -1,53 +0,0 @@
# $Header$
EM = ../../..
h = $(EM)/h
CDIR = $(EM)/mach/proto/nas
CPP = $(EM)/lib/cpp
DEF =
FFLAG =
CFLAGS = $(FFLAG) -O -I$h $(DEF)
YFLAGS = -d
LDFLAGS = $(FFLAG) -i
CSRC = $(CDIR)/comm3.c $(CDIR)/comm4.c $(CDIR)/comm5.c \
$(CDIR)/comm6.c $(CDIR)/comm7.c $(CDIR)/comm8.c
COBJ = $(CDIR)/comm3.o $(CDIR)/comm4.o $(CDIR)/comm5.o \
$(CDIR)/comm6.o $(CDIR)/comm7.o $(CDIR)/comm8.o
MACH = mach0.c mach1.c mach2.c mach3.c mach4.c mach5.c
COMM = $(CDIR)/comm0.h $(CDIR)/comm1.h $(CDIR)/comm2.y $(CSRC)
all: as
install:all
../../install as
cmp:
-../../compare as
clean:
rm -f *.o as as.[cy] y.tab.h
pr: $(MACH)
@pr -n $(MACH)
opr:
make pr | opr
as: $(COBJ) as.o
$(CC) $(LDFLAGS) $(COBJ) as.o -o as
as.y: $(CDIR)/comm2.y
$(CPP) -P -I$h $(DEF) $(CDIR)/comm2.y >as.y
@echo "expect 1 shift/reduce conflict"
lint: $(CSRC) as.c
lint $(CSRC) as.c
y.tab.h: as.c
$(COBJ): y.tab.h
$(COBJ) as.y: $(CDIR)/comm0.h mach0.c
$(COBJ) as.y: $(CDIR)/comm1.h mach1.c
as.y: mach2.c
comm3.o: mach3.c
as.y: mach4.c
comm8.o: mach5.c

View file

@ -1,252 +0,0 @@
/* @(#)comm0.h 1.8 */
/*
* All preprocessor based options/constants/functions
*/
/* ========== ON/OFF options (use #define in mach0.c) ========== */
/*
* The following options are available, to be set/removed in "mach0.c":
* THREE_PASS: three passes needed for branch optimization
* BYTES_REVERSED: lowest target address for word high-order byte
* WORDS_REVERSED: lowest target address for long high-order byte
* LISTING: include listing facilities
* RELOCATION: relocatable code generated
* DEBUG: for debugging purposes only
* TMPDIR: directory for temporary files
* ASLD: combined assembler/linker
* AOUTSEEK: seek on a.out instead of multiple opens
*/
/* ========== constants (use #undef, #define in mach0.c) ========== */
/* table sizes */
#define STRINGMAX 200 /* <= 256 */
#define BITMAX 2000 /* for short or long branches */
#define SECTMAX 64
#define NAMEMAX 80
#define MEMINCR 2048
/* Some character constants for parsing */
#define ASC_LPAR '['
#define ASC_RPAR ']'
#define ASC_SQUO '\''
#define ASC_DQUO '"'
#define ASC_COMM '!'
#define ISALPHA(c) (isalpha(c) || (c) == '_' || (c) == '.')
#define ISALNUM(c) (isalnum(c) || (c) == '_')
#define GENLAB "I" /* compiler generated labels */
#define ushort unsigned short
#define valu_t short /* type of expression values */
#define addr_t ushort /* type of dot */
#define word_t short /* type of keyword value */
/*
* NOTE: word_t is introduced to reduce the tokenfile size for machines
* with large expressions but smaller opcodes (68000)
*/
#define ALIGNWORD 1
#define ALIGNSECT 1
#define machstart(x) /* nothing */
#define machfinish(x) /* nothing */
#define SETBASE(sp) ((long)(sp)->s_base)
#define VALWIDTH 4
/* ========== Machine dependent option/constant settings ========== */
#include "mach0.c"
/* ========== default option setting ========== */
#ifndef NOLD
#define ASLD /* default ON */
#endif
#ifndef ASLD
#ifndef RELOCATION
separate linker only possible if relocation info produced
#endif RELOCATION
#endif ASLD
#ifndef DEBUG
#define DEBUG 1
#endif
/* ========== Machine independent type declarations ========== */
#ifdef _include
_include <stdio.h>
_include <ctype.h>
_include <signal.h>
#else
#include <stdio.h>
#include <ctype.h>
#include <signal.h>
#endif
#ifdef ASLD
#include "aar.h"
#endif
#include "out.h"
#if DEBUG == 0
#define assert(ex) /* nothing */
#endif
#if DEBUG == 1
#define assert(ex) {if (!(ex)) assert1();}
#endif
#if DEBUG == 2
#define assert(ex) {if (!(ex)) assert2(__FILE__, __LINE__);}
#endif
#define CTRL(x) ((x) & 037)
#define lowb(z) ((int)(z) & 0xFF)
#define loww(z) ((int)(z) & 0xFFFF)
#define fitb(x) ((((x) + 0x80) & ~0xFF) == 0)
#define fitw(x) ((((x) + 0x8000) & ~0xFFFF) == 0)
#define fit(x) if (!(x)) nofit()
#define PASS_1 0
#define PASS_2 1
#define PASS_3 2
#ifdef THREE_PASS
#define PASS_SYMB (pass != PASS_1)
#define PASS_RELO (pass != PASS_1)
#else
#define PASS_SYMB 1
#define PASS_RELO 1
#endif THREE_PASS
#ifdef ASLD
#define RELOMOVE(a,b) /* empty */
#else
#define RELOMOVE(a,b) {a = b; b = 0;}
#endif
/* symbol table management */
#define H_SIZE 256 /* hash size */
#define H_KEY (0*H_SIZE) /* key symbol headers */
#define H_LOCAL (1*H_SIZE) /* module symbol headers */
#ifdef ASLD
#define H_GLOBAL (2*H_SIZE) /* external symbol headers */
#define H_TOTAL (3*H_SIZE)
#else
#define H_TOTAL (2*H_SIZE)
#endif
/* numeric label table management */
#define FB_SIZE 10
#define FB_HEAD (0*FB_SIZE)
#define FB_TAIL (1*FB_SIZE)
#define FB_BACK (2*FB_SIZE)
#define FB_FORW (3*FB_SIZE)
/* miscellaneous */
#define KEYDEFINE 0
#define DOTGAIN DOTSCT->s_gain
/* ========== type declarations ========== */
struct expr_t {
short typ;
valu_t val;
};
typedef struct expr_t expr_t;
struct item_t {
struct item_t *
i_next; /* linked lists with same hash value */
short i_type;
/*
* the i_type field is used for two different purposes:
* - the token type for keywords, returned by yylex()
* - the symbol type for IDENT and FBSYM tokens
*/
valu_t i_valu; /* symbol value */
char *i_name; /* symbol name */
};
typedef struct item_t item_t;
struct sect_t {
short s_flag; /* some flag bits */
addr_t s_base; /* section base */
addr_t s_size; /* section size */
addr_t s_comm; /* length of commons */
addr_t s_zero; /* delayed emit1(0) */
addr_t s_lign; /* section alignment */
long s_foff; /* section file offset */
item_t *s_item; /* points to section name */
#ifdef THREE_PASS
addr_t s_gain; /* gain in PASS_2 */
#endif
};
typedef struct sect_t sect_t;
/* ========== flag field bits ========== */
/* s_flag bits: */
#define BASED 1 /* at fixed position */
/* sflag bits: */
#define SYM_EXT 001 /* external symbols */
#define SYM_LOC 002 /* local symbols */
#define SYM_LAB 004 /* local, compiler-generated labels */
#define SYM_SMB 010 /* .symb symbols */
#define SYM_LIN 020 /* .line and .file */
#define SYM_SCT 040 /* section names */
#define SYM_DEF 073 /* default value */
/*
* extra type bits out of S_ETC, internal use only
#ifndef DUK
* S_COM:
* - symbols declared by .comm
#endif DUK
* S_VAR:
* - type not known at end of PASS_1 (S_VAR|S_UND)
* - value not known at end of PASS_2 (S_VAR|S_ABS)
* S_DOT:
* - dot expression
*/
#ifndef DUK
#define S_COM 0x0100
#endif DUK
#define S_VAR 0x0200
#define S_DOT 0x0400
/* should be tested by preprocessor
* due to error in preprocessor it cannot
* test performed at runtime now
* #if (S_ETC|S_COM|S_VAR|S_DOT) != S_ETC
* incorrect type bits
* #endif
*/
/* parts of the a.out file */
#define PARTEMIT 0
#define PARTRELO 1
#define PARTNAME 2
#define PARTCHAR 3
#define PARTS 4
#ifdef AOUTSEEK
#define AOUTPART(p) if(aoutpart!=p){aoutpart=p;fseek(aoutfile,aoutseek[p],0);}
#define AOUTPUTC(c,p) {putc(c,aoutfile);aoutseek[p]++;if(ferror(aoutfile))werror();}
#else
#define AOUTPART(p) /* empty */
#define AOUTPUTC(c,p) {putc(c,aoutfile[p]);if(ferror(aoutfile[p]))werror();}
#endif

View file

@ -1,122 +0,0 @@
/* @(#)comm1.h 1.5 */
/*
* variable declarations
*/
#ifdef extern
#define INIT(x) = x
#else
#define INIT(x) /* empty */
#endif
extern short pass INIT(PASS_1);
/* PASS 1, 2 or 3 */
extern short peekc; /* push back symbol (PASS_1) */
extern short unresolved; /* number of unresolved references */
extern short lineno; /* input line number */
extern short hllino; /* high-level language line number */
extern short nerrors; /* terminate at end of pass if set */
extern short sflag INIT(SYM_DEF);
/* -s option (symbol table info) */
extern char *progname; /* for error messages */
extern char *modulename; /* for error messages */
#ifdef ASLD
extern short archmode; /* scanning archives */
extern long archsize; /* size of individual archive entries */
#else
extern short uflag; /* if 1 make undefineds extern */
/* symbol table index for last S_UND */
#endif
#ifdef LISTING
extern short dflag; /* -d option (list mode) */
#endif
#ifdef ASLD
#ifdef RELOCATION
extern short rflag; /* -r option (relocation info) */
#endif RELOCATION
#else
#define rflag 1
extern valu_t relonami;
#endif ASLD
#ifdef THREE_PASS
extern short bflag; /* -b option (no optimizations) */
#endif
extern char *aoutpath INIT("a.out");
extern char temppath[50];
extern FILE *input;
extern FILE *tempfile;
#ifdef AOUTSEEK
extern FILE *aoutfile;
extern int aoutpart INIT(-1);
extern long aoutseek[PARTS];
#else
extern FILE *aoutfile[PARTS];
#endif
extern char stringbuf[STRINGMAX];
/* contains last string value */
extern sect_t sect[SECTMAX];
/*
* specials for the location counter
*/
extern sect_t *DOTSCT; /* &sect[DOTTYP-S_MIN] or NULL */
extern addr_t DOTVAL; /* DOTSCT->s_size + DOTSCT->s_base */
extern short DOTTYP; /* S_MIN..S_MAX or S_UND */
extern item_t *hashtab[H_TOTAL];
extern short hashindex; /* see item_search() */
extern item_t *fb_ptr[4*FB_SIZE];
#ifdef THREE_PASS
extern char bittab[BITMAX>>3];
/* one bit per small-large decision */
extern short nbits; /* number of decisions so far */
#endif
#ifdef LISTING
extern short listmode; /* -d option for current pass */
extern short listtemp; /* listmode if .list seen */
extern short listflag; /* copied from listtemp at '\n' */
extern short listcolm; /* column on output */
extern short listeoln INIT(1);
/* set by endline, tested by emit1 */
extern FILE *listfile; /* copy of source text */
extern char listpath[50];
#endif
#ifndef extern
extern item_t keytab[];
extern struct outhead outhead;
#endif
/* forward function declarations */
extern char *libname();
extern char *readident();
extern char *remember();
extern item_t *fb_shift();
extern item_t *fb_alloc();
extern item_t *item_alloc();
extern item_t *item_search();
extern valu_t load();
extern FILE *ffcreat();
extern FILE *fftemp();
/* some library functions used */
extern long atol();
extern char *mktemp();
extern char *sbrk();
extern char *getenv();
/* ========== Machine dependent C declarations ========== */
#include "mach1.c"

View file

@ -1,424 +0,0 @@
/* @(#)comm2.y 1.7 */
/*
* delay inclusion of machine dependent stuff (see comm0.h)
*/
#define _include #include
%{
#include "comm0.h"
#include "comm1.h"
%}
/* ========== Machine independent Yacc definitions ========== */
%union {
word_t y_word;
valu_t y_valu;
expr_t y_expr;
item_t *y_item;
#ifdef ASLD
char *y_strp;
#endif
};
#ifdef ASLD
%token <y_strp> MODULE
#endif
%token STRING
%token <y_item> IDENT
%token <y_item> FBSYM
%token <y_valu> CODE1
%token <y_valu> CODE2
%token <y_valu> CODE4
%token NUMBER0 /* keep NUMBER* in this order */
%token NUMBER1
%token NUMBER2
%token NUMBER3
%token <y_valu> NUMBER
%token DOT
%token EXTERN
%token <y_word> DATA
%token <y_word> ASCII
%token SECTION
%token COMMON
%token BASE
%token SYMB
%token ALIGN
%token ASSERT
%token SPACE
%token <y_word> LINE
%token FILe
%token <y_word> LIST
%token OP_EQ
%token OP_NE
%token OP_LE
%token OP_GE
%token OP_LL
%token OP_RR
%token OP_OO
%token OP_AA
%left OP_OO
%left OP_AA
%left '|'
%left '^'
%left '&'
%left OP_EQ OP_NE
%left '<' '>' OP_LE OP_GE
%left OP_LL OP_RR
%left '+' '-'
%left '*' '/' '%'
%nonassoc '~'
%type <y_valu> absexp optabs1 optabs2
%type <y_expr> expr
%type <y_item> id_fb
/* ========== Machine dependent Yacc definitions ========== */
#include "mach2.c"
%%
/* ========== Machine independent rules ========== */
#ifdef LISTING
#define LISTLINE(n) listline(n)
#else
#define LISTLINE(n) /* empty */
#endif LISTING
#ifdef ASLD
#define RELODONE /* empty */
#else
#define RELODONE assert(relonami == 0)
#endif
program : /* empty */
#ifdef ASLD
| program MODULE /* not in PASS_1 */
{ newmodule($2);}
#endif
| program IDENT ':'
{ newident($2, DOTTYP); newlabel($2);}
| program NUMBER ':'
{ if ($2 < 0 || $2 > 9) {
serror("bad f/b label");
$2 = 0;
}
newlabel(fb_shift((int)$2));
}
| program CODE1
{ emit1((char)$2); LISTLINE(0);}
| program CODE2
{ emit2((short)$2); LISTLINE(0);}
| program CODE4
{ emit4((long)$2); LISTLINE(0);}
| program operation ';'
| program operation '\n'
{ lineno++; LISTLINE(1); RELODONE;}
| program '#' NUMBER STRING '\n'
{ lineno++; LISTLINE(1); RELODONE;}
| program error '\n'
{ serror("syntax error"); yyerrok;
lineno++; LISTLINE(1); RELODONE;
}
;
#undef LISTLINE
#undef RELODONE
operation
: /* empty */
| IDENT '=' expr
{
#ifdef LISTING
if (listflag & 1)
listcolm += printx(VALWIDTH, $3.val);
#endif
newequate($1, $3.typ);
store($1, $3.val);
}
#ifdef LISTING
| LIST
{ if ($1)
listtemp = listmode;
else if ((dflag & 01000) == 0)
listtemp = 0;
}
#endif
| SECTION IDENT
{ newsect($2);}
| COMMON IDENT ',' absexp
{ newcomm($2, $4);}
| BASE absexp
{ if (pass == PASS_1) newbase($2);}
| ASSERT expr
{ if ($2.val == 0 && pass == PASS_3)
warning("assertion failed");
}
| SYMB STRING ',' expr optabs2 optabs2
{ if ((sflag & SYM_SMB) && PASS_SYMB) {
#ifndef ASLD
if (
pass == PASS_3
&&
($4.typ & S_TYP) == S_UND
) {
serror("expression undefined");
relonami = -1;
}
#endif
newsymb(
stringbuf+1,
(short)(
($4.typ & (S_EXT|S_TYP))
|
((ushort)$5<<8)
),
(short)$6,
$4.val
);
}
}
| LINE optabs1
{ if ((sflag & SYM_LIN) && PASS_SYMB) {
if ($2)
hllino = (short)$2;
else
hllino++;
newsymb(
(char *)0,
(short)(DOTTYP | S_LIN),
(short)hllino,
(valu_t)DOTVAL
);
}
}
| FILe STRING
{ if ((sflag & SYM_LIN) && PASS_SYMB) {
hllino = 0;
newsymb(
stringbuf+1,
(short)(DOTTYP | S_FIL),
(short)0,
(valu_t)DOTVAL
);
}
}
| EXTERN externlist
| ALIGN optabs1
{ align($2);}
| SPACE absexp
{ if (DOTSCT == NULL)
nosect();
DOTVAL += $2;
DOTSCT->s_zero += $2;
}
| DATA datalist
| ASCII STRING
{ emitstr($1);}
;
externlist
: IDENT
{ $1->i_type |= S_EXT;}
| externlist ',' IDENT
{ $3->i_type |= S_EXT;}
;
datalist
: expr
{
#ifdef RELOCATION
if (rflag != 0 && PASS_RELO)
#ifdef DUK
#ifdef BYTES_REVERSED
#ifdef WORDS_REVERSED
newrelo($1.typ,
(int)$<y_word>0 | RELBR | RELWR
);
#else WORDS_REVERSED
newrelo($1.typ, (int)$<y_word>0|RELBR);
#endif WORDS_REVERSED
#else BYTES_REVERSED
#ifdef WORDS_REVERSED
newrelo($1.typ, (int)$<y_word>0|RELWR);
#else WORDS_REVERSED
newrelo($1.typ, (int)$<y_word>0);
#endif WORDS_REVERSED
#endif BYTES_REVERSED
#else DUK
newrelo($1.typ, (int)$<y_word>0);
#endif DUK
#endif
emitx($1.val, (int)$<y_word>0);
}
| datalist ',' expr
{
#ifdef RELOCATION
if (rflag != 0 && PASS_RELO)
#ifdef DUK
#ifdef BYTES_REVERSED
#ifdef WORDS_REVERSED
newrelo($3.typ,
(int)$<y_word>0 | RELBR | RELWR
);
#else WORDS_REVERSED
newrelo($3.typ, (int)$<y_word>0|RELBR);
#endif WORDS_REVERSED
#else BYTES_REVERSED
#ifdef WORDS_REVERSED
newrelo($3.typ, (int)$<y_word>0|RELWR);
#else WORDS_REVERSED
newrelo($3.typ, (int)$<y_word>0);
#endif WORDS_REVERSED
#endif BYTES_REVERSED
#else DUK
newrelo($3.typ, (int)$<y_word>0);
#endif DUK
#endif
emitx($3.val, (int)$<y_word>0);
}
;
expr : error
{ serror("expr syntax err");
$$.val = 0; $$.typ = S_UND;
}
| NUMBER
{ $$.val = $1; $$.typ = S_ABS;}
| id_fb
{ $$.val = load($1);
$$.typ = $1->i_type & ~S_EXT;
}
| STRING
{ if (stringbuf[0] != 1)
serror("too many chars");
$$.val = stringbuf[1];
$$.typ = S_ABS;
}
| ASC_LPAR expr ASC_RPAR
{ $$ = $2;}
| expr OP_OO expr
{ $$.val = ($1.val || $3.val);
$$.typ = combine($1.typ, $3.typ, 0);
}
| expr OP_AA expr
{ $$.val = ($1.val && $3.val);
$$.typ = combine($1.typ, $3.typ, 0);
}
| expr '|' expr
{ $$.val = ($1.val | $3.val);
$$.typ = combine($1.typ, $3.typ, 0);
}
| expr '^' expr
{ $$.val = ($1.val ^ $3.val);
$$.typ = combine($1.typ, $3.typ, 0);
}
| expr '&' expr
{ $$.val = ($1.val & $3.val);
$$.typ = combine($1.typ, $3.typ, 0);
}
| expr OP_EQ expr
{ $$.val = ($1.val == $3.val);
$$.typ = combine($1.typ, $3.typ, '>');
}
| expr OP_NE expr
{ $$.val = ($1.val != $3.val);
$$.typ = combine($1.typ, $3.typ, '>');
}
| expr '<' expr
{ $$.val = ($1.val < $3.val);
$$.typ = combine($1.typ, $3.typ, '>');
}
| expr '>' expr
{ $$.val = ($1.val > $3.val);
$$.typ = combine($1.typ, $3.typ, '>');
}
| expr OP_LE expr
{ $$.val = ($1.val <= $3.val);
$$.typ = combine($1.typ, $3.typ, '>');
}
| expr OP_GE expr
{ $$.val = ($1.val >= $3.val);
$$.typ = combine($1.typ, $3.typ, '>');
}
| expr OP_RR expr
{ $$.val = ($1.val >> $3.val);
$$.typ = combine($1.typ, $3.typ, 0);
}
| expr OP_LL expr
{ $$.val = ($1.val << $3.val);
$$.typ = combine($1.typ, $3.typ, 0);
}
| expr '+' expr
{ $$.val = ($1.val + $3.val);
$$.typ = combine($1.typ, $3.typ, '+');
}
| expr '-' expr
{ $$.val = ($1.val - $3.val);
$$.typ = combine($1.typ, $3.typ, '-');
}
| expr '*' expr
{ $$.val = ($1.val * $3.val);
$$.typ = combine($1.typ, $3.typ, 0);
}
| expr '/' expr
{ if ($3.val == 0) {
if (pass == PASS_3)
serror("divide by zero");
$$.val = 0;
} else
$$.val = ($1.val / $3.val);
$$.typ = combine($1.typ, $3.typ, 0);
}
| expr '%' expr
{ if ($3.val == 0) {
if (pass == PASS_3)
serror("divide by zero");
$$.val = 0;
} else
$$.val = ($1.val % $3.val);
$$.typ = combine($1.typ, $3.typ, 0);
}
| '+' expr %prec '*'
{ $$.val = $2.val;
$$.typ = combine(S_ABS, $2.typ, 0);
}
| '-' expr %prec '*'
{ $$.val = -$2.val;
$$.typ = combine(S_ABS, $2.typ, 0);
}
| '~' expr
{ $$.val = ~$2.val;
$$.typ = combine(S_ABS, $2.typ, 0);
}
| DOT
{ $$.val = DOTVAL;
$$.typ = DOTTYP|S_DOT;
}
;
id_fb : IDENT
| FBSYM
;
absexp : expr
{ if (($1.typ & ~S_EXT) != S_ABS)
serror("must be absolute");
$$ = $1.val;
}
;
optabs1
: /* empty */
{ $$ = 0;}
| absexp
{ $$ = $1;}
;
optabs2
: /* empty */
{ $$ = 0;}
| ',' absexp
{ $$ = $2;}
;
/* ========== Machine dependent rules ========== */
#include "mach4.c"
%%

View file

@ -1,50 +0,0 @@
/* @(#)comm3.c 1.1 */
/*
* storage allocation for variables
*/
#include "comm0.h"
#define extern /* empty, to force storage allocation */
#include "comm1.h"
struct outhead outhead = {
O_MAGIC, O_STAMP, 0
#ifndef DUK
#ifdef BYTES_REVERSED
| HF_BREV
#endif
#ifdef WORDS_REVERSED
| HF_WREV
#endif
#endif DUK
};
#include "y.tab.h"
item_t keytab[] = {
0, EXTERN, 0, ".define",
0, EXTERN, 0, ".extern",
0, DOT, 0, ".",
0, DATA, 1, ".data1",
0, DATA, 2, ".data2",
0, DATA, 4, ".data4",
0, ASCII, 0, ".ascii",
0, ASCII, 1, ".asciz",
0, ALIGN, 0, ".align",
0, ASSERT, 0, ".assert",
0, SPACE, 0, ".space",
0, COMMON, 0, ".comm",
0, SECTION, 0, ".sect",
0, BASE, 0, ".base",
0, SYMB, 0, ".symb",
0, LINE, 0, ".line",
0, FILe, 0, ".file",
#ifdef LISTING
0, LIST, 0, ".nolist",
0, LIST, 1, ".list",
#endif
#include "mach3.c"
0, 0, 0, 0
};

View file

@ -1,539 +0,0 @@
/* @(#)comm4.c 1.6 */
/*
* Micro processor assembler framework written by
* Johan Stevenson, Vrije Universiteit, Amsterdam
* modified by
* Johan Stevenson, Han Schaminee and Hans de Vries
* Philips S&I, T&M, PMDS, Eindhoven
*/
#include "comm0.h"
#include "comm1.h"
#include "y.tab.h"
extern YYSTYPE yylval;
/* ========== Machine independent C routines ========== */
stop() {
#if DEBUG < 2
unlink(temppath);
#ifdef LISTING
unlink(listpath);
#endif
#endif
exit(nerrors != 0);
}
main(argc, argv)
char **argv;
{
register char *p;
register i;
static char sigs[] = {
SIGHUP, SIGINT, SIGQUIT, SIGTERM, 0
};
/* this test should be performed by the
* preprocessor, but it cannot
*/
if ((S_ETC|S_COM|S_VAR|S_DOT) != S_ETC)
fatal("incorrect type bits");
progname = *argv++; argc--;
for (p = sigs; i = *p++; )
if (signal(i, SIG_IGN) != SIG_IGN)
signal(i, stop);
for (i = 0; i < argc; i++) {
p = argv[i];
if (*p++ != '-')
continue;
switch (*p++) {
case 'o':
if (*p != NULL) {
aoutpath = p;
break;
}
argv[i] = 0;
if (++i >= argc)
fatal("-o needs filename");
aoutpath = argv[i];
break;
case 'd':
#ifdef LISTING
dflag = 0;
while (*p >= '0' && *p <= '7')
dflag = (dflag << 3) + *p++ - '0';
if ((dflag & 0777) == 0)
dflag |= 0700;
dflag &= ~4;
#endif
break;
case 's':
sflag = 0;
while (*p >= '0' && *p <= '7')
sflag = (sflag << 3) + *p++ - '0';
break;
case 'r':
#ifdef RELOCATION
#ifdef ASLD
rflag = 1;
#endif ASLD
#endif RELOCATION
break;
case 'b':
#ifdef THREE_PASS
bflag = 1;
#endif
break;
#ifndef ASLD
case 'u':
case '\0':
uflag = 1;
break;
#endif
default:
continue;
}
argv[i] = 0;
}
#ifdef RELOCATION
if (rflag)
sflag |= SYM_SCT;
#endif RELOCATION
pass_1(argc, argv);
#ifdef THREE_PASS
pass_23(PASS_2);
#endif
pass_23(PASS_3);
stop();
}
/* ---------- pass 1: arguments, modules, archives ---------- */
pass_1(argc, argv)
char **argv;
{
register i;
register char *p;
register item_t *ip;
#ifdef ASLD
char armagic[SZMAGIC];
#else
register nfile = 0;
#endif
tempfile = fftemp(temppath, "asTXXXXXX");
#ifdef LISTING
listmode = dflag;
if (listmode & 0440)
listfile = fftemp(listpath, "asLXXXXXX");
#endif
for (ip = keytab; ip->i_type; ip++)
item_insert(ip, H_KEY+hash(ip->i_name));
machstart(PASS_1);
while (--argc >= 0) {
p = *argv++;
if (p == 0)
continue;
#ifdef ASLD
if (p[0] == '-' && p[1] == '\0') {
input = stdin;
parse("STDIN");
continue;
}
#else
if (nfile != 0)
fatal("second source file %s", p);
nfile++;
#endif
if ((input = fopen(p, "r")) == NULL)
fatal("can't open %s", p);
#ifdef ASLD
if (
fread(armagic, SZMAGIC, 1, input) == 1
&&
strncmp(armagic, ARMAGIC, SZMAGIC) == 0
) {
archive();
fclose(input);
continue;
}
rewind(input);
#endif
parse(p);
fclose(input);
}
commfinish();
machfinish(PASS_1);
#ifdef ASLD
if (unresolved) {
nerrors++;
fflush(stdout);
fprintf(stderr, "unresolved references:\n");
for (i = 0; i < H_SIZE; i++) {
ip = hashtab[H_GLOBAL+i];
while (ip != 0) {
if ((ip->i_type & (S_EXT|S_TYP)) == (S_EXT|S_UND))
fprintf(stderr, "\t%s\n", ip->i_name);
ip = ip->i_next;
}
}
}
#else
if (unresolved)
outhead.oh_flags |= HF_LINK;
if (nfile == 0)
fatal("no source file");
#endif
}
#ifdef ASLD
archive()
{
register long offset;
register i;
register long modsize;
char modhead[SZMHEAD];
archmode++;
offset = SZMAGIC;
for (;;) {
if (unresolved == 0)
break;
fseek(input, offset, 0);
if (fread(modhead, SZMHEAD, 1, input) != 1)
break;
if (
strncmp(&modhead[OFF_BEG], STR_BEG, LEN_BEG)
||
strncmp(&modhead[OFF_END], STR_END, LEN_END)
)
fatal("bad archive");
offset += SZMHEAD;
modsize = atol(&modhead[OFF_SIZ]);
archsize = modsize;
if (needed()) {
fseek(input, offset, 0);
archsize = modsize;
for (i = 0; i < LEN_NAM; i++)
if (modhead[OFF_NAM+i] == ' ')
break;
modhead[OFF_NAM+i] = '\0';
parse(remember(&modhead[OFF_NAM]));
}
offset += modsize;
}
archmode = 0;
}
needed()
{
register c, first;
register item_t *ip;
register need;
#ifdef LISTING
register save;
save = listflag; listflag = 0;
#endif
need = 0;
peekc = -1;
first = 1;
for (;;) {
c = nextchar();
if (c == '\n') {
first = 1;
continue;
}
if (c == ' ' || c == '\t' || c == ',')
continue;
if (ISALPHA(c) == 0)
break;
if ((ip = item_search(readident(c))) == 0) {
if (first)
break;
continue;
}
if (first) {
if (ip != &keytab[KEYDEFINE])
break;
first = 0;
}
if ((ip->i_type & S_TYP) == S_UND) {
need++;
break;
}
}
#ifdef LISTING
listflag = save;
#endif
return(need);
}
#endif ASLD
parse(s)
char *s;
{
register i;
register item_t *ip;
register char *p;
for (p = s; *p; )
if (*p++ == '/')
s = p;
#ifdef ASLD
yylval.y_strp = s;
putval(MODULE);
#endif
for (i = 0; i < FB_SIZE; i++)
fb_ptr[FB_BACK+i] = 0;
newmodule(s);
peekc = -1;
yyparse();
/*
* Check for undefined symbols
*/
#ifdef ASLD
for (i = 0; i < H_SIZE; i++) {
while (ip = hashtab[H_LOCAL+i]) {
/*
* cleanup local queue
*/
hashtab[H_LOCAL+i] = ip->i_next;
/*
* make undefined references extern
*/
if ((ip->i_type & (S_VAR|S_TYP)) == S_UND)
ip->i_type |= S_EXT;
/*
* relink externals in global queue
*/
if (ip->i_type & S_EXT)
item_insert(ip, H_GLOBAL+i);
}
}
#else
for (i = 0; i < H_SIZE; i++) {
for (ip = hashtab[H_LOCAL+i]; ip; ip = ip->i_next) {
if (ip->i_type & S_EXT)
continue;
if (ip->i_type != S_UND)
continue;
if (uflag == 0)
serror("undefined symbol %s", ip->i_name);
ip->i_type |= S_EXT;
}
}
#endif
/*
* Check for undefined numeric labels
*/
for (i = 0; i < FB_SIZE; i++) {
if ((ip = fb_ptr[FB_FORW+i]) == 0)
continue;
serror("undefined label %d", i);
fb_ptr[FB_FORW+i] = 0;
}
}
pass_23(n)
{
register i;
#ifdef ASLD
register addr_t base = 0;
#endif
register sect_t *sp;
if (nerrors)
stop();
pass = n;
#ifdef LISTING
listmode >>= 3;
if (listmode & 4)
ffreopen(listpath, listfile);
listeoln = 1;
#endif
#ifdef THREE_PASS
nbits = 0;
#endif
for (i = 0; i < FB_SIZE; i++)
fb_ptr[FB_FORW+i] = fb_ptr[FB_HEAD+i];
outhead.oh_nemit = 0;
for (sp = sect; sp < &sect[outhead.oh_nsect]; sp++) {
#ifdef ASLD
if (sp->s_flag & BASED) {
base = sp->s_base;
if (base % sp->s_lign)
fatal("base not aligned");
} else {
base += (sp->s_lign - 1);
base -= (base % sp->s_lign);
sp->s_base = base;
}
base += sp->s_size;
base += sp->s_comm;
#endif
outhead.oh_nemit += sp->s_size - sp->s_zero;
}
if (pass == PASS_3)
setupoutput();
for (sp = sect; sp < &sect[outhead.oh_nsect]; sp++) {
sp->s_size = 0;
sp->s_zero = 0;
#ifdef THREE_PASS
sp->s_gain = 0;
#endif
}
machstart(n);
#ifndef ASLD
newmodule(modulename);
#endif ASLD
ffreopen(temppath, tempfile);
yyparse();
commfinish();
machfinish(n);
}
newmodule(s)
char *s;
{
switchsect(S_UND);
modulename = s;
lineno = 1;
if ((sflag & (SYM_EXT|SYM_LOC|SYM_LAB)) && PASS_SYMB)
newsymb(s, S_MOD, (short)0, (valu_t)0);
#ifdef LISTING
listtemp = 0;
if (dflag & 01000)
listtemp = listmode;
listflag = listtemp;
#endif
}
setupoutput()
{
register sect_t *sp;
register long off;
struct outsect outsect;
#ifdef AOUTSEEK
#define AOUTseek(p,o) {aoutseek[p]=o;}
aoutfile = ffcreat(aoutpath);
#else
#define AOUTseek(p,o) {fseek(aoutfile[p],o,0);}
aoutfile[PARTEMIT]=ffcreat(aoutpath);
#ifdef RELOCATION
aoutfile[PARTRELO]=ffcreat(aoutpath);
#endif
aoutfile[PARTNAME]=ffcreat(aoutpath);
aoutfile[PARTCHAR]=ffcreat(aoutpath);
#endif
/*
* header generation
*/
AOUTseek(PARTEMIT, 0);
putofmt((char *)&outhead, SF_HEAD, PARTEMIT);
/*
* section table generation
*/
off = SZ_HEAD;
off += (long)outhead.oh_nsect * SZ_SECT;
for (sp = sect; sp < &sect[outhead.oh_nsect]; sp++) {
sp->s_foff = off;
outsect.os_base = SETBASE(sp);
outsect.os_size = sp->s_size + sp->s_comm;
outsect.os_foff = sp->s_foff;
outsect.os_flen = sp->s_size - sp->s_zero;
outsect.os_lign = sp->s_lign;
off += outsect.os_flen;
putofmt((char *)&outsect, SF_SECT, PARTEMIT);
}
#ifdef RELOCATION
AOUTseek(PARTRELO, off);
off += (long)outhead.oh_nrelo * SZ_RELO;
#endif
if (sflag == 0)
return;
AOUTseek(PARTNAME, off);
off += (long)outhead.oh_nname * SZ_NAME;
AOUTseek(PARTCHAR, off);
outhead.oh_nchar = off; /* see newsymb() */
#undef AOUTseek
}
commfinish()
{
register i;
register item_t *ip;
register sect_t *sp;
register valu_t addr;
switchsect(S_UND);
#ifdef ASLD
/*
* assign .comm labels and produce .comm symbol table entries
*/
for (i = 0; i<H_SIZE; i++)
for (ip = hashtab[H_GLOBAL+i]; ip; ip = ip->i_next) {
if ((ip->i_type & S_COM) == 0)
continue;
sp = &sect[(ip->i_type & S_TYP) - S_MIN];
if (pass == PASS_1) {
addr = sp->s_size + sp->s_comm;
sp->s_comm += ip->i_valu;
ip->i_valu = addr;
}
#ifdef THREE_PASS
if (pass == PASS_2)
ip->i_valu -= sp->s_gain;
#endif
if ((sflag & SYM_EXT) && PASS_SYMB)
newsymb(
ip->i_name,
ip->i_type & (S_EXT|S_TYP),
(short)0,
load(ip)
);
}
#endif
if (PASS_SYMB == 0)
return;
#ifndef ASLD
/*
* produce symbol table entries for undefined's
*/
for (i = 0; i<H_SIZE; i++)
for (ip = hashtab[H_LOCAL+i]; ip; ip = ip->i_next) {
if (ip->i_type != (S_EXT|S_UND))
continue;
if (pass != PASS_3)
/*
* save symbol table index
* for possible relocation
*/
ip->i_valu = outhead.oh_nname;
if (sflag & SYM_SCT)
newsymb(
ip->i_name,
S_EXT|S_UND,
(short)0,
(valu_t)0
);
}
#endif ASLD
/*
* produce symbol table entries for sections
*/
if (sflag & SYM_SCT)
for (sp = sect; sp < &sect[outhead.oh_nsect]; sp++) {
ip = sp->s_item;
newsymb(
ip->i_name,
(short)(ip->i_type | S_SCT),
(short)0,
load(ip)
);
}
}

View file

@ -1,528 +0,0 @@
/* @(#)comm5.c 1.1 */
#include "comm0.h"
#include "comm1.h"
#include "y.tab.h"
extern YYSTYPE yylval;
yylex()
{
register c;
if (pass == PASS_1) {
/* scan the input file */
do
c = nextchar();
while (isspace(c) && c != '\n');
if (ISALPHA(c))
c = inident(c);
else if (isdigit(c))
c = innumber(c);
else switch (c) {
case '=':
case '<':
case '>':
case '|':
case '&':
c = induo(c); break;
case ASC_SQUO:
case ASC_DQUO:
c = instring(c); break;
case ASC_COMM:
do
c = nextchar();
while (c != '\n' && c != '\0');
break;
case CTRL('A'):
c = CODE1; readcode(1); break;
case CTRL('B'):
c = CODE2; readcode(2); break;
case CTRL('C'):
c = CODE4; readcode(4); break;
}
/* produce the intermediate token file */
if (c <= 0)
return(0);
if (c <= 127)
putc(c, tempfile);
else
putval(c);
} else {
/* read from intermediate token file */
c = getc(tempfile);
if (c == EOF)
return(0);
if (c > 127) {
c += 128;
c = getval(c);
}
}
return(c);
}
putval(c)
{
register valu_t v;
register n;
register char *p;
assert(c >= 256 && c < 256+128);
switch (c) {
case CODE1:
n = 1; goto putnum;
case CODE2:
n = 2; goto putnum;
case CODE4:
n = 4; goto putnum;
case NUMBER:
v = yylval.y_valu;
for (n = 0; n < sizeof(v); n++) {
if (v == 0)
break;
v >>= 8;
}
c = NUMBER0 + n;
putnum:
putc(c-128, tempfile);
v = yylval.y_valu;
while (--n >= 0)
putc(v >> (n*8), tempfile);
return;
case IDENT:
case FBSYM:
n = sizeof(item_t *);
p = (char *) &yylval.y_item; break;
#ifdef ASLD
case MODULE:
n = sizeof(char *);
p = (char *) &yylval.y_strp; break;
#endif
case STRING:
p = stringbuf;
n = (*p & 0377) + 1; break;
case OP_EQ:
case OP_NE:
case OP_LE:
case OP_GE:
case OP_LL:
case OP_RR:
case OP_OO:
case OP_AA:
n = 0; break;
default:
n = sizeof(word_t);
p = (char *) &yylval.y_word; break;
}
putc(c-128, tempfile);
while (--n >= 0)
putc(*p++, tempfile);
}
getval(c)
{
register n;
register valu_t v;
register char *p;
switch (c) {
case CODE1:
n = 1; goto getnum;
case CODE2:
n = 2; goto getnum;
case CODE4:
n = 4; goto getnum;
case NUMBER0:
n = 0; c = NUMBER; goto getnum;
case NUMBER1:
n = 1; c = NUMBER; goto getnum;
case NUMBER2:
n = 2; c = NUMBER; goto getnum;
case NUMBER3:
n = 3; c = NUMBER; goto getnum;
case NUMBER:
n = 4;
getnum:
v = 0;
while (--n >= 0) {
v <<= 8;
v |= getc(tempfile);
}
yylval.y_valu = v;
return(c);
case IDENT:
case FBSYM:
n = sizeof(item_t *);
p = (char *) &yylval.y_item; break;
#ifdef ASLD
case MODULE:
n = sizeof(char *);
p = (char *) &yylval.y_strp; break;
#endif
case STRING:
p = stringbuf;
#ifdef DUK
*p++ = n = getc(tempfile);
p[n] = '\0';
break;
#else DUK
*p++ = n = getc(tempfile); break;
#endif DUK
case OP_EQ:
case OP_NE:
case OP_LE:
case OP_GE:
case OP_LL:
case OP_RR:
case OP_OO:
case OP_AA:
n = 0; break;
default:
n = sizeof(word_t);
p = (char *) &yylval.y_word; break;
}
while (--n >= 0)
*p++ = getc(tempfile);
return(c);
}
/* ---------- lexical scan in pass 1 ---------- */
nextchar()
{
register c;
if (peekc != -1) {
c = peekc;
peekc = -1;
return(c);
}
#ifdef ASLD
if (archmode && --archsize < 0)
return(0);
#endif
if ((c = getc(input)) == EOF)
return(0);
if (isascii(c) == 0)
fatal("non-ascii character");
#ifdef LISTING
if (listflag & 0440)
putc(c, listfile);
#endif
return(c);
}
readcode(n)
{
register c;
yylval.y_valu = 0;
do {
if (
#ifdef ASLD
(archmode && --archsize < 0)
||
#endif
(c = getc(input)) == EOF
)
fatal("unexpected EOF in compact input");
yylval.y_valu <<= 8;
yylval.y_valu |= c;
} while (--n);
}
induo(c)
register c;
{
static short duo[] = {
('='<<8) | '=', OP_EQ,
('<'<<8) | '>', OP_NE,
('<'<<8) | '=', OP_LE,
('>'<<8) | '=', OP_GE,
('<'<<8) | '<', OP_LL,
('>'<<8) | '>', OP_RR,
('|'<<8) | '|', OP_OO,
('&'<<8) | '&', OP_AA,
};
register short *p;
c = (c<<8) | nextchar();
for (p = duo; *p; p++)
if (*p++ == c)
return(*p++);
peekc = c & 0377;
return(c>>8);
}
inident(c)
char c;
{
register char *p;
register item_t *ip;
p = readident(c);
ip = item_search(p);
if (ip == 0) {
ip = item_alloc(S_UND);
ip->i_name = remember(p);
/* printf("ident %s %o\n", ip->i_name, ip); */
unresolved++;
item_insert(ip, H_LOCAL + (hashindex%H_SIZE));
} else if (hashindex < H_SIZE) {
assert(H_KEY == 0);
yylval.y_word = (word_t) ip->i_valu;
return(ip->i_type);
}
yylval.y_item = ip;
return(IDENT);
}
char *
readident(c)
register c;
{
static char name[NAMEMAX+1];
register n = NAMEMAX;
register char *p = name;
do {
if (--n >= 0)
*p++ = c;
c = nextchar();
} while (ISALNUM(c));
*p++ = '\0';
peekc = c;
return(name);
}
innumber(c)
register c;
{
register char *p;
register radix;
static char num[20+1];
p = num;
radix = 20;
do {
if (--radix < 0)
fatal("number too long");
if (isupper(c))
c += ('a' - 'A');
*p++ = c;
c = nextchar();
} while (ISALNUM(c));
peekc = c;
*p = '\0';
c = *--p;
p = num;
radix = 10;
if (*p == '0') {
radix = 8;
p++;
if (*p == 'x') {
radix = 16;
p++;
} else if (*p == 'b') {
radix = 2;
p++;
}
}
if (radix != 16 && (c == 'f' || c == 'b'))
return(infbsym(num));
yylval.y_valu = 0;
while (c = *p++) {
if (c > '9')
c -= ('a' - '9' - 1);
c -= '0';
if (c >= radix)
serror("digit exceeds radix");
yylval.y_valu = yylval.y_valu * radix + c;
}
return(NUMBER);
}
instring(termc)
{
register char *p;
register c;
p = stringbuf+1;
for (;;) {
c = nextchar();
if (c == '\n' || c == '\0') {
peekc = c;
serror("non-terminated string");
break;
}
if (c == termc)
break;
if (c == '\\')
c = inescape();
#ifdef DUK
if (p >= &stringbuf[STRINGMAX - 1])
#else DUK
if (p >= &stringbuf[STRINGMAX])
#endif DUK
fatal("string buffer overflow");
*p++ = c;
}
stringbuf[0] = p - stringbuf - 1;
#ifdef DUK
*p = '\0';
#endif DUK
return(STRING);
}
inescape()
{
register c, j, r;
c = nextchar();
if (c >= '0' && c <= '7') {
r = c - '0';
for (j = 0; j < 2; j++) {
c = nextchar();
if (c < '0' || c > '7') {
peekc = c;
return(r);
}
r <<= 3;
r += (c - '0');
}
return(r);
}
switch (c) {
case 'b': return('\b');
case 'f': return('\f');
case 'n': return('\n');
case 'r': return('\r');
case 't': return('\t');
case '\'': return('\'');
case '"': return('"');
}
return(c);
}
infbsym(p)
register char *p;
{
register lab;
register item_t *ip;
lab = *p++ - '0';
if ((unsigned)lab < 10) {
if (*p++ == 'f') {
ip = fb_ptr[FB_FORW+lab];
if (ip == 0) {
ip = fb_alloc(lab);
fb_ptr[FB_FORW+lab] = ip;
}
goto ok;
}
ip = fb_ptr[FB_BACK+lab];
if (ip != 0 && *p == 0)
goto ok;
}
serror("bad numeric label");
ip = fb_alloc(0);
ok:
yylval.y_item = ip;
return(FBSYM);
}
hash(p)
register char *p;
{
register unsigned h;
register c;
h = 0;
while (c = *p++) {
h <<= 2;
h += c;
}
return(h % H_SIZE);
}
item_t *
item_search(p)
register char *p;
{
register h;
register item_t *ip;
for (h = hash(p); h < H_TOTAL; h += H_SIZE) {
ip = hashtab[h];
while (ip != 0) {
if (strcmp(p, ip->i_name) == 0)
goto done;
ip = ip->i_next;
}
}
done:
hashindex = h;
return(ip);
}
item_insert(ip, h)
item_t *ip;
{
ip->i_next = hashtab[h];
hashtab[h] = ip;
}
item_t *
item_alloc(typ)
{
register item_t *ip;
static nleft = 0;
static item_t *next;
if (--nleft < 0) {
next = (item_t *) sbrk(MEMINCR);
if ((int) next == -1)
fatal("out of memory");
nleft += (MEMINCR / sizeof(item_t));
}
ip = next++;
ip->i_next = 0;
ip->i_type = typ;
ip->i_name = 0;
ip->i_valu = 0;
return(ip);
}
item_t *
fb_alloc(lab)
register lab;
{
register item_t *ip, *p;
ip = item_alloc(S_UND);
p = fb_ptr[FB_TAIL+lab];
if (p == 0)
fb_ptr[FB_HEAD+lab] = ip;
else
p->i_next = ip;
fb_ptr[FB_TAIL+lab] = ip;
return(ip);
}
item_t *
fb_shift(lab)
register lab;
{
register item_t *ip;
ip = fb_ptr[FB_FORW+lab];
if (ip == 0)
if (pass == PASS_1)
ip = fb_alloc(lab);
else
ip = fb_ptr[FB_HEAD+lab];
fb_ptr[FB_BACK+lab] = ip;
fb_ptr[FB_FORW+lab] = ip->i_next;
return(ip);
}

View file

@ -1,362 +0,0 @@
/* @(#)comm6.c 1.7 */
/*
* implement pseudo instructions
*/
#include "comm0.h"
#include "comm1.h"
#include "y.tab.h"
newequate(ip, typ)
register item_t *ip;
register short typ;
{
typ &= ~S_EXT;
if (typ & S_COM)
typ = S_UND;
else if ((typ & S_VAR) && (typ & S_TYP) != S_ABS)
typ = S_UND;
#ifdef THREE_PASS
else if (pass == PASS_1 && typ == S_UND)
typ = S_VAR;
else if (pass == PASS_2 && (ip->i_type & S_TYP) == S_UND)
ip->i_type |= typ;
#endif THREE_PASS
if (typ == S_UND)
serror("illegal equate");
if (pass == PASS_3)
assert((ip->i_type & S_TYP) == (typ & S_TYP));
newident(ip, typ);
}
newident(ip, typ)
register item_t *ip;
{
register flag;
#ifdef GENLAB
static char genlab[] = GENLAB;
#endif GENLAB
if (pass == PASS_1) {
/* printf("declare %s: %o\n", ip->i_name, typ); */
if (ip->i_type & ~S_EXT)
serror("multiple declared");
else
--unresolved;
ip->i_type |= typ;
}
if (PASS_SYMB == 0)
return;
#ifdef THREE_PASS
if (ip->i_type & S_EXT)
flag = SYM_EXT;
else
flag = SYM_LOC;
#else
flag = SYM_EXT|SYM_LOC; /* S_EXT not stable in PASS_1 */
#endif THREE_PASS
#ifdef GENLAB
if (strncmp(ip->i_name, genlab, sizeof(genlab)-1) == 0)
flag = SYM_LAB;
#endif GENLAB
if (sflag & flag)
newsymb(
ip->i_name,
ip->i_type & (S_EXT|S_TYP),
(short)0,
load(ip)
);
}
newlabel(ip)
register item_t *ip;
{
#ifdef THREE_PASS
register addr_t oldval = ip->i_valu;
#endif
if (DOTSCT == NULL)
nosect();
ip->i_type &= ~S_TYP;
ip->i_type |= DOTTYP;
if (store(ip, (valu_t) DOTVAL) == 0)
return;
#ifdef THREE_PASS
assert(pass != PASS_2 || oldval - ip->i_valu == DOTGAIN);
#endif
}
newsect(ip)
register item_t *ip;
{
register ushort typ;
register sect_t *sp = NULL;
typ = ip->i_type & S_TYP;
if (typ == S_UND) {
/*
* new section
*/
assert(pass == PASS_1);
--unresolved;
typ = outhead.oh_nsect + S_MIN;
outhead.oh_nsect++;
if (outhead.oh_nsect > SECTMAX || typ > S_MAX)
fatal("too many sections");
sp = &sect[typ - S_MIN];
sp->s_item = ip;
sp->s_lign = ALIGNSECT;
#ifdef DUK
ip->i_type = typ;
#else DUK
ip->i_type = typ | S_EXT;
#endif DUK
ip->i_valu = 0;
} else if (typ >= S_MIN) {
sp = &sect[typ - S_MIN];
if (sp->s_item != ip)
sp = NULL;
}
if (sp == NULL)
serror("multiple declared");
else
switchsect(typ);
}
newbase(base)
valu_t base;
{
#ifdef ASLD
register sect_t *sp;
if ((sp = DOTSCT) == NULL)
nosect();
if (sp->s_flag & BASED)
serror("already based");
sp->s_base = base;
sp->s_flag |= BASED;
DOTVAL += base;
#else
warning(".base ignored");
#endif
}
/*
* NOTE: A rather different solution is used for ASLD and NOLD:
* ASLD:
* - maximum length of .comm is recorded in i_valu during PASS_1
* - address of .comm is recorded in i_valu in later passes:
* assigned at end of PASS_1, corrected for s_gain at end of PASS_2
* - symbol table entries are produced in commfinish()
* NOLD:
* - i_valu cannot be used since it is needed for relocation info
* - only one .comm with a particular symbol is allowed per module
* - symbol table entries are produced in newcomm()
*/
newcomm(ip, val)
register item_t *ip;
valu_t val;
{
if (pass == PASS_1) {
if (DOTSCT == NULL)
nosect();
if (val == 0)
serror("bad size");
/* printf("declare %s: %o\n", ip->i_name, DOTTYP); */
if ((ip->i_type & ~S_EXT) == S_UND) {
--unresolved;
ip->i_type = S_COM|S_EXT|DOTTYP;
#ifdef ASLD
ip->i_valu = val;
} else if (ip->i_type == (S_COM|S_EXT|DOTTYP)) {
if (ip->i_valu < val)
ip->i_valu = val;
#endif
} else
serror("multiple declared");
}
#ifndef ASLD
if (PASS_SYMB == 0)
return;
if (pass != PASS_3)
/*
* save symbol table index
* for possible relocation
*/
ip->i_valu = outhead.oh_nname;
#ifdef DUK
newsymb(ip->i_name, S_COM|S_EXT|DOTTYP, (short)0, val);
#else DUK
newsymb(ip->i_name, S_EXT|DOTTYP, (short)0, val);
#endif DUK
#endif
}
switchsect(newtyp)
short newtyp;
{
register sect_t *sp;
if (sp = DOTSCT)
sp->s_size = DOTVAL - sp->s_base;
if (newtyp == S_UND) {
DOTSCT = NULL;
DOTTYP = newtyp;
return;
}
assert(newtyp >= S_MIN);
sp = &sect[newtyp - S_MIN];
if (pass == PASS_3) {
#ifdef AOUTSEEK
aoutpart = -1;
aoutseek[PARTEMIT] = sp->s_foff + sp->s_size - sp->s_zero;
#else
fseek(aoutfile[PARTEMIT], sp->s_foff + sp->s_size - sp->s_zero, 0);
#endif
}
DOTVAL = sp->s_size + sp->s_base;
DOTSCT = sp;
DOTTYP = newtyp;
}
align(bytes)
valu_t bytes;
{
register valu_t gap;
register sect_t *sp;
if ((sp = DOTSCT) == NULL)
nosect();
if (bytes == 0)
bytes = ALIGNWORD;
if (sp->s_lign % bytes)
if (bytes % sp->s_lign)
serror("illegal alignment");
else
sp->s_lign = bytes;
if (pass == PASS_1)
/*
* be pessimistic: biggest gap possible
*/
gap = bytes - 1;
else {
/*
* calculate gap correctly;
* will be the same in PASS_2 and PASS_3
*/
if ((gap = DOTVAL % bytes) != 0)
gap = bytes - gap;
#ifdef THREE_PASS
if (pass == PASS_2)
/*
* keep track of gain with respect to PASS_1
*/
DOTGAIN += (bytes - 1) - gap;
#endif
}
DOTVAL += gap;
sp->s_zero += gap;
}
#ifdef RELOCATION
newrelo(s, n)
short s;
{
struct outrelo outrelo;
#ifdef DUK
int iscomm;
#endif DUK
if (rflag == 0)
return;
if (PASS_RELO == 0)
return;
s &= ~S_DOT;
assert((s & ~(S_COM|S_VAR|S_TYP)) == 0);
#ifndef THREE_PASS
if (s == S_UND)
serror("bad relocation");
#endif
/*
* always relocation info if S_VAR to solve problems with:
* move b,d0
* b=a
* a: .data2 0
*/
#ifdef DUK
iscomm = s & S_COM;
#endif DUK
s &= ~S_COM;
if ((n & RELPC) == 0 && s == S_ABS)
return;
if ((n & RELPC) != 0 && s == DOTTYP)
return;
if (pass != PASS_3) {
outhead.oh_nrelo++;
return;
}
s &= ~S_VAR;
outrelo.or_type = (char)n;
outrelo.or_sect = (char)DOTTYP;
#ifndef ASLD
#ifdef DUK
if (s == S_UND || iscomm) {
#else DUK
if (s == S_UND) {
#endif DUK
assert(relonami != 0);
outrelo.or_nami = relonami-1;
relonami = 0;
} else
#endif
if (s < S_MIN) {
assert(s == S_ABS);
/*
* use first non existing entry (argh)
*/
outrelo.or_nami = outhead.oh_nname;
} else {
/*
* section symbols are at the end
*/
outrelo.or_nami = outhead.oh_nname
- outhead.oh_nsect
+ (s - S_MIN)
;
}
outrelo.or_addr = (long)DOTVAL;
putofmt((char *)&outrelo, SF_RELO, PARTRELO);
}
#endif
newsymb(name, type, desc, valu)
register char *name;
short type;
short desc;
valu_t valu;
{
struct outname outname;
if (name && *name == 0)
name = 0;
assert(PASS_SYMB);
if (pass != PASS_3) {
if (name)
outhead.oh_nchar += strlen(name)+1;
outhead.oh_nname++;
return;
}
if (name) {
AOUTPART(PARTCHAR);
outname.on_foff = outhead.oh_nchar;
do {
AOUTPUTC(*name, PARTCHAR);
outhead.oh_nchar++;
} while (*name++);
} else
outname.on_foff = 0;
outname.on_type = type;
outname.on_desc = desc;
outname.on_valu = valu & ~((0xFFFFFFFF)<<(8*sizeof(valu_t)));
putofmt((char *)&outname, SF_NAME, PARTNAME);
}

View file

@ -1,430 +0,0 @@
/* @(#)comm7.c 1.10 */
/*
* miscellaneous
*/
#include "comm0.h"
#include "comm1.h"
#include "y.tab.h"
valu_t
load(ip)
register item_t *ip;
{
#ifdef ASLD
register short typ;
typ = ip->i_type & S_TYP;
if ((typ -= S_MIN) < 0) /* S_UND or S_ABS */
return(ip->i_valu);
return(ip->i_valu + sect[typ].s_base);
#else
#ifdef DUK
if ((ip->i_type & S_TYP) == S_UND || (ip->i_type & S_COM)) {
#else DUK
if ((ip->i_type & S_TYP) == S_UND) {
#endif DUK
if (pass == PASS_3) {
if (relonami != 0)
serror("relocation error");
relonami = ip->i_valu+1;
}
return(0);
}
return(ip->i_valu);
#endif
}
store(ip, val)
register item_t *ip;
valu_t val;
{
#ifdef ASLD
register short typ;
typ = ip->i_type & S_TYP;
if ((typ -= S_MIN) >= 0)
val -= sect[typ].s_base;
#else
if ((ip->i_type & S_TYP) == S_UND)
return(0);
#endif
assert(pass != PASS_3 || (ip->i_type & S_VAR) || ip->i_valu == val);
ip->i_valu = val;
return(1);
}
char *
remember(s)
register char *s;
{
register char *p;
register n;
static nleft = 0;
static char *next;
p = s;
n = 0;
do
n++;
while (*p++);
if ((nleft -= n) < 0) {
next = sbrk(MEMINCR);
if ((int) next == -1)
fatal("out of memory");
nleft = (MEMINCR / sizeof(char)) - n;
assert(nleft >= 0);
}
p = next;
while (*p++ = *s++)
;
s = next;
next = p;
return(s);
}
combine(typ1, typ2, op)
register typ1, typ2;
{
switch (op) {
case '+':
if (typ1 == S_ABS)
return(typ2);
if (typ2 == S_ABS)
return(typ1);
break;
case '-':
if (typ2 == S_ABS)
return(typ1);
if ((typ1 & ~S_DOT) == (typ2 & ~S_DOT) && typ1 != S_UND)
return(S_ABS|S_VAR);
break;
case '>':
if (typ1 == S_ABS && typ2 == S_ABS)
return(S_ABS);
if (
((typ1 & ~S_DOT) == (typ2 & ~S_DOT) && typ1 != S_UND)
|| (typ1 == S_ABS)
|| (typ2 == S_ABS)
)
return(S_ABS|S_VAR);
break;
default:
if (typ1 == S_ABS && typ2 == S_ABS)
return(S_ABS);
break;
}
if (pass != PASS_1)
serror("illegal operator");
return(S_UND);
}
#ifdef LISTING
printx(ndig, val)
valu_t val;
{
static char buf[8];
register char *p;
register c, n;
p = buf; n = ndig;
do {
*p++ = (int) val & 017;
val >>= 4;
} while (--n);
do {
c = "0123456789ABCDEF"[*--p];
putchar(c);
} while (p > buf);
return(ndig);
}
#endif
#ifdef LISTING
listline(textline)
{
register c;
if ((listflag & 4) && (c = getc(listfile)) != '\n' && textline) {
if (listcolm >= 24)
printf(" \\\n\t\t\t");
else
do {
putchar('\t');
listcolm += 8;
} while (listcolm < 24);
do {
assert(c != EOF);
putchar(c);
} while ((c = getc(listfile)) != '\n');
}
if (listflag & 7)
putchar('\n');
listeoln = 1;
listcolm = 0;
listflag = listtemp;
}
#endif LISTING
/* ---------- code optimization ---------- */
#ifdef THREE_PASS
small(fitsmall, gain)
{
register bit;
register char *p;
if (DOTSCT == NULL)
nosect();
if (bflag)
return(0);
if ((bit = nbits++) >= BITMAX) {
if (bit != BITMAX)
nbits--; /* prevent wraparound */
else if (pass == PASS_1)
warning("bit table overflow");
return(0);
}
p = &bittab[bit>>3];
bit = 1 << (bit&7);
switch (pass) {
case PASS_1:
return(0);
case PASS_2:
if (fitsmall) {
DOTGAIN += gain;
*p |= bit;
}
return(fitsmall);
case PASS_3:
assert(fitsmall || (*p & bit) == 0);
return(*p & bit);
}
}
#endif
/* ---------- output ---------- */
emit1(arg)
char arg;
{
#ifdef LISTING
if (listeoln) {
if (listflag & 1) {
listcolm += printx(VALWIDTH, DOTVAL);
listcolm++;
putchar(' ');
}
listeoln = 0;
}
if (listflag & 2)
listcolm += printx(2, (valu_t) arg);
#endif
switch (pass) {
case PASS_1:
if (DOTSCT == NULL)
nosect();
/* no break */
case PASS_2:
DOTSCT->s_zero = 0;
break;
case PASS_3:
AOUTPART(PARTEMIT);
while (DOTSCT->s_zero) {
AOUTPUTC(0, PARTEMIT);
DOTSCT->s_zero--;
}
AOUTPUTC(arg, PARTEMIT);
break;
}
DOTVAL++;
}
emit2(arg)
short arg;
{
#ifdef BYTES_REVERSED
emit1((char)(arg>>8)); emit1((char)arg);
#else
emit1((char)arg); emit1((char)(arg>>8));
#endif
}
emit4(arg)
long arg;
{
#ifdef WORDS_REVERSED
emit2((short)(arg>>16)); emit2((short)(arg));
#else
emit2((short)(arg)); emit2((short)(arg>>16));
#endif
}
emitx(val, n)
valu_t val;
register n;
{
switch (n) {
case 1:
emit1((char)val); break;
case 2:
emit2((short)val); break;
case 4:
emit4((long)val); break;
default:
assert(0);
}
}
emitstr(zero)
{
register i;
register char *p;
p = stringbuf;
i = *p++ & 0377;
while (--i >= 0)
emit1(*p++);
if (zero)
emit1(0);
}
/* ---------- Error checked file I/O ---------- */
ffreopen(s, f)
char *s;
FILE *f;
{
if (freopen(s, "r", f) == NULL)
fatal("can't reopen %s", s);
}
FILE *
ffcreat(s)
char *s;
{
FILE *f;
if ((f = fopen(s, "w")) == NULL)
fatal("can't create %s", s);
return(f);
}
FILE *
fftemp(path, tail)
char *path;
{
register char *dir;
if ((dir = getenv("TMPDIR")) == NULL)
#ifdef TMPDIR
dir = TMPDIR;
#else
dir = "/tmp";
#endif
sprintf(path, "%s/%s", dir, tail);
return(ffcreat(mktemp(path)));
}
putofmt(p, s, part)
register char *p;
register char *s;
{
register i;
register long l;
AOUTPART(part);
while (i = *s++) {
switch (i -= '0') {
/* case 0: p++; break; */
case 1:
l = (long) *((char *)p); p += sizeof(char );
break;
case 2:
l = (long) *((short *)p); p += sizeof(short);
break;
case 4:
l = (long) *((long *)p); p += sizeof(long );
break;
default:
assert(0);
}
while (--i >= 0) {
AOUTPUTC((int)l, part);
l >>= 8;
}
}
}
/* ---------- Error handling ---------- */
yyerror(){} /* we will do our own error printing */
nosect()
{
fatal("no sections");
}
werror()
{
fatal("write error");
}
/* VARARGS1 */
fatal(s, a1, a2, a3, a4)
char *s;
{
nerrors++;
diag(" (fatal)\n", s, a1, a2, a3, a4);
stop();
}
#if DEBUG == 2
assert2(file, line)
char *file;
{
fatal("assertion failed (%s, %d)", file, line);
}
#endif
#if DEBUG == 1
assert1()
{
diag(" (fatal)\n", "assertion failed");
abort();
}
#endif
/* VARARGS1 */
serror(s, a1, a2, a3, a4)
char *s;
{
nerrors++;
diag("\n", s, a1, a2, a3, a4);
}
/* VARARGS1 */
warning(s, a1, a2, a3, a4)
char *s;
{
diag(" (warning)\n", s, a1, a2, a3, a4);
}
/* VARARGS1 */
diag(tail, s, a1, a2, a3, a4)
char *tail, *s;
{
fflush(stdout);
if (modulename)
fprintf(stderr, "\"%s\", line %d: ", modulename, lineno);
else
fprintf(stderr, "%s: ", progname);
fprintf(stderr, s, a1, a2, a3, a4);
fprintf(stderr, tail);
}
nofit()
{
if (pass == PASS_3)
warning("too big");
}

View file

@ -1,9 +0,0 @@
/* @(#)comm8.c 1.1 */
#include "comm0.h"
#include "comm1.h"
#include "y.tab.h"
/* ========== Machine dependent C routines ========== */
#include "mach5.c"

View file

@ -116,6 +116,10 @@ fixregvars(saveall) {
}
}
f_regsave();
#ifndef TEM_BSIZE
for(rv=rvlist;rv!=0;rv=rv->rv_next)
if (rv->rv_off >= 0) rv->rv_off += TEM_BSIZE;
#endif
}
isregvar(off) long off; {

View file

@ -20,7 +20,14 @@ typedef char * string;
#define full int
#endif
#if TEM_WSIZE>2
#define word long
#ifndef WRD_FMT
#define WRD_FMT "%ld"
#define WRD_FMT "%D"
#endif WRD_FMT
#else
#define word int
#ifndef WRD_FMT
#define WRD_FMT "%d"
#endif WRD_FMT
#endif

View file

@ -392,14 +392,14 @@ if(Debug>1) fprintf(stderr,"Next tuple %d,%d,%d,%d\n",
ntup = tup->p_next;
for (i=0,t=0;i<nregneeded && t<mincost; i++)
t += docoerc(regtp[i],regcp[i],ply,FALSE,tup->p_rar[i]);
if ( t<mincost && tokpatlen<=stackheight ) {
if (t<mincost) {
#ifndef NDEBUG
if (Debug>2)
fprintf(stderr,"Continuing match after coercions\n");
#endif
t += codegen(codep,ply,FALSE,mincost-t,0);
}
if ( t<mincost && tokpatlen<=stackheight ) {
if (t<mincost) {
mincost = t;
besttup = tup;
} else
@ -480,7 +480,6 @@ normalfailed: if (stackpad!=tokpatlen) {
result=compute(&enodes[nodeno]);
if (result.e_typ!=EV_REG)
break;
if ( in_stack(result.e_v.e_reg) ) BROKE() ; /* Check aside-stack */
for (tp= &fakestack[stackheight-tokpatlen-1];tp>=&fakestack[0];tp--)
if (tp->t_token==-1) {
if(tp->t_att[0].ar==result.e_v.e_reg)

View file

@ -96,9 +96,7 @@ move(tp1,tp2,ply,toplevel,maxcost) token_p tp1,tp2; unsigned maxcost; {
fakestack[stackheight] = *tp2;
fakestack[stackheight+1] = *tp1;
stackheight += 2;
tokpatlen += 2;
t = codegen(&coderules[mp->m_cindex],ply,toplevel,maxcost,0);
tokpatlen -= 2;
stackheight -= 2;
return(t);
}
@ -145,9 +143,7 @@ test(tp,ply,toplevel,maxcost) token_p tp; unsigned maxcost; {
fakestack[stackheight] = *tp;
stackheight++;
tokpatlen++;
t = codegen(&coderules[mp->t_cindex],ply,toplevel,maxcost,0);
tokpatlen--;
stackheight--;
return(t);
}

View file

@ -392,66 +392,6 @@ tref(tp,amount) register token_p tp; {
}
#define MAXSAVE 10
/* A few routines to save the top of the current stack,
restore it and check whether a certain register is present in the
saved stack
*/
token_t aside[MAXSAVE] ;
int aside_length = -1 ;
save_stack(tp) register token_p tp ; {
int i ;
aside_length = &fakestack[stackheight-1] -tp;
assert(aside_length<=MAXSAVE);
#ifndef NDEBUG
if (aside_length!=0 && Debug>1)
fprintf(stderr,"Saving %d items from fakestack\n",aside_length);
#endif
for (i=1;i<=aside_length;i++)
aside[i-1] = tp[i];
stackheight -= aside_length;
}
in_stack(reg) {
register token_p tp ;
register i ;
register tkdef_p tdp ;
for ( i=0, tp=aside ; i<aside_length ; i++, tp++ )
if (tp->t_token==-1) {
if(tp->t_att[0].ar==reg)
goto gotone ;
} else {
tdp = &tokens[tp->t_token];
for(i=0;i<TOKENSIZE;i++)
if (tdp->t_type[i]==EV_REG &&
tp->t_att[i].ar==reg)
goto gotone ;
}
return 0 ;
gotone:
#ifndef NDEBUG
if ( Debug>2 )
fprintf(stderr,"Register %d present on non-visible stack\n",
reg ) ;
#endif
return 1 ;
}
rest_stack() {
register int i ;
assert(aside_length!= -1);
#ifndef NDEBUG
if (aside_length!=0 && Debug>1)
fprintf(stderr,"Restoring %d items to fakestack(%d)\n",
aside_length,stackheight);
#endif
for (i=0;i<aside_length;i++)
fakestack[stackheight++] = aside[i];
aside_length= -1 ;
}
#ifdef MAXSPLIT
split(tp,ip,ply,toplevel) token_p tp; register int *ip; {
@ -478,26 +418,49 @@ split(tp,ip,ply,toplevel) token_p tp; register int *ip; {
return(0);
found:
assert(stackheight+cp->c2_nsplit-1<MAXFSTACK);
save_stack(tp);
stp = &fakestack[stackheight-1];
diff = stp - tp;
assert(diff<=MAXSAVE);
for (i=1;i<=diff;i++)
savestack[i-1] = tp[i]; /* save top of stack */
stackheight -= diff;
tpl = tokpatlen;
tokpatlen = 1;
codegen(&coderules[cp->c2_codep],ply,toplevel,MAXINT,0);
tokpatlen = tpl;
rest_stack();
for (i=0;i<diff;i++) /* restore top of stack */
fakestack[stackheight++] = savestack[i];
return(cp->c2_nsplit);
}
#endif MAXSPLIT
unsigned docoerc(tp,cp,ply,toplevel,forced) token_p tp; register c3_p cp; {
token_t savestack[MAXSAVE];
token_p stp;
register int i,diff;
unsigned cost;
int tpl; /* saved tokpatlen */
save_stack(tp) ;
stp = &fakestack[stackheight-1];
diff = stp -tp;
assert(diff<=MAXSAVE);
#ifndef NDEBUG
if (diff!=0 && Debug>1)
fprintf(stderr,"Saving %d items from fakestack\n",diff);
#endif
for (i=1;i<=diff;i++)
savestack[i-1] = tp[i];
stackheight -= diff;
tpl = tokpatlen;
tokpatlen = 1;
cost = codegen(&coderules[cp->c3_codep],ply,toplevel,MAXINT,forced);
tokpatlen = tpl;
rest_stack() ;
#ifndef NDEBUG
if (diff!=0 && Debug>1)
fprintf(stderr,"Restoring %d items to fakestack(%d)\n",diff,stackheight);
#endif
for (i=0;i<diff;i++)
fakestack[stackheight++] = savestack[i];
nallreg = 0;
return(cost);
}

View file

@ -20,4 +20,8 @@ typedef char * string;
#define full int
#endif
#if TEM_WSIZE>2
#define word long
#else
#define word int
#endif

View file

@ -1,53 +0,0 @@
# $Header$
EM = ../../..
h = $(EM)/h
CDIR = $(EM)/mach/proto/nas
CPP = $(EM)/lib/cpp
DEF =
FFLAG =
CFLAGS = $(FFLAG) -O -I$h $(DEF)
YFLAGS = -d
LDFLAGS = $(FFLAG) -i
CSRC = $(CDIR)/comm3.c $(CDIR)/comm4.c $(CDIR)/comm5.c \
$(CDIR)/comm6.c $(CDIR)/comm7.c $(CDIR)/comm8.c
COBJ = $(CDIR)/comm3.o $(CDIR)/comm4.o $(CDIR)/comm5.o \
$(CDIR)/comm6.o $(CDIR)/comm7.o $(CDIR)/comm8.o
MACH = mach0.c mach1.c mach2.c mach3.c mach4.c mach5.c
COMM = $(CDIR)/comm0.h $(CDIR)/comm1.h $(CDIR)/comm2.y $(CSRC)
all: as
install:all
../../install as
cmp:
-../../compare as
clean:
rm -f *.o as as.[cy] y.tab.h
pr: $(MACH)
@pr -n $(MACH)
opr:
make pr | opr
as: $(COBJ) as.o
$(CC) $(LDFLAGS) $(COBJ) as.o -o as
as.y: $(CDIR)/comm2.y
$(CPP) -P -I$h $(DEF) $(CDIR)/comm2.y >as.y
@echo "expect 1 shift/reduce conflict"
lint: $(CSRC) as.c
lint $(CSRC) as.c
y.tab.h: as.c
$(COBJ): y.tab.h
$(COBJ) as.y: $(CDIR)/comm0.h mach0.c
$(COBJ) as.y: $(CDIR)/comm1.h mach1.c
as.y: mach2.c
comm3.o: mach3.c
as.y: mach4.c
comm8.o: mach5.c

View file

@ -1,53 +0,0 @@
# $Header$
EM = ../../..
h = $(EM)/h
CDIR = $(EM)/mach/proto/nas
CPP = $(EM)/lib/cpp
DEF =
FFLAG =
CFLAGS = $(FFLAG) -O -I$h $(DEF)
YFLAGS = -d
LDFLAGS = $(FFLAG) -i
CSRC = $(CDIR)/comm3.c $(CDIR)/comm4.c $(CDIR)/comm5.c \
$(CDIR)/comm6.c $(CDIR)/comm7.c $(CDIR)/comm8.c
COBJ = $(CDIR)/comm3.o $(CDIR)/comm4.o $(CDIR)/comm5.o \
$(CDIR)/comm6.o $(CDIR)/comm7.o $(CDIR)/comm8.o
MACH = mach0.c mach1.c mach2.c mach3.c mach4.c mach5.c
COMM = $(CDIR)/comm0.h $(CDIR)/comm1.h $(CDIR)/comm2.y $(CSRC)
all: as
install:all
../../install as
cmp:
-../../compare as
clean:
rm -f *.o as as.[cy] y.tab.h
pr: $(MACH)
@pr -n $(MACH)
opr:
make pr | opr
as: $(COBJ) as.o
$(CC) $(LDFLAGS) $(COBJ) as.o -o as
as.y: $(CDIR)/comm2.y
$(CPP) -P -I$h $(DEF) $(CDIR)/comm2.y >as.y
@echo "expect 1 shift/reduce conflict"
lint: $(CSRC) as.c
lint $(CSRC) as.c
y.tab.h: as.c
$(COBJ): y.tab.h
$(COBJ) as.y: $(CDIR)/comm0.h mach0.c
$(COBJ) as.y: $(CDIR)/comm1.h mach1.c
as.y: mach2.c
comm3.o: mach3.c
as.y: mach4.c
comm8.o: mach5.c

View file

@ -1,53 +0,0 @@
# $Header$
EM = ../../..
h = $(EM)/h
CDIR = $(EM)/mach/proto/nas
CPP = $(EM)/lib/cpp
DEF =
FFLAG =
CFLAGS = $(FFLAG) -O -I$h $(DEF)
YFLAGS = -d
LDFLAGS = $(FFLAG) -i
CSRC = $(CDIR)/comm3.c $(CDIR)/comm4.c $(CDIR)/comm5.c \
$(CDIR)/comm6.c $(CDIR)/comm7.c $(CDIR)/comm8.c
COBJ = $(CDIR)/comm3.o $(CDIR)/comm4.o $(CDIR)/comm5.o \
$(CDIR)/comm6.o $(CDIR)/comm7.o $(CDIR)/comm8.o
MACH = mach0.c mach1.c mach2.c mach3.c mach4.c mach5.c
COMM = $(CDIR)/comm0.h $(CDIR)/comm1.h $(CDIR)/comm2.y $(CSRC)
all: as
install:all
../../install as
cmp:
-../../compare as
clean:
rm -f *.o as as.[cy] y.tab.h
pr: $(MACH)
@pr -n $(MACH)
opr:
make pr | opr
as: $(COBJ) as.o
$(CC) $(LDFLAGS) $(COBJ) as.o -o as
as.y: $(CDIR)/comm2.y
$(CPP) -P -I$h $(DEF) $(CDIR)/comm2.y >as.y
@echo "expect 1 shift/reduce conflict"
lint: $(CSRC) as.c
lint $(CSRC) as.c
y.tab.h: as.c
$(COBJ): y.tab.h
$(COBJ) as.y: $(CDIR)/comm0.h mach0.c
$(COBJ) as.y: $(CDIR)/comm1.h mach1.c
as.y: mach2.c
comm3.o: mach3.c
as.y: mach4.c
comm8.o: mach5.c

View file

@ -1,28 +0,0 @@
.define putchr
! output routine in monitor
CRT = 0x013B
! output a charcter
! entry: ascii character in a
putchr:
push hl
push bc
ld hl,tab
ld b,5
1: cp (hl)
jr z,fetch
inc hl
inc hl
djnz 1b
2: call CRT
pop bc
pop hl
ret
fetch: inc hl
ld a,(hl)
jr 2b
! conversion table for nascom characters
tab: .byte 0x0D,0x00
.byte 0x1B,0x1E
.byte 0x08,0x1D
.byte 0x0A,0x1F
.byte 0x7F,0x00

View file

@ -1,21 +0,0 @@
.define putchr
putchr:
push hl
push de
push bc
cp 0x0A
jr nz,1f
ld a,0x1F
1:
ld c,a
2:
in a,0xF1
and 4
jr z,2b
ld a,c
out 0xF0,a
pop bc
pop de
pop hl
ret

View file

@ -1,197 +0,0 @@
.define _read,_write,_ioctl,_getpid,_open,_close,_exit,_errno
_read:
ld (savebc),bc
push af
pop bc
ld (saveaf),bc ! save all registers in savereg
ld (savede),de
ld (savehl),hl
ld (saveix),ix
ex (sp),hl ! return address in hl
pop bc ! skip return address
pop bc ! get fd
ld a,b ! check fd = 0
or c
jr nz,errrd
pop de ! get buffer
pop bc ! get count
ld ix,0 ! reset counter
push bc
push de
push ix
push hl ! return address
ex de,hl ! buffer to hl
1: ld a,b
or c
jr z,done ! done if count = 0
call getchr
ld (hl),a
inc hl ! increment pointer
inc ix ! increment char counter
dec bc ! decrement count
cp 0xA
jr nz,1b ! done if char = CR
done:
ld bc,(saveaf)
push bc
pop af
ld bc,(savebc)
ld de,(savede)
ld hl,(savehl)
ld ix,(saveix)
ret
errrd:
push bc
push hl ! return address
ld bc,(saveaf)
push bc
pop af
ld bc,(savebc)
ld de,(savede)
ld hl,(savehl)
ld ix,(saveix)
ld ix,-1
ret
_write:
ld (savebc),bc
push af
pop bc
ld (saveaf),bc ! save all registers in savereg
ld (savede),de
ld (savehl),hl
ld (saveix),ix
ex (sp),hl ! return address in hl
pop de ! skip return address
pop de ! get fd
ld a,e ! check for fd = 1
cp 1
jr nz,errwr
ld a,d
or a
jr nz,errwr
pop de ! buffer in de
pop bc ! count in bc
push bc
push de
push de
push hl
ex de,hl ! buffer in hl
ld e,c
ld d,b ! count also in de
1: ld a,b
or c
jr z,exit
ld a,(hl)
call putchr
inc hl
dec bc
jr 1b
errwr:
push de
push hl
ld bc,(saveaf)
push bc
pop af
ld bc,(savebc)
ld de,(savede)
ld hl,(savehl)
ld ix,(saveix)
ld ix,-1 ! error in fd
ret
exit:
push de ! count on stack
ld bc,(saveaf)
push bc
pop af
ld bc,(savebc)
ld de,(savede)
ld hl,(savehl)
ld ix,(saveix)
pop ix ! return count to caller
ret
_ioctl:
ret
_getpid:
ret
! open return a file descriptor (0,1,2)
! depending on 'mode'
! mode 2 doesn't work!!
_open:
ld (savebc),bc
push af
pop bc
ld (saveaf),bc ! save all registers in savereg
ld (savede),de
ld (savehl),hl
ld (saveix),ix
pop bc ! return address
pop de ! name pointer
pop ix ! mode (0 for read,
! 1 for write)
push ix
push de
push bc
ld bc,(saveaf)
push bc
pop af
ld bc,(savebc)
ld de,(savede)
ld hl,(savehl)
ld ix,(saveix)
ret ! return fd = 0 for read
! fd = 1 for write
_close:
ld ix,0 ! return succes
ret
_exit:
jp 0x38
.data
_errno:
.word 0
! output routine in monitor
CRT = 0x013B
! output a charcter
! entry: ascii character in a
.text
!putchr:
! push hl
! push bc
! ld hl,tab
! ld b,5
!1: cp (hl)
! jr z,fetch
! inc hl
! inc hl
! djnz 1b
!2: call CRT
! pop bc
! pop hl
! ret
!fetch: inc hl
! ld a,(hl)
! jr 2b
!! conversion table for nascom characters
!tab: .byte 0x0D,0x00
! .byte 0x1B,0x1E
! .byte 0x08,0x1D
! .byte 0x0A,0x1F
! .byte 0x7F,0x00
KBD = 0x69
! get character from keyboard
getchr:
call KBD
jr nc,getchr
cp 0x1F
jr z,CR
cp 0x1D
jr z,BS
ret
CR: ld a,0xA
ret
BS: ld a,0x8
ret

View file

@ -1,28 +0,0 @@
.define putchr
! output routine in monitor
CRT = 0x013B
! output a charcter
! entry: ascii character in a
putchr:
push hl
push bc
ld hl,tab
ld b,5
1: cp (hl)
jr z,fetch
inc hl
inc hl
djnz 1b
2: call CRT
pop bc
pop hl
ret
fetch: inc hl
ld a,(hl)
jr 2b
! conversion table for nascom characters
tab: .byte 0x0D,0x00
.byte 0x1B,0x1E
.byte 0x08,0x1D
.byte 0x0A,0x1F
.byte 0x7F,0x00

View file

@ -1,21 +0,0 @@
.define putchr
putchr:
push hl
push de
push bc
cp 0x0A
jr nz,1f
ld a,0x1F
1:
ld c,a
2:
in a,0xF1
and 4
jr z,2b
ld a,c
out 0xF0,a
pop bc
pop de
pop hl
ret

View file

@ -1,197 +0,0 @@
.define _read,_write,_ioctl,_getpid,_open,_close,_exit,_errno
_read:
ld (savebc),bc
push af
pop bc
ld (saveaf),bc ! save all registers in savereg
ld (savede),de
ld (savehl),hl
ld (saveix),ix
ex (sp),hl ! return address in hl
pop bc ! skip return address
pop bc ! get fd
ld a,b ! check fd = 0
or c
jr nz,errrd
pop de ! get buffer
pop bc ! get count
ld ix,0 ! reset counter
push bc
push de
push ix
push hl ! return address
ex de,hl ! buffer to hl
1: ld a,b
or c
jr z,done ! done if count = 0
call getchr
ld (hl),a
inc hl ! increment pointer
inc ix ! increment char counter
dec bc ! decrement count
cp 0xA
jr nz,1b ! done if char = CR
done:
ld bc,(saveaf)
push bc
pop af
ld bc,(savebc)
ld de,(savede)
ld hl,(savehl)
ld ix,(saveix)
ret
errrd:
push bc
push hl ! return address
ld bc,(saveaf)
push bc
pop af
ld bc,(savebc)
ld de,(savede)
ld hl,(savehl)
ld ix,(saveix)
ld ix,-1
ret
_write:
ld (savebc),bc
push af
pop bc
ld (saveaf),bc ! save all registers in savereg
ld (savede),de
ld (savehl),hl
ld (saveix),ix
ex (sp),hl ! return address in hl
pop de ! skip return address
pop de ! get fd
ld a,e ! check for fd = 1
cp 1
jr nz,errwr
ld a,d
or a
jr nz,errwr
pop de ! buffer in de
pop bc ! count in bc
push bc
push de
push de
push hl
ex de,hl ! buffer in hl
ld e,c
ld d,b ! count also in de
1: ld a,b
or c
jr z,exit
ld a,(hl)
call putchr
inc hl
dec bc
jr 1b
errwr:
push de
push hl
ld bc,(saveaf)
push bc
pop af
ld bc,(savebc)
ld de,(savede)
ld hl,(savehl)
ld ix,(saveix)
ld ix,-1 ! error in fd
ret
exit:
push de ! count on stack
ld bc,(saveaf)
push bc
pop af
ld bc,(savebc)
ld de,(savede)
ld hl,(savehl)
ld ix,(saveix)
pop ix ! return count to caller
ret
_ioctl:
ret
_getpid:
ret
! open return a file descriptor (0,1,2)
! depending on 'mode'
! mode 2 doesn't work!!
_open:
ld (savebc),bc
push af
pop bc
ld (saveaf),bc ! save all registers in savereg
ld (savede),de
ld (savehl),hl
ld (saveix),ix
pop bc ! return address
pop de ! name pointer
pop ix ! mode (0 for read,
! 1 for write)
push ix
push de
push bc
ld bc,(saveaf)
push bc
pop af
ld bc,(savebc)
ld de,(savede)
ld hl,(savehl)
ld ix,(saveix)
ret ! return fd = 0 for read
! fd = 1 for write
_close:
ld ix,0 ! return succes
ret
_exit:
jp 0x38
.data
_errno:
.word 0
! output routine in monitor
CRT = 0x013B
! output a charcter
! entry: ascii character in a
.text
!putchr:
! push hl
! push bc
! ld hl,tab
! ld b,5
!1: cp (hl)
! jr z,fetch
! inc hl
! inc hl
! djnz 1b
!2: call CRT
! pop bc
! pop hl
! ret
!fetch: inc hl
! ld a,(hl)
! jr 2b
!! conversion table for nascom characters
!tab: .byte 0x0D,0x00
! .byte 0x1B,0x1E
! .byte 0x08,0x1D
! .byte 0x0A,0x1F
! .byte 0x7F,0x00
KBD = 0x69
! get character from keyboard
getchr:
call KBD
jr nc,getchr
cp 0x1F
jr z,CR
cp 0x1D
jr z,BS
ret
CR: ld a,0xA
ret
BS: ld a,0x8
ret

View file

@ -1,53 +0,0 @@
# $Header$
EM = ../../..
h = $(EM)/h
CDIR = $(EM)/mach/proto/nas
CPP = $(EM)/lib/cpp
DEF =
FFLAG =
CFLAGS = $(FFLAG) -O -I$h $(DEF)
YFLAGS = -d
LDFLAGS = $(FFLAG) -i
CSRC = $(CDIR)/comm3.c $(CDIR)/comm4.c $(CDIR)/comm5.c \
$(CDIR)/comm6.c $(CDIR)/comm7.c $(CDIR)/comm8.c
COBJ = $(CDIR)/comm3.o $(CDIR)/comm4.o $(CDIR)/comm5.o \
$(CDIR)/comm6.o $(CDIR)/comm7.o $(CDIR)/comm8.o
MACH = mach0.c mach1.c mach2.c mach3.c mach4.c mach5.c
COMM = $(CDIR)/comm0.h $(CDIR)/comm1.h $(CDIR)/comm2.y $(CSRC)
all: as
install:all
../../install as
cmp:
-../../compare as
clean:
rm -f *.o as as.[cy] y.tab.h
pr: $(MACH)
@pr -n $(MACH)
opr:
make pr | opr
as: $(COBJ) as.o
$(CC) $(LDFLAGS) $(COBJ) as.o -o as
as.y: $(CDIR)/comm2.y
$(CPP) -P -I$h $(DEF) $(CDIR)/comm2.y >as.y
@echo "expect 1 shift/reduce conflict"
lint: $(CSRC) as.c
lint $(CSRC) as.c
y.tab.h: as.c
$(COBJ): y.tab.h
$(COBJ) as.y: $(CDIR)/comm0.h mach0.c
$(COBJ) as.y: $(CDIR)/comm1.h mach1.c
as.y: mach2.c
comm3.o: mach3.c
as.y: mach4.c
comm8.o: mach5.c

View file

@ -1,23 +0,0 @@
Makefile
ack.h
data.c
data.h
dmach.c
dmach.h
files.c
grows.c
grows.h
intable.c
list.c
list.h
main.c
malloc.c
mktables.c
pc
rmach.c
run.c
scan.c
svars.c
trans.c
trans.h
util.c

View file

@ -1,2 +0,0 @@
Makefile
em_pc.c

View file

@ -1,19 +0,0 @@
# @(#)Makefile 1.1
EM = ../..
h = $(EM)/h
CFLAGS = -n -O -I$h
ALL = anm asize astrip
OFILES = anm.o asize.o astrip.o
CFILES = anm.c asize.c astrip.c
all: $(ALL)
cp cmp: all
for i in $(ALL); do $@ $$i $$ROOT/usr/bin/$$i; done
clean: ; rm -f $(ALL) $(OFILES)
get: ; getall
unget: ; ungetall
print: $(CFILES)
pr -n Makefile $(CFILES) | lpr

View file

@ -1,310 +0,0 @@
#define DUK /* Modifications by Duk Bekema. */
/* @(#)anm.c 1.4 */
/* $Header$ */
/*
** print symbol tables for
** ACK object files
**
** anm [-gopruns] [name ...]
*/
#define ushort unsigned short
#include "out.h"
#include <stdio.h>
#include <ctype.h>
int numsort_flg;
int sectsort_flg;
int undef_flg;
int revsort_flg = 1;
int globl_flg;
int nosort_flg;
int arch_flg;
int prep_flg;
struct outhead hbuf;
struct outsect sbuf;
FILE *fi;
long off;
char *malloc();
char *realloc();
long s_base[S_MAX]; /* for specially encoded bases */
main(argc, argv)
char **argv;
{
int narg;
int compare();
if (--argc>0 && argv[1][0]=='-' && argv[1][1]!=0) {
argv++;
while (*++*argv) switch (**argv) {
case 'n': /* sort numerically */
numsort_flg++;
continue;
case 's': /* sort in section order */
sectsort_flg++;
continue;
case 'g': /* globl symbols only */
globl_flg++;
continue;
case 'u': /* undefined symbols only */
undef_flg++;
continue;
case 'r': /* sort in reverse order */
revsort_flg = -1;
continue;
case 'p': /* don't sort -- symbol table order */
nosort_flg++;
continue;
case 'o': /* prepend a name to each line */
prep_flg++;
continue;
default: /* oops */
fprintf(stderr, "anm: invalid argument -%c\n", *argv[0]);
exit(1);
}
argc--;
}
if (argc == 0) {
argc = 1;
argv[1] = "a.out";
}
narg = argc;
while(argc--) {
struct outname *nbufp = NULL;
struct outname nbuf;
char *cbufp;
long fi_to_co;
long n;
unsigned readcount;
int i,j;
fi = fopen(*++argv,"r");
if (fi == NULL) {
fprintf(stderr, "anm: cannot open %s\n", *argv);
continue;
}
getofmt((char *)&hbuf, SF_HEAD, fi);
if (BADMAGIC(hbuf)) {
fprintf(stderr, "anm: %s-- bad format\n", *argv);
fclose(fi);
continue;
}
if (narg > 1)
printf("\n%s:\n", *argv);
n = hbuf.oh_nname;
if (n == 0) {
fprintf(stderr, "anm: %s-- no name list\n", *argv);
fclose(fi);
continue;
}
if (hbuf.oh_nchar == 0) {
fprintf(stderr, "anm: %s-- no names\n", *argv);
fclose(fi);
continue;
}
if ((readcount = hbuf.oh_nchar) != hbuf.oh_nchar) {
fprintf(stderr, "anm: string area too big in %s\n", *argv);
exit(2);
}
/* store special section bases */
if (hbuf.oh_flags & HF_8086) {
for (i=0; i<hbuf.oh_nsect; i++) {
getofmt((char *)&sbuf, SF_SECT, fi);
s_base[i+S_MIN] =
(sbuf.os_base>>12) & 03777760;
}
}
if ((cbufp = (char *)malloc(readcount)) == NULL) {
fprintf(stderr, "anm: out of memory on %s\n", *argv);
exit(2);
}
fseek(fi, OFF_CHAR(hbuf), 0);
if (fread(cbufp, 1, readcount, fi) == 0) {
fprintf(stderr, "anm: read error on %s\n", *argv);
exit(2);
}
fi_to_co = cbufp - OFF_CHAR(hbuf);
fseek(fi, OFF_NAME(hbuf), 0);
i = 0;
while (--n >= 0) {
getofmt((char *)&nbuf, SF_NAME, fi);
if (nbuf.on_foff == 0)
continue; /* skip entries without names */
if (globl_flg && (nbuf.on_type&S_EXT)==0)
continue;
if (undef_flg
&&
((nbuf.on_type&S_TYP)!=S_UND || (nbuf.on_type&S_ETC)!=0))
continue;
nbuf.on_mptr = nbuf.on_foff + fi_to_co;
/* adjust value for specially encoded bases */
if (hbuf.oh_flags & HF_8086) {
if (((nbuf.on_type&S_ETC) == 0) ||
((nbuf.on_type&S_ETC) == S_SCT)) {
j = nbuf.on_type&S_TYP;
if ((j>=S_MIN) && (j<=S_MAX))
nbuf.on_valu += s_base[j];
}
}
if (nbufp == NULL)
nbufp = (struct outname *)malloc(sizeof(struct outname));
else
nbufp = (struct outname *)realloc(nbufp, (i+1)*sizeof(struct outname));
if (nbufp == NULL) {
fprintf(stderr, "anm: out of memory on %s\n", *argv);
exit(2);
}
nbufp[i++] = nbuf;
}
if (nosort_flg==0)
qsort(nbufp, i, sizeof(struct outname), compare);
for (n=0; n<i; n++) {
char cs1[4];
char cs2[4];
if (prep_flg)
printf("%s:", *argv);
switch(nbufp[n].on_type&S_ETC) {
case S_SCT:
sprintf(cs1, "%2d", (nbufp[n].on_type&S_TYP) - S_MIN);
sprintf(cs2, " S");
break;
case S_FIL:
sprintf(cs1, " -");
sprintf(cs2, " F");
break;
case S_MOD:
sprintf(cs1, " -");
sprintf(cs2, " M");
break;
case 0:
if (nbufp[n].on_type&S_EXT)
sprintf(cs2, " E");
else
sprintf(cs2, " -");
switch(nbufp[n].on_type&S_TYP) {
case S_UND:
sprintf(cs1, " U");
break;
case S_ABS:
sprintf(cs1, " A");
break;
default:
sprintf(cs1, "%2d", (nbufp[n].on_type&S_TYP) - S_MIN);
}
break;
default:
continue;
}
printf("%8lx %s %s %s\n",nbufp[n].on_valu,cs1,cs2,nbufp[n].on_mptr);
}
if (nbufp)
free((char *)nbufp);
if (cbufp)
free((char *)cbufp);
fclose(fi);
}
exit(0);
}
compare(p1, p2)
struct outname *p1, *p2;
{
int i;
if (sectsort_flg) {
if ((p1->on_type&S_TYP) > (p2->on_type&S_TYP))
return(revsort_flg);
if ((p1->on_type&S_TYP) < (p2->on_type&S_TYP))
return(-revsort_flg);
}
if (numsort_flg) {
if (p1->on_valu > p2->on_valu)
return(revsort_flg);
if (p1->on_valu < p2->on_valu)
return(-revsort_flg);
}
i = strcmp(p1->on_mptr, p2->on_mptr);
if (i > 0)
return(revsort_flg);
if (i < 0)
return(-revsort_flg);
return(0);
}
getofmt(p, s, f)
register char *p;
register char *s;
register FILE *f;
{
register i;
register long l;
for (;;) {
switch (*s++) {
/* case '0': p++; continue; */
case '1':
*p++ = getc(f);
continue;
case '2':
i = getc(f);
i |= (getc(f) << 8);
#ifndef DUK
*((short *)p)++ = i;
#else DUK
*((short *)p) = i;
p += sizeof(short);
#endif DUK
continue;
case '4':
l = (long)getc(f);
l |= ((long)getc(f) << 8);
l |= ((long)getc(f) << 16);
l |= ((long)getc(f) << 24);
#ifndef DUK
*((long *)p)++ = l;
#else DUK
*((long *)p) = l;
p += sizeof(long);
#endif DUK
continue;
default:
case '\0':
break;
}
break;
}
}

View file

@ -1,106 +0,0 @@
#define DUK /* Modifications by Duk Bekema. */
/* @(#)asize.c 1.2 */
/* $Header$ */
#define ushort unsigned short
#include <stdio.h>
#include "out.h"
/*
asize -- determine object size
*/
main(argc, argv)
char **argv;
{
struct outhead buf;
struct outsect sbuf;
ushort nrsect;
long sum;
int gorp;
FILE *f;
if (--argc == 0) {
argc = 1;
argv[1] = "a.out";
}
gorp = argc;
while(argc--) {
if ((f = fopen(*++argv, "r"))==NULL) {
fprintf(stderr, "asize: cannot open %s\n", *argv);
continue;
}
getofmt ((char *)&buf, SF_HEAD , f);
if(BADMAGIC(buf)) {
fprintf(stderr, "asize: %s-- bad format\n", *argv);
fclose(f);
continue;
}
nrsect = buf.oh_nsect;
if (nrsect == 0) {
fprintf(stderr, "asize: %s-- no sections\n", *argv);
fclose(f);
continue;
}
if (gorp > 1)
printf("%s: ", *argv);
sum = 0;
while (nrsect-- > 0) {
getofmt ((char *)&sbuf, SF_SECT , f);
printf("%ld", sbuf.os_size);
sum += sbuf.os_size;
if (nrsect > 0)
putchar('+');
}
printf(" = %ld = 0x%lx\n", sum, sum);
fclose(f);
}
}
getofmt(p, s, f)
register char *p;
register char *s;
register FILE *f;
{
register i;
register long l;
for (;;) {
switch (*s++) {
/* case '0': p++; continue; */
case '1':
*p++ = getc(f);
continue;
case '2':
i = getc(f);
i |= (getc(f) << 8);
#ifndef DUK
*((short *)p)++ = i;
#else DUK
*((short *)p) = i;
p += sizeof(short);
#endif DUK
continue;
case '4':
l = (long)getc(f);
l |= (long)(getc(f) << 8);
l |= ((long)getc(f) << 16);
l |= ((long)getc(f) << 24);
#ifndef DUK
*((long *)p)++ = l;
#else DUK
*((long *)p) = l;
p += sizeof(long);
#endif DUK
continue;
default:
case '\0':
break;
}
break;
}
}

View file

@ -1,213 +0,0 @@
#define DUK /* Modifications by Duk Bekema. */
/* @(#)astrip.c 1.1 */
/* $Header$ */
#define ushort unsigned short
#include "out.h"
#include <signal.h>
#include <stdio.h>
/*
astrip -- remove symbols and relocation bits
*/
char *tname;
char *mktemp();
FILE *fopen();
FILE *tf;
struct outhead buf;
main(argc, argv)
char **argv;
{
int status;
signal(SIGHUP, SIG_IGN);
signal(SIGINT, SIG_IGN);
signal(SIGQUIT, SIG_IGN);
tname = mktemp("/tmp/sXXXXX");
while(--argc) {
if ((status = strip(argv[argc])) > 1)
break;
}
unlink(tname);
exit(status);
}
strip(name)
char *name;
{
long size;
FILE *f;
if ((f = fopen(name,"r")) == NULL) {
fprintf(stderr, "astrip: cannot open %s\n", name);
return(1);
}
getofmt ((char *)&buf, SF_HEAD , f);
if(BADMAGIC(buf)) {
fprintf(stderr, "astrip: %s-- bad format\n", name);
fclose(f);
return(1);
}
size = OFF_RELO(buf) - SZ_HEAD;
buf.oh_flags &= ~HF_LINK;
buf.oh_nrelo = 0;
buf.oh_nname = 0;
buf.oh_nchar = 0;
if ((tf = fopen(tname,"w")) == NULL) {
fprintf(stderr, "astrip: cannot create temp file %s\n", tname);
fclose(f);
return(2);
}
fseek(tf, (long)0, 0);
putofmt((char *)&buf,SF_HEAD,tf,tname);
if(copy(name, tname, f, tf, size)) {
fclose(f);
fclose(tf);
return(1);
}
fclose(f);
fclose(tf);
size += SZ_HEAD;
if ((f = fopen(name,"w")) == NULL) {
fprintf(stderr, "astrip: cannot write %s\n", name);
return(1);
}
if ((tf = fopen(tname,"r")) == NULL) {
fprintf(stderr, "astrip: cannot read temp file %s\n", tname);
fclose(f);
return(2);
}
fseek(tf, (long)0, 0);
if(copy(tname, name, tf, f, size)) {
fclose(f);
fclose(tf);
return(2);
}
fclose(f);
fclose(tf);
return(0);
}
copy(fnam, tnam, fr, to, size)
char *fnam;
char *tnam;
long size;
FILE *fr,*to;
{
register s, n;
char lbuf[512];
while(size != (long)0) {
s = 512;
if(size < 512)
s = (int) size;
n = fread(lbuf,1,s,fr);
if(n != s) {
fprintf(stderr, "astrip: unexpected eof on %s\n", fnam);
return(1);
}
n = fwrite(lbuf,1,s,to);
if(n != s) {
fprintf(stderr, "astrip: write error on %s\n", tnam);
return(1);
}
size -= (long)s;
}
return(0);
}
getofmt(p, s, f)
register char *p;
register char *s;
register FILE *f;
{
register i;
register long l;
for (;;) {
switch (*s++) {
/* case '0': p++; continue; */
case '1':
*p++ = getc(f);
continue;
case '2':
i = getc(f);
i |= (getc(f) << 8);
#ifndef DUK
*((short *)p)++ = i;
#else DUK
*((short *)p) = i;
p += sizeof(short);
#endif DUK
continue;
case '4':
l = (long)getc(f);
l |= (long)(getc(f) << 8);
l |= ((long)getc(f) << 16);
l |= ((long)getc(f) << 24);
#ifndef DUK
*((long *)p)++ = l;
#else DUK
*((long *)p) = l;
p += sizeof(long);
#endif DUK
continue;
default:
case '\0':
break;
}
break;
}
}
putofmt(p, s, f, fnam)
register char *p;
register char *s;
register FILE *f;
char *fnam;
{
register i,j;
register long l;
while (j = *s++) {
switch (j -= '0') {
/* case 0: p++; break; */
case 1:
i = *p++; putc(i,f);
break;
case 2:
#ifndef DUK
i = *((short *)p)++;
#else DUK
i = *((short *)p);
p += sizeof(short);
#endif DUK
putc(i,f);
i>>=8; putc(i,f);
break;
case 4:
#ifndef DUK
l = *((long *)p)++;
#else DUK
l = *((long *)p);
p += sizeof(long);
#endif DUK
putc(l,f);
l >>=8; putc(l,f);
l >>=8; putc(l,f);
l >>=8; putc(l,f);
break;
default:
break;
}
if (ferror(f)) fprintf(stderr, "astrip: write error on %s\n", fnam);
}
}

View file

@ -1835,7 +1835,7 @@ finishio() {
if (bsize>=0)
fprintf(hfile,"#define TEM_BSIZE %d\n",bsize);
else
yyerror("EM_BSIZE undefined");
fprintf(hfile,"extern int TEM_BSIZE;\n");
if (fmt!=0)
fprintf(hfile,"#define WRD_FMT \"%s\"\n",fmt);
fprintf(hfile,"#define MAXALLREG %d\n",maxallreg);

View file

@ -1,60 +0,0 @@
EMH=../../../h
EMLIB=../../../lib
SHR=../share
CFILES=\
bo.c
OFILES=\
bo.o
HFILES=
PRFILES=\
$(CFILES) $(HFILES) Makefile
SHARE_OFILES=\
$(SHR)/get.o $(SHR)/put.o $(SHR)/alloc.o $(SHR)/global.o $(SHR)/debug.o \
$(SHR)/files.o $(SHR)/map.o $(SHR)/lset.o $(SHR)/cset.o $(SHR)/aux.o \
$(SHR)/stack_chg.o $(SHR)/go.o
SHARE_MFILES=\
$(SHR)/get.m $(SHR)/put.m $(SHR)/alloc.m $(SHR)/global.m $(SHR)/debug.m \
$(SHR)/files.m $(SHR)/map.m $(SHR)/lset.m $(SHR)/cset.m $(SHR)/aux.m \
$(SHR)/stack_chg.m $(SHR)/go.m
bo: $(OFILES)
$(CC) -o bo $(LDFLAGS) $(OFILES) $(SHARE_OFILES) $(EMLIB)/em_data.a
bo_ack: $(CFILES) $(SHARE_MFILES)
$(CC) -c.o $(CFLAGS) $(CFILES) $(SHARE_MFILES)
$(CC) -o bo -.c $(LDFLAGS) bo.o $(EMLIB)/em_data.a
lint:
lint $(LINTFLAGS) $(CPPFLAGS) $(CFILES)
pr: $(PRFILES)
@pr $?
@touch pr
depend:
$(SHR)/makedepend
# the next lines are generated automatically
# AUTOAUTOAUTOAUTOAUTOAUTO
bo.o: ../share/alloc.h
bo.o: ../share/aux.h
bo.o: ../share/debug.h
bo.o: ../share/def.h
bo.o: ../share/files.h
bo.o: ../share/get.h
bo.o: ../share/global.h
bo.o: ../share/go.h
bo.o: ../share/lset.h
bo.o: ../share/map.h
bo.o: ../share/put.h
bo.o: ../share/types.h
bo.o: ../../../h/em_mnem.h
bo.o: ../../../h/em_pseu.h
bo.o: ../../../h/em_spec.h

View file

@ -1,318 +0,0 @@
/* B R A N C H O P T I M I Z A T I O N
*
* B O . C
*/
#include <stdio.h>
#include "../share/types.h"
#include "../share/debug.h"
#include "../share/global.h"
#include "../share/files.h"
#include "../share/get.h"
#include "../share/put.h"
#include "../share/lset.h"
#include "../share/map.h"
#include "../share/alloc.h"
#include "../share/aux.h"
#include "../share/def.h"
#include "../share/go.h"
#include "../../../h/em_mnem.h"
#include "../../../h/em_pseu.h"
#include "../../../h/em_spec.h"
#define LP_BLOCKS lp_extend->lpx_ra.lpx_blocks
#define newbolpx() (lpext_p) newstruct(lpext_ra)
#define oldbolpx(x) oldstruct(lpext_ra,x)
STATIC int Sbo; /* #optimizations found */
#define DLINK(l1,l2) l1->l_next=l2; l2->l_prev=l1
/* This module performs some very simple branch optimizations.
*
* I) Look for pairs of basic blocks (B1,B2), such that
* SUCC(b1) = {B2} and
* PRED(B2) = {B1}.
* In this case B1 and B2 can be combined into one block.
* This optimization is mainly succesful:
* 1) for switch statements in C, as the C compiler generates a branch
* over the entire switch.
* 2) for return statements, if the only way to return from a procedure
* is via a return statement somewhere in the middle of the procedure.
* II) Optimize while statements. Transformations like:
* 1: jmp 2
* tst cond 1:
* beq 2f S
* S 2:
* jmp 1 tst cond
* 2: bneq 1
* are done by this optimization.
*/
STATIC line_p last_code(lines,skip_pseu)
line_p lines;
bool skip_pseu;
{
/* Determine the last line of a list */
register line_p l;
for (l = lines; l->l_next != (line_p) 0; l = l->l_next);
if (skip_pseu) {
while (INSTR(l) < sp_fmnem || INSTR(l) > sp_lmnem) l = PREV(l);
}
return l;
}
STATIC short cc_tab[12] =
{op_blt,op_zlt,op_ble,op_zle,op_beq,op_zeq,
op_zne,op_bne,op_zgt,op_bgt,op_zge,op_bge};
STATIC short rev_cond(cond)
short cond;
{
register i;
for (i = 0; i < 12; i++) {
if (cond == cc_tab[i]) return cc_tab[11-i];
}
return op_nop;
}
STATIC bool is_bcc(l)
line_p l;
{
return rev_cond(INSTR(l)) != op_nop;
}
STATIC bo_optloop(p,b,x,bra,bcc)
proc_p p;
bblock_p b,x;
line_p bra,bcc;
{
bblock_p prevb,n;
line_p l;
if (b->b_start == bra) {
b->b_start = (line_p) 0;
} else {
PREV(bra)->l_next = (line_p) 0;
}
PREV(bra) = (line_p) 0;
bcc->l_instr = rev_cond(INSTR(bcc));
n = x->b_next;
l = n->b_start;
if (l == (line_p) 0 || INSTR(l) != op_lab) {
l = newline(OPINSTRLAB);
l->l_instr = op_lab;
INSTRLAB(l) = freshlabel();
if (n->b_start != (line_p) 0) {
DLINK(l,n->b_start);
}
n->b_start = l;
}
INSTRLAB(bcc) = INSTRLAB(l);
for (prevb = p->p_start; prevb != (bblock_p) 0 && prevb->b_next != x;
prevb = prevb->b_next);
if (prevb == (bblock_p) 0) {
p->p_start = x->b_next;
} else {
prevb->b_next = x->b_next;
l = last_instr(prevb);
if (l == (line_p) 0) {
prevb->b_start = bra;
} else {
if (INSTR(l) == op_bra &&
INSTRLAB(l) == INSTRLAB(bra)) {
oldline(bra);
} else {
appnd_line(bra,l);
}
}
}
x->b_next = b->b_next;
b->b_next = x;
}
STATIC bo_tryloop(p,loop)
proc_p p;
lset loop;
{
Lindex i,j;
bblock_p b,x;
line_p bra,bcc;
for (i = Lfirst(loop); i != (Lindex) 0; i = Lnext(i,loop)) {
b = (bblock_p) Lelem(i);
if (b->b_next != (bblock_p) 0 && !Lis_elem(b->b_next,loop)) {
j = Lfirst(b->b_succ);
if (j != (Lindex) 0 &&
(bra = last_instr(b)) != (line_p) 0 &&
INSTR(bra) == op_bra) {
x = (bblock_p) Lelem(j); /* single successor */
if (Lis_elem(b->b_next,x->b_succ) &&
is_bcc((bcc = last_instr(x)))) {
OUTVERBOSE("branch optimization proc %d block %d\n", curproc->p_id,x->b_id);
Sbo++;
bo_optloop(p,b,x,bra,bcc);
return;
}
}
}
}
}
STATIC bo_loops(p)
proc_p p;
{
Lindex i;
loop_p lp;
for (i = Lfirst(p->p_loops); i != (Lindex) 0; i = Lnext(i,p->p_loops)) {
lp = (loop_p) (Lelem(i));
bo_tryloop(p,lp->LP_BLOCKS);
}
}
STATIC mv_code(b1,b2)
bblock_p b1,b2;
{
line_p l,x;
l = last_code(b2->b_start,TRUE);
DLINK(l,b1->b_start);
x = l->l_next;
if (INSTR(l) == op_bra) {
rm_line(l,b2);
}
if (INSTR(x) == op_lab) {
rm_line(x,b2);
}
}
bo_switch(b)
bblock_p b;
{
bblock_p s,x;
Lindex i;
line_p l;
if (Lnrelems(b->b_succ) == 1) {
s = (bblock_p) Lelem(Lfirst(b->b_succ));
if (b->b_start != (line_p) 0 &&
s->b_start != (line_p) 0 &&
Lnrelems(s->b_pred) == 1 &&
(s->b_next == (bblock_p) 0 ||
!Lis_elem(s->b_next,s->b_succ))) {
l = last_code(s->b_start,FALSE);
if (INSTR(l) == ps_end) {
if (PREV(l) == (line_p) 0) return;
PREV(l)->l_next = (line_p) 0;
PREV(l) = (line_p) 0;
} else {
l = (line_p) 0;
}
OUTVERBOSE("branch optimization in proc %d, block %d",curproc->p_id,b->b_id);
Sbo++;
Ldeleteset(b->b_succ);
b->b_succ = s->b_succ;
Ldeleteset(s->b_pred);
s->b_succ = Lempty_set();
s->b_pred = Lempty_set();
for (i = Lfirst(b->b_succ); i != (Lindex) 0;
i = Lnext(i,b->b_succ)) {
x = (bblock_p) Lelem(i);
Lremove(s,&x->b_pred);
Ladd(b,&x->b_pred);
if (x->b_idom == s) {
x->b_idom = b;
}
}
mv_code(s,b);
s->b_start = l;
}
}
}
STATIC bo_extproc(p)
proc_p p;
{
/* Allocate the extended data structures for procedure p */
register loop_p lp;
register Lindex pi;
for (pi = Lfirst(p->p_loops); pi != (Lindex) 0;
pi = Lnext(pi,p->p_loops)) {
lp = (loop_p) Lelem(pi);
lp->lp_extend = newbolpx();
}
}
STATIC loop_blocks(p)
proc_p p;
{
/* Compute the LP_BLOCKS sets for all loops of p */
register bblock_p b;
register Lindex i;
for (b = p->p_start; b != (bblock_p) 0; b = b->b_next) {
for (i = Lfirst(b->b_loops); i != (Lindex) 0;
i = Lnext(i,b->b_loops)) {
Ladd(b,&(((loop_p) Lelem(i))->LP_BLOCKS));
}
}
}
STATIC bo_cleanproc(p)
proc_p p;
{
/* Allocate the extended data structures for procedure p */
register loop_p lp;
register Lindex pi;
register bblock_p b;
for (pi = Lfirst(p->p_loops); pi != (Lindex) 0;
pi = Lnext(pi,p->p_loops)) {
lp = (loop_p) Lelem(pi);
oldbolpx(lp->lp_extend);
}
}
bo_optimize(p)
proc_p p;
{
bblock_p b;
bo_extproc(p);
loop_blocks(p);
bo_loops(p);
for (b = p->p_start; b != 0; b = b->b_next) {
bo_switch(b);
}
bo_cleanproc(p);
}
main(argc,argv)
int argc;
char *argv[];
{
go(argc,argv,no_action,bo_optimize,no_action,no_action);
report("branch optimizations", Sbo);
exit(0);
}

View file

@ -1,65 +0,0 @@
EMH=../../../h
EMLIB=../../../lib
SHR=../share
CFILES=\
ca.c ca_put.c
OFILES=\
ca.o ca_put.o
HFILES=\
ca.h ca_put.h
PRFILES=\
$(CFILES) $(HFILES) Makefile
SHARE_OFILES=\
$(SHR)/get.o $(SHR)/alloc.o $(SHR)/global.o $(SHR)/aux.o $(SHR)/debug.o \
$(SHR)/lset.o $(SHR)/cset.o $(SHR)/files.o $(SHR)/map.o
SHARE_MFILES=\
$(SHR)/get.m $(SHR)/alloc.m $(SHR)/global.m $(SHR)/aux.m $(SHR)/debug.m \
$(SHR)/lset.m $(SHR)/cset.m $(SHR)/files.m $(SHR)/map.m
ca: $(OFILES)
$(CC) -o ca $(LDFLAGS) $(OFILES) $(SHARE_OFILES) $(EMLIB)/em_data.a
ca_ack: $(CFILES) $(SHARE_MFILES)
$(CC) -c.o $(CFLAGS) $(CFILES) $(SHARE_MFILES)
$(CC) -o ca -.c $(LDFLAGS) ca.o $(EMLIB)/em_data.a
lint:
lint $(LINTFLAGS) $(CPPFLAGS) $(CFILES)
pr: $(PRFILES)
@pr $?
@touch pr
depend:
$(SHR)/makedepend
# the next lines are generated automatically
# AUTOAUTOAUTOAUTOAUTOAUTO
ca.o: ../share/alloc.h
ca.o: ../share/debug.h
ca.o: ../share/files.h
ca.o: ../share/get.h
ca.o: ../share/global.h
ca.o: ../share/lset.h
ca.o: ../share/map.h
ca.o: ../share/types.h
ca.o: ca.h
ca.o: ca_put.h
ca_put.o: ../../../h/em_flag.h
ca_put.o: ../../../h/em_mes.h
ca_put.o: ../../../h/em_mnem.h
ca_put.o: ../../../h/em_pseu.h
ca_put.o: ../../../h/em_spec.h
ca_put.o: ../share/alloc.h
ca_put.o: ../share/debug.h
ca_put.o: ../share/def.h
ca_put.o: ../share/map.h
ca_put.o: ../share/types.h
ca_put.o: ca.h

View file

@ -1,271 +0,0 @@
/*
* C O M P A C T A S S E M B L Y L A N G U A G E G E N E R A T I O N
*
*/
#include <stdio.h>
#include "../share/types.h"
#include "ca.h"
#include "../share/debug.h"
#include "../share/global.h"
#include "../share/lset.h"
#include "../share/files.h"
#include "../share/map.h"
#include "../share/alloc.h"
#include "../share/get.h"
#include "../../../h/em_pseu.h"
#include "../../../h/em_mes.h"
#include "ca_put.h"
/* This phase transforms the Intermediate Code of the global optimizer
* to 'standard' compact assembly language, which will be processed
* by the code generator.
*/
short dlength;
dblock_p *dmap;
char **dnames, **pnames; /* Dynamically allocated arrays of strings.
* pnames[i] contains a pointer to the name
* of the procedure with proc_id i.
*/
STATIC char **newnametab(tablen,namelen)
short tablen,namelen;
{
register char **np, **tab;
tab = (char **) newmap(tablen);
for (np = &tab[1]; np <= &tab[tablen]; np++) {
*np = (char *) newcore(namelen);
}
return tab;
}
STATIC line_p get_ca_lines(lf,p_out)
FILE *lf;
proc_p *p_out;
{
/* Read lines of EM text and link them.
* Register messages are outputted immediately after the PRO.
*/
line_p head, *pp, l;
line_p headm, *mp;
arg_p a;
curinp = lf; /* EM input file */
pp = &head;
mp = &headm;
headm = (line_p) 0;
while (TRUE) {
l = read_line(p_out);
if (feof(curinp)) break;
assert (l != (line_p) 0);
if (INSTR(l) == ps_end && INSTR(head) != ps_pro) {
/* Delete end pseudo after data-unit */
oldline(l);
break;
}
if (INSTR(l) == ps_mes && l->l_a.la_arg->a_a.a_offset == ms_reg) {
/* l is a register message */
if (l->l_a.la_arg->a_next == (arg_p) 0) {
/* register message without arguments */
oldline(l);
} else {
*mp = l;
mp = &l->l_next;
}
} else {
*pp = l;
pp = &l->l_next;
}
if (INSTR(l) == ps_end) {
break;
}
}
*pp = (line_p) 0;
if (head != (line_p) 0 && INSTR(head) == ps_pro) {
/* append register message without arguments to list */
l = newline(OPLIST);
l->l_instr = ps_mes;
a = ARG(l) = newarg(ARGOFF);
a->a_a.a_offset = ms_reg;
*mp = l;
l->l_next = head->l_next;
head->l_next = headm;
} else {
assert(headm == (line_p) 0);
}
return head;
}
STATIC int makedmap(dbl)
dblock_p dbl;
{
/* construct the dmap table */
dblock_p d;
int cnt;
/* determine the length of the table */
cnt = 0;
for (d = dbl; d != (dblock_p) 0; d = d->d_next) cnt++;
dmap = (dblock_p *) newmap(cnt);
for (d = dbl; d != (dblock_p) 0; d = d->d_next) {
assert(d->d_id) <= cnt;
dmap[d->d_id] = d;
}
return cnt;
}
STATIC getdnames(dumpd)
FILE *dumpd;
{
/* Read the names of the datalabels from
* the dump file.
*/
char str[IDL+1];
char *s;
int id;
register int i;
dnames = (char **) newnametab(dlength,IDL);
for (;;) {
if (fscanf(dumpd,"%d %s",&id,str) == EOF) return;
assert(id <= dlength);
s = dnames[id];
for (i = 0; i < IDL; i++) {
*s++ = str[i];
}
}
}
STATIC getpnames(dumpp)
FILE *dumpp;
{
/* Read the names of the procedures from
* the dump file.
*/
char str[IDL+1];
char *s;
int id;
register int i;
pnames = (char **) newnametab(plength,IDL);
for (;;) {
if (fscanf(dumpp,"%d %s",&id,str) == EOF) return;
assert(id <= plength);
s = pnames[id];
for (i = 0; i < IDL; i++) {
*s++ = str[i];
}
}
}
STATIC bool name_exists(name,endp,endd)
char *name;
proc_p endp;
dblock_p endd;
{
/* Search the proctable (from fproc to endp)
* and the data block table (from fdblock to endd)
* to see if the name is already in use.
*/
proc_p p;
dblock_p d;
for (p = fproc; p != endp; p = p->p_next) {
if (strncmp(name,pnames[p->p_id],IDL) == 0) return TRUE;
}
for (d = fdblock; d != endd; d = d->d_next) {
if (strncmp(name,dnames[d->d_id],IDL) == 0) return TRUE;
}
return FALSE;
}
static int nn = 0;
STATIC new_name(s)
char *s;
{
s[0] = '_';
s[1] = 'I';
s[2] = 'I';
sprintf(&s[3],"%d",nn);
nn++;
}
STATIC uniq_names()
{
/* The names of all internal procedures and data blocks
* are made different. As the optimizer combines several
* modules into one, there may be name conflicts between
* procedures or data blocks that were internal in
* different source modules.
*/
proc_p p;
dblock_p d;
for (p = fproc; p != (proc_p) 0; p = p->p_next) {
if (!(p->p_flags1 & PF_EXTERNAL) &&
name_exists(pnames[p->p_id],p,fdblock)) {
new_name(pnames[p->p_id]);
}
}
for (d = fdblock; d != (dblock_p) 0; d = d->d_next) {
if (!(d->d_flags1 & DF_EXTERNAL) &&
name_exists(dnames[d->d_id],(proc_p) 0,d) ) {
new_name(dnames[d->d_id]);
}
}
}
main(argc,argv)
int argc;
char *argv[];
{
/* CA does not output proctable etc. files. Instead, its
* pname2 and dname2 arguments contain the names of the
* dump files created by IC.
*/
FILE *f, *f2; /* The EM input and output. */
FILE *df, *pf; /* The dump files */
line_p lnp;
fproc = getptable(pname); /* proc table */
fdblock = getdtable(dname); /* data block table */
dlength = makedmap(fdblock); /* allocate dmap table */
df = openfile(dname2,"r");
getdnames(df);
fclose(df);
pf = openfile(pname2,"r");
getpnames(pf);
fclose(pf);
uniq_names();
f = openfile(lname,"r");
f2 = stdout;
cputmagic(f2); /* write magic number */
while ((lnp = get_ca_lines(f,&curproc)) != (line_p) 0) {
cputlines(lnp,f2);
}
fclose(f);
fclose(f2);
exit(0);
}

View file

@ -1,15 +0,0 @@
/*
* C O M P A C T A S S E M B L Y L A N G U A G E G E N E R A T I O N
*
*/
#define PF_SYMOUT 01
#define DF_SYMOUT 01
extern dblock_p *dmap;
extern char **dnames;
extern char **pnames;
extern byte em_flag[];

View file

@ -1,413 +0,0 @@
#include <stdio.h>
#include "../share/types.h"
#include "ca.h"
#include "../share/debug.h"
#include "../share/def.h"
#include "../share/map.h"
#include "../../../h/em_spec.h"
#include "../../../h/em_pseu.h"
#include "../../../h/em_mnem.h"
#include "../../../h/em_flag.h"
#include "../../../h/em_mes.h"
#include "../share/alloc.h"
#define outbyte(b) putc(b,outfile)
FILE *outfile;
STATIC proc_p thispro;
STATIC outinst(m) {
outbyte( (byte) m );
}
STATIC coutshort(i) short i; {
outbyte( (byte) (i&BMASK) );
outbyte( (byte) (i>>8) );
}
STATIC coutint(i) short i; {
if (i>= -sp_zcst0 && i< sp_ncst0-sp_zcst0)
outbyte( (byte) (i+sp_zcst0+sp_fcst0) );
else {
outbyte( (byte) sp_cst2) ;
coutshort(i);
}
}
STATIC coutoff(off) offset off; {
if ((short) off == off)
coutint((short) off);
else {
outbyte( (byte) sp_cst4) ;
coutshort( (short) (off&0177777L) );
coutshort( (short) (off>>16) );
}
}
STATIC outsym(s,t)
char *s;
int t;
{
register byte *p;
register unsigned num;
if (s[0] == '.') {
num = atoi(&s[1]);
if (num < 256) {
outbyte( (byte) sp_dlb1) ;
outbyte( (byte) (num) );
} else {
outbyte( (byte) sp_dlb2) ;
coutshort((short) num);
}
} else {
p= s;
while (*p && p < &s[IDL])
p++;
num = p - s;
outbyte( (byte) t);
coutint((short) num);
p = s;
while (num--)
outbyte( (byte) *p++ );
}
}
STATIC outdsym(dbl)
dblock_p dbl;
{
outsym(dnames[dbl->d_id],sp_dnam);
}
STATIC outpsym(p)
proc_p p;
{
outsym(pnames[p->p_id],sp_pnam);
}
STATIC outddef(id) short id; {
dblock_p dbl;
dbl = dmap[id];
dbl->d_flags2 |= DF_SYMOUT;
if (dbl->d_flags1 & DF_EXTERNAL) {
outinst(ps_exa);
outdsym(dbl);
}
}
STATIC outpdef(p) proc_p p; {
p->p_flags2 |= PF_SYMOUT;
if (p->p_flags1 & PF_EXTERNAL) {
outinst(ps_exp);
outpsym(p);
}
}
STATIC outdocc(obj) obj_p obj; {
dblock_p dbl;
dbl = obj->o_dblock;
if ((dbl->d_flags2 & DF_SYMOUT) == 0) {
dbl->d_flags2 |= DF_SYMOUT;
if ((dbl->d_flags1 & DF_EXTERNAL) == 0) {
outinst(ps_ina);
outdsym(dbl);
}
}
}
STATIC outpocc(p) proc_p p; {
if ((p->p_flags2 & PF_SYMOUT) == 0) {
p->p_flags2 |= PF_SYMOUT;
if ((p->p_flags1 & PF_EXTERNAL) == 0) {
outinst(ps_inp);
outpsym(p);
}
}
}
STATIC coutobject(obj)
obj_p obj;
{
/* In general, an object is defined by a global data
* label and an offset. There are two special cases:
* the label is omitted if the object is part of the current
* hol block; the offset is omitted if it is 0 and the label
* was not omitted.
*/
if (dnames[obj->o_dblock->d_id][0] == '\0') {
coutoff(obj->o_off);
} else {
if (obj->o_off == 0) {
outdsym(obj->o_dblock);
} else {
outbyte((byte) sp_doff);
outdsym(obj->o_dblock);
coutoff(obj->o_off);
}
}
}
STATIC cputstr(abp) register argb_p abp; {
register argb_p tbp;
register length;
length = 0;
tbp = abp;
while (tbp!= (argb_p) 0) {
length += tbp->ab_index;
tbp = tbp->ab_next;
}
coutint(length);
while (abp != (argb_p) 0) {
for (length=0;length<abp->ab_index;length++)
outbyte( (byte) abp->ab_contents[length] );
abp = abp->ab_next;
}
}
STATIC outnum(n)
int n;
{
if (n < 256) {
outbyte((byte) sp_ilb1);
outbyte((byte) n);
} else {
outbyte((byte) sp_ilb2);
coutshort((short) n);
}
}
STATIC numlab(n)
int n;
{
if (n < sp_nilb0) {
outbyte((byte) (n + sp_filb0));
} else {
outnum(n);
}
}
STATIC cputargs(lnp)
line_p lnp;
{
register arg_p ap;
int cnt = 0;
ap = ARG(lnp);
while (ap != (arg_p) 0) {
switch(ap->a_type) {
case ARGOFF:
coutoff(ap->a_a.a_offset);
break;
case ARGOBJECT:
coutobject(ap->a_a.a_obj);
break;
case ARGPROC:
outpsym(ap->a_a.a_proc);
break;
case ARGINSTRLAB:
outnum(ap->a_a.a_instrlab);
break;
case ARGSTRING:
outbyte((byte) sp_scon);
cputstr(&ap->a_a.a_string);
break;
case ARGICN:
outbyte((byte) sp_icon);
goto casecon;
case ARGUCN:
outbyte((byte) sp_ucon);
goto casecon;
case ARGFCN:
outbyte((byte) sp_fcon);
casecon:
coutint(ap->a_a.a_con.ac_length);
cputstr(&ap->a_a.a_con.ac_con);
break;
default:
assert(FALSE);
}
ap = ap->a_next;
/* Avoid generating extremely long CON or ROM statements */
if (cnt++ > 10 && ap != (arg_p) 0 &&
(INSTR(lnp) == ps_con || INSTR(lnp) == ps_rom)) {
cnt = 0;
outbyte((byte) sp_cend);
outinst(INSTR(lnp));
}
}
}
STATIC outoperand(lnp)
line_p lnp;
{
/* Output the operand of instruction lnp */
switch(TYPE(lnp)) {
case OPNO:
if ((em_flag[INSTR(lnp)-sp_fmnem]&EM_PAR) != PAR_NO) {
outbyte((byte) sp_cend);
}
break;
case OPSHORT:
if (INSTR(lnp) == ps_sym) {
outsym(dnames[SHORT(lnp)],sp_dnam);
} else {
coutint(SHORT(lnp));
}
break;
case OPOFFSET:
coutoff(OFFSET(lnp));
break;
case OPINSTRLAB:
if (INSTR(lnp) == op_lab) {
numlab(INSTRLAB(lnp));
} else {
if (INSTR(lnp) < sp_fpseu) {
coutint(INSTRLAB(lnp));
} else {
numlab(INSTRLAB(lnp));
}
}
break;
case OPOBJECT:
coutobject(OBJ(lnp));
break;
case OPPROC:
outpsym(PROC(lnp));
break;
case OPLIST:
cputargs(lnp);
switch(INSTR(lnp)) {
case ps_con:
case ps_rom:
case ps_mes:
outbyte((byte) sp_cend);
/* list terminator */
break;
}
break;
default:
assert(FALSE);
}
}
STATIC outvisibility(lnp)
line_p lnp;
{
/* In EM names of datalabels and procedures can be made
* externally visible, so they can be used in other files.
* There are special EM pseudo-instructions to state
* explicitly that a certain identifier is externally
* visible (ps_exa,ps_exp) or invisible (ps_ina,ps_inp).
* If there is no such pseudo for a certain identifier,
* the identifier is external only if its first use
* in the current file is an applied occurrence.
* Unfortunately the global optimizer may change the
* order of defining and applied occurrences.
* In the first optimizer pass (ic) we record for each identifier
* whether it is external or not. If necessary we generate
* pseudo instructions here.
*/
arg_p ap;
short instr;
instr = INSTR(lnp);
switch(TYPE(lnp)) {
case OPOBJECT:
outdocc(OBJ(lnp));
/* applied occurrence of a data label */
break;
case OPSHORT:
if (instr == ps_sym) {
outddef(SHORT(lnp));
/* defining occ. data label */
}
break;
case OPPROC:
if (instr == ps_pro) {
outpdef(PROC(lnp));
/* defining occ. procedure */
} else {
outpocc(PROC(lnp));
}
break;
case OPLIST:
for (ap = ARG(lnp); ap != (arg_p) 0; ap = ap->a_next) {
switch(ap->a_type) {
case ARGOBJECT:
outdocc(ap->a_a.a_obj);
break;
case ARGPROC:
outpocc(ap->a_a.a_proc);
break;
}
}
break;
}
}
cputlines(l,lf)
line_p l;
FILE *lf;
{
/* Output the lines in Campact assembly language
* format.
*/
line_p next,lnp;
outfile = lf;
for (lnp = l; lnp != (line_p) 0; lnp = next) {
next = lnp->l_next;
outvisibility(lnp); /* take care of visibiltity rules */
if (INSTR(lnp) != ps_sym && INSTR(lnp) != op_lab) {
outinst(INSTR(lnp));
}
outoperand(lnp);
switch(INSTR(lnp)) {
case ps_pro:
thispro = PROC(lnp);
/* fall through ... */
case ps_end:
coutoff(thispro->p_localbytes);
}
oldline(lnp);
}
if (lmap != (line_p *) 0) {
oldmap(lmap,llength);
lmap = (line_p *) 0;
}
}
cputmagic(lf)
FILE *lf;
{
/* write the magic number */
outfile = lf;
coutshort(sp_magic);
}

View file

@ -1,9 +0,0 @@
/* C O M P A C T A S S E M B L Y G E N E R A T I O N
*
* C A _ P U T . C
*
*/
extern cputlines();
extern cputmagic();

View file

@ -1,82 +0,0 @@
EMH=../../../h
EMLIB=../../../lib
SHR=../share
CFILES=\
cf.c cf_succ.c cf_idom.c cf_loop.c
OFILES=\
cf.o cf_idom.o cf_loop.o cf_succ.o
HFILES=\
cf.h cf_succ.h cf_idom.h cf_loop.h
PRFILES=\
$(CFILES) $(HFILES) Makefile
SHARE_OFILES=\
$(SHR)/get.o $(SHR)/put.o $(SHR)/alloc.o $(SHR)/global.o \
$(SHR)/debug.o $(SHR)/files.o $(SHR)/map.o $(SHR)/lset.o \
$(SHR)/cset.o $(SHR)/aux.o
SHARE_MFILES=\
$(SHR)/get.m $(SHR)/put.m $(SHR)/alloc.m $(SHR)/global.m \
$(SHR)/debug.m $(SHR)/files.m $(SHR)/map.m $(SHR)/lset.m \
$(SHR)/cset.m $(SHR)/aux.m
cf: $(OFILES)
$(CC) -o cf $(LDFLAGS) $(OFILES) $(SHARE_OFILES) $(EMLIB)/em_data.a
cf_ack: $(CFILES) $(SHARE_MFILES)
$(CC) -c.o $(CFLAGS) $(CFILES) $(SHARE_MFILES)
$(CC) -o cf -.c $(LDFLAGS) cf.o $(EMLIB)/em_data.a
lint:
lint $(LINTFLAGS) $(CPPFLAGS) $(CFILES)
pr: $(PRFILES)
@pr $?
@touch pr
depend:
$(SHR)/makedepend
# the next lines are generated automatically
# AUTOAUTOAUTOAUTOAUTOAUTO
cf.o: ../../../h/em_mnem.h
cf.o: ../share/alloc.h
cf.o: ../share/cset.h
cf.o: ../share/debug.h
cf.o: ../share/files.h
cf.o: ../share/get.h
cf.o: ../share/global.h
cf.o: ../share/lset.h
cf.o: ../share/map.h
cf.o: ../share/put.h
cf.o: ../share/types.h
cf.o: cf.h
cf.o: cf_idom.h
cf.o: cf_loop.h
cf.o: cf_succ.h
cf_idom.o: ../share/alloc.h
cf_idom.o: ../share/debug.h
cf_idom.o: ../share/lset.h
cf_idom.o: ../share/types.h
cf_idom.o: cf.h
cf_loop.o: ../share/alloc.h
cf_loop.o: ../share/debug.h
cf_loop.o: ../share/lset.h
cf_loop.o: ../share/types.h
cf_loop.o: cf.h
cf_succ.o: ../../../h/em_flag.h
cf_succ.o: ../../../h/em_mnem.h
cf_succ.o: ../../../h/em_pseu.h
cf_succ.o: ../../../h/em_spec.h
cf_succ.o: ../share/cset.h
cf_succ.o: ../share/debug.h
cf_succ.o: ../share/def.h
cf_succ.o: ../share/global.h
cf_succ.o: ../share/lset.h
cf_succ.o: ../share/map.h
cf_succ.o: ../share/types.h
cf_succ.o: cf.h

View file

@ -1,520 +0,0 @@
/* C O N T R O L F L O W
*
* M A I N R O U T I N E
*/
#include <stdio.h>
#include "../share/types.h"
#include "../share/debug.h"
#include "../share/map.h"
#include "../share/files.h"
#include "../share/global.h"
#include "../share/alloc.h"
#include "../share/lset.h"
#include "../share/cset.h"
#include "../share/get.h"
#include "../share/put.h"
#include "../../../h/em_mnem.h"
#include "../../../h/em_pseu.h"
#include "../../../h/em_spec.h"
#include "../../../h/em_flag.h"
#include "../share/def.h"
#include "cf.h"
#include "cf_succ.h"
#include "cf_idom.h"
#include "cf_loop.h"
#define newcfbx() (bext_p) newstruct(bext_cf)
#define oldcfbx(x) oldstruct(bext_cf,x)
extern char em_flag[];
STATIC cset lpi_set; /* set of procedures used in LPI instruction */
STATIC cset cai_set; /* set of all procedures doing a CAI */
/* The procedure getbblocks reads the EM textfile and
* partitions every procedure into a number of basic blocks.
*/
#define LABEL0 0
#define LABEL 1
#define NORMAL 2
#define JUMP 3
#define END 4
#define AFTERPRO 5
#define INIT 6
/* These global variables are used by getbblocks and nextblock. */
STATIC bblock_p b, *bp; /* b is the current basic block, bp is
* the address where the next block has
* to be linked.
*/
STATIC line_p lnp, *lp; /* lnp is the current line, lp is
* the address where the next line
* has to be linked.
*/
STATIC short state; /* We use a finite state machine with the
* following states:
* LABEL0: after the first (successive)
* instruction label.
* LABEL1: after at least two successive
* instruction labels.
* NORMAL: after a normal instruction.
* JUMP: after a branch (conditional,
* unconditional or CSA/CSB).
* END: after an END pseudo
* AFTERPRO: after we've read a PRO pseudo
* INIT: initial state
*/
STATIC nextblock()
{
/* allocate a new basic block structure and
* set b, bp and lp.
*/
b = *bp = freshblock();
bp = &b->b_next;
b->b_start = lnp;
b->b_succ = Lempty_set();
b->b_pred = Lempty_set();
b->b_extend = newcfbx(); /* basic block extension for CF */
b->b_extend->bx_cf.bx_bucket = Lempty_set();
b->b_extend->bx_cf.bx_semi = 0;
lp = &lnp->l_next;
#ifdef TRACE
fprintf(stderr,"new basic block, id = %d\n",lastbid);
#endif
}
STATIC short kind(lnp)
line_p lnp;
{
/* determine if lnp is a label, branch, end or otherwise */
short instr;
byte flow;
if ((instr = INSTR(lnp)) == op_lab) return (short) LABEL;
if (instr == ps_end) return (short) END;
if (instr > sp_lmnem) return (short) NORMAL; /* pseudo */
if ((flow = (em_flag[instr-sp_fmnem] & EM_FLO)) == FLO_C ||
flow == FLO_T) return (short) JUMP; /* conditional/uncond. jump */
return (short) NORMAL;
}
STATIC bool getbblocks(fp,kind_out,n_out,g_out,l_out)
FILE *fp;
short *kind_out;
short *n_out;
bblock_p *g_out;
line_p *l_out;
{
bblock_p head = (bblock_p) 0;
line_p headl = (line_p) 0;
curproc = (proc_p) 0;
/* curproc will get a value when we encounter a PRO pseudo.
* If there is no such pseudo, we're reading only data
* declarations or messages (outside any proc.).
*/
curinp = fp;
lastbid = (block_id) 0; /* block identier */
state = INIT; /* initial state */
bp = &head;
for (;;) {
#ifdef TRACE
fprintf(stderr,"state = %d\n",state);
#endif
switch(state) {
case LABEL0:
nextblock();
/* Fall through !! */
case LABEL:
lbmap[INSTRLAB(lnp)] = b;
/* The lbmap table contains for each
* label_id the basic block of that label.
*/
lnp = read_line(&curproc);
state = kind(lnp);
if (state != END) {
*lp = lnp;
lp = &lnp->l_next;
}
break;
case NORMAL:
lnp = read_line(&curproc);
if ( (state = kind(lnp)) == LABEL) {
/* If we come accross a label
* here, it must be the beginning
* of a new basic block.
*/
state = LABEL0;
} else {
if (state != END) {
*lp = lnp;
lp = &lnp->l_next;
}
}
break;
case JUMP:
lnp = read_line(&curproc);
/* fall through ... */
case AFTERPRO:
switch(state = kind(lnp)) {
case LABEL:
state = LABEL0;
break;
case JUMP:
case NORMAL:
nextblock();
break;
}
break;
case END:
*lp = lnp;
#ifdef TRACE
fprintf(stderr,"at end of proc, %d blocks\n",lastbid);
#endif
if (head == (bblock_p) 0) {
*kind_out = LDATA;
*l_out = headl;
} else {
*kind_out = LTEXT;
*g_out = head;
*n_out = (short) lastbid;
/* number of basic blocks */
}
return TRUE;
case INIT:
lnp = read_line(&curproc);
if (feof(curinp)) return FALSE;
if (INSTR(lnp) == ps_pro) {
state = AFTERPRO;
} else {
state = NORMAL;
headl = lnp;
lp = &lnp->l_next;
}
break;
}
}
}
STATIC interproc_analysis(p)
proc_p p;
{
/* Interprocedural analysis of a procedure p determines:
* - all procedures called by p (the 'call graph')
* - the set of objects changed by p (directly)
* - whether p does a load-indirect (loi,lof etc.)
* - whether p does a store-indirect (sti, stf etc.)
* The changed/used variables information will be
* transitively closed, i.e. if P calls Q and Q changes
* a variable X, the P changes X too.
* (The same applies for used variables and for use/store
* indirect).
* The transitive closure will be computed by main
* after all procedures have been processed.
*/
bblock_p b;
line_p lnp;
bool inloop;
/* Allocate memory for structs and sets */
p->p_use = newuse();
p->p_change = newchange();
p->p_change->c_ext = Cempty_set(olength);
p->p_calling = Cempty_set(plength);
for (b = p->p_start; b != (bblock_p) 0; b = b->b_next) {
inloop = (Lnrelems(b->b_loops) > 0);
for (lnp = b->b_start; lnp != (line_p) 0; lnp = lnp->l_next) {
/* for all instructions of p do */
switch(INSTR(lnp)) {
case op_cal:
Cadd(PROC(lnp)->p_id, &p->p_calling);
/* add called proc to p_calling */
if (inloop) {
CALLED_IN_LOOP(PROC(lnp));
}
break;
case op_cai:
Cadd(p->p_id,&cai_set);
break;
case op_lpi:
Cadd(PROC(lnp)->p_id, &lpi_set);
/* All procedures that have their names used
* in an lpi instruction, may be called via
* a cai instruction.
*/
PROC(lnp)->p_flags1 |= PF_LPI;
break;
case op_ste:
case op_sde:
case op_ine:
case op_dee:
case op_zre:
Cadd(OBJ(lnp)->o_id, &p->p_change->c_ext);
/* Add changed object to c_ext */
break;
case op_lil:
case op_lof:
case op_loi:
case op_los:
case op_lar:
p->p_use->u_flags |= UF_INDIR;
/* p does a load-indirect */
break;
case op_sil:
case op_stf:
case op_sti:
case op_sts:
case op_sar:
p->p_change->c_flags |= CF_INDIR;
/* p does a store-indirect */
break;
case op_blm:
case op_bls:
p->p_use->u_flags |= UF_INDIR;
p->p_change->c_flags |= CF_INDIR;
/* p does both */
break;
case op_mon:
printf("mon not yet implemented\n");
break;
case op_lxl:
case op_lxa:
curproc->p_flags1 |= PF_ENVIRON;
break;
}
}
}
}
STATIC cf_cleanproc(p)
proc_p p;
{
/* Remove the extended data structures of p */
register bblock_p b;
register Lindex pi;
loop_p lp;
for (b = p->p_start; b != (bblock_p) 0; b = b->b_next) {
oldcfbx(b->b_extend);
}
for (pi = Lfirst(p->p_loops); pi != (Lindex) 0; pi = Lnext(pi,
p->p_loops)) {
lp = (loop_p) Lelem(pi);
oldcflpx(lp->lp_extend);
}
}
#define CHANGE_INDIR(ch) ((ch->c_flags & CF_INDIR) != 0)
#define USE_INDIR(us) ((us->u_flags & UF_INDIR) != 0)
#define CALLS_UNKNOWN(p) (p->p_flags1 & (byte) PF_CALUNKNOWN)
#define BODY_KNOWN(p) (p->p_flags1 & (byte) PF_BODYSEEN)
#define ENVIRON(p) (p->p_flags1 & (byte) PF_ENVIRON)
STATIC bool add_info(q,p)
proc_p q,p;
{
/* Determine the consequences for used/changed variables info
* of the fact that p calls q. If e.g. q changes a variable X
* then p changes this variable too. This routine is an
* auxiliary routine of the transitive closure process.
* The returned value indicates if there was any change in
* the information of p.
*/
change_p chp, chq;
use_p usp, usq;
bool diff = FALSE;
chp = p->p_change;
chq = q->p_change;
usp = p->p_use;
usq = q->p_use;
if (!BODY_KNOWN(q)) {
/* q is a procedure of which the body is not available
* as EM text.
*/
if (CALLS_UNKNOWN(p)) {
return FALSE;
/* p already called an unknown procedure */
} else {
p->p_flags1 |= PF_CALUNKNOWN;
return TRUE;
}
}
if (CALLS_UNKNOWN(q)) {
/* q calls a procedure of which the body is not available
* as EM text.
*/
if (!CALLS_UNKNOWN(p)) {
p->p_flags1 |= PF_CALUNKNOWN;
diff = TRUE;
}
}
if (IS_CALLED_IN_LOOP(p) && !IS_CALLED_IN_LOOP(q)) {
CALLED_IN_LOOP(q);
diff = TRUE;
}
if (!Cis_subset(chq->c_ext, chp->c_ext)) {
/* q changes global variables (objects) that
* p did not (yet) change. Add all variables
* changed by q to the c_ext set of p.
*/
Cjoin(chq->c_ext, &chp->c_ext);
diff = TRUE;
}
if (CHANGE_INDIR(chq) && !CHANGE_INDIR(chp)) {
/* q does a change-indirect (sil etc.)
* and p did not (yet).
*/
chp->c_flags |= CF_INDIR;
diff = TRUE;
}
if (USE_INDIR(usq) && !USE_INDIR(usp)) {
/* q does a use-indirect (lil etc.)
* and p dis not (yet).
*/
usp->u_flags |= UF_INDIR;
diff = TRUE;
}
if (ENVIRON(q) && !ENVIRON(p)) {
/* q uses or changes local variables in its
* environment while p does not (yet).
*/
p->p_flags1 |= PF_ENVIRON;
diff = TRUE;
}
return diff;
}
STATIC trans_clos(head)
proc_p head;
{
/* Compute the transitive closure of the used/changed
* variable information.
*/
register proc_p p,q;
Cindex i;
bool changes = TRUE;
while(changes) {
changes = FALSE;
for (p = head; p != (proc_p) 0; p = p->p_next) {
if (!BODY_KNOWN(p)) continue;
for (i = Cfirst(p->p_calling); i != (Cindex) 0;
i = Cnext(i,p->p_calling)) {
q = pmap[Celem(i)];
if (add_info(q,p)) {
changes = TRUE;
}
}
}
}
}
indir_calls()
{
Cindex i;
proc_p p;
for (i = Cfirst(cai_set); i != (Cindex) 0; i = Cnext(i,cai_set)) {
p = pmap[Celem(i)]; /* p does a CAI */
Cjoin(lpi_set, &p->p_calling);
}
Cdeleteset(lpi_set);
Cdeleteset(cai_set);
}
main(argc,argv)
int argc;
char *argv[];
{
FILE *f, *f2, *gf2; /* The EM input, EM output, basic block output */
bblock_p g;
short n, kind;
line_p l;
linecount = 0;
fproc = getptable(pname); /* proc table */
fdblock = getdtable(dname); /* data block table */
lpi_set = Cempty_set(plength);
cai_set = Cempty_set(plength);
if ((f = fopen(lname,"r")) == NULL) {
error("cannot open %s", lname);
}
if ((f2 = fopen(lname2,"w")) == NULL) {
error("cannot open %s", lname2);
}
if ((gf2 = fopen(bname2,"w")) == NULL) {
error("cannot open %s",bname2);
}
while (getbblocks(f,&kind,&n,&g,&l)) {
/* read EM text of one unit and
* (if it is a procedure)
* partition it into n basic blocks.
*/
if (kind == LDATA) {
putunit(LDATA,(proc_p) 0,l,gf2,f2);
} else {
curproc->p_start = g;
/* The global variable curproc points to the
* current procedure. It is set by getbblocks
*/
control_flow(g); /* compute pred and succ */
dominators(g,n); /* compute immediate dominators */
loop_detection(curproc); /* compute loops */
interproc_analysis(curproc);
/* Interprocedural analysis */
cf_cleanproc(curproc);
putunit(LTEXT,curproc,(line_p) 0,gf2,f2);
/* output control flow graph + text */
}
}
fclose(f);
fclose(f2);
fclose(gf2);
indir_calls();
trans_clos(fproc);
/* Compute transitive closure of used/changed
* variables information for every procedure.
*/
if ((f = fopen(dname2,"w")) == NULL) {
error("cannot open %s",dname2);
}
putdtable(fdblock,f);
if ((f = fopen(pname2,"w")) == NULL) {
error("cannot open %s",pname2);
}
putptable(fproc,f,TRUE);
exit(0);
}

View file

@ -1,16 +0,0 @@
/* C O N T R O L F L O W */
/* Macro's for extended data structures: */
#define B_SEMI b_extend->bx_cf.bx_semi
#define B_PARENT b_extend->bx_cf.bx_parent
#define B_BUCKET b_extend->bx_cf.bx_bucket
#define B_ANCESTOR b_extend->bx_cf.bx_ancestor
#define B_LABEL b_extend->bx_cf.bx_label
#define LP_BLOCKS lp_extend->lpx_cf.lpx_blocks
#define LP_COUNT lp_extend->lpx_cf.lpx_count
#define LP_MESSY lp_extend->lpx_cf.lpx_messy
#define newcflpx() (lpext_p) newstruct(lpext_cf)
#define oldcflpx(x) oldstruct(lpext_cf,x)

View file

@ -1,138 +0,0 @@
/* C O N T R O L F L O W
*
* C F _ I D O M . C
*/
#include "../share/types.h"
#include "../share/debug.h"
#include "../share/lset.h"
#include "../share/alloc.h"
#include "cf.h"
/* The algorithm for finding dominators in a flowgraph
* that is used here, was developed by Thomas Lengauer
* and Robert E. Tarjan of Stanford University.
* The algorithm is described in their article:
* A Fast Algorithm for Finding Dominators
* in a Flowgraph
* which was published in:
* ACM Transactions on Programming Languages and Systems,
* Vol. 1, No. 1, July 1979, Pages 121-141.
*/
#define UNREACHABLE(b) (b->B_SEMI == (short) 0)
short dfs_nr;
bblock_p *vertex; /* dynamically allocated array */
STATIC dfs(v)
bblock_p v;
{
/* Depth First Search */
Lindex i;
bblock_p w;
v->B_SEMI = ++dfs_nr;
vertex[dfs_nr] = v->B_LABEL = v;
v->B_ANCESTOR = (bblock_p) 0;
for (i = Lfirst(v->b_succ); i != (Lindex) 0; i = Lnext(i,v->b_succ)) {
w = (bblock_p) Lelem(i);
if (w->B_SEMI == 0) {
w->B_PARENT = v;
dfs(w);
}
}
}
STATIC compress(v)
bblock_p v;
{
if (v->B_ANCESTOR->B_ANCESTOR != (bblock_p) 0) {
compress(v->B_ANCESTOR);
if (v->B_ANCESTOR->B_LABEL->B_SEMI < v->B_LABEL->B_SEMI) {
v->B_LABEL = v->B_ANCESTOR->B_LABEL;
}
v->B_ANCESTOR = v->B_ANCESTOR->B_ANCESTOR;
}
}
STATIC bblock_p eval(v)
bblock_p v;
{
if (v->B_ANCESTOR == (bblock_p) 0) {
return v;
} else {
compress(v);
return v->B_LABEL;
}
}
STATIC linkblocks(v,w)
bblock_p v,w;
{
w->B_ANCESTOR = v;
}
dominators(r,n)
bblock_p r;
short n;
{
/* Compute the immediate dominator of every basic
* block in the control flow graph rooted by r.
*/
register short i;
Lindex ind, next;
bblock_p v,w,u;
dfs_nr = 0;
vertex = (bblock_p *) newmap(n);
/* allocate vertex (dynamic array). All remaining
* initializations were done by the routine
* nextblock of get.c.
*/
dfs(r);
for (i = dfs_nr; i > 1; i--) {
w = vertex[i];
for (ind = Lfirst(w->b_pred); ind != (Lindex) 0;
ind = Lnext(ind,w->b_pred)) {
v = (bblock_p) Lelem(ind);
if (UNREACHABLE(v)) continue;
u = eval(v);
if (u->B_SEMI < w->B_SEMI) {
w->B_SEMI = u->B_SEMI;
}
}
Ladd(w,&(vertex[w->B_SEMI]->B_BUCKET));
linkblocks(w->B_PARENT,w);
for (ind = Lfirst(w->B_PARENT->B_BUCKET); ind != (Lindex) 0;
ind = next) {
next = Lnext(ind,w->B_PARENT->B_BUCKET);
v = (bblock_p) Lelem(ind);
Lremove(v,&w->B_PARENT->B_BUCKET);
u = eval(v);
v->b_idom = (u->B_SEMI < v->B_SEMI ? u : w->B_PARENT);
}
}
for (i = 2; i <= dfs_nr; i++) {
w = vertex[i];
if (w->b_idom != vertex[w->B_SEMI]) {
w->b_idom = w->b_idom->b_idom;
}
}
r->b_idom = (bblock_p) 0;
oldmap(vertex,n); /* release memory for dynamic array vertex */
}

View file

@ -1,15 +0,0 @@
/* C O N T R O L F L O W
*
* I M M E D I A T E D O M I N A T O R S
*/
extern dominator(); /* (bblock_p head, short n)
* Compute for every basic block its immediate
* dominator. The dominator relation is hence
* recorded as a tree in which every node contains
* a pointer to its parent, which is its
* immediate dominator.
* 'n' is the number of nodes (basic blocks) in
* the control flow graph.
*/

View file

@ -1,400 +0,0 @@
/* C O N T R O L F L O W
*
* C F _ L O O P . C
*/
#include "../share/types.h"
#include "../share/debug.h"
#include "../share/lset.h"
#include "../share/alloc.h"
#include "../share/aux.h"
#include "cf.h"
#define MARK_STRONG(b) b->b_flags |= BF_STRONG
#define MARK_FIRM(b) b->b_flags |= BF_FIRM
#define BF_MARK 04
#define MARK(b) b->b_flags |= BF_MARK
#define MARKED(b) (b->b_flags&BF_MARK)
#define INSIDE_LOOP(b,lp) Lis_elem(b,lp->LP_BLOCKS)
/* The algorithm to detect loops that is used here is taken
* from: Aho & Ullman, Principles of Compiler Design, section 13.1.
* The algorithm uses the dominator relation between nodes
* of the control flow graph:
* d DOM n => every path from the initial node to n goes through d.
* The dominator relation is recorded via the immediate dominator tree
* (b_idom field of bblock struct) from which the dominator relation
* can be easily computed (see procedure 'dom' below).
* The algorithm first finds 'back edges'. A back edge is an edge
* a->b in the flow graph whose head (b) dominates its tail (a).
* The 'natural loop' of back edge n->d consists of those nodes
* that can reach n without going through d. These nodes, plus d
* form the loop.
* The whole process is rather complex, because different back edges
* may result in the same loop and because loops may partly overlap
* each other (without one being nested inside the other).
*/
STATIC bool same_loop(l1,l2)
loop_p l1,l2;
{
/* Two loops are the same if:
* (1) they have the same number of basic blocks, and
* (2) the head of the back edge of the first loop
* also is part of the second loop, and
* (3) the tail of the back edge of the first loop
* also is part of the second loop.
*/
return (l1->LP_COUNT == l2->LP_COUNT &&
Lis_elem(l1->lp_entry, l2->LP_BLOCKS) &&
Lis_elem(l1->lp_end, l2->LP_BLOCKS));
}
STATIC bool inner_loop(l1,l2)
loop_p l1,l2;
{
/* Loop l1 is an inner loop of l2 if:
* (1) the first loop has fewer basic blocks than
* the second one, and
* (2) the head of the back edge of the first loop
* also is part of the second loop, and
* (3) the tail of the back edge of the first loop
* also is part of the second loop.
*/
return (l1->LP_COUNT < l2->LP_COUNT &&
Lis_elem(l1->lp_entry, l2->LP_BLOCKS) &&
Lis_elem(l1->lp_end, l2->LP_BLOCKS));
}
STATIC insrt(b,lpb,s_p)
bblock_p b;
lset *lpb;
lset *s_p;
{
/* Auxiliary routine used by 'natural_loop'.
* Note that we use a set rather than a stack,
* as Aho & Ullman do.
*/
if (!Lis_elem(b,*lpb)) {
Ladd(b,lpb);
Ladd(b,s_p);
}
}
STATIC loop_p natural_loop(d,n)
bblock_p d,n;
{
/* Find the basic blocks of the natural loop of the
* back edge 'n->d' (i.e. n->d is an edge in the control
* flow graph and d dominates n). The natural loop consists
* of those blocks which can reach n without going through d.
* We find these blocks by finding all predecessors of n,
* up to d.
*/
loop_p lp;
bblock_p m;
lset loopblocks;
Lindex pi;
lset s;
lp = newloop();
lp->lp_extend = newcflpx();
lp->lp_entry = d; /* loop entry block */
lp->lp_end = n; /* tail of back edge */
s = Lempty_set();
loopblocks = Lempty_set();
Ladd(d,&loopblocks);
insrt(n,&loopblocks,&s);
while ((pi = Lfirst(s)) != (Lindex) 0) {
m = (bblock_p) Lelem(pi);
Lremove(m,&s);
for (pi = Lfirst(m->b_pred); pi != (Lindex) 0;
pi = Lnext(pi,m->b_pred)) {
insrt((bblock_p) Lelem(pi),&loopblocks,&s);
}
}
lp->LP_BLOCKS = loopblocks;
lp->LP_COUNT = Lnrelems(loopblocks);
return lp;
}
STATIC loop_p org_loop(lp,loops)
loop_p lp;
lset loops;
{
/* See if the loop lp was already found via another
* back edge; if so return this loop; else return 0.
*/
register Lindex li;
for (li = Lfirst(loops); li != (Lindex) 0; li = Lnext(li,loops)) {
if (same_loop((loop_p) Lelem(li), lp)) {
#ifdef DEBUG
/* printf("messy loop found\n"); */
#endif
return (loop_p) Lelem(li);
}
}
return (loop_p) 0;
}
STATIC collapse_loops(loops_p)
lset *loops_p;
{
register Lindex li1, li2;
register loop_p lp1,lp2;
for (li1 = Lfirst(*loops_p); li1 != (Lindex) 0; li1 = Lnext(li1,*loops_p)) {
lp1 = (loop_p) Lelem(li1);
lp1->lp_level = (short) 0;
for (li2 = Lfirst(*loops_p); li2 != (Lindex) 0;
li2 = Lnext(li2,*loops_p)) {
lp2 = (loop_p) Lelem(li2);
if (lp1 != lp2 && lp1->lp_entry == lp2->lp_entry) {
Ljoin(lp2->LP_BLOCKS,&lp1->LP_BLOCKS);
oldcflpx(lp2->lp_extend);
Lremove(lp2,loops_p);
}
}
}
}
STATIC loop_per_block(lp)
loop_p lp;
{
bblock_p b;
/* Update the b_loops sets */
register Lindex bi;
for (bi = Lfirst(lp->LP_BLOCKS); bi != (Lindex) 0;
bi = Lnext(bi,lp->LP_BLOCKS)) {
b = (bblock_p) Lelem(bi);
Ladd(lp,&(b->b_loops));
}
}
STATIC loop_attrib(loops)
lset loops;
{
/* Compute several attributes */
register Lindex li;
register loop_p lp;
loop_id lastlpid = 0;
for (li = Lfirst(loops); li != (Lindex) 0; li = Lnext(li,loops)) {
lp = (loop_p) Lelem(li);
lp->lp_id = ++lastlpid;
loop_per_block(lp);
}
}
STATIC nest_levels(loops)
lset loops;
{
/* Compute the nesting levels of all loops of
* the current procedure. For every loop we just count
* all loops of which the former is an inner loop.
* The running time is quadratic in the number of loops
* of the current procedure. As this number tends to be
* very small, there is no cause for alarm.
*/
register Lindex li1, li2;
register loop_p lp;
for (li1 = Lfirst(loops); li1 != (Lindex) 0; li1 = Lnext(li1,loops)) {
lp = (loop_p) Lelem(li1);
lp->lp_level = (short) 0;
for (li2 = Lfirst(loops); li2 != (Lindex) 0;
li2 = Lnext(li2,loops)) {
if (inner_loop(lp,(loop_p) Lelem(li2))) {
lp->lp_level++;
}
}
}
}
STATIC cleanup(loops)
lset loops;
{
/* Throw away the LP_BLOCKS sets */
register Lindex i;
for (i = Lfirst(loops); i != (Lindex) 0; i = Lnext(i,loops)) {
Ldeleteset(((loop_p) Lelem(i))->LP_BLOCKS);
}
}
STATIC bool does_exit(b,lp)
bblock_p b;
loop_p lp;
{
/* See if b may exit the loop, i.e. if it
* has a successor outside the loop
*/
Lindex i;
for (i = Lfirst(b->b_succ); i != (Lindex) 0; i = Lnext(i,b->b_succ)) {
if (!INSIDE_LOOP(Lelem(i),lp)) return TRUE;
}
return FALSE;
}
STATIC mark_succ(b,lp)
bblock_p b;
loop_p lp;
{
Lindex i;
bblock_p succ;
for (i = Lfirst(b->b_succ); i != (Lindex) 0; i = Lnext(i,b->b_succ)) {
succ = (bblock_p) Lelem(i);
if (succ != b && succ != lp->lp_entry && INSIDE_LOOP(succ,lp) &&
!MARKED(succ)) {
MARK(succ);
mark_succ(succ,lp);
}
}
}
STATIC mark_blocks(lp)
loop_p lp;
{
/* Mark the strong and firm blocks of a loop.
* The last set of blocks consists of the end-block
* of the loop (i.e. the head of the back edge
* of the natural loop) and its dominators
* (including the loop entry block, i.e. the
* tail of the back edge).
*/
register bblock_p b;
/* First mark all blocks that are the successor of a
* block that may exit the loop (i.e. contains a
* -possibly conditional- jump to somewhere outside
* the loop.
*/
if (lp->LP_MESSY) return; /* messy loops are hopeless cases */
for (b = lp->lp_entry; b != (bblock_p) 0; b = b->b_next) {
if (!MARKED(b) && does_exit(b,lp)) {
mark_succ(b,lp);
}
}
/* Now find all firm blocks. A block is strong
* if it is firm and not marked.
*/
for (b = lp->lp_end; ; b = b->b_idom) {
MARK_FIRM(b);
if (!MARKED(b)) {
MARK_STRONG(b);
}
if (b == lp->lp_entry) break;
}
}
STATIC mark_loopblocks(loops)
lset loops;
{
/* Determine for all loops which basic blocks
* of the loop are strong (i.e. are executed
* during every iteration) and which blocks are
* firm (i.e. executed during every iteration with
* the only possible exception of the last one).
*/
Lindex i;
loop_p lp;
for (i = Lfirst(loops); i != (Lindex) 0; i = Lnext(i,loops)) {
lp = (loop_p) Lelem(i);
mark_blocks(lp);
}
}
loop_detection(p)
proc_p p;
{
/* Find all natural loops of procedure p. Every loop is
* assigned a unique identifying number, a set of basic
* blocks, a loop entry block and a nesting level number.
* Every basic block is assigned a nesting level number
* and a set of loops it is part of.
*/
lset loops; /* the set of all loops */
loop_p lp,org;
register bblock_p b;
bblock_p s;
Lindex si;
loops = Lempty_set();
for (b = p->p_start; b != (bblock_p) 0; b = b->b_next) {
for (si = Lfirst(b->b_succ); si != (Lindex) 0;
si = Lnext(si,b->b_succ)) {
s = (bblock_p) Lelem(si);
if (dom(s,b)) {
/* 'b->s' is a back edge */
lp = natural_loop(s,b);
if ((org = org_loop(lp,loops)) == (loop_p) 0) {
/* new loop */
Ladd(lp,&loops);
} else {
/* Same loop, generated by several back
* edges; such a loop is called a messy
* loop.
*/
org->LP_MESSY = TRUE;
Ldeleteset(lp->LP_BLOCKS);
oldcflpx(lp->lp_extend);
oldloop(lp);
}
}
}
}
collapse_loops(&loops);
loop_attrib(loops);
nest_levels(loops);
mark_loopblocks(loops); /* determine firm and strong blocks */
cleanup(loops);
p->p_loops = loops;
}

View file

@ -1,14 +0,0 @@
/* C O N T R O L F L O W
*
* L O O P D E T E C T I O N
*/
extern loop_detection(); /* (proc_p p)
* Detect all loops of procedure p.
* Every basic block of p is assigned
* a set of all loops it is part of.
* For every loop we record the number
* of blocks it contains, the loop entry
* block and its nesting level (0 = outer
* loop, 1 = loop within loop etc.).
*/

View file

@ -1,250 +0,0 @@
/* C O N T R O L F L O W
*
* C F _ S U C C . C
*/
#include <stdio.h>
#include "../share/types.h"
#include "../share/def.h"
#include "../share/debug.h"
#include "../share/global.h"
#include "../share/lset.h"
#include "../share/cset.h"
#include "../../../h/em_spec.h"
#include "../../../h/em_pseu.h"
#include "../../../h/em_flag.h"
#include "../../../h/em_mnem.h"
#include "cf.h"
#include "../share/map.h"
extern char em_flag[];
STATIC succeeds(succ,pred)
bblock_p succ, pred;
{
assert(pred != (bblock_p) 0);
if (succ != (bblock_p) 0) {
Ladd(succ, &pred->b_succ);
Ladd(pred, &succ->b_pred);
}
}
#define IS_RETURN(i) (i == op_ret || i == op_rtt)
#define IS_CASE_JUMP(i) (i == op_csa || i == op_csb)
#define IS_UNCOND_JUMP(i) (i <= sp_lmnem && (em_flag[i-sp_fmnem] & EM_FLO) == FLO_T)
#define IS_COND_JUMP(i) (i <= sp_lmnem && (em_flag[i-sp_fmnem] & EM_FLO) == FLO_C)
#define TARGET(lnp) (lbmap[INSTRLAB(lnp)])
#define ATARGET(arg) (lbmap[arg->a_a.a_instrlab])
STATIC arg_p skip_const(arg)
arg_p arg;
{
assert(arg != (arg_p) 0);
switch(arg->a_type) {
case ARGOFF:
case ARGICN:
case ARGUCN:
break;
default:
error("bad case descriptor");
}
return arg->a_next;
}
STATIC arg_p use_label(arg,b)
arg_p arg;
bblock_p b;
{
if (arg->a_type == ARGINSTRLAB) {
/* arg is a non-null label */
succeeds(ATARGET(arg),b);
}
return arg->a_next;
}
STATIC case_flow(instr,desc,b)
short instr;
line_p desc;
bblock_p b;
{
/* Analyse the case descriptor (given as a ROM pseudo instruction).
* Every instruction label appearing in the descriptor
* heads a basic block that is a successor of the block
* in which the case instruction appears (b).
*/
register arg_p arg;
assert(instr == op_csa || instr == op_csb);
assert(TYPE(desc) == OPLIST);
arg = ARG(desc);
arg = use_label(arg,b);
/* See if there is a default label. If so, then
* its block is a successor of b. Set arg to
* next argument.
*/
if (instr == op_csa) {
arg = skip_const(arg); /* skip lower bound */
arg = skip_const(arg); /* skip lower-upper bound */
while (arg != (arg_p) 0) {
/* All following arguments are case labels
* or zeroes.
*/
arg = use_label(arg,b);
}
} else {
/* csb instruction */
arg = skip_const(arg); /* skip #entries */
while (arg != (arg_p) 0) {
/* All following arguments are alternatively
* an index and an instruction label (possibly 0).
*/
arg = skip_const(arg); /* skip index */
arg = use_label(arg,b);
}
}
}
STATIC line_p case_descr(lnp)
line_p lnp;
{
/* lnp is the instruction just before a csa or csb,
* so it is the instruction that pushes the address
* of a case descriptor on the stack. Find that
* descriptor, i.e. a rom pseudo instruction.
* Note that this instruction will always be part
* of the procedure in which the csa/csb occurs.
*/
register line_p l;
dblock_p d;
obj_p obj;
dblock_id id;
if (lnp == (line_p) 0 || (INSTR(lnp)) != op_lae) {
error("cannot find 'lae descr' before csa/csb");
}
/* We'll first find the ROM and its dblock_id */
obj = OBJ(lnp);
if (obj->o_off != (offset) 0) {
error("bad 'lae descr' before csa/csb");
/* We require a descriptor to be an entire rom,
* not part of a rom.
*/
}
d = obj->o_dblock;
assert(d != (dblock_p) 0);
if (d->d_pseudo != DROM) {
error("case descriptor must be in rom");
}
id = d->d_id;
/* We'll use the dblock_id to find the defining occurrence
* of the rom in the EM text (i.e. a rom pseudo). As all
* pseudos appear at the beginning of a procedure, we only
* have to look in its first basic block.
*/
assert(curproc != (proc_p) 0);
assert(curproc->p_start != (bblock_p) 0);
l = curproc->p_start->b_start; /* first instruction of curproc */
while (l != (line_p) 0) {
if ((INSTR(l)) == ps_sym &&
SHORT(l) == id) {
/* found! */
assert((INSTR(l->l_next)) == ps_rom);
return l->l_next;
}
l = l->l_next;
}
error("cannot find rom pseudo for case descriptor");
/* NOTREACHED */
}
STATIC last2_instrs(b,last_out,prev_out)
bblock_p b;
line_p *last_out,*prev_out;
{
/* Determine the last and one-but-last instruction
* of basic block b. An end-pseudo is not regarded
* as an instruction. If the block contains only 1
* instruction, prev_out is 0.
*/
register line_p l1,l2;
l2 = b->b_start; /* first instruction of b */
assert(l2 != (line_p) 0); /* block can not be empty */
if ((l1 = l2->l_next) == (line_p) 0 || INSTR(l1) == ps_end) {
*last_out = l2; /* single instruction */
*prev_out = (line_p) 0;
} else {
while(l1->l_next != (line_p) 0 && INSTR(l1->l_next) != ps_end) {
l2 = l1;
l1 = l1->l_next;
}
*last_out = l1;
*prev_out = l2;
}
}
control_flow(head)
bblock_p head;
{
/* compute the successor and predecessor relation
* for every basic block.
*/
register bblock_p b;
line_p lnp, prev;
short instr;
for (b = head; b != (bblock_p) 0; b = b->b_next) {
/* for every basic block, in textual order, do */
last2_instrs(b, &lnp, &prev);
/* find last and one-but-last instruction */
instr = INSTR(lnp);
/* The last instruction of the basic block
* determines the set of successors of the block.
*/
if (IS_CASE_JUMP(instr)) {
case_flow(instr,case_descr(prev),b);
/* If lnp is a csa or csb, then the instruction
* just before it (i.e. prev) must be the
* instruction that pushes the address of the
* case descriptor. This descriptor is found
* and analysed in order to build the successor
* and predecessor sets of b.
*/
} else {
if (!IS_RETURN(instr)) {
if (IS_UNCOND_JUMP(instr)) {
succeeds(TARGET(lnp),b);
} else {
if (IS_COND_JUMP(instr)) {
succeeds(TARGET(lnp),b);
succeeds(b->b_next, b);
/* Textually next block is
* a successor of b.
*/
} else {
/* normal instruction */
succeeds(b->b_next, b);
}
}
}
}
}
}

View file

@ -1,10 +0,0 @@
/* C O N T R O L F L O W
*
* S U C C E S S O R / P R E D E C E S S O R R E L A T I O N S
*/
extern control_flow(); /* (bblock_p head)
* Compute for every basic block
* its successors and predecessors
* in the control flow graph.
*/

View file

@ -1,60 +0,0 @@
EMH=../../../h
EMLIB=../../../lib
SHR=../share
CFILES=\
cj.c
OFILES=\
cj.o
HFILES=
PRFILES=\
$(CFILES) $(HFILES) Makefile
SHARE_OFILES=\
$(SHR)/get.o $(SHR)/put.o $(SHR)/alloc.o $(SHR)/global.o $(SHR)/debug.o \
$(SHR)/files.o $(SHR)/map.o $(SHR)/lset.o $(SHR)/cset.o $(SHR)/aux.o \
$(SHR)/stack_chg.o $(SHR)/go.o
SHARE_MFILES=\
$(SHR)/get.m $(SHR)/put.m $(SHR)/alloc.m $(SHR)/global.m $(SHR)/debug.m \
$(SHR)/files.m $(SHR)/map.m $(SHR)/lset.m $(SHR)/cset.m $(SHR)/aux.m $(SHR)/stack_chg.m $(SHR)/go.m
cj: $(OFILES)
$(CC) -o \
cj $(LDFLAGS) $(OFILES) $(SHARE_OFILES) $(EMLIB)/em_data.a
cj_ack: $(CFILES) $(SHARE_MFILES)
$(CC) -c.o $(CFLAGS) $(CFILES) $(SHARE_MFILES)
$(CC) -o cj -.c $(LDFLAGS) cj.o $(EMLIB)/em_data.a
lint:
lint $(LINTFLAGS) $(CPPFLAGS) $(CFILES)
pr: $(PRFILES)
@pr $?
@touch pr
depend:
$(SHR)/makedepend
# the next lines are generated automatically
# AUTOAUTOAUTOAUTOAUTOAUTO
cj.o: ../../../h/em_mnem.h
cj.o: ../../../h/em_spec.h
cj.o: ../share/alloc.h
cj.o: ../share/aux.h
cj.o: ../share/debug.h
cj.o: ../share/def.h
cj.o: ../share/files.h
cj.o: ../share/get.h
cj.o: ../share/global.h
cj.o: ../share/go.h
cj.o: ../share/lset.h
cj.o: ../share/map.h
cj.o: ../share/put.h
cj.o: ../share/stack_chg.h
cj.o: ../share/types.h

View file

@ -1,355 +0,0 @@
/* C R O S S J U M P I N G
*
* CJ.H
*
*/
#include <stdio.h>
#include "../share/types.h"
#include "../share/debug.h"
#include "../share/global.h"
#include "../share/files.h"
#include "../share/get.h"
#include "../share/put.h"
#include "../share/lset.h"
#include "../share/map.h"
#include "../share/alloc.h"
#include "../share/aux.h"
#include "../share/def.h"
#include "../share/stack_chg.h"
#include "../share/go.h"
#include "../../../h/em_mnem.h"
#include "../../../h/em_spec.h"
/* Cross jumping performs optimzations like:
*
* if cond then goto L1; if cond then goto L1
* S1; -----> S1;
* S2; goto L3;
* goto L2; L1:
* L1: S3;
* S3; L3:
* S2; S2;
* L2:
*
* CJ looks for two basic blocks b1 and b2 with the following properties:
* - there exists a basic block S such that SUCC(b1) = SUCC(b2) = {S}
* (so both have only 1 successor)
* - the last N (N > 0) instructions of b1 and b2, not counting a possible
* BRAnch instruction, are the same.
* As a result of the first condition, at least of the two blocks must end
* on an (unconditional) BRAnch instruction. If both end on a BRA, one block
* is chosen at random. Assume this block is b1. A new label L is put just
* before the N common instructions of block b2 (so this block is split
* into two). The BRA of b1 is changed into a BRA L. So dynamically the same
* instructions are executed in a slightly different order; yet the size of
* the code has become smaller.
*/
STATIC int Scj; /* number of optimizations found */
#define DLINK(l1,l2) l1->l_next=l2; l2->l_prev=l1
STATIC bool same_instr(l1,l2)
line_p l1,l2;
{
/* See if l1 and l2 are the same instruction */
if (l1 == 0 || l2 == 0 || TYPE(l1) != TYPE(l2)) return FALSE;
if (INSTR(l1) != INSTR(l2)) return FALSE;
switch(TYPE(l1)) {
case OPSHORT: return SHORT(l1) == SHORT(l2);
case OPOFFSET: return OFFSET(l1) == OFFSET(l2);
case OPPROC: return PROC(l1) == PROC(l2);
case OPOBJECT: return OBJ(l1) == OBJ(l2);
case OPINSTRLAB: return INSTRLAB(l1) == INSTRLAB(l2);
case OPNO: return TRUE;
default: return FALSE;
}
}
STATIC line_p last_mnem(b)
bblock_p b;
{
/* Determine the last line of a list */
register line_p l;
for (l = b->b_start; l->l_next != (line_p) 0; l = l->l_next);
while (l != (line_p) 0 && (INSTR(l) < sp_fmnem || INSTR(l) > sp_lmnem)) {
l = PREV(l);
}
return l;
}
STATIC bool is_desirable(text)
line_p text;
{
/* We avoid to generate a BRAnch in the middle of some expression,
* as the code generator will write the contents of the fakestack
* to the real stack if it encounters a BRA. We do not avoid to
* split the parameter-pushing code of a subroutine call into two,
* as the parameters are pushed on the real stack anyway.
* So e.g. "LOL a ; LOL b; ADI" will not be split, but
* "LOL a; LOL b; CAL f" may be split.
*/
line_p l;
bool ok;
int stack_diff,pop,push;
stack_diff = 0;
for (l = text; l != (line_p) 0; l = l->l_next) {
switch(INSTR(l)) {
case op_cal:
case op_asp:
case op_bra:
return TRUE;
}
line_change(l,&ok,&pop,&push);
/* printf("instr %d, pop %d, push %d, ok %d\n",INSTR(l),pop,push,ok); */
if (!ok || (stack_diff -= pop) < 0) {
return FALSE;
} else {
stack_diff += push;
}
}
return TRUE;
}
STATIC cp_loops(b1,b2)
bblock_p b1,b2;
{
/* Copy the loopset of b2 to b1 */
Lindex i;
loop_p lp;
for (i = Lfirst(b2->b_loops); i != (Lindex) 0;
i = Lnext(i,b2->b_loops)) {
lp = (loop_p) Lelem(i);
Ladd(lp,&b1->b_loops);
}
}
STATIC jump_cross(l1,l2,b1,b2)
line_p l1,l2;
bblock_p b1,b2;
{
/* A cross-jump from block b2 to block b1 is found; the code in
* block b2 from line l2 up to the BRAnch is removed; block b1 is
* split into two; the second part consists of a new label
* followed by the code from l1 till the end of the block.
*/
line_p l;
bblock_p b;
bblock_p s;
/* First adjust the control flow graph */
b = freshblock(); /* create a new basic block */
b->b_succ = b1->b_succ;
/* SUCC(b1) = {b} */
b1->b_succ = Lempty_set(); Ladd(b,&b1->b_succ);
/* SUCC(b2) = {b} */
Ldeleteset(b2->b_succ); b2->b_succ = Lempty_set(); Ladd(b,&b2->b_succ);
/* PRED(b) = {b1,b2} */
b->b_pred = Lempty_set(); Ladd(b1,&b->b_pred); Ladd(b2,&b->b_pred);
/* PRED(SUCC(b)) := PRED(SUCC(b)) - {b1,b2} + {b} */
assert(Lnrelems(b->b_succ) == 1);
s = (bblock_p) Lelem(Lfirst(b->b_succ));
Lremove(b1,&s->b_pred); Lremove(b2,&s->b_pred); Ladd(b,&s->b_pred);
cp_loops(b,b1);
b->b_idom = common_dom(b1,b2);
b->b_flags = b1->b_flags;
b->b_next = b1->b_next;
b1->b_next = b;
/* Now adjust the EM text */
l = PREV(l1);
if (l == (line_p) 0) {
b1->b_start = (line_p) 0;
} else {
l->l_next = (line_p) 0;
}
l = newline(OPINSTRLAB);
l->l_instr = op_lab;
INSTRLAB(l) = freshlabel();
DLINK(l,l1);
b->b_start = l;
for (l = l2; INSTR(l) != op_bra; l = l->l_next) {
assert (l != (line_p) 0);
rm_line(l,b2);
}
INSTRLAB(l) = INSTRLAB(b->b_start);
}
STATIC bool try_tail(b1,b2)
bblock_p b1,b2;
{
/* See if b1 and b2 end on the same sequence of instructions */
line_p l1,l2;
bblock_p b = (bblock_p) 0;
int cnt = 0;
/* printf("try block %d and %d\n",b1->b_id,b2->b_id); */
if (b1->b_start == (line_p) 0 || b2->b_start == (line_p) 0) return FALSE;
l1 = last_mnem(b1);
l2 = last_mnem(b2);
if (l1 == (line_p) 0 || l2 == (line_p) 0) return FALSE;
/* printf("consider:\n"); showinstr(l1); showinstr(l2); */
if (INSTR(l1) == op_bra) {
b = b1;
l1 = PREV(l1);
}
if (INSTR(l2) == op_bra) {
b = b2;
l2 = PREV(l2);
}
assert(b != (bblock_p) 0);
while(same_instr(l1,l2)) {
cnt++;
l1 = PREV(l1);
l2 = PREV(l2);
/* printf("consider:\n"); showinstr(l1); showinstr(l2); */
}
if (cnt >= 1) {
l1 = (l1 == 0 ? b1->b_start : l1->l_next);
l2 = (l2 == 0 ? b2->b_start : l2->l_next);
if (is_desirable(l1)) {
if (b == b1) {
jump_cross(l2,l1,b2,b1);
Scj++;
} else {
jump_cross(l1,l2,b1,b2);
Scj++;
}
return TRUE;
}
}
return FALSE;
}
STATIC bool try_pred(b)
bblock_p b;
{
/* See if there is any pair (b1,b2), both in PRED(b) for
* which we can perform cross jumping.
*/
register bblock_p b1,b2;
register Lindex i,j;
lset s = b->b_pred;
for (i = Lfirst(s); i != (Lindex) 0; i = Lnext(i,s)) {
b1 = (bblock_p) Lelem(i);
if (Lnrelems(b1->b_succ) != 1) continue;
for (j = Lfirst(s); j != (Lindex) 0; j = Lnext(j,s)) {
b2 = (bblock_p) Lelem(j);
if (b1 != b2 && Lnrelems(b2->b_succ) == 1) {
if (try_tail(b1,b2)) return TRUE;
}
}
}
return FALSE;
}
cj_optimize(p)
proc_p p;
{
/* Perform cross jumping for procedure p.
* In case cases a cross-jumping optimization which give
* new opportunities for further cross-jumping optimizations.
* Hence we repeat the whole process for the entire procedure,
* untill we find no further optimizations.
*/
bblock_p b;
bool changes = TRUE;
while(changes) {
changes = FALSE;
b = p->p_start;
while (b != (bblock_p) 0) {
if (try_pred(b)) {
changes = TRUE;
} else {
b = b->b_next;
}
}
}
}
main(argc,argv)
int argc;
char *argv[];
{
go(argc,argv,no_action,cj_optimize,no_action,no_action);
report("cross jumps",Scj);
exit(0);
}
/******
* Debugging stuff
*/
extern char em_mnem[]; /* The mnemonics of the EM instructions. */
STATIC showinstr(lnp) line_p lnp; {
/* Makes the instruction in `lnp' human readable. Only lines that
* can occur in expressions that are going to be eliminated are
* properly handled.
*/
if (lnp == 0) return;
if (INSTR(lnp) < sp_fmnem || INSTR(lnp) > sp_lmnem) {
printf("\t*** ?\n");
return;
}
printf("\t%s", &em_mnem[4 * (INSTR(lnp)-sp_fmnem)]);
switch (TYPE(lnp)) {
case OPNO:
break;
case OPSHORT:
printf(" %d", SHORT(lnp)); break;
case OPOBJECT:
printf(" %d", OBJ(lnp)->o_id); break;
case OPOFFSET:
printf(" %D", OFFSET(lnp)); break;
default:
printf(" ?"); break;
}
printf("\n");
} /* showinstr */
STATIC print_list(list,b1,b2,p)
line_p list;
bblock_p b1,b2;
proc_p p;
{
line_p l;
printf("block %d and %d of proc %d:\n",b1->b_id,b2->b_id,p->p_id);
for (l = list; l != 0; l = l->l_next) {
showinstr(l);
}
}

View file

@ -1,178 +0,0 @@
EMH=../../../h
EMLIB=../../../lib
SHR=../share
CFILES=\
cs.c cs_alloc.c cs_aux.c cs_avail.c cs_debug.c cs_elim.c \
cs_entity.c cs_kill.c cs_partit.c cs_profit.c cs_getent.c \
cs_stack.c cs_vnm.c
OFILES=\
cs.o cs_alloc.o cs_aux.o cs_avail.o cs_debug.o cs_elim.o \
cs_entity.o cs_kill.o cs_partit.o cs_profit.o cs_getent.o \
cs_stack.o cs_vnm.o
HFILES=\
cs.h cs_alloc.h cs_aux.h cs_avail.h cs_debug.h cs_elim.h \
cs_entity.h cs_kill.h cs_partit.h cs_profit.h cs_getent.h \
cs_stack.h cs_vnm.h
PRFILES=\
$(CFILES) $(HFILES) Makefile
SHARE_OFILES=\
$(SHR)/get.o $(SHR)/put.o $(SHR)/alloc.o $(SHR)/global.o $(SHR)/debug.o\
$(SHR)/files.o $(SHR)/map.o $(SHR)/lset.o $(SHR)/cset.o $(SHR)/aux.o\
$(SHR)/go.o
SHARE_MFILES=\
$(SHR)/get.m $(SHR)/put.m $(SHR)/alloc.m $(SHR)/global.m $(SHR)/debug.m\
$(SHR)/files.m $(SHR)/map.m $(SHR)/lset.m $(SHR)/cset.m $(SHR)/aux.m\
$(SHR)/go.m
cs: $(OFILES)
$(CC) -o cs $(LDFLAGS) $(OFILES) $(SHARE_OFILES) $(EMLIB)/em_data.a
cs_ack: $(CFILES) $(SHARE_MFILES)
$(CC) -c.o $(CFLAGS) $(CFILES) $(SHARE_MFILES)
$(CC) -o cs -.c $(LDFLAGS) cs.o $(EMLIB)/em_data.a
lint:
lint $(LINTFLAGS) $(CPPFLAGS) $(CFILES)
pr: $(PRFILES)
@pr $?
@touch pr
depend:
$(SHR)/makedepend
# the next lines are generated automatically
# AUTOAUTOAUTOAUTOAUTOAUTO
cs.o: ../share/debug.h
cs.o: ../share/go.h
cs.o: ../share/types.h
cs.o: cs.h
cs.o: cs_aux.h
cs.o: cs_avail.h
cs.o: cs_debug.h
cs.o: cs_elim.h
cs.o: cs_entity.h
cs.o: cs_profit.h
cs.o: cs_stack.h
cs.o: cs_vnm.h
cs_alloc.o: ../share/alloc.h
cs_alloc.o: ../share/types.h
cs_alloc.o: cs.h
cs_aux.o: ../share/aux.h
cs_aux.o: ../share/debug.h
cs_aux.o: ../share/global.h
cs_aux.o: ../share/lset.h
cs_aux.o: ../share/types.h
cs_aux.o: cs.h
cs_aux.o: cs_entity.h
cs_avail.o: ../../../h/em_mnem.h
cs_avail.o: ../share/aux.h
cs_avail.o: ../share/debug.h
cs_avail.o: ../share/global.h
cs_avail.o: ../share/lset.h
cs_avail.o: ../share/types.h
cs_avail.o: cs.h
cs_avail.o: cs_alloc.h
cs_avail.o: cs_aux.h
cs_avail.o: cs_getent.h
cs_debug.o: ../../../h/em_spec.h
cs_debug.o: ../share/debug.h
cs_debug.o: ../share/lset.h
cs_debug.o: ../share/types.h
cs_debug.o: cs.h
cs_debug.o: cs_aux.h
cs_debug.o: cs_avail.h
cs_debug.o: cs_entity.h
cs_elim.o: ../../../h/em_mnem.h
cs_elim.o: ../../../h/em_reg.h
cs_elim.o: ../share/alloc.h
cs_elim.o: ../share/aux.h
cs_elim.o: ../share/debug.h
cs_elim.o: ../share/global.h
cs_elim.o: ../share/lset.h
cs_elim.o: ../share/types.h
cs_elim.o: cs.h
cs_elim.o: cs_alloc.h
cs_elim.o: cs_aux.h
cs_elim.o: cs_avail.h
cs_elim.o: cs_debug.h
cs_elim.o: cs_partit.h
cs_elim.o: cs_profit.h
cs_entity.o: ../share/debug.h
cs_entity.o: ../share/global.h
cs_entity.o: ../share/lset.h
cs_entity.o: ../share/types.h
cs_entity.o: cs.h
cs_entity.o: cs_aux.h
cs_getent.o: ../../../h/em_mnem.h
cs_getent.o: ../share/aux.h
cs_getent.o: ../share/debug.h
cs_getent.o: ../share/global.h
cs_getent.o: ../share/types.h
cs_getent.o: cs.h
cs_getent.o: cs_aux.h
cs_getent.o: cs_entity.h
cs_getent.o: cs_stack.h
cs_kill.o: ../../../h/em_mnem.h
cs_kill.o: ../share/aux.h
cs_kill.o: ../share/cset.h
cs_kill.o: ../share/debug.h
cs_kill.o: ../share/global.h
cs_kill.o: ../share/lset.h
cs_kill.o: ../share/types.h
cs_kill.o: cs.h
cs_kill.o: cs_aux.h
cs_kill.o: cs_avail.h
cs_kill.o: cs_debug.h
cs_kill.o: cs_entity.h
cs_partit.o: ../../../h/em_mnem.h
cs_partit.o: ../../../h/em_pseu.h
cs_partit.o: ../../../h/em_reg.h
cs_partit.o: ../../../h/em_spec.h
cs_partit.o: ../share/aux.h
cs_partit.o: ../share/debug.h
cs_partit.o: ../share/global.h
cs_partit.o: ../share/types.h
cs_partit.o: cs.h
cs_partit.o: cs_stack.h
cs_profit.o: ../../../h/em_mnem.h
cs_profit.o: ../../../h/em_spec.h
cs_profit.o: ../share/aux.h
cs_profit.o: ../share/cset.h
cs_profit.o: ../share/debug.h
cs_profit.o: ../share/global.h
cs_profit.o: ../share/lset.h
cs_profit.o: ../share/types.h
cs_profit.o: cs.h
cs_profit.o: cs_aux.h
cs_profit.o: cs_avail.h
cs_profit.o: cs_partit.h
cs_stack.o: ../share/aux.h
cs_stack.o: ../share/debug.h
cs_stack.o: ../share/global.h
cs_stack.o: ../share/types.h
cs_stack.o: cs.h
cs_stack.o: cs_aux.h
cs_valno.o: ../share/debug.h
cs_valno.o: ../share/types.h
cs_valno.o: cs.h
cs_vnm.o: ../../../h/em_mnem.h
cs_vnm.o: ../share/aux.h
cs_vnm.o: ../share/debug.h
cs_vnm.o: ../share/global.h
cs_vnm.o: ../share/types.h
cs_vnm.o: cs.h
cs_vnm.o: cs_alloc.h
cs_vnm.o: cs_aux.h
cs_vnm.o: cs_avail.h
cs_vnm.o: cs_entity.h
cs_vnm.o: cs_getent.h
cs_vnm.o: cs_kill.h
cs_vnm.o: cs_partit.h
cs_vnm.o: cs_stack.h

View file

@ -1,78 +0,0 @@
/* C O M M O N S U B E X P R E S S I O N E L I M I N A T I O N */
#include <stdio.h>
#include "../share/types.h"
#include "../share/lset.h"
#include "../share/debug.h"
#include "../share/go.h"
#include "cs.h"
#include "cs_aux.h"
#include "cs_avail.h"
#include "cs_debug.h"
#include "cs_elim.h"
#include "cs_entity.h"
#include "cs_profit.h"
#include "cs_stack.h"
#include "cs_vnm.h"
int Scs; /* Number of optimizations found. */
STATIC cs_clear()
{
clr_avails();
clr_entities();
clr_stack();
start_valnum();
}
STATIC cs_optimize(p)
proc_p p;
{
/* Optimize all basic blocks of one procedure. */
register bblock_p rbp, bdone;
avails = (avail_p) 0;
entities = Lempty_set();
cs_clear();
rbp = p->p_start;
while (rbp != (bblock_p) 0) {
/* First we build a list of common expressions with the
* value numbering algorithm. We take blocks in textual order
* as long as the next block can only be reached through the
* block we have just done. Note that if a block is preceded
* by itself, the number of predecessors is greater than 1,
* but the previous block can still be its immediate dominator.
*/
do { vnm(rbp); bdone = rbp;
OUTTRACE("basic block %d processed", bdone->b_id);
rbp = rbp->b_next;
} while (rbp != (bblock_p) 0 && rbp->b_idom == bdone &&
Lnrelems(rbp->b_pred) == 1
);
OUTTRACE("value numbering completed", 0);
OUTAVAILS(); OUTENTITIES();
/* Now we put out the instructions without common
* subexpressions but with the use of temporaries,
* which will be local variables of procedure p.
*/
eliminate(p);
cs_clear();
}
}
main(argc, argv)
int argc;
char *argv[];
{
Scs = 0;
go(argc, argv, no_action, cs_optimize, cs_machinit, no_action);
report("Duplicate expressions eliminated", Scs);
exit(0);
}

View file

@ -1,123 +0,0 @@
typedef short valnum;
typedef struct entity *entity_p;
typedef struct avail *avail_p;
typedef struct token *token_p;
typedef struct occur *occur_p;
struct token {
valnum tk_vn;
offset tk_size;
line_p tk_lfirst; /* Textually first instruction, involved
* in pushing this token.
*/
};
/* We distinguish these entities. */
#define ENCONST 0
#define ENLOCAL 1
#define ENEXTERNAL 2
#define ENINDIR 3
#define ENOFFSETTED 4
#define ENALOCAL 5
#define ENAEXTERNAL 6
#define ENAOFFSETTED 7
#define ENALOCBASE 8
#define ENAARGBASE 9
#define ENPROC 10
#define ENFZER 11
#define ENARRELEM 12
#define ENLOCBASE 13
#define ENHEAPPTR 14
#define ENIGNMASK 15
struct entity {
valnum en_vn;
bool en_static;
byte en_kind; /* ENLOCAL, ENEXTERNAL, etc. */
offset en_size;
union {
offset en__val; /* ENCONST. */
offset en__loc; /* ENLOCAL, ENALOCAL. */
obj_p en__ext; /* ENEXTERNAL, ENAEXTERNAL. */
valnum en__ind; /* ENINDIR. */
struct {
valnum en__base;
offset en__off;
} en_offs; /* ENOFFSETTED, ENAOFFSETTED. */
offset en__levels; /* ENALOCBASE, ENAARGBASE. */
proc_p en__pro; /* ENPROC. */
struct {
valnum en__arbase;
valnum en__index;
valnum en__adesc;
} en_arr; /* ENARRELEM. */
} en_inf;
};
/* Macros to increase ease of use. */
#define en_val en_inf.en__val
#define en_loc en_inf.en__loc
#define en_ext en_inf.en__ext
#define en_ind en_inf.en__ind
#define en_base en_inf.en_offs.en__base
#define en_off en_inf.en_offs.en__off
#define en_levels en_inf.en__levels
#define en_pro en_inf.en__pro
#define en_arbase en_inf.en_arr.en__arbase
#define en_index en_inf.en_arr.en__index
#define en_adesc en_inf.en_arr.en__adesc
struct occur {
line_p oc_lfirst; /* First instruction of expression. */
line_p oc_llast; /* Last one. */
bblock_p oc_belongs; /* Basic block it belongs to. */
};
/* We distinguish these groups of instructions. */
#define SIMPLE_LOAD 0
#define EXPENSIVE_LOAD 1
#define LOAD_ARRAY 2
#define STORE_DIRECT 3
#define STORE_INDIR 4
#define STORE_ARRAY 5
#define UNAIR_OP 6
#define BINAIR_OP 7
#define TERNAIR_OP 8
#define KILL_ENTITY 9
#define SIDE_EFFECTS 10
#define FIDDLE_STACK 11
#define IGNORE 12
#define HOPELESS 13
#define BBLOCK_END 14
struct avail {
avail_p av_before; /* Ptr to earlier discovered expressions. */
byte av_instr; /* Operator instruction. */
offset av_size;
line_p av_found; /* Line where expression is first found. */
lset av_occurs; /* Set of recurrences of expression. */
entity_p av_saveloc; /* Local where result is put in. */
valnum av_result;
union {
valnum av__operand; /* EXPENSIVE_LOAD, UNAIR_OP. */
struct {
valnum av__oleft;
valnum av__oright;
} av_2; /* BINAIR_OP. */
struct {
valnum av__ofirst;
valnum av__osecond;
valnum av__othird;
} av_3; /* TERNAIR_OP. */
} av_o;
};
/* Macros to increase ease of use. */
#define av_operand av_o.av__operand
#define av_oleft av_o.av_2.av__oleft
#define av_oright av_o.av_2.av__oright
#define av_ofirst av_o.av_3.av__ofirst
#define av_osecond av_o.av_3.av__osecond
#define av_othird av_o.av_3.av__othird
extern int Scs; /* Number of optimizations found. */

View file

@ -1,44 +0,0 @@
#include "../share/types.h"
#include "../share/alloc.h"
#include "cs.h"
occur_p newoccur(l1, l2, b)
line_p l1, l2;
bblock_p b;
{
/* Allocate a new struct occur and initialize it. */
register occur_p rop;
rop = (occur_p) newcore(sizeof(struct occur));
rop->oc_lfirst = l1; rop->oc_llast = l2; rop->oc_belongs = b;
return rop;
}
oldoccur(ocp)
occur_p ocp;
{
oldcore((short *) ocp, sizeof(struct occur));
}
avail_p newavail()
{
return (avail_p) newcore(sizeof(struct avail));
}
oldavail(avp)
avail_p avp;
{
oldcore((short *) avp, sizeof(struct avail));
}
entity_p newentity()
{
return (entity_p) newcore(sizeof(struct entity));
}
oldentity(enp)
entity_p enp;
{
oldcore((short *) enp, sizeof(struct entity));
}

View file

@ -1,24 +0,0 @@
extern occur_p newoccur(); /* (line_p l1, l2; bblock_p b)
* Returns a pointer to a new struct occur
* and initializes it.
*/
extern oldoccur(); /* (occur_p ocp)
* Release the struct occur ocp points to.
*/
extern avail_p newavail(); /* ()
* Return a pointer to a new struct avail.
*/
extern oldavail(); /* (avail_p avp)
* Release the struct avail avp points to.
*/
extern entity_p newentity(); /* ()
* Return a pointer to a new struct entity.
*/
extern oldentity(); /* (entity_p enp)
* Release the struct entity enp points to.
*/

View file

@ -1,64 +0,0 @@
#include "../share/types.h"
#include "../share/debug.h"
#include "../share/aux.h"
#include "../share/global.h"
#include "../share/lset.h"
#include "cs.h"
#include "cs_entity.h"
offset array_elemsize(vn)
valnum vn;
{
/* Vn is the valuenumber of an entity that points to
* an array-descriptor. The third element of this descriptor holds
* the size of the array-elements.
* IF we can find this entity, AND IF we can find the descriptor AND IF
* this descriptor is located in ROM, then we return the size.
*/
entity_p enp;
enp = find_entity(vn);
if (enp == (entity_p) 0)
return UNKNOWN_SIZE;
if (enp->en_kind != ENAEXTERNAL)
return UNKNOWN_SIZE;
if (enp->en_ext->o_dblock->d_pseudo != DROM)
return UNKNOWN_SIZE;
return aoff(enp->en_ext->o_dblock->d_values, 2);
}
occur_p occ_elem(i)
Lindex i;
{
return (occur_p) Lelem(i);
}
entity_p en_elem(i)
Lindex i;
{
return (entity_p) Lelem(i);
}
/* The value numbers associated with each distinct value
* start at 1.
*/
STATIC valnum val_no;
valnum newvalnum()
{
/* Return a completely new value number. */
return ++val_no;
}
start_valnum()
{
/* Restart value numbering. */
val_no = 0;
}

View file

@ -1,25 +0,0 @@
extern offset array_elemsize(); /* (valnum vm)
* Returns the size of array-elements,
* if vn is the valuenumber of the
* address of an array-descriptor.
*/
extern occur_p occ_elem(); /* (Lindex i)
* Returns a pointer to the occurrence
* of which i is an index in a set.
*/
extern entity_p en_elem(); /* (Lindex i)
* Returns a pointer to the entity
* of which i is an index in a set.
*/
extern valnum newvalnum(); /* ()
* Returns a completely new
* value number.
*/
extern start_valnum(); /* ()
* Restart value numbering.
*/

View file

@ -1,203 +0,0 @@
/* M O D U L E F O R A C C E S S S I N G T H E L I S T
*
* O F A V A I L A B L E E X P R E S S I O N S
*/
#include "../../../h/em_mnem.h"
#include "../share/types.h"
#include "../share/debug.h"
#include "../share/aux.h"
#include "../share/lset.h"
#include "../share/global.h"
#include "cs.h"
#include "cs_aux.h"
#include "cs_debug.h"
#include "cs_alloc.h"
#include "cs_getent.h"
avail_p avails; /* The list of available expressions. */
STATIC bool commutative(instr)
int instr;
{
/* Is instr a commutative operator? */
switch (instr) {
case op_adf: case op_adi: case op_adu: case op_and:
case op_cms: case op_ior: case op_mlf: case op_mli:
case op_mlu:
return TRUE;
default:
return FALSE;
}
}
STATIC bool same_avail(kind, avp1, avp2)
byte kind;
avail_p avp1, avp2;
{
/* Two expressions are the same if they have the same operator,
* the same size, and their operand(s) have the same value.
* Only if the operator is commutative, the order of the operands
* does not matter.
*/
if (avp1->av_instr != avp2->av_instr) return FALSE;
if (avp1->av_size != avp2->av_size) return FALSE;
switch (kind) {
default:
assert(FALSE);
break;
case EXPENSIVE_LOAD:
case UNAIR_OP:
return avp1->av_operand == avp2->av_operand;
case BINAIR_OP:
if (commutative(avp1->av_instr & BMASK))
return avp1->av_oleft == avp2->av_oleft &&
avp1->av_oright == avp2->av_oright
||
avp1->av_oleft == avp2->av_oright &&
avp1->av_oright == avp2->av_oleft
;
else
return avp1->av_oleft == avp2->av_oleft &&
avp1->av_oright == avp2->av_oright;
case TERNAIR_OP:
return avp1->av_ofirst == avp2->av_ofirst &&
avp1->av_osecond == avp2->av_osecond &&
avp1->av_othird == avp2->av_othird;
}
/* NOTREACHED */
}
STATIC check_local(avp)
avail_p avp;
{
/* Check if the local in which the result of avp was stored,
* still holds this result. Update if not.
*/
if (avp->av_saveloc == (entity_p) 0) return; /* Nothing to check. */
if (avp->av_saveloc->en_vn != avp->av_result) {
OUTTRACE("save local changed value", 0);
avp->av_saveloc = (entity_p) 0;
}
}
STATIC entity_p result_local(size, l)
offset size;
line_p l;
{
/* If the result of an expression of size bytes is stored into a
* local for which a registermessage was generated, return a pointer
* to this local.
*/
line_p dummy;
entity_p enp;
if (l == (line_p) 0)
return (entity_p) 0;
if (INSTR(l)==op_stl && size==ws || INSTR(l)==op_sdl && size==2*ws) {
enp = getentity(l, &dummy);
if (is_regvar(enp->en_loc)) {
OUTTRACE("save local found, %D(LB)", enp->en_loc);
return enp;
}
}
return (entity_p) 0;
}
STATIC copy_avail(kind, src, dst)
int kind;
avail_p src, dst;
{
/* Copy some attributes from src to dst. */
dst->av_instr = src->av_instr;
dst->av_size = src->av_size;
switch (kind) {
default:
assert(FALSE);
break;
case EXPENSIVE_LOAD:
case UNAIR_OP:
dst->av_operand = src->av_operand;
break;
case BINAIR_OP:
dst->av_oleft = src->av_oleft;
dst->av_oright = src->av_oright;
break;
case TERNAIR_OP:
dst->av_ofirst = src->av_ofirst;
dst->av_osecond = src->av_osecond;
dst->av_othird = src->av_othird;
break;
}
}
avail_p av_enter(avp, ocp, kind)
avail_p avp;
occur_p ocp;
int kind;
{
/* Put the available expression avp in the list,
* if it is not already there.
* Add ocp to the set of occurrences of this expression.
*/
register avail_p ravp;
line_p last = ocp->oc_llast;
for (ravp = avails; ravp != (avail_p) 0; ravp = ravp->av_before) {
if (same_avail(kind, ravp, avp)) { /* It was there. */
Ladd(ocp, &ravp->av_occurs);
/* Can we still use the local in which
* the result was stored?
*/
check_local(ravp);
return ravp;
}
}
/* A new available axpression. */
ravp = newavail();
/* Remember local, if any, that holds result. */
if (avp->av_instr != (byte) INSTR(last)) {
/* Only possible when instr is the implicit AAR in
* a LAR or SAR.
*/
ravp->av_saveloc = (entity_p) 0;
} else {
ravp->av_saveloc = result_local(avp->av_size, last->l_next);
}
ravp->av_found = last;
ravp->av_result = kind == EXPENSIVE_LOAD? avp->av_operand: newvalnum();
copy_avail(kind, avp, ravp);
oldoccur(ocp);
ravp->av_before = avails;
avails = ravp;
return ravp;
}
clr_avails()
{
/* Throw away the information about the available expressions. */
register avail_p ravp, next;
register Lindex i;
register lset s;
for (ravp = avails; ravp != (avail_p) 0; ravp = next) {
next = ravp->av_before;
s = ravp->av_occurs;
for (i = Lfirst(s); i != (Lindex) 0; i = Lnext(i, s)) {
oldoccur(occ_elem(i));
}
Ldeleteset(s);
oldavail(ravp);
}
avails = (avail_p) 0;
}

View file

@ -1,18 +0,0 @@
extern avail_p avails; /* The set of available expressions. */
extern avail_p av_enter(); /* (avail_p avp, occur_p ocp, byte kind)
* Puts the available expression in avp
* in the list of available expressions,
* if it is not already there. Add ocp to set of
* occurrences of this expression.
* If we have a new expression, we test whether
* the result is saved. When this expression
* recurs,we test if we can still use the
* variable into which it was saved.
* (Kind is the kind of the expression.)
* Returns a pointer into the list.
*/
extern clr_avails(); /* Release all space occupied by the old list
* of available expressions.
*/

View file

@ -1,156 +0,0 @@
#include <stdio.h>
#include "../../../h/em_spec.h"
#include "../share/types.h"
#include "../share/debug.h"
#include "../share/lset.h"
#include "cs.h"
#include "cs_aux.h"
#include "cs_avail.h"
#include "cs_entity.h"
#ifdef VERBOSE
extern char em_mnem[]; /* The mnemonics of the EM instructions. */
STATIC showinstr(lnp)
line_p lnp;
{
/* Makes the instruction in `lnp' human readable. Only lines that
* can occur in expressions that are going to be eliminated are
* properly handled.
*/
if (INSTR(lnp) < sp_fmnem && INSTR(lnp) > sp_lmnem) {
fprintf(stderr,"*** ?\n");
return;
}
fprintf(stderr,"%s", &em_mnem[4 * (INSTR(lnp)-sp_fmnem)]);
switch (TYPE(lnp)) {
case OPNO:
break;
case OPSHORT:
fprintf(stderr," %d", SHORT(lnp));
break;
case OPOBJECT:
fprintf(stderr," %d", OBJ(lnp)->o_id);
break;
case OPOFFSET:
fprintf(stderr," %D", OFFSET(lnp));
break;
default:
fprintf(stderr," ?");
break;
}
fprintf(stderr,"\n");
}
SHOWOCCUR(ocp)
occur_p ocp;
{
/* Shows all instructions in an occurrence. */
register line_p lnp, next;
if (verbose_flag) {
for (lnp = ocp->oc_lfirst; lnp != (line_p) 0; lnp = next) {
next = lnp == ocp->oc_llast ? (line_p) 0 : lnp->l_next;
showinstr(lnp);
}
}
}
#endif
#ifdef TRACE
SHOWAVAIL(avp)
avail_p avp;
{
/* Shows an available expression. */
showinstr(avp->av_found);
fprintf(stderr,"result %d,", avp->av_result);
fprintf(stderr,"occurred %d times\n", Lnrelems(avp->av_occurs) + 1);
}
OUTAVAILS()
{
register avail_p ravp;
fprintf(stderr,"AVAILABLE EXPRESSIONS\n");
for (ravp = avails; ravp != (avail_p) 0; ravp = ravp->av_before) {
SHOWAVAIL(ravp);
fprintf(stderr,"\n");
}
}
STATIC char *enkinds[] = {
"constant",
"local",
"external",
"indirect",
"offsetted",
"address of local",
"address of external",
"address of offsetted",
"address of local base",
"address of argument base",
"procedure",
"floating zero",
"array element",
"local base",
"heap pointer",
"ignore mask"
};
OUTENTITIES()
{
register Lindex i;
fprintf(stderr,"ENTITIES\n");
for (i = Lfirst(entities); i != (Lindex) 0; i = Lnext(i, entities)) {
register entity_p rep = en_elem(i);
fprintf(stderr,"%s,", enkinds[rep->en_kind]);
fprintf(stderr,"size %D,", rep->en_size);
fprintf(stderr,"valno %d,", rep->en_vn);
switch (rep->en_kind) {
case ENCONST:
fprintf(stderr,"$%D\n", rep->en_val);
break;
case ENLOCAL:
case ENALOCAL:
fprintf(stderr,"%D(LB)\n", rep->en_loc);
break;
case ENINDIR:
fprintf(stderr,"*%d\n", rep->en_ind);
break;
case ENOFFSETTED:
case ENAOFFSETTED:
fprintf(stderr,"%D(%d)\n", rep->en_off, rep->en_base);
break;
case ENALOCBASE:
case ENAARGBASE:
fprintf(stderr,"%D levels\n", rep->en_levels);
break;
case ENARRELEM:
fprintf(stderr,"%d[%d], ",rep->en_arbase,rep->en_index);
fprintf(stderr,"rom at %d\n", rep->en_adesc);
break;
}
fprintf(stderr,"\n");
}
}
/* XXX */
OUTTRACE(s, n)
char *s;
{
fprintf(stderr,"trace: ");
fprintf(stderr,s, n);
fprintf(stderr,"\n");
}
#endif TRACE

View file

@ -1,33 +0,0 @@
#ifdef VERBOSE
extern SHOWOCCUR(); /* (occur_p ocp)
* Shows all lines in an occurrence.
*/
#else
#define SHOWOCCUR(x)
#endif
#ifdef TRACE
extern OUTAVAILS(); /* ()
* Prints all available expressions.
*/
extern OUTENTITIES(); /* ()
* Prints all entities.
*/
extern SHOWAVAIL(); /* (avail_p avp)
* Shows an available expression.
*/
#else TRACE
#define OUTAVAILS()
#define OUTENTITIES()
#define SHOWAVAIL(x)
#endif TRACE

View file

@ -1,283 +0,0 @@
#include "../../../h/em_reg.h"
#include "../../../h/em_mnem.h"
#include "../share/types.h"
#include "../share/alloc.h"
#include "../share/lset.h"
#include "../share/aux.h"
#include "../share/global.h"
#include "../share/debug.h"
#include "cs.h"
#include "cs_avail.h"
#include "cs_alloc.h"
#include "cs_aux.h"
#include "cs_debug.h"
#include "cs_profit.h"
#include "cs_partit.h"
#include "cs_debug.h"
STATIC dlink(l1, l2)
line_p l1, l2;
{
/* Doubly link the lines in l1 and l2. */
if (l1 != (line_p) 0)
l1->l_next = l2;
if (l2 != (line_p) 0)
l2->l_prev = l1;
}
STATIC remove_lines(first, last)
line_p first, last;
{
/* Throw away the lines between and including first and last.
* Don't worry about any pointers; the (must) have been taken care of.
*/
register line_p lnp, next;
last->l_next = (line_p) 0; /* Delimit the list. */
for (lnp = first; lnp != (line_p) 0; lnp = next) {
next = lnp->l_next;
oldline(lnp);
}
}
STATIC bool contained(ocp1, ocp2)
occur_p ocp1, ocp2;
{
/* Determine whether ocp1 is contained within ocp2. */
register line_p lnp, next;
for (lnp = ocp2->oc_lfirst; lnp != (line_p) 0; lnp = next) {
next = lnp != ocp2->oc_llast ? lnp->l_next : (line_p) 0;
if (lnp == ocp1->oc_llast) return TRUE;
}
return FALSE;
}
STATIC delete(ocp, start)
occur_p ocp;
avail_p start;
{
/* Delete all occurrences that are contained within ocp.
* They must have been entered in the list before start:
* if an expression is contained with an other, its operator line
* appears before the operator line of the other because EM-expressions
* are postfix.
*/
register avail_p ravp;
register Lindex i, next;
for (ravp = start; ravp != (avail_p) 0; ravp = ravp->av_before) {
for (i = Lfirst(ravp->av_occurs); i != (Lindex) 0; i = next) {
next = Lnext(i, ravp->av_occurs);
if (contained(occ_elem(i), ocp)) {
OUTTRACE("delete contained occurrence", 0);
# ifdef TRACE
SHOWOCCUR(occ_elem(i));
# endif
oldoccur(occ_elem(i));
Lremove(Lelem(i), &ravp->av_occurs);
}
}
}
}
STATIC complete_aar(lnp, instr, descr_vn)
line_p lnp;
int instr;
valnum descr_vn;
{
/* Lnp is an instruction that loads the address of an array-element.
* Instr tells us what effect we should achieve; load (instr is op_lar)
* or store (instr is op_sar) this array-element. Descr_vn is the
* valuenumber of the address of the descriptor of this array.
* We append a loi or sti of the correct number of bytes.
*/
register line_p lindir;
lindir = int_line(array_elemsize(descr_vn));
lindir->l_instr = instr == op_lar ? op_loi : op_sti;
dlink(lindir, lnp->l_next);
dlink(lnp, lindir);
}
STATIC replace(ocp, tmp, avp)
occur_p ocp;
offset tmp;
avail_p avp;
{
/* Replace the lines in the occurrence in ocp by a load of the
* temporary with offset tmp.
*/
register line_p lol, first, last;
assert(avp->av_size == ws || avp->av_size == 2*ws);
first = ocp->oc_lfirst; last = ocp->oc_llast;
lol = int_line(tmp);
lol->l_instr = avp->av_size == ws ? op_lol : op_ldl;
dlink(lol, last->l_next);
if (first->l_prev == (line_p) 0) ocp->oc_belongs->b_start = lol;
dlink(first->l_prev, lol);
if (avp->av_instr == (byte) op_aar) {
/* There may actually be a LAR or a SAR instruction; in that
* case we have to complete the array-instruction.
*/
register int instr = INSTR(last);
if (instr != op_aar) complete_aar(lol, instr, avp->av_othird);
}
/* Throw away the by now useless lines. */
remove_lines(first, last);
}
STATIC append(avp, tmp)
avail_p avp;
offset tmp;
{
/* Avp->av_found points to a line with an operator in it. This
* routine emits a sequence of instructions that saves the result
* in a local with offset tmp. In most cases we just append
* avp->av_found with stl/sdl tmp and lol/ldl tmp depending on
* avp->av_size. If however the operator is an aar contained
* within a lar or sar, we must first generate the aar.
*/
register line_p stl, lol;
assert(avp->av_size == ws || avp->av_size == 2*ws);
stl = int_line(tmp);
stl->l_instr = avp->av_size == ws ? op_stl : op_sdl;
lol = int_line(tmp);
lol->l_instr = avp->av_size == ws ? op_lol : op_ldl;
dlink(lol, avp->av_found->l_next);
dlink(stl, lol);
dlink(avp->av_found, stl);
if (avp->av_instr == (byte) op_aar) {
register int instr = INSTR(avp->av_found);
if (instr != op_aar) {
complete_aar(lol, instr, avp->av_othird);
avp->av_found->l_instr = op_aar;
}
}
}
STATIC set_replace(avp, tmp)
avail_p avp;
offset tmp;
{
/* Avp->av_occurs is now a set of occurrences, each of which will be
* replaced by a reference to a local.
* Each time we eliminate an expression, we delete from our
* list those expressions that are physically contained in them,
* because we cannot eliminate them again.
*/
register Lindex i;
register lset s = avp->av_occurs;
for (i = Lfirst(s); i != (Lindex) 0; i = Lnext(i, s)) {
OUTVERBOSE("eliminate duplicate", 0);
SHOWOCCUR(occ_elem(i));
Scs++;
delete(occ_elem(i), avp->av_before);
replace(occ_elem(i), tmp, avp);
}
}
STATIC int reg_score(enp)
entity_p enp;
{
/* Enp is a local that will go into a register.
* We return its score upto now.
*/
assert(is_regvar(enp->en_loc));
return regv_arg(enp->en_loc, 4);
}
STATIC line_p gen_mesreg(off, avp, pp)
offset off;
avail_p avp;
proc_p pp;
{
/* Generate a register message for the local that will hold the
* result of the expression in avp, at the appropriate place in
* the procedure in pp.
*/
register line_p reg;
reg = reg_mes(off, (short) avp->av_size, regtype(avp->av_instr), 0);
appnd_line(reg, pp->p_start->b_start);
return reg;
}
STATIC change_score(mes, score)
line_p mes;
int score;
{
/* Change the score in the register message in mes to score. */
register arg_p ap = ARG(mes);
ap = ap->a_next; /* Offset. */
ap = ap->a_next; /* Size. */
ap = ap->a_next; /* Type. */
ap = ap->a_next; /* Score. */
ap->a_a.a_offset = score;
}
eliminate(pp)
proc_p pp;
{
/* Eliminate costly common subexpressions within procedure pp.
* We scan the available expressions in - with respect to time found -
* reverse order, to find largest first, e.g. `A + B + C' before
* `A + B'.
* We do not eliminate an expression when the size
* is not one of ws or 2*ws, because then we cannot use lol or ldl.
* Code is appended to the first occurrence of the expression
* to store the result into a local.
*/
register avail_p ravp;
register int score;
register offset tmp;
register line_p mes;
for (ravp = avails; ravp != (avail_p) 0; ravp = ravp->av_before) {
if (ravp->av_size != ws && ravp->av_size != 2*ws) continue;
if (ravp->av_saveloc == (entity_p) 0) {
/* We save it ourselves. */
score = 2; /* Stl and lol. */
} else {
score = reg_score(ravp->av_saveloc);
}
if (desirable(ravp)) {
score += Lnrelems(ravp->av_occurs);
OUTTRACE("temporary local score %d", score);
if (ravp->av_saveloc != (entity_p) 0) {
tmp = ravp->av_saveloc->en_loc;
mes = find_mesreg(tmp);
OUTVERBOSE("re-using %D(LB)", tmp);
} else {
tmp = tmplocal(pp, ravp->av_size);
mes = gen_mesreg(tmp, ravp, pp);
append(ravp, tmp);
}
change_score(mes, score);
set_replace(ravp, tmp);
}
}
}

View file

@ -1,5 +0,0 @@
extern eliminate(); /* (proc_p pp)
* Eliminate some of the recurrences of expressions
* that were found by the valuenumbering
* algorithm.
*/

View file

@ -1,142 +0,0 @@
/* F U N C T I O N S F O R A C C E S S I N G T H E S E T
*
* O F E N T I T I E S
*/
#include "../share/types.h"
#include "../share/global.h"
#include "../share/lset.h"
#include "../share/debug.h"
#include "cs.h"
#include "cs_alloc.h"
#include "cs_aux.h"
lset entities; /* Our pseudo symbol-table. */
entity_p find_entity(vn)
valnum vn;
{
/* Try to find the entity with valuenumber vn. */
register Lindex i;
for (i = Lfirst(entities); i != (Lindex) 0; i = Lnext(i, entities)) {
if (en_elem(i)->en_vn == vn)
return en_elem(i);
}
return (entity_p) 0;
}
STATIC bool same_entity(enp1, enp2)
entity_p enp1, enp2;
{
if (enp1->en_kind != enp2->en_kind) return FALSE;
if (enp1->en_size != enp2->en_size) return FALSE;
if (enp1->en_size == UNKNOWN_SIZE) return FALSE;
switch (enp1->en_kind) {
case ENCONST:
return enp1->en_val == enp2->en_val;
case ENLOCAL:
case ENALOCAL:
return enp1->en_loc == enp2->en_loc;
case ENEXTERNAL:
case ENAEXTERNAL:
return enp1->en_ext == enp2->en_ext;
case ENINDIR:
return enp1->en_ind == enp2->en_ind;
case ENOFFSETTED:
case ENAOFFSETTED:
return enp1->en_base == enp2->en_base &&
enp1->en_off == enp2->en_off;
case ENALOCBASE:
case ENAARGBASE:
return enp1->en_levels == enp2->en_levels;
case ENPROC:
return enp1->en_pro == enp2->en_pro;
case ENARRELEM:
return enp1->en_arbase == enp2->en_arbase &&
enp1->en_index == enp2->en_index &&
enp1->en_adesc == enp2->en_adesc;
default:
return TRUE;
}
}
STATIC copy_entity(src, dst)
entity_p src, dst;
{
dst->en_static = src->en_static;
dst->en_kind = src->en_kind;
dst->en_size = src->en_size;
switch (src->en_kind) {
case ENCONST:
dst->en_val = src->en_val;
break;
case ENLOCAL:
case ENALOCAL:
dst->en_loc = src->en_loc;
break;
case ENEXTERNAL:
case ENAEXTERNAL:
dst->en_ext = src->en_ext;
break;
case ENINDIR:
dst->en_ind = src->en_ind;
break;
case ENOFFSETTED:
case ENAOFFSETTED:
dst->en_base = src->en_base;
dst->en_off = src->en_off;
break;
case ENALOCBASE:
case ENAARGBASE:
dst->en_levels = src->en_levels;
break;
case ENPROC:
dst->en_pro = src->en_pro;
break;
case ENARRELEM:
dst->en_arbase = src->en_arbase;
dst->en_index = src->en_index;
dst->en_adesc = src->en_adesc;
break;
}
}
entity_p en_enter(enp)
register entity_p enp;
{
/* Put the entity in enp in the entity set, if it is not already there.
* Return pointer to stored entity.
*/
register Lindex i;
register entity_p new;
for (i = Lfirst(entities); i != (Lindex) 0; i = Lnext(i, entities)) {
if (same_entity(en_elem(i), enp))
return en_elem(i);
}
/* A new entity. */
new = newentity();
new->en_vn = newvalnum();
copy_entity(enp, new);
Ladd(new, &entities);
return new;
}
clr_entities()
{
/* Throw away all pseudo-symboltable information. */
register Lindex i;
for (i = Lfirst(entities); i != (Lindex) 0; i = Lnext(i, entities)) {
oldentity(en_elem(i));
}
Ldeleteset(entities);
entities = Lempty_set();
}

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