fixup commit for tag 'distr2'
This commit is contained in:
parent
0f4da3a208
commit
ab5d79a8ce
35
Makefile
35
Makefile
@ -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
1
bin/em.pascal
Executable file
@ -0,0 +1 @@
|
|||||||
|
exec /usr/em/doc/em.doc/int/em /usr/em/doc/em.doc/int/tables ${1-e.out} core
|
||||||
118
doc/i80.doc
118
doc/i80.doc
@ -1,3 +1,4 @@
|
|||||||
|
." $Header$
|
||||||
.RP
|
.RP
|
||||||
.TL
|
.TL
|
||||||
Back end table for the Intel 8080 micro-processor
|
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
|
.br
|
||||||
The sign bit S is set (cleared) by certain instructions when the most significant
|
The sign bit S is set (cleared) by certain instructions when the most significant
|
||||||
bit of the result of an operation equals one (zero).
|
bit of the result of an operation equals one (zero).
|
||||||
|
.br
|
||||||
The zero bit Z is set (cleared) by certain operations when the
|
The zero bit Z is set (cleared) by certain operations when the
|
||||||
8-bit result of an operation equals (does not equal) zero.
|
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
|
The parity bit P is set (cleared) if the 8-bit result of an
|
||||||
operation includes an even (odd) number of ones.
|
operation includes an even (odd) number of ones.
|
||||||
|
.br
|
||||||
C is the normal carry bit.
|
C is the normal carry bit.
|
||||||
|
.br
|
||||||
AC is an auxiliary carry that indicates whether there has been a carry
|
AC is an auxiliary carry that indicates whether there has been a carry
|
||||||
out of bit 3 of the accumulator.
|
out of bit 3 of the accumulator.
|
||||||
This auxiliary carry is used only by the DAA instruction, which
|
This auxiliary carry is used only by the DAA instruction, which
|
||||||
@ -125,12 +130,14 @@ of register-pair HL.
|
|||||||
.NH 3
|
.NH 3
|
||||||
Register addressing
|
Register addressing
|
||||||
.PP
|
.PP
|
||||||
With each instruction using register addressing,
|
|
||||||
|
With each intruction using register addressing,
|
||||||
only one register is specified (except for the MOV instruction),
|
only one register is specified (except for the MOV instruction),
|
||||||
although in many of them the accumulator is implied as
|
although in many of them the accumulator is implied as
|
||||||
second operand.
|
second operand.
|
||||||
Examples are CMP E, which compares register E with the accumulator,
|
Examples are CMP E, which compares register E with the accumulator,
|
||||||
and DCR B, which decrements register B.
|
and DCR B, which decrements register B.
|
||||||
|
.br
|
||||||
A few instructions deal with 16 bit register-pairs:
|
A few instructions deal with 16 bit register-pairs:
|
||||||
examples are DCX B, which decrements register-pair BC and the
|
examples are DCX B, which decrements register-pair BC and the
|
||||||
PUSH and POP instructions.
|
PUSH and POP instructions.
|
||||||
@ -166,7 +173,7 @@ The high order byte is stored at the highest address.
|
|||||||
THE 8080 BACK END TABLE
|
THE 8080 BACK END TABLE
|
||||||
.PP
|
.PP
|
||||||
The back end table is designed as described in [5].
|
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
|
.br
|
||||||
This section deals with problems encountered in writing the
|
This section deals with problems encountered in writing the
|
||||||
8080 back-end table.
|
8080 back-end table.
|
||||||
@ -178,30 +185,30 @@ Constant definitions
|
|||||||
Word size (EM_WSIZE) and pointer size (EM_PSIZE) are both
|
Word size (EM_WSIZE) and pointer size (EM_PSIZE) are both
|
||||||
defined as two bytes.
|
defined as two bytes.
|
||||||
The hole between AB and LB (EM_BSIZE) is four bytes: only the
|
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
|
.NH 2
|
||||||
Registers and their properties
|
Registers and their properties
|
||||||
.PP
|
.PP
|
||||||
All properties have the default size of two bytes, because one-byte
|
All properties have the default size of two bytes, because one-byte
|
||||||
registers also cover two bytes when put on the real stack.
|
registers also cover two bytes when put on the real stack.
|
||||||
.sp 1
|
.sp 1
|
||||||
The next considerations led to the choice of register-pair BC
|
The next considerations led to the choise of register-pair BC
|
||||||
as local base.
|
as localbase.
|
||||||
Though saving the local base in memory would leave one more register-pair
|
Though saving the localbase in memory would leave one more register-pair
|
||||||
available as scratch register, it would slow down instructions
|
available as scratch register, it would slow down instructions
|
||||||
as 'lol' and 'stl' too much.
|
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
|
Because a back-end without a free register-pair HL is completely
|
||||||
broken-winged, the only reasonable choices are BC and DE.
|
broken-winged, the only reasonable choises are BC and DE.
|
||||||
Though the choice between them might seem arbitrary at first sight,
|
Though the choise between them might seem arbitrary at first sight,
|
||||||
there is a difference between register-pairs BC and DE:
|
there is a difference between register-pairs BC and DE:
|
||||||
the instruction XCHG exchanges the contents of register-pairs DE and
|
the instruction XCHG exchanges the contents of register-pairs DE and
|
||||||
HL.
|
HL.
|
||||||
When DE and HL are both heavily used on the fake-stack, this instruction
|
When DE and HL are both heavily used on the fake-stack, this instruction
|
||||||
is very useful.
|
is very usefull.
|
||||||
Since it won't be useful too often to exchange HL with the local base
|
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
|
and since an instruction exchanging BC and HL does not exist, BC is
|
||||||
chosen as local base.
|
chosen as localbase.
|
||||||
.sp 1
|
.sp 1
|
||||||
Many of the register properties are never mentioned in the
|
Many of the register properties are never mentioned in the
|
||||||
PATTERNS part of the table.
|
PATTERNS part of the table.
|
||||||
@ -212,7 +219,7 @@ The properties really used in the PATTERNS part are:
|
|||||||
the accumulator only
|
the accumulator only
|
||||||
.IP reg:
|
.IP reg:
|
||||||
any of the registers A, D, E, H or L. Of course the registers B and C which are
|
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
|
When there is a single register on the fake-stack, its value
|
||||||
is always considered non-negative.
|
is always considered non-negative.
|
||||||
.IP dereg:
|
.IP dereg:
|
||||||
@ -221,12 +228,12 @@ register-pair DE only
|
|||||||
register-pair HL only
|
register-pair HL only
|
||||||
.IP hl_or_de:
|
.IP hl_or_de:
|
||||||
register-pairs HL and DE both have this property
|
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')
|
used only once (i.e. in the EM-instruction 'str 0')
|
||||||
.PP
|
.PP
|
||||||
.sp 1
|
.sp 1
|
||||||
The stackpointer SP and the processor status word PSW have to be
|
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).
|
(i.e. SP in LXI, DCX and INX and PSW in PUSH and POP).
|
||||||
.br
|
.br
|
||||||
It doesn't matter that the processor status word is not just register A
|
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).
|
different tokens (four).
|
||||||
Reasons are the limited addressing modes of the 8080 microprocessor,
|
Reasons are the limited addressing modes of the 8080 microprocessor,
|
||||||
no index registers etc.
|
no index registers etc.
|
||||||
|
.br
|
||||||
For example to translate the EM-instruction
|
For example to translate the EM-instruction
|
||||||
.DS
|
.DS
|
||||||
lol 10
|
lol 10
|
||||||
@ -252,15 +260,16 @@ lol 10
|
|||||||
the next 8080 instructions are generated:
|
the next 8080 instructions are generated:
|
||||||
.DS L
|
.DS L
|
||||||
LXI H,10 /* load registers pair HL with value 10 */
|
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 */
|
MOV E,M /* load E with byte pointed to by HL */
|
||||||
INX H /* increment HL */
|
INX H /* increment HL */
|
||||||
MOV D,M /* load D with next byte */
|
MOV D,M /* load D with next byte */
|
||||||
.DE
|
.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
|
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
|
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.
|
See also the comment on the load instructions.
|
||||||
.NH 2
|
.NH 2
|
||||||
Sets
|
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
|
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
|
orthogonal this results in small deficiencies for the DCR, INR and MOV
|
||||||
instructions.
|
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
|
corrected in the INSTRUCTIONS part, by treating the register indirect
|
||||||
mode separately.
|
mode seperately.
|
||||||
.sp 1
|
.sp 1
|
||||||
The costs of the conditional call and return instructions really
|
The costs of the conditional call and return instructions really
|
||||||
depend on whether or not the call resp. return is actually made.
|
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
|
.sp 1
|
||||||
Instructions not used in this table have been commented out.
|
Instructions not used in this table have been commented out.
|
||||||
Of course many of them are used in the library routines.
|
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
|
.B cgg
|
||||||
from complaining.
|
from complaining.
|
||||||
.NH 2
|
.NH 2
|
||||||
Stacking rules
|
Stackingrules
|
||||||
.PP
|
.PP
|
||||||
When, for example, the token {const2,10} has to be stacked while
|
When, for example, the token {const2,10} has to be stacked while
|
||||||
no free register-pair is available, the next code is generated:
|
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.
|
register-pairs.
|
||||||
Before the coercion is carried out other appearances of DE and HL
|
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
|
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.
|
of both DE and HL.
|
||||||
|
.br
|
||||||
The coercion transposing one register-pair to another one by
|
The coercion transposing one register-pair to another one by
|
||||||
emitting two MOV-instructions, will be used only if
|
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
|
.NH 2
|
||||||
Patterns
|
Patterns
|
||||||
.PP
|
.PP
|
||||||
@ -351,7 +361,7 @@ gen lhld {label,$1} yields hl
|
|||||||
.DE
|
.DE
|
||||||
the 'uses'-clause could have been omitted because
|
the 'uses'-clause could have been omitted because
|
||||||
.B cgg
|
.B cgg
|
||||||
knows that LHLD destroys register-pair HL.
|
knows that LHLD destroyes register-pair HL.
|
||||||
.sp 1
|
.sp 1
|
||||||
Since there is only one register with property 'hlreg',
|
Since there is only one register with property 'hlreg',
|
||||||
there is no difference between 'uses hlreg' (allocate a
|
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).
|
all registers with property 'hlreg' from the fake-stack).
|
||||||
The same applies for the property 'dereg'.
|
The same applies for the property 'dereg'.
|
||||||
.br
|
.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
|
.NH 3
|
||||||
Group 1: Load instructions
|
Group 1: Load instructions
|
||||||
.PP
|
.PP
|
||||||
@ -375,6 +385,7 @@ To refrain
|
|||||||
.B cgg
|
.B cgg
|
||||||
from emitting the code for 'lol 10' again, an extra
|
from emitting the code for 'lol 10' again, an extra
|
||||||
pattern is included in the table for cases like this.
|
pattern is included in the table for cases like this.
|
||||||
|
.br
|
||||||
The same applies for two consecutive 'loe'-s or 'lil'-s.
|
The same applies for two consecutive 'loe'-s or 'lil'-s.
|
||||||
.sp 1
|
.sp 1
|
||||||
A bit tricky is 'lof'.
|
A bit tricky is 'lof'.
|
||||||
@ -390,7 +401,7 @@ knows that HL is destroyed).
|
|||||||
.sp 1
|
.sp 1
|
||||||
By lookahead,
|
By lookahead,
|
||||||
.B cgg
|
.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'.
|
second code rule of 'loi 4'.
|
||||||
The same applies for several other instructions.
|
The same applies for several other instructions.
|
||||||
.NH 3
|
.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
|
Since the 8080 instruction set doesn't provide multiply and
|
||||||
divide instructions, special routines are made to accomplish these tasks.
|
divide instructions, special routines are made to accomplish these tasks.
|
||||||
.sp 1
|
.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,
|
unsigned division, yielding the quotient or the remainder,
|
||||||
the routines are merged.
|
the routines are merged.
|
||||||
This saves space and assembly time
|
This saves space and assembly time
|
||||||
when several variants are used in a particular program,
|
when several variants are used in a particular program,
|
||||||
at the cost of a little speed.
|
at the cost of a little speed.
|
||||||
|
.br
|
||||||
When the routine is called, bit 7 of register A indicates whether
|
When the routine is called, bit 7 of register A indicates whether
|
||||||
the operands should be considered as signed or as unsigned integers,
|
the operands should be considered as signed or as unsigned integers,
|
||||||
and bit 0 of register A indicates whether the quotient or the
|
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
|
.NH 3
|
||||||
Group 5: Floating point arithmetic
|
Group 5: Floating point arithmetic
|
||||||
.PP
|
.PP
|
||||||
Floating point is not implemented.
|
Floating points are not implemented.
|
||||||
|
.br
|
||||||
Whenever an EM-instruction involving floating points is offered
|
Whenever an EM-instruction involving floating points is offered
|
||||||
to the code-generator, it calls the corresponding
|
to the code-generator, it generates the code 'call eunimpl',
|
||||||
library routine with the proper parameters.
|
which traps with trap number 63.
|
||||||
Each floating point library routine calls 'eunimpl',
|
|
||||||
trapping with trap number 63.
|
|
||||||
Some of the Pascal and C library routines output floating point
|
Some of the Pascal and C library routines output floating point
|
||||||
EM-instructions, so code has to be generated for them.
|
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
|
.NH 3
|
||||||
Group 12: Compare instructions
|
Group 12: Compare instructions
|
||||||
.PP
|
.PP
|
||||||
@ -457,6 +468,7 @@ gen mov a,%1.2
|
|||||||
but the current version of
|
but the current version of
|
||||||
.B cgg
|
.B cgg
|
||||||
doesn't approve this.
|
doesn't approve this.
|
||||||
|
.br
|
||||||
In any case
|
In any case
|
||||||
.B cgg
|
.B cgg
|
||||||
chooses either DE or HL to store the result, using lookahead.
|
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
|
LIBRARY ROUTINES
|
||||||
.PP
|
.PP
|
||||||
Most of the library routines start with saving the return address
|
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.
|
and the registers B and C are available as scratch registers.
|
||||||
Since register-pair HL is needed to accomplish these tasks,
|
Since register-pair HL is needed to accomplish these tasks,
|
||||||
and also to restore everything just before the routine returns,
|
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.
|
registers-pair DE.
|
||||||
When it returns more than 2 bytes they are pushed onto the stack.
|
When it returns more than 2 bytes they are pushed onto the stack.
|
||||||
.br
|
.br
|
||||||
|
|
||||||
It would have been possible to let the 32 bit arithmetic routines
|
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
|
return 2 bytes in DE and the remaining 2 bytes on the stack
|
||||||
(this often would have saved some space and execution time),
|
(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,
|
Whenever a trap, for example trying to divide by zero,
|
||||||
occurs in a program that originally was written in C or Pascal,
|
occurs in a program that originally was written in C or Pascal,
|
||||||
a special trap handler is called.
|
a special trap handler is called.
|
||||||
|
.br
|
||||||
This trap handler wants to write an appropriate error message on the
|
This trap handler wants to write an appropriate error message on the
|
||||||
monitor.
|
monitor.
|
||||||
It tries to read the message from a file (e.g. etc/pc_rt_errors in the
|
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).
|
by storing it in ROM (Read Only Memory).
|
||||||
.sp 1
|
.sp 1
|
||||||
Depending on the characteristics of the particular 8080 based system, some
|
Depending on the characteristics of the particular 8080 based system, some
|
||||||
adaptations have to be made:
|
adaptions have to be made:
|
||||||
.IP 1) 10
|
.IP 1) 10
|
||||||
In 'head_em': the base address, which is the address where the first
|
In 'head_em': the base address, which is the address where the first
|
||||||
8080 instruction will be stored, and the initial value of the
|
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
|
.br
|
||||||
Other systems require other values.
|
Other systems require other values.
|
||||||
.IP 2)
|
.IP 2)
|
||||||
@ -560,12 +574,12 @@ If this is not the right way on your system, change it.
|
|||||||
.IP 5)
|
.IP 5)
|
||||||
In 'tail_em': the current version of the 8080 back-end has very limited I/O
|
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
|
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;
|
So the implementation of the EM-instruction 'mon' is very simple;
|
||||||
it can only do the following things:
|
it can only do the following things:
|
||||||
.RS
|
.RS
|
||||||
.IP Monitor\ call\ 1: 40
|
.IP Monitor\ call\ 1: 40
|
||||||
exit
|
Exit
|
||||||
.IP Monitor\ call\ 3:
|
.IP Monitor\ call\ 3:
|
||||||
read, always reads from the monitor.
|
read, always reads from the monitor.
|
||||||
.br
|
.br
|
||||||
@ -593,7 +607,7 @@ INTEL 8080 VERSUS ZILOG Z80 AND INTEL 8086
|
|||||||
.NH 2
|
.NH 2
|
||||||
Introduction
|
Introduction
|
||||||
.PP
|
.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,
|
for the Intel 8080 and Intel 8085,
|
||||||
Frans van Haarlem did the same job for the Zilog z80 microprocessor.
|
Frans van Haarlem did the same job for the Zilog z80 microprocessor.
|
||||||
Since the z80 processor is an extension of the 8080,
|
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.
|
to a z80 too.
|
||||||
The assembly languages are quite different however.
|
The assembly languages are quite different however.
|
||||||
.br
|
.br
|
||||||
During the developments of the back ends we have used
|
During the devellopments of the back ends we have used
|
||||||
two micro-computers, both equipped with a z80 microprocessor.
|
two micro-computers, both equiped with a z80 microprocessor.
|
||||||
Of course the output of the 8080 back end is assembled by an
|
Of course the output of the 8080 back end is assembled by an
|
||||||
8080 assembler. This should assure I have never used any of
|
8080 assembler. This should assure I have never used any of
|
||||||
the features that are potentially available in the z80 processor,
|
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
|
Differences between the 8080 and z80 processors
|
||||||
.PP
|
.PP
|
||||||
Except for some features that are less important concerning back ends,
|
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
|
.IP First, 18
|
||||||
the z80 has two additional index registers, IX and IY.
|
the z80 has two additional index registers, IX and IY.
|
||||||
They are used as in
|
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
|
Consequences for the 8080 and z80 back end
|
||||||
.PP
|
.PP
|
||||||
The most striking difference between the 8080 and z80 back ends
|
The most striking difference between the 8080 and z80 back ends
|
||||||
is the choice of the local base.
|
is the choise of the localbase.
|
||||||
The writer of the z80 back end chose index register IY as local base,
|
The writer of the z80 back end chose index register IY as localbase,
|
||||||
because this results in the cheapest coding of EM-instructions
|
because this results in the cheapest coding of EM-instructions
|
||||||
like 'lol' and 'stl'.
|
like 'lol' and 'stl'.
|
||||||
|
.br
|
||||||
The z80 instructions that load local 10, for example
|
The z80 instructions that load local 10, for example
|
||||||
.DS
|
.DS
|
||||||
LD E,(IY+10)
|
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
|
it should be noted that as a side effect it may save some
|
||||||
pushing and popping since register pair HL is not used.
|
pushing and popping since register pair HL is not used.
|
||||||
.sp 1
|
.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
|
The root of the problem is that it is not possible to add
|
||||||
IY to HL.
|
IY to HL.
|
||||||
For the EM-instruction
|
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
|
other instructions, for instance in 'lol' when the offset
|
||||||
doesn't fit in one byte.
|
doesn't fit in one byte.
|
||||||
.sp 1
|
.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,
|
fundamental difference between the 8080 and z80 back ends,
|
||||||
except of course that the z80 back end has register pair BC
|
except of course that the z80 back end has register pair BC
|
||||||
and, less important, index register IX available as scratch registers.
|
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.
|
Then I produced 8080, z80 and 8086 code for them.
|
||||||
Investigating the assembler listing I found the
|
Investigating the assembler listing I found the
|
||||||
lengths of the different parts of the generated code.
|
lengths of the different parts of the generated code.
|
||||||
|
.br
|
||||||
I have checked two areas:
|
I have checked two areas:
|
||||||
.IP 1) 8
|
.IP 1) 8
|
||||||
the entire text part
|
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
|
For all programs I have computed the ratio of the code-lengths
|
||||||
of the 8080, z80 and 8086.
|
of the 8080, z80 and 8086.
|
||||||
The averages of all Pascal/C programs are listed in the table,
|
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
|
So the listed '107' indicates that the lengths
|
||||||
of the text parts of the z80 programs that originally were Pascal programs,
|
of the text parts of the z80 programs that originally were Pascal programs,
|
||||||
averaged 7 percent larger than in the corresponding 8080 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
|
The most striking thing in this table is that the z80 back end appears
|
||||||
to produce larger code than the 8080 back end.
|
to produce larger code than the 8080 back end.
|
||||||
The reason is that the current z80 back end table is
|
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.
|
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
|
So the table shows that the preparations in the 8080 back end table
|
||||||
to produce faster code (like recognizing special EM-patterns
|
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
|
was not just for fun, but really improved the generated code
|
||||||
significantly.
|
significantly.
|
||||||
.sp 1
|
.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.
|
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
|
This is not very surprising since the 8080 back end sometimes
|
||||||
uses library routines where the z80 and especially the 8086 don't.
|
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]
|
.IP [3]
|
||||||
Tanenbaum, A.S., Stevenson, J.W., Keizer, E.G., and van Staveren, H.
|
Tanenbaum, A.S., Stevenson, J.W., Keizer, E.G., and van Staveren, H.
|
||||||
.br
|
.br
|
||||||
Description of an experimental machine architecture for use with block
|
Desciption of an experimental machine architecture for use with block
|
||||||
structured languages,
|
structured languages,
|
||||||
.br
|
.br
|
||||||
Informatica report 81, Vrije Universiteit, Amsterdam, 1983.
|
Informatica report 81, Vrije Universiteit, Amsterdam, 1983.
|
||||||
|
|||||||
196
doc/ncg.doc
196
doc/ncg.doc
@ -57,7 +57,7 @@ and the assembly code of the machine at hand.
|
|||||||
.NH 1
|
.NH 1
|
||||||
What has changed since version 1 ?
|
What has changed since version 1 ?
|
||||||
.PP
|
.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.
|
It is not needed to understand the current version.
|
||||||
.PP
|
.PP
|
||||||
This paper describes the second version of the code generator system.
|
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.
|
at the bottom of the fake stack.
|
||||||
Both ways, the concatenation of the real stack and 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).
|
will be the stack as it would have been on a real EM machine (see figure).
|
||||||
.KF
|
.TS
|
||||||
.DS L
|
center;
|
||||||
.ta 8 16 24 32 40 48 56 64 72
|
cw(3.5c) cw(3c) cw(3.5c)
|
||||||
EM machine target machine
|
cw(3.5c) cw(3c) cw(3.5c)
|
||||||
|
|cw(3.5c)| cw(3c) |cw(3.5c)| .
|
||||||
| | | |
|
EM machine target machine
|
||||||
| | | |
|
|
||||||
| | | |
|
|
||||||
| | | |
|
|
||||||
| | | real stack |
|
|
||||||
| | | | |
|
|
||||||
| | | | | growing
|
|
||||||
| EM stack | | | |
|
|
||||||
| | |_______________| \e|/
|
|
||||||
| | | |
|
|
||||||
| | | |
|
|
||||||
| | | |
|
|
||||||
| | | fake stack |
|
|
||||||
| | | |
|
|
||||||
|_______________| |_______________|
|
|
||||||
|
|
||||||
|
|
||||||
.I
|
|
||||||
Relation between EM stack, real stack and fake stack.
|
|
||||||
.R
|
|
||||||
.DE
|
real stack
|
||||||
.KE
|
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
|
During code generation tokens will be kept on the fake stack as long
|
||||||
as possible but when they are moved to the real stack,
|
as possible but when they are moved to the real stack,
|
||||||
by generating code for the push,
|
by generating code for the push,
|
||||||
all tokens above\u*\d
|
all tokens above\v'-.25m'\(dg\v'.25m'
|
||||||
.FS
|
.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
|
although the top of the stack will mean the first element that will
|
||||||
be popped.
|
be popped.
|
||||||
.FE
|
.FE
|
||||||
@ -233,7 +234,7 @@ to register variables in the rest of this document.
|
|||||||
.PP
|
.PP
|
||||||
The front ends generate messages to the back ends telling them which
|
The front ends generate messages to the back ends telling them which
|
||||||
local variables could go into registers.
|
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.
|
and a scoring number, roughly the number of times it occurs.
|
||||||
.PP
|
.PP
|
||||||
The decision which variable to put in which register is taken by the
|
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,
|
Identifiers used in the table have the same syntax as C identifiers,
|
||||||
upper and lower case considered different, all characters significant.
|
upper and lower case considered different, all characters significant.
|
||||||
Here is a list of reserved words; all of these are unavailable as identifiers.
|
Here is a list of reserved words; all of these are unavailable as identifiers.
|
||||||
.DS L
|
.TS
|
||||||
.ta 14 28 42 56
|
box;
|
||||||
|
l l l l l.
|
||||||
ADDR STACK from reg_any test
|
ADDR STACK from reg_any test
|
||||||
COERCIONS STACKINGRULES gen reg_float to
|
COERCIONS STACKINGRULES gen reg_float to
|
||||||
INSTRUCTIONS TESTS highw reg_loop ufit
|
INSTRUCTIONS TESTS highw reg_loop ufit
|
||||||
@ -309,7 +311,7 @@ PROPERTIES cost loww reusing
|
|||||||
REGISTERS defined move rom
|
REGISTERS defined move rom
|
||||||
SETS exact pat samesign
|
SETS exact pat samesign
|
||||||
SIZEFACTOR example proc sfit
|
SIZEFACTOR example proc sfit
|
||||||
.DE
|
.TE
|
||||||
C style comments are accepted.
|
C style comments are accepted.
|
||||||
.DS
|
.DS
|
||||||
/* this is a comment */
|
/* this is a comment */
|
||||||
@ -330,7 +332,7 @@ NAME=value
|
|||||||
.DE
|
.DE
|
||||||
value being an integer or string.
|
value being an integer or string.
|
||||||
Three constants must be defined here:
|
Three constants must be defined here:
|
||||||
.IP EM_WSIZE 10
|
.IP EM_WSIZE 14
|
||||||
Number of bytes in a machine word.
|
Number of bytes in a machine word.
|
||||||
This is the number of bytes
|
This is the number of bytes
|
||||||
a \fBloc\fP instruction will put on the stack.
|
a \fBloc\fP instruction will put on the stack.
|
||||||
@ -360,21 +362,21 @@ This is given as
|
|||||||
FORMAT = string
|
FORMAT = string
|
||||||
.DE
|
.DE
|
||||||
The string must be a valid printf(III) format,
|
The string must be a valid printf(III) format,
|
||||||
and defaults to "%d" or "%ld" depending on the wordsize of
|
and defaults to "%ld".
|
||||||
the machine. For example on the PDP-11 one can use
|
For example on the PDP-11 one can use
|
||||||
.DS
|
.DS
|
||||||
FORMAT= "0%o"
|
FORMAT= "0%lo"
|
||||||
.DE
|
.DE
|
||||||
to satisfy the old UNIX assembler that reads octal unless followed by
|
to satisfy the old UNIX assembler that reads octal unless followed by
|
||||||
a period, and the ACK assembler that follows C conventions.
|
a period, and the ACK assembler that follows C conventions.
|
||||||
.PP
|
.PP
|
||||||
Tables under control of programs like
|
Tables under control of source code control systems like
|
||||||
.I sccs
|
.I sccs
|
||||||
or
|
or
|
||||||
.I rcs
|
.I rcs
|
||||||
can put their id-string here, for example
|
can put their id-string here, for example
|
||||||
.DS
|
.DS
|
||||||
rcsid="$Header$"
|
rcsid="$\&Header$"
|
||||||
.DE
|
.DE
|
||||||
These strings, like all strings in the table, will eventually
|
These strings, like all strings in the table, will eventually
|
||||||
end up in the binary code generator produced.
|
end up in the binary code generator produced.
|
||||||
@ -385,6 +387,7 @@ same order of magnitude.
|
|||||||
This can be done as
|
This can be done as
|
||||||
.DS
|
.DS
|
||||||
SIZEFACTOR = C\d3\u/C\d4\u
|
SIZEFACTOR = C\d3\u/C\d4\u
|
||||||
|
.sp
|
||||||
TIMEFACTOR = C\d1\u/C\d2\u
|
TIMEFACTOR = C\d1\u/C\d2\u
|
||||||
.DE
|
.DE
|
||||||
Above numbers must be read as rational numbers.
|
Above numbers must be read as rational numbers.
|
||||||
@ -403,8 +406,8 @@ It consists of a list of user-defined
|
|||||||
identifiers optionally followed by the size
|
identifiers optionally followed by the size
|
||||||
of the property in parentheses, default EM_WSIZE.
|
of the property in parentheses, default EM_WSIZE.
|
||||||
Example for the PDP-11:
|
Example for the PDP-11:
|
||||||
.DS
|
.TS
|
||||||
.ta 8 16 24 32 40
|
l l.
|
||||||
PROPERTIES /* The header word for this section */
|
PROPERTIES /* The header word for this section */
|
||||||
|
|
||||||
GENREG /* All PDP registers */
|
GENREG /* All PDP registers */
|
||||||
@ -420,7 +423,7 @@ DBLREGPAIR(16) /* Same, double precision */
|
|||||||
LOCALBASE /* Guess what */
|
LOCALBASE /* Guess what */
|
||||||
STACKPOINTER
|
STACKPOINTER
|
||||||
PROGRAMCOUNTER
|
PROGRAMCOUNTER
|
||||||
.DE
|
.TE
|
||||||
Registers are allocated by asking for a property,
|
Registers are allocated by asking for a property,
|
||||||
so if for some reason in later parts of the table
|
so if for some reason in later parts of the table
|
||||||
one particular register must be allocated it
|
one particular register must be allocated it
|
||||||
@ -438,8 +441,8 @@ Syntax:
|
|||||||
<register> : ident [ '(' string ')' ] [ '=' ident [ '+' ident ] ]
|
<register> : ident [ '(' string ')' ] [ '=' ident [ '+' ident ] ]
|
||||||
.DE
|
.DE
|
||||||
Example for the PDP-11:
|
Example for the PDP-11:
|
||||||
.DS L
|
.TS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
l l.
|
||||||
REGISTERS
|
REGISTERS
|
||||||
|
|
||||||
r0,r2,r4 : GENREG,REG.
|
r0,r2,r4 : GENREG,REG.
|
||||||
@ -453,7 +456,7 @@ dr01("r0")=dr0+dr1,dr23("r2")=dr2+dr3 : DBLREGPAIR.
|
|||||||
lb("r5") : GENREG,LOCALBASE.
|
lb("r5") : GENREG,LOCALBASE.
|
||||||
sp : GENREG,STACKPOINTER.
|
sp : GENREG,STACKPOINTER.
|
||||||
pc : GENREG,PROGRAMCOUNTER.
|
pc : GENREG,PROGRAMCOUNTER.
|
||||||
.DE
|
.TE
|
||||||
.PP
|
.PP
|
||||||
The names in the left hand lists are names of registers as used
|
The names in the left hand lists are names of registers as used
|
||||||
in the table.
|
in the table.
|
||||||
@ -525,7 +528,8 @@ Tokens should usually be declared for every addressing mode
|
|||||||
of the machine at hand and for every size directly usable in
|
of the machine at hand and for every size directly usable in
|
||||||
a machine instruction.
|
a machine instruction.
|
||||||
Example for the PDP-11 (incomplete):
|
Example for the PDP-11 (incomplete):
|
||||||
.DS L
|
.TS
|
||||||
|
l l.
|
||||||
TOKENS
|
TOKENS
|
||||||
|
|
||||||
const2 = { INT num; } 2 cost(2,300) "$" num .
|
const2 = { INT num; } 2 cost(2,300) "$" num .
|
||||||
@ -538,7 +542,7 @@ reginddef2 = { GENREG reg; ADDR off; } 2 "*" off "(" reg ")" .
|
|||||||
regconst2 = { GENREG reg; ADDR off; } 2 .
|
regconst2 = { GENREG reg; ADDR off; } 2 .
|
||||||
relative2 = { ADDR off; } 2 off .
|
relative2 = { ADDR off; } 2 off .
|
||||||
reldef2 = { ADDR off; } 2 "*" off.
|
reldef2 = { ADDR off; } 2 "*" off.
|
||||||
.DE
|
.TE
|
||||||
.PP
|
.PP
|
||||||
Types allowed in the struct are ADDR, INT and all register properties.
|
Types allowed in the struct are ADDR, INT and all register properties.
|
||||||
The type ADDR means a string and an integer,
|
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.
|
from 100% time to 100% space.
|
||||||
.LP
|
.LP
|
||||||
By supplying different code rules in certain situations
|
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.
|
code to the need of the moment.
|
||||||
This is probably most useful with small machines,
|
This is probably most useful with small machines,
|
||||||
experience has shown that on the larger micro's and mini's
|
experience has shown that on the larger micro's and mini's
|
||||||
@ -620,13 +624,13 @@ in the remainder of the table,
|
|||||||
but for clarity it is usually better not to.
|
but for clarity it is usually better not to.
|
||||||
.LP
|
.LP
|
||||||
Example for the PDP-11 (incomplete):
|
Example for the PDP-11 (incomplete):
|
||||||
.DS L
|
.TS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
l l.
|
||||||
SETS
|
SETS
|
||||||
|
|
||||||
src2 = GENREG + regdef2 + regind2 + reginddef2 + relative2 +
|
src2 = GENREG + regdef2 + regind2 + reginddef2 + relative2 +
|
||||||
reldef2 + addr_external + const2 + LOCAL + ILOCAL +
|
\h'\w'= 'u'reldef2 + addr_external + const2 + LOCAL + ILOCAL +
|
||||||
autodec + autoinc .
|
\h'\w'= 'u'autodec + autoinc .
|
||||||
dst2 = src2 - ( const2 + addr_external ) .
|
dst2 = src2 - ( const2 + addr_external ) .
|
||||||
xsrc2 = src2 + ftoint .
|
xsrc2 = src2 + ftoint .
|
||||||
src1 = regdef1 + regind1 + reginddef1 + relative1 + reldef1 .
|
src1 = regdef1 + regind1 + reginddef1 + relative1 + reldef1 .
|
||||||
@ -634,7 +638,7 @@ dst1 = src1 .
|
|||||||
src1or2 = src1 + src2 .
|
src1or2 = src1 + src2 .
|
||||||
src4 = relative4 + regdef4 + DLOCAL + regind4 .
|
src4 = relative4 + regdef4 + DLOCAL + regind4 .
|
||||||
dst4 = src4 .
|
dst4 = src4 .
|
||||||
.DE
|
.TE
|
||||||
Permissible in the set construction are all the usual set operators, i.e.
|
Permissible in the set construction are all the usual set operators, i.e.
|
||||||
.IP +
|
.IP +
|
||||||
set union
|
set union
|
||||||
@ -1154,9 +1158,10 @@ This can of course be done with
|
|||||||
.DS
|
.DS
|
||||||
kills ALL
|
kills ALL
|
||||||
.DE
|
.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
|
if the stack pattern does not start with
|
||||||
.I exact .
|
.I exact .
|
||||||
|
The latter does not erase the contents of registers.
|
||||||
.PP
|
.PP
|
||||||
It is unfortunate that this part is still present in the table
|
It is unfortunate that this part is still present in the table
|
||||||
but it is too much for now to let the
|
but it is too much for now to let the
|
||||||
@ -1248,7 +1253,7 @@ The author of
|
|||||||
.I cgg
|
.I cgg
|
||||||
could not get
|
could not get
|
||||||
.I yacc
|
.I yacc
|
||||||
to be silent without it.
|
to accept his syntax without it.
|
||||||
Sorry about this.
|
Sorry about this.
|
||||||
.IP 2)
|
.IP 2)
|
||||||
a
|
a
|
||||||
@ -1366,15 +1371,14 @@ A list of examples for the PDP-11 is given here.
|
|||||||
Far from being complete it gives examples of most kinds
|
Far from being complete it gives examples of most kinds
|
||||||
of instructions.
|
of instructions.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
pat loc yields {const2, $1}
|
pat loc yields {const2, $1}
|
||||||
|
|
||||||
pat ldc yields {const2, loww($1)}
|
pat ldc yields {const2, loww($1)} {const2, highw($1)}
|
||||||
{const2, highw($1)}
|
|
||||||
.DE
|
.DE
|
||||||
These simple patterns just push one or more tokens onto the fake stack.
|
These simple patterns just push one or more tokens onto the fake stack.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
pat lof
|
pat lof
|
||||||
with REG yields {regind2,%1,$1}
|
with REG yields {regind2,%1,$1}
|
||||||
with exact regconst2 yields {regind2,%1.reg,$1+%1.off}
|
with exact regconst2 yields {regind2,%1.reg,$1+%1.off}
|
||||||
@ -1389,10 +1393,9 @@ not preceded by
|
|||||||
that can always be taken after a coercion,
|
that can always be taken after a coercion,
|
||||||
if necessary.
|
if necessary.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
pat lxl $1>3
|
pat lxl $1>3
|
||||||
uses REG={LOCAL, SL, 2},
|
uses REG={LOCAL, SL, 2}, REG={const2,$1-1}
|
||||||
REG={const2,$1-1}
|
|
||||||
gen 1:
|
gen 1:
|
||||||
move {regind2,%a, SL},%a
|
move {regind2,%a, SL},%a
|
||||||
sob %b,{label,1b} yields %a
|
sob %b,{label,1b} yields %a
|
||||||
@ -1404,7 +1407,7 @@ of the static link,
|
|||||||
that is pushed by the Pascal compiler as the last argument of
|
that is pushed by the Pascal compiler as the last argument of
|
||||||
a function.
|
a function.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
pat stf
|
pat stf
|
||||||
with regconst2 xsrc2
|
with regconst2 xsrc2
|
||||||
kills allexeptcon
|
kills allexeptcon
|
||||||
@ -1419,7 +1422,7 @@ part in a store instruction.
|
|||||||
The set allexeptcon contains all tokens that can be the destination
|
The set allexeptcon contains all tokens that can be the destination
|
||||||
of an indirect store.
|
of an indirect store.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
pat sde
|
pat sde
|
||||||
with exact FLTREG
|
with exact FLTREG
|
||||||
kills posextern
|
kills posextern
|
||||||
@ -1445,7 +1448,7 @@ The third rule is taken by default,
|
|||||||
resulting in two separate stores,
|
resulting in two separate stores,
|
||||||
nothing better exists on the PDP-11.
|
nothing better exists on the PDP-11.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
pat sbi $1==2
|
pat sbi $1==2
|
||||||
with src2 REG
|
with src2 REG
|
||||||
gen sub %1,%2 yields %2
|
gen sub %1,%2 yields %2
|
||||||
@ -1456,9 +1459,9 @@ with exact REG src2-REG
|
|||||||
This rule for
|
This rule for
|
||||||
.I sbi
|
.I sbi
|
||||||
has a normal first part,
|
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
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
pat mli $1==2
|
pat mli $1==2
|
||||||
with ODDREG src2
|
with ODDREG src2
|
||||||
gen mul %2,%1 yields %1
|
gen mul %2,%1 yields %1
|
||||||
@ -1469,7 +1472,7 @@ This shows the general property for rules with commutative
|
|||||||
operators,
|
operators,
|
||||||
heuristics or look ahead will have to decide which rule is the best.
|
heuristics or look ahead will have to decide which rule is the best.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
pat loc sli $1==1 && $2==2
|
pat loc sli $1==1 && $2==2
|
||||||
with REG
|
with REG
|
||||||
gen asl %1 yields %1
|
gen asl %1 yields %1
|
||||||
@ -1477,7 +1480,7 @@ gen asl %1 yields %1
|
|||||||
A simple rule involving a longer EM-pattern,
|
A simple rule involving a longer EM-pattern,
|
||||||
to make use of a specialized instruction available.
|
to make use of a specialized instruction available.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
pat loc loc cii $1==1 && $2==2
|
pat loc loc cii $1==1 && $2==2
|
||||||
with src1or2
|
with src1or2
|
||||||
uses reusing %1,REG
|
uses reusing %1,REG
|
||||||
@ -1488,8 +1491,9 @@ Note the
|
|||||||
.I reusing
|
.I reusing
|
||||||
clause.
|
clause.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
pat loc loc loc cii $1>=0 && $2==2 && $3==4 leaving loc $1 loc 0
|
pat loc loc loc cii $1>=0 && $2==2 && $3==4
|
||||||
|
leaving loc $1 loc 0
|
||||||
.DE
|
.DE
|
||||||
Shows a trivial example of EM-replacement.
|
Shows a trivial example of EM-replacement.
|
||||||
This is a rule that could be done by the
|
This is a rule that could be done by the
|
||||||
@ -1498,7 +1502,7 @@ if word order in longs was defined in EM.
|
|||||||
On a `big-endian' machine the two replacement
|
On a `big-endian' machine the two replacement
|
||||||
instructions would be the other way around.
|
instructions would be the other way around.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
pat and $1==2
|
pat and $1==2
|
||||||
with const2 REG
|
with const2 REG
|
||||||
gen bic {const2,~%1.num},%2 yields %2
|
gen bic {const2,~%1.num},%2 yields %2
|
||||||
@ -1513,7 +1517,7 @@ if an
|
|||||||
.I and -instruction
|
.I and -instruction
|
||||||
is not available on your machine.
|
is not available on your machine.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
pat set $1==2
|
pat set $1==2
|
||||||
with REG
|
with REG
|
||||||
uses REG={const2,1}
|
uses REG={const2,1}
|
||||||
@ -1521,7 +1525,7 @@ gen ash %1,%a yields %a
|
|||||||
.DE
|
.DE
|
||||||
Shows the building of a word-size set.
|
Shows the building of a word-size set.
|
||||||
.DS
|
.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
|
pat lae aar $2==2 && rom($1,3)==1 && rom($1,1)==0
|
||||||
leaving adi 2
|
leaving adi 2
|
||||||
|
|
||||||
@ -1531,7 +1535,7 @@ pat lae aar $2==2 && rom($1,3)==1 && rom($1,1)!=0
|
|||||||
Two rules showing the use of the rom pseudo function,
|
Two rules showing the use of the rom pseudo function,
|
||||||
and some array optimalisation.
|
and some array optimalisation.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
pat bra
|
pat bra
|
||||||
with STACK
|
with STACK
|
||||||
gen jbr {label, $1}
|
gen jbr {label, $1}
|
||||||
@ -1540,7 +1544,7 @@ A simple jump.
|
|||||||
The stack pattern guarantees that everything will be stacked
|
The stack pattern guarantees that everything will be stacked
|
||||||
before the jump is taken.
|
before the jump is taken.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
pat cal
|
pat cal
|
||||||
with STACK
|
with STACK
|
||||||
gen jsr pc,{label, $1}
|
gen jsr pc,{label, $1}
|
||||||
@ -1548,7 +1552,7 @@ gen jsr pc,{label, $1}
|
|||||||
A simple call.
|
A simple call.
|
||||||
Same comments as previous rule.
|
Same comments as previous rule.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
pat lfr $1==2 yields r0
|
pat lfr $1==2 yields r0
|
||||||
pat lfr $1==4 yields r1 r0
|
pat lfr $1==4 yields r1 r0
|
||||||
.DE
|
.DE
|
||||||
@ -1560,7 +1564,7 @@ instruction, and some other instructions must leave
|
|||||||
the function return area intact.
|
the function return area intact.
|
||||||
See the defining document for EM for exact information.
|
See the defining document for EM for exact information.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
pat ret $1==0
|
pat ret $1==0
|
||||||
with STACK
|
with STACK
|
||||||
gen mov lb,sp
|
gen mov lb,sp
|
||||||
@ -1574,7 +1578,7 @@ In a table with register variables the
|
|||||||
part would just contain
|
part would just contain
|
||||||
.I return .
|
.I return .
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
pat blm
|
pat blm
|
||||||
with REG REG
|
with REG REG
|
||||||
uses REG={const2,$1/2}
|
uses REG={const2,$1/2}
|
||||||
@ -1592,7 +1596,7 @@ It uses the marriage thesis from Hall,
|
|||||||
a thesis from combinatorial mathematics,
|
a thesis from combinatorial mathematics,
|
||||||
to accomplish this.
|
to accomplish this.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
pat exg $1==2
|
pat exg $1==2
|
||||||
with src2 src2 yields %1 %2
|
with src2 src2 yields %1 %2
|
||||||
.DE
|
.DE
|
||||||
@ -1600,8 +1604,8 @@ This rule shows the exchanging of two elements on the fake stack.
|
|||||||
.NH 2
|
.NH 2
|
||||||
Code rules using procedures
|
Code rules using procedures
|
||||||
.PP
|
.PP
|
||||||
To start this chapter it must be admitted at once that the
|
To start this section it must be admitted at once that the
|
||||||
word procedure is chosen here mainly for it's advertising
|
word procedure is chosen here mainly for its advertising
|
||||||
value.
|
value.
|
||||||
It more resembles a glorified goto but this of course can
|
It more resembles a glorified goto but this of course can
|
||||||
not be admitted in the glossy brochures.
|
not be admitted in the glossy brochures.
|
||||||
@ -1660,7 +1664,7 @@ The string `*' can be used as an equivalent for `[1]'.
|
|||||||
Just in case this is not clear, here is an example for
|
Just in case this is not clear, here is an example for
|
||||||
a procedure to increment/decrement a register.
|
a procedure to increment/decrement a register.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
incop REG:rw:cc . /* in the INSTRUCTIONS part of course */
|
incop REG:rw:cc . /* in the INSTRUCTIONS part of course */
|
||||||
|
|
||||||
proc incdec
|
proc incdec
|
||||||
@ -1676,7 +1680,7 @@ call <identifier> '(' string [ ',' string ] ')'
|
|||||||
.DE
|
.DE
|
||||||
which leads to the following large example:
|
which leads to the following large example:
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
proc bxx example beq
|
proc bxx example beq
|
||||||
with src2 src2 STACK
|
with src2 src2 STACK
|
||||||
gen cmp %2,%1
|
gen cmp %2,%1
|
||||||
@ -1852,7 +1856,7 @@ The next part of the table defines the coercions that are possible
|
|||||||
on the defined tokens.
|
on the defined tokens.
|
||||||
Example for the PDP-11:
|
Example for the PDP-11:
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
COERCIONS
|
COERCIONS
|
||||||
|
|
||||||
from STACK
|
from STACK
|
||||||
@ -1871,7 +1875,7 @@ gen mov {autoinc,sp},%a.1
|
|||||||
These three coercions just deliver a certain type
|
These three coercions just deliver a certain type
|
||||||
of register by popping it from the real stack.
|
of register by popping it from the real stack.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
from LOCAL yields {regind2,lb,%1.ind}
|
from LOCAL yields {regind2,lb,%1.ind}
|
||||||
|
|
||||||
from DLOCAL yields {regind4,lb,%1.ind}
|
from DLOCAL yields {regind4,lb,%1.ind}
|
||||||
@ -1880,7 +1884,7 @@ from REG yields {regconst2, %1, 0}
|
|||||||
.DE
|
.DE
|
||||||
These three are zero-cost rewriting rules.
|
These three are zero-cost rewriting rules.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
from regconst2 %1.off==1
|
from regconst2 %1.off==1
|
||||||
uses reusing %1,REG=%1.reg
|
uses reusing %1,REG=%1.reg
|
||||||
gen inc %a yields %a
|
gen inc %a yields %a
|
||||||
@ -1900,7 +1904,7 @@ Only in the last case is it always necessary to allocate
|
|||||||
an extra register,
|
an extra register,
|
||||||
since arithmetic on the localbase is unthinkable.
|
since arithmetic on the localbase is unthinkable.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
from xsrc2
|
from xsrc2
|
||||||
uses reusing %1, REG=%1 yields %a
|
uses reusing %1, REG=%1 yields %a
|
||||||
|
|
||||||
@ -1921,7 +1925,7 @@ ensure bytes are not sign-extended.
|
|||||||
In EM it is defined that the result of a \fBloi\fP\ 1
|
In EM it is defined that the result of a \fBloi\fP\ 1
|
||||||
instruction is an integer in the range 0..255.
|
instruction is an integer in the range 0..255.
|
||||||
.DS
|
.DS
|
||||||
.ta 8 16 24 32 40 48 56 64
|
.ta 7.5c
|
||||||
from REGPAIR yields %1.2 %1.1
|
from REGPAIR yields %1.2 %1.1
|
||||||
|
|
||||||
from regind4 yields {regind2,%1.reg,2+%1.off}
|
from regind4 yields {regind2,%1.reg,2+%1.off}
|
||||||
@ -1953,7 +1957,7 @@ and TEM_PSIZE.
|
|||||||
The type 'int' is used for things like counters that won't require
|
The type 'int' is used for things like counters that won't require
|
||||||
more than 16 bits precision.
|
more than 16 bits precision.
|
||||||
The type 'word' is used among others to assemble datawords and
|
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
|
The type 'full' is used for addresses and is of type 'long' if
|
||||||
TEM_WSIZE>2 or TEM_PSIZE>2.
|
TEM_WSIZE>2 or TEM_PSIZE>2.
|
||||||
.PP
|
.PP
|
||||||
@ -2082,7 +2086,7 @@ If omitted no initialization is assumed.
|
|||||||
.NH 3
|
.NH 3
|
||||||
Example mach.h for the PDP-11
|
Example mach.h for the PDP-11
|
||||||
.DS L
|
.DS L
|
||||||
.ta 8 16 24 32 40 48 56
|
.ta 4c
|
||||||
#define ex_ap(y) fprintf(codefile,"\et.globl %s\en",y)
|
#define ex_ap(y) fprintf(codefile,"\et.globl %s\en",y)
|
||||||
#define in_ap(y) /* nothing */
|
#define in_ap(y) /* nothing */
|
||||||
|
|
||||||
@ -2094,13 +2098,13 @@ Example mach.h for the PDP-11
|
|||||||
|
|
||||||
#define cst_fmt "$%d."
|
#define cst_fmt "$%d."
|
||||||
#define off_fmt "%d."
|
#define off_fmt "%d."
|
||||||
#define ilb_fmt "I%02x%x"
|
#define ilb_fmt "I%x_%x"
|
||||||
#define dlb_fmt "_%d"
|
#define dlb_fmt "_%d"
|
||||||
#define hol_fmt "hol%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_ilb(x) fprintf(codefile,"%s\en",x)
|
||||||
#define con_dlb(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
|
This function is called when a
|
||||||
.B mes
|
.B mes
|
||||||
pseudo is seen that is not handled by the machine independent part.
|
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 -
|
.IP -
|
||||||
segname[]
|
segname[]
|
||||||
.br
|
.br
|
||||||
@ -2212,7 +2216,7 @@ Example mach.c for the PDP-11
|
|||||||
As an example of the sort of code expected,
|
As an example of the sort of code expected,
|
||||||
the mach.c for the PDP-11 is presented here.
|
the mach.c for the PDP-11 is presented here.
|
||||||
.DS L
|
.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
|
* machine dependent back end routines for the PDP-11
|
||||||
*/
|
*/
|
||||||
@ -2678,7 +2682,7 @@ otherwise the register is marked empty.
|
|||||||
.NH 4
|
.NH 4
|
||||||
DO_INSTR
|
DO_INSTR
|
||||||
.PP
|
.PP
|
||||||
This prints an instruction and it's operands.
|
This prints an instruction and its operands.
|
||||||
Only done on toplevel.
|
Only done on toplevel.
|
||||||
.NH 4
|
.NH 4
|
||||||
DO_MOVE
|
DO_MOVE
|
||||||
|
|||||||
@ -4,4 +4,4 @@
|
|||||||
# define VERSION 3 /* 16 bits number */
|
# define VERSION 3 /* 16 bits number */
|
||||||
|
|
||||||
/* The default machine used by ack, acc, apc */
|
/* The default machine used by ack, acc, apc */
|
||||||
# define ACKM "vax2"
|
# define ACKM "pdp"
|
||||||
|
|||||||
120
h/out.h
120
h/out.h
@ -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))
|
|
||||||
25
h/ranlib.h
25
h/ranlib.h
@ -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"
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -12,7 +12,6 @@ csb.s
|
|||||||
dup.s
|
dup.s
|
||||||
dvi2.s
|
dvi2.s
|
||||||
exg.s
|
exg.s
|
||||||
flp.s
|
|
||||||
inn.s
|
inn.s
|
||||||
ior.s
|
ior.s
|
||||||
lar2.s
|
lar2.s
|
||||||
|
|||||||
@ -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
|
|
||||||
@ -818,61 +818,15 @@ gen Call {label,".sri4"}
|
|||||||
/* Group 5: Floating point arithmetic */
|
/* Group 5: Floating point arithmetic */
|
||||||
/********************************************/
|
/********************************************/
|
||||||
|
|
||||||
pat adf $1==4
|
/* Floating points are not supported */
|
||||||
with STACK
|
|
||||||
gen Call {label,".adf4"}
|
|
||||||
|
|
||||||
pat adf $1==8
|
pat adf gen Call {label,"eunimpl"}
|
||||||
with STACK
|
pat sbf gen Call {label,"eunimpl"}
|
||||||
gen Call {label,".adf8"}
|
pat mlf gen Call {label,"eunimpl"}
|
||||||
|
pat dvf gen Call {label,"eunimpl"}
|
||||||
pat sbf $1==4
|
pat ngf gen Call {label,"eunimpl"}
|
||||||
with STACK
|
pat fif gen Call {label,"eunimpl"}
|
||||||
gen Call {label,".sbf4"}
|
pat fef gen Call {label,"eunimpl"}
|
||||||
|
|
||||||
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"}
|
|
||||||
|
|
||||||
/********************************************/
|
/********************************************/
|
||||||
/* Group 6: Pointer arithmetic */
|
/* Group 6: Pointer arithmetic */
|
||||||
@ -965,13 +919,7 @@ pat zre
|
|||||||
uses hlreg={const2,0}
|
uses hlreg={const2,0}
|
||||||
gen shld {label,$1}
|
gen shld {label,$1}
|
||||||
|
|
||||||
pat zrf $1==4
|
pat zrf gen Call {label,"eunimpl"}
|
||||||
with STACK
|
|
||||||
gen Call {label,".zrf4"}
|
|
||||||
|
|
||||||
pat zrf $1==8
|
|
||||||
with STACK
|
|
||||||
gen Call {label,".zrf8"}
|
|
||||||
|
|
||||||
pat zer $1==2 yields {const2,0}
|
pat zer $1==2 yields {const2,0}
|
||||||
|
|
||||||
@ -1087,25 +1035,11 @@ with STACK
|
|||||||
uses areg={const1,0}
|
uses areg={const1,0}
|
||||||
gen Call {label,".cii"}
|
gen Call {label,".cii"}
|
||||||
|
|
||||||
pat cfi
|
pat cfi gen Call {label,"eunimpl"}
|
||||||
with STACK
|
pat cif gen Call {label,"eunimpl"}
|
||||||
gen Call {label,".cfi"}
|
pat cuf gen Call {label,"eunimpl"}
|
||||||
|
pat cff gen Call {label,"eunimpl"}
|
||||||
pat cif
|
pat cfu gen Call {label,"eunimpl"}
|
||||||
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"}
|
|
||||||
|
|
||||||
/*****************************************/
|
/*****************************************/
|
||||||
/* Group 9: Logical instructions */
|
/* Group 9: Logical instructions */
|
||||||
@ -1392,13 +1326,7 @@ with STACK
|
|||||||
uses areg={const1,1}
|
uses areg={const1,1}
|
||||||
gen Call {label,".cmi4"} yields de
|
gen Call {label,".cmi4"} yields de
|
||||||
|
|
||||||
pat cmf $1==4
|
pat cmf gen Call {label,"eunimpl"}
|
||||||
with STACK
|
|
||||||
gen Call {label,".cmf4"}
|
|
||||||
|
|
||||||
pat cmf $1==8
|
|
||||||
with STACK
|
|
||||||
gen Call {label,".cmf8"}
|
|
||||||
|
|
||||||
pat cmu $1==2
|
pat cmu $1==2
|
||||||
with hl_or_de hl_or_de
|
with hl_or_de hl_or_de
|
||||||
|
|||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -23,19 +23,6 @@ static char rcsid[] = "$Header$";
|
|||||||
* machine dependent back end routines for the Motorola 68000
|
* 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; {
|
con_part(sz,w) register sz; word w; {
|
||||||
|
|
||||||
while (part_size % sz)
|
while (part_size % sz)
|
||||||
@ -61,58 +48,24 @@ con_mult(sz) word sz; {
|
|||||||
fprintf(codefile,".long %s\n",str);
|
fprintf(codefile,".long %s\n",str);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef IEEEFLOAT
|
con_float() {
|
||||||
dbl_adjust(fl)
|
|
||||||
my_dbl *fl;
|
|
||||||
{
|
|
||||||
EXTEND buf;
|
|
||||||
|
|
||||||
/* special routine to strip SGL_BIAS */
|
static int been_here;
|
||||||
dbl_extract(fl,&buf);
|
if (argval != 4 && argval != 8)
|
||||||
/* standard routine to add DBL_BIAS */
|
fatal("bad fcon size");
|
||||||
fcompact(&buf,fl,sizeof(double));
|
fprintf(codefile,".long\t");
|
||||||
}
|
if (argval == 8)
|
||||||
#endif IEEEFLOAT
|
fprintf(codefile,"F_DUM,");
|
||||||
|
fprintf(codefile,"F_DUM\n");
|
||||||
con_float()
|
if ( !been_here++)
|
||||||
{
|
{
|
||||||
register word sz;
|
fprintf(stderr,"Warning : dummy float-constant(s)\n");
|
||||||
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++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef REGVARS
|
#ifdef REGVARS
|
||||||
|
|
||||||
|
|
||||||
regscore(off,size,typ,score,totyp)
|
regscore(off,size,typ,score,totyp)
|
||||||
long off;
|
long off;
|
||||||
{
|
{
|
||||||
@ -140,6 +93,8 @@ regscore(off,size,typ,score,totyp)
|
|||||||
score -= 1; /* take save/restore into account */
|
score -= 1; /* take save/restore into account */
|
||||||
return score;
|
return score;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct regsav_t {
|
struct regsav_t {
|
||||||
char *rs_reg; /* e.g. "a3" or "d5" */
|
char *rs_reg; /* e.g. "a3" or "d5" */
|
||||||
long rs_off; /* offset of variable */
|
long rs_off; /* offset of variable */
|
||||||
@ -148,10 +103,20 @@ struct regsav_t {
|
|||||||
|
|
||||||
|
|
||||||
int regnr;
|
int regnr;
|
||||||
|
int nr_a_regs,nr_d_regs;
|
||||||
|
int TEM_BSIZE;
|
||||||
|
static long nlocals;
|
||||||
|
|
||||||
|
prolog(n)
|
||||||
|
{ nlocals = n; }
|
||||||
|
|
||||||
|
|
||||||
i_regsave()
|
i_regsave()
|
||||||
{
|
{
|
||||||
regnr = 0;
|
regnr = 0;
|
||||||
|
nr_a_regs = 0;
|
||||||
|
nr_d_regs = 0;
|
||||||
|
TEM_BSIZE = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MOVEM_LIMIT 2
|
#define MOVEM_LIMIT 2
|
||||||
@ -160,9 +125,11 @@ i_regsave()
|
|||||||
* we simply use several move.l's.
|
* we simply use several move.l's.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
save()
|
save()
|
||||||
{
|
{
|
||||||
register struct regsav_t *p;
|
register struct regsav_t *p;
|
||||||
|
int i;
|
||||||
|
|
||||||
if (regnr > MOVEM_LIMIT) {
|
if (regnr > MOVEM_LIMIT) {
|
||||||
fprintf(codefile,"movem.l ");
|
fprintf(codefile,"movem.l ");
|
||||||
@ -173,16 +140,37 @@ save()
|
|||||||
}
|
}
|
||||||
fprintf(codefile,",-(sp)\n");
|
fprintf(codefile,",-(sp)\n");
|
||||||
} else {
|
} else {
|
||||||
for (p = regsav; p < ®sav[regnr]; p++) {
|
/* Note that the order in which the registers are saved
|
||||||
fprintf(codefile,"move.l %s,-(sp)\n",p->rs_reg);
|
* 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 */
|
/* initialise register-parameters */
|
||||||
for (p = regsav; p < ®sav[regnr]; p++) {
|
for (p = regsav; p < ®sav[regnr]; p++) {
|
||||||
if (p->rs_off >= 0) {
|
if (p->rs_off >= 0) {
|
||||||
fprintf(codefile,"move.%c %ld(a6),%s\n",
|
fprintf(codefile,"move.%c %ld(a6),%s\n",
|
||||||
(p->rs_size == 4 ? 'l' : 'w'),
|
(p->rs_size == 4 ? 'l' : 'w'),
|
||||||
p->rs_off,
|
p->rs_off + TEM_BSIZE,
|
||||||
p->rs_reg);
|
p->rs_reg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -191,7 +179,10 @@ save()
|
|||||||
restr()
|
restr()
|
||||||
{
|
{
|
||||||
register struct regsav_t *p;
|
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) {
|
if (regnr > MOVEM_LIMIT) {
|
||||||
fprintf(codefile,"movem.l (sp)+,");
|
fprintf(codefile,"movem.l (sp)+,");
|
||||||
for (p = regsav; ;) {
|
for (p = regsav; ;) {
|
||||||
@ -201,11 +192,13 @@ restr()
|
|||||||
}
|
}
|
||||||
putc('\n',codefile);
|
putc('\n',codefile);
|
||||||
} else {
|
} else {
|
||||||
for (p = ®sav[regnr-1]; p >= regsav; p--) {
|
for (i = nr_d_regs - 1; i >= 0; i--) {
|
||||||
fprintf(codefile,"move.l (sp)+,%s\n",p->rs_reg);
|
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");
|
fprintf(codefile,"rts\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,6 +214,12 @@ regsave(str,off,size)
|
|||||||
{
|
{
|
||||||
assert (regnr < 9);
|
assert (regnr < 9);
|
||||||
regsav[regnr].rs_reg = str;
|
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_off = off;
|
||||||
regsav[regnr++].rs_size = size;
|
regsav[regnr++].rs_size = size;
|
||||||
fprintf(codefile, "!Local %ld into %s\n",off,str);
|
fprintf(codefile, "!Local %ld into %s\n",off,str);
|
||||||
@ -233,11 +232,15 @@ regreturn()
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef REGVARS
|
||||||
|
|
||||||
prolog(nlocals) full nlocals; {
|
prolog(nlocals) full nlocals; {
|
||||||
|
|
||||||
fprintf(codefile,"tst.b -%D(sp)\nlink\ta6,#-%D\n",nlocals+40,nlocals);
|
fprintf(codefile,"tst.b -%D(sp)\nlink\ta6,#-%D\n",nlocals+40,nlocals);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
mes(type) word type ; {
|
mes(type) word type ; {
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
"$Header$"
|
|
||||||
/*
|
/*
|
||||||
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||||
*
|
*
|
||||||
@ -33,7 +32,6 @@
|
|||||||
|
|
||||||
EM_WSIZE = 2
|
EM_WSIZE = 2
|
||||||
EM_PSIZE = 4
|
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]"
|
ABS1 = {STRING addr;} 2 cost=(3,5) "%[addr]"
|
||||||
IMMEDIATE = {INT cc;} 2 cost=(1,2) "#%[cc]"
|
IMMEDIATE = {INT cc;} 2 cost=(1,2) "#%[cc]"
|
||||||
LOCAL_ADDR = {INT off;} 4 /* not really addressable */
|
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]"
|
EXTERNAL_ADDR = {STRING off;} 4 cost=(4,4) "#%[off]"
|
||||||
INDEX_ADDR = {REGISTER reg,ireg;
|
INDEX_ADDR = {REGISTER reg,ireg;
|
||||||
INT di;} 4
|
INT di;} 4
|
||||||
@ -156,15 +152,13 @@ ALT_MEM = ALTERABLE * MEMORY
|
|||||||
DATASCR = DATAREG * SCRATCH
|
DATASCR = DATAREG * SCRATCH
|
||||||
ADDSCR = ADDREG * SCRATCH
|
ADDSCR = ADDREG * SCRATCH
|
||||||
MEM_ALL = ALL - DATAREG - DATAREG4 - ADDREG - IMMEDIATE - IMMEDIATE4
|
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
|
ALL_ACCESSIBLE = IADDREG + IADDREG4 + IADDREG1 + INDEXED + INDEXED4
|
||||||
|
|
||||||
ANY1 = DISPL1 + ABS1 + IADDREG1
|
ANY1 = DISPL1 + ABS1 + IADDREG1
|
||||||
DATA_ALT1 = ANY1
|
DATA_ALT_1OR2 = DATA_ALT + ANY1
|
||||||
DATA_ALT_1OR2 = DATA_ALT + DATA_ALT1
|
|
||||||
|
|
||||||
|
|
||||||
REG4 = DATAREG4 + ADDREG
|
|
||||||
DATA4 = DATAREG4 + IADDREG4 + DISPL4 + INDEXED4 +
|
DATA4 = DATAREG4 + IADDREG4 + DISPL4 + INDEXED4 +
|
||||||
ABS4 + IMMEDIATE4 + DOUBLE
|
ABS4 + IMMEDIATE4 + DOUBLE
|
||||||
MEMORY4 = DATA4 - DATAREG4
|
MEMORY4 = DATA4 - DATAREG4
|
||||||
@ -210,18 +204,13 @@ lil | | allocate(ADDREG = {DISPL4,LB,$1})| {IADDREG,%[a]} | |
|
|||||||
lof | ADDREG | | {DISPL,%[1],$1} | |
|
lof | ADDREG | | {DISPL,%[1],$1} | |
|
||||||
... | nocoercions: EXTERNAL_ADDR | | {ABS,%[1.off]+"+"+tostring($1)} | |
|
... | nocoercions: EXTERNAL_ADDR | | {ABS,%[1.off]+"+"+tostring($1)} | |
|
||||||
... | nocoercions: LOCAL_ADDR | | {DISPL,LB,%[1.off]+$1} | |
|
... | nocoercions: LOCAL_ADDR | | {DISPL,LB,%[1.off]+$1} | |
|
||||||
... | nocoercions: REGOFF_ADDR | | {DISPL,%[1.reg],%[1.off]+$1} | |
|
|
||||||
ldf | ADDREG | | {DISPL4,%[1],$1} | |
|
ldf | ADDREG | | {DISPL4,%[1],$1} | |
|
||||||
... | nocoercions: EXTERNAL_ADDR | | {ABS4,%[1.off]+"+"+tostring($1)} | |
|
... | nocoercions: EXTERNAL_ADDR | | {ABS4,%[1.off]+"+"+tostring($1)} | |
|
||||||
... | nocoercions: LOCAL_ADDR | | {DISPL4,LB,%[1.off]+$1} | |
|
... | nocoercions: LOCAL_ADDR | | {DISPL4,LB,%[1.off]+$1} | |
|
||||||
... | nocoercions: REGOFF_ADDR | | {DISPL4,%[1.reg],%[1.off]+$1} | |
|
|
||||||
lal | | | {LOCAL_ADDR,$1} | |
|
lal | | | {LOCAL_ADDR,$1} | |
|
||||||
| LOCAL_ADDR | allocate(ADDREG)
|
| LOCAL_ADDR | allocate(ADDREG)
|
||||||
"lea %[1.off](a6),%[a]"
|
"lea %[1.off](a6),%[a]"
|
||||||
samecc | %[a] | |
|
samecc | %[a] | |
|
||||||
| REGOFF_ADDR | allocate(ADDREG)
|
|
||||||
"lea %[1.off](%[1.reg]),%[a]"
|
|
||||||
samecc | %[a] | |
|
|
||||||
lae | | | {EXTERNAL_ADDR,$1} | |
|
lae | | | {EXTERNAL_ADDR,$1} | |
|
||||||
| EXTERNAL_ADDR | allocate(ADDREG)
|
| EXTERNAL_ADDR | allocate(ADDREG)
|
||||||
"lea %[1.off],%[a]"
|
"lea %[1.off],%[a]"
|
||||||
@ -230,33 +219,17 @@ lae | | | {EXTERNAL_ADDR,$1} | |
|
|||||||
/* For the lxl and lxa instructions we assume that the static link
|
/* For the lxl and lxa instructions we assume that the static link
|
||||||
* (i.e. a pointer to the LB of the lexically enclosing subprogram)
|
* (i.e. a pointer to the LB of the lexically enclosing subprogram)
|
||||||
* is passed as zero-th actual parameter. The distance (in bytes)
|
* 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 == 0 | | | LB | |
|
||||||
lxl $1 == 1 | | | {DISPL4,LB,8} | |
|
lxl $1>=1 | STACK |
|
||||||
lxl $1>1 | |
|
"move.w #$1,-(sp)"
|
||||||
allocate(ADDREG,DATAREG = {IMMEDIATE,$1-1})
|
"jsr .lxl" | A0 | |
|
||||||
"move.l a6,%[a]"
|
lxa | STACK | "move.w #$1,-(sp)"
|
||||||
"1:"
|
"jsr .lxa" | A0 | |
|
||||||
"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] | |
|
|
||||||
loi $1 == 1 | ADDREG | | {IADDREG1, %[1]} | |
|
loi $1 == 1 | ADDREG | | {IADDREG1, %[1]} | |
|
||||||
... | nocoercions: LOCAL_ADDR | | {DISPL1,LB,%[1.off]} | |
|
... | nocoercions: LOCAL_ADDR | | {DISPL1,LB,%[1.off]} | |
|
||||||
... | nocoercions: REGOFF_ADDR | | {DISPL1,%[1.reg],%[1.off]} | |
|
|
||||||
... | nocoercions: EXTERNAL_ADDR | | {ABS1,%[1.off]} | |
|
... | nocoercions: EXTERNAL_ADDR | | {ABS1,%[1.off]} | |
|
||||||
loi $1 == 2 | ADDREG | | {IADDREG,%[1]} | |
|
loi $1 == 2 | ADDREG | | {IADDREG,%[1]} | |
|
||||||
loi $1 == 4 | ADDREG | | {IADDREG4,%[1]} | |
|
loi $1 == 4 | ADDREG | | {IADDREG4,%[1]} | |
|
||||||
@ -272,9 +245,7 @@ lae loi $2 == 6 | | remove(ALL)
|
|||||||
lae loi $2 == 8 | | remove(ALL)
|
lae loi $2 == 8 | | remove(ALL)
|
||||||
"move.l $1+4,-(sp)"
|
"move.l $1+4,-(sp)"
|
||||||
"move.l $1,-(sp)" | | |
|
"move.l $1,-(sp)" | | |
|
||||||
loi $1 == 6 | ADDREG | | {DISPL,%[1],4} {IADDREG4,%[1]} | |
|
loi $1 > 4 | ADDSCR | remove(ALL)
|
||||||
loi $1 == 8 | ADDREG | | {DISPL4,%[1],4} {IADDREG4,%[1]} | |
|
|
||||||
loi $1 > 8 | ADDSCR | remove(ALL)
|
|
||||||
allocate(DATAREG4= {IMMEDIATE4,$1/2-1})
|
allocate(DATAREG4= {IMMEDIATE4,$1/2-1})
|
||||||
"add.l #$1,%[1]"
|
"add.l #$1,%[1]"
|
||||||
"1:"
|
"1:"
|
||||||
@ -328,12 +299,10 @@ lpi | | | {EXTERNAL_ADDR,$1} | |
|
|||||||
|
|
||||||
|
|
||||||
#ifdef REGVARS
|
#ifdef REGVARS
|
||||||
stl inreg($1)==2 | nocoercions: ANY | remove(regvar($1))
|
stl inreg($1)==2 | ANY | remove(regvar($1))
|
||||||
move(%[1],regvar($1)) | | |
|
move(%[1],regvar($1)) | | |
|
||||||
... | STACK |
|
|
||||||
"move.w (sp)+,%(regvar($1)%)" | | |
|
|
||||||
#endif
|
#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 ||
|
remove(DISPL4,%[reg] == LB && (%[dis] == $1-2 ||
|
||||||
%[dis] == $1))
|
%[dis] == $1))
|
||||||
remove(DISPL1,%[reg] == LB && (%[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(DISPL1,%[reg] != LB)
|
||||||
remove(ALL_ACCESSIBLE)
|
remove(ALL_ACCESSIBLE)
|
||||||
move(%[1],{DISPL,LB,$1}) | | |
|
move(%[1],{DISPL,LB,$1}) | | |
|
||||||
... | STACK |
|
|
||||||
"move.w (sp)+,$1(a6)" | | |
|
|
||||||
ste | ANY |
|
ste | ANY |
|
||||||
remove(ABS)
|
remove(ABS)
|
||||||
remove(ABS4)
|
remove(ABS4)
|
||||||
@ -411,29 +378,6 @@ sti $1 == 1
|
|||||||
... | nocoercions: LOCAL_ADDR ANY1 |
|
... | nocoercions: LOCAL_ADDR ANY1 |
|
||||||
remove(MEM_ALL)
|
remove(MEM_ALL)
|
||||||
move(%[2],{DISPL1,LB,%[1.off]}) | | |
|
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 |
|
... | nocoercions: EXTERNAL_ADDR DATAREG |
|
||||||
remove(MEM_ALL)
|
remove(MEM_ALL)
|
||||||
move(%[2], {ABS1,%[1.off]}) | | |
|
move(%[2], {ABS1,%[1.off]}) | | |
|
||||||
@ -471,13 +415,10 @@ sts $1 == 2 | | remove(ALL)
|
|||||||
"jsr .sts"
|
"jsr .sts"
|
||||||
| | |
|
| | |
|
||||||
#ifdef REGVARS
|
#ifdef REGVARS
|
||||||
sdl inreg($1)==2 | nocoercions: ANY4 | remove(regvar($1))
|
sdl inreg($1)==2 | ANY4 | remove(regvar($1))
|
||||||
move (%[1],regvar($1)) | | |
|
move (%[1],regvar($1)) | | |
|
||||||
... | STACK |
|
|
||||||
"move.l (sp)+,%(regvar($1)%)" | | |
|
|
||||||
#endif
|
#endif
|
||||||
sdl | nocoercions: ANY4 |
|
sdl | ANY4 | remove(DISPL,%[reg] == LB && (%[dis] == $1 || %[dis] == $1+2))
|
||||||
remove(DISPL,%[reg] == LB && (%[dis] == $1 || %[dis] == $1+2))
|
|
||||||
remove(DISPL4,%[reg] == LB && (%[dis] >= $1-2 &&
|
remove(DISPL4,%[reg] == LB && (%[dis] >= $1-2 &&
|
||||||
%[dis] <= $1+2))
|
%[dis] <= $1+2))
|
||||||
remove(DISPL1,%[reg] == LB && (%[dis] >= $1 &&
|
remove(DISPL1,%[reg] == LB && (%[dis] >= $1 &&
|
||||||
@ -487,8 +428,6 @@ sdl | nocoercions: ANY4 |
|
|||||||
remove(DISPL1,%[reg] != LB)
|
remove(DISPL1,%[reg] != LB)
|
||||||
remove(ALL_ACCESSIBLE)
|
remove(ALL_ACCESSIBLE)
|
||||||
move(%[1],{DISPL4,LB,$1}) | | |
|
move(%[1],{DISPL4,LB,$1}) | | |
|
||||||
... | STACK |
|
|
||||||
"move.l (sp)+,$1(a6)" | | |
|
|
||||||
sde | ANY4 |
|
sde | ANY4 |
|
||||||
remove(ABS)
|
remove(ABS)
|
||||||
remove(ABS4)
|
remove(ABS4)
|
||||||
@ -510,41 +449,6 @@ sdf | ADDREG ANY4 | remove(MEM_ALL)
|
|||||||
* local variables that are not register-variables.
|
* 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 |
|
lol adi stl $1 == $3 && $2 == 2 && inreg($1)==2 | ANY |
|
||||||
remove(regvar($1))
|
remove(regvar($1))
|
||||||
@ -643,15 +547,14 @@ lol loc slu stl $1 == $4 && $2 == 1 && $3 == 2 && inreg($1)==2 | |
|
|||||||
remove(regvar($1))
|
remove(regvar($1))
|
||||||
"asl.w #1,%(regvar($1)%)"
|
"asl.w #1,%(regvar($1)%)"
|
||||||
erase(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))
|
ldl adp sdl $1 == $3 && inreg($1)==2 | | remove(regvar($1))
|
||||||
"add.l #$2,%(regvar($1)%)"
|
"add.l #$2,%(regvar($1)%)"
|
||||||
erase(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 | |
|
loc ldl ads sdl $2 == $4 && $3 == 2 && inreg($2)==2 | |
|
||||||
remove(regvar($2))
|
remove(regvar($2))
|
||||||
"add.l #$1,%(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)) | | |
|
erase(regvar($2)) | | |
|
||||||
lil inc sil $1==$3 && inreg($1)==2 | |
|
lil inc sil $1==$3 && inreg($1)==2 | |
|
||||||
remove(MEM_ALL)
|
remove(MEM_ALL)
|
||||||
"add.w #1,(%(regvar($1)%))"
|
"add.w #1,(%(regvar($1)%))" | | |
|
||||||
setcc({IADDREG,regvar($1)}) | | |
|
|
||||||
lil dec sil $1==$3 && inreg($1)==2 | |
|
lil dec sil $1==$3 && inreg($1)==2 | |
|
||||||
remove(MEM_ALL)
|
remove(MEM_ALL)
|
||||||
"sub.w #1,(%(regvar($1)%))"
|
"sub.w #1,(%(regvar($1)%))" | | |
|
||||||
setcc({IADDREG,regvar($1)}) | | |
|
|
||||||
lol and stl $1 == $3 && $2 == 2 && inreg($1)==2 | ANY |
|
lol and stl $1 == $3 && $2 == 2 && inreg($1)==2 | ANY |
|
||||||
remove(regvar($1))
|
remove(regvar($1))
|
||||||
"and.w %[1],%(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 | |
|
loe ngi ste $1 == $3 && $2 == 4 | |
|
||||||
remove(MEM_ALL)
|
remove(MEM_ALL)
|
||||||
"neg.l $1" | | |
|
"neg.l $1" | | |
|
||||||
loc sli $1 == 1 && $2 == 2 | DATASCR |
|
loc sli $1 >= 1 && $1 <= 8 && $2 == 2 | DATASCR |
|
||||||
"add.w %[1],%[1]"
|
|
||||||
erase(%[1])
|
|
||||||
setcc(%[1]) | %[1] | |
|
|
||||||
loc sli $1 > 1 && $1 <= 8 && $2 == 2 | DATASCR |
|
|
||||||
"asl.w #$1,%[1]"
|
"asl.w #$1,%[1]"
|
||||||
erase(%[1]) | %[1] | |
|
erase(%[1]) | %[1] | |
|
||||||
loc sli $1 == 1 && $2 == 4 | DATASCR4 |
|
loc sli $1 >= 1 && $1 <= 8 && $2 == 4 | DATASCR4 |
|
||||||
"add.l %[1],%[1]"
|
|
||||||
erase(%[1])
|
|
||||||
setcc(%[1]) | %[1] | |
|
|
||||||
loc sli $1 > 1 && $1 <= 8 && $2 == 4 | DATASCR4 |
|
|
||||||
"asl.l #$1,%[1]"
|
"asl.l #$1,%[1]"
|
||||||
erase(%[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 | |
|
lol loc sli stl $1 == $4 && $2 == 1 && $3 == 2 | |
|
||||||
remove(MEM_ALL)
|
remove(MEM_ALL)
|
||||||
"asl.w #1, $1(a6)" | | |
|
"asl.w #1, $1(a6)" | | |
|
||||||
@ -1035,78 +924,16 @@ adu | | | | adi $1 |
|
|||||||
sbu | | | | sbi $1 |
|
sbu | | | | sbi $1 |
|
||||||
slu | | | | sli $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 */
|
/* 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
|
adp $1 >= 1 && $1 <= 8 | ADDSCR | "add.l #$1,%[1]"
|
||||||
| 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]"
|
|
||||||
erase(%[1])
|
erase(%[1])
|
||||||
setcc(%[1]) | %[1] | |
|
setcc(%[1]) | %[1] | |
|
||||||
adp $1 >= 0-32767 && $1 <= 32767
|
adp | ADDSCR | "lea $1(%[1]),%[1]"
|
||||||
| 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]"
|
|
||||||
erase(%[1])
|
erase(%[1])
|
||||||
setcc(%[1]) | %[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 */
|
/* The next patterns are for efficient translation of "*p++" in C */
|
||||||
ldl ldl adp sdl $1 == $2 && $2 == $4 | |
|
ldl ldl adp sdl $1 == $2 && $2 == $4 | |
|
||||||
allocate(ADDREG={DISPL4,LB,$1})
|
allocate(ADDREG={DISPL4,LB,$1})
|
||||||
@ -1175,12 +1002,10 @@ inc | DATASCR | "add.w #1,%[1]"
|
|||||||
#ifdef REGVARS
|
#ifdef REGVARS
|
||||||
lil inc sil $1==$3 && inreg($1) == 2 | |
|
lil inc sil $1==$3 && inreg($1) == 2 | |
|
||||||
remove(MEM_ALL)
|
remove(MEM_ALL)
|
||||||
"add.w #1,(%(regvar($1)%))"
|
"add.w #1,(%(regvar($1)%))" | | |
|
||||||
setcc({IADDREG,regvar($1)}) | | |
|
|
||||||
lil dec sil $1==$3 && inreg($1) == 2 | |
|
lil dec sil $1==$3 && inreg($1) == 2 | |
|
||||||
remove(MEM_ALL)
|
remove(MEM_ALL)
|
||||||
"sub.w #1,(%(regvar($1)%))"
|
"sub.w #1,(%(regvar($1)%))" | | |
|
||||||
setcc({IADDREG,regvar($1)}) | | |
|
|
||||||
#endif
|
#endif
|
||||||
lil inc sil $1==$3 | | allocate(ADDREG={DISPL4,LB,$1})
|
lil inc sil $1==$3 | | allocate(ADDREG={DISPL4,LB,$1})
|
||||||
remove(MEM_ALL)
|
remove(MEM_ALL)
|
||||||
@ -1293,7 +1118,6 @@ zer $1 > 12 | | remove(ALL)
|
|||||||
"1:"
|
"1:"
|
||||||
"clr -(sp)"
|
"clr -(sp)"
|
||||||
"dbf %[a],1b" | | |
|
"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] | |
|
loc loc cui $1==4 && $2==2 | DATAREG4 | | %[1.1] | |
|
||||||
... | ANY | | | |
|
... | 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 */
|
/* G R O U P IX : L O G I C A L */
|
||||||
|
|
||||||
and defined($1) && $1 == 2 | ANY DATASCR |
|
and defined($1) && $1 == 2 | ANY DATASCR |
|
||||||
@ -1435,11 +1177,6 @@ and defined($1) && $1 == 2 | ANY DATASCR |
|
|||||||
"and %[2],%[1]"
|
"and %[2],%[1]"
|
||||||
setcc(%[1])
|
setcc(%[1])
|
||||||
erase(%[1]) | %[1] | | (2,2)+%[2]
|
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 | |
|
loc lol and stl $2 == $4 && $3 == 2 && inreg($2) < 2 | |
|
||||||
remove(MEM_ALL)
|
remove(MEM_ALL)
|
||||||
"and.w #$1,$2(a6)" | | | (6,10)
|
"and.w #$1,$2(a6)" | | | (6,10)
|
||||||
@ -1519,10 +1256,6 @@ ior defined($1) && $1 == 2 | ANY DATASCR |
|
|||||||
"or %[2],%[1]"
|
"or %[2],%[1]"
|
||||||
erase(%[1])
|
erase(%[1])
|
||||||
setcc(%[1]) | %[1] | | (2,2)+%[2]
|
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 | |
|
loc lol ior stl $2 == $4 && $3 == 2 && inreg($2) < 2 | |
|
||||||
remove(MEM_ALL)
|
remove(MEM_ALL)
|
||||||
"or.w #$1,$2(a6)" | | | (6,10)
|
"or.w #$1,$2(a6)" | | | (6,10)
|
||||||
@ -1599,10 +1332,6 @@ xor defined($1) && $1 == 2 | DATAREG DATASCR |
|
|||||||
"eor %[2],%[1]"
|
"eor %[2],%[1]"
|
||||||
erase(%[1])
|
erase(%[1])
|
||||||
setcc(%[1]) | %[1] | | (2,2)+%[2]
|
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 | |
|
lol loc xor stl $1 == $4 && $3 == 2 | |
|
||||||
remove(MEM_ALL)
|
remove(MEM_ALL)
|
||||||
"eor.w #$2,$1(a6)" | | | (6,10)
|
"eor.w #$2,$1(a6)" | | | (6,10)
|
||||||
@ -1854,15 +1583,6 @@ cms !defined($1) | ANY | remove(ALL)
|
|||||||
cmp | | remove(ALL)
|
cmp | | remove(ALL)
|
||||||
"jsr .cmp"
|
"jsr .cmp"
|
||||||
| D1 | |
|
| 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 |
|
cmi tlt and $1==2 && $3==2 | ANY DATAREG DATASCR |
|
||||||
"cmp %[1],%[2]"
|
"cmp %[1],%[2]"
|
||||||
@ -2245,22 +1965,22 @@ ldc cmi tgt loww(1)==0&&highw(1)==0 | DATA_ALT4 | allocate(DATAREG={IMMEDIATE,1}
|
|||||||
"clr %[a]"
|
"clr %[a]"
|
||||||
"1:"
|
"1:"
|
||||||
erase(%[a]) | %[a] | |
|
erase(%[a]) | %[a] | |
|
||||||
cmi zlt $1==4 | ANY4 REG4 STACK |
|
cmi zlt $1==4 | ANY4 DATAREG4 STACK |
|
||||||
"cmp.l %[1],%[2]"
|
"cmp.l %[1],%[2]"
|
||||||
"blt $2" | | |
|
"blt $2" | | |
|
||||||
cmi zle $1==4 | ANY4 REG4 STACK |
|
cmi zle $1==4 | ANY4 DATAREG4 STACK |
|
||||||
"cmp.l %[1],%[2]"
|
"cmp.l %[1],%[2]"
|
||||||
"ble $2" | | |
|
"ble $2" | | |
|
||||||
cmi zeq $1==4 | ANY4 REG4 STACK |
|
cmi zeq $1==4 | ANY4 DATAREG4 STACK |
|
||||||
"cmp.l %[1],%[2]"
|
"cmp.l %[1],%[2]"
|
||||||
"beq $2" | | |
|
"beq $2" | | |
|
||||||
cmi zne $1==4 | ANY4 REG4 STACK |
|
cmi zne $1==4 | ANY4 DATAREG4 STACK |
|
||||||
"cmp.l %[1],%[2]"
|
"cmp.l %[1],%[2]"
|
||||||
"bne $2" | | |
|
"bne $2" | | |
|
||||||
cmi zge $1==4 | ANY4 REG4 STACK |
|
cmi zge $1==4 | ANY4 DATAREG4 STACK |
|
||||||
"cmp.l %[1],%[2]"
|
"cmp.l %[1],%[2]"
|
||||||
"bge $2" | | |
|
"bge $2" | | |
|
||||||
cmi zgt $1==4 | ANY4 REG4 STACK |
|
cmi zgt $1==4 | ANY4 DATAREG4 STACK |
|
||||||
"cmp.l %[1],%[2]"
|
"cmp.l %[1],%[2]"
|
||||||
"bgt $2" | | |
|
"bgt $2" | | |
|
||||||
ldc cmi zlt loww(1)==0&&highw(1)==0 && $2==4 | DATA_ALT4 STACK |
|
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 */
|
/* G R O U P XIII : B R A N C H */
|
||||||
|
|
||||||
bra | STACK | "bra $1" | | |
|
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 | IMMEDIATE DATA_ALT STACK | "cmp %[1],%[2]"
|
||||||
"blt $1" | | |
|
"blt $1" | | |
|
||||||
... | ANY DATAREG STACK | "cmp %[1],%[2]"
|
... | ANY DATAREG STACK | "cmp %[1],%[2]"
|
||||||
@ -2758,12 +2463,8 @@ dus $1 == 2 | DATASCR | remove(ALL)
|
|||||||
exg | STACK | "move.w #$1,d0"
|
exg | STACK | "move.w #$1,d0"
|
||||||
"jsr .exg" | | |
|
"jsr .exg" | | |
|
||||||
fil | | "move.l #$1,.filn" | | |
|
fil | | "move.l #$1,.filn" | | |
|
||||||
gto | STACK | allocate(ADDREG)
|
gto | STACK | "pea $1"
|
||||||
"lea $1,%[a]"
|
"jmp .gto" | | |
|
||||||
"move.l 4(%[a]),sp"
|
|
||||||
"move.l 8(%[a]),a6"
|
|
||||||
"move.l (%[a]),%[a]"
|
|
||||||
"jmp (%[a])" | | |
|
|
||||||
lin | | "move.w #$1,.lino" | | |
|
lin | | "move.w #$1,.lino" | | |
|
||||||
lni | | "add.w #1,.lino" | | |
|
lni | | "add.w #1,.lino" | | |
|
||||||
mon | STACK | "jsr .mon" | | |
|
mon | STACK | "jsr .mon" | | |
|
||||||
@ -2772,7 +2473,7 @@ lim | | | {ABS4,".trpim"} | |
|
|||||||
lor $1 == 0 | | | LB | |
|
lor $1 == 0 | | | LB | |
|
||||||
lor $1 == 1 | STACK | "move.l sp,-(sp)" | | |
|
lor $1 == 1 | STACK | "move.l sp,-(sp)" | | |
|
||||||
lor $1 == 2 | | | {ABS4,".reghp"} | |
|
lor $1 == 2 | | | {ABS4,".reghp"} | |
|
||||||
lpb | | | | adp 8 |
|
lpb | STACK | "jsr .lpb" | A0 | |
|
||||||
rck $1 == 2 | | remove(ALL)
|
rck $1 == 2 | | remove(ALL)
|
||||||
"jsr .rck"
|
"jsr .rck"
|
||||||
| | |
|
| | |
|
||||||
@ -2788,6 +2489,27 @@ str $1 == 2 | | remove(ALL)
|
|||||||
trp | STACK | "jsr .trp" | | |
|
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 */
|
/* C O E R C I O N S */
|
||||||
|
|
||||||
|
|
||||||
@ -2858,7 +2580,6 @@ STACKS:
|
|||||||
(ANY, , "move.w %[1],-(sp)" setcc(%[1]), (2,4) + %[1])
|
(ANY, , "move.w %[1],-(sp)" setcc(%[1]), (2,4) + %[1])
|
||||||
(EXTERNAL_ADDR, , "pea %[1.off]" nocc)
|
(EXTERNAL_ADDR, , "pea %[1.off]" nocc)
|
||||||
(LOCAL_ADDR, , "pea %[1.off](a6)" 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)
|
(INDEX_ADDR, , "pea %[1.di](%[1.reg],%[1.ireg].w)" nocc)
|
||||||
(IMMEDIATE4 %[cc] == 0, , "clr.l -(sp)")
|
(IMMEDIATE4 %[cc] == 0, , "clr.l -(sp)")
|
||||||
(IMMEDIATE4, , "pea %[1.cc]" nocc)
|
(IMMEDIATE4, , "pea %[1.cc]" nocc)
|
||||||
|
|||||||
@ -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);
|
|
||||||
}
|
|
||||||
@ -2,6 +2,6 @@
|
|||||||
.extern _times
|
.extern _times
|
||||||
.text
|
.text
|
||||||
_times: move.w #0x2B,d0
|
_times: move.w #0x2B,d0
|
||||||
move.l 4(sp),a0
|
move.w 4(sp),a0
|
||||||
trap #0
|
trap #0
|
||||||
rts
|
rts
|
||||||
|
|||||||
@ -2,20 +2,15 @@ tail_mon.a
|
|||||||
exit.s
|
exit.s
|
||||||
_exit.s
|
_exit.s
|
||||||
access.s
|
access.s
|
||||||
acct.s
|
|
||||||
alarm.s
|
alarm.s
|
||||||
chdir.s
|
chdir.s
|
||||||
chmod.s
|
chmod.s
|
||||||
chown.s
|
|
||||||
chroot.s
|
chroot.s
|
||||||
close.s
|
close.s
|
||||||
creat.s
|
creat.s
|
||||||
dup.s
|
|
||||||
dup2.s
|
|
||||||
execl.s
|
execl.s
|
||||||
execve.s
|
execve.s
|
||||||
fork.s
|
fork.s
|
||||||
ftime.s
|
|
||||||
getegid.s
|
getegid.s
|
||||||
getgid.s
|
getgid.s
|
||||||
getpid.s
|
getpid.s
|
||||||
@ -25,16 +20,12 @@ gtty.s
|
|||||||
ioctl.s
|
ioctl.s
|
||||||
kill.s
|
kill.s
|
||||||
link.s
|
link.s
|
||||||
lock.s
|
|
||||||
lseek.s
|
lseek.s
|
||||||
mknod.s
|
mknod.s
|
||||||
mount.s
|
mount.s
|
||||||
nice.s
|
nice.s
|
||||||
open.s
|
open.s
|
||||||
pause.s
|
pause.s
|
||||||
pipe.s
|
|
||||||
profil.s
|
|
||||||
ptrace.s
|
|
||||||
read.s
|
read.s
|
||||||
setgid.s
|
setgid.s
|
||||||
setuid.s
|
setuid.s
|
||||||
@ -43,10 +34,8 @@ stime.s
|
|||||||
sync.s
|
sync.s
|
||||||
time.s
|
time.s
|
||||||
times.s
|
times.s
|
||||||
umask.s
|
|
||||||
umount.s
|
umount.s
|
||||||
unlink.s
|
unlink.s
|
||||||
utime.s
|
|
||||||
write.s
|
write.s
|
||||||
brk.s
|
brk.s
|
||||||
wait.s
|
wait.s
|
||||||
@ -54,4 +43,3 @@ fstat.s
|
|||||||
signal.s
|
signal.s
|
||||||
call.s
|
call.s
|
||||||
cleanup.s
|
cleanup.s
|
||||||
errno.s
|
|
||||||
|
|||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -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);
|
|
||||||
}
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -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; /* §[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"
|
|
||||||
@ -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"
|
|
||||||
|
|
||||||
%%
|
|
||||||
@ -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
|
|
||||||
};
|
|
||||||
@ -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 < §[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 < §[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 < §[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 = §[(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 < §[outhead.oh_nsect]; sp++) {
|
|
||||||
ip = sp->s_item;
|
|
||||||
newsymb(
|
|
||||||
ip->i_name,
|
|
||||||
(short)(ip->i_type | S_SCT),
|
|
||||||
(short)0,
|
|
||||||
load(ip)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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);
|
|
||||||
}
|
|
||||||
@ -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 = §[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 = §[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 = §[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);
|
|
||||||
}
|
|
||||||
@ -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");
|
|
||||||
}
|
|
||||||
@ -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"
|
|
||||||
@ -116,6 +116,10 @@ fixregvars(saveall) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
f_regsave();
|
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; {
|
isregvar(off) long off; {
|
||||||
|
|||||||
@ -20,7 +20,14 @@ typedef char * string;
|
|||||||
#define full int
|
#define full int
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if TEM_WSIZE>2
|
||||||
#define word long
|
#define word long
|
||||||
#ifndef WRD_FMT
|
#ifndef WRD_FMT
|
||||||
#define WRD_FMT "%ld"
|
#define WRD_FMT "%D"
|
||||||
#endif WRD_FMT
|
#endif WRD_FMT
|
||||||
|
#else
|
||||||
|
#define word int
|
||||||
|
#ifndef WRD_FMT
|
||||||
|
#define WRD_FMT "%d"
|
||||||
|
#endif WRD_FMT
|
||||||
|
#endif
|
||||||
|
|||||||
@ -392,14 +392,14 @@ if(Debug>1) fprintf(stderr,"Next tuple %d,%d,%d,%d\n",
|
|||||||
ntup = tup->p_next;
|
ntup = tup->p_next;
|
||||||
for (i=0,t=0;i<nregneeded && t<mincost; i++)
|
for (i=0,t=0;i<nregneeded && t<mincost; i++)
|
||||||
t += docoerc(regtp[i],regcp[i],ply,FALSE,tup->p_rar[i]);
|
t += docoerc(regtp[i],regcp[i],ply,FALSE,tup->p_rar[i]);
|
||||||
if ( t<mincost && tokpatlen<=stackheight ) {
|
if (t<mincost) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (Debug>2)
|
if (Debug>2)
|
||||||
fprintf(stderr,"Continuing match after coercions\n");
|
fprintf(stderr,"Continuing match after coercions\n");
|
||||||
#endif
|
#endif
|
||||||
t += codegen(codep,ply,FALSE,mincost-t,0);
|
t += codegen(codep,ply,FALSE,mincost-t,0);
|
||||||
}
|
}
|
||||||
if ( t<mincost && tokpatlen<=stackheight ) {
|
if (t<mincost) {
|
||||||
mincost = t;
|
mincost = t;
|
||||||
besttup = tup;
|
besttup = tup;
|
||||||
} else
|
} else
|
||||||
@ -480,7 +480,6 @@ normalfailed: if (stackpad!=tokpatlen) {
|
|||||||
result=compute(&enodes[nodeno]);
|
result=compute(&enodes[nodeno]);
|
||||||
if (result.e_typ!=EV_REG)
|
if (result.e_typ!=EV_REG)
|
||||||
break;
|
break;
|
||||||
if ( in_stack(result.e_v.e_reg) ) BROKE() ; /* Check aside-stack */
|
|
||||||
for (tp= &fakestack[stackheight-tokpatlen-1];tp>=&fakestack[0];tp--)
|
for (tp= &fakestack[stackheight-tokpatlen-1];tp>=&fakestack[0];tp--)
|
||||||
if (tp->t_token==-1) {
|
if (tp->t_token==-1) {
|
||||||
if(tp->t_att[0].ar==result.e_v.e_reg)
|
if(tp->t_att[0].ar==result.e_v.e_reg)
|
||||||
|
|||||||
@ -96,9 +96,7 @@ move(tp1,tp2,ply,toplevel,maxcost) token_p tp1,tp2; unsigned maxcost; {
|
|||||||
fakestack[stackheight] = *tp2;
|
fakestack[stackheight] = *tp2;
|
||||||
fakestack[stackheight+1] = *tp1;
|
fakestack[stackheight+1] = *tp1;
|
||||||
stackheight += 2;
|
stackheight += 2;
|
||||||
tokpatlen += 2;
|
|
||||||
t = codegen(&coderules[mp->m_cindex],ply,toplevel,maxcost,0);
|
t = codegen(&coderules[mp->m_cindex],ply,toplevel,maxcost,0);
|
||||||
tokpatlen -= 2;
|
|
||||||
stackheight -= 2;
|
stackheight -= 2;
|
||||||
return(t);
|
return(t);
|
||||||
}
|
}
|
||||||
@ -145,9 +143,7 @@ test(tp,ply,toplevel,maxcost) token_p tp; unsigned maxcost; {
|
|||||||
|
|
||||||
fakestack[stackheight] = *tp;
|
fakestack[stackheight] = *tp;
|
||||||
stackheight++;
|
stackheight++;
|
||||||
tokpatlen++;
|
|
||||||
t = codegen(&coderules[mp->t_cindex],ply,toplevel,maxcost,0);
|
t = codegen(&coderules[mp->t_cindex],ply,toplevel,maxcost,0);
|
||||||
tokpatlen--;
|
|
||||||
stackheight--;
|
stackheight--;
|
||||||
return(t);
|
return(t);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -392,66 +392,6 @@ tref(tp,amount) register token_p tp; {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define MAXSAVE 10
|
#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
|
#ifdef MAXSPLIT
|
||||||
split(tp,ip,ply,toplevel) token_p tp; register int *ip; {
|
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);
|
return(0);
|
||||||
found:
|
found:
|
||||||
assert(stackheight+cp->c2_nsplit-1<MAXFSTACK);
|
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;
|
tpl = tokpatlen;
|
||||||
tokpatlen = 1;
|
tokpatlen = 1;
|
||||||
codegen(&coderules[cp->c2_codep],ply,toplevel,MAXINT,0);
|
codegen(&coderules[cp->c2_codep],ply,toplevel,MAXINT,0);
|
||||||
tokpatlen = tpl;
|
tokpatlen = tpl;
|
||||||
rest_stack();
|
for (i=0;i<diff;i++) /* restore top of stack */
|
||||||
|
fakestack[stackheight++] = savestack[i];
|
||||||
return(cp->c2_nsplit);
|
return(cp->c2_nsplit);
|
||||||
}
|
}
|
||||||
#endif MAXSPLIT
|
#endif MAXSPLIT
|
||||||
|
|
||||||
unsigned docoerc(tp,cp,ply,toplevel,forced) token_p tp; register c3_p cp; {
|
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;
|
unsigned cost;
|
||||||
int tpl; /* saved tokpatlen */
|
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;
|
tpl = tokpatlen;
|
||||||
tokpatlen = 1;
|
tokpatlen = 1;
|
||||||
cost = codegen(&coderules[cp->c3_codep],ply,toplevel,MAXINT,forced);
|
cost = codegen(&coderules[cp->c3_codep],ply,toplevel,MAXINT,forced);
|
||||||
tokpatlen = tpl;
|
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;
|
nallreg = 0;
|
||||||
return(cost);
|
return(cost);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,4 +20,8 @@ typedef char * string;
|
|||||||
#define full int
|
#define full int
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if TEM_WSIZE>2
|
||||||
#define word long
|
#define word long
|
||||||
|
#else
|
||||||
|
#define word int
|
||||||
|
#endif
|
||||||
|
|||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
Makefile
|
|
||||||
em_pc.c
|
|
||||||
@ -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
|
|
||||||
310
util/amisc/anm.c
310
util/amisc/anm.c
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1835,7 +1835,7 @@ finishio() {
|
|||||||
if (bsize>=0)
|
if (bsize>=0)
|
||||||
fprintf(hfile,"#define TEM_BSIZE %d\n",bsize);
|
fprintf(hfile,"#define TEM_BSIZE %d\n",bsize);
|
||||||
else
|
else
|
||||||
yyerror("EM_BSIZE undefined");
|
fprintf(hfile,"extern int TEM_BSIZE;\n");
|
||||||
if (fmt!=0)
|
if (fmt!=0)
|
||||||
fprintf(hfile,"#define WRD_FMT \"%s\"\n",fmt);
|
fprintf(hfile,"#define WRD_FMT \"%s\"\n",fmt);
|
||||||
fprintf(hfile,"#define MAXALLREG %d\n",maxallreg);
|
fprintf(hfile,"#define MAXALLREG %d\n",maxallreg);
|
||||||
|
|||||||
@ -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
|
|
||||||
318
util/ego/bo/bo.c
318
util/ego/bo/bo.c
@ -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);
|
|
||||||
}
|
|
||||||
@ -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
|
|
||||||
271
util/ego/ca/ca.c
271
util/ego/ca/ca.c
@ -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);
|
|
||||||
}
|
|
||||||
@ -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[];
|
|
||||||
@ -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);
|
|
||||||
}
|
|
||||||
@ -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();
|
|
||||||
@ -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
|
|
||||||
520
util/ego/cf/cf.c
520
util/ego/cf/cf.c
@ -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);
|
|
||||||
}
|
|
||||||
@ -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)
|
|
||||||
@ -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 */
|
|
||||||
}
|
|
||||||
@ -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.
|
|
||||||
*/
|
|
||||||
@ -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;
|
|
||||||
}
|
|
||||||
@ -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.).
|
|
||||||
*/
|
|
||||||
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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.
|
|
||||||
*/
|
|
||||||
@ -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
|
|
||||||
355
util/ego/cj/cj.c
355
util/ego/cj/cj.c
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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
|
|
||||||
@ -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);
|
|
||||||
}
|
|
||||||
123
util/ego/cs/cs.h
123
util/ego/cs/cs.h
@ -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. */
|
|
||||||
@ -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));
|
|
||||||
}
|
|
||||||
@ -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.
|
|
||||||
*/
|
|
||||||
@ -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;
|
|
||||||
}
|
|
||||||
@ -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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
@ -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;
|
|
||||||
}
|
|
||||||
@ -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.
|
|
||||||
*/
|
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
extern eliminate(); /* (proc_p pp)
|
|
||||||
* Eliminate some of the recurrences of expressions
|
|
||||||
* that were found by the valuenumbering
|
|
||||||
* algorithm.
|
|
||||||
*/
|
|
||||||
@ -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
Loading…
x
Reference in New Issue
Block a user