Merge pull request #30 from camthesaxman/arm_support

Build ARM compiler
This commit is contained in:
huderlem 2020-02-15 09:06:38 -06:00 committed by GitHub
commit 74e171579e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
483 changed files with 585365 additions and 1 deletions

50
.gitignore vendored
View File

@ -1,3 +1,53 @@
*.exe
*.o
*.a
gcc_arm/Makefile
agbcc
agbcc_arm
old_agbcc
*/genattr
*/genattrtab
*/gencheck
*/gencodes
*/genconfig
*/genemit
*/genextract
*/genflags
*/gengenrtl
*/genopinit
*/genoutput
*/genpeep
*/genrecog
*/config.log
gcc_arm/auto-host.h
gcc_arm/config.cache
gcc_arm/config.log
gcc_arm/config.status
gcc_arm/genrtl.c
gcc_arm/genrtl.h
gcc_arm/insn-attr.h
gcc_arm/insn-attrtab.c
gcc_arm/insn-codes.h
gcc_arm/insn-config.h
gcc_arm/insn-emit.c
gcc_arm/insn-extract.c
gcc_arm/insn-flags.h
gcc_arm/insn-opinit.c
gcc_arm/insn-output.c
gcc_arm/insn-peep.c
gcc_arm/insn-recog.c
gcc_arm/s-attr
gcc_arm/s-attrtab
gcc_arm/s-check
gcc_arm/s-codes
gcc_arm/s-config
gcc_arm/s-emit
gcc_arm/s-extract
gcc_arm/s-flags
gcc_arm/s-genrtl
gcc_arm/s-opinit
gcc_arm/s-output
gcc_arm/s-peep
gcc_arm/s-recog
gcc_arm/tree-check.h

26
.travis.yml Normal file
View File

@ -0,0 +1,26 @@
language: generic
dist: bionic
sudo: false
env:
global:
- DEVKITPRO=$HOME
- DEVKITARM=$DEVKITPRO/devkitARM
addons:
apt:
packages:
- gcc-multilib
- linux-libc-dev
- zlib-dev
cache:
apt: true
install:
- pushd $HOME
- travis_retry wget https://github.com/devkitPro/buildscripts/releases/download/devkitARM_r50/devkitARM_r50-linux.tar.xz
- tar xJf devkitARM*.tar.xz
- popd
matrix:
include:
- os: linux
env: _="Build"
script:
- sh build.sh

View File

@ -2,6 +2,7 @@
set -e
CCOPT=
CXXOPT=
if [ ! -z "$CC" ]; then CCOPT=CC=$CC; fi
if [ ! -z "$CXX" ]; then CXXOPT=CXX=$CXX; fi
make -C gcc clean
@ -10,6 +11,10 @@ mv gcc/old_agbcc .
make -C gcc clean
make -C gcc $CCOPT $CXXOPT
mv gcc/agbcc .
# not sure if the ARM compiler is the old one or the new one (-DOLD_COMPILER)
rm -f gcc_arm/config.status gcc_arm/config.cache
cd gcc_arm && ./configure --target=arm-elf --host=i386-linux-gnu && make cc1 && cd ..
mv gcc_arm/cc1 agbcc_arm
make -C libgcc clean
make -C libgcc $CCOPT $CXXOPT
mv libgcc/libgcc.a .

87
config.if Executable file
View File

@ -0,0 +1,87 @@
#! /dev/null
# Don't call it directly. This shell script fragment is called to
# determine:
#
# 1. libstcxx_interface: the interface name for libstdc++.
# 2. cxx_interface: the interface name for c++.
# 3. libc_interface: the interface name for libc.
#
# Get the top level src dir.
if [ -z "${topsrcdir}" -a -z "${top_srcdir}" ]
then
echo "Undefined top level src dir: topsrcdir and top_srcdir are empty" >&2
exit 1
fi
if [ -n "${topsrcdir}" ]
then
if_topsrcdir=${topsrcdir}
else
if_topsrcdir=${top_srcdir}
fi
if [ -f ${if_topsrcdir}/libstdc++/Makefile.in ]; then
# We check libstdc++ for libstdcxx_interface.
libstdcxx_interface=`grep "^INTERFACE" ${if_topsrcdir}/libstdc++/Makefile.in | sed 's/INTERFACE[ ]*=[ ]*\(.*\)/\1/'`
else
libstdcxx_interface=
fi
if [ -f ${if_topsrcdir}/gcc/cp/Makefile.in ]; then
# We check gcc/cp for cxx_interface.
cxx_interface=`grep "^INTERFACE" ${if_topsrcdir}/gcc/cp/Makefile.in | sed 's/INTERFACE[ ]*=[ ]*\(.*\)/\1/'`
else
cxx_interface=
fi
# The trickiest part is libc_interface.
if [ -z "${libc_interface}" ]
then
case ${target_os} in
*linux*libc1*|*linux*libc5*)
case ${target_alias} in
*alpha*|*powerpc*)
libc_interface=-libc5.9-
;;
*)
libc_interface=-libc5-
;;
esac
;;
*linux*gnu*)
# We have to work harder to figure it out.
if [ ${target_alias} = ${build_alias} ]
then
dummy=if$$
cat >$dummy.c <<EOF
#include <features.h>
main(argc, argv)
int argc;
char *argv[];
{
printf("%d\n", __GLIBC_MINOR__);
return 0;
}
EOF
${CC-cc} $dummy.c -o $dummy 2>/dev/null
if [ "$?" = 0 ]
then
libc_interface=-libc6.`./$dummy`-
rm -f $dummy.c $dummy
else
# It should never happen.
echo "Cannot find the GNU C library minor version number." >&2
rm -f $dummy.c $dummy
exit 1
fi
else
# Cross compiling. Assume glibc 2.1.
libc_interface=-libc6.1-
fi
;;
*)
libc_interface=-
;;
esac
fi

1274
config.sub vendored Executable file

File diff suppressed because it is too large Load Diff

340
gcc_arm/COPYING Executable file
View File

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

482
gcc_arm/COPYING.LIB Executable file
View File

@ -0,0 +1,482 @@
GNU LIBRARY GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1991 Free Software Foundation, Inc.
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the library GPL. It is
numbered 2 because it goes with version 2 of the ordinary GPL.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Library General Public License, applies to some
specially designated Free Software Foundation software, and to any
other libraries whose authors decide to use it. You can use it for
your libraries, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if
you distribute copies of the library, or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link a program with the library, you must provide
complete object files to the recipients so that they can relink them
with the library, after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
Our method of protecting your rights has two steps: (1) copyright
the library, and (2) offer you this license which gives you legal
permission to copy, distribute and/or modify the library.
Also, for each distributor's protection, we want to make certain
that everyone understands that there is no warranty for this free
library. If the library is modified by someone else and passed on, we
want its recipients to know that what they have is not the original
version, so that any problems introduced by others will not reflect on
the original authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that companies distributing free
software will individually obtain patent licenses, thus in effect
transforming the program into proprietary software. To prevent this,
we have made it clear that any patent must be licensed for everyone's
free use or not licensed at all.
Most GNU software, including some libraries, is covered by the ordinary
GNU General Public License, which was designed for utility programs. This
license, the GNU Library General Public License, applies to certain
designated libraries. This license is quite different from the ordinary
one; be sure to read it in full, and don't assume that anything in it is
the same as in the ordinary license.
The reason we have a separate public license for some libraries is that
they blur the distinction we usually make between modifying or adding to a
program and simply using it. Linking a program with a library, without
changing the library, is in some sense simply using the library, and is
analogous to running a utility program or application program. However, in
a textual and legal sense, the linked executable is a combined work, a
derivative of the original library, and the ordinary General Public License
treats it as such.
Because of this blurred distinction, using the ordinary General
Public License for libraries did not effectively promote software
sharing, because most developers did not use the libraries. We
concluded that weaker conditions might promote sharing better.
However, unrestricted linking of non-free programs would deprive the
users of those programs of all benefit from the free status of the
libraries themselves. This Library General Public License is intended to
permit developers of non-free programs to use free libraries, while
preserving your freedom as a user of such programs to change the free
libraries that are incorporated in them. (We have not seen how to achieve
this as regards changes in header files, but we have achieved it as regards
changes in the actual functions of the Library.) The hope is that this
will lead to faster development of free libraries.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, while the latter only
works together with the library.
Note that it is possible for a library to be covered by the ordinary
General Public License rather than by this special one.
GNU LIBRARY GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library which
contains a notice placed by the copyright holder or other authorized
party saying it may be distributed under the terms of this Library
General Public License (also called "this License"). Each licensee is
addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also compile or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
c) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
d) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the source code distributed need not include anything that is normally
distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Library General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

10905
gcc_arm/ChangeLog Executable file

File diff suppressed because it is too large Load Diff

13017
gcc_arm/ChangeLog.0 Executable file

File diff suppressed because it is too large Load Diff

3393
gcc_arm/ChangeLog.Cygnus Executable file

File diff suppressed because it is too large Load Diff

3781
gcc_arm/ChangeLog.lib Executable file

File diff suppressed because it is too large Load Diff

1503
gcc_arm/FSFChangeLog Executable file

File diff suppressed because it is too large Load Diff

10110
gcc_arm/FSFChangeLog.10 Executable file

File diff suppressed because it is too large Load Diff

14493
gcc_arm/FSFChangeLog.11 Executable file

File diff suppressed because it is too large Load Diff

1244
gcc_arm/FSFChangeLog.12 Executable file

File diff suppressed because it is too large Load Diff

2188
gcc_arm/INSTALL Executable file

File diff suppressed because it is too large Load Diff

91
gcc_arm/LANGUAGES Executable file
View File

@ -0,0 +1,91 @@
Right now there is no documentation for the GCC tree -> rtl interfaces
(or more generally the interfaces for adding new languages).
Such documentation would be of great benefit to the project. Until such
time as we can formally start documenting the interface this file will
serve as a repository for information on these interface and any incompatable
changes we've made.
Aug 31, 1998:
The interface to HANDLE_PRAGMA has changed. It now takes three arguments.
The first two are pointers to functions that should be used to read characters
from the input stream, and to push them back into the input stream respectively.
The third argument is a pointer to a null terminate string which is the first
word after #pragma. The expression supplied by HANDLE_PRAGMA should return
non-zero if it parsed and implemented the pragma. Otherwise it should return
zero, and leave the input stream as it was before the expression was evaluated.
A new back-end definable macro has been added: INSERT_ATTRIBUTES. This macro
allows backend to add attributes to decls as they are created.
Jun 10, 1998:
The interface to lang_decode_option has changed. It now uses and argc/argv
interface to allow for options that use more than one input string. The new
declaration is: int lang_decode_option (int argc, char** argv). It now
returns the number of input strings processed, or 0 if the option is
unknown.
Jun 7, 1998:
Front-ends must now define lang_init_options. It is safe for this
function to do nothing. See c-lang.c.
Apr 21, 1998:
Front ends which link with c-common or other files from the C/C++
front-ends may need to handle TI types. Look for references to
[unsigned]int_DI_type_node in your front end. If you have references
to these variables, you'll need up update the front end.
To update the front end you must mirror all the code which currently
deals with intDI_type_node to also handle intTI_type_node.
Apr 7, 1998:
The interface between toplev.c and the language front ends for opening the
source file has changed:
o init_lex() has been renamed to init_parse (char *filename) where filename
is the name of the source file.
o The code in toplev.c which opened the source file should be moved to
the new init_parse function.
o toplev.c now calls finish_parse() instead of closing the source file
using fclose(). This should now be done in finish_parse, if necessary.
Apr 1, 1998:
Front-ends must now define lang_print_xnode. It is safe for this
function to do nothing. See c-lang.c.
Feb 1, 1998:
GCC used to store structure sizes & offsets to elements as bitsize
quantities. This causes problems because a structure can only be
(target memsize / 8) bytes long (this may effect arrays too). This
is particularly problematical on machines with small address spaces.
So:
All trees that represent sizes in bits should have a TREE_TYPE of
bitsizetype (rather than sizetype).
Accordingly, when such values are computed / initialized, care has to
be takes to use / compute the proper type.
When a size in bits is converted into a size in bytes, which is expressed
in trees, care should be taken to change the tree's type again to sizetype.
We've updated C, C++, Fortran & Objective-C to work with the new
scheme. Other languages will need to be updated accordingly.
Contact amylaar@cygnus.com for additional information.
?? 1997:
In an effort to decrease cache thrashing and useless loads we've changed the
third argument to the DEFTREECODE macro to be a single char. This will
effect languages that defined their own tree codes (usually in a .def file).
Old way:
DEFTREECODE (CLASS_METHOD_DECL, "class_method_decl", "d", 0)
New way:
DEFTREECODE (CLASS_METHOD_DECL, "class_method_decl", 'd', 0)

101
gcc_arm/LITERATURE Executable file
View File

@ -0,0 +1,101 @@
Collected papers/sites on standards, compilers, optimization, etc.
- Massively Scalar Compiler Project
ftp://cs.rice.edu/public/preston/optimizer
- Searchable article archive
http://hypatia.dcs.qmw.ac.uk/SEL-HPC/Articles/CompilersArchive.html
- David M Keaton's site
http://www.dmk.com, ftp://ftp.dmk.com
c9x stuff is in ftp://ftp.dmk.com/DMK/sc22wg14/c9x
- Some information about optimizing for x86 processors, links to
x86 manuals and documentation.
http://www.goof.com/pcg/docs.html
http://www.announce.com/agner/assem/
- AMD site with optimization guide for x86
http://www.amd.com/K6/k6docs/pdf/21828a.pdf
- Links related to many compiler topics
http://www.nullstone.com/htmls/connections.htm
- HPPA information:
http://www.hp.com/computing/framed/technology/micropro
- New compiler book. Online appendix includes some compiler links
http://www.mkp.com/books_catalog/1-55860-320-4.asp
- Various MIPS stuff:
http://www.sgi.com/MIPS/arch/mips4docs/mipsiv_3_2.pdf (*)
http://www.sgi.com/MIPS/arch/MIPS16/MIPS16.whitepaper.pdf
http://www.sgi.com/MIPS/arch/MIPS16/mips16.pdf
http://www.sgi.com/MIPS/arch/ISA5/isa5_tech_brf.pdf
http://www.sgi.com/MIPS/arch/ISA5/MDMXspec.pdf
http://www.sgi.com/MIPS/arch/ISA5/MIPSVspec.pdf
- IBM Journal of Research and Development
http://www.almaden.ibm.com/journal/
- System V PowerPC ABI
http://www.esofta.com/softspecs.html
- C9X draft
http://www.dkuug.dk/JTC1/SC22/WG14/www/docs/n794.htm
- DWARF v2 spec and sample implementation
ftp://sgigate.sgi.com/pub/dwarf/
- Various m68k info (including user guides in pdf format)
http://www.mot.com/SPS/HPESD/prod/0X0
- Modula 3 Stuff
http://www.cmass.com
http://www.cl.cam.ac.uk/m3doc/linux/cambridge.html
ftp://ftp.freebsd.org/pub/FreeBSD/distfiles/LOCAL_PORTS/m3-fbsd-m3cc-3.6.tar.gz
http://www.m3.org
- Comp.compilers archive
http://www.iecc.com/compilers
- Intel Pentium design info:
http://developer.intel.com/design/litcentr/index.htm
- comp.std.c++ FAQ:
http://reality.sgi.com/employees/austern_mti/std-c++/faq.html
- EG3 maintains a list of compiler Internet resources, including FAQ's,
papers, hot list pages, potential software/shareware, all known companies, etc.
http://www.eg3.com/ulc/compulc.htm
http://www.eg3.com/softd/compiler.htm
http://www.eg3.com/softdv/compiler.htm
These resource pages are published as part of EG3's
Free Electronic Engineers' Toolbox at:
http://www.eg3.com/ebox.htm

21
gcc_arm/Make-hooks Normal file
View File

@ -0,0 +1,21 @@
lang.all.build:
lang.all.cross:
lang.start.encap:
lang.rest.encap:
lang.info:
lang.dvi:
lang.install-normal:
lang.install-common:
lang.install-info:
lang.install-man:
lang.uninstall:
lang.distdir:
lang.mostlyclean:
lang.clean:
lang.distclean:
lang.extraclean:
lang.maintainer-clean:
lang.stage1:
lang.stage2:
lang.stage3:
lang.stage4:

0
gcc_arm/Make-host Normal file
View File

0
gcc_arm/Make-lang Normal file
View File

35
gcc_arm/Make-target Normal file
View File

@ -0,0 +1,35 @@
CROSS_LIBGCC1 = libgcc1-asm.a
LIB1ASMSRC = arm/lib1funcs.asm
# CYGNUS LOCAL interworking
LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _call_via_rX
# END CYGNUS LOCAL interworking
# These are really part of libgcc1, but this will cause them to be
# built correctly, so...
LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c
fp-bit.c: $(srcdir)/config/fp-bit.c
echo '#define FLOAT' > fp-bit.c
echo '#ifndef __ARMEB__' >> fp-bit.c
echo '#define FLOAT_BIT_ORDER_MISMATCH' >> fp-bit.c
echo '#endif' >> fp-bit.c
cat $(srcdir)/config/fp-bit.c >> fp-bit.c
dp-bit.c: $(srcdir)/config/fp-bit.c
echo '#ifndef __ARMEB__' > dp-bit.c
echo '#define FLOAT_BIT_ORDER_MISMATCH' >> dp-bit.c
echo '#define FLOAT_WORD_ORDER_MISMATCH' >> dp-bit.c
echo '#endif' >> dp-bit.c
cat $(srcdir)/config/fp-bit.c >> dp-bit.c
# CYGNUS LOCAL
MULTILIB_OPTIONS = mlittle-endian/mbig-endian mhard-float/msoft-float mapcs-32/mapcs-26 mno-thumb-interwork/mthumb-interwork fno-leading-underscore/fleading-underscore mcpu=arm7
MULTILIB_DIRNAMES = le be fpu soft 32bit 26bit normal interwork elf under nofmult
MULTILIB_EXCEPTIONS = *mapcs-26/*mthumb-interwork* *mthumb-interwork*/*mcpu=arm7*
MULTILIB_MATCHES = mbig-endian=mbe mlittle-endian=mle mcpu?arm7=mcpu?arm7d mcpu?arm7=mcpu?arm7di mcpu?arm7=mcpu?arm70 mcpu?arm7=mcpu?arm700 mcpu?arm7=mcpu?arm700i mcpu?arm7=mcpu?arm710 mcpu?arm7=mcpu?arm710c mcpu?arm7=mcpu?arm7100 mcpu?arm7=mcpu?arm7500 mcpu?arm7=mcpu?arm7500fe mcpu?arm7=mcpu?arm6 mcpu?arm7=mcpu?arm60 mcpu?arm7=mcpu?arm600 mcpu?arm7=mcpu?arm610 mcpu?arm7=mcpu?arm620
LIBGCC = stmp-multilib
INSTALL_LIBGCC = install-multilib
# END CYGNUS LOCAL
TARGET_LIBGCC2_CFLAGS = -Dinhibit_libc

2800
gcc_arm/Makefile.in Executable file

File diff suppressed because it is too large Load Diff

1078
gcc_arm/NEWS Executable file

File diff suppressed because it is too large Load Diff

117
gcc_arm/PROBLEMS Executable file
View File

@ -0,0 +1,117 @@
3. When find_reloads is used to count number of spills needed
it does not take into account the fact that a reload may
turn out to be a dummy.
I'm not sure this really happens any more. Doesn't it find
all the dummies on both passes?
10. movl a3@,a0
movl a3@(16),a1
clrb a0@(a1:l)
is generated and may be worse than
movl a3@,a0
addl a3@(16),a0
clrb a0@
If ordering of operands is improved, many more
such cases will be generated from typical array accesses.
38. Hack expand_mult so that if there is no same-modes multiply
it will use a widening multiply and then truncate rather than
calling the library.
39. Hack expanding of division to notice cases for
long -> short division.
40. Represent divide insns as (DIV:SI ...) followed by
a separate lowpart extract. Represent remainder insns as DIV:SI
followed by a separate highpart extract. Then cse can work on
the DIV:SI part. Problem is, this may not be desirable on machines
where computing the quotient alone does not necessarily give
a remainder--such as the 68020 for long operands.
52. Reloading can look at how reload_contents got set up.
If it was copied from a register, just reload from that register.
Otherwise, perhaps can change the previous insn to move the
data via the reload reg, thus avoiding one memory ref.
63. Potential problem in cc_status.value2, if it ever activates itself
after a two-address subtraction (which currently cannot happen).
It is supposed to compare the current value of the destination
but eliminating it would use the results of the subtraction, equivalent
to comparing the previous value of the destination.
65. Should loops that neither start nor end with a break
be rearranged to end with the last break?
69. Define the floating point converting arithmetic instructions
for the 68881.
74. Combine loop opt with cse opt in one pass. Do cse on each loop,
then loop opt on that loop, and go from innermost loops outward.
Make loop invariants available for cse at end of loop.
85. pea can force a value to be reloaded into an areg
which can make it worse than separate adding and pushing.
This can only happen for adding something within addql range
and it only loses if the qty becomes dead at that point
so it can be added to with no copying.
93. If a pseudo doesn't get a hard reg everywhere,
can it get one during a loop?
96. Can do SImode bitfield insns without reloading, but must
alter the operands in special ways.
99. final could check loop-entry branches to see if they
screw up deletion of a test instruction. If they do,
can put another test instruction before the branch and
make it conditional and redirect it.
106. Aliasing may be impossible if data types of refs differ
and data type of containing objects also differ.
(But check this wrt unions.)
108. Can speed up flow analysis by making a table saying which
register is set and which registers are used by each instruction that
only sets one register and only uses two. This way avoid the tree
walk for such instructions (most instructions).
109. It is desirable to avoid converting INDEX to SImode if a
narrower mode suffices, as HImode does on the 68000.
How can this be done?
110. Possible special combination pattern:
If the two operands to a comparison die there and both come from insns
that are identical except for replacing one operand with the other,
throw away those insns. Ok if insns being discarded are known 1 to 1.
An andl #1 after a seq is 1 to 1, but how should compiler know that?
112. Can convert float to unsigned int by subtracting a constant,
converting to signed int, and changing the sign bit.
117. Any number of slow zero-extensions in one loop, that have
their clr insns moved out of the loop, can share one register
if their original life spans are disjoint.
But it may be hard to be sure of this since
the life span data that regscan produces may be hard to interpret
validly or may be incorrect after cse.
118. In cse, when a bfext insn refers to a register, if the field
corresponds to a halfword or a byte and the register is equivalent
to a memory location, it would be possible to detect this and
replace it with a simple memory reference.
121. Insns that store two values cannot be moved out of loops.
The code in scan_loop doesn't even try to deal with them.
122. When insn-output.c turns a bit-test into a sign-test,
it should see whether the cc is already set up with that sign.
123. When a conditional expression is used as a function arg, it would
be faster (and in some cases shorter) to push each alternative rather
than compute in a register and push that. This would require
being able to specify "push this" as a target for expand_expr.
124. On the 386, bad code results from foo (bar ()) when bar
returns a double, because the pseudo used fails to get preferenced
into an fp reg because of the distinction between regs 8 and 9.

435
gcc_arm/PROJECTS Executable file
View File

@ -0,0 +1,435 @@
Haifa scheduler (haifa-sched.c, loop.[ch], unroll.[ch], genattrtab.c):
(contact law@cygnus.com before starting any serious haifa work)
* Fix all the formatting problems. Simple, mindless work.
* Fix/add comments throughout the code. Many of the comments are from
the old scheduler and are out of date and misleading. Many new hunks
of code don't have sufficient comments and documentation. Those which
do have comments need to be rewritten to use complete sentences and
proper formatting.
* Someone needs make one (or more) passes over the scheduler as a whole to
just clean it up. Try to move the machine dependent bits into the target
files where they belong, avoid re-creating functions where or near
equivalents already exist (ie is_conditional_branch and friends), etc., etc.
* Document the new scheduling options. Remove those options which are
not really useful (like reverse scheduling for example). In general
the haifa scheduler adds _way_ too many options. I'm definitely of the
opinion that gcc already has too many -foptions, and haifa doesn't help
that situation.
* Testing and benchmarking. We've converted a few ports to using the
Haifa scheduler (hppa, sparc, ppc, alpha). We need to continue testing
and benchmarking the new scheduler on additional targets.
We need to have some kind of docs for how to best describe a machine to
the haifa scheduler to get good performance. Some existing ports have
been tuned to deal with the old scheduler -- they may need to be tuned
to generate good schedules with haifa.
Improvements to global cse and partial redundancy elimination:
The current implementation of global cse uses partial redundancy elimination
as described in Chow's thesis.
Long term we want to use lazy code motion as the basis for partial redundancy
elimination. lcm will find as many (or more) redunancies *and* it will
place the remaining computations at computationally optimal placement points
within the function. This reduces the number of redundant operations performed
as well as reducing register lifetimes. My experiments have shown that the
cases were the current PRE code hurts performance are greatly helped by using
lazy code motion.
lcm also provides the underlying framework for several additional optimizations
such as shrink wrapping, spill code motion, dead store elimination, and generic
load/store motion (all the other examples are subcases of load/store motion).
It can probably also be used to improve the reg-stack pass of the compiler.
Contact law@cygnus.com if you're interested in working on lazy code motion.
-------------
The old PROJECTS file. Stuff I know has been done has been deleted.
Stuff in progress has a contact name associated with it.
has been
1. Better optimization.
* Constants in unused inline functions
It would be nice to delay output of string constants so that string
constants mentioned in unused inline functions are never generated.
Perhaps this would also take care of string constants in dead code.
The difficulty is in finding a clean way for the RTL which refers
to the constant (currently, only by an assembler symbol name)
to point to the constant and cause it to be output.
* Optimize a sequence of if statements whose conditions are exclusive.
It is possible to optimize
if (x == 1) ...;
if (x == 2) ...;
if (x == 3) ...;
into
if (x == 1) ...;
else if (x == 2) ...;
else if (x == 3) ...;
provided that x is not altered by the contents of the if statements.
It's not certain whether this is worth doing. Perhaps programmers
nearly always write the else's themselves, leaving few opportunities
to improve anything.
* Un-cse.
Perhaps we should have an un-cse step right after cse, which tries to
replace a reg with its value if the value can be substituted for the
reg everywhere, if that looks like an improvement. Which is if the
reg is used only a few times. Use rtx_cost to determine if the
change is really an improvement.
* Clean up how cse works.
The scheme is that each value has just one hash entry. The
first_same_value and next_same_value chains are no longer needed.
For arithmetic, each hash table elt has the following slots:
* Operation. This is an rtx code.
* Mode.
* Operands 0, 1 and 2. These point to other hash table elements.
So, if we want to enter (PLUS:SI (REG:SI 30) (CONST_INT 104)), we
first enter (CONST_INT 104) and find the entry that (REG:SI 30) now
points to. Then we put these elts into operands 0 and 1 of a new elt.
We put PLUS and SI into the new elt.
Registers and mem refs would never be entered into the table as such.
However, the values they contain would be entered. There would be a
table indexed by regno which points at the hash entry for the value in
that reg.
The hash entry index now plays the role of a qty number.
We still need qty_first_reg, reg_next_eqv, etc. to record which regs
share a particular qty.
When a reg is used whose contents are unknown, we need to create a
hash table entry whose contents say "unknown", as a place holder for
whatever the reg contains. If that reg is added to something, then
the hash entry for the sum will refer to the "unknown" entry. Use
UNKNOWN for the rtx code in this entry. This replaces make_new_qty.
For a constant, a unique hash entry would be made based on the
value of the constant.
What about MEM? Each time a memory address is referenced, we need a
qty (a hash table elt) to represent what is in it. (Just as for a
register.) If this isn't known, create one, just as for a reg whose
contents are unknown.
We need a way to find all mem refs that still contain a certain value.
Do this with a chain of hash elts (for memory addresses) that point to
locations that hold the value. The hash elt for the value itself should
point to the start of the chain. It would be good for the hash elt
for an address to point to the hash elt for the contents of that address
(but this ptr can be null if the contents have never been entered).
With this data structure, nothing need ever be invalidated except
the lists of which regs or mems hold a particular value. It is easy
to see if there is a reg or mem that is equiv to a particular value.
If the value is constant, it is always explicitly constant.
* Support more general tail-recursion among different functions.
This might be possible under certain circumstances, such as when
the argument lists of the functions have the same lengths.
Perhaps it could be done with a special declaration.
You would need to verify in the calling function that it does not
use the addresses of any local variables and does not use setjmp.
* Put short statics vars at low addresses and use short addressing mode?
Useful on the 68000/68020 and perhaps on the 32000 series,
provided one has a linker that works with the feature.
This is said to make a 15% speedup on the 68000.
* Keep global variables in registers.
Here is a scheme for doing this. A global variable, or a local variable
whose address is taken, can be kept in a register for an entire function
if it does not use non-constant memory addresses and (for globals only)
does not call other functions. If the entire function does not meet
this criterion, a loop may.
The VAR_DECL for such a variable would have to have two RTL expressions:
the true home in memory, and the pseudo-register used temporarily.
It is necessary to emit insns to copy the memory location into the
pseudo-register at the beginning of the function or loop, and perhaps
back out at the end. These insns should have REG_EQUIV notes so that,
if the pseudo-register does not get a hard register, it is spilled into
the memory location which exists in any case.
The easiest way to set up these insns is to modify the routine
put_var_into_stack so that it does not apply to the entire function
(sparing any loops which contain nothing dangerous) and to call it at
the end of the function regardless of where in the function the
address of a local variable is taken. It would be called
unconditionally at the end of the function for all relevant global
variables.
For debugger output, the thing to do is to invent a new binding level
around the appropriate loop and define the variable name as a register
variable with that scope.
* Live-range splitting.
Currently a variable is allocated a hard register either for the full
extent of its use or not at all. Sometimes it would be good to
allocate a variable a hard register for just part of a function; for
example, through a particular loop where the variable is mostly used,
or outside of a particular loop where the variable is not used. (The
latter is nice because it might let the variable be in a register most
of the time even though the loop needs all the registers.)
Contact meissner@cygnus.com before starting any work on live range
splitting.
* Detect dead stores into memory?
A store into memory is dead if it is followed by another store into
the same location; and, in between, there is no reference to anything
that might be that location (including no reference to a variable
address).
This can be modeled as a partial redundancy elimination/lazy code motion
problem. Contact law@cygnus.com before working on dead store elimination
optimizations.
* Loop optimization.
Strength reduction and iteration variable elimination could be
smarter. They should know how to decide which iteration variables are
not worth making explicit because they can be computed as part of an
address calculation. Based on this information, they should decide
when it is desirable to eliminate one iteration variable and create
another in its place.
It should be possible to compute what the value of an iteration
variable will be at the end of the loop, and eliminate the variable
within the loop by computing that value at the loop end.
When a loop has a simple increment that adds 1,
instead of jumping in after the increment,
decrement the loop count and jump to the increment.
This allows aob insns to be used.
* Using constraints on values.
Many operations could be simplified based on knowledge of the
minimum and maximum possible values of a register at any particular time.
These limits could come from the data types in the tree, via rtl generation,
or they can be deduced from operations that are performed. For example,
the result of an `and' operation one of whose operands is 7 must be in
the range 0 to 7. Compare instructions also tell something about the
possible values of the operand, in the code beyond the test.
Value constraints can be used to determine the results of a further
comparison. They can also indicate that certain `and' operations are
redundant. Constraints might permit a decrement and branch
instruction that checks zeroness to be used when the user has
specified to exit if negative.
* Change the type of a variable.
Sometimes a variable is declared as `int', it is assigned only once
from a value of type `char', and then it is used only by comparison
against constants. On many machines, better code would result if
the variable had type `char'. If the compiler could detect this
case, it could change the declaration of the variable and change
all the places that use it.
* Better handling for very sparse switches.
There may be cases where it would be better to compile a switch
statement to use a fixed hash table rather than the current
combination of jump tables and binary search.
* Order of subexpressions.
It might be possible to make better code by paying attention
to the order in which to generate code for subexpressions of an expression.
* More code motion.
Consider hoisting common code up past conditional branches or tablejumps.
Contact law@cygnus.com before working on code hoisting.
* Trace scheduling.
This technique is said to be able to figure out which way a jump
will usually go, and rearrange the code to make that path the
faster one.
* Distributive law.
The C expression *(X + 4 * (Y + C)) compiles better on certain
machines if rewritten as *(X + 4*C + 4*Y) because of known addressing
modes. It may be tricky to determine when, and for which machines, to
use each alternative.
Some work has been done on this, in combine.c.
* Can optimize by changing if (x) y; else z; into z; if (x) y;
if z and x do not interfere and z has no effects not undone by y.
This is desirable if z is faster than jumping.
* For a two-insn loop on the 68020, such as
foo: movb a2@+,a3@+
jne foo
it is better to insert dbeq d0,foo before the jne.
d0 can be a junk register. The challenge is to fit this into
a portable framework: when can you detect this situation and
still be able to allocate a junk register?
2. Simpler porting.
Right now, describing the target machine's instructions is done
cleanly, but describing its addressing mode is done with several
ad-hoc macro definitions. Porting would be much easier if there were
an RTL description for addressing modes like that for instructions.
Tools analogous to genflags and genrecog would generate macros from
this description.
There would be one pattern in the address-description file for each
kind of addressing, and this pattern would have:
* the RTL expression for the address
* C code to verify its validity (since that may depend on
the exact data).
* C code to print the address in assembler language.
* C code to convert the address into a valid one, if it is not valid.
(This would replace LEGITIMIZE_ADDRESS).
* Register constraints for all indeterminates that appear
in the RTL expression.
3. Other languages.
Front ends for Pascal, Fortran, Algol, Cobol, Modula-2 and Ada are
desirable.
Pascal, Modula-2 and Ada require the implementation of functions
within functions. Some of the mechanisms for this already exist.
4. More extensions.
* Generated unique labels. Have some way of generating distinct labels
for use in extended asm statements. I don't know what a good syntax would
be.
* A way of defining a structure containing a union, in which the choice of
union alternative is controlled by a previous structure component.
Here is a possible syntax for this.
struct foo {
enum { INT, DOUBLE } code;
auto union { case INT: int i; case DOUBLE: double d;} value : code;
};
* Allow constructor expressions as lvalues, like this:
(struct foo) {a, b, c} = foo();
This would call foo, which returns a structure, and then store the
several components of the structure into the variables a, b, and c.
5. Generalize the machine model.
* Some new compiler features may be needed to do a good job on machines
where static data needs to be addressed using base registers.
* Some machines have two stacks in different areas of memory, one used
for scalars and another for large objects. The compiler does not
now have a way to understand this.
6. Useful warnings.
* Warn about statements that are undefined because the order of
evaluation of increment operators makes a big difference. Here is an
example:
*foo++ = hack (*foo);
7. Better documentation of how GCC works and how to port it.
Here is an outline proposed by Allan Adler.
I. Overview of this document
II. The machines on which GCC is implemented
A. Prose description of those characteristics of target machines and
their operating systems which are pertinent to the implementation
of GCC.
i. target machine characteristics
ii. comparison of this system of machine characteristics with
other systems of machine specification currently in use
B. Tables of the characteristics of the target machines on which
GCC is implemented.
C. A priori restrictions on the values of characteristics of target
machines, with special reference to those parts of the source code
which entail those restrictions
i. restrictions on individual characteristics
ii. restrictions involving relations between various characteristics
D. The use of GCC as a cross-compiler
i. cross-compilation to existing machines
ii. cross-compilation to non-existent machines
E. Assumptions which are made regarding the target machine
i. assumptions regarding the architecture of the target machine
ii. assumptions regarding the operating system of the target machine
iii. assumptions regarding software resident on the target machine
iv. where in the source code these assumptions are in effect made
III. A systematic approach to writing the files tm.h and xm.h
A. Macros which require special care or skill
B. Examples, with special reference to the underlying reasoning
IV. A systematic approach to writing the machine description file md
A. Minimal viable sets of insn descriptions
B. Examples, with special reference to the underlying reasoning
V. Uses of the file aux-output.c
VI. Specification of what constitutes correct performance of an
implementation of GCC
A. The components of GCC
B. The itinerary of a C program through GCC
C. A system of benchmark programs
D. What your RTL and assembler should look like with these benchmarks
E. Fine tuning for speed and size of compiled code
VII. A systematic procedure for debugging an implementation of GCC
A. Use of GDB
i. the macros in the file .gdbinit for GCC
ii. obstacles to the use of GDB
a. functions implemented as macros can't be called in GDB
B. Debugging without GDB
i. How to turn off the normal operation of GCC and access specific
parts of GCC
C. Debugging tools
D. Debugging the parser
i. how machine macros and insn definitions affect the parser
E. Debugging the recognizer
i. how machine macros and insn definitions affect the recognizer
ditto for other components
VIII. Data types used by GCC, with special reference to restrictions not
specified in the formal definition of the data type
IX. References to the literature for the algorithms used in GCC

26
gcc_arm/README Executable file
View File

@ -0,0 +1,26 @@
This directory contains the egcs version 1.1 release of the GNU C
compiler. It includes all of the support for compiling C++ and
Objective C, including a run-time library for Objective C.
The GNU C compiler is free software. See the file COPYING for copying
permission.
See the file gcc.texi (together with other files that it includes) for
installation and porting information. The file INSTALL contains a
copy of the installation information, as plain ASCII.
Installing this package will create various files in subdirectories of
/usr/local/lib, which are passes used by the compiler and a library
named libgcc.a. It will also create /usr/local/bin/gcc, which is
the user-level command to do a compilation.
See the Bugs chapter of the GCC Manual for how to report bugs
usefully. An online readable version of the manual is in the files
gcc.info*.
The files pself.c and pself1.c are not part of GCC.
They are programs that print themselves on standard output.
They were written by Dario Dariol and Giovanni Cozzi, and are
included for your hacking pleasure. Likewise pself2.c
(Who is the author of that?) and pself3.c (by Vlad Taeerov and Rashit
Fakhreyev).

144
gcc_arm/README-bugs Executable file
View File

@ -0,0 +1,144 @@
The purpose of GCC pretesting is to verify that the new GCC
distribution, about to be released, works properly on your system *with
no change whatever*, when installed following the precise
recommendations that come with the distribution.
Here are some guidelines on how to do pretesting so as to make it
helpful. All of them follow from common sense together with the
nature of the purpose and the situation.
* It is absolutely vital that you mention even the smallest change or
departure from the standard sources and installation procedure.
Otherwise, you are not testing the same program that I wrote. Testing
a different program is usually of no use whatever. It can even cause
trouble if you fail to tell me that you tested some other program
instead of what I know as GCC. I might think that GCC works, when in
fact it has not been properly tried, and might have a glaring fault.
* Even changing the compilation options counts as a change in the
program. The GCC sources specify which compilation options to use.
Some of them are specified in makefiles, and some in machine-specific
configuration files.
You have ways to override this--but if you do, then you are not
testing what ordinary users will do. Therefore, when pretesting, it
is vital to test with the default compilation options.
(It is okay to test with nonstandard options as well as testing with
the standard ones.)
* The machine and system configuration files of GCC are parts of
GCC. So when you test GCC, you need to do it with the
configuration files that come with GCC.
If GCC does not come with configuration files for a certain machine,
and you test it with configuration files that don't come with GCC,
this is effectively changing GCC. Because the crucial fact about
the planned release is that, without changes, it doesn't work on that
machine.
To make GCC work on that machine, I would need to install new
configuration files. That is not out of the question, since it is
safe--it certainly won't break any other machines that already work.
But you will have to rush me the legal papers to give the FSF
permission to use a large piece of text.
* Look for recommendations for your system.
You can find these recommendations in the Installation node of the
manual, and in the file INSTALL. (These two files have the same text.)
These files say which configuration name to use for your machine, so
use the ones that are recommended. If you guess, you might guess
wrong and encounter spurious difficulties. What's more, if you don't
follow the recommendations then you aren't helping to test that its
recommendations are valid.
These files may describe other things that you need to do to make GCC
work on your machine. If so, you should follow these recommendations
also, for the same reason.
Also look at the Trouble chapter of the manual for items that
pertain to your machine.
* Don't delay sending information.
When you find a problem, please double check it if you can do so
quickly. But don't spend a long time double-checking. A good rule is
always to tell me about every problem on the same day you encounter
it, even if that means you can't find a solution before you report the
problem.
I'd much rather hear about a problem today and a solution tomorrow
than get both of them tomorrow at the same time.
* Make each bug report self-contained.
If you refer back to another message, whether from you or from someone
else, then it will be necessary for anyone who wants to investigate
the bug to find the other message. This may be difficult, it is
probably time-consuming.
To help me save time, simply copy the relevant parts of any previous
messages into your own bug report.
In particular, if I ask you for more information because a bug report
was incomplete, it is best to send me the *entire* collection of
relevant information, all together. If you send just the additional
information, that makes me do extra work. There is even a risk that
I won't remember what question you are sending me the answer to.
* Always be precise when talking about changes you have made. Show
things rather than describing them. Use exact filenames (relative to
the main directory of the distribution), not partial ones. For
example, say "I changed Makefile" rather than "I changed the
makefile". Instead of saying "I defined the MUMBLE macro", send a
diff that shows your change.
* Always use `diff -c' to make diffs. If you don't include context,
it may be hard for me to figure out where you propose to make the
changes. I might have to ignore your patch because I can't tell what
it means.
* When you write a fix, keep in mind that I can't install a change
that would break other systems.
People often suggest fixing a problem by changing machine-independent
files such as toplev.c to do something special that a particular
system needs. Sometimes it is totally obvious that such changes would
break GCC for almost all users. I can't possibly make a change like
that. All I can do is send it back to you and ask you to find a fix
that is safe to install.
Sometimes people send fixes that *might* be an improvement in
general--but it is hard to be sure of this. I can install such
changes some of the time, but not during pretest, when I am trying to
get a new version to work reliably as quickly as possible.
The safest changes for me to install are changes to the configuration
files for a particular machine. At least I know those can't create
bugs on other machines.
* Don't try changing GCC unless it fails to work if you don't change it.
* Don't even suggest changes that would only make GCC cleaner.
Every change I install could introduce a bug, so I won't install
a change unless I see it is necessary.
* If you would like to suggest changes for purposes other than fixing
serious bugs, don't wait till pretest time. Instead, send them just
after I make a release. That's the best time for me to install them.
* In some cases, if you don't follow these guidelines, your
information might still be useful, but I might have to do more work to
make use of it. Unfortunately, I am so far behind in my work that I
just can't get the job done unless you help me to do it efficiently.
Thank you
rms
Local Variables:
mode: text
End:

9
gcc_arm/README-fixinc Executable file
View File

@ -0,0 +1,9 @@
This README file is copied into the directory for GCC-only header files
when fixincludes is run by the makefile for GCC.
Many of the files in this directory were made from the standard system
header files of this system by the shell script `fixincludes'.
They are system-specific, and will not work on any other kind of system.
They are also not part of GCC. The reason for making the files here
is to fix the places in the header files which use constructs
that are incompatible with ANSI C.

39
gcc_arm/TESTS.FLUNK Executable file
View File

@ -0,0 +1,39 @@
This is a collection of things that test suites have
said were "wrong" with GCC--but that I don't agree with.
First, test suites sometimes test for compatibility with
traditional C. GCC with -traditional is not completely
compatible with traditional C, and in some ways I think it
should not be.
* K&R C allowed \x to appear in a string literal (or character
literal?) even in cases where it is *not* followed by a sequence of
hex digits. I'm not convinced this is desirable.
* K&R compilers allow comments to cross over an inclusion boundary (i.e.
started in an include file and ended in the including file).
I think this would be quite ugly and can't imagine it could
be needed.
Sometimes tests disagree with GCC's interpretation of the ANSI standard.
* One test claims that this function should return 1.
enum {A, B} foo;
func (enum {B, A} arg)
{
return B;
}
I think it should return 0, because the definition of B that
applies is the one in func.
* Some tests report failure when the compiler does not produce
an error message for a certain program.
ANSI C requires a "diagnostic" message for certain kinds of invalid
programs, but a warning counts as a diagnostic. If GCC produces
a warning but not an error, that is correct ANSI support.
When test suites call this "failure", the tests are broken.

96
gcc_arm/acconfig.h Executable file
View File

@ -0,0 +1,96 @@
/* Define if you can safely include both <string.h> and <strings.h>. */
#undef STRING_WITH_STRINGS
/* Define if printf supports "%p". */
#undef HAVE_PRINTF_PTR
/* Define if you want expensive run-time checks. */
#undef ENABLE_CHECKING
/* Define if your cpp understands the stringify operator. */
#undef HAVE_CPP_STRINGIFY
/* Define if your compiler understands volatile. */
#undef HAVE_VOLATILE
/* Define if your assembler supports specifying the maximum number
of bytes to skip when using the GAS .p2align command. */
#undef HAVE_GAS_MAX_SKIP_P2ALIGN
/* Define if your assembler supports .balign and .p2align. */
#undef HAVE_GAS_BALIGN_AND_P2ALIGN
/* Define if your assembler supports .subsection and .subsection -1 starts
emitting at the beginning of your section */
#undef HAVE_GAS_SUBSECTION_ORDERING
/* Define if you have a working <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Whether malloc must be declared even if <stdlib.h> is included. */
#undef NEED_DECLARATION_MALLOC
/* Whether realloc must be declared even if <stdlib.h> is included. */
#undef NEED_DECLARATION_REALLOC
/* Whether calloc must be declared even if <stdlib.h> is included. */
#undef NEED_DECLARATION_CALLOC
/* Whether free must be declared even if <stdlib.h> is included. */
#undef NEED_DECLARATION_FREE
/* Whether bcopy must be declared even if <string.h> is included. */
#undef NEED_DECLARATION_BCOPY
/* Whether bcmp must be declared even if <string.h> is included. */
#undef NEED_DECLARATION_BCMP
/* Whether bzero must be declared even if <string.h> is included. */
#undef NEED_DECLARATION_BZERO
/* Whether index must be declared even if <string.h> is included. */
#undef NEED_DECLARATION_INDEX
/* Whether rindex must be declared even if <string.h> is included. */
#undef NEED_DECLARATION_RINDEX
/* Whether getenv must be declared even if <stdlib.h> is included. */
#undef NEED_DECLARATION_GETENV
/* Whether atol must be declared even if <stdlib.h> is included. */
#undef NEED_DECLARATION_ATOL
/* Whether sbrk must be declared even if <stdlib.h> is included. */
#undef NEED_DECLARATION_SBRK
/* Whether abort must be declared even if <stdlib.h> is included. */
#undef NEED_DECLARATION_ABORT
/* Whether strerror must be declared even if <string.h> is included. */
#undef NEED_DECLARATION_STRERROR
/* Whether strsignal must be declared even if <string.h> is included. */
#undef NEED_DECLARATION_STRSIGNAL
/* Whether getcwd must be declared even if <unistd.h> is included. */
#undef NEED_DECLARATION_GETCWD
/* Whether getwd must be declared even if <unistd.h> is included. */
#undef NEED_DECLARATION_GETWD
/* Whether getrlimit must be declared even if <sys/resource.h> is included. */
#undef NEED_DECLARATION_GETRLIMIT
/* Whether setrlimit must be declared even if <sys/resource.h> is included. */
#undef NEED_DECLARATION_SETRLIMIT
/* Define if you want expensive run-time checks. */
#undef ENABLE_CHECKING
/* Define to enable the use of a default assembler. */
#undef DEFAULT_ASSEMBLER
/* Define to enable the use of a default linker. */
#undef DEFAULT_LINKER
@TOP@

237
gcc_arm/aclocal.m4 vendored Executable file
View File

@ -0,0 +1,237 @@
dnl See whether we can include both string.h and strings.h.
AC_DEFUN(GCC_HEADER_STRING,
[AC_CACHE_CHECK([whether string.h and strings.h may both be included],
gcc_cv_header_string,
[AC_TRY_COMPILE([#include <string.h>
#include <strings.h>], , gcc_cv_header_string=yes, gcc_cv_header_string=no)])
if test $gcc_cv_header_string = yes; then
AC_DEFINE(STRING_WITH_STRINGS)
fi
])
dnl See whether we need a declaration for a function.
dnl GCC_NEED_DECLARATION(FUNCTION [, EXTRA-HEADER-FILES])
AC_DEFUN(GCC_NEED_DECLARATION,
[AC_MSG_CHECKING([whether $1 must be declared])
AC_CACHE_VAL(gcc_cv_decl_needed_$1,
[AC_TRY_COMPILE([
#include <stdio.h>
#ifdef STRING_WITH_STRINGS
# include <string.h>
# include <strings.h>
#else
# ifdef HAVE_STRING_H
# include <string.h>
# else
# ifdef HAVE_STRINGS_H
# include <strings.h>
# endif
# endif
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifndef HAVE_RINDEX
#define rindex strrchr
#endif
#ifndef HAVE_INDEX
#define index strchr
#endif
$2],
[char *(*pfn) = (char *(*)) $1],
eval "gcc_cv_decl_needed_$1=no", eval "gcc_cv_decl_needed_$1=yes")])
if eval "test \"`echo '$gcc_cv_decl_needed_'$1`\" = yes"; then
AC_MSG_RESULT(yes)
gcc_tr_decl=NEED_DECLARATION_`echo $1 | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
AC_DEFINE_UNQUOTED($gcc_tr_decl)
else
AC_MSG_RESULT(no)
fi
])dnl
dnl Check multiple functions to see whether each needs a declaration.
dnl GCC_NEED_DECLARATIONS(FUNCTION... [, EXTRA-HEADER-FILES])
AC_DEFUN(GCC_NEED_DECLARATIONS,
[for ac_func in $1
do
GCC_NEED_DECLARATION($ac_func, $2)
done
])
dnl Check if we have vprintf and possibly _doprnt.
dnl Note autoconf checks for vprintf even though we care about vfprintf.
AC_DEFUN(GCC_FUNC_VFPRINTF_DOPRNT,
[AC_FUNC_VPRINTF
vfprintf=
doprint=
if test $ac_cv_func_vprintf != yes ; then
vfprintf=vfprintf.o
if test $ac_cv_func__doprnt != yes ; then
doprint=doprint.o
fi
fi
AC_SUBST(vfprintf)
AC_SUBST(doprint)
])
dnl See if the printf functions in libc support %p in format strings.
AC_DEFUN(GCC_FUNC_PRINTF_PTR,
[AC_CACHE_CHECK(whether the printf functions support %p,
gcc_cv_func_printf_ptr,
[AC_TRY_RUN([#include <stdio.h>
main()
{
char buf[64];
char *p = buf, *q = NULL;
sprintf(buf, "%p", p);
sscanf(buf, "%p", &q);
exit (p != q);
}], gcc_cv_func_printf_ptr=yes, gcc_cv_func_printf_ptr=no,
gcc_cv_func_printf_ptr=no)
rm -f core core.* *.core])
if test $gcc_cv_func_printf_ptr = yes ; then
AC_DEFINE(HAVE_PRINTF_PTR)
fi
])
dnl See if symbolic links work and if not, try to substitute either hard links or simple copy.
AC_DEFUN(GCC_PROG_LN_S,
[AC_MSG_CHECKING(whether ln -s works)
AC_CACHE_VAL(gcc_cv_prog_LN_S,
[rm -f conftestdata_t
echo >conftestdata_f
if ln -s conftestdata_f conftestdata_t 2>/dev/null
then
gcc_cv_prog_LN_S="ln -s"
else
if ln conftestdata_f conftestdata_t 2>/dev/null
then
gcc_cv_prog_LN_S=ln
else
gcc_cv_prog_LN_S=cp
fi
fi
rm -f conftestdata_f conftestdata_t
])dnl
LN_S="$gcc_cv_prog_LN_S"
if test "$gcc_cv_prog_LN_S" = "ln -s"; then
AC_MSG_RESULT(yes)
else
if test "$gcc_cv_prog_LN_S" = "ln"; then
AC_MSG_RESULT([no, using ln])
else
AC_MSG_RESULT([no, and neither does ln, so using cp])
fi
fi
AC_SUBST(LN_S)dnl
])
dnl See if hard links work and if not, try to substitute either symbolic links or simple copy.
AC_DEFUN(GCC_PROG_LN,
[AC_MSG_CHECKING(whether ln works)
AC_CACHE_VAL(gcc_cv_prog_LN,
[rm -f conftestdata_t
echo >conftestdata_f
if ln conftestdata_f conftestdata_t 2>/dev/null
then
gcc_cv_prog_LN="ln"
else
if ln -s conftestdata_f conftestdata_t 2>/dev/null
then
gcc_cv_prog_LN="ln -s"
else
gcc_cv_prog_LN=cp
fi
fi
rm -f conftestdata_f conftestdata_t
])dnl
LN="$gcc_cv_prog_LN"
if test "$gcc_cv_prog_LN" = "ln"; then
AC_MSG_RESULT(yes)
else
if test "$gcc_cv_prog_LN" = "ln -s"; then
AC_MSG_RESULT([no, using ln -s])
else
AC_MSG_RESULT([no, and neither does ln -s, so using cp])
fi
fi
AC_SUBST(LN)dnl
])
dnl See whether the stage1 host compiler accepts the volatile keyword.
AC_DEFUN(GCC_C_VOLATILE,
[AC_CACHE_CHECK([for volatile], gcc_cv_c_volatile,
[AC_TRY_COMPILE(, [volatile int foo;],
gcc_cv_c_volatile=yes, gcc_cv_c_volatile=no)])
if test $gcc_cv_c_volatile = yes ; then
AC_DEFINE(HAVE_VOLATILE)
fi
])
AC_DEFUN(EGCS_PROG_INSTALL,
[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
# Find a good install program. We prefer a C program (faster),
# so one script is as good as another. But avoid the broken or
# incompatible versions:
# SysV /etc/install, /usr/sbin/install
# SunOS /usr/etc/install
# IRIX /sbin/install
# AIX /bin/install
# AFS /usr/afsws/bin/install, which mishandles nonexistent args
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# ./install, which can be erroneously created by make from ./install.sh.
AC_MSG_CHECKING(for a BSD compatible install)
if test -z "$INSTALL"; then
AC_CACHE_VAL(ac_cv_path_install,
[ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS="${IFS}:"
for ac_dir in $PATH; do
# Account for people who put trailing slashes in PATH elements.
case "$ac_dir/" in
/|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
*)
# OSF1 and SCO ODT 3.0 have their own names for install.
for ac_prog in ginstall scoinst install; do
if test -f $ac_dir/$ac_prog; then
if test $ac_prog = install &&
grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
# AIX install. It has an incompatible calling convention.
# OSF/1 installbsd also uses dspmsg, but is usable.
:
else
ac_cv_path_install="$ac_dir/$ac_prog -c"
break 2
fi
fi
done
;;
esac
done
IFS="$ac_save_IFS"
])dnl
if test "${ac_cv_path_install+set}" = set; then
INSTALL="$ac_cv_path_install"
else
# As a last resort, use the slow shell script. We don't cache a
# path for INSTALL within a source directory, because that will
# break other packages using the cache if that directory is
# removed, or if the path is relative.
INSTALL="$ac_install_sh"
fi
fi
dnl We do special magic for INSTALL instead of AC_SUBST, to get
dnl relative paths right.
AC_MSG_RESULT($INSTALL)
AC_SUBST(INSTALL)dnl
# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
# It thinks the first close brace ends the variable substitution.
test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
AC_SUBST(INSTALL_PROGRAM)dnl
test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
AC_SUBST(INSTALL_DATA)dnl
])

1545
gcc_arm/alias.c Executable file

File diff suppressed because it is too large Load Diff

54
gcc_arm/assert.h Executable file
View File

@ -0,0 +1,54 @@
/* Allow this file to be included multiple times
with different settings of NDEBUG. */
#undef assert
#undef __assert
#ifdef NDEBUG
#define assert(ignore) ((void) 0)
#else
#ifndef __GNUC__
#define assert(expression) \
((void) ((expression) ? 0 : __assert (expression, __FILE__, __LINE__)))
#define __assert(expression, file, lineno) \
(printf ("%s:%u: failed assertion\n", file, lineno), \
abort (), 0)
#else
#if defined(__STDC__) || defined (__cplusplus)
/* Defined in libgcc.a */
#ifdef __cplusplus
extern "C" {
extern void __eprintf (const char *, const char *, unsigned, const char *)
__attribute__ ((noreturn));
}
#else
extern void __eprintf (const char *, const char *, unsigned, const char *)
__attribute__ ((noreturn));
#endif
#define assert(expression) \
((void) ((expression) ? 0 : __assert (#expression, __FILE__, __LINE__)))
#define __assert(expression, file, line) \
(__eprintf ("%s:%u: failed assertion `%s'\n", \
file, line, expression), 0)
#else /* no __STDC__ and not C++; i.e. -traditional. */
extern void __eprintf () __attribute__ ((noreturn)); /* Defined in libgcc.a */
#define assert(expression) \
((void) ((expression) ? 0 : __assert (expression, __FILE__, __LINE__)))
#define __assert(expression, file, lineno) \
(__eprintf ("%s:%u: failed assertion `%s'\n", \
file, lineno, "expression"), 0)
#endif /* no __STDC__ and not C++; i.e. -traditional. */
#endif /* no __GNU__; i.e., /bin/cc. */
#endif

215
gcc_arm/basic-block.h Executable file
View File

@ -0,0 +1,215 @@
/* Define control and data flow tables, and regsets.
Copyright (C) 1987, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "bitmap.h"
#include "sbitmap.h"
typedef bitmap regset; /* Head of register set linked list. */
/* Clear a register set by freeing up the linked list. */
#define CLEAR_REG_SET(HEAD) bitmap_clear (HEAD)
/* Copy a register set to another register set. */
#define COPY_REG_SET(TO, FROM) bitmap_copy (TO, FROM)
/* `and' a register set with a second register set. */
#define AND_REG_SET(TO, FROM) bitmap_operation (TO, TO, FROM, BITMAP_AND)
/* `and' the complement of a register set with a register set. */
#define AND_COMPL_REG_SET(TO, FROM) \
bitmap_operation (TO, TO, FROM, BITMAP_AND_COMPL)
/* Inclusive or a register set with a second register set. */
#define IOR_REG_SET(TO, FROM) bitmap_operation (TO, TO, FROM, BITMAP_IOR)
/* Or into TO the register set FROM1 `and'ed with the complement of FROM2. */
#define IOR_AND_COMPL_REG_SET(TO, FROM1, FROM2) \
bitmap_ior_and_compl (TO, FROM1, FROM2)
/* Clear a single register in a register set. */
#define CLEAR_REGNO_REG_SET(HEAD, REG) bitmap_clear_bit (HEAD, REG)
/* Set a single register in a register set. */
#define SET_REGNO_REG_SET(HEAD, REG) bitmap_set_bit (HEAD, REG)
/* Return true if a register is set in a register set. */
#define REGNO_REG_SET_P(TO, REG) bitmap_bit_p (TO, REG)
/* Copy the hard registers in a register set to the hard register set. */
#define REG_SET_TO_HARD_REG_SET(TO, FROM) \
do { \
int i_; \
CLEAR_HARD_REG_SET (TO); \
for (i_ = 0; i_ < FIRST_PSEUDO_REGISTER; i_++) \
if (REGNO_REG_SET_P (FROM, i_)) \
SET_HARD_REG_BIT (TO, i_); \
} while (0)
/* Loop over all registers in REGSET, starting with MIN, setting REGNUM to the
register number and executing CODE for all registers that are set. */
#define EXECUTE_IF_SET_IN_REG_SET(REGSET, MIN, REGNUM, CODE) \
EXECUTE_IF_SET_IN_BITMAP (REGSET, MIN, REGNUM, CODE)
/* Loop over all registers in REGSET1 and REGSET2, starting with MIN, setting
REGNUM to the register number and executing CODE for all registers that are
set in the first regset and not set in the second. */
#define EXECUTE_IF_AND_COMPL_IN_REG_SET(REGSET1, REGSET2, MIN, REGNUM, CODE) \
EXECUTE_IF_AND_COMPL_IN_BITMAP (REGSET1, REGSET2, MIN, REGNUM, CODE)
/* Loop over all registers in REGSET1 and REGSET2, starting with MIN, setting
REGNUM to the register number and executing CODE for all registers that are
set in both regsets. */
#define EXECUTE_IF_AND_IN_REG_SET(REGSET1, REGSET2, MIN, REGNUM, CODE) \
EXECUTE_IF_AND_IN_BITMAP (REGSET1, REGSET2, MIN, REGNUM, CODE)
/* Allocate a register set with oballoc. */
#define OBSTACK_ALLOC_REG_SET(OBSTACK) BITMAP_OBSTACK_ALLOC (OBSTACK)
/* Allocate a register set with alloca. */
#define ALLOCA_REG_SET() BITMAP_ALLOCA ()
/* Do any cleanup needed on a regset when it is no longer used. */
#define FREE_REG_SET(REGSET) BITMAP_FREE(REGSET)
/* Do any one-time initializations needed for regsets. */
#define INIT_ONCE_REG_SET() BITMAP_INIT_ONCE ()
/* Grow any tables needed when the number of registers is calculated
or extended. For the linked list allocation, nothing needs to
be done, other than zero the statistics on the first allocation. */
#define MAX_REGNO_REG_SET(NUM_REGS, NEW_P, RENUMBER_P)
/* Number of basic blocks in the current function. */
extern int n_basic_blocks;
/* Index by basic block number, get first insn in the block. */
extern rtx *x_basic_block_head;
/* Index by basic block number, get last insn in the block. */
extern rtx *x_basic_block_end;
/* Index by basic block number, determine whether the block can be reached
through a computed jump. */
extern char *basic_block_computed_jump_target;
/* Index by basic block number, get address of regset
describing the registers live at the start of that block. */
extern regset *basic_block_live_at_start;
/* What registers are live at the setjmp call. */
extern regset regs_live_at_setjmp;
/* Indexed by n, gives number of basic block that (REG n) is used in.
If the value is REG_BLOCK_GLOBAL (-2),
it means (REG n) is used in more than one basic block.
REG_BLOCK_UNKNOWN (-1) means it hasn't been seen yet so we don't know.
This information remains valid for the rest of the compilation
of the current function; it is used to control register allocation. */
#define REG_BLOCK_UNKNOWN -1
#define REG_BLOCK_GLOBAL -2
#define REG_BASIC_BLOCK(N) (VARRAY_REG (reg_n_info, N)->basic_block)
/* List of integers.
These are used for storing things like predecessors, etc.
This scheme isn't very space efficient, especially on 64 bit machines.
The interface is designed so that the implementation can be replaced with
something more efficient if desirable. */
typedef struct int_list {
struct int_list *next;
int val;
} int_list;
typedef int_list *int_list_ptr;
/* Integer list elements are allocated in blocks to reduce the frequency
of calls to malloc and to reduce the associated space overhead. */
typedef struct int_list_block {
struct int_list_block *next;
int nodes_left;
#define INT_LIST_NODES_IN_BLK 500
struct int_list nodes[INT_LIST_NODES_IN_BLK];
} int_list_block;
/* Given a pointer to the list, return pointer to first element. */
#define INT_LIST_FIRST(il) (il)
/* Given a pointer to a list element, return pointer to next element. */
#define INT_LIST_NEXT(p) ((p)->next)
/* Return non-zero if P points to the end of the list. */
#define INT_LIST_END(p) ((p) == NULL)
/* Return element pointed to by P. */
#define INT_LIST_VAL(p) ((p)->val)
#define INT_LIST_SET_VAL(p, new_val) ((p)->val = (new_val))
extern void free_int_list PROTO ((int_list_block **));
/* Stuff for recording basic block info. */
#define BLOCK_HEAD(B) x_basic_block_head[(B)]
#define BLOCK_END(B) x_basic_block_end[(B)]
/* Special block numbers [markers] for entry and exit. */
#define ENTRY_BLOCK (-1)
#define EXIT_BLOCK (-2)
/* from flow.c */
extern void free_regset_vector PROTO ((regset *, int nelts));
extern int *uid_block_number;
#define BLOCK_NUM(INSN) uid_block_number[INSN_UID (INSN)]
extern void dump_bb_data PROTO ((FILE *, int_list_ptr *, int_list_ptr *,
int));
extern void free_bb_mem PROTO ((void));
extern void free_basic_block_vars PROTO ((int));
/* CYGNUS LOCAL edge_splitting/law */
extern int compute_preds_succs PROTO ((int_list_ptr *, int_list_ptr *,
int *, int *, int));
/* END CYGNUS LOCAL */
extern void compute_dominators PROTO ((sbitmap *, sbitmap *,
int_list_ptr *, int_list_ptr *));
/* CYGNUS LOCAL lcm/law */
/* In lcm.c */
extern void pre_lcm PROTO ((int, int, int_list_ptr *,
int_list_ptr *,
sbitmap *, sbitmap *,
sbitmap *, sbitmap *));
extern void pre_rev_lcm PROTO ((int, int, int_list_ptr *,
int_list_ptr *,
sbitmap *, sbitmap *,
sbitmap *, sbitmap *));
/* END CYGNUS LOCAL */

642
gcc_arm/bitmap.c Executable file
View File

@ -0,0 +1,642 @@
/* Functions to support general ended bitmaps.
Copyright (C) 1997, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
#include "rtl.h"
#include "flags.h"
#include "obstack.h"
#include "regs.h"
#include "basic-block.h"
/* Obstack to allocate bitmap elements from. */
static struct obstack bitmap_obstack;
static int bitmap_obstack_init = FALSE;
#ifndef INLINE
#ifndef __GNUC__
#define INLINE
#else
#define INLINE __inline__
#endif
#endif
/* Global data */
bitmap_element bitmap_zero; /* An element of all zero bits. */
bitmap_element *bitmap_free; /* Freelist of bitmap elements. */
static void bitmap_element_free PROTO((bitmap, bitmap_element *));
static bitmap_element *bitmap_element_allocate PROTO((void));
static int bitmap_element_zerop PROTO((bitmap_element *));
static void bitmap_element_link PROTO((bitmap, bitmap_element *));
static bitmap_element *bitmap_find_bit PROTO((bitmap, unsigned int));
/* Free a bitmap element */
static INLINE void
bitmap_element_free (head, elt)
bitmap head;
bitmap_element *elt;
{
bitmap_element *next = elt->next;
bitmap_element *prev = elt->prev;
if (prev)
prev->next = next;
if (next)
next->prev = prev;
if (head->first == elt)
head->first = next;
/* Since the first thing we try is to insert before current,
make current the next entry in preference to the previous. */
if (head->current == elt)
head->current = next != 0 ? next : prev;
elt->next = bitmap_free;
bitmap_free = elt;
}
/* Allocate a bitmap element. The bits are cleared, but nothing else is. */
static INLINE bitmap_element *
bitmap_element_allocate ()
{
bitmap_element *element;
#if BITMAP_ELEMENT_WORDS != 2
int i;
#endif
if (bitmap_free != 0)
{
element = bitmap_free;
bitmap_free = element->next;
}
else
{
/* We can't use gcc_obstack_init to initialize the obstack since
print-rtl.c now calls bitmap functions, and bitmap is linked
into the gen* functions. */
if (!bitmap_obstack_init)
{
bitmap_obstack_init = TRUE;
/* Let particular systems override the size of a chunk. */
#ifndef OBSTACK_CHUNK_SIZE
#define OBSTACK_CHUNK_SIZE 0
#endif
/* Let them override the alloc and free routines too. */
#ifndef OBSTACK_CHUNK_ALLOC
#define OBSTACK_CHUNK_ALLOC xmalloc
#endif
#ifndef OBSTACK_CHUNK_FREE
#define OBSTACK_CHUNK_FREE free
#endif
#if !defined(__GNUC__) || (__GNUC__ < 2)
#define __alignof__(type) 0
#endif
obstack_specify_allocation (&bitmap_obstack, OBSTACK_CHUNK_SIZE,
__alignof__ (bitmap_element),
(void *(*) ()) OBSTACK_CHUNK_ALLOC,
(void (*) ()) OBSTACK_CHUNK_FREE);
}
element = (bitmap_element *) obstack_alloc (&bitmap_obstack,
sizeof (bitmap_element));
}
#if BITMAP_ELEMENT_WORDS == 2
element->bits[0] = element->bits[1] = 0;
#else
for (i = 0; i < BITMAP_ELEMENT_WORDS; i++)
element->bits[i] = 0;
#endif
return element;
}
/* Return nonzero if all bits in an element are zero. */
static INLINE int
bitmap_element_zerop (element)
bitmap_element *element;
{
#if BITMAP_ELEMENT_WORDS == 2
return (element->bits[0] | element->bits[1]) == 0;
#else
int i;
for (i = 0; i < BITMAP_ELEMENT_WORDS; i++)
if (element->bits[i] != 0)
return 0;
return 1;
#endif
}
/* Link the bitmap element into the current bitmap linked list. */
static INLINE void
bitmap_element_link (head, element)
bitmap head;
bitmap_element *element;
{
unsigned int indx = element->indx;
bitmap_element *ptr;
/* If this is the first and only element, set it in. */
if (head->first == 0)
{
element->next = element->prev = 0;
head->first = element;
}
/* If this index is less than that of the current element, it goes someplace
before the current element. */
else if (indx < head->indx)
{
for (ptr = head->current;
ptr->prev != 0 && ptr->prev->indx > indx;
ptr = ptr->prev)
;
if (ptr->prev)
ptr->prev->next = element;
else
head->first = element;
element->prev = ptr->prev;
element->next = ptr;
ptr->prev = element;
}
/* Otherwise, it must go someplace after the current element. */
else
{
for (ptr = head->current;
ptr->next != 0 && ptr->next->indx < indx;
ptr = ptr->next)
;
if (ptr->next)
ptr->next->prev = element;
element->next = ptr->next;
element->prev = ptr;
ptr->next = element;
}
/* Set up so this is the first element searched. */
head->current = element;
head->indx = indx;
}
/* Clear a bitmap by freeing the linked list. */
INLINE void
bitmap_clear (head)
bitmap head;
{
bitmap_element *element, *next;
for (element = head->first; element != 0; element = next)
{
next = element->next;
element->next = bitmap_free;
bitmap_free = element;
}
head->first = head->current = 0;
}
/* Copy a bitmap to another bitmap */
void
bitmap_copy (to, from)
bitmap to;
bitmap from;
{
bitmap_element *from_ptr, *to_ptr = 0;
#if BITMAP_ELEMENT_WORDS != 2
int i;
#endif
bitmap_clear (to);
/* Copy elements in forward direction one at a time */
for (from_ptr = from->first; from_ptr; from_ptr = from_ptr->next)
{
bitmap_element *to_elt = bitmap_element_allocate ();
to_elt->indx = from_ptr->indx;
#if BITMAP_ELEMENT_WORDS == 2
to_elt->bits[0] = from_ptr->bits[0];
to_elt->bits[1] = from_ptr->bits[1];
#else
for (i = 0; i < BITMAP_ELEMENT_WORDS; i++)
to_elt->bits[i] = from_ptr->bits[i];
#endif
/* Here we have a special case of bitmap_element_link, for the case
where we know the links are being entered in sequence. */
if (to_ptr == 0)
{
to->first = to->current = to_elt;
to->indx = from_ptr->indx;
to_elt->next = to_elt->prev = 0;
}
else
{
to_elt->prev = to_ptr;
to_elt->next = 0;
to_ptr->next = to_elt;
}
to_ptr = to_elt;
}
}
/* Find a bitmap element that would hold a bitmap's bit.
Update the `current' field even if we can't find an element that
would hold the bitmap's bit to make eventual allocation
faster. */
static INLINE bitmap_element *
bitmap_find_bit (head, bit)
bitmap head;
unsigned int bit;
{
bitmap_element *element;
unsigned HOST_WIDE_INT indx = bit / BITMAP_ELEMENT_ALL_BITS;
if (head->current == 0)
return 0;
if (head->indx > indx)
for (element = head->current;
element->prev != 0 && element->indx > indx;
element = element->prev)
;
else
for (element = head->current;
element->next != 0 && element->indx < indx;
element = element->next)
;
/* `element' is the nearest to the one we want. If it's not the one we
want, the one we want doesn't exist. */
head->current = element;
head->indx = element->indx;
if (element != 0 && element->indx != indx)
element = 0;
return element;
}
/* Clear a single bit in a bitmap. */
void
bitmap_clear_bit (head, bit)
bitmap head;
int bit;
{
bitmap_element *ptr = bitmap_find_bit (head, bit);
if (ptr != 0)
{
unsigned bit_num = bit % (unsigned) HOST_BITS_PER_WIDE_INT;
unsigned word_num = ((bit / (unsigned) HOST_BITS_PER_WIDE_INT)
% BITMAP_ELEMENT_WORDS);
ptr->bits[word_num] &= ~ (((unsigned HOST_WIDE_INT) 1) << bit_num);
/* If we cleared the entire word, free up the element */
if (bitmap_element_zerop (ptr))
bitmap_element_free (head, ptr);
}
}
/* Set a single bit in a bitmap. */
void
bitmap_set_bit (head, bit)
bitmap head;
int bit;
{
bitmap_element *ptr = bitmap_find_bit (head, bit);
unsigned word_num
= ((bit / (unsigned) HOST_BITS_PER_WIDE_INT) % BITMAP_ELEMENT_WORDS);
unsigned bit_num = bit % (unsigned) HOST_BITS_PER_WIDE_INT;
unsigned HOST_WIDE_INT bit_val = ((unsigned HOST_WIDE_INT) 1) << bit_num;
if (ptr == 0)
{
ptr = bitmap_element_allocate ();
ptr->indx = bit / BITMAP_ELEMENT_ALL_BITS;
ptr->bits[word_num] = bit_val;
bitmap_element_link (head, ptr);
}
else
ptr->bits[word_num] |= bit_val;
}
/* Return whether a bit is set within a bitmap. */
int
bitmap_bit_p (head, bit)
bitmap head;
int bit;
{
bitmap_element *ptr;
unsigned bit_num;
unsigned word_num;
ptr = bitmap_find_bit (head, bit);
if (ptr == 0)
return 0;
bit_num = bit % (unsigned) HOST_BITS_PER_WIDE_INT;
word_num
= ((bit / (unsigned) HOST_BITS_PER_WIDE_INT) % BITMAP_ELEMENT_WORDS);
return
(ptr->bits[word_num] & (((unsigned HOST_WIDE_INT) 1) << bit_num)) != 0;
}
/* Store in bitmap TO the result of combining bitmap FROM1 and
FROM2 using a specific bit manipulation. */
void
bitmap_operation (to, from1, from2, operation)
bitmap to;
bitmap from1;
bitmap from2;
enum bitmap_bits operation;
{
bitmap_element *delete_list = 0;
bitmap_element *from1_ptr = from1->first;
bitmap_element *from2_ptr = from2->first;
unsigned int indx1
= (from1_ptr) ? from1_ptr->indx : ~ (unsigned HOST_WIDE_INT) 0;
unsigned int indx2
= (from2_ptr) ? from2_ptr->indx : ~ (unsigned HOST_WIDE_INT) 0;
bitmap_element *to_ptr = 0;
bitmap_element *from1_tmp;
bitmap_element *from2_tmp;
unsigned int indx;
#if BITMAP_ELEMENT_WORDS != 2
int i;
#endif
/* To simplify things, always create a new list. If the old list was one
of the inputs, free it later. Otherwise, free it now. */
if (to == from1 || to == from2)
{
delete_list = to->first;
to->first = to->current = 0;
}
else
bitmap_clear (to);
while (from1_ptr != 0 || from2_ptr != 0)
{
/* Figure out whether we need to substitute zero elements for
missing links. */
if (indx1 == indx2)
{
indx = indx1;
from1_tmp = from1_ptr;
from2_tmp = from2_ptr;
from1_ptr = from1_ptr->next;
indx1 = (from1_ptr) ? from1_ptr->indx : ~ (unsigned HOST_WIDE_INT) 0;
from2_ptr = from2_ptr->next;
indx2 = (from2_ptr) ? from2_ptr->indx : ~ (unsigned HOST_WIDE_INT) 0;
}
else if (indx1 < indx2)
{
indx = indx1;
from1_tmp = from1_ptr;
from2_tmp = &bitmap_zero;
from1_ptr = from1_ptr->next;
indx1 = (from1_ptr) ? from1_ptr->indx : ~ (unsigned HOST_WIDE_INT) 0;
}
else
{
indx = indx2;
from1_tmp = &bitmap_zero;
from2_tmp = from2_ptr;
from2_ptr = from2_ptr->next;
indx2 = (from2_ptr) ? from2_ptr->indx : ~ (unsigned HOST_WIDE_INT) 0;
}
if (to_ptr == 0)
to_ptr = bitmap_element_allocate ();
/* Do the operation, and if any bits are set, link it into the
linked list. */
switch (operation)
{
default:
abort ();
case BITMAP_AND:
#if BITMAP_ELEMENT_WORDS == 2
to_ptr->bits[0] = from1_tmp->bits[0] & from2_tmp->bits[0];
to_ptr->bits[1] = from1_tmp->bits[1] & from2_tmp->bits[1];
#else
for (i = BITMAP_ELEMENT_WORDS - 1; i >= 0; i--)
to_ptr->bits[i] = from1_tmp->bits[i] & from2_tmp->bits[i];
#endif
break;
case BITMAP_AND_COMPL:
#if BITMAP_ELEMENT_WORDS == 2
to_ptr->bits[0] = from1_tmp->bits[0] & ~ from2_tmp->bits[0];
to_ptr->bits[1] = from1_tmp->bits[1] & ~ from2_tmp->bits[1];
#else
for (i = BITMAP_ELEMENT_WORDS - 1; i >= 0; i--)
to_ptr->bits[i] = from1_tmp->bits[i] & ~ from2_tmp->bits[i];
#endif
break;
case BITMAP_IOR:
#if BITMAP_ELEMENT_WORDS == 2
to_ptr->bits[0] = from1_tmp->bits[0] | from2_tmp->bits[0];
to_ptr->bits[1] = from1_tmp->bits[1] | from2_tmp->bits[1];
#else
for (i = BITMAP_ELEMENT_WORDS - 1; i >= 0; i--)
to_ptr->bits[i] = from1_tmp->bits[i] | from2_tmp->bits[i];
#endif
break;
}
if (! bitmap_element_zerop (to_ptr))
{
to_ptr->indx = indx;
bitmap_element_link (to, to_ptr);
to_ptr = 0;
}
}
/* If we have an unallocated element due to the last element being 0,
release it back to the free pool. Don't bother calling
bitmap_element_free since it was never linked into a bitmap. */
if (to_ptr != 0)
{
to_ptr->next = bitmap_free;
bitmap_free = to_ptr;
}
/* If the output bitmap was one of the inputs, free up its
elements now that we're done. */
for (; delete_list != 0; delete_list = to_ptr)
{
to_ptr = delete_list->next;
delete_list->next = bitmap_free;
bitmap_free = delete_list;
}
}
/* Or into bitmap TO bitmap FROM1 and'ed with the complement of
bitmap FROM2. */
void
bitmap_ior_and_compl (to, from1, from2)
bitmap to;
bitmap from1;
bitmap from2;
{
bitmap_head tmp;
tmp.first = tmp.current = 0;
bitmap_operation (&tmp, from1, from2, BITMAP_AND_COMPL);
bitmap_operation (to, to, &tmp, BITMAP_IOR);
bitmap_clear (&tmp);
}
/* Initialize a bitmap header. */
bitmap
bitmap_initialize (head)
bitmap head;
{
head->first = head->current = 0;
return head;
}
/* Debugging function to print out the contents of a bitmap. */
void
bitmap_debug_file (file, head)
FILE *file;
bitmap head;
{
bitmap_element *ptr;
fprintf (file, "\nfirst = ");
fprintf (file, HOST_PTR_PRINTF, head->first);
fprintf (file, " current = ");
fprintf (file, HOST_PTR_PRINTF, head->current);
fprintf (file, " indx = %u\n", head->indx);
for (ptr = head->first; ptr; ptr = ptr->next)
{
int i, j, col = 26;
fprintf (file, "\t");
fprintf (file, HOST_PTR_PRINTF, ptr);
fprintf (file, " next = ");
fprintf (file, HOST_PTR_PRINTF, ptr->next);
fprintf (file, " prev = ");
fprintf (file, HOST_PTR_PRINTF, ptr->prev);
fprintf (file, " indx = %u\n\t\tbits = {", ptr->indx);
for (i = 0; i < BITMAP_ELEMENT_WORDS; i++)
for (j = 0; j < HOST_BITS_PER_WIDE_INT; j++)
if ((ptr->bits[i] & (((unsigned HOST_WIDE_INT) 1) << j)) != 0)
{
if (col > 70)
{
fprintf (file, "\n\t\t\t");
col = 24;
}
fprintf (file, " %u", (ptr->indx * BITMAP_ELEMENT_ALL_BITS
+ i * HOST_BITS_PER_WIDE_INT + j));
col += 4;
}
fprintf (file, " }\n");
}
}
/* Function to be called from the debugger to print the contents
of a bitmap. */
void
debug_bitmap (head)
bitmap head;
{
bitmap_debug_file (stdout, head);
}
/* Function to print out the contents of a bitmap. Unlike bitmap_debug_file,
it does not print anything but the bits. */
void
bitmap_print (file, head, prefix, suffix)
FILE *file;
bitmap head;
char *prefix;
char *suffix;
{
char *comma = "";
int i;
fputs (prefix, file);
EXECUTE_IF_SET_IN_BITMAP (head, 0, i,
{
fprintf (file, "%s%d", comma, i);
comma = ", ";
});
fputs (suffix, file);
}
/* Release any memory allocated by bitmaps. */
void
bitmap_release_memory ()
{
bitmap_free = 0;
if (bitmap_obstack_init)
{
bitmap_obstack_init = FALSE;
obstack_free (&bitmap_obstack, NULL_PTR);
}
}

317
gcc_arm/bitmap.h Executable file
View File

@ -0,0 +1,317 @@
/* Functions to support general ended bitmaps.
Copyright (C) 1997, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* Number of words to use for each element in the linked list. */
#ifndef BITMAP_ELEMENT_WORDS
#define BITMAP_ELEMENT_WORDS 2
#endif
/* Number of bits in each actual element of a bitmap. We get slightly better
code for bit % BITMAP_ELEMENT_ALL_BITS and bit / BITMAP_ELEMENT_ALL_BITS if
bits is unsigned, assuming it is a power of 2. */
#define BITMAP_ELEMENT_ALL_BITS \
((unsigned) (BITMAP_ELEMENT_WORDS * HOST_BITS_PER_WIDE_INT))
/* Bitmap set element. We use a linked list to hold only the bits that
are set. This allows for use to grow the bitset dynamically without
having to realloc and copy a giant bit array. The `prev' field is
undefined for an element on the free list. */
typedef struct bitmap_element_def
{
struct bitmap_element_def *next; /* Next element. */
struct bitmap_element_def *prev; /* Previous element. */
unsigned int indx; /* regno/BITMAP_ELEMENT_ALL_BITS. */
unsigned HOST_WIDE_INT bits[BITMAP_ELEMENT_WORDS]; /* Bits that are set. */
} bitmap_element;
/* Head of bitmap linked list. */
typedef struct bitmap_head_def {
bitmap_element *first; /* First element in linked list. */
bitmap_element *current; /* Last element looked at. */
int indx; /* Index of last element looked at. */
} bitmap_head, *bitmap;
/* Enumeration giving the various operations we support. */
enum bitmap_bits {
BITMAP_AND, /* TO = FROM1 & FROM2 */
BITMAP_AND_COMPL, /* TO = FROM1 & ~ FROM2 */
BITMAP_IOR /* TO = FROM1 | FROM2 */
};
/* Global data */
extern bitmap_element *bitmap_free; /* Freelist of bitmap elements */
extern bitmap_element bitmap_zero; /* Zero bitmap element */
/* Clear a bitmap by freeing up the linked list. */
extern void bitmap_clear PROTO((bitmap));
/* Copy a bitmap to another bitmap. */
extern void bitmap_copy PROTO((bitmap, bitmap));
/* Perform an operation on two bitmaps, yielding a third. */
extern void bitmap_operation PROTO((bitmap, bitmap, bitmap, enum bitmap_bits));
/* `or' into one bitmap the `and' of a second bitmap witih the complement
of a third. */
extern void bitmap_ior_and_compl PROTO((bitmap, bitmap, bitmap));
/* Clear a single register in a register set. */
extern void bitmap_clear_bit PROTO((bitmap, int));
/* Set a single register in a register set. */
extern void bitmap_set_bit PROTO((bitmap, int));
/* Return true if a register is set in a register set. */
extern int bitmap_bit_p PROTO((bitmap, int));
/* Debug functions to print a bitmap linked list. */
extern void bitmap_debug PROTO((bitmap));
extern void bitmap_debug_file PROTO((FILE *, bitmap));
/* Print a bitmap */
extern void bitmap_print PROTO((FILE *, bitmap, char *, char *));
/* Initialize a bitmap header. */
extern bitmap bitmap_initialize PROTO((bitmap));
/* Release all memory held by bitmaps. */
extern void bitmap_release_memory PROTO((void));
extern void debug_bitmap PROTO((bitmap));
/* Allocate a bitmap with oballoc. */
#define BITMAP_OBSTACK_ALLOC(OBSTACK) \
bitmap_initialize ((bitmap) obstack_alloc (OBSTACK, sizeof (bitmap_head)))
/* Allocate a bitmap with alloca. */
#define BITMAP_ALLOCA() \
bitmap_initialize ((bitmap) alloca (sizeof (bitmap_head)))
/* Do any cleanup needed on a bitmap when it is no longer used. */
#define BITMAP_FREE(BITMAP) \
do { \
if (BITMAP) \
{ \
bitmap_clear (BITMAP); \
(BITMAP) = 0; \
} \
} while (0)
/* Do any one-time initializations needed for bitmaps. */
#define BITMAP_INIT_ONCE()
/* Loop over all bits in BITMAP, starting with MIN, setting BITNUM to the
bit number and executing CODE for all bits that are set. */
#define EXECUTE_IF_SET_IN_BITMAP(BITMAP, MIN, BITNUM, CODE) \
do { \
bitmap_element *ptr_ = (BITMAP)->first; \
unsigned int indx_ = (MIN) / BITMAP_ELEMENT_ALL_BITS; \
unsigned bit_num_ = (MIN) % ((unsigned) HOST_BITS_PER_WIDE_INT); \
unsigned word_num_ = (((MIN) / ((unsigned) HOST_BITS_PER_WIDE_INT)) \
% BITMAP_ELEMENT_WORDS); \
\
\
/* Find the block the minimum bit is in. */ \
while (ptr_ != 0 && ptr_->indx < indx_) \
ptr_ = ptr_->next; \
\
if (ptr_ != 0 && ptr_->indx != indx_) \
{ \
bit_num_ = 0; \
word_num_ = 0; \
} \
\
for (; ptr_ != 0; ptr_ = ptr_->next) \
{ \
for (; word_num_ < BITMAP_ELEMENT_WORDS; word_num_++) \
{ \
unsigned HOST_WIDE_INT word_ = ptr_->bits[word_num_]; \
\
if (word_ != 0) \
{ \
for (; bit_num_ < HOST_BITS_PER_WIDE_INT; bit_num_++) \
{ \
unsigned HOST_WIDE_INT mask_ \
= ((unsigned HOST_WIDE_INT) 1) << bit_num_; \
\
if ((word_ & mask_) != 0) \
{ \
word_ &= ~ mask_; \
(BITNUM) = (ptr_->indx * BITMAP_ELEMENT_ALL_BITS \
+ word_num_ * HOST_BITS_PER_WIDE_INT \
+ bit_num_); \
CODE; \
\
if (word_ == 0) \
break; \
} \
} \
} \
\
bit_num_ = 0; \
} \
\
word_num_ = 0; \
} \
} while (0)
/* Loop over all bits in BITMAP1 and BITMAP2, starting with MIN, setting
BITNUM to the bit number and executing CODE for all bits that are set in
the first bitmap and not set in the second. */
#define EXECUTE_IF_AND_COMPL_IN_BITMAP(BITMAP1, BITMAP2, MIN, BITNUM, CODE) \
do { \
bitmap_element *ptr1_ = (BITMAP1)->first; \
bitmap_element *ptr2_ = (BITMAP2)->first; \
unsigned int indx_ = (MIN) / BITMAP_ELEMENT_ALL_BITS; \
unsigned bit_num_ = (MIN) % ((unsigned) HOST_BITS_PER_WIDE_INT); \
unsigned word_num_ = (((MIN) / ((unsigned) HOST_BITS_PER_WIDE_INT)) \
% BITMAP_ELEMENT_WORDS); \
\
/* Find the block the minimum bit is in in the first bitmap. */ \
while (ptr1_ != 0 && ptr1_->indx < indx_) \
ptr1_ = ptr1_->next; \
\
if (ptr1_ != 0 && ptr1_->indx != indx_) \
{ \
bit_num_ = 0; \
word_num_ = 0; \
} \
\
for (; ptr1_ != 0 ; ptr1_ = ptr1_->next) \
{ \
/* Advance BITMAP2 to the equivalent link, using an all \
zero element if an equivalent link doesn't exist. */ \
bitmap_element *tmp2_; \
\
while (ptr2_ != 0 && ptr2_->indx < ptr1_->indx) \
ptr2_ = ptr2_->next; \
\
tmp2_ = ((ptr2_ != 0 && ptr2_->indx == ptr1_->indx) \
? ptr2_ : &bitmap_zero); \
\
for (; word_num_ < BITMAP_ELEMENT_WORDS; word_num_++) \
{ \
unsigned HOST_WIDE_INT word_ = (ptr1_->bits[word_num_] \
& ~ tmp2_->bits[word_num_]); \
if (word_ != 0) \
{ \
for (; bit_num_ < HOST_BITS_PER_WIDE_INT; bit_num_++) \
{ \
unsigned HOST_WIDE_INT mask_ \
= ((unsigned HOST_WIDE_INT)1) << bit_num_; \
\
if ((word_ & mask_) != 0) \
{ \
word_ &= ~ mask_; \
(BITNUM) = (ptr1_->indx * BITMAP_ELEMENT_ALL_BITS \
+ word_num_ * HOST_BITS_PER_WIDE_INT \
+ bit_num_); \
\
CODE; \
if (word_ == 0) \
break; \
} \
} \
} \
\
bit_num_ = 0; \
} \
\
word_num_ = 0; \
} \
} while (0)
/* Loop over all bits in BITMAP1 and BITMAP2, starting with MIN, setting
BITNUM to the bit number and executing CODE for all bits that are set in
the both bitmaps. */
#define EXECUTE_IF_AND_IN_BITMAP(BITMAP1, BITMAP2, MIN, BITNUM, CODE) \
do { \
bitmap_element *ptr1_ = (BITMAP1)->first; \
bitmap_element *ptr2_ = (BITMAP2)->first; \
unsigned int indx_ = (MIN) / BITMAP_ELEMENT_ALL_BITS; \
unsigned bit_num_ = (MIN) % ((unsigned) HOST_BITS_PER_WIDE_INT); \
unsigned word_num_ = (((MIN) / ((unsigned) HOST_BITS_PER_WIDE_INT)) \
% BITMAP_ELEMENT_WORDS); \
\
/* Find the block the minimum bit is in in the first bitmap. */ \
while (ptr1_ != 0 && ptr1_->indx < indx_) \
ptr1_ = ptr1_->next; \
\
if (ptr1_ != 0 && ptr1_->indx != indx_) \
{ \
bit_num_ = 0; \
word_num_ = 0; \
} \
\
for (; ptr1_ != 0 ; ptr1_ = ptr1_->next) \
{ \
/* Advance BITMAP2 to the equivalent link */ \
while (ptr2_ != 0 && ptr2_->indx < ptr1_->indx) \
ptr2_ = ptr2_->next; \
\
if (ptr2_ == 0) \
{ \
/* If there are no more elements in BITMAP2, exit loop now.*/ \
ptr1_ = (bitmap_element *)0; \
break; \
} \
else if (ptr2_->indx > ptr1_->indx) \
{ \
bit_num_ = word_num_ = 0; \
continue; \
} \
\
for (; word_num_ < BITMAP_ELEMENT_WORDS; word_num_++) \
{ \
unsigned HOST_WIDE_INT word_ = (ptr1_->bits[word_num_] \
& ptr2_->bits[word_num_]); \
if (word_ != 0) \
{ \
for (; bit_num_ < HOST_BITS_PER_WIDE_INT; bit_num_++) \
{ \
unsigned HOST_WIDE_INT mask_ \
= ((unsigned HOST_WIDE_INT)1) << bit_num_; \
\
if ((word_ & mask_) != 0) \
{ \
word_ &= ~ mask_; \
(BITNUM) = (ptr1_->indx * BITMAP_ELEMENT_ALL_BITS \
+ word_num_ * HOST_BITS_PER_WIDE_INT \
+ bit_num_); \
\
CODE; \
if (word_ == 0) \
break; \
} \
} \
} \
\
bit_num_ = 0; \
} \
\
word_num_ = 0; \
} \
} while (0)

35
gcc_arm/build-make Executable file
View File

@ -0,0 +1,35 @@
# We have to use the cross-compiler we just built to compile it.
CC = gcc -b $(host)
# Need those to compile binaries running on host machine.
# It is configured by
#
# configure --host=target_cpu-target_os \
# --target=host=target_cpu-target_os --build=host_cpu-host_os
#
# That HOST stuff has to be taken care of very carefully.
HOST_PREFIX=l-
HOST_PREFIX_1=$(HOST_PREFIX)
HOST_CC=$(CC) -b $(build)
HOST_CFLAGS=$(INTERNAL_CFLAGS) $(T_CFLAGS) $(CFLAGS) $(XCFLAGS)
HOST_CLIB=
HOST_LDFLAGS=$(LDFLAGS)
HOST_CPPFLAGS=$(ALL_CPPFLAGS)
HOST_ALLOCA=$(ALLOCA)
HOST_MALLOC=$(MALLOC)
HOST_OBSTACK=$(OBSTACK)
# To build the native compiler with the cross compiler, the headers
# for the target are already fixed. And /usr/include is for host, not
# target.
FIXINCLUDES=Makefile.in
# Don't run fixproto either
STMP_FIXPROTO =
# Cause installation using install-build. We do nothing here.
#INSTALL_TARGET = install-build
# Don't try to compile the things we can't compile or we have made
# while making gcc with the cross-compiler.
#ALL = all.build

322
gcc_arm/bytecode.def Executable file
View File

@ -0,0 +1,322 @@
# -*- C -*-
# bytecode.def - definitions of bytecodes for the stack machine.
# The production of the bytecode interpreter and compiler is
# heavily automated by using this file creatively.
# Various elementary data types are understood by the bytecode interpreter.
# Q[IU] - quarter word (byte) signed and unsigned integers (char).
# H[IU] - half word signed and unsigned integers (short int, maybe int).
# S[IU] - single word signed and unsigned integers (maybe int, long int).
# D[IU] - double word signed and unsigned integers (long long int).
# SF - single precision floating point (float).
# DF - double precision floating point (double).
# XF - extended precision floating point (long double).
# P - pointer type for address arithmetic and other purposes.
# The bytecode specification consists of a series of define_operator
# forms, that are parsed by preprocessors to automatically build
# various switch statements.
# define_operator(name,
# <C prototype code for implementing the operator>,
# <list of variations>)
# The <C prototype> is self explanatory.
# The <list of variations> consists of a (parenthesized list) of
# variation items, each of which is in itself a list. A variation
# item consists of a name suffix, the types of the input arguments
# expected on the stack (shallowest item first) and (optionally) the
# types of the output arguments (similarly ordered). Finally, the
# types of the literal arguments (if any) may appear.
# Substitution in the C prototype code is as follows:
# Substitution happens only after a dollar sign. To get a literal
# dollar sign (why would you ever want one anyway?) use $$.
# $R1 means "result 1" $TR1 means "type name of result one"
# $S1 means "source 1" and similarly with $TS1.
# $L1 means "literal (inline) argument 1" and $TL1 means type thereof.
#
# Notice that the number following $R doesn't affect the push order;
# it's used only for clarity and orthogonality, although it's checked
# to make sure it doesn't exceed the number of outputs. A $R reference
# results in a push, and represents the result lvalue. E.g.
# $R1 = 2\, $R2 = 17
# will expand to:
# INTERP_PUSH($TR1) = 2, INTERP_PUSH($TR2) = 17
#
# Opcode 0 should never happen.
define_operator(neverneverland, abort\(\), (()))
# Stack manipulations.
define_operator(drop, 0, ((, (SI))))
define_operator(duplicate, 0, ((, (SI), (SI, SI))))
define_operator(over, 0, ((, (SI), (SI, SI))))
# Adjust stack pointer
define_operator(setstack, 0, ((SI,,,(SI))))
define_operator(adjstack, 0, ((SI,,,(SI))))
# Constants, loads, and stores.
define_operator(const,
$R1 = $L1,
((QI,, (QI), (QI)), (HI,, (HI), (HI)),
(SI,, (SI), (SI)), (DI,, (DI), (DI)),
(SF,, (SF), (SF)), (DF,, (DF), (DF)),
(XF,, (XF), (XF)), (P,, (P), (P))))
define_operator(load,
$R1 = *\($TR1 *\) $S1,
((QI, (P), (QI)), (HI, (P), (HI)),
(SI, (P), (SI)), (DI, (P), (DI)),
(SF, (P), (SF)), (DF, (P), (DF)),
(XF, (P), (XF)), (P, (P), (P))))
define_operator(store,
*\($TS2 *\) $S1 = $S2,
((QI, (P, QI)), (HI, (P, HI)),
(SI, (P, SI)), (DI, (P, DI)),
(SF, (P, SF)), (DF, (P, DF)),
(XF, (P, XF)), (P, (P, P)),
(BLK, (SI, BLK, BLK))))
# Clear memory block
define_operator(clear, $S1 + $S2, ((BLK, (SI, BLK))))
# Advance pointer by SI constant
define_operator(addconst, $R1 = $S1, ((PSI, (P), (P), (SI))))
# newlocalSI is used for creating variable-sized storage during function
# initialization.
# Create local space, return pointer to block
define_operator(newlocal, $R1 = $S1, ((SI, (SI), (P))))
# Push the address of a local variable.
define_operator(local, $R1 = locals + $L1, ((P,, (P), (SI))))
# Push the address of an argument variable.
define_operator(arg, $R1 = args + $L1, ((P,, (P), (SI))))
# Arithmetic conversions.
define_operator(convert,
$R1 = \($TR1\) $S1,
(# Signed integral promotions (sign extensions).
(QIHI, (QI), (HI)), (HISI, (HI), (SI)), (SIDI, (SI), (DI)),
(QISI, (QI), (SI)),
# Unsigned integral promotions (zero extensions).
(QUHU, (QU), (HU)), (HUSU, (HU), (SU)), (SUDU, (SU), (DU)),
(QUSU, (QU), (SU)),
# Floating promotions.
(SFDF, (SF), (DF)), (DFXF, (DF), (XF)),
# Integral truncation.
(HIQI, (HI), (QI)), (SIHI, (SI), (HI)), (DISI, (DI), (SI)),
(SIQI, (SI), (QI)),
# Unsigned truncation.
(SUQU, (SU), (QU)),
# Floating truncation.
(DFSF, (DF), (SF)), (XFDF, (XF), (DF)),
# Integral conversions to floating types.
(SISF, (SI), (SF)), (SIDF, (SI), (DF)), (SIXF, (SI), (XF)),
(SUSF, (SU), (SF)), (SUDF, (SU), (DF)), (SUXF, (SU), (XF)),
(DISF, (DI), (SF)), (DIDF, (DI), (DF)), (DIXF, (DI), (XF)),
(DUSF, (DU), (SF)), (DUDF, (DU), (DF)), (DUXF, (DU), (XF)),
# Floating conversions to integral types.
(SFSI, (SF), (SI)), (DFSI, (DF), (SI)), (XFSI, (XF), (SI)),
(SFSU, (SF), (SU)), (DFSU, (DF), (SU)), (XFSU, (XF), (SU)),
(SFDI, (SF), (DI)), (DFDI, (DF), (DI)), (XFDI, (XF), (DI)),
(SFDU, (SF), (DU)), (DFDU, (DF), (DU)), (XFDU, (XF), (DU)),
# Pointer/integer conversions.
(PSI, (P), (SI)), (SIP, (SI), (P))))
# Truth value conversion. These are necessary because conversions of, e.g.,
# floating types to integers may not function correctly for large values.
define_operator(convert,
$R1 = !!$S1,
((SIT, (SI), (T)), (DIT, (DI), (T)),
(SFT, (SF), (T)), (DFT, (DF), (T)),
(XFT, (XF), (T)), (PT, (P), (T))))
# Bit field load/store.
# Load and zero-extend bitfield
define_operator(zxload, $R1 = $S1, ((BI, (SU, SU, P), (SU))))
# Load and sign-extend bitfield
define_operator(sxload, $R1 = $S1, ((BI, (SU, SU, P), (SI))))
# Store integer in bitfield
define_operator(sstore, $R1 = $S1, ((BI, (SU, SU, P, SI))))
# Binary operations.
define_operator(add,
$R1 = $S1 + $S2,
((SI, (SI, SI), (SI)), (DI, (DI, DI), (DI)),
(SF, (SF, SF), (SF)), (DF, (DF, DF), (DF)),
(XF, (XF, XF), (XF)),
(PSI, (P, SI), (P))))
define_operator(sub,
$R1 = $S1 - $S2,
((SI, (SI, SI), (SI)), (DI, (DI, DI), (DI)),
(SF, (SF, SF), (SF)), (DF, (DF, DF), (DF)),
(XF, (XF, XF), (XF)),
(PP, (P, P), (SI))))
define_operator(mul,
$R1 = $S1 * $S2,
((SI, (SI, SI), (SI)), (DI, (DI, DI), (DI)),
(SU, (SU, SU), (SU)), (DU, (DU, DU), (DU)),
(SF, (SF, SF), (SF)), (DF, (DF, DF), (DF)),
(XF, (XF, XF), (XF))))
define_operator(div,
$R1 = $S1 / $S2,
((SI, (SI, SI), (SI)), (DI, (DI, DI), (DI)),
(SU, (SU, SU), (SU)), (DU, (DU, DU), (DU)),
(SF, (SF, SF), (SF)), (DF, (DF, DF), (DF)),
(XF, (XF, XF), (XF))))
define_operator(mod,
$R1 = $S1 % $S2,
((SI, (SI, SI), (SI)), (DI, (DI, DI), (DI)),
(SU, (SU, SU), (SU)), (DU, (DU, DU), (DU))))
define_operator(and,
$R1 = $S1 & $S2,
((SI, (SI, SI), (SI)), (DI, (DI, DI), (DI))))
define_operator(ior,
$R1 = $S1 | $S2,
((SI, (SI, SI), (SI)), (DI, (DI, DI), (DI))))
define_operator(xor,
$R1 = $S1 ^ $S2,
((SI, (SI, SI), (SI)), (DI, (DI, DI), (DI))))
define_operator(lshift,
$R1 = $S1 << $S2,
((SI, (SI, SI), (SI)), (SU, (SU, SI), (SU)),
(DI, (DI, SI), (DI)), (DU, (DU, SI), (DU))))
define_operator(rshift,
$R1 = $S1 >> $S2,
((SI, (SI, SI), (SI)), (SU, (SU, SI), (SU)),
(DI, (DI, SI), (DI)), (DU, (DU, SI), (DU))))
define_operator(lt,
$R1 = $S1 < $S2,
((SI, (SI, SI), (T)), (SU, (SU, SU), (T)),
(DI, (DI, DI), (T)), (DU, (DU, DU), (T)),
(SF, (SF, SF), (T)), (DF, (DF, DF), (T)),
(XF, (XF, XF), (T)), (P, (P, P), (T))))
define_operator(le,
$R1 = $S1 <= $S2,
((SI, (SI, SI), (T)), (SU, (SU, SU), (T)),
(DI, (DI, DI), (T)), (DU, (DU, DU), (T)),
(SF, (SF, SF), (T)), (DF, (DF, DF), (T)),
(XF, (XF, XF), (T)), (P, (P, P), (T))))
define_operator(ge,
$R1 = $S1 >= $S2,
((SI, (SI, SI), (T)), (SU, (SU, SU), (T)),
(DI, (DI, DI), (T)), (DU, (DU, DU), (T)),
(SF, (SF, SF), (T)), (DF, (DF, DF), (T)),
(XF, (XF, XF), (T)), (P, (P, P), (T))))
define_operator(gt,
$R1 = $S1 > $S2,
((SI, (SI, SI), (T)), (SU, (SU, SU), (T)),
(DI, (DI, DI), (T)), (DU, (DU, DU), (T)),
(SF, (SF, SF), (T)), (DF, (DF, DF), (T)),
(XF, (XF, XF), (T)), (P, (P, P), (T))))
define_operator(eq,
$R1 = $S1 == $S2,
((SI, (SI, SI), (T)), (DI, (DI, DI), (T)),
(SF, (SF, SF), (T)), (DF, (DF, DF), (T)),
(XF, (XF, XF), (T)), (P, (P, P), (T))))
define_operator(ne,
$R1 = $S1 != $S2,
((SI, (SI, SI), (T)), (DI, (DI, DI), (T)),
(SF, (SF, SF), (T)), (DF, (DF, DF), (T)),
(XF, (XF, XF), (T)), (P, (P, P), (T))))
# Unary operations.
define_operator(neg,
$R1 = -$S1,
((SI, (SI), (SI)), (DI, (DI), (DI)),
(SF, (SF), (SF)), (DF, (DF), (DF)),
(XF, (XF), (XF))))
define_operator(not,
$R1 = ~$S1,
((SI, (SI), (SI)), (DI, (DI), (DI))))
define_operator(not,
$R1 = !$S1,
((T, (SI), (SI))))
# Increment operations.
define_operator(predec,
$R1 = *\($TR1 *\) $S1 -= $S2,
((QI, (P, QI), (QI)), (HI, (P, HI), (HI)),
(SI, (P, SI), (SI)), (DI, (P, DI), (DI)),
(P, (P, SI), (P)), (SF, (P, SF), (SF)),
(DF, (P, DF), (DF)), (XF, (P, XF), (XF)),
(BI, (SU, SU, P, SI), (SI))))
define_operator(preinc,
$R1 = *\($TR1 *\) $S1 += $S2,
((QI, (P, QI), (QI)), (HI, (P, HI), (HI)),
(SI, (P, SI), (SI)), (DI, (P, DI), (DI)),
(P, (P, SI), (P)), (SF, (P, SF), (SF)),
(DF, (P, DF), (DF)), (XF, (P, XF), (XF)),
(BI, (SU, SU, P, SI), (SI))))
define_operator(postdec,
$R1 = *\($TR1 *\) $S1\, *\($TR1 *\) $S1 -= $S2,
((QI, (P, QI), (QI)), (HI, (P, HI), (HI)),
(SI, (P, SI), (SI)), (DI, (P, DI), (DI)),
(P, (P, SI), (P)), (SF, (P, SF), (SF)),
(DF, (P, DF), (DF)), (XF, (P, XF), (XF)),
(BI, (SU, SU, P, SI), (SI))))
define_operator(postinc,
$R1 = *\($TR1 *\) $S1\, *\($TR1 *\) $S1 += $S2,
((QI, (P, QI), (QI)), (HI, (P, HI), (HI)),
(SI, (P, SI), (SI)), (DI, (P, DI), (DI)),
(P, (P, SI), (P)), (SF, (P, SF), (SF)),
(DF, (P, DF), (DF)), (XF, (P, XF), (XF)),
(BI, (SU, SU, P, SI), (SI))))
# Jumps.
define_operator(xjumpif, if \($S1\) pc = code->pc0 + $L1, ((, (T),, (SI))))
define_operator(xjumpifnot, if \(! $S1\) pc = code->pc0 + $L1, ((, (T),, (SI))))
define_operator(jump, pc = code->pc0 + $L1, ((,,,(SI))))
# This is for GCC2. It jumps to the address on the stack.
define_operator(jump, pc = \(void *\) $S1, ((P,,)))
# Switches. In order to (eventually) support ranges we provide four different
# varieties of switches. Arguments are the switch index from the stack, the
# bytecode offset of the switch table, the size of the switch table, and
# the default label.
define_operator(caseSI, CASESI\($S1\, $L1\, $L2\, $L3\), ((, (SI),, (SI, SI, SI))))
define_operator(caseSU, CASESU\($S1\, $L1\, $L2\, $L3\), ((, (SU),, (SI, SI, SI))))
define_operator(caseDI, CASEDI\($S1\, $L1\, $L2\, $L3\), ((, (DI),, (SI, SI, SI))))
define_operator(caseDU, CASEDU\($S1\, $L1\, $L2\, $L3\), ((, (DU),, (SI, SI, SI))))
# Procedure call.
# Stack arguments are (deepest first):
# procedure arguments in reverse order.
# pointer to the place to hold the return value.
# address of the call description vector.
# pointer to the procedure to be called.
define_operator(call, CALL\($S1\, $S2\, $S3\, sp\), ((, (P, P, P))))
# Procedure return.
# Pushes on interpreter stack:
# value of retptr (pointer to return value storage slot)
define_operator(return, $R1 = retptr, ((P,,(P))))
# Really return.
define_operator(ret, return, (()))
# Print an obnoxious line number.
define_operator(linenote, fprintf\(stderr\, "%d\\n"\, $L1\), ((,,,(SI))))

82
gcc_arm/bytecode.h Executable file
View File

@ -0,0 +1,82 @@
/* Bytecode definitions for GNU C-compiler.
Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
extern int output_bytecode;
extern int stack_depth;
extern int max_stack_depth;
/* Emit DI constant according to target machine word ordering */
#define bc_emit_bytecode_DI_const(CST) \
{ int opcode; \
opcode = (WORDS_BIG_ENDIAN \
? TREE_INT_CST_HIGH (CST) \
: TREE_INT_CST_LOW (CST)); \
bc_emit_bytecode_const ((char *) &opcode, sizeof opcode); \
opcode = (WORDS_BIG_ENDIAN \
? TREE_INT_CST_LOW (CST) \
: TREE_INT_CST_HIGH (CST)); \
bc_emit_bytecode_const ((char *) &opcode, sizeof opcode); \
}
extern void bc_expand_expr ();
extern void bc_output_data_constructor ();
extern void bc_store_field ();
extern void bc_load_bit_field ();
extern void bc_store_bit_field ();
extern void bc_push_offset_and_size ();
extern void bc_init_mode_to_code_map ();
/* These are just stubs, so the compiler will compile for targets
that aren't yet supported by the bytecode generator. */
#ifndef TARGET_SUPPORTS_BYTECODE
#define MACHINE_SEG_ALIGN 1
#define INT_ALIGN 1
#define PTR_ALIGN 1
#define NAMES_HAVE_UNDERSCORES
#define BC_NOP (0)
#define BC_GLOBALIZE_LABEL(FP, NAME) BC_NOP
#define BC_OUTPUT_COMMON(FP, NAME, SIZE, ROUNDED) BC_NOP
#define BC_OUTPUT_BSS(FP, NAME, SIZE, ROUNDED) BC_NOP
#define BC_OUTPUT_LOCAL(FP, NAME, SIZE, ROUNDED) BC_NOP
#define BC_OUTPUT_ALIGN(FP, ALIGN) BC_NOP
#define BC_OUTPUT_LABEL(FP, NAME) BC_NOP
#define BC_OUTPUT_SKIP(FP, SIZE) BC_NOP
#define BC_OUTPUT_LABELREF(FP, NAME) BC_NOP
#define BC_OUTPUT_FLOAT(FP, VAL) BC_NOP
#define BC_OUTPUT_DOUBLE(FP, VAL) BC_NOP
#define BC_OUTPUT_BYTE(FP, VAL) BC_NOP
#define BC_OUTPUT_FILE ASM_OUTPUT_FILE
#define BC_OUTPUT_ASCII ASM_OUTPUT_ASCII
#define BC_OUTPUT_IDENT ASM_OUTPUT_IDENT
#define BCXSTR(RTX) ((RTX)->bc_label)
#define BC_WRITE_FILE(FP) BC_NOP
#define BC_WRITE_SEGSYM(SEGSYM, FP) BC_NOP
#define BC_WRITE_RELOC_ENTRY(SEGRELOC, FP, OFFSET) BC_NOP
#define BC_START_BYTECODE_LINE(FP) BC_NOP
#define BC_WRITE_BYTECODE(SEP, VAL, FP) BC_NOP
#define BC_WRITE_RTL(R, FP) BC_NOP
#define BC_EMIT_TRAMPOLINE(TRAMPSEG, CALLINFO) BC_NOP
#define VALIDATE_STACK BC_NOP
#endif /* !TARGET_SUPPORTS_BYTECODE */

35
gcc_arm/bytetypes.h Executable file
View File

@ -0,0 +1,35 @@
/* These should come from genemit */
/* Use __signed__ in case compiling with -traditional. */
typedef __signed__ char QItype;
typedef unsigned char QUtype;
typedef __signed__ short int HItype;
typedef unsigned short int HUtype;
typedef __signed__ long int SItype;
typedef unsigned long int SUtype;
typedef __signed__ long long int DItype;
typedef unsigned long long int DUtype;
typedef float SFtype;
typedef double DFtype;
typedef long double XFtype;
typedef char *Ptype;
typedef int Ttype;
typedef union stacktype
{
QItype QIval;
QUtype QUval;
HItype HIval;
HUtype HUval;
SItype SIval;
SUtype SUval;
DItype DIval;
DUtype DUval;
SFtype SFval;
DFtype DFval;
XFtype XFval;
Ptype Pval;
Ttype Tval;
} stacktype;

661
gcc_arm/c-aux-info.c Executable file
View File

@ -0,0 +1,661 @@
/* Generate information regarding function declarations and definitions based
on information stored in GCC's tree structure. This code implements the
-aux-info option.
Copyright (C) 1989, 91, 94, 95, 97, 1998 Free Software Foundation, Inc.
Contributed by Ron Guilmette (rfg@segfault.us.com).
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
#include "flags.h"
#include "tree.h"
#include "c-tree.h"
enum formals_style_enum {
ansi,
k_and_r_names,
k_and_r_decls
};
typedef enum formals_style_enum formals_style;
static char *data_type;
static char *affix_data_type PROTO((char *));
static char *gen_formal_list_for_type PROTO((tree, formals_style));
static int deserves_ellipsis PROTO((tree));
static char *gen_formal_list_for_func_def PROTO((tree, formals_style));
static char *gen_type PROTO((char *, tree, formals_style));
static char *gen_decl PROTO((tree, int, formals_style));
/* Concatenate a sequence of strings, returning the result.
This function is based on the one in libiberty. */
/* This definition will conflict with the one from prefix.c in
libcpp.a when linking cc1 and cc1obj. So only provide it if we are
not using libcpp.a */
#ifndef USE_CPPLIB
char *
concat VPROTO((const char *first, ...))
{
register int length;
register char *newstr;
register char *end;
register const char *arg;
va_list args;
#ifndef ANSI_PROTOTYPES
const char *first;
#endif
/* First compute the size of the result and get sufficient memory. */
VA_START (args, first);
#ifndef ANSI_PROTOTYPES
first = va_arg (args, const char *);
#endif
arg = first;
length = 0;
while (arg != 0)
{
length += strlen (arg);
arg = va_arg (args, const char *);
}
newstr = (char *) malloc (length + 1);
va_end (args);
/* Now copy the individual pieces to the result string. */
VA_START (args, first);
#ifndef ANSI_PROTOTYPES
first = va_arg (args, char *);
#endif
end = newstr;
arg = first;
while (arg != 0)
{
while (*arg)
*end++ = *arg++;
arg = va_arg (args, const char *);
}
*end = '\000';
va_end (args);
return (newstr);
}
#endif /* ! USE_CPPLIB */
/* Given a string representing an entire type or an entire declaration
which only lacks the actual "data-type" specifier (at its left end),
affix the data-type specifier to the left end of the given type
specification or object declaration.
Because of C language weirdness, the data-type specifier (which normally
goes in at the very left end) may have to be slipped in just to the
right of any leading "const" or "volatile" qualifiers (there may be more
than one). Actually this may not be strictly necessary because it seems
that GCC (at least) accepts `<data-type> const foo;' and treats it the
same as `const <data-type> foo;' but people are accustomed to seeing
`const char *foo;' and *not* `char const *foo;' so we try to create types
that look as expected. */
static char *
affix_data_type (type_or_decl)
char *type_or_decl;
{
char *p = type_or_decl;
char *qualifiers_then_data_type;
char saved;
/* Skip as many leading const's or volatile's as there are. */
for (;;)
{
if (!strncmp (p, "volatile ", 9))
{
p += 9;
continue;
}
if (!strncmp (p, "const ", 6))
{
p += 6;
continue;
}
break;
}
/* p now points to the place where we can insert the data type. We have to
add a blank after the data-type of course. */
if (p == type_or_decl)
return concat (data_type, " ", type_or_decl, NULL_PTR);
saved = *p;
*p = '\0';
qualifiers_then_data_type = concat (type_or_decl, data_type, NULL_PTR);
*p = saved;
return concat (qualifiers_then_data_type, " ", p, NULL_PTR);
}
/* Given a tree node which represents some "function type", generate the
source code version of a formal parameter list (of some given style) for
this function type. Return the whole formal parameter list (including
a pair of surrounding parens) as a string. Note that if the style
we are currently aiming for is non-ansi, then we just return a pair
of empty parens here. */
static char *
gen_formal_list_for_type (fntype, style)
tree fntype;
formals_style style;
{
char *formal_list = "";
tree formal_type;
if (style != ansi)
return "()";
formal_type = TYPE_ARG_TYPES (fntype);
while (formal_type && TREE_VALUE (formal_type) != void_type_node)
{
char *this_type;
if (*formal_list)
formal_list = concat (formal_list, ", ", NULL_PTR);
this_type = gen_type ("", TREE_VALUE (formal_type), ansi);
formal_list
= ((strlen (this_type))
? concat (formal_list, affix_data_type (this_type), NULL_PTR)
: concat (formal_list, data_type, NULL_PTR));
formal_type = TREE_CHAIN (formal_type);
}
/* If we got to here, then we are trying to generate an ANSI style formal
parameters list.
New style prototyped ANSI formal parameter lists should in theory always
contain some stuff between the opening and closing parens, even if it is
only "void".
The brutal truth though is that there is lots of old K&R code out there
which contains declarations of "pointer-to-function" parameters and
these almost never have fully specified formal parameter lists associated
with them. That is, the pointer-to-function parameters are declared
with just empty parameter lists.
In cases such as these, protoize should really insert *something* into
the vacant parameter lists, but what? It has no basis on which to insert
anything in particular.
Here, we make life easy for protoize by trying to distinguish between
K&R empty parameter lists and new-style prototyped parameter lists
that actually contain "void". In the latter case we (obviously) want
to output the "void" verbatim, and that what we do. In the former case,
we do our best to give protoize something nice to insert.
This "something nice" should be something that is still valid (when
re-compiled) but something that can clearly indicate to the user that
more typing information (for the parameter list) should be added (by
hand) at some convenient moment.
The string chosen here is a comment with question marks in it. */
if (!*formal_list)
{
if (TYPE_ARG_TYPES (fntype))
/* assert (TREE_VALUE (TYPE_ARG_TYPES (fntype)) == void_type_node); */
formal_list = "void";
else
formal_list = "/* ??? */";
}
else
{
/* If there were at least some parameters, and if the formals-types-list
petered out to a NULL (i.e. without being terminated by a
void_type_node) then we need to tack on an ellipsis. */
if (!formal_type)
formal_list = concat (formal_list, ", ...", NULL_PTR);
}
return concat (" (", formal_list, ")", NULL_PTR);
}
/* For the generation of an ANSI prototype for a function definition, we have
to look at the formal parameter list of the function's own "type" to
determine if the function's formal parameter list should end with an
ellipsis. Given a tree node, the following function will return non-zero
if the "function type" parameter list should end with an ellipsis. */
static int
deserves_ellipsis (fntype)
tree fntype;
{
tree formal_type;
formal_type = TYPE_ARG_TYPES (fntype);
while (formal_type && TREE_VALUE (formal_type) != void_type_node)
formal_type = TREE_CHAIN (formal_type);
/* If there were at least some parameters, and if the formals-types-list
petered out to a NULL (i.e. without being terminated by a void_type_node)
then we need to tack on an ellipsis. */
return (!formal_type && TYPE_ARG_TYPES (fntype));
}
/* Generate a parameter list for a function definition (in some given style).
Note that this routine has to be separate (and different) from the code that
generates the prototype parameter lists for function declarations, because
in the case of a function declaration, all we have to go on is a tree node
representing the function's own "function type". This can tell us the types
of all of the formal parameters for the function, but it cannot tell us the
actual *names* of each of the formal parameters. We need to output those
parameter names for each function definition.
This routine gets a pointer to a tree node which represents the actual
declaration of the given function, and this DECL node has a list of formal
parameter (variable) declarations attached to it. These formal parameter
(variable) declaration nodes give us the actual names of the formal
parameters for the given function definition.
This routine returns a string which is the source form for the entire
function formal parameter list. */
static char *
gen_formal_list_for_func_def (fndecl, style)
tree fndecl;
formals_style style;
{
char *formal_list = "";
tree formal_decl;
formal_decl = DECL_ARGUMENTS (fndecl);
while (formal_decl)
{
char *this_formal;
if (*formal_list && ((style == ansi) || (style == k_and_r_names)))
formal_list = concat (formal_list, ", ", NULL_PTR);
this_formal = gen_decl (formal_decl, 0, style);
if (style == k_and_r_decls)
formal_list = concat (formal_list, this_formal, "; ", NULL_PTR);
else
formal_list = concat (formal_list, this_formal, NULL_PTR);
formal_decl = TREE_CHAIN (formal_decl);
}
if (style == ansi)
{
if (!DECL_ARGUMENTS (fndecl))
formal_list = concat (formal_list, "void", NULL_PTR);
if (deserves_ellipsis (TREE_TYPE (fndecl)))
formal_list = concat (formal_list, ", ...", NULL_PTR);
}
if ((style == ansi) || (style == k_and_r_names))
formal_list = concat (" (", formal_list, ")", NULL_PTR);
return formal_list;
}
/* Generate a string which is the source code form for a given type (t). This
routine is ugly and complex because the C syntax for declarations is ugly
and complex. This routine is straightforward so long as *no* pointer types,
array types, or function types are involved.
In the simple cases, this routine will return the (string) value which was
passed in as the "ret_val" argument. Usually, this starts out either as an
empty string, or as the name of the declared item (i.e. the formal function
parameter variable).
This routine will also return with the global variable "data_type" set to
some string value which is the "basic" data-type of the given complete type.
This "data_type" string can be concatenated onto the front of the returned
string after this routine returns to its caller.
In complicated cases involving pointer types, array types, or function
types, the C declaration syntax requires an "inside out" approach, i.e. if
you have a type which is a "pointer-to-function" type, you need to handle
the "pointer" part first, but it also has to be "innermost" (relative to
the declaration stuff for the "function" type). Thus, is this case, you
must prepend a "(*" and append a ")" to the name of the item (i.e. formal
variable). Then you must append and prepend the other info for the
"function type" part of the overall type.
To handle the "innermost precedence" rules of complicated C declarators, we
do the following (in this routine). The input parameter called "ret_val"
is treated as a "seed". Each time gen_type is called (perhaps recursively)
some additional strings may be appended or prepended (or both) to the "seed"
string. If yet another (lower) level of the GCC tree exists for the given
type (as in the case of a pointer type, an array type, or a function type)
then the (wrapped) seed is passed to a (recursive) invocation of gen_type()
this recursive invocation may again "wrap" the (new) seed with yet more
declarator stuff, by appending, prepending (or both). By the time the
recursion bottoms out, the "seed value" at that point will have a value
which is (almost) the complete source version of the declarator (except
for the data_type info). Thus, this deepest "seed" value is simply passed
back up through all of the recursive calls until it is given (as the return
value) to the initial caller of the gen_type() routine. All that remains
to do at this point is for the initial caller to prepend the "data_type"
string onto the returned "seed". */
static char *
gen_type (ret_val, t, style)
char *ret_val;
tree t;
formals_style style;
{
tree chain_p;
/* If there is a typedef name for this type, use it. */
if (TYPE_NAME (t) && TREE_CODE (TYPE_NAME (t)) == TYPE_DECL)
data_type = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t)));
else
{
switch (TREE_CODE (t))
{
case POINTER_TYPE:
if (TYPE_READONLY (t))
ret_val = concat ("const ", ret_val, NULL_PTR);
if (TYPE_VOLATILE (t))
ret_val = concat ("volatile ", ret_val, NULL_PTR);
ret_val = concat ("*", ret_val, NULL_PTR);
if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE || TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
ret_val = concat ("(", ret_val, ")", NULL_PTR);
ret_val = gen_type (ret_val, TREE_TYPE (t), style);
return ret_val;
case ARRAY_TYPE:
if (TYPE_SIZE (t) == 0 || TREE_CODE (TYPE_SIZE (t)) != INTEGER_CST)
ret_val = gen_type (concat (ret_val, "[]", NULL_PTR),
TREE_TYPE (t), style);
else if (int_size_in_bytes (t) == 0)
ret_val = gen_type (concat (ret_val, "[0]", NULL_PTR),
TREE_TYPE (t), style);
else
{
int size = (int_size_in_bytes (t) / int_size_in_bytes (TREE_TYPE (t)));
char buff[10];
sprintf (buff, "[%d]", size);
ret_val = gen_type (concat (ret_val, buff, NULL_PTR),
TREE_TYPE (t), style);
}
break;
case FUNCTION_TYPE:
ret_val = gen_type (concat (ret_val,
gen_formal_list_for_type (t, style),
NULL_PTR),
TREE_TYPE (t), style);
break;
case IDENTIFIER_NODE:
data_type = IDENTIFIER_POINTER (t);
break;
/* The following three cases are complicated by the fact that a
user may do something really stupid, like creating a brand new
"anonymous" type specification in a formal argument list (or as
part of a function return type specification). For example:
int f (enum { red, green, blue } color);
In such cases, we have no name that we can put into the prototype
to represent the (anonymous) type. Thus, we have to generate the
whole darn type specification. Yuck! */
case RECORD_TYPE:
if (TYPE_NAME (t))
data_type = IDENTIFIER_POINTER (TYPE_NAME (t));
else
{
data_type = "";
chain_p = TYPE_FIELDS (t);
while (chain_p)
{
data_type = concat (data_type, gen_decl (chain_p, 0, ansi),
NULL_PTR);
chain_p = TREE_CHAIN (chain_p);
data_type = concat (data_type, "; ", NULL_PTR);
}
data_type = concat ("{ ", data_type, "}", NULL_PTR);
}
data_type = concat ("struct ", data_type, NULL_PTR);
break;
case UNION_TYPE:
if (TYPE_NAME (t))
data_type = IDENTIFIER_POINTER (TYPE_NAME (t));
else
{
data_type = "";
chain_p = TYPE_FIELDS (t);
while (chain_p)
{
data_type = concat (data_type, gen_decl (chain_p, 0, ansi),
NULL_PTR);
chain_p = TREE_CHAIN (chain_p);
data_type = concat (data_type, "; ", NULL_PTR);
}
data_type = concat ("{ ", data_type, "}", NULL_PTR);
}
data_type = concat ("union ", data_type, NULL_PTR);
break;
case ENUMERAL_TYPE:
if (TYPE_NAME (t))
data_type = IDENTIFIER_POINTER (TYPE_NAME (t));
else
{
data_type = "";
chain_p = TYPE_VALUES (t);
while (chain_p)
{
data_type = concat (data_type,
IDENTIFIER_POINTER (TREE_PURPOSE (chain_p)), NULL_PTR);
chain_p = TREE_CHAIN (chain_p);
if (chain_p)
data_type = concat (data_type, ", ", NULL_PTR);
}
data_type = concat ("{ ", data_type, " }", NULL_PTR);
}
data_type = concat ("enum ", data_type, NULL_PTR);
break;
case TYPE_DECL:
data_type = IDENTIFIER_POINTER (DECL_NAME (t));
break;
case INTEGER_TYPE:
data_type = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t)));
/* Normally, `unsigned' is part of the deal. Not so if it comes
with a type qualifier. */
if (TREE_UNSIGNED (t) && TYPE_QUALS (t))
data_type = concat ("unsigned ", data_type, NULL_PTR);
break;
case REAL_TYPE:
data_type = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t)));
break;
case VOID_TYPE:
data_type = "void";
break;
case ERROR_MARK:
data_type = "[ERROR]";
break;
default:
abort ();
}
}
if (TYPE_READONLY (t))
ret_val = concat ("const ", ret_val, NULL_PTR);
if (TYPE_VOLATILE (t))
ret_val = concat ("volatile ", ret_val, NULL_PTR);
if (TYPE_RESTRICT (t))
ret_val = concat ("restrict ", ret_val, NULL_PTR);
return ret_val;
}
/* Generate a string (source) representation of an entire entity declaration
(using some particular style for function types).
The given entity may be either a variable or a function.
If the "is_func_definition" parameter is non-zero, assume that the thing
we are generating a declaration for is a FUNCTION_DECL node which is
associated with a function definition. In this case, we can assume that
an attached list of DECL nodes for function formal arguments is present. */
static char *
gen_decl (decl, is_func_definition, style)
tree decl;
int is_func_definition;
formals_style style;
{
char *ret_val;
if (DECL_NAME (decl))
ret_val = IDENTIFIER_POINTER (DECL_NAME (decl));
else
ret_val = "";
/* If we are just generating a list of names of formal parameters, we can
simply return the formal parameter name (with no typing information
attached to it) now. */
if (style == k_and_r_names)
return ret_val;
/* Note that for the declaration of some entity (either a function or a
data object, like for instance a parameter) if the entity itself was
declared as either const or volatile, then const and volatile properties
are associated with just the declaration of the entity, and *not* with
the `type' of the entity. Thus, for such declared entities, we have to
generate the qualifiers here. */
if (TREE_THIS_VOLATILE (decl))
ret_val = concat ("volatile ", ret_val, NULL_PTR);
if (TREE_READONLY (decl))
ret_val = concat ("const ", ret_val, NULL_PTR);
data_type = "";
/* For FUNCTION_DECL nodes, there are two possible cases here. First, if
this FUNCTION_DECL node was generated from a function "definition", then
we will have a list of DECL_NODE's, one for each of the function's formal
parameters. In this case, we can print out not only the types of each
formal, but also each formal's name. In the second case, this
FUNCTION_DECL node came from an actual function declaration (and *not*
a definition). In this case, we do nothing here because the formal
argument type-list will be output later, when the "type" of the function
is added to the string we are building. Note that the ANSI-style formal
parameter list is considered to be a (suffix) part of the "type" of the
function. */
if (TREE_CODE (decl) == FUNCTION_DECL && is_func_definition)
{
ret_val = concat (ret_val, gen_formal_list_for_func_def (decl, ansi),
NULL_PTR);
/* Since we have already added in the formals list stuff, here we don't
add the whole "type" of the function we are considering (which
would include its parameter-list info), rather, we only add in
the "type" of the "type" of the function, which is really just
the return-type of the function (and does not include the parameter
list info). */
ret_val = gen_type (ret_val, TREE_TYPE (TREE_TYPE (decl)), style);
}
else
ret_val = gen_type (ret_val, TREE_TYPE (decl), style);
ret_val = affix_data_type (ret_val);
if (TREE_CODE (decl) != FUNCTION_DECL && DECL_REGISTER (decl))
ret_val = concat ("register ", ret_val, NULL_PTR);
if (TREE_PUBLIC (decl))
ret_val = concat ("extern ", ret_val, NULL_PTR);
if (TREE_CODE (decl) == FUNCTION_DECL && !TREE_PUBLIC (decl))
ret_val = concat ("static ", ret_val, NULL_PTR);
return ret_val;
}
extern FILE *aux_info_file;
/* Generate and write a new line of info to the aux-info (.X) file. This
routine is called once for each function declaration, and once for each
function definition (even the implicit ones). */
void
gen_aux_info_record (fndecl, is_definition, is_implicit, is_prototyped)
tree fndecl;
int is_definition;
int is_implicit;
int is_prototyped;
{
if (flag_gen_aux_info)
{
static int compiled_from_record = 0;
/* Each output .X file must have a header line. Write one now if we
have not yet done so. */
if (! compiled_from_record++)
{
/* The first line tells which directory file names are relative to.
Currently, -aux-info works only for files in the working
directory, so just use a `.' as a placeholder for now. */
fprintf (aux_info_file, "/* compiled from: . */\n");
}
/* Write the actual line of auxiliary info. */
fprintf (aux_info_file, "/* %s:%d:%c%c */ %s;",
DECL_SOURCE_FILE (fndecl),
DECL_SOURCE_LINE (fndecl),
(is_implicit) ? 'I' : (is_prototyped) ? 'N' : 'O',
(is_definition) ? 'F' : 'C',
gen_decl (fndecl, is_definition, ansi));
/* If this is an explicit function declaration, we need to also write
out an old-style (i.e. K&R) function header, just in case the user
wants to run unprotoize. */
if (is_definition)
{
fprintf (aux_info_file, " /*%s %s*/",
gen_formal_list_for_func_def (fndecl, k_and_r_names),
gen_formal_list_for_func_def (fndecl, k_and_r_decls));
}
fprintf (aux_info_file, "\n");
}
}

3240
gcc_arm/c-common.c Executable file

File diff suppressed because it is too large Load Diff

97
gcc_arm/c-convert.c Executable file
View File

@ -0,0 +1,97 @@
/* Language-level data type conversion for GNU C.
Copyright (C) 1987, 1988, 1991, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* This file contains the functions for converting C expressions
to different data types. The only entry point is `convert'.
Every language front end must have a `convert' function
but what kind of conversions it does will depend on the language. */
#include "config.h"
#include "tree.h"
#include "flags.h"
#include "convert.h"
#include "toplev.h"
/* Change of width--truncation and extension of integers or reals--
is represented with NOP_EXPR. Proper functioning of many things
assumes that no other conversions can be NOP_EXPRs.
Conversion between integer and pointer is represented with CONVERT_EXPR.
Converting integer to real uses FLOAT_EXPR
and real to integer uses FIX_TRUNC_EXPR.
Here is a list of all the functions that assume that widening and
narrowing is always done with a NOP_EXPR:
In convert.c, convert_to_integer.
In c-typeck.c, build_binary_op (boolean ops), and truthvalue_conversion.
In expr.c: expand_expr, for operands of a MULT_EXPR.
In fold-const.c: fold.
In tree.c: get_narrower and get_unwidened. */
/* Subroutines of `convert'. */
/* Create an expression whose value is that of EXPR,
converted to type TYPE. The TREE_TYPE of the value
is always TYPE. This function implements all reasonable
conversions; callers should filter out those that are
not permitted by the language being compiled. */
tree
convert (type, expr)
tree type, expr;
{
register tree e = expr;
register enum tree_code code = TREE_CODE (type);
if (type == TREE_TYPE (expr)
|| TREE_CODE (expr) == ERROR_MARK)
return expr;
if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (expr)))
return fold (build1 (NOP_EXPR, type, expr));
if (TREE_CODE (TREE_TYPE (expr)) == ERROR_MARK)
return error_mark_node;
if (TREE_CODE (TREE_TYPE (expr)) == VOID_TYPE)
{
error ("void value not ignored as it ought to be");
return error_mark_node;
}
if (code == VOID_TYPE)
return build1 (CONVERT_EXPR, type, e);
#if 0
/* This is incorrect. A truncation can't be stripped this way.
Extensions will be stripped by the use of get_unwidened. */
if (TREE_CODE (expr) == NOP_EXPR)
return convert (type, TREE_OPERAND (expr, 0));
#endif
if (code == INTEGER_TYPE || code == ENUMERAL_TYPE)
return fold (convert_to_integer (type, e));
if (code == POINTER_TYPE)
return fold (convert_to_pointer (type, e));
if (code == REAL_TYPE)
return fold (convert_to_real (type, e));
if (code == COMPLEX_TYPE)
return fold (convert_to_complex (type, e));
error ("conversion to non-scalar type requested");
return error_mark_node;
}

7458
gcc_arm/c-decl.c Executable file

File diff suppressed because it is too large Load Diff

192
gcc_arm/c-gperf.h Executable file
View File

@ -0,0 +1,192 @@
/* KR-C code produced by gperf version 2.7.1 (19981006 egcs) */
/* Command-line: gperf -L KR-C -F , 0, 0 -p -j1 -i 1 -g -o -t -G -N is_reserved_word -k1,3,$ ../../gcc/c-parse.gperf */
/* Command-line: gperf -L KR-C -F ', 0, 0' -p -j1 -i 1 -g -o -t -N is_reserved_word -k1,3,$ c-parse.gperf */
struct resword { char *name; short token; enum rid rid; };
#define TOTAL_KEYWORDS 83
#define MIN_WORD_LENGTH 2
#define MAX_WORD_LENGTH 20
#define MIN_HASH_VALUE 8
#define MAX_HASH_VALUE 141
/* maximum key range = 134, duplicates = 0 */
static inline unsigned int
hash (str, len)
register char *str;
register unsigned int len;
{
static unsigned char asso_values[] =
{
142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
142, 142, 142, 142, 35, 142, 142, 142, 142, 142,
142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
142, 142, 142, 142, 142, 1, 142, 90, 1, 28,
40, 6, 1, 24, 3, 13, 142, 36, 60, 14,
49, 3, 6, 142, 19, 8, 1, 50, 33, 11,
2, 23, 4, 142, 142, 142, 142, 142, 142, 142,
142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
142, 142, 142, 142, 142, 142
};
register int hval = len;
switch (hval)
{
default:
case 3:
hval += asso_values[(unsigned char)str[2]];
case 2:
case 1:
hval += asso_values[(unsigned char)str[0]];
break;
}
return hval + asso_values[(unsigned char)str[len - 1]];
}
static struct resword wordlist[] =
{
{"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0},
{"out", TYPE_QUAL, RID_OUT},
{"", 0, 0},
{"float", TYPESPEC, RID_FLOAT},
{"__typeof", TYPEOF, NORID},
{"", 0, 0},
{"__typeof__", TYPEOF, NORID},
{"typeof", TYPEOF, NORID},
{"typedef", SCSPEC, RID_TYPEDEF},
{"if", IF, NORID},
{"short", TYPESPEC, RID_SHORT},
{"int", TYPESPEC, RID_INT},
{"sizeof", SIZEOF, NORID},
{"__signed__", TYPESPEC, RID_SIGNED},
{"__extension__", EXTENSION, NORID},
{"inout", TYPE_QUAL, RID_INOUT},
{"__imag__", IMAGPART, NORID},
{"else", ELSE, NORID},
{"__inline__", SCSPEC, RID_INLINE},
{"byref", TYPE_QUAL, RID_BYREF},
{"__iterator__", SCSPEC, RID_ITERATOR},
{"__inline", SCSPEC, RID_INLINE},
{"__real__", REALPART, NORID},
{"switch", SWITCH, NORID},
{"__restrict", TYPE_QUAL, RID_RESTRICT},
{"goto", GOTO, NORID},
{"__restrict__", TYPE_QUAL, RID_RESTRICT},
{"struct", STRUCT, NORID},
{"while", WHILE, NORID},
{"restrict", TYPE_QUAL, RID_RESTRICT},
{"__const", TYPE_QUAL, RID_CONST},
{"oneway", TYPE_QUAL, RID_ONEWAY},
{"__const__", TYPE_QUAL, RID_CONST},
{"__complex", TYPESPEC, RID_COMPLEX},
{"__complex__", TYPESPEC, RID_COMPLEX},
{"for", FOR, NORID},
{"__iterator", SCSPEC, RID_ITERATOR},
{"__imag", IMAGPART, NORID},
{"do", DO, NORID},
{"case", CASE, NORID},
{"__volatile__", TYPE_QUAL, RID_VOLATILE},
{"break", BREAK, NORID},
{"default", DEFAULT, NORID},
{"__volatile", TYPE_QUAL, RID_VOLATILE},
{"", 0, 0}, {"", 0, 0}, {"", 0, 0},
{"@defs", DEFS, NORID},
{"id", OBJECTNAME, RID_ID},
{"", 0, 0},
{"__signed", TYPESPEC, RID_SIGNED},
{"bycopy", TYPE_QUAL, RID_BYCOPY},
{"", 0, 0}, {"", 0, 0}, {"", 0, 0},
{"extern", SCSPEC, RID_EXTERN},
{"", 0, 0},
{"in", TYPE_QUAL, RID_IN},
{"", 0, 0},
{"@compatibility_alias", ALIAS, NORID},
{"", 0, 0},
{"@private", PRIVATE, NORID},
{"@selector", SELECTOR, NORID},
{"register", SCSPEC, RID_REGISTER},
{"__label__", LABEL, NORID},
{"", 0, 0}, {"", 0, 0},
{"enum", ENUM, NORID},
{"return", RETURN, NORID},
{"", 0, 0}, {"", 0, 0},
{"signed", TYPESPEC, RID_SIGNED},
{"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0},
{"const", TYPE_QUAL, RID_CONST},
{"", 0, 0},
{"inline", SCSPEC, RID_INLINE},
{"__real", REALPART, NORID},
{"", 0, 0}, {"", 0, 0}, {"", 0, 0},
{"void", TYPESPEC, RID_VOID},
{"continue", CONTINUE, NORID},
{"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0},
{"@encode", ENCODE, NORID},
{"auto", SCSPEC, RID_AUTO},
{"__asm__", ASM_KEYWORD, NORID},
{"@interface", INTERFACE, NORID},
{"__alignof", ALIGNOF, NORID},
{"double", TYPESPEC, RID_DOUBLE},
{"__alignof__", ALIGNOF, NORID},
{"@protected", PROTECTED, NORID},
{"__attribute__", ATTRIBUTE, NORID},
{"unsigned", TYPESPEC, RID_UNSIGNED},
{"volatile", TYPE_QUAL, RID_VOLATILE},
{"__attribute", ATTRIBUTE, NORID},
{"@class", CLASS, NORID},
{"__asm", ASM_KEYWORD, NORID},
{"", 0, 0}, {"", 0, 0},
{"@implementation", IMPLEMENTATION, NORID},
{"", 0, 0}, {"", 0, 0}, {"", 0, 0},
{"union", UNION, NORID},
{"", 0, 0}, {"", 0, 0},
{"@public", PUBLIC, NORID},
{"asm", ASM_KEYWORD, NORID},
{"", 0, 0},
{"@protocol", PROTOCOL, NORID},
{"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0},
{"@end", END, NORID},
{"", 0, 0}, {"", 0, 0}, {"", 0, 0},
{"static", SCSPEC, RID_STATIC},
{"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0},
{"long", TYPESPEC, RID_LONG},
{"", 0, 0}, {"", 0, 0}, {"", 0, 0},
{"char", TYPESPEC, RID_CHAR}
};
static inline struct resword *
is_reserved_word (str, len)
register char *str;
register unsigned int len;
{
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
{
register int key = hash (str, len);
if (key <= MAX_HASH_VALUE && key >= 0)
{
register char *s = wordlist[key].name;
if (*str == *s && !strcmp (str + 1, s + 1))
return &wordlist[key];
}
}
return 0;
}

604
gcc_arm/c-iterate.c Executable file
View File

@ -0,0 +1,604 @@
/* Build expressions with type checking for C compiler.
Copyright (C) 1987, 88, 89, 92, 93, 96, 1997, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* This file is part of the C front end.
It is responsible for implementing iterators,
both their declarations and the expansion of statements using them. */
#include "config.h"
#include "system.h"
#include "tree.h"
#include "c-tree.h"
#include "flags.h"
#include "obstack.h"
#include "rtl.h"
#include "toplev.h"
#include "expr.h"
/*
KEEPING TRACK OF EXPANSIONS
In order to clean out expansions corresponding to statements inside
"{(...)}" constructs we have to keep track of all expansions. The
cleanup is needed when an automatic, or implicit, expansion on
iterator, say X, happens to a statement which contains a {(...)}
form with a statement already expanded on X. In this case we have
to go back and cleanup the inner expansion. This can be further
complicated by the fact that {(...)} can be nested.
To make this cleanup possible, we keep lists of all expansions, and
to make it work for nested constructs, we keep a stack. The list at
the top of the stack (ITER_STACK.CURRENT_LEVEL) corresponds to the
currently parsed level. All expansions of the levels below the
current one are kept in one list whose head is pointed to by
ITER_STACK.SUBLEVEL_FIRST (SUBLEVEL_LAST is there for making merges
easy). The process works as follows:
-- On "({" a new node is added to the stack by PUSH_ITERATOR_STACK.
The sublevel list is not changed at this point.
-- On "})" the list for the current level is appended to the sublevel
list.
-- On ";" sublevel lists are appended to the current level lists.
The reason is this: if they have not been superseded by the
expansion at the current level, they still might be
superseded later by the expansion on the higher level.
The levels do not have to distinguish levels below, so we
can merge the lists together. */
struct ixpansion
{
tree ixdecl; /* Iterator decl */
rtx ixprologue_start; /* First insn of epilogue. NULL means */
/* explicit (FOR) expansion*/
rtx ixprologue_end;
rtx ixepilogue_start;
rtx ixepilogue_end;
struct ixpansion *next; /* Next in the list */
};
struct iter_stack_node
{
struct ixpansion *first; /* Head of list of ixpansions */
struct ixpansion *last; /* Last node in list of ixpansions */
struct iter_stack_node *next; /* Next level iterator stack node */
};
struct iter_stack_node *iter_stack;
struct iter_stack_node sublevel_ixpansions;
/* A special obstack, and a pointer to the start of
all the data in it (so we can free everything easily). */
static struct obstack ixp_obstack;
static char *ixp_firstobj;
/* During collect_iterators, a list of SAVE_EXPRs already scanned. */
static tree save_exprs;
static void expand_stmt_with_iterators_1 PROTO((tree, tree));
static tree collect_iterators PROTO((tree, tree));
static void iterator_loop_prologue PROTO((tree, rtx *, rtx *));
static void iterator_loop_epilogue PROTO((tree, rtx *, rtx *));
static int top_level_ixpansion_p PROTO((void));
static void isn_append PROTO((struct iter_stack_node *,
struct iter_stack_node *));
static void istack_sublevel_to_current PROTO((void));
static void add_ixpansion PROTO((tree, rtx, rtx, rtx, rtx));
static void delete_ixpansion PROTO((tree));
/* Initialize our obstack once per compilation. */
void
init_iterators ()
{
gcc_obstack_init (&ixp_obstack);
ixp_firstobj = (char *) obstack_alloc (&ixp_obstack, 0);
}
/* Handle the start of an explicit `for' loop for iterator IDECL. */
void
iterator_for_loop_start (idecl)
tree idecl;
{
ITERATOR_BOUND_P (idecl) = 1;
add_ixpansion (idecl, 0, 0, 0, 0);
iterator_loop_prologue (idecl, 0, 0);
}
/* Handle the end of an explicit `for' loop for iterator IDECL. */
void
iterator_for_loop_end (idecl)
tree idecl;
{
iterator_loop_epilogue (idecl, 0, 0);
ITERATOR_BOUND_P (idecl) = 0;
}
/*
ITERATOR RTL EXPANSIONS
Expanding simple statements with iterators is straightforward:
collect the list of all free iterators in the statement, and
generate a loop for each of them.
An iterator is "free" if it has not been "bound" by a FOR
operator. The DECL_RTL of the iterator is the loop counter. */
/* Expand a statement STMT, possibly containing iterator usage, into RTL. */
void
iterator_expand (stmt)
tree stmt;
{
tree iter_list;
save_exprs = NULL_TREE;
iter_list = collect_iterators (stmt, NULL_TREE);
expand_stmt_with_iterators_1 (stmt, iter_list);
istack_sublevel_to_current ();
}
static void
expand_stmt_with_iterators_1 (stmt, iter_list)
tree stmt, iter_list;
{
if (iter_list == 0)
expand_expr_stmt (stmt);
else
{
tree current_iterator = TREE_VALUE (iter_list);
tree iter_list_tail = TREE_CHAIN (iter_list);
rtx p_start, p_end, e_start, e_end;
iterator_loop_prologue (current_iterator, &p_start, &p_end);
expand_stmt_with_iterators_1 (stmt, iter_list_tail);
iterator_loop_epilogue (current_iterator, &e_start, &e_end);
/** Delete all inner expansions based on current_iterator **/
/** before adding the outer one. **/
delete_ixpansion (current_iterator);
add_ixpansion (current_iterator, p_start, p_end, e_start, e_end);
}
}
/* Return a list containing all the free (i.e. not bound by a
containing `for' statement) iterators mentioned in EXP, plus those
in LIST. Do not add duplicate entries to the list. */
static tree
collect_iterators (exp, list)
tree exp, list;
{
if (exp == 0) return list;
switch (TREE_CODE (exp))
{
case VAR_DECL:
if (! ITERATOR_P (exp) || ITERATOR_BOUND_P (exp))
return list;
if (value_member (exp, list))
return list;
return tree_cons (NULL_TREE, exp, list);
case TREE_LIST:
{
tree tail;
for (tail = exp; tail; tail = TREE_CHAIN (tail))
list = collect_iterators (TREE_VALUE (tail), list);
return list;
}
case SAVE_EXPR:
/* In each scan, scan a given save_expr only once. */
if (value_member (exp, save_exprs))
return list;
save_exprs = tree_cons (NULL_TREE, exp, save_exprs);
return collect_iterators (TREE_OPERAND (exp, 0), list);
/* we do not automatically iterate blocks -- one must */
/* use the FOR construct to do that */
case BLOCK:
return list;
default:
switch (TREE_CODE_CLASS (TREE_CODE (exp)))
{
case '1':
return collect_iterators (TREE_OPERAND (exp, 0), list);
case '2':
case '<':
return collect_iterators (TREE_OPERAND (exp, 0),
collect_iterators (TREE_OPERAND (exp, 1),
list));
case 'e':
case 'r':
{
int num_args = tree_code_length[(int) TREE_CODE (exp)];
int i;
/* Some tree codes have RTL, not trees, as operands. */
switch (TREE_CODE (exp))
{
case CALL_EXPR:
num_args = 2;
break;
case METHOD_CALL_EXPR:
num_args = 3;
break;
case WITH_CLEANUP_EXPR:
num_args = 1;
break;
case RTL_EXPR:
return list;
default:
break;
}
for (i = 0; i < num_args; i++)
list = collect_iterators (TREE_OPERAND (exp, i), list);
return list;
}
default:
return list;
}
}
}
/* Emit rtl for the start of a loop for iterator IDECL.
If necessary, create loop counter rtx and store it as DECL_RTL of IDECL.
The prologue normally starts and ends with notes, which are returned
by this function in *START_NOTE and *END_NODE.
If START_NOTE and END_NODE are 0, we don't make those notes. */
static void
iterator_loop_prologue (idecl, start_note, end_note)
tree idecl;
rtx *start_note, *end_note;
{
tree expr;
/* Force the save_expr in DECL_INITIAL to be calculated
if it hasn't been calculated yet. */
expand_expr (DECL_INITIAL (idecl), const0_rtx, VOIDmode,
EXPAND_NORMAL);
if (DECL_RTL (idecl) == 0)
expand_decl (idecl);
if (start_note)
*start_note = emit_note (0, NOTE_INSN_DELETED);
/* Initialize counter. */
expr = build (MODIFY_EXPR, TREE_TYPE (idecl), idecl, integer_zero_node);
TREE_SIDE_EFFECTS (expr) = 1;
expand_expr (expr, const0_rtx, VOIDmode, EXPAND_NORMAL);
expand_start_loop_continue_elsewhere (1);
ITERATOR_BOUND_P (idecl) = 1;
if (end_note)
*end_note = emit_note (0, NOTE_INSN_DELETED);
}
/* Similar to the previous function, but for the end of the loop.
DECL_RTL is zeroed unless we are inside "({...})". The reason for that is
described below.
When we create two (or more) loops based on the same IDECL, and
both inside the same "({...})" construct, we must be prepared to
delete both of the loops and create a single one on the level
above, i.e. enclosing the "({...})". The new loop has to use the
same counter rtl because the references to the iterator decl
(IDECL) have already been expanded as references to the counter
rtl.
It is incorrect to use the same counter reg in different functions,
and it is desirable to use different counters in disjoint loops
when we know there's no need to combine them (because then they can
get allocated separately). */
static void
iterator_loop_epilogue (idecl, start_note, end_note)
tree idecl;
rtx *start_note, *end_note;
{
tree test, incr;
if (start_note)
*start_note = emit_note (0, NOTE_INSN_DELETED);
expand_loop_continue_here ();
incr = build_binary_op (PLUS_EXPR, idecl, integer_one_node, 0);
incr = build (MODIFY_EXPR, TREE_TYPE (idecl), idecl, incr);
TREE_SIDE_EFFECTS (incr) = 1;
expand_expr (incr, const0_rtx, VOIDmode, EXPAND_NORMAL);
test = build_binary_op (LT_EXPR, idecl, DECL_INITIAL (idecl), 0);
expand_exit_loop_if_false (0, test);
expand_end_loop ();
ITERATOR_BOUND_P (idecl) = 0;
/* we can reset rtl since there is not chance that this expansion */
/* would be superseded by a higher level one */
/* but don't do this if the decl is static, since we need to share */
/* the same decl in that case. */
if (top_level_ixpansion_p () && ! TREE_STATIC (idecl))
DECL_RTL (idecl) = 0;
if (end_note)
*end_note = emit_note (0, NOTE_INSN_DELETED);
}
/* Return true if we are not currently inside a "({...})" construct. */
static int
top_level_ixpansion_p ()
{
return iter_stack == 0;
}
/* Given two chains of iter_stack_nodes,
append the nodes in X into Y. */
static void
isn_append (x, y)
struct iter_stack_node *x, *y;
{
if (x->first == 0)
return;
if (y->first == 0)
{
y->first = x->first;
y->last = x->last;
}
else
{
y->last->next = x->first;
y->last = x->last;
}
}
/** Make X empty **/
#define ISN_ZERO(X) (X).first=(X).last=0
/* Move the ixpansions in sublevel_ixpansions into the current
node on the iter_stack, or discard them if the iter_stack is empty.
We do this at the end of a statement. */
static void
istack_sublevel_to_current ()
{
/* At the top level we can throw away sublevel's expansions **/
/* because there is nobody above us to ask for a cleanup **/
if (iter_stack != 0)
/** Merging with empty sublevel list is a no-op **/
if (sublevel_ixpansions.last)
isn_append (&sublevel_ixpansions, iter_stack);
if (iter_stack == 0)
obstack_free (&ixp_obstack, ixp_firstobj);
ISN_ZERO (sublevel_ixpansions);
}
/* Push a new node on the iter_stack, when we enter a ({...}). */
void
push_iterator_stack ()
{
struct iter_stack_node *new_top
= (struct iter_stack_node *)
obstack_alloc (&ixp_obstack, sizeof (struct iter_stack_node));
new_top->first = 0;
new_top->last = 0;
new_top->next = iter_stack;
iter_stack = new_top;
}
/* Pop iter_stack, moving the ixpansions in the node being popped
into sublevel_ixpansions. */
void
pop_iterator_stack ()
{
if (iter_stack == 0)
abort ();
isn_append (iter_stack, &sublevel_ixpansions);
/** Pop current level node: */
iter_stack = iter_stack->next;
}
/* Record an iterator expansion ("ixpansion") for IDECL.
The remaining parameters are the notes in the loop entry
and exit rtl. */
static void
add_ixpansion (idecl, pro_start, pro_end, epi_start, epi_end)
tree idecl;
rtx pro_start, pro_end, epi_start, epi_end;
{
struct ixpansion *newix;
/* Do nothing if we are not inside "({...})",
as in that case this expansion can't need subsequent RTL modification. */
if (iter_stack == 0)
return;
newix = (struct ixpansion *) obstack_alloc (&ixp_obstack,
sizeof (struct ixpansion));
newix->ixdecl = idecl;
newix->ixprologue_start = pro_start;
newix->ixprologue_end = pro_end;
newix->ixepilogue_start = epi_start;
newix->ixepilogue_end = epi_end;
newix->next = iter_stack->first;
iter_stack->first = newix;
if (iter_stack->last == 0)
iter_stack->last = newix;
}
/* Delete the RTL for all ixpansions for iterator IDECL
in our sublevels. We do this when we make a larger
containing expansion for IDECL. */
static void
delete_ixpansion (idecl)
tree idecl;
{
struct ixpansion *previx = 0, *ix;
for (ix = sublevel_ixpansions.first; ix; ix = ix->next)
if (ix->ixdecl == idecl)
{
/** zero means that this is a mark for FOR -- **/
/** we do not delete anything, just issue an error. **/
if (ix->ixprologue_start == 0)
error_with_decl (idecl,
"`for (%s)' appears within implicit iteration");
else
{
rtx insn;
/* We delete all insns, including notes because leaving loop */
/* notes and barriers produced by iterator expansion would */
/* be misleading to other phases */
for (insn = NEXT_INSN (ix->ixprologue_start);
insn != ix->ixprologue_end;
insn = NEXT_INSN (insn))
delete_insn (insn);
for (insn = NEXT_INSN (ix->ixepilogue_start);
insn != ix->ixepilogue_end;
insn = NEXT_INSN (insn))
delete_insn (insn);
}
/* Delete this ixpansion from sublevel_ixpansions. */
if (previx)
previx->next = ix->next;
else
sublevel_ixpansions.first = ix->next;
if (sublevel_ixpansions.last == ix)
sublevel_ixpansions.last = previx;
}
else
previx = ix;
}
#ifdef DEBUG_ITERATORS
/* The functions below are for use from source level debugger.
They print short forms of iterator lists and the iterator stack. */
/* Print the name of the iterator D. */
void
prdecl (d)
tree d;
{
if (d)
{
if (TREE_CODE (d) == VAR_DECL)
{
tree tname = DECL_NAME (d);
char *dname = IDENTIFIER_POINTER (tname);
fprintf (stderr, dname);
}
else
fprintf (stderr, "<<Not a Decl!!!>>");
}
else
fprintf (stderr, "<<NULL!!>>");
}
/* Print Iterator List -- names only */
tree
pil (head)
tree head;
{
tree current, next;
for (current = head; current; current = next)
{
tree node = TREE_VALUE (current);
prdecl (node);
next = TREE_CHAIN (current);
if (next) fprintf (stderr, ",");
}
fprintf (stderr, "\n");
}
/* Print IXpansion List */
struct ixpansion *
pixl (head)
struct ixpansion *head;
{
struct ixpansion *current, *next;
fprintf (stderr, "> ");
if (head == 0)
fprintf (stderr, "(empty)");
for (current=head; current; current = next)
{
tree node = current->ixdecl;
prdecl (node);
next = current->next;
if (next)
fprintf (stderr, ",");
}
fprintf (stderr, "\n");
return head;
}
/* Print Iterator Stack. */
void
pis ()
{
struct iter_stack_node *stack_node;
fprintf (stderr, "--SubLevel: ");
pixl (sublevel_ixpansions.first);
fprintf (stderr, "--Stack:--\n");
for (stack_node = iter_stack;
stack_node;
stack_node = stack_node->next)
pixl (stack_node->first);
}
#endif /* DEBUG_ITERATORS */

213
gcc_arm/c-lang.c Executable file
View File

@ -0,0 +1,213 @@
/* Language-specific hook definitions for C front end.
Copyright (C) 1991, 1995, 1997, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
#include "tree.h"
#include "input.h"
#include "c-tree.h"
#include "c-lex.h"
#include "toplev.h"
#include "output.h"
#if USE_CPPLIB
#include "cpplib.h"
extern char *yy_cur;
extern cpp_reader parse_in;
extern cpp_options parse_options;
#endif
/* Each of the functions defined here
is an alternative to a function in objc-actions.c. */
int
lang_decode_option (argc, argv)
int argc;
char **argv;
{
return c_decode_option (argc, argv);
}
void
lang_init_options ()
{
#if USE_CPPLIB
cpp_reader_init (&parse_in);
parse_in.opts = &parse_options;
cpp_options_init (&parse_options);
#endif
}
void
lang_init ()
{
/* the beginning of the file is a new line; check for # */
/* With luck, we discover the real source file's name from that
and put it in input_filename. */
#if !USE_CPPLIB
ungetc (check_newline (), finput);
#else
check_newline ();
yy_cur--;
#endif
}
void
lang_finish ()
{
}
char *
lang_identify ()
{
return "c";
}
void
print_lang_statistics ()
{
}
/* used by print-tree.c */
void
lang_print_xnode (file, node, indent)
FILE *file ATTRIBUTE_UNUSED;
tree node ATTRIBUTE_UNUSED;
int indent ATTRIBUTE_UNUSED;
{
}
/* Used by c-lex.c, but only for objc. */
tree
lookup_interface (arg)
tree arg ATTRIBUTE_UNUSED;
{
return 0;
}
tree
is_class_name (arg)
tree arg ATTRIBUTE_UNUSED;
{
return 0;
}
void
maybe_objc_check_decl (decl)
tree decl ATTRIBUTE_UNUSED;
{
}
int
maybe_objc_comptypes (lhs, rhs, reflexive)
tree lhs ATTRIBUTE_UNUSED;
tree rhs ATTRIBUTE_UNUSED;
int reflexive ATTRIBUTE_UNUSED;
{
return -1;
}
tree
maybe_objc_method_name (decl)
tree decl ATTRIBUTE_UNUSED;
{
return 0;
}
tree
maybe_building_objc_message_expr ()
{
return 0;
}
int
recognize_objc_keyword ()
{
return 0;
}
tree
build_objc_string (len, str)
int len ATTRIBUTE_UNUSED;
char *str ATTRIBUTE_UNUSED;
{
abort ();
return NULL_TREE;
}
/* Called at end of parsing, but before end-of-file processing. */
void
finish_file ()
{
#ifndef ASM_OUTPUT_CONSTRUCTOR
extern tree static_ctors;
#endif
#ifndef ASM_OUTPUT_DESTRUCTOR
extern tree static_dtors;
#endif
extern tree build_function_call PROTO((tree, tree));
#if !defined(ASM_OUTPUT_CONSTRUCTOR) || !defined(ASM_OUTPUT_DESTRUCTOR)
tree void_list_node = build_tree_list (NULL_TREE, void_type_node);
#endif
#ifndef ASM_OUTPUT_CONSTRUCTOR
if (static_ctors)
{
tree fnname = get_file_function_name ('I');
start_function (void_list_node,
build_parse_node (CALL_EXPR, fnname, void_list_node,
NULL_TREE),
NULL_TREE, NULL_TREE, 0);
fnname = DECL_ASSEMBLER_NAME (current_function_decl);
store_parm_decls ();
for (; static_ctors; static_ctors = TREE_CHAIN (static_ctors))
expand_expr_stmt (build_function_call (TREE_VALUE (static_ctors),
NULL_TREE));
finish_function (0);
assemble_constructor (IDENTIFIER_POINTER (fnname));
}
#endif
#ifndef ASM_OUTPUT_DESTRUCTOR
if (static_dtors)
{
tree fnname = get_file_function_name ('D');
start_function (void_list_node,
build_parse_node (CALL_EXPR, fnname, void_list_node,
NULL_TREE),
NULL_TREE, NULL_TREE, 0);
fnname = DECL_ASSEMBLER_NAME (current_function_decl);
store_parm_decls ();
for (; static_dtors; static_dtors = TREE_CHAIN (static_dtors))
expand_expr_stmt (build_function_call (TREE_VALUE (static_dtors),
NULL_TREE));
finish_function (0);
assemble_destructor (IDENTIFIER_POINTER (fnname));
}
#endif
}

2312
gcc_arm/c-lex.c Executable file

File diff suppressed because it is too large Load Diff

88
gcc_arm/c-lex.h Executable file
View File

@ -0,0 +1,88 @@
/* Define constants for communication with c-parse.y.
Copyright (C) 1987, 1992, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
enum rid
{
RID_UNUSED,
RID_INT,
RID_CHAR,
RID_FLOAT,
RID_DOUBLE,
RID_VOID,
RID_UNUSED1,
RID_UNSIGNED,
RID_SHORT,
RID_LONG,
RID_AUTO,
RID_STATIC,
RID_EXTERN,
RID_REGISTER,
RID_TYPEDEF,
RID_SIGNED,
RID_CONST,
RID_RESTRICT,
RID_VOLATILE,
RID_INLINE,
RID_NOALIAS,
RID_ITERATOR,
RID_COMPLEX,
RID_IN,
RID_OUT,
RID_INOUT,
RID_BYCOPY,
RID_BYREF,
RID_ONEWAY,
RID_ID,
RID_MAX
};
#define NORID RID_UNUSED
#define RID_FIRST_MODIFIER RID_UNSIGNED
/* The elements of `ridpointers' are identifier nodes
for the reserved type names and storage classes.
It is indexed by a RID_... value. */
extern tree ridpointers[(int) RID_MAX];
/* the declaration found for the last IDENTIFIER token read in.
yylex must look this up to detect typedefs, which get token type TYPENAME,
so it is left around in case the identifier is not a typedef but is
used in a context which makes it a reference to a variable. */
extern tree lastiddecl;
extern char *token_buffer; /* Pointer to token buffer. */
extern tree make_pointer_declarator PROTO((tree, tree));
extern void reinit_parse_for_function PROTO((void));
extern void position_after_white_space PROTO((void));
extern int check_newline PROTO((void));
extern int yylex PROTO((void));
extern void yyerror PROTO((char *));
extern void forget_protocol_qualifiers PROTO((void));
extern void remember_protocol_qualifiers PROTO((void));
extern tree is_class_name PROTO((tree));

5078
gcc_arm/c-parse.c Normal file

File diff suppressed because it is too large Load Diff

88
gcc_arm/c-parse.gperf Executable file
View File

@ -0,0 +1,88 @@
%{
/* Command-line: gperf -L KR-C -F ', 0, 0' -p -j1 -i 1 -g -o -t -N is_reserved_word -k1,3,$ c-parse.gperf */
%}
struct resword { char *name; short token; enum rid rid; };
%%
@class, CLASS, NORID
@compatibility_alias, ALIAS, NORID
@defs, DEFS, NORID
@encode, ENCODE, NORID
@end, END, NORID
@implementation, IMPLEMENTATION, NORID
@interface, INTERFACE, NORID
@private, PRIVATE, NORID
@protected, PROTECTED, NORID
@protocol, PROTOCOL, NORID
@public, PUBLIC, NORID
@selector, SELECTOR, NORID
__alignof, ALIGNOF, NORID
__alignof__, ALIGNOF, NORID
__asm, ASM_KEYWORD, NORID
__asm__, ASM_KEYWORD, NORID
__attribute, ATTRIBUTE, NORID
__attribute__, ATTRIBUTE, NORID
__complex, TYPESPEC, RID_COMPLEX
__complex__, TYPESPEC, RID_COMPLEX
__const, TYPE_QUAL, RID_CONST
__const__, TYPE_QUAL, RID_CONST
__extension__, EXTENSION, NORID
__imag, IMAGPART, NORID
__imag__, IMAGPART, NORID
__inline, SCSPEC, RID_INLINE
__inline__, SCSPEC, RID_INLINE
__iterator, SCSPEC, RID_ITERATOR
__iterator__, SCSPEC, RID_ITERATOR
__label__, LABEL, NORID
__real, REALPART, NORID
__real__, REALPART, NORID
__restrict, TYPE_QUAL, RID_RESTRICT
__restrict__, TYPE_QUAL, RID_RESTRICT
__signed, TYPESPEC, RID_SIGNED
__signed__, TYPESPEC, RID_SIGNED
__typeof, TYPEOF, NORID
__typeof__, TYPEOF, NORID
__volatile, TYPE_QUAL, RID_VOLATILE
__volatile__, TYPE_QUAL, RID_VOLATILE
asm, ASM_KEYWORD, NORID
auto, SCSPEC, RID_AUTO
break, BREAK, NORID
bycopy, TYPE_QUAL, RID_BYCOPY
byref, TYPE_QUAL, RID_BYREF
case, CASE, NORID
char, TYPESPEC, RID_CHAR
const, TYPE_QUAL, RID_CONST
continue, CONTINUE, NORID
default, DEFAULT, NORID
do, DO, NORID
double, TYPESPEC, RID_DOUBLE
else, ELSE, NORID
enum, ENUM, NORID
extern, SCSPEC, RID_EXTERN
float, TYPESPEC, RID_FLOAT
for, FOR, NORID
goto, GOTO, NORID
id, OBJECTNAME, RID_ID
if, IF, NORID
in, TYPE_QUAL, RID_IN
inout, TYPE_QUAL, RID_INOUT
inline, SCSPEC, RID_INLINE
int, TYPESPEC, RID_INT
long, TYPESPEC, RID_LONG
oneway, TYPE_QUAL, RID_ONEWAY
out, TYPE_QUAL, RID_OUT
register, SCSPEC, RID_REGISTER
restrict, TYPE_QUAL, RID_RESTRICT
return, RETURN, NORID
short, TYPESPEC, RID_SHORT
signed, TYPESPEC, RID_SIGNED
sizeof, SIZEOF, NORID
static, SCSPEC, RID_STATIC
struct, STRUCT, NORID
switch, SWITCH, NORID
typedef, SCSPEC, RID_TYPEDEF
typeof, TYPEOF, NORID
union, UNION, NORID
unsigned, TYPESPEC, RID_UNSIGNED
void, TYPESPEC, RID_VOID
volatile, TYPE_QUAL, RID_VOLATILE
while, WHILE, NORID

114
gcc_arm/c-parse.h Normal file
View File

@ -0,0 +1,114 @@
/* A Bison parser, made by GNU Bison 2.3. */
/* Skeleton interface for Bison's Yacc-like parsers in C
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA. */
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
under terms of your choice, so long as that work isn't itself a
parser generator using the skeleton or a modified version thereof
as a parser skeleton. Alternatively, if you modify or redistribute
the parser skeleton itself, you may (at your option) remove this
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
/* Tokens. */
#define IDENTIFIER 258
#define TYPENAME 259
#define SCSPEC 260
#define TYPESPEC 261
#define TYPE_QUAL 262
#define CONSTANT 263
#define STRING 264
#define ELLIPSIS 265
#define SIZEOF 266
#define ENUM 267
#define STRUCT 268
#define UNION 269
#define IF 270
#define ELSE 271
#define WHILE 272
#define DO 273
#define FOR 274
#define SWITCH 275
#define CASE 276
#define DEFAULT 277
#define BREAK 278
#define CONTINUE 279
#define RETURN 280
#define GOTO 281
#define ASM_KEYWORD 282
#define TYPEOF 283
#define ALIGNOF 284
#define ATTRIBUTE 285
#define EXTENSION 286
#define LABEL 287
#define REALPART 288
#define IMAGPART 289
#define ASSIGN 290
#define OROR 291
#define ANDAND 292
#define EQCOMPARE 293
#define ARITHCOMPARE 294
#define RSHIFT 295
#define LSHIFT 296
#define MINUSMINUS 297
#define PLUSPLUS 298
#define UNARY 299
#define HYPERUNARY 300
#define POINTSAT 301
#define INTERFACE 302
#define IMPLEMENTATION 303
#define END 304
#define SELECTOR 305
#define DEFS 306
#define ENCODE 307
#define CLASSNAME 308
#define PUBLIC 309
#define PRIVATE 310
#define PROTECTED 311
#define PROTOCOL 312
#define OBJECTNAME 313
#define CLASS 314
#define ALIAS 315
#define OBJC_STRING 316
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
#line 87 "c-parse.y"
{long itype; tree ttype; enum tree_code code;
char *filename; int lineno; int ends_in_label; }
/* Line 1489 of yacc.c. */
#line 174 "c-parse.h"
YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
# define YYSTYPE_IS_TRIVIAL 1
#endif
extern YYSTYPE yylval;

3079
gcc_arm/c-parse.in Executable file

File diff suppressed because it is too large Load Diff

452
gcc_arm/c-pragma.c Executable file
View File

@ -0,0 +1,452 @@
/* Handle #pragma, system V.4 style. Supports #pragma weak and #pragma pack.
Copyright (C) 1992, 1997, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
#include "rtl.h"
#include "tree.h"
#include "except.h"
#include "function.h"
#include "defaults.h"
#include "c-pragma.h"
#include "flags.h"
#include "toplev.h"
#ifdef HANDLE_GENERIC_PRAGMAS
#ifdef HANDLE_PRAGMA_PACK
/* When structure field packing is in effect, this variable is the
number of bits to use as the maximum alignment. When packing is not
in effect, this is zero. */
extern int maximum_field_alignment;
#endif
#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
typedef struct align_stack
{
int alignment;
unsigned int num_pushes;
struct align_stack * prev;
} align_stack;
static struct align_stack * alignment_stack = NULL;
static int push_alignment PROTO((int));
static int pop_alignment PROTO((void));
/* Push an alignment value onto the stack. */
static int
push_alignment (alignment)
int alignment;
{
switch (alignment)
{
case 0:
case 1:
case 2:
case 4:
case 8:
case 16:
break;
default:
warning ("\
Alignment must be a small power of two, not %d, in #pragma pack",
alignment);
return 0;
}
if (alignment_stack == NULL
|| alignment_stack->alignment != alignment)
{
align_stack * entry;
entry = (align_stack *) xmalloc (sizeof (* entry));
if (entry == NULL)
{
warning ("Out of memory pushing #pragma pack");
return 0;
}
entry->alignment = alignment;
entry->num_pushes = 1;
entry->prev = alignment_stack;
alignment_stack = entry;
if (alignment < 8)
maximum_field_alignment = alignment * 8;
else
/* MSVC ignores alignments > 4. */
maximum_field_alignment = 0;
}
else
alignment_stack->num_pushes ++;
return 1;
}
/* Undo a push of an alignment onto the stack. */
static int
pop_alignment ()
{
if (alignment_stack == NULL)
{
warning ("\
#pragma pack(pop) encountered without corresponding #pragma pack(push,<n>)");
return 0;
}
if (-- alignment_stack->num_pushes == 0)
{
align_stack * entry;
entry = alignment_stack->prev;
if (entry == NULL || entry->alignment > 4)
maximum_field_alignment = 0;
else
maximum_field_alignment = entry->alignment * 8;
free (alignment_stack);
alignment_stack = entry;
}
return 1;
}
/* Generate 'packed' and 'aligned' attributes for decls whilst a
#pragma pack(push... is in effect. */
void
insert_pack_attributes (node, attributes, prefix)
tree node;
tree * attributes;
tree * prefix;
{
tree a;
/* If we are not packing, then there is nothing to do. */
if (maximum_field_alignment == 0
|| alignment_stack == NULL)
return;
/* We are only interested in fields. */
if (TREE_CODE_CLASS (TREE_CODE (node)) != 'd'
|| TREE_CODE (node) != FIELD_DECL)
return;
/* Add a 'packed' attribute. */
* attributes = tree_cons (get_identifier ("packed"), NULL, * attributes);
/* If the alignment is > 8 then add an alignment attribute as well. */
if (maximum_field_alignment > 8)
{
/* If the aligned attribute is already present then do not override it. */
for (a = * attributes; a; a = TREE_CHAIN (a))
{
tree name = TREE_PURPOSE (a);
if (strcmp (IDENTIFIER_POINTER (name), "aligned") == 0)
break;
}
if (a == NULL)
for (a = * prefix; a; a = TREE_CHAIN (a))
{
tree name = TREE_PURPOSE (a);
if (strcmp (IDENTIFIER_POINTER (name), "aligned") == 0)
break;
}
if (a == NULL)
{
* attributes = tree_cons
(get_identifier ("aligned"),
tree_cons (NULL,
build_int_2 (maximum_field_alignment / 8, 0),
NULL),
* attributes);
}
}
return;
}
#endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
#ifdef HANDLE_PRAGMA_WEAK
static int add_weak PROTO((char *, char *));
static int
add_weak (name, value)
char * name;
char * value;
{
struct weak_syms * weak;
weak = (struct weak_syms *) permalloc (sizeof (struct weak_syms));
if (weak == NULL)
return 0;
weak->next = weak_decls;
weak->name = name;
weak->value = value;
weak_decls = weak;
return 1;
}
#endif /* HANDLE_PRAGMA_WEAK */
/* Handle one token of a pragma directive. TOKEN is the current token, and
STRING is its printable form. Some front ends do not support generating
tokens, and will only pass in a STRING. Also some front ends will reuse
the buffer containing STRING, so it must be copied to a local buffer if
it needs to be preserved.
If STRING is non-NULL, then the return value will be ignored, and there
will be futher calls to handle_pragma_token() in order to handle the rest of
the line containing the #pragma directive. If STRING is NULL, the entire
line has now been presented to handle_pragma_token() and the return value
should be zero if the pragma flawed in some way, or if the pragma was not
recognised, and non-zero if it was successfully handled. */
int
handle_pragma_token (string, token)
char * string;
tree token;
{
static enum pragma_state state = ps_start;
static enum pragma_state type;
static char * name;
static char * value;
static int align;
/* If we have reached the end of the #pragma directive then
determine what value we should return. */
if (string == NULL)
{
int ret_val = 0;
switch (type)
{
default:
abort ();
break;
case ps_done:
/* The pragma was not recognised. */
break;
#ifdef HANDLE_PRAGMA_PACK
case ps_pack:
if (state == ps_right)
{
maximum_field_alignment = align * 8;
ret_val = 1;
}
else
warning ("malformed `#pragma pack'");
break;
#endif /* HANDLE_PRAGMA_PACK */
#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
case ps_push:
if (state == ps_right)
ret_val = push_alignment (align);
else
warning ("incomplete '#pragma pack(push,<n>)'");
break;
case ps_pop:
if (state == ps_right)
ret_val = pop_alignment ();
else
warning ("missing closing parenthesis in '#pragma pack(pop)'");
break;
#endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
#ifdef HANDLE_PRAGMA_WEAK
case ps_weak:
if (HANDLE_PRAGMA_WEAK)
{
if (state == ps_name)
ret_val = add_weak (name, NULL);
else if (state == ps_value)
ret_val = add_weak (name, value);
else
warning ("malformed `#pragma weak'");
}
else
ret_val = 1; /* Ignore the pragma. */
break;
#endif /* HANDLE_PRAGMA_WEAK */
}
type = state = ps_start;
return ret_val;
}
/* If we have been given a token, but it is not an identifier,
or a small constant, then something has gone wrong. */
if (token)
{
switch (TREE_CODE (token))
{
case IDENTIFIER_NODE:
break;
case INTEGER_CST:
if (TREE_INT_CST_HIGH (token) != 0)
return 0;
break;
default:
return 0;
}
}
switch (state)
{
case ps_start:
type = state = ps_done;
#ifdef HANDLE_PRAGMA_PACK
if (strcmp (string, "pack") == 0)
type = state = ps_pack;
#endif
#ifdef HANDLE_PRAGMA_WEAK
if (strcmp (string, "weak") == 0)
type = state = ps_weak;
#endif
break;
#ifdef HANDLE_PRAGMA_WEAK
case ps_weak:
name = permalloc (strlen (string) + 1);
if (name == NULL)
{
warning ("Out of memory parsing #pragma weak");
state = ps_bad;
}
else
{
strcpy (name, string);
state = ps_name;
}
break;
case ps_name:
state = (strcmp (string, "=") ? ps_bad : ps_equals);
break;
case ps_equals:
value = permalloc (strlen (string) + 1);
if (value == NULL)
{
warning ("Out of memory parsing #pragma weak");
state = ps_bad;
}
else
{
strcpy (value, string);
state = ps_value;
}
break;
case ps_value:
state = ps_bad;
break;
#endif /* HANDLE_PRAGMA_WEAK */
#ifdef HANDLE_PRAGMA_PACK
case ps_pack:
state = (strcmp (string, "(") ? ps_bad : ps_left);
break;
case ps_left:
if (token && TREE_CODE(token) == INTEGER_CST)
align = TREE_INT_CST_LOW(token);
else
align = atoi (string);
switch (align)
{
case 1:
case 2:
case 4:
state = ps_align;
break;
case 0:
state = (strcmp (string, ")") ? ps_bad : ps_right);
#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
if (state == ps_bad)
{
if (strcmp (string, "push") == 0)
type = state = ps_push;
else if (strcmp (string, "pop") == 0)
type = state = ps_pop;
}
#endif
break;
default:
state = ps_bad;
break;
}
break;
#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
case ps_pop:
#endif
case ps_align:
state = (strcmp (string, ")") ? ps_bad : ps_right);
break;
case ps_right:
state = ps_bad;
break;
#endif /* HANDLE_PRAGMA_PACK */
#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
case ps_push:
state = (strcmp (string, ",") ? ps_bad : ps_comma);
break;
case ps_comma:
align = atoi (string);
state = ps_align;
break;
#endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
case ps_bad:
case ps_done:
break;
default:
abort ();
}
return 1;
}
#endif /* HANDLE_GENERIC_PRAGMAS */

100
gcc_arm/c-pragma.h Executable file
View File

@ -0,0 +1,100 @@
/* Pragma related interfaces.
Copyright (C) 1995, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifndef _C_PRAGMA_H
#define _C_PRAGMA_H
#ifdef HANDLE_SYSV_PRAGMA
/* Support #pragma weak iff ASM_WEAKEN_LABEL and ASM_OUTPUT_DEF are
defined. */
#if defined (ASM_WEAKEN_LABEL) && defined (ASM_OUTPUT_DEF)
#define HANDLE_PRAGMA_WEAK SUPPORTS_WEAK
#endif
/* We always support #pragma pack for SYSV pragmas. */
#ifndef HANDLE_PRAGMA_PACK
#define HANDLE_PRAGMA_PACK 1
#endif
#endif /* HANDLE_SYSV_PRAGMA */
#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
/* If we are supporting #pragma pack(push... then we automatically
support #pragma pack(<n>) */
#define HANDLE_PRAGMA_PACK 1
#define PRAGMA_INSERT_ATTRIBUTES(node, pattr, prefix_attr) \
insert_pack_attributes (node, pattr, prefix_attr)
extern void insert_pack_attributes PROTO((tree, tree *, tree *));
#endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
#ifdef HANDLE_PRAGMA_WEAK
/* This structure contains any weak symbol declarations waiting to be emitted. */
struct weak_syms
{
struct weak_syms * next;
char * name;
char * value;
};
/* Declared in varasm.c */
extern struct weak_syms * weak_decls;
#endif /* HANDLE_PRAGMA_WEAK */
#if defined HANDLE_PRAGMA_PACK || defined HANDLE_PRAGMA_WEAK
/* Define HANDLE_GENERIC_PRAGMAS if any kind of front-end pragma
parsing is to be done. The code in GCC's generic C source files
will only look for the definition of this constant. They will
ignore definitions of HANDLE_PRAGMA_PACK and so on. */
#define HANDLE_GENERIC_PRAGMAS 1
#endif
#ifdef HANDLE_GENERIC_PRAGMAS
enum pragma_state
{
ps_start,
ps_done,
#ifdef HANDLE_PRAGMA_WEAK
ps_weak,
ps_name,
ps_equals,
ps_value,
#endif
#ifdef HANDLE_PRAGMA_PACK
ps_pack,
ps_left,
ps_align,
ps_right,
#endif
#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
ps_push,
ps_pop,
ps_comma,
#endif
ps_bad
};
/* Handle a C style pragma */
extern int handle_pragma_token PROTO((char *, tree));
#endif /* HANDLE_GENERIC_PRAGMAS */
#endif /* _C_PRAGMA_H */

560
gcc_arm/c-tree.h Executable file
View File

@ -0,0 +1,560 @@
/* Definitions for C parsing and type checking.
Copyright (C) 1987, 1993, 1994, 1995, 1997, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifndef _C_TREE_H
#define _C_TREE_H
/* Language-dependent contents of an identifier. */
/* The limbo_value is used for block level extern declarations, which need
to be type checked against subsequent extern declarations. They can't
be referenced after they fall out of scope, so they can't be global. */
struct lang_identifier
{
struct tree_identifier ignore;
tree global_value, local_value, label_value, implicit_decl;
tree error_locus, limbo_value;
};
/* Macros for access to language-specific slots in an identifier. */
/* Each of these slots contains a DECL node or null. */
/* This represents the value which the identifier has in the
file-scope namespace. */
#define IDENTIFIER_GLOBAL_VALUE(NODE) \
(((struct lang_identifier *) (NODE))->global_value)
/* This represents the value which the identifier has in the current
scope. */
#define IDENTIFIER_LOCAL_VALUE(NODE) \
(((struct lang_identifier *) (NODE))->local_value)
/* This represents the value which the identifier has as a label in
the current label scope. */
#define IDENTIFIER_LABEL_VALUE(NODE) \
(((struct lang_identifier *) (NODE))->label_value)
/* This records the extern decl of this identifier, if it has had one
at any point in this compilation. */
#define IDENTIFIER_LIMBO_VALUE(NODE) \
(((struct lang_identifier *) (NODE))->limbo_value)
/* This records the implicit function decl of this identifier, if it
has had one at any point in this compilation. */
#define IDENTIFIER_IMPLICIT_DECL(NODE) \
(((struct lang_identifier *) (NODE))->implicit_decl)
/* This is the last function in which we printed an "undefined variable"
message for this identifier. Value is a FUNCTION_DECL or null. */
#define IDENTIFIER_ERROR_LOCUS(NODE) \
(((struct lang_identifier *) (NODE))->error_locus)
/* In identifiers, C uses the following fields in a special way:
TREE_PUBLIC to record that there was a previous local extern decl.
TREE_USED to record that such a decl was used.
TREE_ADDRESSABLE to record that the address of such a decl was used. */
/* Nonzero means reject anything that ANSI standard C forbids. */
extern int pedantic;
/* In a RECORD_TYPE or UNION_TYPE, nonzero if any component is read-only. */
#define C_TYPE_FIELDS_READONLY(type) TREE_LANG_FLAG_1 (type)
/* In a RECORD_TYPE or UNION_TYPE, nonzero if any component is volatile. */
#define C_TYPE_FIELDS_VOLATILE(type) TREE_LANG_FLAG_2 (type)
/* In a RECORD_TYPE or UNION_TYPE or ENUMERAL_TYPE
nonzero if the definition of the type has already started. */
#define C_TYPE_BEING_DEFINED(type) TYPE_LANG_FLAG_0 (type)
/* C types are partitioned into three subsets: object, function, and
incomplete types. */
#define C_TYPE_OBJECT_P(type) \
(TREE_CODE (type) != FUNCTION_TYPE && TYPE_SIZE (type))
#define C_TYPE_FUNCTION_P(type) \
(TREE_CODE (type) == FUNCTION_TYPE)
#define C_TYPE_INCOMPLETE_P(type) \
(TREE_CODE (type) != FUNCTION_TYPE && TYPE_SIZE (type) == 0)
/* For convenience we define a single macro to identify the class of
object or incomplete types. */
#define C_TYPE_OBJECT_OR_INCOMPLETE_P(type) \
(!C_TYPE_FUNCTION_P (type))
/* In a RECORD_TYPE, a sorted array of the fields of the type. */
struct lang_type
{
int len;
tree elts[1];
};
/* Mark which labels are explicitly declared.
These may be shadowed, and may be referenced from nested functions. */
#define C_DECLARED_LABEL_FLAG(label) TREE_LANG_FLAG_1 (label)
/* Record whether a type or decl was written with nonconstant size.
Note that TYPE_SIZE may have simplified to a constant. */
#define C_TYPE_VARIABLE_SIZE(type) TYPE_LANG_FLAG_1 (type)
#define C_DECL_VARIABLE_SIZE(type) DECL_LANG_FLAG_0 (type)
/* Record in each node resulting from a binary operator
what operator was specified for it. */
#define C_EXP_ORIGINAL_CODE(exp) ((enum tree_code) TREE_COMPLEXITY (exp))
#if 0 /* Not used. */
/* Record whether a decl for a function or function pointer has
already been mentioned (in a warning) because it was called
but didn't have a prototype. */
#define C_MISSING_PROTOTYPE_WARNED(decl) DECL_LANG_FLAG_2(decl)
#endif
/* Store a value in that field. */
#define C_SET_EXP_ORIGINAL_CODE(exp, code) \
(TREE_COMPLEXITY (exp) = (int) (code))
/* Record whether a typedef for type `int' was actually `signed int'. */
#define C_TYPEDEF_EXPLICITLY_SIGNED(exp) DECL_LANG_FLAG_1 ((exp))
/* Nonzero for a declaration of a built in function if there has been no
occasion that would declare the function in ordinary C.
Using the function draws a pedantic warning in this case. */
#define C_DECL_ANTICIPATED(exp) DECL_LANG_FLAG_3 ((exp))
/* For FUNCTION_TYPE, a hidden list of types of arguments. The same as
TYPE_ARG_TYPES for functions with prototypes, but created for functions
without prototypes. */
#define TYPE_ACTUAL_ARG_TYPES(NODE) TYPE_NONCOPIED_PARTS (NODE)
/* In a FIELD_DECL, nonzero if the decl was originally a bitfield. */
#define DECL_C_BIT_FIELD(NODE) DECL_LANG_FLAG_4 (NODE)
/* Nonzero if the type T promotes to itself.
ANSI C states explicitly the list of types that promote;
in particular, short promotes to int even if they have the same width. */
#define C_PROMOTING_INTEGER_TYPE_P(t) \
(TREE_CODE ((t)) == INTEGER_TYPE \
&& (TYPE_MAIN_VARIANT (t) == char_type_node \
|| TYPE_MAIN_VARIANT (t) == signed_char_type_node \
|| TYPE_MAIN_VARIANT (t) == unsigned_char_type_node \
|| TYPE_MAIN_VARIANT (t) == short_integer_type_node \
|| TYPE_MAIN_VARIANT (t) == short_unsigned_type_node))
/* In a VAR_DECL, means the variable is really an iterator. */
#define ITERATOR_P(D) (DECL_LANG_FLAG_4(D))
/* In a VAR_DECL for an iterator, means we are within
an explicit loop over that iterator. */
#define ITERATOR_BOUND_P(NODE) ((NODE)->common.readonly_flag)
/* in c-lang.c and objc-act.c */
extern tree lookup_interface PROTO((tree));
extern tree is_class_name PROTO((tree));
extern void maybe_objc_check_decl PROTO((tree));
extern void finish_file PROTO((void));
extern int maybe_objc_comptypes PROTO((tree, tree, int));
extern tree maybe_building_objc_message_expr PROTO((void));
extern tree maybe_objc_method_name PROTO((tree));
extern int recognize_objc_keyword PROTO((void));
extern tree build_objc_string PROTO((int, char *));
/* in c-aux-info.c */
extern void gen_aux_info_record PROTO((tree, int, int, int));
/* in c-common.c */
extern void declare_function_name PROTO((void));
extern void decl_attributes PROTO((tree, tree, tree));
extern void init_function_format_info PROTO((void));
extern void check_function_format PROTO((tree, tree, tree));
extern int c_get_alias_set PROTO((tree));
extern void c_apply_type_quals_to_decl PROTO((int, tree));
/* Print an error message for invalid operands to arith operation CODE.
NOP_EXPR is used as a special case (see truthvalue_conversion). */
extern void binary_op_error PROTO((enum tree_code));
extern void c_expand_expr_stmt PROTO((tree));
extern void c_expand_start_cond PROTO((tree, int, int));
extern void c_expand_start_else PROTO((void));
extern void c_expand_end_cond PROTO((void));
/* Validate the expression after `case' and apply default promotions. */
extern tree check_case_value PROTO((tree));
/* Concatenate a list of STRING_CST nodes into one STRING_CST. */
extern tree combine_strings PROTO((tree));
extern void constant_expression_warning PROTO((tree));
extern tree convert_and_check PROTO((tree, tree));
extern void overflow_warning PROTO((tree));
extern void unsigned_conversion_warning PROTO((tree, tree));
/* Read the rest of the current #-directive line. */
#if USE_CPPLIB
extern char *get_directive_line PROTO((void));
#define GET_DIRECTIVE_LINE() get_directive_line ()
#else
extern char *get_directive_line PROTO((FILE *));
#define GET_DIRECTIVE_LINE() get_directive_line (finput)
#endif
/* Subroutine of build_binary_op, used for comparison operations.
See if the operands have both been converted from subword integer types
and, if so, perhaps change them both back to their original type. */
extern tree shorten_compare PROTO((tree *, tree *, tree *, enum tree_code *));
/* Prepare expr to be an argument of a TRUTH_NOT_EXPR,
or validate its data type for an `if' or `while' statement or ?..: exp. */
extern tree truthvalue_conversion PROTO((tree));
extern tree type_for_mode PROTO((enum machine_mode, int));
extern tree type_for_size PROTO((unsigned, int));
/* in c-convert.c */
extern tree convert PROTO((tree, tree));
/* in c-decl.c */
/* Standard named or nameless data types of the C compiler. */
extern tree char_array_type_node;
extern tree char_type_node;
extern tree const_ptr_type_node;
extern tree const_string_type_node;
extern tree default_function_type;
extern tree double_ftype_double;
extern tree double_ftype_double_double;
extern tree double_type_node;
extern tree float_type_node;
#if HOST_BITS_PER_WIDE_INT >= 64
extern tree intTI_type_node;
#endif
extern tree intDI_type_node;
extern tree intHI_type_node;
extern tree intQI_type_node;
extern tree intSI_type_node;
extern tree int_array_type_node;
extern tree int_ftype_cptr_cptr_sizet;
extern tree int_ftype_int;
extern tree int_ftype_ptr_ptr_int;
extern tree int_ftype_string_string;
extern tree integer_type_node;
extern tree long_double_type_node;
extern tree long_ftype_long;
extern tree long_integer_type_node;
extern tree long_long_integer_type_node;
extern tree long_long_unsigned_type_node;
extern tree long_unsigned_type_node;
extern tree complex_integer_type_node;
extern tree complex_float_type_node;
extern tree complex_double_type_node;
extern tree complex_long_double_type_node;
extern tree ptr_type_node;
extern tree ptrdiff_type_node;
extern tree short_integer_type_node;
extern tree short_unsigned_type_node;
extern tree signed_char_type_node;
extern tree signed_wchar_type_node;
extern tree string_ftype_ptr_ptr;
extern tree string_type_node;
extern tree unsigned_char_type_node;
#if HOST_BITS_PER_WIDE_INT >= 64
extern tree unsigned_intTI_type_node;
#endif
extern tree unsigned_intDI_type_node;
extern tree unsigned_intHI_type_node;
extern tree unsigned_intQI_type_node;
extern tree unsigned_intSI_type_node;
extern tree unsigned_type_node;
extern tree unsigned_wchar_type_node;
extern tree void_ftype_ptr_int_int;
extern tree void_ftype_ptr_ptr_int;
extern tree void_type_node;
extern tree wchar_array_type_node;
extern tree wchar_type_node;
extern tree boolean_type_node;
extern tree boolean_true_node;
extern tree boolean_false_node;
extern tree build_enumerator PROTO((tree, tree));
/* Declare a predefined function. Return the declaration. */
extern tree builtin_function PROTO((char *, tree, enum built_in_function function_, char *));
/* Add qualifiers to a type, in the fashion for C. */
extern tree c_build_qualified_type PROTO((tree, int));
#define c_build_type_variant(TYPE, CONST_P, VOLATILE_P) \
c_build_qualified_type (TYPE, \
((CONST_P) ? TYPE_QUAL_CONST : 0) | \
((VOLATILE_P) ? TYPE_QUAL_VOLATILE : 0))
extern int c_decode_option PROTO((int, char **));
extern void c_mark_varargs PROTO((void));
extern tree check_identifier PROTO((tree, tree));
extern void clear_parm_order PROTO((void));
extern tree combine_parm_decls PROTO((tree, tree, int));
extern int complete_array_type PROTO((tree, tree, int));
extern void declare_parm_level PROTO((int));
extern tree define_label PROTO((char *, int, tree));
extern void delete_block PROTO((tree));
extern void finish_decl PROTO((tree, tree, tree));
extern void finish_decl_top_level PROTO((tree, tree, tree));
extern tree finish_enum PROTO((tree, tree, tree));
extern void finish_function PROTO((int));
extern tree finish_struct PROTO((tree, tree, tree));
extern tree get_parm_info PROTO((int));
extern tree getdecls PROTO((void));
extern tree gettags PROTO((void));
extern int global_bindings_p PROTO((void));
extern tree grokfield PROTO((char *, int, tree, tree, tree));
extern tree groktypename PROTO((tree));
extern tree groktypename_in_parm_context PROTO((tree));
extern tree implicitly_declare PROTO((tree));
extern int in_parm_level_p PROTO((void));
extern void init_decl_processing PROTO((void));
extern void insert_block PROTO((tree));
extern void keep_next_level PROTO((void));
extern int kept_level_p PROTO((void));
extern tree lookup_label PROTO((tree));
extern tree lookup_name PROTO((tree));
extern tree lookup_name_current_level PROTO((tree));
extern tree lookup_name_current_level_global PROTO((tree));
extern tree maybe_build_cleanup PROTO((tree));
extern void parmlist_tags_warning PROTO((void));
extern void pending_xref_error PROTO((void));
extern void pop_c_function_context PROTO((void));
extern void pop_label_level PROTO((void));
extern tree poplevel PROTO((int, int, int));
extern void print_lang_decl PROTO((FILE *, tree, int));
extern void print_lang_identifier PROTO((FILE *, tree, int));
extern void print_lang_type PROTO((FILE *, tree, int));
extern void push_c_function_context PROTO((void));
extern void push_label_level PROTO((void));
extern void push_parm_decl PROTO((tree));
extern tree pushdecl PROTO((tree));
extern tree pushdecl_top_level PROTO((tree));
extern void pushlevel PROTO((int));
extern void pushtag PROTO((tree, tree));
extern void set_block PROTO((tree));
extern tree shadow_label PROTO((tree));
extern void shadow_record_fields PROTO((tree));
extern void shadow_tag PROTO((tree));
extern void shadow_tag_warned PROTO((tree, int));
extern tree start_enum PROTO((tree));
extern int start_function PROTO((tree, tree, tree,
tree, int));
extern tree start_decl PROTO((tree, tree, int,
tree, tree));
extern tree start_struct PROTO((enum tree_code, tree));
extern void store_parm_decls PROTO((void));
extern tree xref_tag PROTO((enum tree_code, tree));
/* in c-typeck.c */
extern tree require_complete_type PROTO((tree));
extern void incomplete_type_error PROTO((tree, tree));
/* Given two integer or real types, return the type for their sum.
Given two compatible ANSI C types, returns the merged type. */
extern tree common_type PROTO((tree, tree));
extern int comptypes PROTO((tree, tree));
extern int self_promoting_args_p PROTO((tree));
extern tree c_sizeof PROTO((tree));
extern tree c_sizeof_nowarn PROTO((tree));
extern tree c_size_in_bytes PROTO((tree));
extern tree c_alignof PROTO((tree));
extern tree c_alignof_expr PROTO((tree));
extern tree default_conversion PROTO((tree));
extern tree build_component_ref PROTO((tree, tree));
extern tree build_indirect_ref PROTO((tree, char *));
extern tree build_array_ref PROTO((tree, tree));
extern tree build_function_call PROTO((tree, tree));
extern tree parser_build_binary_op PROTO((enum tree_code,
tree, tree));
extern tree build_binary_op PROTO((enum tree_code,
tree, tree, int));
extern tree build_unary_op PROTO((enum tree_code,
tree, int));
extern int lvalue_p PROTO((tree));
extern int lvalue_or_else PROTO((tree, char *));
extern void readonly_warning PROTO((tree, char *));
extern int mark_addressable PROTO((tree));
extern tree build_conditional_expr PROTO((tree, tree, tree));
extern tree build_compound_expr PROTO((tree));
extern tree build_c_cast PROTO((tree, tree));
extern tree build_modify_expr PROTO((tree, enum tree_code,
tree));
extern tree initializer_constant_valid_p PROTO((tree, tree));
extern void store_init_value PROTO((tree, tree));
extern void error_init PROTO((char *, char *,
char *));
extern void pedwarn_init PROTO((char *, char *,
char *));
extern void start_init PROTO((tree, tree, int));
extern void finish_init PROTO((void));
extern void really_start_incremental_init PROTO((tree));
extern void push_init_level PROTO((int));
extern tree pop_init_level PROTO((int));
extern void set_init_index PROTO((tree, tree));
extern void set_init_label PROTO((tree));
extern void process_init_element PROTO((tree));
extern void c_expand_asm_operands PROTO((tree, tree, tree, tree,
int, char *, int));
extern void c_expand_return PROTO((tree));
extern tree c_expand_start_case PROTO((tree));
/* in c-iterate.c */
extern void init_iterators PROTO((void));
extern void iterator_expand PROTO((tree));
extern void iterator_for_loop_start PROTO((tree));
extern void iterator_for_loop_end PROTO((tree));
extern void iterator_for_loop_record PROTO((tree));
extern void push_iterator_stack PROTO((void));
extern void pop_iterator_stack PROTO((void));
/* Set to 0 at beginning of a function definition, set to 1 if
a return statement that specifies a return value is seen. */
extern int current_function_returns_value;
/* Set to 0 at beginning of a function definition, set to 1 if
a return statement with no argument is seen. */
extern int current_function_returns_null;
/* Nonzero means the expression being parsed will never be evaluated.
This is a count, since unevaluated expressions can nest. */
extern int skip_evaluation;
/* Nonzero means `$' can be in an identifier. */
extern int dollars_in_ident;
/* Nonzero means allow type mismatches in conditional expressions;
just make their values `void'. */
extern int flag_cond_mismatch;
/* Nonzero means don't recognize the keyword `asm'. */
extern int flag_no_asm;
/* Nonzero means environment is hosted (i.e., not freestanding) */
extern int flag_hosted;
/* Nonzero means ignore `#ident' directives. */
extern int flag_no_ident;
/* Nonzero means warn about implicit declarations. */
extern int warn_implicit;
/* Nonzero means give string constants the type `const char *'
to get extra warnings from them. These warnings will be too numerous
to be useful, except in thoroughly ANSIfied programs. */
extern int flag_const_strings;
/* Nonzero means warn about sizeof (function) or addition/subtraction
of function pointers. */
extern int warn_pointer_arith;
/* Nonzero means warn for all old-style non-prototype function decls. */
extern int warn_strict_prototypes;
/* Nonzero means warn about multiple (redundant) decls for the same single
variable or function. */
extern int warn_redundant_decls;
/* Nonzero means warn about extern declarations of objects not at
file-scope level and about *all* declarations of functions (whether
extern or static) not at file-scope level. Note that we exclude
implicit function declarations. To get warnings about those, use
-Wimplicit. */
extern int warn_nested_externs;
/* Nonzero means warn about pointer casts that can drop a type qualifier
from the pointer target type. */
extern int warn_cast_qual;
/* Nonzero means warn when casting a function call to a type that does
not match the return type (e.g. (float)sqrt() or (anything*)malloc()
when there is no previous declaration of sqrt or malloc. */
extern int warn_bad_function_cast;
/* Warn about functions which might be candidates for attribute noreturn. */
extern int warn_missing_noreturn;
/* Warn about traditional constructs whose meanings changed in ANSI C. */
extern int warn_traditional;
/* Warn about *printf or *scanf format/argument anomalies. */
extern int warn_format;
/* Warn about a subscript that has type char. */
extern int warn_char_subscripts;
/* Warn if a type conversion is done that might have confusing results. */
extern int warn_conversion;
/* Warn if main is suspicious. */
extern int warn_main;
/* Nonzero means do some things the same way PCC does. */
extern int flag_traditional;
/* Nonzero means use the ISO C9x dialect of C. */
extern int flag_isoc9x;
/* Nonzero means to allow single precision math even if we're generally
being traditional. */
extern int flag_allow_single_precision;
/* Nonzero means warn about suggesting putting in ()'s. */
extern int warn_parentheses;
/* Warn if initializer is not completely bracketed. */
extern int warn_missing_braces;
/* Warn about comparison of signed and unsigned values. */
extern int warn_sign_compare;
/* Warn about multicharacter constants. */
extern int warn_multichar;
/* Warn about long long. */
extern int warn_long_long;
/* Nonzero means we are reading code that came from a system header file. */
extern int system_header_p;
/* Nonzero enables objc features. */
extern int doing_objc_thang;
/* In c-decl.c */
extern void finish_incomplete_decl PROTO((tree));
#endif /* not _C_TREE_H */

7022
gcc_arm/c-typeck.c Executable file

File diff suppressed because it is too large Load Diff

757
gcc_arm/caller-save.c Executable file
View File

@ -0,0 +1,757 @@
/* Save and restore call-clobbered registers which are live across a call.
Copyright (C) 1989, 1992, 94-95, 97, 98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
#include "rtl.h"
#include "insn-config.h"
#include "flags.h"
#include "regs.h"
#include "hard-reg-set.h"
#include "recog.h"
#include "basic-block.h"
#include "reload.h"
#include "expr.h"
#include "toplev.h"
#ifndef MAX_MOVE_MAX
#define MAX_MOVE_MAX MOVE_MAX
#endif
#ifndef MIN_UNITS_PER_WORD
#define MIN_UNITS_PER_WORD UNITS_PER_WORD
#endif
#define MOVE_MAX_WORDS (MOVE_MAX / UNITS_PER_WORD)
/* Modes for each hard register that we can save. The smallest mode is wide
enough to save the entire contents of the register. When saving the
register because it is live we first try to save in multi-register modes.
If that is not possible the save is done one register at a time. */
static enum machine_mode
regno_save_mode[FIRST_PSEUDO_REGISTER][MAX_MOVE_MAX / MIN_UNITS_PER_WORD + 1];
/* For each hard register, a place on the stack where it can be saved,
if needed. */
static rtx
regno_save_mem[FIRST_PSEUDO_REGISTER][MAX_MOVE_MAX / MIN_UNITS_PER_WORD + 1];
/* We will only make a register eligible for caller-save if it can be
saved in its widest mode with a simple SET insn as long as the memory
address is valid. We record the INSN_CODE is those insns here since
when we emit them, the addresses might not be valid, so they might not
be recognized. */
static enum insn_code
reg_save_code[FIRST_PSEUDO_REGISTER][MAX_MOVE_MAX / MIN_UNITS_PER_WORD + 1];
static enum insn_code
reg_restore_code[FIRST_PSEUDO_REGISTER][MAX_MOVE_MAX / MIN_UNITS_PER_WORD + 1];
/* Set of hard regs currently residing in save area (during insn scan). */
static HARD_REG_SET hard_regs_saved;
/* Number of registers currently in hard_regs_saved. */
static int n_regs_saved;
/* Computed by mark_referenced_regs, all regs referenced in a given
insn. */
static HARD_REG_SET referenced_regs;
/* Computed in mark_set_regs, holds all registers set by the current
instruction. */
static HARD_REG_SET this_insn_sets;
static void mark_set_regs PROTO((rtx, rtx));
static void mark_referenced_regs PROTO((rtx));
static int insert_save PROTO((struct insn_chain *, int, int,
HARD_REG_SET *));
static int insert_restore PROTO((struct insn_chain *, int, int,
int));
static void insert_one_insn PROTO((struct insn_chain *, int,
enum insn_code, rtx));
/* Initialize for caller-save.
Look at all the hard registers that are used by a call and for which
regclass.c has not already excluded from being used across a call.
Ensure that we can find a mode to save the register and that there is a
simple insn to save and restore the register. This latter check avoids
problems that would occur if we tried to save the MQ register of some
machines directly into memory. */
void
init_caller_save ()
{
char *first_obj = (char *) oballoc (0);
rtx addr_reg;
int offset;
rtx address;
int i, j;
/* First find all the registers that we need to deal with and all
the modes that they can have. If we can't find a mode to use,
we can't have the register live over calls. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
{
if (call_used_regs[i] && ! call_fixed_regs[i])
{
for (j = 1; j <= MOVE_MAX_WORDS; j++)
{
regno_save_mode[i][j] = HARD_REGNO_CALLER_SAVE_MODE (i, j);
if (regno_save_mode[i][j] == VOIDmode && j == 1)
{
call_fixed_regs[i] = 1;
SET_HARD_REG_BIT (call_fixed_reg_set, i);
}
}
}
else
regno_save_mode[i][1] = VOIDmode;
}
/* The following code tries to approximate the conditions under which
we can easily save and restore a register without scratch registers or
other complexities. It will usually work, except under conditions where
the validity of an insn operand is dependent on the address offset.
No such cases are currently known.
We first find a typical offset from some BASE_REG_CLASS register.
This address is chosen by finding the first register in the class
and by finding the smallest power of two that is a valid offset from
that register in every mode we will use to save registers. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (TEST_HARD_REG_BIT (reg_class_contents[(int) BASE_REG_CLASS], i))
break;
if (i == FIRST_PSEUDO_REGISTER)
abort ();
addr_reg = gen_rtx_REG (Pmode, i);
for (offset = 1 << (HOST_BITS_PER_INT / 2); offset; offset >>= 1)
{
address = gen_rtx_PLUS (Pmode, addr_reg, GEN_INT (offset));
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (regno_save_mode[i][1] != VOIDmode
&& ! strict_memory_address_p (regno_save_mode[i][1], address))
break;
if (i == FIRST_PSEUDO_REGISTER)
break;
}
/* If we didn't find a valid address, we must use register indirect. */
if (offset == 0)
address = addr_reg;
/* Next we try to form an insn to save and restore the register. We
see if such an insn is recognized and meets its constraints. */
start_sequence ();
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
for (j = 1; j <= MOVE_MAX_WORDS; j++)
if (regno_save_mode[i][j] != VOIDmode)
{
rtx mem = gen_rtx_MEM (regno_save_mode[i][j], address);
rtx reg = gen_rtx_REG (regno_save_mode[i][j], i);
rtx savepat = gen_rtx_SET (VOIDmode, mem, reg);
rtx restpat = gen_rtx_SET (VOIDmode, reg, mem);
rtx saveinsn = emit_insn (savepat);
rtx restinsn = emit_insn (restpat);
int ok;
reg_save_code[i][j] = recog_memoized (saveinsn);
reg_restore_code[i][j] = recog_memoized (restinsn);
/* Now extract both insns and see if we can meet their
constraints. */
ok = (reg_save_code[i][j] != (enum insn_code)-1
&& reg_restore_code[i][j] != (enum insn_code)-1);
if (ok)
{
extract_insn (saveinsn);
ok = constrain_operands (1);
extract_insn (restinsn);
ok &= constrain_operands (1);
}
if (! ok)
{
regno_save_mode[i][j] = VOIDmode;
if (j == 1)
{
call_fixed_regs[i] = 1;
SET_HARD_REG_BIT (call_fixed_reg_set, i);
}
}
}
end_sequence ();
obfree (first_obj);
}
/* Initialize save areas by showing that we haven't allocated any yet. */
void
init_save_areas ()
{
int i, j;
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
for (j = 1; j <= MOVE_MAX_WORDS; j++)
regno_save_mem[i][j] = 0;
}
/* Allocate save areas for any hard registers that might need saving.
We take a conservative approach here and look for call-clobbered hard
registers that are assigned to pseudos that cross calls. This may
overestimate slightly (especially if some of these registers are later
used as spill registers), but it should not be significant.
Future work:
In the fallback case we should iterate backwards across all possible
modes for the save, choosing the largest available one instead of
falling back to the smallest mode immediately. (eg TF -> DF -> SF).
We do not try to use "move multiple" instructions that exist
on some machines (such as the 68k moveml). It could be a win to try
and use them when possible. The hard part is doing it in a way that is
machine independent since they might be saving non-consecutive
registers. (imagine caller-saving d0,d1,a0,a1 on the 68k) */
void
setup_save_areas ()
{
int i, j, k;
HARD_REG_SET hard_regs_used;
/* Allocate space in the save area for the largest multi-register
pseudos first, then work backwards to single register
pseudos. */
/* Find and record all call-used hard-registers in this function. */
CLEAR_HARD_REG_SET (hard_regs_used);
for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
if (reg_renumber[i] >= 0 && REG_N_CALLS_CROSSED (i) > 0)
{
int regno = reg_renumber[i];
int endregno
= regno + HARD_REGNO_NREGS (regno, GET_MODE (regno_reg_rtx[i]));
int nregs = endregno - regno;
for (j = 0; j < nregs; j++)
{
if (call_used_regs[regno+j])
SET_HARD_REG_BIT (hard_regs_used, regno+j);
}
}
/* Now run through all the call-used hard-registers and allocate
space for them in the caller-save area. Try to allocate space
in a manner which allows multi-register saves/restores to be done. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
for (j = MOVE_MAX_WORDS; j > 0; j--)
{
int do_save = 1;
/* If no mode exists for this size, try another. Also break out
if we have already saved this hard register. */
if (regno_save_mode[i][j] == VOIDmode || regno_save_mem[i][1] != 0)
continue;
/* See if any register in this group has been saved. */
for (k = 0; k < j; k++)
if (regno_save_mem[i + k][1])
{
do_save = 0;
break;
}
if (! do_save)
continue;
for (k = 0; k < j; k++)
if (! TEST_HARD_REG_BIT (hard_regs_used, i + k))
{
do_save = 0;
break;
}
if (! do_save)
continue;
/* We have found an acceptable mode to store in. */
regno_save_mem[i][j]
= assign_stack_local (regno_save_mode[i][j],
GET_MODE_SIZE (regno_save_mode[i][j]), 0);
/* Setup single word save area just in case... */
for (k = 0; k < j; k++)
{
/* This should not depend on WORDS_BIG_ENDIAN.
The order of words in regs is the same as in memory. */
rtx temp = gen_rtx_MEM (regno_save_mode[i+k][1],
XEXP (regno_save_mem[i][j], 0));
regno_save_mem[i+k][1]
= adj_offsettable_operand (temp, k * UNITS_PER_WORD);
}
}
}
/* Find the places where hard regs are live across calls and save them. */
void
save_call_clobbered_regs ()
{
struct insn_chain *chain, *next;
CLEAR_HARD_REG_SET (hard_regs_saved);
n_regs_saved = 0;
for (chain = reload_insn_chain; chain != 0; chain = next)
{
rtx insn = chain->insn;
enum rtx_code code = GET_CODE (insn);
next = chain->next;
if (chain->is_caller_save_insn)
abort ();
if (GET_RTX_CLASS (code) == 'i')
{
/* If some registers have been saved, see if INSN references
any of them. We must restore them before the insn if so. */
if (n_regs_saved)
{
int regno;
if (code == JUMP_INSN)
/* Restore all registers if this is a JUMP_INSN. */
COPY_HARD_REG_SET (referenced_regs, hard_regs_saved);
else
{
CLEAR_HARD_REG_SET (referenced_regs);
mark_referenced_regs (PATTERN (insn));
AND_HARD_REG_SET (referenced_regs, hard_regs_saved);
}
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
if (TEST_HARD_REG_BIT (referenced_regs, regno))
regno += insert_restore (chain, 1, regno, MOVE_MAX_WORDS);
}
if (code == CALL_INSN)
{
rtx x;
int regno, nregs;
HARD_REG_SET hard_regs_to_save;
/* Use the register life information in CHAIN to compute which
regs are live before the call. */
REG_SET_TO_HARD_REG_SET (hard_regs_to_save, chain->live_before);
compute_use_by_pseudos (&hard_regs_to_save, chain->live_before);
/* Record all registers set in this call insn. These don't need
to be saved. */
CLEAR_HARD_REG_SET (this_insn_sets);
note_stores (PATTERN (insn), mark_set_regs);
/* Compute which hard regs must be saved before this call. */
AND_COMPL_HARD_REG_SET (hard_regs_to_save, call_fixed_reg_set);
AND_COMPL_HARD_REG_SET (hard_regs_to_save, this_insn_sets);
AND_COMPL_HARD_REG_SET (hard_regs_to_save, hard_regs_saved);
AND_HARD_REG_SET (hard_regs_to_save, call_used_reg_set);
/* Registers used for function parameters need not be saved. */
for (x = CALL_INSN_FUNCTION_USAGE (insn); x != 0;
x = XEXP (x, 1))
{
rtx y;
if (GET_CODE (XEXP (x, 0)) != USE)
continue;
y = XEXP (XEXP (x, 0), 0);
if (GET_CODE (y) != REG)
abort ();
regno = REGNO (y);
if (REGNO (y) >= FIRST_PSEUDO_REGISTER)
abort ();
nregs = HARD_REGNO_NREGS (regno, GET_MODE (y));
while (nregs-- > 0)
CLEAR_HARD_REG_BIT (hard_regs_to_save, regno + nregs);
}
/* Neither do registers for which we find a death note. */
for (x = REG_NOTES (insn); x != 0; x = XEXP (x, 1))
{
rtx y = XEXP (x, 0);
if (REG_NOTE_KIND (x) != REG_DEAD)
continue;
if (GET_CODE (y) != REG)
abort ();
regno = REGNO (y);
if (regno >= FIRST_PSEUDO_REGISTER)
regno = reg_renumber[regno];
if (regno < 0)
continue;
nregs = HARD_REGNO_NREGS (regno, GET_MODE (y));
while (nregs-- > 0)
CLEAR_HARD_REG_BIT (hard_regs_to_save, regno + nregs);
}
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
if (TEST_HARD_REG_BIT (hard_regs_to_save, regno))
regno += insert_save (chain, 1, regno, &hard_regs_to_save);
/* Must recompute n_regs_saved. */
n_regs_saved = 0;
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
if (TEST_HARD_REG_BIT (hard_regs_saved, regno))
n_regs_saved++;
}
}
if (chain->next == 0 || chain->next->block > chain->block)
{
int regno;
/* At the end of the basic block, we must restore any registers that
remain saved. If the last insn in the block is a JUMP_INSN, put
the restore before the insn, otherwise, put it after the insn. */
if (n_regs_saved)
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
if (TEST_HARD_REG_BIT (hard_regs_saved, regno))
regno += insert_restore (chain, GET_CODE (insn) == JUMP_INSN,
regno, MOVE_MAX_WORDS);
}
}
}
/* Here from note_stores when an insn stores a value in a register.
Set the proper bit or bits in this_insn_sets. All pseudos that have
been assigned hard regs have had their register number changed already,
so we can ignore pseudos. */
static void
mark_set_regs (reg, setter)
rtx reg;
rtx setter ATTRIBUTE_UNUSED;
{
register int regno, endregno, i;
enum machine_mode mode = GET_MODE (reg);
int word = 0;
if (GET_CODE (reg) == SUBREG)
{
word = SUBREG_WORD (reg);
reg = SUBREG_REG (reg);
}
if (GET_CODE (reg) != REG || REGNO (reg) >= FIRST_PSEUDO_REGISTER)
return;
regno = REGNO (reg) + word;
endregno = regno + HARD_REGNO_NREGS (regno, mode);
for (i = regno; i < endregno; i++)
SET_HARD_REG_BIT (this_insn_sets, i);
}
/* Walk X and record all referenced registers in REFERENCED_REGS. */
static void
mark_referenced_regs (x)
rtx x;
{
enum rtx_code code = GET_CODE (x);
char *fmt;
int i, j;
if (code == SET)
mark_referenced_regs (SET_SRC (x));
if (code == SET || code == CLOBBER)
{
x = SET_DEST (x);
code = GET_CODE (x);
if (code == REG || code == PC || code == CC0
|| (code == SUBREG && GET_CODE (SUBREG_REG (x)) == REG))
return;
}
if (code == MEM || code == SUBREG)
{
x = XEXP (x, 0);
code = GET_CODE (x);
}
if (code == REG)
{
int regno = REGNO (x);
int hardregno = (regno < FIRST_PSEUDO_REGISTER ? regno
: reg_renumber[regno]);
if (hardregno >= 0)
{
int nregs = HARD_REGNO_NREGS (hardregno, GET_MODE (x));
while (nregs-- > 0)
SET_HARD_REG_BIT (referenced_regs, hardregno + nregs);
}
/* If this is a pseudo that did not get a hard register, scan its
memory location, since it might involve the use of another
register, which might be saved. */
else if (reg_equiv_mem[regno] != 0)
mark_referenced_regs (XEXP (reg_equiv_mem[regno], 0));
else if (reg_equiv_address[regno] != 0)
mark_referenced_regs (reg_equiv_address[regno]);
return;
}
fmt = GET_RTX_FORMAT (code);
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{
if (fmt[i] == 'e')
mark_referenced_regs (XEXP (x, i));
else if (fmt[i] == 'E')
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
mark_referenced_regs (XVECEXP (x, i, j));
}
}
/* Insert a sequence of insns to restore. Place these insns in front of
CHAIN if BEFORE_P is nonzero, behind the insn otherwise. MAXRESTORE is
the maximum number of registers which should be restored during this call.
It should never be less than 1 since we only work with entire registers.
Note that we have verified in init_caller_save that we can do this
with a simple SET, so use it. Set INSN_CODE to what we save there
since the address might not be valid so the insn might not be recognized.
These insns will be reloaded and have register elimination done by
find_reload, so we need not worry about that here.
Return the extra number of registers saved. */
static int
insert_restore (chain, before_p, regno, maxrestore)
struct insn_chain *chain;
int before_p;
int regno;
int maxrestore;
{
int i;
rtx pat = NULL_RTX;
enum insn_code code = CODE_FOR_nothing;
int numregs = 0;
/* A common failure mode if register status is not correct in the RTL
is for this routine to be called with a REGNO we didn't expect to
save. That will cause us to write an insn with a (nil) SET_DEST
or SET_SRC. Instead of doing so and causing a crash later, check
for this common case and abort here instead. This will remove one
step in debugging such problems. */
if (regno_save_mem[regno][1] == 0)
abort ();
/* Get the pattern to emit and update our status.
See if we can restore `maxrestore' registers at once. Work
backwards to the single register case. */
for (i = maxrestore; i > 0; i--)
{
int j, k;
int ok = 1;
if (regno_save_mem[regno][i] == 0)
continue;
for (j = 0; j < i; j++)
if (! TEST_HARD_REG_BIT (hard_regs_saved, regno + j))
{
ok = 0;
break;
}
/* Must do this one restore at a time */
if (! ok)
continue;
pat = gen_rtx_SET (VOIDmode,
gen_rtx_REG (GET_MODE (regno_save_mem[regno][i]),
regno),
regno_save_mem[regno][i]);
code = reg_restore_code[regno][i];
/* Clear status for all registers we restored. */
for (k = 0; k < i; k++)
{
CLEAR_HARD_REG_BIT (hard_regs_saved, regno + k);
n_regs_saved--;
}
numregs = i;
break;
}
insert_one_insn (chain, before_p, code, pat);
/* Tell our callers how many extra registers we saved/restored */
return numregs - 1;
}
/* Like insert_restore above, but save registers instead. */
static int
insert_save (chain, before_p, regno, to_save)
struct insn_chain *chain;
int before_p;
int regno;
HARD_REG_SET *to_save;
{
int i;
rtx pat = NULL_RTX;
enum insn_code code = CODE_FOR_nothing;
int numregs = 0;
/* A common failure mode if register status is not correct in the RTL
is for this routine to be called with a REGNO we didn't expect to
save. That will cause us to write an insn with a (nil) SET_DEST
or SET_SRC. Instead of doing so and causing a crash later, check
for this common case and abort here instead. This will remove one
step in debugging such problems. */
if (regno_save_mem[regno][1] == 0)
abort ();
/* Get the pattern to emit and update our status.
See if we can save several registers with a single instruction.
Work backwards to the single register case. */
for (i = MOVE_MAX_WORDS; i > 0; i--)
{
int j, k;
int ok = 1;
if (regno_save_mem[regno][i] == 0)
continue;
for (j = 0; j < i; j++)
if (! TEST_HARD_REG_BIT (*to_save, regno + j))
{
ok = 0;
break;
}
/* Must do this one save at a time */
if (! ok)
continue;
pat = gen_rtx_SET (VOIDmode, regno_save_mem[regno][i],
gen_rtx_REG (GET_MODE (regno_save_mem[regno][i]),
regno));
code = reg_save_code[regno][i];
/* Set hard_regs_saved for all the registers we saved. */
for (k = 0; k < i; k++)
{
SET_HARD_REG_BIT (hard_regs_saved, regno + k);
n_regs_saved++;
}
numregs = i;
break;
}
insert_one_insn (chain, before_p, code, pat);
/* Tell our callers how many extra registers we saved/restored */
return numregs - 1;
}
/* Emit a new caller-save insn and set the code. */
static void
insert_one_insn (chain, before_p, code, pat)
struct insn_chain *chain;
int before_p;
enum insn_code code;
rtx pat;
{
rtx insn = chain->insn;
struct insn_chain *new;
#ifdef HAVE_cc0
/* If INSN references CC0, put our insns in front of the insn that sets
CC0. This is always safe, since the only way we could be passed an
insn that references CC0 is for a restore, and doing a restore earlier
isn't a problem. We do, however, assume here that CALL_INSNs don't
reference CC0. Guard against non-INSN's like CODE_LABEL. */
if ((GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN)
&& before_p
&& reg_referenced_p (cc0_rtx, PATTERN (insn)))
chain = chain->prev, insn = chain->insn;
#endif
new = new_insn_chain ();
if (before_p)
{
new->prev = chain->prev;
if (new->prev != 0)
new->prev->next = new;
else
reload_insn_chain = new;
chain->prev = new;
new->next = chain;
new->insn = emit_insn_before (pat, insn);
/* ??? It would be nice if we could exclude the already / still saved
registers from the live sets. */
COPY_REG_SET (new->live_before, chain->live_before);
COPY_REG_SET (new->live_after, chain->live_before);
if (chain->insn == BLOCK_HEAD (chain->block))
BLOCK_HEAD (chain->block) = new->insn;
}
else
{
new->next = chain->next;
if (new->next != 0)
new->next->prev = new;
chain->next = new;
new->prev = chain;
new->insn = emit_insn_after (pat, insn);
/* ??? It would be nice if we could exclude the already / still saved
registers from the live sets, and observe REG_UNUSED notes. */
COPY_REG_SET (new->live_before, chain->live_after);
COPY_REG_SET (new->live_after, chain->live_after);
if (chain->insn == BLOCK_END (chain->block))
BLOCK_END (chain->block) = new->insn;
}
new->block = chain->block;
new->is_caller_save_insn = 1;
INSN_CODE (new->insn) = code;
}

3743
gcc_arm/calls.c Executable file

File diff suppressed because it is too large Load Diff

674
gcc_arm/cccp.1 Executable file
View File

@ -0,0 +1,674 @@
.\" Copyright (c) 1991, 1992, 1993 Free Software Foundation \-*-Text-*-
.\" See section COPYING for conditions for redistribution
.TH cpp 1 "30apr1993" "GNU Tools" "GNU Tools"
.SH NAME
cccp, cpp \- The GNU C-Compatible Compiler Preprocessor.
.SH SYNOPSIS
.hy 0
.na
.TP
.B cccp
.RB "[\|" \-$ "\|]"
.RB "[\|" \-A \c
.I predicate\c
.RB [ (\c
.I value\c
.BR ) ]\|]
.RB "[\|" \-C "\|]"
.RB "[\|" \-D \c
.I name\c
.RB [ =\c
.I definition\c
\&]\|]
.RB "[\|" \-dD "\|]"
.RB "[\|" \-dM "\|]"
.RB "[\|" "\-I\ "\c
.I directory\c
\&\|]
.RB "[\|" \-H "\|]"
.RB "[\|" \-I\- "\|]"
.RB "[\|" "\-imacros\ "\c
.I file\c
\&\|]
.RB "[\|" "\-include\ "\c
.I file\c
\&\|]
.RB "[\|" "\-idirafter\ "\c
.I dir\c
\&\|]
.RB "[\|" "\-iprefix\ "\c
.I prefix\c
\&\|]
.RB "[\|" "\-iwithprefix\ "\c
.I dir\c
\&\|]
.RB "[\|" \-lang\-c "\|]"
.RB "[\|" \-lang\-c++ "\|]"
.RB "[\|" \-lang\-objc "\|]"
.RB "[\|" \-lang\-objc++ "\|]"
.RB "[\|" \-lint "\|]"
.RB "[\|" \-M\ [ \-MG "\|]]"
.RB "[\|" \-MM\ [ \-MG "\|]]"
.RB "[\|" \-MD\ \c
.I file\ \c
\&\|]
.RB "[\|" \-MMD\ \c
.I file\ \c
\&\|]
.RB "[\|" \-nostdinc "\|]"
.RB "[\|" \-nostdinc++ "\|]"
.RB "[\|" \-P "\|]"
.RB "[\|" \-pedantic "\|]"
.RB "[\|" \-pedantic\-errors "\|]"
.RB "[\|" \-traditional "\|]"
.RB "[\|" \-trigraphs "\|]"
.RB "[\|" \-U \c
.I name\c
\&\|]
.RB "[\|" \-undef "\|]"
.RB "[\|" \-Wtrigraphs "\|]"
.RB "[\|" \-Wcomment "\|]"
.RB "[\|" \-Wall "\|]"
.RB "[\|" \-Wtraditional "\|]"
.br
.RB "[\|" \c
.I infile\c
.RB | \- "\|]"
.RB "[\|" \c
.I outfile\c
.RB | \- "\|]"
.ad b
.hy 1
.SH DESCRIPTION
The C preprocessor is a \c
.I macro processor\c
\& that is used automatically by
the C compiler to transform your program before actual compilation. It is
called a macro processor because it allows you to define \c
.I macros\c
\&,
which are brief abbreviations for longer constructs.
The C preprocessor provides four separate facilities that you can use as
you see fit:
.TP
\(bu
Inclusion of header files. These are files of declarations that can be
substituted into your program.
.TP
\(bu
Macro expansion. You can define \c
.I macros\c
\&, which are abbreviations
for arbitrary fragments of C code, and then the C preprocessor will
replace the macros with their definitions throughout the program.
.TP
\(bu
Conditional compilation. Using special preprocessing directives, you
can include or exclude parts of the program according to various
conditions.
.TP
\(bu
Line control. If you use a program to combine or rearrange source files into
an intermediate file which is then compiled, you can use line control
to inform the compiler of where each source line originally came from.
.PP
C preprocessors vary in some details. For a full explanation of the
GNU C preprocessor, see the
.B info
file `\|\c
.B cpp.info\c
\&\|', or the manual
.I The C Preprocessor\c
\&. Both of these are built from the same documentation source file, `\|\c
.B cpp.texinfo\c
\&\|'. The GNU C
preprocessor provides a superset of the features of ANSI Standard C.
ANSI Standard C requires the rejection of many harmless constructs commonly
used by today's C programs. Such incompatibility would be inconvenient for
users, so the GNU C preprocessor is configured to accept these constructs
by default. Strictly speaking, to get ANSI Standard C, you must use the
options `\|\c
.B \-trigraphs\c
\&\|', `\|\c
.B \-undef\c
\&\|' and `\|\c
.B \-pedantic\c
\&\|', but in
practice the consequences of having strict ANSI Standard C make it
undesirable to do this.
Most often when you use the C preprocessor you will not have to invoke it
explicitly: the C compiler will do so automatically. However, the
preprocessor is sometimes useful individually.
When you call the preprocessor individually, either name
(\c
.B cpp\c
\& or \c
.B cccp\c
\&) will do\(em\&they are completely synonymous.
The C preprocessor expects two file names as arguments, \c
.I infile\c
\& and
\c
.I outfile\c
\&. The preprocessor reads \c
.I infile\c
\& together with any other
files it specifies with `\|\c
.B #include\c
\&\|'. All the output generated by the
combined input files is written in \c
.I outfile\c
\&.
Either \c
.I infile\c
\& or \c
.I outfile\c
\& may be `\|\c
.B \-\c
\&\|', which as \c
.I infile\c
\&
means to read from standard input and as \c
.I outfile\c
\& means to write to
standard output. Also, if \c
.I outfile\c
\& or both file names are omitted,
the standard output and standard input are used for the omitted file names.
.SH OPTIONS
Here is a table of command options accepted by the C preprocessor.
These options can also be given when compiling a C program; they are
passed along automatically to the preprocessor when it is invoked by
the compiler.
.TP
.B \-P
Inhibit generation of `\|\c
.B #\c
\&\|'-lines with line-number information in
the output from the preprocessor. This might be
useful when running the preprocessor on something that is not C code
and will be sent to a program which might be confused by the
`\|\c
.B #\c
\&\|'-lines.
.TP
.B \-C
Do not discard comments: pass them through to the output file.
Comments appearing in arguments of a macro call will be copied to the
output before the expansion of the macro call.
.TP
.B \-traditional
Try to imitate the behavior of old-fashioned C, as opposed to ANSI C.
.TP
.B \-trigraphs
Process ANSI standard trigraph sequences. These are three-character
sequences, all starting with `\|\c
.B ??\c
\&\|', that are defined by ANSI C to
stand for single characters. For example, `\|\c
.B ??/\c
\&\|' stands for
`\|\c
.BR "\e" "\|',"
so `\|\c
.B '??/n'\c
\&\|' is a character constant for a newline.
Strictly speaking, the GNU C preprocessor does not support all
programs in ANSI Standard C unless `\|\c
.B \-trigraphs\c
\&\|' is used, but if
you ever notice the difference it will be with relief.
You don't want to know any more about trigraphs.
.TP
.B \-pedantic
Issue warnings required by the ANSI C standard in certain cases such
as when text other than a comment follows `\|\c
.B #else\c
\&\|' or `\|\c
.B #endif\c
\&\|'.
.TP
.B \-pedantic\-errors
Like `\|\c
.B \-pedantic\c
\&\|', except that errors are produced rather than
warnings.
.TP
.B \-Wtrigraphs
Warn if any trigraphs are encountered (assuming they are enabled).
.TP
.B \-Wcomment
.TP
.B \-Wcomments
Warn whenever a comment-start sequence `\|\c
.B /*\c
\&\|' appears in a comment.
(Both forms have the same effect).
.TP
.B \-Wall
Requests both `\|\c
.B \-Wtrigraphs\c
\&\|' and `\|\c
.B \-Wcomment\c
\&\|' (but not
`\|\c
.B \-Wtraditional\c
\&\|').
.TP
.B \-Wtraditional
Warn about certain constructs that behave differently in traditional and
ANSI C.
.TP
.BI "\-I " directory\c
\&
Add the directory \c
.I directory\c
\& to the end of the list of
directories to be searched for header files.
This can be used to override a system header file, substituting your
own version, since these directories are searched before the system
header file directories. If you use more than one `\|\c
.B \-I\c
\&\|' option,
the directories are scanned in left-to-right order; the standard
system directories come after.
.TP
.B \-I\-
Any directories specified with `\|\c
.B \-I\c
\&\|' options before the `\|\c
.B \-I\-\c
\&\|'
option are searched only for the case of `\|\c
.B #include "\c
.I file\c
\&"\c
\&\|';
they are not searched for `\|\c
.B #include <\c
.I file\c
\&>\c
\&\|'.
If additional directories are specified with `\|\c
.B \-I\c
\&\|' options after
the `\|\c
.B \-I\-\c
\&\|', these directories are searched for all `\|\c
.B #include\c
\&\|'
directives.
In addition, the `\|\c
.B \-I\-\c
\&\|' option inhibits the use of the current
directory as the first search directory for `\|\c
.B #include "\c
.I file\c
\&"\c
\&\|'.
Therefore, the current directory is searched only if it is requested
explicitly with `\|\c
.B \-I.\c
\&\|'. Specifying both `\|\c
.B \-I\-\c
\&\|' and `\|\c
.B \-I.\c
\&\|'
allows you to control precisely which directories are searched before
the current one and which are searched after.
.TP
.B \-nostdinc
Do not search the standard system directories for header files.
Only the directories you have specified with `\|\c
.B \-I\c
\&\|' options
(and the current directory, if appropriate) are searched.
.TP
.B \-nostdinc++
Do not search for header files in the C++ specific standard
directories, but do still search the other standard directories.
(This option is used when building libg++.)
.TP
.BI "\-D " "name"\c
\&
Predefine \c
.I name\c
\& as a macro, with definition `\|\c
.B 1\c
\&\|'.
.TP
.BI "\-D " "name" = definition
\&
Predefine \c
.I name\c
\& as a macro, with definition \c
.I definition\c
\&.
There are no restrictions on the contents of \c
.I definition\c
\&, but if
you are invoking the preprocessor from a shell or shell-like program
you may need to use the shell's quoting syntax to protect characters
such as spaces that have a meaning in the shell syntax. If you use more than
one `\|\c
.B \-D\c
\&\|' for the same
.I name\c
\&, the rightmost definition takes effect.
.TP
.BI "\-U " "name"\c
\&
Do not predefine \c
.I name\c
\&. If both `\|\c
.B \-U\c
\&\|' and `\|\c
.B \-D\c
\&\|' are
specified for one name, the `\|\c
.B \-U\c
\&\|' beats the `\|\c
.B \-D\c
\&\|' and the name
is not predefined.
.TP
.B \-undef
Do not predefine any nonstandard macros.
.TP
.BI "\-A " "name(" value )
Assert (in the same way as the \c
.B #assert\c
\& directive)
the predicate \c
.I name\c
\& with tokenlist \c
.I value\c
\&. Remember to escape or quote the parentheses on
shell command lines.
You can use `\|\c
.B \-A-\c
\&\|' to disable all predefined assertions; it also
undefines all predefined macros.
.TP
.B \-dM
Instead of outputting the result of preprocessing, output a list of
`\|\c
.B #define\c
\&\|' directives for all the macros defined during the
execution of the preprocessor, including predefined macros. This gives
you a way of finding out what is predefined in your version of the
preprocessor; assuming you have no file `\|\c
.B foo.h\c
\&\|', the command
.sp
.br
touch\ foo.h;\ cpp\ \-dM\ foo.h
.br
.sp
will show the values of any predefined macros.
.TP
.B \-dD
Like `\|\c
.B \-dM\c
\&\|' except in two respects: it does \c
.I not\c
\& include the
predefined macros, and it outputs \c
.I both\c
\& the `\|\c
.B #define\c
\&\|'
directives and the result of preprocessing. Both kinds of output go to
the standard output file.
.PP
.TP
.BR \-M\ [ \-MG ]
Instead of outputting the result of preprocessing, output a rule
suitable for \c
.B make\c
\& describing the dependencies of the main
source file. The preprocessor outputs one \c
.B make\c
\& rule containing
the object file name for that source file, a colon, and the names of
all the included files. If there are many included files then the
rule is split into several lines using `\|\c
.B \\\\\c
\&\|'-newline.
`\|\c
.B \-MG\c
\&\|' says to treat missing header files as generated files and assume \c
they live in the same directory as the source file. It must be specified \c
in addition to `\|\c
.B \-M\c
\&\|'.
This feature is used in automatic updating of makefiles.
.TP
.BR \-MM\ [ \-MG ]
Like `\|\c
.B \-M\c
\&\|' but mention only the files included with `\|\c
.B #include
"\c
.I file\c
\&"\c
\&\|'. System header files included with `\|\c
.B #include
<\c
.I file\c
\&>\c
\&\|' are omitted.
.TP
.BI \-MD\ file
Like `\|\c
.B \-M\c
\&\|' but the dependency information is written to `\|\c
.I file\c
\&\|'. This is in addition to compiling the file as
specified\(em\&`\|\c
.B \-MD\c
\&\|' does not inhibit ordinary compilation the way
`\|\c
.B \-M\c
\&\|' does.
When invoking gcc, do not specify the `\|\c
.I file\c
\&\|' argument. Gcc will create file names made by replacing `\|\c
.B .c\c
\&\|' with `\|\c
.B .d\c
\&\|' at the end of the input file names.
In Mach, you can use the utility \c
.B md\c
\& to merge multiple files
into a single dependency file suitable for using with the `\|\c
.B make\c
\&\|'
command.
.TP
.BI \-MMD\ file
Like `\|\c
.B \-MD\c
\&\|' except mention only user header files, not system
header files.
.TP
.B \-H
Print the name of each header file used, in addition to other normal
activities.
.TP
.BI "\-imacros " "file"\c
\&
Process \c
.I file\c
\& as input, discarding the resulting output, before
processing the regular input file. Because the output generated from
\c
.I file\c
\& is discarded, the only effect of `\|\c
.B \-imacros \c
.I file\c
\&\c
\&\|' is to
make the macros defined in \c
.I file\c
\& available for use in the main
input. The preprocessor evaluates any `\|\c
.B \-D\c
\&\|' and `\|\c
.B \-U\c
\&\|' options
on the command line before processing `\|\c
.B \-imacros \c
.I file\c
\&\|' \c
\&.
.TP
.BI "\-include " "file"
Process
.I file
as input, and include all the resulting output,
before processing the regular input file.
.TP
.BI "-idirafter " "dir"\c
\&
Add the directory \c
.I dir\c
\& to the second include path. The directories
on the second include path are searched when a header file is not found
in any of the directories in the main include path (the one that
`\|\c
.B \-I\c
\&\|' adds to).
.TP
.BI "-iprefix " "prefix"\c
\&
Specify \c
.I prefix\c
\& as the prefix for subsequent `\|\c
.B \-iwithprefix\c
\&\|'
options.
.TP
.BI "-iwithprefix " "dir"\c
\&
Add a directory to the second include path. The directory's name is
made by concatenating \c
.I prefix\c
\& and \c
.I dir\c
\&, where \c
.I prefix\c
\&
was specified previously with `\|\c
.B \-iprefix\c
\&\|'.
.TP
.B \-lang-c
.TP
.B \-lang-c++
.TP
.B \-lang-objc
.TP
.B \-lang-objc++
Specify the source language. `\|\c
.B \-lang-c++\c
\&\|' makes the preprocessor
handle C++ comment syntax, and includes extra default include
directories for C++, and `\|\c
.B \-lang-objc\c
\&\|' enables the Objective C
`\|\c
.B #import\c
\&\|' directive. `\|\c
.B \-lang-c\c
\&\|' explicitly turns off both of
these extensions, and `\|\c
.B \-lang-objc++\c
\&\|' enables both.
These options are generated by the compiler driver \c
.B gcc\c
\&, but not
passed from the `\|\c
.B gcc\c
\&\|' command line.
.TP
.B \-lint
Look for commands to the program checker \c
.B lint\c
\& embedded in
comments, and emit them preceded by `\|\c
.B #pragma lint\c
\&\|'. For example,
the comment `\|\c
.B /* NOTREACHED */\c
\&\|' becomes `\|\c
.B #pragma lint
NOTREACHED\c
\&\|'.
This option is available only when you call \c
.B cpp\c
\& directly;
\c
.B gcc\c
\& will not pass it from its command line.
.TP
.B \-$
Forbid the use of `\|\c
.B $\c
\&\|' in identifiers. This was formerly required for strict conformance
to the C Standard before the standard was corrected. \c
This option is available only when you call \c
.B cpp\c
\& directly;
.B gcc\c
\& will not pass it from its command line.
.SH "SEE ALSO"
.RB "`\|" Cpp "\|'"
entry in
.B info\c
\&;
.I The C Preprocessor\c
, Richard M. Stallman.
.br
.BR gcc "(" 1 ");"
.RB "`\|" Gcc "\|'"
entry in
.B info\c
\&;
.I
Using and Porting GNU CC (for version 2.0)\c
, Richard M. Stallman.
.SH COPYING
Copyright (c) 1991, 1992, 1993 Free Software Foundation, Inc.
.PP
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
are preserved on all copies.
.PP
Permission is granted to copy and distribute modified versions of this
manual under the conditions for verbatim copying, provided that the
entire resulting derived work is distributed under the terms of a
permission notice identical to this one.
.PP
Permission is granted to copy and distribute translations of this
manual into another language, under the above conditions for modified
versions, except that this permission notice may be included in
translations approved by the Free Software Foundation instead of in
the original English.

11450
gcc_arm/cccp.c Executable file

File diff suppressed because it is too large Load Diff

1248
gcc_arm/cexp.y Executable file

File diff suppressed because it is too large Load Diff

12112
gcc_arm/combine.c Executable file

File diff suppressed because it is too large Load Diff

118
gcc_arm/conditions.h Executable file
View File

@ -0,0 +1,118 @@
/* Definitions for condition code handling in final.c and output routines.
Copyright (C) 1987 Free Software Foundation, Inc.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* None of the things in the files exist if we don't use CC0. */
#ifdef HAVE_cc0
/* The variable cc_status says how to interpret the condition code.
It is set by output routines for an instruction that sets the cc's
and examined by output routines for jump instructions.
cc_status contains two components named `value1' and `value2'
that record two equivalent expressions for the values that the
condition codes were set from. (Either or both may be null if
there is no useful expression to record.) These fields are
used for eliminating redundant test and compare instructions
in the cases where the condition codes were already set by the
previous instruction.
cc_status.flags contains flags which say that the condition codes
were set in a nonstandard manner. The output of jump instructions
uses these flags to compensate and produce the standard result
with the nonstandard condition codes. Standard flags are defined here.
The tm.h file can also define other machine-dependent flags.
cc_status also contains a machine-dependent component `mdep'
whose type, `CC_STATUS_MDEP', may be defined as a macro in the
tm.h file. */
#ifndef CC_STATUS_MDEP
#define CC_STATUS_MDEP int
#endif
#ifndef CC_STATUS_MDEP_INIT
#define CC_STATUS_MDEP_INIT 0
#endif
typedef struct {int flags; rtx value1, value2; CC_STATUS_MDEP mdep;} CC_STATUS;
/* While outputting an insn as assembler code,
this is the status BEFORE that insn. */
extern CC_STATUS cc_prev_status;
/* While outputting an insn as assembler code,
this is being altered to the status AFTER that insn. */
extern CC_STATUS cc_status;
/* These are the machine-independent flags: */
/* Set if the sign of the cc value is inverted:
output a following jump-if-less as a jump-if-greater, etc. */
#define CC_REVERSED 1
/* This bit means that the current setting of the N bit is bogus
and conditional jumps should use the Z bit in its place.
This state obtains when an extraction of a signed single-bit field
or an arithmetic shift right of a byte by 7 bits
is turned into a btst, because btst does not set the N bit. */
#define CC_NOT_POSITIVE 2
/* This bit means that the current setting of the N bit is bogus
and conditional jumps should pretend that the N bit is clear.
Used after extraction of an unsigned bit
or logical shift right of a byte by 7 bits is turned into a btst.
The btst does not alter the N bit, but the result of that shift
or extract is never negative. */
#define CC_NOT_NEGATIVE 4
/* This bit means that the current setting of the overflow flag
is bogus and conditional jumps should pretend there is no overflow. */
/* ??? Note that for most targets this macro is misnamed as it applies
to the carry flag, not the overflow flag. */
#define CC_NO_OVERFLOW 010
/* This bit means that what ought to be in the Z bit
should be tested as the complement of the N bit. */
#define CC_Z_IN_NOT_N 020
/* This bit means that what ought to be in the Z bit
should be tested as the N bit. */
#define CC_Z_IN_N 040
/* Nonzero if we must invert the sense of the following branch, i.e.
change EQ to NE. This is not safe for IEEE floating point operations!
It is intended for use only when a combination of arithmetic
or logical insns can leave the condition codes set in a fortuitous
(though inverted) state. */
#define CC_INVERTED 0100
/* Nonzero if we must convert signed condition operators to unsigned.
This is only used by machine description files. */
#define CC_NOT_SIGNED 0200
/* This is how to initialize the variable cc_status.
final does this at appropriate moments. */
#define CC_STATUS_INIT \
(cc_status.flags = 0, cc_status.value1 = 0, cc_status.value2 = 0, \
CC_STATUS_MDEP_INIT)
#endif

4
gcc_arm/config.guess vendored Executable file
View File

@ -0,0 +1,4 @@
#!/bin/sh
# Use the top-level config.guess so that we don't have two of them.
guesssys=`echo $0 | sed 's|config.guess|../config.guess|'`
exec ${guesssys} "$@"

12
gcc_arm/config.h Normal file
View File

@ -0,0 +1,12 @@
#include "auto-host.h"
#include "gansidecl.h"
#include "i386/xm-i386.h"
#ifndef HAVE_ATEXIT
#define HAVE_ATEXIT
#endif
#ifndef POSIX
#define POSIX
#endif
#ifndef BSTRING
#define BSTRING
#endif

240
gcc_arm/config.in Executable file
View File

@ -0,0 +1,240 @@
/* config.in. Generated automatically from configure.in by autoheader. */
/* Define if you can safely include both <string.h> and <strings.h>. */
#undef STRING_WITH_STRINGS
/* Define if printf supports "%p". */
#undef HAVE_PRINTF_PTR
/* Define if you want expensive run-time checks. */
#undef ENABLE_CHECKING
/* Define if your cpp understands the stringify operator. */
#undef HAVE_CPP_STRINGIFY
/* Define if your compiler understands volatile. */
#undef HAVE_VOLATILE
/* Define if your assembler supports specifying the maximum number
of bytes to skip when using the GAS .p2align command. */
#undef HAVE_GAS_MAX_SKIP_P2ALIGN
/* Define if your assembler supports .balign and .p2align. */
#undef HAVE_GAS_BALIGN_AND_P2ALIGN
/* Define if your assembler supports .subsection and .subsection -1 starts
emitting at the beginning of your section */
#undef HAVE_GAS_SUBSECTION_ORDERING
/* Define if you have a working <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Whether malloc must be declared even if <stdlib.h> is included. */
#undef NEED_DECLARATION_MALLOC
/* Whether realloc must be declared even if <stdlib.h> is included. */
#undef NEED_DECLARATION_REALLOC
/* Whether calloc must be declared even if <stdlib.h> is included. */
#undef NEED_DECLARATION_CALLOC
/* Whether free must be declared even if <stdlib.h> is included. */
#undef NEED_DECLARATION_FREE
/* Whether bcopy must be declared even if <string.h> is included. */
#undef NEED_DECLARATION_BCOPY
/* Whether bcmp must be declared even if <string.h> is included. */
#undef NEED_DECLARATION_BCMP
/* Whether bzero must be declared even if <string.h> is included. */
#undef NEED_DECLARATION_BZERO
/* Whether index must be declared even if <string.h> is included. */
#undef NEED_DECLARATION_INDEX
/* Whether rindex must be declared even if <string.h> is included. */
#undef NEED_DECLARATION_RINDEX
/* Whether getenv must be declared even if <stdlib.h> is included. */
#undef NEED_DECLARATION_GETENV
/* Whether atol must be declared even if <stdlib.h> is included. */
#undef NEED_DECLARATION_ATOL
/* Whether sbrk must be declared even if <stdlib.h> is included. */
#undef NEED_DECLARATION_SBRK
/* Whether abort must be declared even if <stdlib.h> is included. */
#undef NEED_DECLARATION_ABORT
/* Whether strerror must be declared even if <string.h> is included. */
#undef NEED_DECLARATION_STRERROR
/* Whether strsignal must be declared even if <string.h> is included. */
#undef NEED_DECLARATION_STRSIGNAL
/* Whether getcwd must be declared even if <unistd.h> is included. */
#undef NEED_DECLARATION_GETCWD
/* Whether getwd must be declared even if <unistd.h> is included. */
#undef NEED_DECLARATION_GETWD
/* Whether getrlimit must be declared even if <sys/resource.h> is included. */
#undef NEED_DECLARATION_GETRLIMIT
/* Whether setrlimit must be declared even if <sys/resource.h> is included. */
#undef NEED_DECLARATION_SETRLIMIT
/* Define if you want expensive run-time checks. */
#undef ENABLE_CHECKING
/* Define to enable the use of a default assembler. */
#undef DEFAULT_ASSEMBLER
/* Define to enable the use of a default linker. */
#undef DEFAULT_LINKER
/* Define if you don't have vprintf but do have _doprnt. */
#undef HAVE_DOPRNT
/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
#undef HAVE_SYS_WAIT_H
/* Define if you have <vfork.h>. */
#undef HAVE_VFORK_H
/* Define if you have the vprintf function. */
#undef HAVE_VPRINTF
/* Define to `int' if <sys/types.h> doesn't define. */
#undef pid_t
/* Define if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define if `sys_siglist' is declared by <signal.h>. */
#undef SYS_SIGLIST_DECLARED
/* Define if you can safely include both <sys/time.h> and <time.h>. */
#undef TIME_WITH_SYS_TIME
/* Define vfork as fork if vfork does not work. */
#undef vfork
/* Define if you have the atoll function. */
#undef HAVE_ATOLL
/* Define if you have the atoq function. */
#undef HAVE_ATOQ
/* Define if you have the bcmp function. */
#undef HAVE_BCMP
/* Define if you have the bcopy function. */
#undef HAVE_BCOPY
/* Define if you have the bsearch function. */
#undef HAVE_BSEARCH
/* Define if you have the bzero function. */
#undef HAVE_BZERO
/* Define if you have the fputc_unlocked function. */
#undef HAVE_FPUTC_UNLOCKED
/* Define if you have the fputs_unlocked function. */
#undef HAVE_FPUTS_UNLOCKED
/* Define if you have the getrlimit function. */
#undef HAVE_GETRLIMIT
/* Define if you have the gettimeofday function. */
#undef HAVE_GETTIMEOFDAY
/* Define if you have the index function. */
#undef HAVE_INDEX
/* Define if you have the isascii function. */
#undef HAVE_ISASCII
/* Define if you have the kill function. */
#undef HAVE_KILL
/* Define if you have the popen function. */
#undef HAVE_POPEN
/* Define if you have the putc_unlocked function. */
#undef HAVE_PUTC_UNLOCKED
/* Define if you have the putenv function. */
#undef HAVE_PUTENV
/* Define if you have the rindex function. */
#undef HAVE_RINDEX
/* Define if you have the setrlimit function. */
#undef HAVE_SETRLIMIT
/* Define if you have the strchr function. */
#undef HAVE_STRCHR
/* Define if you have the strerror function. */
#undef HAVE_STRERROR
/* Define if you have the strrchr function. */
#undef HAVE_STRRCHR
/* Define if you have the strsignal function. */
#undef HAVE_STRSIGNAL
/* Define if you have the strtoul function. */
#undef HAVE_STRTOUL
/* Define if you have the sysconf function. */
#undef HAVE_SYSCONF
/* Define if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H
/* Define if you have the <limits.h> header file. */
#undef HAVE_LIMITS_H
/* Define if you have the <stab.h> header file. */
#undef HAVE_STAB_H
/* Define if you have the <stddef.h> header file. */
#undef HAVE_STDDEF_H
/* Define if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define if you have the <sys/file.h> header file. */
#undef HAVE_SYS_FILE_H
/* Define if you have the <sys/param.h> header file. */
#undef HAVE_SYS_PARAM_H
/* Define if you have the <sys/resource.h> header file. */
#undef HAVE_SYS_RESOURCE_H
/* Define if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define if you have the <sys/time.h> header file. */
#undef HAVE_SYS_TIME_H
/* Define if you have the <sys/times.h> header file. */
#undef HAVE_SYS_TIMES_H
/* Define if you have the <time.h> header file. */
#undef HAVE_TIME_H
/* Define if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H

1225
gcc_arm/config.sub vendored Executable file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,742 @@
Arm / Thumb Interworking
========================
The Cygnus GNU Pro Toolkit for the ARM7T processor supports function
calls between code compiled for the ARM instruction set and code
compiled for the Thumb instruction set and vice versa. This document
describes how that interworking support operates and explains the
command line switches that should be used in order to produce working
programs.
Note: The Cygnus GNU Pro Toolkit does not support switching between
compiling for the ARM instruction set and the Thumb instruction set
on anything other than a per file basis. There are in fact two
completely separate compilers, one that produces ARM assembler
instructions and one that produces Thumb assembler instructions. The
two compilers share the same assembler, linker and so on.
1. Explicit interworking support for C and C++ files
====================================================
By default if a file is compiled without any special command line
switches then the code produced will not support interworking.
Provided that a program is made up entirely from object files and
libraries produced in this way and which contain either exclusively
ARM instructions or exclusively Thumb instructions then this will not
matter and a working executable will be created. If an attempt is
made to link together mixed ARM and Thumb object files and libraries,
then warning messages will be produced by the linker and a non-working
executable will be created.
In order to produce code which does support interworking it should be
compiled with the
-mthumb-interwork
command line option. Provided that a program is made up entirely from
object files and libraries built with this command line switch a
working executable will be produced, even if both ARM and Thumb
instructions are used by the various components of the program. (No
warning messages will be produced by the linker either).
Note that specifying -mthumb-interwork does result in slightly larger,
slower code being produced. This is why interworking support must be
specifically enabled by a switch.
2. Explicit interworking support for assembler files
====================================================
If assembler files are to be included into an interworking program
then the following rules must be obeyed:
* Any externally visible functions must return by using the BX
instruction.
* Normal function calls can just use the BL instruction. The
linker will automatically insert code to switch between ARM
and Thumb modes as necessary.
* Calls via function pointers should use the BX instruction if
the call is made in ARM mode:
.code 32
mov lr, pc
bx rX
This code sequence will not work in Thumb mode however, since
the mov instruction will not set the bottom bit of the lr
register. Instead a branch-and-link to the _call_via_rX
functions should be used instead:
.code 16
bl _call_via_rX
where rX is replaced by the name of the register containing
the function address.
* All externally visible functions which should be entered in
Thumb mode must have the .thumb_func pseudo op specified just
before their entry point. eg:
.code 16
.global function
.thumb_func
function:
...start of function....
* All assembler files must be assembled with the switch
-mthumb-interwork specified on the command line. (If the file
is assembled by calling gcc it will automatically pass on the
-mthumb-interwork switch to the assembler, provided that it
was specified on the gcc command line in the first place.)
3. Support for old, non-interworking aware code.
================================================
If it is necessary to link together code produced by an older,
non-interworking aware compiler, or code produced by the new compiler
but without the -mthumb-interwork command line switch specified, then
there are two command line switches that can be used to support this.
The switch
-mcaller-super-interworking
will allow calls via function pointers in Thumb mode to work,
regardless of whether the function pointer points to old,
non-interworking aware code or not. Specifying this switch does
produce slightly slower code however.
Note: There is no switch to allow calls via function pointers in ARM
mode to be handled specially. Calls via function pointers from
interworking aware ARM code to non-interworking aware ARM code work
without any special considerations by the compiler. Calls via
function pointers from interworking aware ARM code to non-interworking
aware Thumb code however will not work. (Actually under some
circumstances they may work, but there are no guarantees). This is
because only the new compiler is able to produce Thumb code, and this
compiler already has a command line switch to produce interworking
aware code.
The switch
-mcallee-super-interworking
will allow non-interworking aware ARM or Thumb code to call Thumb
functions, either directly or via function pointers. Specifying this
switch does produce slightly larger, slower code however.
Note: There is no switch to allow non-interworking aware ARM or Thumb
code to call ARM functions. There is no need for any special handling
of calls from non-interworking aware ARM code to interworking aware
ARM functions, they just work normally. Calls from non-interworking
aware Thumb functions to ARM code however, will not work. There is no
option to support this, since it is always possible to recompile the
Thumb code to be interworking aware.
As an alternative to the command line switch
-mcallee-super-interworking, which affects all externally visible
functions in a file, it is possible to specify an attribute or
declspec for individual functions, indicating that that particular
function should support being called by non-interworking aware code.
The function should be defined like this:
int __attribute__((interfacearm)) function
{
... body of function ...
}
or
int __declspec(interfacearm) function
{
... body of function ...
}
4. Interworking support in dlltool
==================================
It is possible to create DLLs containing mixed ARM and Thumb code. It
is also possible to call Thumb code in a DLL from an ARM program and
vice versa. It is even possible to call ARM DLLs that have been compiled
without interworking support (say by an older version of the compiler),
from Thumb programs and still have things work properly.
A version of the `dlltool' program which supports the `--interwork'
command line switch is needed, as well as the following special
considerations when building programs and DLLs:
*Use `-mthumb-interwork'*
When compiling files for a DLL or a program the `-mthumb-interwork'
command line switch should be specified if calling between ARM and
Thumb code can happen. If a program is being compiled and the
mode of the DLLs that it uses is not known, then it should be
assumed that interworking might occur and the switch used.
*Use `-m thumb'*
If the exported functions from a DLL are all Thumb encoded then the
`-m thumb' command line switch should be given to dlltool when
building the stubs. This will make dlltool create Thumb encoded
stubs, rather than its default of ARM encoded stubs.
If the DLL consists of both exported Thumb functions and exported
ARM functions then the `-m thumb' switch should not be used.
Instead the Thumb functions in the DLL should be compiled with the
`-mcallee-super-interworking' switch, or with the `interfacearm'
attribute specified on their prototypes. In this way they will be
given ARM encoded prologues, which will work with the ARM encoded
stubs produced by dlltool.
*Use `-mcaller-super-interworking'*
If it is possible for Thumb functions in a DLL to call
non-interworking aware code via a function pointer, then the Thumb
code must be compiled with the `-mcaller-super-interworking'
command line switch. This will force the function pointer calls
to use the _interwork_call_via_rX stub functions which will
correctly restore Thumb mode upon return from the called function.
*Link with `libgcc.a'*
When the dll is built it may have to be linked with the GCC
library (`libgcc.a') in order to extract the _call_via_rX functions
or the _interwork_call_via_rX functions. This represents a partial
redundancy since the same functions *may* be present in the
application itself, but since they only take up 372 bytes this
should not be too much of a consideration.
*Use `--support-old-code'*
When linking a program with an old DLL which does not support
interworking, the `--support-old-code' command line switch to the
linker should be used. This causes the linker to generate special
interworking stubs which can cope with old, non-interworking aware
ARM code, at the cost of generating bulkier code. The linker will
still generate a warning message along the lines of:
"Warning: input file XXX does not support interworking, whereas YYY does."
but this can now be ignored because the --support-old-code switch
has been used.
5. How interworking support works
=================================
Switching between the ARM and Thumb instruction sets is accomplished
via the BX instruction which takes as an argument a register name.
Control is transfered to the address held in this register (with the
bottom bit masked out), and if the bottom bit is set, then Thumb
instruction processing is enabled, otherwise ARM instruction
processing is enabled.
When the -mthumb-interwork command line switch is specified, gcc
arranges for all functions to return to their caller by using the BX
instruction. Thus provided that the return address has the bottom bit
correctly initialised to indicate the instruction set of the caller,
correct operation will ensue.
When a function is called explicitly (rather than via a function
pointer), the compiler generates a BL instruction to do this. The
Thumb version of the BL instruction has the special property of
setting the bottom bit of the LR register after it has stored the
return address into it, so that a future BX instruction will correctly
return the instruction after the BL instruction, in Thumb mode.
The BL instruction does not change modes itself however, so if an ARM
function is calling a Thumb function, or vice versa, it is necessary
to generate some extra instructions to handle this. This is done in
the linker when it is storing the address of the referenced function
into the BL instruction. If the BL instruction is an ARM style BL
instruction, but the referenced function is a Thumb function, then the
linker automatically generates a calling stub that converts from ARM
mode to Thumb mode, puts the address of this stub into the BL
instruction, and puts the address of the referenced function into the
stub. Similarly if the BL instruction is a Thumb BL instruction, and
the referenced function is an ARM function, the linker generates a
stub which converts from Thumb to ARM mode, puts the address of this
stub into the BL instruction, and the address of the referenced
function into the stub.
This is why it is necessary to mark Thumb functions with the
.thumb_func pseudo op when creating assembler files. This pseudo op
allows the assembler to distinguish between ARM functions and Thumb
functions. (The Thumb version of GCC automatically generates these
pseudo ops for any Thumb functions that it generates).
Calls via function pointers work differently. Whenever the address of
a function is taken, the linker examines the type of the function
being referenced. If the function is a Thumb function, then it sets
the bottom bit of the address. Technically this makes the address
incorrect, since it is now one byte into the start of the function,
but this is never a problem because:
a. with interworking enabled all calls via function pointer
are done using the BX instruction and this ignores the
bottom bit when computing where to go to.
b. the linker will always set the bottom bit when the address
of the function is taken, so it is never possible to take
the address of the function in two different places and
then compare them and find that they are not equal.
As already mentioned any call via a function pointer will use the BX
instruction (provided that interworking is enabled). The only problem
with this is computing the return address for the return from the
called function. For ARM code this can easily be done by the code
sequence:
mov lr, pc
bx rX
(where rX is the name of the register containing the function
pointer). This code does not work for the Thumb instruction set,
since the MOV instruction will not set the bottom bit of the LR
register, so that when the called function returns, it will return in
ARM mode not Thumb mode. Instead the compiler generates this
sequence:
bl _call_via_rX
(again where rX is the name if the register containing the function
pointer). The special call_via_rX functions look like this:
.thumb_func
_call_via_r0:
bx r0
nop
The BL instruction ensures that the correct return address is stored
in the LR register and then the BX instruction jumps to the address
stored in the function pointer, switch modes if necessary.
6. How caller-super-interworking support works
==============================================
When the -mcaller-super-interworking command line switch is specified
it changes the code produced by the Thumb compiler so that all calls
via function pointers (including virtual function calls) now go via a
different stub function. The code to call via a function pointer now
looks like this:
bl _interwork_call_via_r0
Note: The compiler does not insist that r0 be used to hold the
function address. Any register will do, and there are a suite of stub
functions, one for each possible register. The stub functions look
like this:
.code 16
.thumb_func
_interwork_call_via_r0
bx pc
nop
.code 32
tst r0, #1
stmeqdb r13!, {lr}
adreq lr, _arm_return
bx r0
The stub first switches to ARM mode, since it is a lot easier to
perform the necessary operations using ARM instructions. It then
tests the bottom bit of the register containing the address of the
function to be called. If this bottom bit is set then the function
being called uses Thumb instructions and the BX instruction to come
will switch back into Thumb mode before calling this function. (Note
that it does not matter how this called function chooses to return to
its caller, since the both the caller and callee are Thumb functions,
and mode switching is necessary). If the function being called is an
ARM mode function however, the stub pushes the return address (with
its bottom bit set) onto the stack, replaces the return address with
the address of the a piece of code called '_arm_return' and then
performs a BX instruction to call the function.
The '_arm_return' code looks like this:
.code 32
_arm_return:
ldmia r13!, {r12}
bx r12
.code 16
It simply retrieves the return address from the stack, and then
performs a BX operation to return to the caller and switch back into
Thumb mode.
7. How callee-super-interworking support works
==============================================
When -mcallee-super-interworking is specified on the command line the
Thumb compiler behaves as if every externally visible function that it
compiles has had the (interfacearm) attribute specified for it. What
this attribute does is to put a special, ARM mode header onto the
function which forces a switch into Thumb mode:
without __attribute__((interfacearm)):
.code 16
.thumb_func
function:
... start of function ...
with __attribute__((interfacearm)):
.code 32
function:
orr r12, pc, #1
bx r12
.code 16
.thumb_func
.real_start_of_function:
... start of function ...
Note that since the function now expects to be entered in ARM mode, it
no longer has the .thumb_func pseudo op specified for its name.
Instead the pseudo op is attached to a new label .real_start_of_<name>
(where <name> is the name of the function) which indicates the start
of the Thumb code. This does have the interesting side effect in that
if this function is now called from a Thumb mode piece of code
outsside of the current file, the linker will generate a calling stub
to switch from Thumb mode into ARM mode, and then this is immediately
overridden by the function's header which switches back into Thumb
mode.
In addition the (interfacearm) attribute also forces the function to
return by using the BX instruction, even if has not been compiled with
the -mthumb-interwork command line flag, so that the correct mode will
be restored upon exit from the function.
8. Some examples
================
Given these two test files:
int arm (void) { return 1 + thumb (); }
int thumb (void) { return 2 + arm (); }
The following pieces of assembler are produced by the ARM and Thumb
version of GCC depending upon the command line options used:
`-O2':
.code 32 .code 16
.global _arm .global _thumb
.thumb_func
_arm: _thumb:
mov ip, sp
stmfd sp!, {fp, ip, lr, pc} push {lr}
sub fp, ip, #4
bl _thumb bl _arm
add r0, r0, #1 add r0, r0, #2
ldmea fp, {fp, sp, pc} pop {pc}
Note how the functions return without using the BX instruction. If
these files were assembled and linked together they would fail to work
because they do not change mode when returning to their caller.
`-O2 -mthumb-interwork':
.code 32 .code 16
.global _arm .global _thumb
.thumb_func
_arm: _thumb:
mov ip, sp
stmfd sp!, {fp, ip, lr, pc} push {lr}
sub fp, ip, #4
bl _thumb bl _arm
add r0, r0, #1 add r0, r0, #2
ldmea fp, {fp, sp, lr} pop {r1}
bx lr bx r1
Now the functions use BX to return their caller. They have grown by
4 and 2 bytes respectively, but they can now successfully be linked
together and be expect to work. The linker will replace the
destinations of the two BL instructions with the addresses of calling
stubs which convert to the correct mode before jumping to the called
function.
`-O2 -mcallee-super-interworking':
.code 32 .code 32
.global _arm .global _thumb
_arm: _thumb:
orr r12, pc, #1
bx r12
mov ip, sp .code 16
stmfd sp!, {fp, ip, lr, pc} push {lr}
sub fp, ip, #4
bl _thumb bl _arm
add r0, r0, #1 add r0, r0, #2
ldmea fp, {fp, sp, lr} pop {r1}
bx lr bx r1
The thumb function now has an ARM encoded prologue, and it no longer
has the `.thumb-func' pseudo op attached to it. The linker will not
generate a calling stub for the call from arm() to thumb(), but it will
still have to generate a stub for the call from thumb() to arm(). Also
note how specifying `--mcallee-super-interworking' automatically
implies `-mthumb-interworking'.
9. Some Function Pointer Examples
=================================
Given this test file:
int func (void) { return 1; }
int call (int (* ptr)(void)) { return ptr (); }
The following varying pieces of assembler are produced by the Thumb
version of GCC depending upon the command line options used:
`-O2':
.code 16
.globl _func
.thumb_func
_func:
mov r0, #1
bx lr
.globl _call
.thumb_func
_call:
push {lr}
bl __call_via_r0
pop {pc}
Note how the two functions have different exit sequences. In
particular call() uses pop {pc} to return, which would not work if the
caller was in ARM mode. func() however, uses the BX instruction, even
though `-mthumb-interwork' has not been specified, as this is the most
efficient way to exit a function when the return address is held in the
link register.
`-O2 -mthumb-interwork':
.code 16
.globl _func
.thumb_func
_func:
mov r0, #1
bx lr
.globl _call
.thumb_func
_call:
push {lr}
bl __call_via_r0
pop {r1}
bx r1
This time both functions return by using the BX instruction. This
means that call() is now two bytes longer and several cycles slower
than the previous version.
`-O2 -mcaller-super-interworking':
.code 16
.globl _func
.thumb_func
_func:
mov r0, #1
bx lr
.globl _call
.thumb_func
_call:
push {lr}
bl __interwork_call_via_r0
pop {pc}
Very similar to the first (non-interworking) version, except that a
different stub is used to call via the function pointer. This new stub
will work even if the called function is not interworking aware, and
tries to return to call() in ARM mode. Note that the assembly code for
call() is still not interworking aware itself, and so should not be
called from ARM code.
`-O2 -mcallee-super-interworking':
.code 32
.globl _func
_func:
orr r12, pc, #1
bx r12
.code 16
.globl .real_start_of_func
.thumb_func
.real_start_of_func:
mov r0, #1
bx lr
.code 32
.globl _call
_call:
orr r12, pc, #1
bx r12
.code 16
.globl .real_start_of_call
.thumb_func
.real_start_of_call:
push {lr}
bl __call_via_r0
pop {r1}
bx r1
Now both functions have an ARM coded prologue, and both functions
return by using the BX instruction. These functions are interworking
aware therefore and can safely be called from ARM code. The code for
the call() function is now 10 bytes longer than the original, non
interworking aware version, an increase of over 200%.
If a prototype for call() is added to the source code, and this
prototype includes the `interfacearm' attribute:
int __attribute__((interfacearm)) call (int (* ptr)(void));
then this code is produced (with only -O2 specified on the command
line):
.code 16
.globl _func
.thumb_func
_func:
mov r0, #1
bx lr
.globl _call
.code 32
_call:
orr r12, pc, #1
bx r12
.code 16
.globl .real_start_of_call
.thumb_func
.real_start_of_call:
push {lr}
bl __call_via_r0
pop {r1}
bx r1
So now both call() and func() can be safely called via
non-interworking aware ARM code. If, when such a file is assembled,
the assembler detects the fact that call() is being called by another
function in the same file, it will automatically adjust the target of
the BL instruction to point to .real_start_of_call. In this way there
is no need for the linker to generate a Thumb-to-ARM calling stub so
that call can be entered in ARM mode.
10. How to use dlltool to build ARM/Thumb DLLs
==============================================
Given a program (`prog.c') like this:
extern int func_in_dll (void);
int main (void) { return func_in_dll(); }
And a DLL source file (`dll.c') like this:
int func_in_dll (void) { return 1; }
Here is how to build the DLL and the program for a purely ARM based
environment:
*Step One
Build a `.def' file describing the DLL:
; example.def
; This file describes the contents of the DLL
LIBRARY example
HEAPSIZE 0x40000, 0x2000
EXPORTS
func_in_dll 1
*Step Two
Compile the DLL source code:
arm-pe-gcc -O2 -c dll.c
*Step Three
Use `dlltool' to create an exports file and a library file:
dlltool --def example.def --output-exp example.o --output-lib example.a
*Step Four
Link together the complete DLL:
arm-pe-ld dll.o example.o -o example.dll
*Step Five
Compile the program's source code:
arm-pe-gcc -O2 -c prog.c
*Step Six
Link together the program and the DLL's library file:
arm-pe-gcc prog.o example.a -o prog
If instead this was a Thumb DLL being called from an ARM program, the
steps would look like this. (To save space only those steps that are
different from the previous version are shown):
*Step Two
Compile the DLL source code (using the Thumb compiler):
thumb-pe-gcc -O2 -c dll.c -mthumb-interwork
*Step Three
Build the exports and library files (and support interworking):
dlltool -d example.def -z example.o -l example.a --interwork -m thumb
*Step Five
Compile the program's source code (and support interworking):
arm-pe-gcc -O2 -c prog.c -mthumb-interwork
If instead, the DLL was an old, ARM DLL which does not support
interworking, and which cannot be rebuilt, then these steps would be
used.
*Step One
Skip. If you do not have access to the sources of a DLL, there is
no point in building a `.def' file for it.
*Step Two
Skip. With no DLL sources there is nothing to compile.
*Step Three
Skip. Without a `.def' file you cannot use dlltool to build an
exports file or a library file.
*Step Four
Skip. Without a set of DLL object files you cannot build the DLL.
Besides it has already been built for you by somebody else.
*Step Five
Compile the program's source code, this is the same as before:
arm-pe-gcc -O2 -c prog.c
*Step Six
Link together the program and the DLL's library file, passing the
`--support-old-code' option to the linker:
arm-pe-gcc prog.o example.a -Wl,--support-old-code -o prog
Ignore the warning message about the input file not supporting
interworking as the --support-old-code switch has taken care if this.

453
gcc_arm/config/arm/aof.h Executable file
View File

@ -0,0 +1,453 @@
/* Definitions of target machine for GNU compiler, for Advanced RISC Machines
ARM compilation, AOF Assembler.
Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
Contributed by Richard Earnshaw (rearnsha@armltd.co.uk)
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#define AOF_ASSEMBLER
#define LINK_LIBGCC_SPECIAL 1
#define LINK_SPEC "%{aof} %{bin} %{aif} %{ihf} %{shl,*} %{reent*} %{split} \
%{ov*,*} %{reloc*} -nodebug"
#define STARTFILE_SPEC "crtbegin.o%s"
#define ENDFILE_SPEC "crtend.o%s"
#ifndef ASM_SPEC
#define ASM_SPEC "%{g -g} -arch 4 \
-apcs 3%{mapcs-32:/32bit}%{mapcs-26:/26bit}%{!mapcs-26:%{!macps-32:/26bit}}"
#endif
#ifndef LIB_SPEC
#define LIB_SPEC "%{Eb: armlib_h.32b%s}%{!Eb: armlib_h.32l%s}"
#endif
#define LIBGCC_SPEC "libgcc.a%s"
/* Dividing the Output into Sections (Text, Data, ...) */
/* AOF Assembler syntax is a nightmare when it comes to areas, since once
we change from one area to another, we can't go back again. Instead,
we must create a new area with the same attributes and add the new output
to that. Unfortunately, there is nothing we can do here to guarantee that
two areas with the same attributes will be linked adjacently in the
resulting executable, so we have to be careful not to do pc-relative
addressing across such boundaries. */
char *aof_text_section ();
#define TEXT_SECTION_ASM_OP aof_text_section ()
#define SELECT_RTX_SECTION(MODE,RTX) text_section ();
char *aof_data_section ();
#define DATA_SECTION_ASM_OP aof_data_section ()
#define EXTRA_SECTIONS in_zero_init, in_ctor, in_dtor, in_common
#define EXTRA_SECTION_FUNCTIONS \
ZERO_INIT_SECTION \
CTOR_SECTION \
DTOR_SECTION \
COMMON_SECTION
#define ZERO_INIT_SECTION \
void \
zero_init_section () \
{ \
static int zero_init_count = 1; \
if (in_section != in_zero_init) \
{ \
fprintf (asm_out_file, "\tAREA |C$$zidata%d|,NOINIT\n", \
zero_init_count++); \
in_section = in_zero_init; \
} \
}
#define CTOR_SECTION \
void \
ctor_section () \
{ \
static int ctors_once = 0; \
if (in_section != in_ctor) \
{ \
if (ctors_once) \
{ \
fprintf (stderr, \
"Attempt to output more than one ctor section\n"); \
abort (); \
} \
fprintf (asm_out_file, "\t%s\n", CTORS_SECTION_ASM_OP); \
in_section = in_ctor; \
ctors_once = 1; \
} \
}
#define DTOR_SECTION \
void \
dtor_section () \
{ \
static int dtors_once = 0; \
if (in_section != in_dtor) \
{ \
if (dtors_once) \
{ \
fprintf (stderr, \
"Attempt to output more than one dtor section\n"); \
abort (); \
} \
fprintf (asm_out_file, "\t%s\n", DTORS_SECTION_ASM_OP); \
in_section = in_dtor; \
dtors_once = 1; \
} \
}
/* Used by ASM_OUTPUT_COMMON (below) to tell varasm.c that we've
changed areas. */
#define COMMON_SECTION \
void \
common_section () \
{ \
static int common_count = 1; \
if (in_section != in_common) \
{ \
in_section = in_common; \
} \
}
#define CTOR_LIST_BEGIN \
asm (CTORS_SECTION_ASM_OP); \
extern func_ptr __CTOR_END__[1]; \
func_ptr __CTOR_LIST__[1] = {__CTOR_END__};
#define CTOR_LIST_END \
asm (CTORS_SECTION_ASM_OP); \
func_ptr __CTOR_END__[1] = { (func_ptr) 0 };
#define DO_GLOBAL_CTORS_BODY \
do { \
func_ptr *ptr = __CTOR_LIST__ + 1; \
while (*ptr) \
(*ptr++) (); \
} while (0)
#define DTOR_LIST_BEGIN \
asm (DTORS_SECTION_ASM_OP); \
extern func_ptr __DTOR_END__[1]; \
func_ptr __DTOR_LIST__[1] = {__DTOR_END__};
#define DTOR_LIST_END \
asm (DTORS_SECTION_ASM_OP); \
func_ptr __DTOR_END__[1] = { (func_ptr) 0 };
#define DO_GLOBAL_DTORS_BODY \
do { \
func_ptr *ptr = __DTOR_LIST__ + 1; \
while (*ptr) \
(*ptr++) (); \
} while (0)
#define JUMP_TABLES_IN_TEXT_SECTION 1
#ifndef ARM_OS_NAME
#define ARM_OS_NAME "(generic)"
#endif
/* For the AOF linker, we need to reference __main to force the standard
library to get linked in. */
#define ASM_FILE_START(STREAM) \
{ \
extern char *version_string; \
fprintf ((STREAM), "%s Generated by gcc %s for ARM/%s\n", \
ASM_COMMENT_START, version_string, ARM_OS_NAME); \
fprintf ((STREAM), "__a1\tRN\t0\n"); \
fprintf ((STREAM), "__a2\tRN\t1\n"); \
fprintf ((STREAM), "__a3\tRN\t2\n"); \
fprintf ((STREAM), "__a4\tRN\t3\n"); \
fprintf ((STREAM), "__v1\tRN\t4\n"); \
fprintf ((STREAM), "__v2\tRN\t5\n"); \
fprintf ((STREAM), "__v3\tRN\t6\n"); \
fprintf ((STREAM), "__v4\tRN\t7\n"); \
fprintf ((STREAM), "__v5\tRN\t8\n"); \
fprintf ((STREAM), "__v6\tRN\t9\n"); \
fprintf ((STREAM), "__sl\tRN\t10\n"); \
fprintf ((STREAM), "__fp\tRN\t11\n"); \
fprintf ((STREAM), "__ip\tRN\t12\n"); \
fprintf ((STREAM), "__sp\tRN\t13\n"); \
fprintf ((STREAM), "__lr\tRN\t14\n"); \
fprintf ((STREAM), "__pc\tRN\t15\n"); \
fprintf ((STREAM), "__f0\tFN\t0\n"); \
fprintf ((STREAM), "__f1\tFN\t1\n"); \
fprintf ((STREAM), "__f2\tFN\t2\n"); \
fprintf ((STREAM), "__f3\tFN\t3\n"); \
fprintf ((STREAM), "__f4\tFN\t4\n"); \
fprintf ((STREAM), "__f5\tFN\t5\n"); \
fprintf ((STREAM), "__f6\tFN\t6\n"); \
fprintf ((STREAM), "__f7\tFN\t7\n"); \
text_section (); \
}
/* Some systems use __main in a way incompatible with its use in gcc, in these
cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
give the same symbol without quotes for an alternative entry point. You
must define both, or neither. */
#define NAME__MAIN "__gccmain"
#define SYMBOL__MAIN __gccmain
#define ASM_FILE_END(STREAM) \
do \
{ \
if (flag_pic) \
aof_dump_pic_table (STREAM); \
aof_dump_imports (STREAM); \
fputs ("\tEND\n", (STREAM)); \
} while (0);
#define ASM_IDENTIFY_GCC(STREAM) fputs ("|gcc2_compiled.|\n", (STREAM))
#define ASM_COMMENT_START ";"
#define ASM_APP_ON ""
#define ASM_APP_OFF ""
#define ASM_OUTPUT_LONG_DOUBLE(STREAM,VALUE) \
ASM_OUTPUT_DOUBLE((STREAM),(VALUE))
#define ASM_OUTPUT_DOUBLE(STREAM,VALUE) \
do { \
char dstr[30]; \
long l[2]; \
REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), l); \
REAL_VALUE_TO_DECIMAL ((VALUE), "%.14g", dstr); \
fprintf ((STREAM), "\tDCD &%lx, &%lx\t%s double %s\n", \
l[0], l[1], ASM_COMMENT_START, dstr); \
} while (0)
#define ASM_OUTPUT_FLOAT(STREAM,VALUE) \
do { \
char dstr[30]; \
long l; \
REAL_VALUE_TO_TARGET_SINGLE ((VALUE), l); \
REAL_VALUE_TO_DECIMAL ((VALUE), "%.7g", dstr); \
fprintf ((STREAM), "\tDCD &%lx\t%s double %s\n", \
l, ASM_COMMENT_START, dstr); \
} while (0)
#define ASM_OUTPUT_INT(STREAM,VALUE) \
(fprintf ((STREAM), "\tDCD\t"), \
output_addr_const ((STREAM), (VALUE)), \
fputc ('\n', (STREAM)))
#define ASM_OUTPUT_SHORT(STREAM,VALUE) \
(fprintf ((STREAM), "\tDCW\t"), \
output_addr_const ((STREAM), (VALUE)), \
fputc ('\n', (STREAM)))
#define ASM_OUTPUT_CHAR(STREAM,VALUE) \
(fprintf ((STREAM), "\tDCB\t"), \
output_addr_const ((STREAM), (VALUE)), \
fputc ('\n', (STREAM)))
#define ASM_OUTPUT_BYTE(STREAM,VALUE) \
fprintf ((STREAM), "\tDCB\t%d\n", (VALUE))
#define ASM_OUTPUT_ASCII(STREAM,PTR,LEN) \
{ \
int i; \
char *ptr = (PTR); \
fprintf ((STREAM), "\tDCB"); \
for (i = 0; i < (LEN); i++) \
fprintf ((STREAM), " &%02x%s", \
(unsigned ) *(ptr++), \
(i + 1 < (LEN) \
? ((i & 3) == 3 ? "\n\tDCB" : ",") \
: "\n")); \
}
#define IS_ASM_LOGICAL_LINE_SEPARATOR(C) ((C) == '\n')
#define ASM_OPEN_PAREN "("
#define ASM_CLOSE_PAREN ")"
/* Output of Uninitialized Variables */
#define ASM_OUTPUT_COMMON(STREAM,NAME,SIZE,ROUNDED) \
(common_section (), \
fprintf ((STREAM), "\tAREA "), \
assemble_name ((STREAM), (NAME)), \
fprintf ((STREAM), ", DATA, COMMON\n\t%% %d\t%s size=%d\n", \
(ROUNDED), ASM_COMMENT_START, SIZE))
#define ASM_OUTPUT_LOCAL(STREAM,NAME,SIZE,ROUNDED) \
(zero_init_section (), \
assemble_name ((STREAM), (NAME)), \
fprintf ((STREAM), "\n"), \
fprintf ((STREAM), "\t%% %d\t%s size=%d\n", \
(ROUNDED), ASM_COMMENT_START, SIZE))
/* Output and Generation of Labels */
extern int arm_main_function;
#define ASM_GLOBALIZE_LABEL(STREAM,NAME) \
do { \
fprintf ((STREAM), "\tEXPORT\t"); \
assemble_name ((STREAM), (NAME)); \
fputc ('\n', (STREAM)); \
if ((NAME)[0] == 'm' && ! strcmp ((NAME), "main")) \
arm_main_function = 1; \
} while (0)
#define ASM_OUTPUT_LABEL(STREAM,NAME) \
do { \
assemble_name (STREAM,NAME); \
fputs ("\n", STREAM); \
} while (0)
#define ASM_DECLARE_FUNCTION_NAME(STREAM,NAME,DECL) \
{ \
ASM_OUTPUT_LABEL (STREAM, NAME); \
if (! TREE_PUBLIC (DECL)) \
{ \
fputs ("\tKEEP ", STREAM); \
ASM_OUTPUT_LABEL (STREAM, NAME); \
} \
aof_delete_import ((NAME)); \
}
#define ASM_DECLARE_OBJECT_NAME(STREAM,NAME,DECL) \
{ \
ASM_OUTPUT_LABEL (STREAM, NAME); \
if (! TREE_PUBLIC (DECL)) \
{ \
fputs ("\tKEEP ", STREAM); \
ASM_OUTPUT_LABEL (STREAM, NAME); \
} \
aof_delete_import ((NAME)); \
}
#define ASM_OUTPUT_EXTERNAL(STREAM,DECL,NAME) \
aof_add_import ((NAME))
#define ASM_OUTPUT_EXTERNAL_LIBCALL(STREAM,SYMREF) \
(fprintf ((STREAM), "\tIMPORT\t"), \
assemble_name ((STREAM), XSTR ((SYMREF), 0)), \
fputc ('\n', (STREAM)))
#define ASM_OUTPUT_LABELREF(STREAM,NAME) \
fprintf ((STREAM), "|%s|", NAME)
#define ASM_GENERATE_INTERNAL_LABEL(STRING,PREFIX,NUM) \
sprintf ((STRING), "*|%s..%d|", (PREFIX), (NUM))
#define ASM_FORMAT_PRIVATE_NAME(OUTVAR,NAME,NUMBER) \
((OUTVAR) = (char *) alloca (strlen ((NAME)) + 10), \
sprintf ((OUTVAR), "%s.%d", (NAME), (NUMBER)))
/* How initialization functions are handled */
#define CTORS_SECTION_ASM_OP "AREA\t|C$$gnu_ctorsvec|, DATA, READONLY"
#define DTORS_SECTION_ASM_OP "AREA\t|C$$gnu_dtorsvec|, DATA, READONLY"
#define ASM_OUTPUT_CONSTRUCTOR(STREAM,NAME) \
do { \
ctor_section (); \
fprintf ((STREAM), "\tDCD\t"); \
assemble_name ((STREAM), (NAME)); \
fputc ('\n', (STREAM)); \
} while (0);
#define ASM_OUTPUT_DESTRUCTOR(STREAM,NAME) \
do { \
dtor_section (); \
fprintf ((STREAM), "\tDCD\t"); \
assemble_name ((STREAM), (NAME)); \
fputc ('\n', (STREAM)); \
} while (0);
/* Output of Assembler Instructions */
#define REGISTER_NAMES \
{ \
"a1", "a2", "a3", "a4", \
"v1", "v2", "v3", "v4", \
"v5", "v6", "sl", "fp", \
"ip", "sp", "lr", "pc", \
"f0", "f1", "f2", "f3", \
"f4", "f5", "f6", "f7", \
"cc", "sfp", "afp" \
}
#define ADDITIONAL_REGISTER_NAMES \
{ \
{"r0", 0}, {"a1", 0}, \
{"r1", 1}, {"a2", 1}, \
{"r2", 2}, {"a3", 2}, \
{"r3", 3}, {"a4", 3}, \
{"r4", 4}, {"v1", 4}, \
{"r5", 5}, {"v2", 5}, \
{"r6", 6}, {"v3", 6}, \
{"r7", 7}, {"wr", 7}, \
{"r8", 8}, {"v5", 8}, \
{"r9", 9}, {"v6", 9}, \
{"r10", 10}, {"sl", 10}, {"v7", 10}, \
{"r11", 11}, {"fp", 11}, \
{"r12", 12}, {"ip", 12}, \
{"r13", 13}, {"sp", 13}, \
{"r14", 14}, {"lr", 14}, \
{"r15", 15}, {"pc", 15} \
}
#define REGISTER_PREFIX "__"
#define USER_LABEL_PREFIX ""
#define LOCAL_LABEL_PREFIX ""
/* Output of Dispatch Tables */
#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM,BODY,VALUE,REL) \
fprintf ((STREAM), "\tb\t|L..%d|\n", (VALUE))
#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM,VALUE) \
fprintf ((STREAM), "\tDCD\t|L..%d|\n", (VALUE))
/* A label marking the start of a jump table is a data label. */
#define ASM_OUTPUT_CASE_LABEL(STREAM,PREFIX,NUM,TABLE) \
fprintf ((STREAM), "\tALIGN\n|%s..%d|\n", (PREFIX), (NUM))
/* Assembler Commands for Alignment */
#define ASM_OUTPUT_SKIP(STREAM,NBYTES) \
fprintf ((STREAM), "\t%%\t%d\n", (NBYTES))
#define ASM_OUTPUT_ALIGN(STREAM,POWER) \
do { \
register int amount = 1 << (POWER); \
if (amount == 2) \
fprintf ((STREAM), "\tALIGN 2\n"); \
else if (amount == 4) \
fprintf ((STREAM), "\tALIGN\n"); \
else \
fprintf ((STREAM), "\tALIGN %d\n", amount); \
} while (0)
#include "arm/arm.h"
#undef DBX_DEBUGGING_INFO

323
gcc_arm/config/arm/aout.h Executable file
View File

@ -0,0 +1,323 @@
/* Definitions of target machine for GNU compiler, for ARM with a.out
Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
Contributed by Richard Earnshaw (rearnsha@armltd.co.uk).
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifndef ARM_OS_NAME
#define ARM_OS_NAME "(generic)"
#endif
/* The text to go at the start of the assembler file */
#ifndef ASM_FILE_START
#define ASM_FILE_START(STREAM) \
{ \
fprintf (STREAM,"%srfp\t.req\t%sr9\n", REGISTER_PREFIX, REGISTER_PREFIX); \
fprintf (STREAM,"%ssl\t.req\t%sr10\n", REGISTER_PREFIX, REGISTER_PREFIX); \
fprintf (STREAM,"%sfp\t.req\t%sr11\n", REGISTER_PREFIX, REGISTER_PREFIX); \
fprintf (STREAM,"%sip\t.req\t%sr12\n", REGISTER_PREFIX, REGISTER_PREFIX); \
fprintf (STREAM,"%ssp\t.req\t%sr13\n", REGISTER_PREFIX, REGISTER_PREFIX); \
fprintf (STREAM,"%slr\t.req\t%sr14\n", REGISTER_PREFIX, REGISTER_PREFIX); \
fprintf (STREAM,"%spc\t.req\t%sr15\n", REGISTER_PREFIX, REGISTER_PREFIX); \
}
#endif
#define ASM_APP_ON ""
#define ASM_APP_OFF ""
/* Switch to the text or data segment. */
#define TEXT_SECTION_ASM_OP ".text"
#define DATA_SECTION_ASM_OP ".data"
#define BSS_SECTION_ASM_OP ".bss"
/* Note: If USER_LABEL_PREFIX or LOCAL_LABEL_PREFIX are changed,
make sure that this change is reflected in the function
coff_arm_is_local_label_name() in bfd/coff-arm.c */
#ifndef REGISTER_PREFIX
#define REGISTER_PREFIX ""
#endif
#ifndef USER_LABEL_PREFIX
#define USER_LABEL_PREFIX "_"
#endif
#ifndef LOCAL_LABEL_PREFIX
#define LOCAL_LABEL_PREFIX ""
#endif
/* The assembler's names for the registers. */
#ifndef REGISTER_NAMES
#define REGISTER_NAMES \
{ \
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
"r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc", \
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
"cc", "sfp", "afp" \
}
#endif
#ifndef ADDITIONAL_REGISTER_NAMES
#define ADDITIONAL_REGISTER_NAMES \
{ \
{"a1", 0}, \
{"a2", 1}, \
{"a3", 2}, \
{"a4", 3}, \
{"v1", 4}, \
{"v2", 5}, \
{"v3", 6}, \
{"v4", 7}, \
{"v5", 8}, \
{"v6", 9}, \
{"rfp", 9}, /* Gcc used to call it this */ \
{"sb", 9}, \
{"v7", 10}, \
{"r10", 10}, /* sl */ \
{"r11", 11}, /* fp */ \
{"r12", 12}, /* ip */ \
{"r13", 13}, /* sp */ \
{"r14", 14}, /* lr */ \
{"r15", 15} /* pc */ \
}
#endif
/* Arm Assembler barfs on dollars */
#define DOLLARS_IN_IDENTIFIERS 0
#define NO_DOLLAR_IN_LABEL
/* DBX register number for a given compiler register number */
#define DBX_REGISTER_NUMBER(REGNO) (REGNO)
/* Generate DBX debugging information. riscix.h will undefine this because
the native assembler does not support stabs. */
#define DBX_DEBUGGING_INFO 1
/* Acorn dbx moans about continuation chars, so don't use any. */
#ifndef DBX_CONTIN_LENGTH
#define DBX_CONTIN_LENGTH 0
#endif
/* Output a source filename for the debugger. RISCiX dbx insists that the
``desc'' field is set to compiler version number >= 315 (sic). */
#define DBX_OUTPUT_MAIN_SOURCE_FILENAME(STREAM,NAME) \
do { \
fprintf (STREAM, ".stabs \"%s\",%d,0,315,%s\n", (NAME), N_SO, \
&ltext_label_name[1]); \
text_section (); \
ASM_OUTPUT_INTERNAL_LABEL (STREAM, "Ltext", 0); \
} while (0)
/* Output a function label definition. */
#ifndef ASM_DECLARE_FUNCTION_NAME
#define ASM_DECLARE_FUNCTION_NAME(STREAM,NAME,DECL) ASM_OUTPUT_LABEL (STREAM, NAME)
#endif
#ifndef ASM_OUTPUT_LABEL
#define ASM_OUTPUT_LABEL(STREAM,NAME) \
do { \
assemble_name (STREAM,NAME); \
fputs (":\n", STREAM); \
} while (0)
#endif
/* Output a globalising directive for a label. */
#ifndef ASM_GLOBALIZE_LABEL
#define ASM_GLOBALIZE_LABEL(STREAM,NAME) \
(fprintf (STREAM, "\t.global\t"), \
assemble_name (STREAM, NAME), \
fputc ('\n',STREAM))
#endif
/* Make an internal label into a string. */
#ifndef ASM_GENERATE_INTERNAL_LABEL
#define ASM_GENERATE_INTERNAL_LABEL(STRING, PREFIX, NUM) \
sprintf (STRING, "*%s%s%d", LOCAL_LABEL_PREFIX, PREFIX, NUM)
#endif
/* Nothing special is done about jump tables */
/* #define ASM_OUTPUT_CASE_LABEL(STREAM,PREFIX,NUM,TABLE) */
/* #define ASM_OUTPUT_CASE_END(STREAM,NUM,TABLE) */
/* Construct a private name. */
#define ASM_FORMAT_PRIVATE_NAME(OUTVAR,NAME,NUMBER) \
((OUTVAR) = (char *) alloca (strlen (NAME) + 10), \
sprintf ((OUTVAR), "%s.%d", (NAME), (NUMBER)))
/* Output an element of a dispatch table. */
#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM,VALUE) \
fprintf (STREAM, "\t.word\t%sL%d\n", LOCAL_LABEL_PREFIX, VALUE)
#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM,BODY,VALUE,REL) \
fprintf (STREAM, "\tb\t%sL%d\n", LOCAL_LABEL_PREFIX, (VALUE))
/* Output various types of constants. For real numbers we output hex, with
a comment containing the "human" value, this allows us to pass NaN's which
the riscix assembler doesn't understand (it also makes cross-assembling
less likely to fail). */
#define ASM_OUTPUT_LONG_DOUBLE(STREAM,VALUE) \
do { char dstr[30]; \
long l[3]; \
/* CYGNUS LOCAL */ \
arm_increase_location (12); \
/* END CYGNUS LOCAL */ \
REAL_VALUE_TO_TARGET_LONG_DOUBLE (VALUE, l); \
REAL_VALUE_TO_DECIMAL (VALUE, "%.20g", dstr); \
fprintf (STREAM, "\t.long 0x%lx,0x%lx,0x%lx\t%s long double %s\n", \
l[0], l[1], l[2], ASM_COMMENT_START, dstr); \
} while (0)
#define ASM_OUTPUT_DOUBLE(STREAM, VALUE) \
do { char dstr[30]; \
long l[2]; \
/* CYGNUS LOCAL */ \
arm_increase_location (8); \
/* END CYGNUS LOCAL */ \
REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \
REAL_VALUE_TO_DECIMAL (VALUE, "%.14g", dstr); \
fprintf (STREAM, "\t.long 0x%lx, 0x%lx\t%s double %s\n", l[0], \
l[1], ASM_COMMENT_START, dstr); \
} while (0)
#define ASM_OUTPUT_FLOAT(STREAM, VALUE) \
do { char dstr[30]; \
long l; \
/* CYGNUS LOCAL */ \
arm_increase_location (4); \
/* END CYGNUS LOCAL */ \
REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \
REAL_VALUE_TO_DECIMAL (VALUE, "%.7g", dstr); \
fprintf (STREAM, "\t.word 0x%lx\t%s float %s\n", l, \
ASM_COMMENT_START, dstr); \
} while (0);
#define ASM_OUTPUT_INT(STREAM, EXP) \
{ \
fprintf (STREAM, "\t.word\t"); \
OUTPUT_INT_ADDR_CONST (STREAM, (EXP)); \
/* CYGNUS LOCAL */ \
arm_increase_location (4), \
/* END CYGNUS LOCAL */ \
fputc ('\n', STREAM); \
}
#define ASM_OUTPUT_SHORT(STREAM, EXP) \
(fprintf (STREAM, "\t.short\t"), \
output_addr_const (STREAM, (EXP)), \
/* CYGNUS LOCAL */ \
arm_increase_location (2), \
/* END CYGNUS LOCAL */ \
fputc ('\n', STREAM))
#define ASM_OUTPUT_CHAR(STREAM, EXP) \
(fprintf (STREAM, "\t.byte\t"), \
output_addr_const (STREAM, (EXP)), \
/* CYGNUS LOCAL */ \
arm_increase_location (1), \
/* END CYGNUS LOCAL */ \
fputc ('\n', STREAM))
#define ASM_OUTPUT_BYTE(STREAM, VALUE) \
/* CYGNUS LOCAL */ \
(fprintf (STREAM, "\t.byte\t%d\n", VALUE), \
arm_increase_location (1))
/* END CYGNUS LOCAL */
#define ASM_OUTPUT_ASCII(STREAM, PTR, LEN) \
output_ascii_pseudo_op ((STREAM), (unsigned char *)(PTR), (LEN))
/* Output a gap. In fact we fill it with nulls. */
#define ASM_OUTPUT_SKIP(STREAM, NBYTES) \
/* CYGNUS LOCAL */ \
(arm_increase_location (NBYTES), \
fprintf (STREAM, "\t.space\t%d\n", NBYTES)) \
/* END CYGNUS LOCAL */
/* Align output to a power of two. Horrible /bin/as. */
#define ASM_OUTPUT_ALIGN(STREAM, POWER) \
do \
{ \
register int amount = 1 << (POWER); \
/* CYGNUS LOCAL */ \
extern int arm_text_location; \
/* END CYGNUS LOCAL */ \
\
if (amount == 2) \
fprintf (STREAM, "\t.even\n"); \
else if (amount != 1) \
fprintf (STREAM, "\t.align\t%d\n", amount - 4); \
\
/* CYGNUS LOCAL */ \
if (in_text_section ()) \
arm_text_location = ((arm_text_location + amount - 1) \
& ~(amount - 1)); \
/* END CYGNUS LOCAL */ \
} while (0)
/* Output a common block */
#ifndef ASM_OUTPUT_COMMON
#define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED) \
(fprintf (STREAM, "\t.comm\t"), \
assemble_name ((STREAM), (NAME)), \
fprintf (STREAM, ", %d\t%s %d\n", ROUNDED, ASM_COMMENT_START, SIZE))
#endif
/* Output a local common block. /bin/as can't do this, so hack a
`.space' into the bss segment. Note that this is *bad* practice,
which is guaranteed NOT to work since it doesn't define STATIC
COMMON space but merely STATIC BSS space. */
#ifndef ASM_OUTPUT_ALIGNED_LOCAL
#define ASM_OUTPUT_ALIGNED_LOCAL(STREAM,NAME,SIZE,ALIGN) \
do { \
bss_section (); \
ASM_OUTPUT_ALIGN (STREAM, floor_log2 (ALIGN / BITS_PER_UNIT)); \
ASM_OUTPUT_LABEL (STREAM, NAME); \
fprintf (STREAM, "\t.space\t%d\n", SIZE); \
} while (0)
#endif
/* Output a zero-initialized block. */
#ifndef ASM_OUTPUT_ALIGNED_BSS
#define ASM_OUTPUT_ALIGNED_BSS(STREAM,DECL,NAME,SIZE,ALIGN) \
asm_output_aligned_bss (STREAM, DECL, NAME, SIZE, ALIGN)
#endif
/* Output a source line for the debugger. */
/* #define ASM_OUTPUT_SOURCE_LINE(STREAM,LINE) */
/* Output a #ident directive. */
#ifndef ASM_OUTPUT_IDENT
#define ASM_OUTPUT_IDENT(STREAM,STRING) \
fprintf (STREAM, "%s - - - ident %s\n", ASM_COMMENT_START, STRING)
#endif
/* The assembler's parentheses characters. */
#define ASM_OPEN_PAREN "("
#define ASM_CLOSE_PAREN ")"
#ifndef ASM_COMMENT_START
#define ASM_COMMENT_START "@"
#endif
/* This works for GAS and some other assemblers. */
#define SET_ASM_OP ".set"
#include "arm/arm.h"

7001
gcc_arm/config/arm/arm.c Executable file

File diff suppressed because it is too large Load Diff

2218
gcc_arm/config/arm/arm.h Executable file

File diff suppressed because it is too large Load Diff

6496
gcc_arm/config/arm/arm.md Executable file

File diff suppressed because it is too large Load Diff

2211
gcc_arm/config/arm/arm_010110a.h Executable file

File diff suppressed because it is too large Load Diff

7160
gcc_arm/config/arm/arm_020422.c Executable file

File diff suppressed because it is too large Load Diff

2309
gcc_arm/config/arm/arm_020422.h Executable file

File diff suppressed because it is too large Load Diff

6508
gcc_arm/config/arm/arm_020422.md Executable file

File diff suppressed because it is too large Load Diff

2309
gcc_arm/config/arm/arm_020428.h Executable file

File diff suppressed because it is too large Load Diff

2210
gcc_arm/config/arm/arm_990720.h Executable file

File diff suppressed because it is too large Load Diff

6488
gcc_arm/config/arm/arm_990720.md Executable file

File diff suppressed because it is too large Load Diff

211
gcc_arm/config/arm/coff.h Executable file
View File

@ -0,0 +1,211 @@
/* Definitions of target machine for GNU compiler,
for ARM with COFF obj format.
Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
Contributed by Doug Evans (dje@cygnus.com).
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "arm/semi.h"
#include "arm/aout.h"
#undef USER_LABEL_PREFIX
#define USER_LABEL_PREFIX "_"
/* Run-time Target Specification. */
#undef TARGET_VERSION
#define TARGET_VERSION fputs (" (ARM/coff)", stderr)
#undef TARGET_DEFAULT
#define TARGET_DEFAULT (ARM_FLAG_SOFT_FLOAT | ARM_FLAG_APCS_32)
/* CYGNUS LOCAL nickc/interworking */
#define MULTILIB_DEFAULTS { "mlittle-endian", "msoft-float", "mapcs-32", "mno-thumb-interwork" }
/* END CYGNUS LOCAL nickc */
/* Setting this to 32 produces more efficient code, but the value set in previous
versions of this toolchain was 8, which produces more compact structures. The
command line option -mstructure_size_boundary=<n> can be used to change this
value. */
#undef STRUCTURE_SIZE_BOUNDARY
#define STRUCTURE_SIZE_BOUNDARY arm_structure_size_boundary
extern int arm_structure_size_boundary;
/* A C expression whose value is nonzero if IDENTIFIER with arguments ARGS
is a valid machine specific attribute for DECL.
The attributes in ATTRIBUTES have previously been assigned to DECL. */
extern int arm_valid_machine_decl_attribute ();
#define VALID_MACHINE_DECL_ATTRIBUTE(DECL, ATTRIBUTES, IDENTIFIER, ARGS) \
arm_valid_machine_decl_attribute (DECL, ATTRIBUTES, IDENTIFIER, ARGS)
/* This is COFF, but prefer stabs. */
#define SDB_DEBUGGING_INFO
#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
#include "dbxcoff.h"
/* A C statement to output assembler commands which will identify the
object file as having been compiled with GNU CC (or another GNU
compiler). */
/* Define this to NULL so we don't get anything.
We have ASM_IDENTIFY_LANGUAGE.
Also, when using stabs, gcc2_compiled must be a stabs entry, not an
ordinary symbol, or gdb won't see it. The stabs entry must be
before the N_SO in order for gdb to find it. */
#define ASM_IDENTIFY_GCC(STREAM) \
fprintf (STREAM, "%sgcc2_compiled.:\n", LOCAL_LABEL_PREFIX )
/* This outputs a lot of .req's to define alias for various registers.
Let's try to avoid this. */
#undef ASM_FILE_START
#define ASM_FILE_START(STREAM) \
do { \
extern char *version_string; \
fprintf (STREAM, "%s Generated by gcc %s for ARM/coff\n", \
ASM_COMMENT_START, version_string); \
} while (0)
/* A C statement to output something to the assembler file to switch to section
NAME for object DECL which is either a FUNCTION_DECL, a VAR_DECL or
NULL_TREE. Some target formats do not support arbitrary sections. Do not
define this macro in such cases. */
#define ASM_OUTPUT_SECTION_NAME(STREAM, DECL, NAME, RELOC) \
do { \
if ((DECL) && TREE_CODE (DECL) == FUNCTION_DECL) \
fprintf (STREAM, "\t.section %s,\"x\"\n", (NAME)); \
else if ((DECL) && DECL_READONLY_SECTION (DECL, RELOC)) \
fprintf (STREAM, "\t.section %s,\"\"\n", (NAME)); \
else \
fprintf (STREAM, "\t.section %s,\"w\"\n", (NAME)); \
} while (0)
/* Support the ctors/dtors and other sections. */
#undef INIT_SECTION_ASM_OP
/* Define this macro if jump tables (for `tablejump' insns) should be
output in the text section, along with the assembler instructions.
Otherwise, the readonly data section is used. */
#define JUMP_TABLES_IN_TEXT_SECTION 1
#undef READONLY_DATA_SECTION
#define READONLY_DATA_SECTION rdata_section
#undef RDATA_SECTION_ASM_OP
#define RDATA_SECTION_ASM_OP "\t.section .rdata"
#undef CTORS_SECTION_ASM_OP
#define CTORS_SECTION_ASM_OP "\t.section .ctors,\"x\""
#undef DTORS_SECTION_ASM_OP
#define DTORS_SECTION_ASM_OP "\t.section .dtors,\"x\""
/* A list of other sections which the compiler might be "in" at any
given time. */
#undef EXTRA_SECTIONS
#define EXTRA_SECTIONS SUBTARGET_EXTRA_SECTIONS in_rdata, in_ctors, in_dtors
#define SUBTARGET_EXTRA_SECTIONS
/* A list of extra section function definitions. */
#undef EXTRA_SECTION_FUNCTIONS
#define EXTRA_SECTION_FUNCTIONS \
RDATA_SECTION_FUNCTION \
CTORS_SECTION_FUNCTION \
DTORS_SECTION_FUNCTION \
SUBTARGET_EXTRA_SECTION_FUNCTIONS
#define SUBTARGET_EXTRA_SECTION_FUNCTIONS
#define RDATA_SECTION_FUNCTION \
void \
rdata_section () \
{ \
if (in_section != in_rdata) \
{ \
fprintf (asm_out_file, "%s\n", RDATA_SECTION_ASM_OP); \
in_section = in_rdata; \
} \
}
#define CTORS_SECTION_FUNCTION \
void \
ctors_section () \
{ \
if (in_section != in_ctors) \
{ \
fprintf (asm_out_file, "%s\n", CTORS_SECTION_ASM_OP); \
in_section = in_ctors; \
} \
}
#define DTORS_SECTION_FUNCTION \
void \
dtors_section () \
{ \
if (in_section != in_dtors) \
{ \
fprintf (asm_out_file, "%s\n", DTORS_SECTION_ASM_OP); \
in_section = in_dtors; \
} \
}
/* Support the ctors/dtors sections for g++. */
#define INT_ASM_OP ".word"
/* A C statement (sans semicolon) to output an element in the table of
global constructors. */
#undef ASM_OUTPUT_CONSTRUCTOR
#define ASM_OUTPUT_CONSTRUCTOR(STREAM,NAME) \
do { \
ctors_section (); \
fprintf (STREAM, "\t%s\t ", INT_ASM_OP); \
assemble_name (STREAM, NAME); \
fprintf (STREAM, "\n"); \
} while (0)
/* A C statement (sans semicolon) to output an element in the table of
global destructors. */
#undef ASM_OUTPUT_DESTRUCTOR
#define ASM_OUTPUT_DESTRUCTOR(STREAM,NAME) \
do { \
dtors_section (); \
fprintf (STREAM, "\t%s\t ", INT_ASM_OP); \
assemble_name (STREAM, NAME); \
fprintf (STREAM, "\n"); \
} while (0)
/* __CTOR_LIST__ and __DTOR_LIST__ must be defined by the linker script. */
#define CTOR_LISTS_DEFINED_EXTERNALLY
#undef DO_GLOBAL_CTORS_BODY
#undef DO_GLOBAL_DTORS_BODY
/* If you don't define HAVE_ATEXIT, and the object file format/OS/whatever
does not support constructors/destructors, then gcc implements destructors
by defining its own exit function, which calls the destructors. This gcc
exit function overrides the C library's exit function, and this can cause
all kinds of havoc if the C library has a non-trivial exit function. You
really don't want to use the exit function in libgcc2.c. */
#define HAVE_ATEXIT
/* The ARM development system defines __main. */
#define NAME__MAIN "__gccmain"
#define SYMBOL__MAIN __gccmain

29
gcc_arm/config/arm/ecos-elf.h Executable file
View File

@ -0,0 +1,29 @@
/* Definitions for ecos based ARM systems using ELF
Copyright (C) 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* Run-time Target Specification. */
#define TARGET_VERSION fputs (" (ARM/ELF Ecos)", stderr);
#define HAS_INIT_SECTION
#include "unknown-elf.h"
#undef INVOKE_main

374
gcc_arm/config/arm/elf.h Executable file
View File

@ -0,0 +1,374 @@
/* Definitions of target machine for GNU compiler,
for ARM with ELF obj format.
Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
Contributed by Philip Blundell <philb@gnu.org> and
Catherine Moore <clm@cygnus.com>
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#define OBJECT_FORMAT_ELF
#ifndef LOCAL_LABEL_PREFIX
#define LOCAL_LABEL_PREFIX "."
#endif
#ifndef USER_LABEL_PREFIX
#define USER_LABEL_PREFIX ""
#endif
#ifndef CPP_PREDEFINES
#define CPP_PREDEFINES "-Darm -Darm_elf -Acpu(arm) -Amachine(arm) -D__ELF__"
#endif
/* The following macro defines the format used to output the second
operand of the .type assembler directive. Different svr4 assemblers
expect various different forms for this operand. The one given here
is just a default. You may need to override it in your machine-
specific tm.h file (depending upon the particulars of your assembler). */
#define TYPE_OPERAND_FMT "%s"
/* Write the extra assembler code needed to declare a function's result.
Most svr4 assemblers don't require any special declaration of the
result value, but there are exceptions. */
#ifndef ASM_DECLARE_RESULT
#define ASM_DECLARE_RESULT(FILE, RESULT)
#endif
/* These macros generate the special .type and .size directives which
are used to set the corresponding fields of the linker symbol table
entries in an ELF object file under SVR4. These macros also output
the starting labels for the relevant functions/objects. */
#define TYPE_ASM_OP ".type"
#define SIZE_ASM_OP ".size"
/* Write the extra assembler code needed to declare a function properly.
Some svr4 assemblers need to also have something extra said about the
function's return value. We allow for that here. */
#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
do { \
fprintf (FILE, "\t%s\t ", TYPE_ASM_OP); \
assemble_name (FILE, NAME); \
putc (',', FILE); \
fprintf (FILE, TYPE_OPERAND_FMT, "function"); \
putc ('\n', FILE); \
ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \
ASM_OUTPUT_LABEL(FILE, NAME); \
} while (0)
/* Write the extra assembler code needed to declare an object properly. */
#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \
do { \
fprintf (FILE, "\t%s\t ", TYPE_ASM_OP); \
assemble_name (FILE, NAME); \
putc (',', FILE); \
fprintf (FILE, TYPE_OPERAND_FMT, "object"); \
putc ('\n', FILE); \
size_directive_output = 0; \
if (!flag_inhibit_size_directive && DECL_SIZE (DECL)) \
{ \
size_directive_output = 1; \
fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \
assemble_name (FILE, NAME); \
putc (',', FILE); \
fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, \
int_size_in_bytes (TREE_TYPE (DECL))); \
fputc ('\n', FILE); \
} \
ASM_OUTPUT_LABEL(FILE, NAME); \
} while (0)
/* Output the size directive for a decl in rest_of_decl_compilation
in the case where we did not do so before the initializer.
Once we find the error_mark_node, we know that the value of
size_directive_output was set
by ASM_DECLARE_OBJECT_NAME when it was run for the same decl. */
#define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP_LEVEL, AT_END) \
do { \
char *name = XSTR (XEXP (DECL_RTL (DECL), 0), 0); \
if (!flag_inhibit_size_directive && DECL_SIZE (DECL) \
&& ! AT_END && TOP_LEVEL \
&& DECL_INITIAL (DECL) == error_mark_node \
&& !size_directive_output) \
{ \
size_directive_output = 1; \
fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \
assemble_name (FILE, name); \
putc (',', FILE); \
fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, \
int_size_in_bytes (TREE_TYPE (DECL))); \
fputc ('\n', FILE); \
} \
} while (0)
/* This is how to declare the size of a function. */
#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \
do { \
if (!flag_inhibit_size_directive) \
{ \
char label[256]; \
static int labelno; \
labelno ++; \
ASM_GENERATE_INTERNAL_LABEL (label, "Lfe", labelno); \
ASM_OUTPUT_INTERNAL_LABEL (FILE, "Lfe", labelno); \
fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \
assemble_name (FILE, (FNAME)); \
fprintf (FILE, ","); \
assemble_name (FILE, label); \
fprintf (FILE, "-"); \
assemble_name (FILE, (FNAME)); \
putc ('\n', FILE); \
} \
} while (0)
/* Define this macro if jump tables (for `tablejump' insns) should be
output in the text section, along with the assembler instructions.
Otherwise, the readonly data section is used. */
#define JUMP_TABLES_IN_TEXT_SECTION 1
#ifndef ASM_SPEC
#define ASM_SPEC "%{mbig-endian:-EB} %{mcpu=*:-m%*} %{march=*:-m%*} \
%{mapcs-*:-mapcs-%*} %{mthumb-interwork:-mthumb-interwork}"
#endif
#ifndef LINK_SPEC
#define LINK_SPEC "%{mbig-endian:-EB} -X"
#endif
/* Run-time Target Specification. */
#ifndef TARGET_VERSION
#define TARGET_VERSION fputs (" (ARM/elf)", stderr)
#endif
#ifndef TARGET_DEFAULT
#define TARGET_DEFAULT (ARM_FLAG_SOFT_FLOAT | ARM_FLAG_APCS_32)
#endif
#ifndef MULTILIB_DEFAULTS
#define MULTILIB_DEFAULTS { "mlittle-endian", "msoft-float", "mapcs-32", "mno-thumb-interwork", "fno-leading-underscore" }
#endif
/* Setting this to 32 produces more efficient code, but the value set in previous
versions of this toolchain was 8, which produces more compact structures. The
command line option -mstructure_size_boundary=<n> can be used to change this
value. */
#undef STRUCTURE_SIZE_BOUNDARY
#define STRUCTURE_SIZE_BOUNDARY arm_structure_size_boundary
extern int arm_structure_size_boundary;
/* A C expression whose value is nonzero if IDENTIFIER with arguments ARGS
is a valid machine specific attribute for DECL.
The attributes in ATTRIBUTES have previously been assigned to DECL. */
extern int arm_valid_machine_decl_attribute ();
#define VALID_MACHINE_DECL_ATTRIBUTE(DECL, ATTRIBUTES, IDENTIFIER, ARGS) \
arm_valid_machine_decl_attribute (DECL, ATTRIBUTES, IDENTIFIER, ARGS)
/* A C statement to output assembler commands which will identify the
object file as having been compiled with GNU CC (or another GNU
compiler). */
/* Define this to NULL so we don't get anything.
We have ASM_IDENTIFY_LANGUAGE.
Also, when using stabs, gcc2_compiled must be a stabs entry, not an
ordinary symbol, or gdb won't see it. The stabs entry must be
before the N_SO in order for gdb to find it. */
#ifndef ASM_IDENTIFY_GCC
#define ASM_IDENTIFY_GCC(STREAM) \
fprintf (STREAM, "%sgcc2_compiled.:\n", LOCAL_LABEL_PREFIX )
#endif
/* This outputs a lot of .req's to define alias for various registers.
Let's try to avoid this. */
#ifndef ASM_FILE_START
#define ASM_FILE_START(STREAM) \
do { \
extern char *version_string; \
fprintf (STREAM, "%s Generated by gcc %s for ARM/elf\n", \
ASM_COMMENT_START, version_string); \
} while (0)
#endif
/* Output an internal label definition. */
#ifndef ASM_OUTPUT_INTERNAL_LABEL
#define ASM_OUTPUT_INTERNAL_LABEL(STREAM, PREFIX, NUM) \
do \
{ \
char *s = (char *) alloca (40 + strlen (PREFIX)); \
extern int arm_target_label, arm_ccfsm_state; \
extern rtx arm_target_insn; \
\
if (arm_ccfsm_state == 3 && arm_target_label == (NUM) \
&& !strcmp (PREFIX, "L")) \
{ \
arm_ccfsm_state = 0; \
arm_target_insn = NULL; \
} \
ASM_GENERATE_INTERNAL_LABEL (s, (PREFIX), (NUM)); \
/* CYGNUS LOCAL nickc */ \
arm_asm_output_label (STREAM, s); \
/* END CYGNUS LOCAL */ \
} while (0)
#endif
/* Support the ctors/dtors and other sections. */
/* Define the pseudo-ops used to switch to the .ctors and .dtors sections.
Note that we want to give these sections the SHF_WRITE attribute
because these sections will actually contain data (i.e. tables of
addresses of functions in the current root executable or shared library
file) and, in the case of a shared library, the relocatable addresses
will have to be properly resolved/relocated (and then written into) by
the dynamic linker when it actually attaches the given shared library
to the executing process. (Note that on SVR4, you may wish to use the
`-z text' option to the ELF linker, when building a shared library, as
an additional check that you are doing everything right. But if you do
use the `-z text' option when building a shared library, you will get
errors unless the .ctors and .dtors sections are marked as writable
via the SHF_WRITE attribute.) */
#ifndef CTORS_SECTION_ASM_OP
#define CTORS_SECTION_ASM_OP "\t.section\t.ctors,\"aw\""
#endif
#ifndef DTORS_SECTION_ASM_OP
#define DTORS_SECTION_ASM_OP "\t.section\t.dtors,\"aw\""
#endif
/* A list of other sections which the compiler might be "in" at any
given time. */
#ifndef SUBTARGET_EXTRA_SECTIONS
#define SUBTARGET_EXTRA_SECTIONS
#endif
#ifndef EXTRA_SECTIONS
#define EXTRA_SECTIONS SUBTARGET_EXTRA_SECTIONS in_ctors, in_dtors
#endif
/* A list of extra section function definitions. */
#ifndef SUBTARGET_EXTRA_SECTION_FUNCTIONS
#define SUBTARGET_EXTRA_SECTION_FUNCTIONS
#endif
#ifndef EXTRA_SECTION_FUNCTIONS
#define EXTRA_SECTION_FUNCTIONS \
SUBTARGET_EXTRA_SECTION_FUNCTIONS \
CTORS_SECTION_FUNCTION \
DTORS_SECTION_FUNCTION
#endif
#ifndef CTORS_SECTION_FUNCTION
#define CTORS_SECTION_FUNCTION \
void \
ctors_section () \
{ \
if (in_section != in_ctors) \
{ \
fprintf (asm_out_file, "%s\n", CTORS_SECTION_ASM_OP); \
in_section = in_ctors; \
} \
}
#endif
#ifndef DTORS_SECTION_FUNCTION
#define DTORS_SECTION_FUNCTION \
void \
dtors_section () \
{ \
if (in_section != in_dtors) \
{ \
fprintf (asm_out_file, "%s\n", DTORS_SECTION_ASM_OP); \
in_section = in_dtors; \
} \
}
#endif
/* Support the ctors/dtors sections for g++. */
#ifndef INT_ASM_OP
#define INT_ASM_OP ".word"
#endif
/* A C statement (sans semicolon) to output an element in the table of
global constructors. */
#ifndef ASM_OUTPUT_CONSTRUCTOR
#define ASM_OUTPUT_CONSTRUCTOR(STREAM,NAME) \
do { \
ctors_section (); \
fprintf (STREAM, "\t%s\t ", INT_ASM_OP); \
assemble_name (STREAM, NAME); \
fprintf (STREAM, "\n"); \
} while (0)
#endif
/* A C statement (sans semicolon) to output an element in the table of
global destructors. */
#ifndef ASM_OUTPUT_DESTRUCTOR
#define ASM_OUTPUT_DESTRUCTOR(STREAM,NAME) \
do { \
dtors_section (); \
fprintf (STREAM, "\t%s\t ", INT_ASM_OP); \
assemble_name (STREAM, NAME); \
fprintf (STREAM, "\n"); \
} while (0)
#endif
/* This is how we tell the assembler that a symbol is weak. */
#define ASM_WEAKEN_LABEL(FILE,NAME) \
do { fputs ("\t.weak\t", FILE); assemble_name (FILE, NAME); \
fputc ('\n', FILE); } while (0)
#include "arm/aout.h"
#define ASM_OUTPUT_UNIQUE_BSS(file, decl, name, size) \
{ \
int len = strlen (name) + 5; \
char * string; \
\
string = alloca (len + 1); \
sprintf (string, ".bss.%s", name); \
\
named_section (NULL, string, 0); \
\
ASM_GLOBALIZE_LABEL (file, name); \
\
ASM_OUTPUT_ALIGN (file, \
floor_log2 (DECL_ALIGN (decl) / BITS_PER_UNIT)); \
\
last_assemble_variable_decl = decl; \
ASM_DECLARE_OBJECT_NAME (file, name, decl); \
ASM_OUTPUT_SKIP (file, size ? size : 1); \
}
#define ASM_OUTPUT_UNIQUE_LOCAL(file, decl, name, size) \
do \
{ \
int len = strlen (name) + 5; \
char * string; \
\
string = alloca (len + 1); \
sprintf (string, ".bss.%s", name); \
\
named_section (NULL, string, 0); \
\
ASM_OUTPUT_ALIGN (file, \
floor_log2 (DECL_ALIGN (decl) / BITS_PER_UNIT)); \
ASM_OUTPUT_LABEL (file, name); \
fprintf (file, "\t.space\t%d\n", size); \
} \
while (0)

580
gcc_arm/config/arm/lib1funcs.asm Executable file
View File

@ -0,0 +1,580 @@
@ libgcc1 routines for ARM cpu.
@ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk)
/* Copyright (C) 1995, 1996, 1998 Free Software Foundation, Inc.
This file is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
In addition to the permissions in the GNU General Public License, the
Free Software Foundation gives you unlimited permission to link the
compiled version of this file with other programs, and to distribute
those programs without any restriction coming from the use of this
file. (The General Public License restrictions do apply in other
respects; for example, they cover modification of the file, and
distribution when not linked into another program.)
This file is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* As a special exception, if you link this library with other files,
some of which are compiled with GCC, to produce an executable,
this library does not by itself cause the resulting executable
to be covered by the GNU General Public License.
This exception does not however invalidate any other reasons why
the executable file might be covered by the GNU General Public License. */
#ifdef __APCS_26__
#define RET movs
#define RETc(x) mov##x##s
#define RETCOND ^
#else
#define RET mov
#define RETc(x) mov##x
#define RETCOND
#endif
#ifndef __USER_LABEL_PREFIX__
#error __USER_LABEL_PREFIX__ not defined
#endif
/* ANSI concatenation macros. */
#define CONCAT1(a, b) CONCAT2(a, b)
#define CONCAT2(a, b) a ## b
/* Use the right prefix for global labels. */
#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
#ifdef __elf__
#define __PLT__ (PLT)
#define TYPE(x) .type SYM(x),function
#define SIZE(x) .size SYM(x), . - SYM(x)
#else
#define __PLT__
#define TYPE(x)
#define SIZE(x)
#endif
#ifdef L_udivsi3
dividend .req r0
divisor .req r1
result .req r2
curbit .req r3
ip .req r12
sp .req r13
lr .req r14
pc .req r15
.text
.globl SYM (__udivsi3)
TYPE (__udivsi3)
.align 0
SYM (__udivsi3):
cmp divisor, #0
beq Ldiv0
mov curbit, #1
mov result, #0
cmp dividend, divisor
bcc Lgot_result
Loop1:
@ Unless the divisor is very big, shift it up in multiples of
@ four bits, since this is the amount of unwinding in the main
@ division loop. Continue shifting until the divisor is
@ larger than the dividend.
cmp divisor, #0x10000000
cmpcc divisor, dividend
movcc divisor, divisor, lsl #4
movcc curbit, curbit, lsl #4
bcc Loop1
Lbignum:
@ For very big divisors, we must shift it a bit at a time, or
@ we will be in danger of overflowing.
cmp divisor, #0x80000000
cmpcc divisor, dividend
movcc divisor, divisor, lsl #1
movcc curbit, curbit, lsl #1
bcc Lbignum
Loop3:
@ Test for possible subtractions, and note which bits
@ are done in the result. On the final pass, this may subtract
@ too much from the dividend, but the result will be ok, since the
@ "bit" will have been shifted out at the bottom.
cmp dividend, divisor
subcs dividend, dividend, divisor
orrcs result, result, curbit
cmp dividend, divisor, lsr #1
subcs dividend, dividend, divisor, lsr #1
orrcs result, result, curbit, lsr #1
cmp dividend, divisor, lsr #2
subcs dividend, dividend, divisor, lsr #2
orrcs result, result, curbit, lsr #2
cmp dividend, divisor, lsr #3
subcs dividend, dividend, divisor, lsr #3
orrcs result, result, curbit, lsr #3
cmp dividend, #0 @ Early termination?
movnes curbit, curbit, lsr #4 @ No, any more bits to do?
movne divisor, divisor, lsr #4
bne Loop3
Lgot_result:
mov r0, result
RET pc, lr
Ldiv0:
str lr, [sp, #-4]!
bl SYM (__div0) __PLT__
mov r0, #0 @ about as wrong as it could be
ldmia sp!, {pc}RETCOND
SIZE (__udivsi3)
#endif /* L_udivsi3 */
#ifdef L_umodsi3
dividend .req r0
divisor .req r1
overdone .req r2
curbit .req r3
ip .req r12
sp .req r13
lr .req r14
pc .req r15
.text
.globl SYM (__umodsi3)
TYPE (__umodsi3)
.align 0
SYM (__umodsi3):
cmp divisor, #0
beq Ldiv0
mov curbit, #1
cmp dividend, divisor
RETc(cc) pc, lr
Loop1:
@ Unless the divisor is very big, shift it up in multiples of
@ four bits, since this is the amount of unwinding in the main
@ division loop. Continue shifting until the divisor is
@ larger than the dividend.
cmp divisor, #0x10000000
cmpcc divisor, dividend
movcc divisor, divisor, lsl #4
movcc curbit, curbit, lsl #4
bcc Loop1
Lbignum:
@ For very big divisors, we must shift it a bit at a time, or
@ we will be in danger of overflowing.
cmp divisor, #0x80000000
cmpcc divisor, dividend
movcc divisor, divisor, lsl #1
movcc curbit, curbit, lsl #1
bcc Lbignum
Loop3:
@ Test for possible subtractions. On the final pass, this may
@ subtract too much from the dividend, so keep track of which
@ subtractions are done, we can fix them up afterwards...
mov overdone, #0
cmp dividend, divisor
subcs dividend, dividend, divisor
cmp dividend, divisor, lsr #1
subcs dividend, dividend, divisor, lsr #1
orrcs overdone, overdone, curbit, ror #1
cmp dividend, divisor, lsr #2
subcs dividend, dividend, divisor, lsr #2
orrcs overdone, overdone, curbit, ror #2
cmp dividend, divisor, lsr #3
subcs dividend, dividend, divisor, lsr #3
orrcs overdone, overdone, curbit, ror #3
mov ip, curbit
cmp dividend, #0 @ Early termination?
movnes curbit, curbit, lsr #4 @ No, any more bits to do?
movne divisor, divisor, lsr #4
bne Loop3
@ Any subtractions that we should not have done will be recorded in
@ the top three bits of "overdone". Exactly which were not needed
@ are governed by the position of the bit, stored in ip.
@ If we terminated early, because dividend became zero,
@ then none of the below will match, since the bit in ip will not be
@ in the bottom nibble.
ands overdone, overdone, #0xe0000000
RETc(eq) pc, lr @ No fixups needed
tst overdone, ip, ror #3
addne dividend, dividend, divisor, lsr #3
tst overdone, ip, ror #2
addne dividend, dividend, divisor, lsr #2
tst overdone, ip, ror #1
addne dividend, dividend, divisor, lsr #1
RET pc, lr
Ldiv0:
str lr, [sp, #-4]!
bl SYM (__div0) __PLT__
mov r0, #0 @ about as wrong as it could be
ldmia sp!, {pc}RETCOND
SIZE (__umodsi3)
#endif /* L_umodsi3 */
#ifdef L_divsi3
dividend .req r0
divisor .req r1
result .req r2
curbit .req r3
ip .req r12
sp .req r13
lr .req r14
pc .req r15
.text
.globl SYM (__divsi3)
TYPE (__divsi3)
.align 0
SYM (__divsi3):
eor ip, dividend, divisor @ Save the sign of the result.
mov curbit, #1
mov result, #0
cmp divisor, #0
rsbmi divisor, divisor, #0 @ Loops below use unsigned.
beq Ldiv0
cmp dividend, #0
rsbmi dividend, dividend, #0
cmp dividend, divisor
bcc Lgot_result
Loop1:
@ Unless the divisor is very big, shift it up in multiples of
@ four bits, since this is the amount of unwinding in the main
@ division loop. Continue shifting until the divisor is
@ larger than the dividend.
cmp divisor, #0x10000000
cmpcc divisor, dividend
movcc divisor, divisor, lsl #4
movcc curbit, curbit, lsl #4
bcc Loop1
Lbignum:
@ For very big divisors, we must shift it a bit at a time, or
@ we will be in danger of overflowing.
cmp divisor, #0x80000000
cmpcc divisor, dividend
movcc divisor, divisor, lsl #1
movcc curbit, curbit, lsl #1
bcc Lbignum
Loop3:
@ Test for possible subtractions, and note which bits
@ are done in the result. On the final pass, this may subtract
@ too much from the dividend, but the result will be ok, since the
@ "bit" will have been shifted out at the bottom.
cmp dividend, divisor
subcs dividend, dividend, divisor
orrcs result, result, curbit
cmp dividend, divisor, lsr #1
subcs dividend, dividend, divisor, lsr #1
orrcs result, result, curbit, lsr #1
cmp dividend, divisor, lsr #2
subcs dividend, dividend, divisor, lsr #2
orrcs result, result, curbit, lsr #2
cmp dividend, divisor, lsr #3
subcs dividend, dividend, divisor, lsr #3
orrcs result, result, curbit, lsr #3
cmp dividend, #0 @ Early termination?
movnes curbit, curbit, lsr #4 @ No, any more bits to do?
movne divisor, divisor, lsr #4
bne Loop3
Lgot_result:
mov r0, result
cmp ip, #0
rsbmi r0, r0, #0
RET pc, lr
Ldiv0:
str lr, [sp, #-4]!
bl SYM (__div0) __PLT__
mov r0, #0 @ about as wrong as it could be
ldmia sp!, {pc}RETCOND
SIZE (__divsi3)
#endif /* L_divsi3 */
#ifdef L_modsi3
dividend .req r0
divisor .req r1
overdone .req r2
curbit .req r3
ip .req r12
sp .req r13
lr .req r14
pc .req r15
.text
.globl SYM (__modsi3)
TYPE (__modsi3)
.align 0
SYM (__modsi3):
mov curbit, #1
cmp divisor, #0
rsbmi divisor, divisor, #0 @ Loops below use unsigned.
beq Ldiv0
@ Need to save the sign of the dividend, unfortunately, we need
@ ip later on; this is faster than pushing lr and using that.
str dividend, [sp, #-4]!
cmp dividend, #0
rsbmi dividend, dividend, #0
cmp dividend, divisor
bcc Lgot_result
Loop1:
@ Unless the divisor is very big, shift it up in multiples of
@ four bits, since this is the amount of unwinding in the main
@ division loop. Continue shifting until the divisor is
@ larger than the dividend.
cmp divisor, #0x10000000
cmpcc divisor, dividend
movcc divisor, divisor, lsl #4
movcc curbit, curbit, lsl #4
bcc Loop1
Lbignum:
@ For very big divisors, we must shift it a bit at a time, or
@ we will be in danger of overflowing.
cmp divisor, #0x80000000
cmpcc divisor, dividend
movcc divisor, divisor, lsl #1
movcc curbit, curbit, lsl #1
bcc Lbignum
Loop3:
@ Test for possible subtractions. On the final pass, this may
@ subtract too much from the dividend, so keep track of which
@ subtractions are done, we can fix them up afterwards...
mov overdone, #0
cmp dividend, divisor
subcs dividend, dividend, divisor
cmp dividend, divisor, lsr #1
subcs dividend, dividend, divisor, lsr #1
orrcs overdone, overdone, curbit, ror #1
cmp dividend, divisor, lsr #2
subcs dividend, dividend, divisor, lsr #2
orrcs overdone, overdone, curbit, ror #2
cmp dividend, divisor, lsr #3
subcs dividend, dividend, divisor, lsr #3
orrcs overdone, overdone, curbit, ror #3
mov ip, curbit
cmp dividend, #0 @ Early termination?
movnes curbit, curbit, lsr #4 @ No, any more bits to do?
movne divisor, divisor, lsr #4
bne Loop3
@ Any subtractions that we should not have done will be recorded in
@ the top three bits of "overdone". Exactly which were not needed
@ are governed by the position of the bit, stored in ip.
@ If we terminated early, because dividend became zero,
@ then none of the below will match, since the bit in ip will not be
@ in the bottom nibble.
ands overdone, overdone, #0xe0000000
beq Lgot_result
tst overdone, ip, ror #3
addne dividend, dividend, divisor, lsr #3
tst overdone, ip, ror #2
addne dividend, dividend, divisor, lsr #2
tst overdone, ip, ror #1
addne dividend, dividend, divisor, lsr #1
Lgot_result:
ldr ip, [sp], #4
cmp ip, #0
rsbmi dividend, dividend, #0
RET pc, lr
Ldiv0:
str lr, [sp, #-4]!
bl SYM (__div0) __PLT__
mov r0, #0 @ about as wrong as it could be
ldmia sp!, {pc}RETCOND
SIZE (__modsi3)
#endif /* L_modsi3 */
#ifdef L_dvmd_tls
.globl SYM (__div0)
TYPE (__div0)
.align 0
SYM (__div0):
RET pc, lr
SIZE (__div0)
#endif /* L_divmodsi_tools */
#ifdef L_dvmd_lnx
@ GNU/Linux division-by zero handler. Used in place of L_dvmd_tls
#include <asm/unistd.h>
#define SIGFPE 8 @ cant use <asm/signal.h> as it
@ contains too much C rubbish
.globl SYM (__div0)
TYPE (__div0)
.align 0
SYM (__div0):
stmfd sp!, {r1, lr}
swi __NR_getpid
cmn r0, #1000
ldmhsfd sp!, {r1, pc}RETCOND @ not much we can do
mov r1, #SIGFPE
swi __NR_kill
ldmfd sp!, {r1, pc}RETCOND
SIZE (__div0)
#endif /* L_dvmd_lnx */
/* These next two sections are here despite the fact that they contain Thumb
assembler because their presence allows interworked code to be linked even
when the GCC library is this one. */
#ifdef L_call_via_rX
/* These labels & instructions are used by the Arm/Thumb interworking code.
The address of function to be called is loaded into a register and then
one of these labels is called via a BL instruction. This puts the
return address into the link register with the bottom bit set, and the
code here switches to the correct mode before executing the function. */
.text
.align 0
.force_thumb
.macro call_via register
.globl SYM (_call_via_\register)
TYPE (_call_via_\register)
.thumb_func
SYM (_call_via_\register):
bx \register
nop
SIZE (_call_via_\register)
.endm
call_via r0
call_via r1
call_via r2
call_via r3
call_via r4
call_via r5
call_via r6
call_via r7
call_via r8
call_via r9
call_via sl
call_via fp
call_via ip
call_via sp
call_via lr
#endif /* L_call_via_rX */
#ifdef L_interwork_call_via_rX
/* These labels & instructions are used by the Arm/Thumb interworking code,
when the target address is in an unknown instruction set. The address
of function to be called is loaded into a register and then one of these
labels is called via a BL instruction. This puts the return address
into the link register with the bottom bit set, and the code here
switches to the correct mode before executing the function. Unfortunately
the target code cannot be relied upon to return via a BX instruction, so
instead we have to store the resturn address on the stack and allow the
called function to return here instead. Upon return we recover the real
return address and use a BX to get back to Thumb mode. */
.text
.align 0
.code 32
.globl _arm_return
_arm_return:
ldmia r13!, {r12}
bx r12
.code 16
.macro interwork register
.code 16
.globl SYM (_interwork_call_via_\register)
TYPE (_interwork_call_via_\register)
.thumb_func
SYM (_interwork_call_via_\register):
bx pc
nop
.code 32
.globl .Lchange_\register
.Lchange_\register:
tst \register, #1
stmeqdb r13!, {lr}
adreq lr, _arm_return
bx \register
SIZE (_interwork_call_via_\register)
.endm
interwork r0
interwork r1
interwork r2
interwork r3
interwork r4
interwork r5
interwork r6
interwork r7
interwork r8
interwork r9
interwork sl
interwork fp
interwork ip
interwork sp
/* The lr case has to be handled a little differently...*/
.code 16
.globl SYM (_interwork_call_via_lr)
TYPE (_interwork_call_via_lr)
.thumb_func
SYM (_interwork_call_via_lr):
bx pc
nop
.code 32
.globl .Lchange_lr
.Lchange_lr:
tst lr, #1
stmeqdb r13!, {lr}
mov ip, lr
adreq lr, _arm_return
bx ip
SIZE (_interwork_call_via_lr)
#endif /* L_interwork_call_via_rX */

572
gcc_arm/config/arm/lib1thumb.asm Executable file
View File

@ -0,0 +1,572 @@
@ libgcc1 routines for ARM cpu.
@ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk)
/* Copyright (C) 1995, 1996, 1998 Free Software Foundation, Inc.
This file is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
In addition to the permissions in the GNU General Public License, the
Free Software Foundation gives you unlimited permission to link the
compiled version of this file with other programs, and to distribute
those programs without any restriction coming from the use of this
file. (The General Public License restrictions do apply in other
respects; for example, they cover modification of the file, and
distribution when not linked into another program.)
This file is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* As a special exception, if you link this library with other files,
some of which are compiled with GCC, to produce an executable,
this library does not by itself cause the resulting executable
to be covered by the GNU General Public License.
This exception does not however invalidate any other reasons why
the executable file might be covered by the GNU General Public License. */
.code 16
#ifndef __USER_LABEL_PREFIX__
#error __USER_LABEL_PREFIX__ not defined
#endif
/* ANSI concatenation macros. */
#define CONCAT1(a, b) CONCAT2(a, b)
#define CONCAT2(a, b) a ## b
/* Use the right prefix for global labels. */
#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
#define __PLT__
#ifdef __ELF__
#define TYPE(x) .type SYM(x),function
#define SIZE(x) .size SYM(x), . - SYM(x)
#else
#define TYPE(x)
#define SIZE(x)
#endif
/* Function end macros. Variants for interworking. */
# define __THUMB_INTERWORK__
# ifdef __THUMB_INTERWORK__
# define RET bx lr
# define RETc(x) bx##x lr
.macro THUMB_LDIV0
.Ldiv0:
push { lr }
bl SYM (__div0)
mov r0, #0 @ About as wrong as it could be.
pop { r1 }
bx r1
.endm
# else
# define RET mov pc, lr
# define RETc(x) mov##x pc, lr
.macro THUMB_LDIV0
.Ldiv0:
push { lr }
bl SYM (__div0)
mov r0, #0 @ About as wrong as it could be.
pop { pc }
.endm
# endif
# define RETCOND
.macro FUNC_END name
.Ldiv0:
THUMB_LDIV0
SIZE (__\name)
.endm
.macro THUMB_FUNC_START name
.globl SYM (\name)
TYPE (\name)
.thumb_func
SYM (\name):
.endm
/* Function start macros. */
#define THUMB_FUNC .thumb_func
#define THUMB_CODE .force_thumb
.macro FUNC_START name
.text
.globl SYM (__\name)
TYPE (__\name)
.align 0
THUMB_CODE
THUMB_FUNC
SYM (__\name):
.endm
/* Register aliases. */
work .req r4 @ XXXX is this safe ?
dividend .req r0
divisor .req r1
overdone .req r2
result .req r2
curbit .req r3
ip .req r12
sp .req r13
lr .req r14
pc .req r15
/* ------------------------------------------------------------------------ */
/* Bodies of the divsion and modulo routines. */
/* ------------------------------------------------------------------------ */
.macro THUMB_DIV_MOD_BODY modulo
@ Load the constant 0x10000000 into our work register.
mov work, #1
lsl work, #28
.Loop1:
@ Unless the divisor is very big, shift it up in multiples of
@ four bits, since this is the amount of unwinding in the main
@ division loop. Continue shifting until the divisor is
@ larger than the dividend.
cmp divisor, work
bhs .Lbignum
cmp divisor, dividend
bhs .Lbignum
lsl divisor, #4
lsl curbit, #4
b .Loop1
.Lbignum:
@ Set work to 0x80000000
lsl work, #3
.Loop2:
@ For very big divisors, we must shift it a bit at a time, or
@ we will be in danger of overflowing.
cmp divisor, work
bhs .Loop3
cmp divisor, dividend
bhs .Loop3
lsl divisor, #1
lsl curbit, #1
b .Loop2
.Loop3:
@ Test for possible subtractions ...
.if \modulo
@ ... On the final pass, this may subtract too much from the dividend,
@ so keep track of which subtractions are done, we can fix them up
@ afterwards.
mov overdone, #0
cmp dividend, divisor
blo .Lover1
sub dividend, dividend, divisor
.Lover1:
lsr work, divisor, #1
cmp dividend, work
blo .Lover2
sub dividend, dividend, work
mov ip, curbit
mov work, #1
ror curbit, work
orr overdone, curbit
mov curbit, ip
.Lover2:
lsr work, divisor, #2
cmp dividend, work
blo .Lover3
sub dividend, dividend, work
mov ip, curbit
mov work, #2
ror curbit, work
orr overdone, curbit
mov curbit, ip
.Lover3:
lsr work, divisor, #3
cmp dividend, work
blo .Lover4
sub dividend, dividend, work
mov ip, curbit
mov work, #3
ror curbit, work
orr overdone, curbit
mov curbit, ip
.Lover4:
mov ip, curbit
.else
@ ... and note which bits are done in the result. On the final pass,
@ this may subtract too much from the dividend, but the result will be ok,
@ since the "bit" will have been shifted out at the bottom.
cmp dividend, divisor
blo .Lover1
sub dividend, dividend, divisor
orr result, result, curbit
.Lover1:
lsr work, divisor, #1
cmp dividend, work
blo .Lover2
sub dividend, dividend, work
lsr work, curbit, #1
orr result, work
.Lover2:
lsr work, divisor, #2
cmp dividend, work
blo .Lover3
sub dividend, dividend, work
lsr work, curbit, #2
orr result, work
.Lover3:
lsr work, divisor, #3
cmp dividend, work
blo .Lover4
sub dividend, dividend, work
lsr work, curbit, #3
orr result, work
.Lover4:
.endif
cmp dividend, #0 @ Early termination?
beq .Lover5
lsr curbit, #4 @ No, any more bits to do?
beq .Lover5
lsr divisor, #4
b .Loop3
.Lover5:
.if \modulo
@ Any subtractions that we should not have done will be recorded in
@ the top three bits of "overdone". Exactly which were not needed
@ are governed by the position of the bit, stored in ip.
mov work, #0xe
lsl work, #28
and overdone, work
beq .Lgot_result
@ If we terminated early, because dividend became zero, then the
@ bit in ip will not be in the bottom nibble, and we should not
@ perform the additions below. We must test for this though
@ (rather relying upon the TSTs to prevent the additions) since
@ the bit in ip could be in the top two bits which might then match
@ with one of the smaller RORs.
mov curbit, ip
mov work, #0x7
tst curbit, work
beq .Lgot_result
mov curbit, ip
mov work, #3
ror curbit, work
tst overdone, curbit
beq .Lover6
lsr work, divisor, #3
add dividend, work
.Lover6:
mov curbit, ip
mov work, #2
ror curbit, work
tst overdone, curbit
beq .Lover7
lsr work, divisor, #2
add dividend, work
.Lover7:
mov curbit, ip
mov work, #1
ror curbit, work
tst overdone, curbit
beq .Lgot_result
lsr work, divisor, #1
add dividend, work
.endif
.Lgot_result:
.endm
/* ------------------------------------------------------------------------ */
/* Start of the Real Functions */
/* ------------------------------------------------------------------------ */
#ifdef L_udivsi3
FUNC_START udivsi3
cmp divisor, #0
beq .Ldiv0
mov curbit, #1
mov result, #0
push { work }
cmp dividend, divisor
blo .Lgot_result
THUMB_DIV_MOD_BODY 0
mov r0, result
pop { work }
RET
FUNC_END udivsi3
#endif /* L_udivsi3 */
/* ------------------------------------------------------------------------ */
#ifdef L_umodsi3
FUNC_START umodsi3
cmp divisor, #0
beq .Ldiv0
mov curbit, #1
cmp dividend, divisor
bhs ..Lover10
RET
..Lover10:
push { work }
THUMB_DIV_MOD_BODY 1
pop { work }
RET
FUNC_END umodsi3
#endif /* L_umodsi3 */
/* ------------------------------------------------------------------------ */
#ifdef L_divsi3
FUNC_START divsi3
cmp divisor, #0
beq .Ldiv0
push { work }
mov work, dividend
eor work, divisor @ Save the sign of the result.
mov ip, work
mov curbit, #1
mov result, #0
cmp divisor, #0
bpl .Lover10
neg divisor, divisor @ Loops below use unsigned.
.Lover10:
cmp dividend, #0
bpl .Lover11
neg dividend, dividend
.Lover11:
cmp dividend, divisor
blo .Lgot_result
THUMB_DIV_MOD_BODY 0
mov r0, result
mov work, ip
cmp work, #0
bpl .Lover12
neg r0, r0
.Lover12:
pop { work }
RET
FUNC_END divsi3
#endif /* L_divsi3 */
/* ------------------------------------------------------------------------ */
#ifdef L_modsi3
FUNC_START modsi3
mov curbit, #1
cmp divisor, #0
beq .Ldiv0
bpl .Lover10
neg divisor, divisor @ Loops below use unsigned.
.Lover10:
push { work }
@ Need to save the sign of the dividend, unfortunately, we need
@ work later on. Must do this after saving the original value of
@ the work register, because we will pop this value off first.
push { dividend }
cmp dividend, #0
bpl .Lover11
neg dividend, dividend
.Lover11:
cmp dividend, divisor
blo .Lgot_result
THUMB_DIV_MOD_BODY 1
pop { work }
cmp work, #0
bpl .Lover12
neg dividend, dividend
.Lover12:
pop { work }
RET
FUNC_END modsi3
#endif /* L_modsi3 */
/* ------------------------------------------------------------------------ */
#ifdef L_dvmd_tls
FUNC_START div0
RET
SIZE (__div0)
#endif /* L_divmodsi_tools */
/* ------------------------------------------------------------------------ */
#ifdef L_dvmd_lnx
@ GNU/Linux division-by zero handler. Used in place of L_dvmd_tls
#include <asm/unistd.h>
#define SIGFPE 8 @ cant use <asm/signal.h> as it
@ contains too much C rubbish
FUNC_START div0
stmfd sp!, {r1, lr}
swi __NR_getpid
cmn r0, #1000
ldmhsfd sp!, {r1, pc}RETCOND @ not much we can do
mov r1, #SIGFPE
swi __NR_kill
#ifdef __THUMB_INTERWORK__
ldmfd sp!, {r1, lr}
bx lr
#else
ldmfd sp!, {r1, pc}RETCOND
#endif
SIZE (__div0)
#endif /* L_dvmd_lnx */
/* ------------------------------------------------------------------------ */
/* These next two sections are here despite the fact that they contain Thumb
assembler because their presence allows interworked code to be linked even
when the GCC library is this one. */
/* Do not build the interworking functions when the target architecture does
not support Thumb instructions. (This can be a multilib option). */
#if defined L_call_via_rX
/* These labels & instructions are used by the Arm/Thumb interworking code.
The address of function to be called is loaded into a register and then
one of these labels is called via a BL instruction. This puts the
return address into the link register with the bottom bit set, and the
code here switches to the correct mode before executing the function. */
.text
.align 0
.force_thumb
.macro call_via register
THUMB_FUNC_START _call_via_\register
bx \register
nop
SIZE (_call_via_\register)
.endm
call_via r0
call_via r1
call_via r2
call_via r3
call_via r4
call_via r5
call_via r6
call_via r7
call_via r8
call_via r9
call_via sl
call_via fp
call_via ip
call_via sp
call_via lr
#endif /* L_call_via_rX */
/* ------------------------------------------------------------------------ */
/* Do not build the interworking functions when the target architecture does
not support Thumb instructions. (This can be a multilib option). */
#if defined L_interwork_call_via_rX
/* These labels & instructions are used by the Arm/Thumb interworking code,
when the target address is in an unknown instruction set. The address
of function to be called is loaded into a register and then one of these
labels is called via a BL instruction. This puts the return address
into the link register with the bottom bit set, and the code here
switches to the correct mode before executing the function. Unfortunately
the target code cannot be relied upon to return via a BX instruction, so
instead we have to store the resturn address on the stack and allow the
called function to return here instead. Upon return we recover the real
return address and use a BX to get back to Thumb mode. */
.text
.align 0
.code 32
.globl _arm_return
_arm_return:
ldmia r13!, {r12}
bx r12
.code 16
.macro interwork register
.code 16
THUMB_FUNC_START _interwork_call_via_\register
bx pc
nop
.code 32
.globl .Lchange_\register
.Lchange_\register:
tst \register, #1
stmeqdb r13!, {lr}
adreq lr, _arm_return
bx \register
SIZE (_interwork_call_via_\register)
.endm
interwork r0
interwork r1
interwork r2
interwork r3
interwork r4
interwork r5
interwork r6
interwork r7
interwork r8
interwork r9
interwork sl
interwork fp
interwork ip
interwork sp
/* The LR case has to be handled a little differently... */
.code 16
THUMB_FUNC_START _interwork_call_via_lr
bx pc
nop
.code 32
.globl .Lchange_lr
.Lchange_lr:
tst lr, #1
stmeqdb r13!, {lr}
mov ip, lr
adreq lr, _arm_return
bx ip
SIZE (_interwork_call_via_lr)
#endif /* L_interwork_call_via_rX */

View File

@ -0,0 +1,747 @@
@ libgcc1 routines for ARM cpu.
@ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk)
/* Copyright (C) 1995, 1996, 1998 Free Software Foundation, Inc.
This file is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
In addition to the permissions in the GNU General Public License, the
Free Software Foundation gives you unlimited permission to link the
compiled version of this file with other programs, and to distribute
those programs without any restriction coming from the use of this
file. (The General Public License restrictions do apply in other
respects; for example, they cover modification of the file, and
distribution when not linked into another program.)
This file is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* As a special exception, if you link this library with other files,
some of which are compiled with GCC, to produce an executable,
this library does not by itself cause the resulting executable
to be covered by the GNU General Public License.
This exception does not however invalidate any other reasons why
the executable file might be covered by the GNU General Public License. */
.code 16
#ifndef __USER_LABEL_PREFIX__
#error __USER_LABEL_PREFIX__ not defined
#endif
#ifdef __elf__
#define __PLT__ (PLT)
#define TYPE(x) .type SYM(x),function
#define SIZE(x) .size SYM(x), . - SYM(x)
#else
#define __PLT__
#define TYPE(x)
#define SIZE(x)
#endif
#define RET mov pc, lr
/* ANSI concatenation macros. */
#define CONCAT1(a, b) CONCAT2(a, b)
#define CONCAT2(a, b) a ## b
/* Use the right prefix for global labels. */
#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
work .req r4 @ XXXX is this safe ?
#ifdef L_udivsi3
dividend .req r0
divisor .req r1
result .req r2
curbit .req r3
ip .req r12
sp .req r13
lr .req r14
pc .req r15
.text
.globl SYM (__udivsi3)
TYPE (__udivsi3)
.align 0
.thumb_func
SYM (__udivsi3):
cmp divisor, #0
beq Ldiv0
mov curbit, #1
mov result, #0
push { work }
cmp dividend, divisor
bcc Lgot_result
@ Load the constant 0x10000000 into our work register
mov work, #1
lsl work, #28
Loop1:
@ Unless the divisor is very big, shift it up in multiples of
@ four bits, since this is the amount of unwinding in the main
@ division loop. Continue shifting until the divisor is
@ larger than the dividend.
cmp divisor, work
bcs Lbignum
cmp divisor, dividend
bcs Lbignum
lsl divisor, #4
lsl curbit, #4
b Loop1
Lbignum:
@ Set work to 0x80000000
lsl work, #3
Loop2:
@ For very big divisors, we must shift it a bit at a time, or
@ we will be in danger of overflowing.
cmp divisor, work
bcs Loop3
cmp divisor, dividend
bcs Loop3
lsl divisor, #1
lsl curbit, #1
b Loop2
Loop3:
@ Test for possible subtractions, and note which bits
@ are done in the result. On the final pass, this may subtract
@ too much from the dividend, but the result will be ok, since the
@ "bit" will have been shifted out at the bottom.
cmp dividend, divisor
bcc Over1
sub dividend, dividend, divisor
orr result, result, curbit
Over1:
lsr work, divisor, #1
cmp dividend, work
bcc Over2
sub dividend, dividend, work
lsr work, curbit, #1
orr result, work
Over2:
lsr work, divisor, #2
cmp dividend, work
bcc Over3
sub dividend, dividend, work
lsr work, curbit, #2
orr result, work
Over3:
lsr work, divisor, #3
cmp dividend, work
bcc Over4
sub dividend, dividend, work
lsr work, curbit, #3
orr result, work
Over4:
cmp dividend, #0 @ Early termination?
beq Lgot_result
lsr curbit, #4 @ No, any more bits to do?
beq Lgot_result
lsr divisor, #4
b Loop3
Lgot_result:
mov r0, result
pop { work }
RET
Ldiv0:
push { lr }
bl SYM (__div0) __PLT__
mov r0, #0 @ about as wrong as it could be
pop { pc }
SIZE (__udivsi3)
#endif /* L_udivsi3 */
#ifdef L_umodsi3
dividend .req r0
divisor .req r1
overdone .req r2
curbit .req r3
ip .req r12
sp .req r13
lr .req r14
pc .req r15
.text
.globl SYM (__umodsi3)
TYPE (__umodsi3)
.align 0
.thumb_func
SYM (__umodsi3):
cmp divisor, #0
beq Ldiv0
mov curbit, #1
cmp dividend, divisor
bcs Over1
RET
Over1:
@ Load the constant 0x10000000 into our work register
push { work }
mov work, #1
lsl work, #28
Loop1:
@ Unless the divisor is very big, shift it up in multiples of
@ four bits, since this is the amount of unwinding in the main
@ division loop. Continue shifting until the divisor is
@ larger than the dividend.
cmp divisor, work
bcs Lbignum
cmp divisor, dividend
bcs Lbignum
lsl divisor, #4
lsl curbit, #4
b Loop1
Lbignum:
@ Set work to 0x80000000
lsl work, #3
Loop2:
@ For very big divisors, we must shift it a bit at a time, or
@ we will be in danger of overflowing.
cmp divisor, work
bcs Loop3
cmp divisor, dividend
bcs Loop3
lsl divisor, #1
lsl curbit, #1
b Loop2
Loop3:
@ Test for possible subtractions. On the final pass, this may
@ subtract too much from the dividend, so keep track of which
@ subtractions are done, we can fix them up afterwards...
mov overdone, #0
cmp dividend, divisor
bcc Over2
sub dividend, dividend, divisor
Over2:
lsr work, divisor, #1
cmp dividend, work
bcc Over3
sub dividend, dividend, work
mov ip, curbit
mov work, #1
ror curbit, work
orr overdone, curbit
mov curbit, ip
Over3:
lsr work, divisor, #2
cmp dividend, work
bcc Over4
sub dividend, dividend, work
mov ip, curbit
mov work, #2
ror curbit, work
orr overdone, curbit
mov curbit, ip
Over4:
lsr work, divisor, #3
cmp dividend, work
bcc Over5
sub dividend, dividend, work
mov ip, curbit
mov work, #3
ror curbit, work
orr overdone, curbit
mov curbit, ip
Over5:
mov ip, curbit
cmp dividend, #0 @ Early termination?
beq Over6
lsr curbit, #4 @ No, any more bits to do?
beq Over6
lsr divisor, #4
b Loop3
Over6:
@ Any subtractions that we should not have done will be recorded in
@ the top three bits of "overdone". Exactly which were not needed
@ are governed by the position of the bit, stored in ip.
@ If we terminated early, because dividend became zero,
@ then none of the below will match, since the bit in ip will not be
@ in the bottom nibble.
mov work, #0xe
lsl work, #28
and overdone, work
bne Over7
pop { work }
RET @ No fixups needed
Over7:
mov curbit, ip
mov work, #3
ror curbit, work
tst overdone, curbit
beq Over8
lsr work, divisor, #3
add dividend, dividend, work
Over8:
mov curbit, ip
mov work, #2
ror curbit, work
tst overdone, curbit
beq Over9
lsr work, divisor, #2
add dividend, dividend, work
Over9:
mov curbit, ip
mov work, #1
ror curbit, work
tst overdone, curbit
beq Over10
lsr work, divisor, #1
add dividend, dividend, work
Over10:
pop { work }
RET
Ldiv0:
push { lr }
bl SYM (__div0) __PLT__
mov r0, #0 @ about as wrong as it could be
pop { pc }
SIZE (__umodsi3)
#endif /* L_umodsi3 */
#ifdef L_divsi3
dividend .req r0
divisor .req r1
result .req r2
curbit .req r3
ip .req r12
sp .req r13
lr .req r14
pc .req r15
.text
.globl SYM (__divsi3)
TYPE (__divsi3)
.align 0
.thumb_func
SYM (__divsi3):
cmp divisor, #0
beq Ldiv0
push { work }
mov work, dividend
eor work, divisor @ Save the sign of the result.
mov ip, work
mov curbit, #1
mov result, #0
cmp divisor, #0
bpl Over1
neg divisor, divisor @ Loops below use unsigned.
Over1:
cmp dividend, #0
bpl Over2
neg dividend, dividend
Over2:
cmp dividend, divisor
bcc Lgot_result
mov work, #1
lsl work, #28
Loop1:
@ Unless the divisor is very big, shift it up in multiples of
@ four bits, since this is the amount of unwinding in the main
@ division loop. Continue shifting until the divisor is
@ larger than the dividend.
cmp divisor, work
Bcs Lbignum
cmp divisor, dividend
Bcs Lbignum
lsl divisor, #4
lsl curbit, #4
b Loop1
Lbignum:
@ For very big divisors, we must shift it a bit at a time, or
@ we will be in danger of overflowing.
lsl work, #3
Loop2:
cmp divisor, work
Bcs Loop3
cmp divisor, dividend
Bcs Loop3
lsl divisor, #1
lsl curbit, #1
b Loop2
Loop3:
@ Test for possible subtractions, and note which bits
@ are done in the result. On the final pass, this may subtract
@ too much from the dividend, but the result will be ok, since the
@ "bit" will have been shifted out at the bottom.
cmp dividend, divisor
Bcc Over3
sub dividend, dividend, divisor
orr result, result, curbit
Over3:
lsr work, divisor, #1
cmp dividend, work
Bcc Over4
sub dividend, dividend, work
lsr work, curbit, #1
orr result, work
Over4:
lsr work, divisor, #2
cmp dividend, work
Bcc Over5
sub dividend, dividend, work
lsr work, curbit, #2
orr result, result, work
Over5:
lsr work, divisor, #3
cmp dividend, work
Bcc Over6
sub dividend, dividend, work
lsr work, curbit, #3
orr result, result, work
Over6:
cmp dividend, #0 @ Early termination?
Beq Lgot_result
lsr curbit, #4 @ No, any more bits to do?
Beq Lgot_result
lsr divisor, #4
b Loop3
Lgot_result:
mov r0, result
mov work, ip
cmp work, #0
Bpl Over7
neg r0, r0
Over7:
pop { work }
RET
Ldiv0:
push { lr }
bl SYM (__div0) __PLT__
mov r0, #0 @ about as wrong as it could be
pop { pc }
SIZE (__divsi3)
#endif /* L_divsi3 */
#ifdef L_modsi3
dividend .req r0
divisor .req r1
overdone .req r2
curbit .req r3
ip .req r12
sp .req r13
lr .req r14
pc .req r15
.text
.globl SYM (__modsi3)
TYPE (__modsi3)
.align 0
.thumb_func
SYM (__modsi3):
mov curbit, #1
cmp divisor, #0
beq Ldiv0
Bpl Over1
neg divisor, divisor @ Loops below use unsigned.
Over1:
push { work }
@ Need to save the sign of the dividend, unfortunately, we need
@ ip later on. Must do this after saving the original value of
@ the work register, because we will pop this value off first.
push { dividend }
cmp dividend, #0
Bpl Over2
neg dividend, dividend
Over2:
cmp dividend, divisor
bcc Lgot_result
mov work, #1
lsl work, #28
Loop1:
@ Unless the divisor is very big, shift it up in multiples of
@ four bits, since this is the amount of unwinding in the main
@ division loop. Continue shifting until the divisor is
@ larger than the dividend.
cmp divisor, work
bcs Lbignum
cmp divisor, dividend
bcs Lbignum
lsl divisor, #4
lsl curbit, #4
b Loop1
Lbignum:
@ Set work to 0x80000000
lsl work, #3
Loop2:
@ For very big divisors, we must shift it a bit at a time, or
@ we will be in danger of overflowing.
cmp divisor, work
bcs Loop3
cmp divisor, dividend
bcs Loop3
lsl divisor, #1
lsl curbit, #1
b Loop2
Loop3:
@ Test for possible subtractions. On the final pass, this may
@ subtract too much from the dividend, so keep track of which
@ subtractions are done, we can fix them up afterwards...
mov overdone, #0
cmp dividend, divisor
bcc Over3
sub dividend, dividend, divisor
Over3:
lsr work, divisor, #1
cmp dividend, work
bcc Over4
sub dividend, dividend, work
mov ip, curbit
mov work, #1
ror curbit, work
orr overdone, curbit
mov curbit, ip
Over4:
lsr work, divisor, #2
cmp dividend, work
bcc Over5
sub dividend, dividend, work
mov ip, curbit
mov work, #2
ror curbit, work
orr overdone, curbit
mov curbit, ip
Over5:
lsr work, divisor, #3
cmp dividend, work
bcc Over6
sub dividend, dividend, work
mov ip, curbit
mov work, #3
ror curbit, work
orr overdone, curbit
mov curbit, ip
Over6:
mov ip, curbit
cmp dividend, #0 @ Early termination?
beq Over7
lsr curbit, #4 @ No, any more bits to do?
beq Over7
lsr divisor, #4
b Loop3
Over7:
@ Any subtractions that we should not have done will be recorded in
@ the top three bits of "overdone". Exactly which were not needed
@ are governed by the position of the bit, stored in ip.
@ If we terminated early, because dividend became zero,
@ then none of the below will match, since the bit in ip will not be
@ in the bottom nibble.
mov work, #0xe
lsl work, #28
and overdone, work
beq Lgot_result
mov curbit, ip
mov work, #3
ror curbit, work
tst overdone, curbit
beq Over8
lsr work, divisor, #3
add dividend, dividend, work
Over8:
mov curbit, ip
mov work, #2
ror curbit, work
tst overdone, curbit
beq Over9
lsr work, divisor, #2
add dividend, dividend, work
Over9:
mov curbit, ip
mov work, #1
ror curbit, work
tst overdone, curbit
beq Lgot_result
lsr work, divisor, #1
add dividend, dividend, work
Lgot_result:
pop { work }
cmp work, #0
bpl Over10
neg dividend, dividend
Over10:
pop { work }
RET
Ldiv0:
push { lr }
bl SYM (__div0) __PLT__
mov r0, #0 @ about as wrong as it could be
pop { pc }
SIZE (__modsi3)
#endif /* L_modsi3 */
#ifdef L_dvmd_tls
.globl SYM (__div0)
TYPE (__div0)
.align 0
.thumb_func
SYM (__div0):
RET
SIZE (__div0)
#endif /* L_divmodsi_tools */
#ifdef L_call_via_rX
/* These labels & instructions are used by the Arm/Thumb interworking code.
The address of function to be called is loaded into a register and then
one of these labels is called via a BL instruction. This puts the
return address into the link register with the bottom bit set, and the
code here switches to the correct mode before executing the function. */
.text
.align 0
.macro call_via register
.globl SYM (_call_via_\register)
TYPE (_call_via_\register)
.thumb_func
SYM (_call_via_\register):
bx \register
nop
SIZE (_call_via_\register)
.endm
call_via r0
call_via r1
call_via r2
call_via r3
call_via r4
call_via r5
call_via r6
call_via r7
call_via r8
call_via r9
call_via sl
call_via fp
call_via ip
call_via sp
call_via lr
#endif /* L_call_via_rX */
#ifdef L_interwork_call_via_rX
/* These labels & instructions are used by the Arm/Thumb interworking code,
when the target address is in an unknown instruction set. The address
of function to be called is loaded into a register and then one of these
labels is called via a BL instruction. This puts the return address
into the link register with the bottom bit set, and the code here
switches to the correct mode before executing the function. Unfortunately
the target code cannot be relied upon to return via a BX instruction, so
instead we have to store the resturn address on the stack and allow the
called function to return here instead. Upon return we recover the real
return address and use a BX to get back to Thumb mode. */
.text
.align 0
.code 32
.globl _arm_return
_arm_return:
ldmia r13!, {r12}
bx r12
.macro interwork register
.code 16
.globl SYM (_interwork_call_via_\register)
TYPE (_interwork_call_via_\register)
.thumb_func
SYM (_interwork_call_via_\register):
bx pc
nop
.code 32
.globl .Lchange_\register
.Lchange_\register:
tst \register, #1
stmeqdb r13!, {lr}
adreq lr, _arm_return
bx \register
SIZE (_interwork_call_via_\register)
.endm
interwork r0
interwork r1
interwork r2
interwork r3
interwork r4
interwork r5
interwork r6
interwork r7
interwork r8
interwork r9
interwork sl
interwork fp
interwork ip
interwork sp
/* The lr case has to be handled a little differently...*/
.code 16
.globl SYM (_interwork_call_via_lr)
TYPE (_interwork_call_via_lr)
.thumb_func
SYM (_interwork_call_via_lr):
bx pc
nop
.code 32
.globl .Lchange_lr
.Lchange_lr:
tst lr, #1
stmeqdb r13!, {lr}
mov ip, lr
adreq lr, _arm_return
bx ip
SIZE (_interwork_call_via_lr)
#endif /* L_interwork_call_via_rX */

58
gcc_arm/config/arm/linux-aout.h Executable file
View File

@ -0,0 +1,58 @@
/* Definitions for ARM running Linux-based GNU systems using a.out.
Copyright (C) 1993, 1994, 1997, 1998 Free Software Foundation, Inc.
Contributed by Russell King <rmk92@ecs.soton.ac.uk>.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <linux-aout.h>
/* these are different... */
#undef STARTFILE_SPEC
#define STARTFILE_SPEC \
"%{pg:gcrt0.o%s} %{!pg:%{p:gcrt0.o%s} %{!p:crt0.o%s}} %{static:-static}"
#undef ASM_APP_ON
#undef ASM_APP_OFF
#undef COMMENT_BEGIN
/* We default to ARM3. */
#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm3
#undef CPP_PREDEFINES
#define CPP_PREDEFINES \
"-Dunix -Darm -Dlinux -Asystem(unix) -Asystem(posix) -Acpu(arm) -Amachine(arm)"
#undef LIB_SPEC
#define LIB_SPEC \
"%{mieee-fp:-lieee} %{p:-lgmon} %{pg:-lgmon} %{!ggdb:-lc} %{ggdb:-lg}"
#define HANDLE_SYSV_PRAGMA
/* Run-time Target Specification. */
#define TARGET_VERSION fputs (" (ARM GNU/Linux with a.out)", stderr);
/*
* Maths operation domain error number, EDOM
* We don't really want this for libc6. However, taking it out would be
* too much of a pain for now and it doesn't hurt much.
*/
#define TARGET_EDOM 33
#include "arm/aout.h"
#include "arm/linux-gas.h"

204
gcc_arm/config/arm/linux-elf.h Executable file
View File

@ -0,0 +1,204 @@
/* Definitions for ARM running Linux-based GNU systems using ELF
Copyright (C) 1993, 1994, 1997, 1998 Free Software Foundation, Inc.
Contributed by Philip Blundell <philb@gnu.org>
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* Run-time Target Specification. */
#define TARGET_VERSION fputs (" (ARM GNU/Linux with ELF)", stderr);
/* We have libgcc2. */
#define HAVE_ATEXIT
/* Default is to use APCS-32 mode. */
#ifndef SUBTARGET_DEFAULT_APCS26
#define TARGET_DEFAULT (ARM_FLAG_APCS_32 | ARM_FLAG_SHORT_BYTE)
#define SUBTARGET_EXTRA_LINK_SPEC \
" %{mapcs-26:-m elf32arm26} %{!mapcs-26:-m elf32arm}"
#define SUBTARGET_EXTRA_ASM_SPEC \
" %{mapcs-26:-mapcs-26} %(!mapcs-26:-mapcs-32}"
#endif
/* Now we define the strings used to build the spec file. */
#define LIB_SPEC "%{!shared:%{!symbolic:-lc}}"
/* Add the compiler's crtend, and the library's crtn. */
#define ENDFILE_SPEC "%{!shared:crtend.o%s} %{shared:crtendS.o%s} \
%{pg:gcrtn.o%s}%{!pg:crtn.o%s}"
#define STARTFILE_SPEC "%{!shared:crt1.o%s} \
crti.o%s \
%{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}"
#define LINK_SPEC "%{h*} %{version:-v} \
%{b} %{Wl,*:%*} \
%{static:-Bstatic} \
%{shared:-shared} \
%{symbolic:-Bsymbolic} \
%{rdynamic:-export-dynamic} \
%{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2} \
-X \
%{mbig-endian:-EB}" \
SUBTARGET_EXTRA_LINK_SPEC
#undef CPP_PREDEFINES
#define CPP_PREDEFINES \
"-Dunix -Darm -Dlinux -Asystem(unix) -Asystem(posix) -Acpu(arm) \
-Amachine(arm) -D__ELF__ -Darm_elf"
#ifndef SUBTARGET_DEFAULT_APCS26
#undef CPP_APCS_PC_DEFAULT_SPEC
#define CPP_APCS_PC_DEFAULT_SPEC "-D__APCS_32__"
#endif
/* Allow #sccs in preprocessor. */
#define SCCS_DIRECTIVE
#define USER_LABEL_PREFIX "" /* For ELF the default is no underscores */
#define LOCAL_LABEL_PREFIX "."
/* Attach a special .ident directive to the end of the file to identify
the version of GCC which compiled this code. */
#define IDENT_ASM_OP ".ident"
/* Output #ident as a .ident. */
#define ASM_OUTPUT_IDENT(FILE, NAME) \
fprintf (FILE, "\t%s\t\"%s\"\n", IDENT_ASM_OP, NAME);
#ifdef IDENTIFY_WITH_IDENT
#define ASM_IDENTIFY_GCC(FILE) /* nothing */
#define ASM_IDENTIFY_LANGUAGE(FILE) \
fprintf (FILE, "\t%s \"GCC (%s) %s\"\n", IDENT_ASM_OP, \
lang_identify (), version_string)
#else
#define ASM_FILE_END(FILE) \
do { \
fprintf ((FILE), "\t%s\t\"GCC: (GNU) %s\"\n", \
IDENT_ASM_OP, version_string); \
} while (0)
#endif
/* Support const sections and the ctors and dtors sections for g++.
Note that there appears to be two different ways to support const
sections at the moment. You can either #define the symbol
READONLY_DATA_SECTION (giving it some code which switches to the
readonly data section) or else you can #define the symbols
EXTRA_SECTIONS, EXTRA_SECTION_FUNCTIONS, SELECT_SECTION, and
SELECT_RTX_SECTION. We do both here just to be on the safe side. */
#define USE_CONST_SECTION 1
/* Support for Constructors and Destructors. */
#define READONLY_DATA_SECTION() const_section ()
/* A default list of other sections which we might be "in" at any given
time. For targets that use additional sections (e.g. .tdesc) you
should override this definition in the target-specific file which
includes this file. */
#define SUBTARGET_EXTRA_SECTIONS in_const,
/* A default list of extra section function definitions. For targets
that use additional sections (e.g. .tdesc) you should override this
definition in the target-specific file which includes this file. */
#define SUBTARGET_EXTRA_SECTION_FUNCTIONS CONST_SECTION_FUNCTION
extern void text_section ();
#define CONST_SECTION_ASM_OP ".section\t.rodata"
#define CONST_SECTION_FUNCTION \
void \
const_section () \
{ \
if (!USE_CONST_SECTION) \
text_section (); \
else if (in_section != in_const) \
{ \
fprintf (asm_out_file, "%s\n", CONST_SECTION_ASM_OP); \
in_section = in_const; \
} \
}
/* Switch into a generic section.
This is currently only used to support section attributes.
We make the section read-only and executable for a function decl,
read-only for a const data decl, and writable for a non-const data decl. */
#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME, RELOC) \
fprintf (FILE, ".section\t%s,\"%s\",%%progbits\n", NAME, \
(DECL) && TREE_CODE (DECL) == FUNCTION_DECL ? "ax" : \
(DECL) && DECL_READONLY_SECTION (DECL, RELOC) ? "a" : "aw")
/* A C statement or statements to switch to the appropriate
section for output of DECL. DECL is either a `VAR_DECL' node
or a constant of some sort. RELOC indicates whether forming
the initial value of DECL requires link-time relocations. */
#define SELECT_SECTION(DECL,RELOC) \
{ \
if (TREE_CODE (DECL) == STRING_CST) \
{ \
if (! flag_writable_strings) \
const_section (); \
else \
data_section (); \
} \
else if (TREE_CODE (DECL) == VAR_DECL) \
{ \
if ((flag_pic && RELOC) \
|| !TREE_READONLY (DECL) || TREE_SIDE_EFFECTS (DECL) \
|| !DECL_INITIAL (DECL) \
|| (DECL_INITIAL (DECL) != error_mark_node \
&& !TREE_CONSTANT (DECL_INITIAL (DECL)))) \
data_section (); \
else \
const_section (); \
} \
else \
const_section (); \
}
/* A C statement or statements to switch to the appropriate
section for output of RTX in mode MODE. RTX is some kind
of constant in RTL. The argument MODE is redundant except
in the case of a `const_int' rtx. Currently, these always
go into the const section. */
#define SELECT_RTX_SECTION(MODE,RTX) const_section ()
/* On svr4, we *do* have support for the .init and .fini sections, and we
can put stuff in there to be executed before and after `main'. We let
crtstuff.c and other files know this by defining the following symbols.
The definitions say how to change sections to the .init and .fini
sections. This is the same for all known svr4 assemblers. */
#define INIT_SECTION_ASM_OP ".section\t.init"
#define FINI_SECTION_ASM_OP ".section\t.fini"
/* This is how we tell the assembler that a symbol is weak. */
#define ASM_WEAKEN_LABEL(FILE,NAME) \
do { fputs ("\t.weak\t", FILE); assemble_name (FILE, NAME); \
fputc ('\n', FILE); } while (0)
/* This is how we tell the assembler that two symbols have the same value. */
#define ASM_OUTPUT_DEF(FILE,NAME1,NAME2) \
do { assemble_name (FILE, NAME1); \
fputs (" = ", FILE); \
assemble_name (FILE, NAME2); \
fputc ('\n', FILE); } while (0)
#include "arm/elf.h"
#include "arm/linux-gas.h"

View File

@ -0,0 +1,32 @@
/* Definitions for 26-bit ARM running Linux-based GNU systems using ELF
Copyright (C) 1998 Free Software Foundation, Inc.
Contributed by Philip Blundell <philb@gnu.org>
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#define SUBTARGET_DEFAULT_APCS26
#define SUBTARGET_LINK_SPEC \
" %{mapcs-32:-m elf32arm} %{!mapcs-32:-m elf32arm26}"
#define SUBTARGET_EXTRA_ASM_SPEC \
" %{mapcs-32:-mapcs-32} %(!mapcs-32:-mapcs-26}"
#define TARGET_DEFAULT (ARM_FLAG_SHORT_BYTE)
#include "arm/linux-elf.h"

87
gcc_arm/config/arm/linux-gas.h Executable file
View File

@ -0,0 +1,87 @@
/* Definitions of target machine for GNU compiler.
ARM Linux-based GNU systems version.
Copyright (C) 1997, 1998 Free Software Foundation, Inc.
Contributed by Russell King <rmk92@ecs.soton.ac.uk>.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/*
* We are using GAS, so stabs should work.
*/
#ifndef DBX_DEBUGGING_INFO
#define DBX_DEBUGGING_INFO 1
#endif
/*
* This is how we tell the assembler that a symbol is weak. GAS always
* supports weak symbols.
*/
#define ASM_WEAKEN_LABEL(FILE,NAME) \
do { fputs ("\t.weak\t", FILE); assemble_name (FILE, NAME); \
fputc ('\n', FILE); } while (0)
/* This is used in ASM_FILE_START */
#undef ARM_OS_NAME
#define ARM_OS_NAME "Linux"
/* Unsigned chars produces much better code than signed. */
#define DEFAULT_SIGNED_CHAR 0
#undef SUBTARGET_CPP_SPEC
#define SUBTARGET_CPP_SPEC "%{posix:-D_POSIX_SOURCE} %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__}"
#undef SIZE_TYPE
#define SIZE_TYPE "unsigned int"
#undef PTRDIFF_TYPE
#define PTRDIFF_TYPE "int"
#undef WCHAR_TYPE
#define WCHAR_TYPE "long int"
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE BITS_PER_WORD
#if 0 /* not yet */
/* Clear the instruction cache from `beg' to `end'. This makes an
inline system call to SYS_cacheflush. The arguments are as
follows:
cacheflush (start, end, flags)
*/
#define CLEAR_INSN_CACHE(BEG, END) \
{ \
register unsigned long _beg __asm ("a1") = (unsigned long) (BEG); \
register unsigned long _end __asm ("a2") = (unsigned long) (END); \
register unsigned long _flg __asm ("a3") = 0; \
__asm __volatile ("swi 0x9000b8"); \
}
#endif
/* If cross-compiling, don't require stdio.h etc to build libgcc.a. */
#ifdef CROSS_COMPILE
#ifndef inhibit_libc
#define inhibit_libc
#endif
#endif

72
gcc_arm/config/arm/linux.h Executable file
View File

@ -0,0 +1,72 @@
/* Definitions for ARM running Linux-based GNU systems.
Copyright (C) 1993, 1994, 1997 Free Software Foundation, Inc.
Contributed by Russell King <rmk92@ecs.soton.ac.uk>.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <linux-aout.h>
/* these are different... */
#undef STARTFILE_SPEC
#define STARTFILE_SPEC \
"%{pg:gcrt0.o%s} %{!pg:%{p:gcrt0.o%s} %{!p:crt0.o%s}} %{static:-static}"
#undef ASM_APP_ON
#undef ASM_APP_OFF
#undef COMMENT_BEGIN
/* We default to ARM3. */
#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm3
#undef CPP_PREDEFINES
#define CPP_PREDEFINES \
"-Dunix -Darm -Dlinux -Asystem(unix) -Asystem(posix) -Acpu(arm) -Amachine(arm)"
#undef LIB_SPEC
#define LIB_SPEC \
"%{mieee-fp:-lieee} %{p:-lgmon} %{pg:-lgmon} %{!ggdb:-lc} %{ggdb:-lg}"
#undef SIZE_TYPE
#define SIZE_TYPE "unsigned int"
#undef PTRDIFF_TYPE
#define PTRDIFF_TYPE "int"
#undef WCHAR_TYPE
#define WCHAR_TYPE "long int"
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE BITS_PER_WORD
#define HANDLE_SYSV_PRAGMA
/* Run-time Target Specification. */
#define TARGET_VERSION fputs (" (ARM GNU/Linux with a.out)", stderr);
/* This is used in ASM_FILE_START */
#define ARM_OS_NAME "Linux"
/* Unsigned chars produces much better code than signed. */
#define DEFAULT_SIGNED_CHAR 0
/* Maths operation domain error number, EDOM */
#define TARGET_EDOM 33
#include "arm/aout.h"
#undef SUBTARGET_CPP_SPEC
#define SUBTARGET_CPP_SPEC "%{posix:-D_POSIX_SOURCE}"

161
gcc_arm/config/arm/netbsd.h Executable file
View File

@ -0,0 +1,161 @@
/* NetBSD/arm (RiscBSD) version.
Copyright (C) 1993, 1994, 1997, 1998 Free Software Foundation, Inc.
Contributed by Mark Brinicombe (amb@physig.ph.kcl.ac.uk)
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* Run-time Target Specification. */
#define TARGET_VERSION fputs (" (ARM/NetBSD)", stderr);
/* This is used in ASM_FILE_START. */
#define ARM_OS_NAME "NetBSD"
/* Unsigned chars produces much better code than signed. */
#define DEFAULT_SIGNED_CHAR 0
/* Since we always use GAS as our assembler we support stabs. */
#define DBX_DEBUGGING_INFO 1
/*#undef ASM_DECLARE_FUNCTION_NAME*/
/* ARM6 family default cpu. */
#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm6
/* Default is to use APCS-32 mode. */
#define TARGET_DEFAULT (ARM_FLAG_APCS_32 | ARM_FLAG_SOFT_FLOAT)
#include "arm/aout.h"
/* This gets redefined in config/netbsd.h. */
#undef TARGET_MEM_FUNCTIONS
#include <netbsd.h>
/* Until they use ELF or something that handles dwarf2 unwinds
and initialization stuff better. */
#undef DWARF2_UNWIND_INFO
/* Some defines for CPP.
arm32 is the NetBSD port name, so we always define arm32 and __arm32__. */
#undef CPP_PREDEFINES
#define CPP_PREDEFINES "\
-Dunix -Driscbsd -Darm32 -D__arm32__ -D__arm__ -D__NetBSD__ \
-Asystem(unix) -Asystem(NetBSD) -Acpu(arm) -Amachine(arm)"
/* Define _POSIX_SOURCE if necessary. */
#undef CPP_SPEC
#define CPP_SPEC "\
%(cpp_cpu_arch) %(cpp_apcs_pc) %(cpp_float) %(cpp_endian) \
%{posix:-D_POSIX_SOURCE} \
"
/* Because TARGET_DEFAULT sets ARM_FLAG_APCS_32 */
#undef CPP_APCS_PC_DEFAULT_SPEC
#define CPP_APCS_PC_DEFAULT_SPEC "-D__APCS_32__"
/* Because TARGET_DEFAULT sets ARM_FLAG_SOFT_FLOAT */
#undef CPP_FLOAT_DEFAULT_SPEC
#define CPP_FLOAT_DEFAULT_SPEC "-D__SOFTFP__"
/* Pass -X to the linker so that it will strip symbols starting with 'L' */
#undef LINK_SPEC
#define LINK_SPEC "\
-X %{!nostdlib:%{!r*:%{!e*:-e start}}} -dc -dp %{R*} \
%{static:-Bstatic} %{assert*} \
"
#undef SIZE_TYPE
#define SIZE_TYPE "unsigned int"
#undef PTRDIFF_TYPE
#define PTRDIFF_TYPE "int"
#undef WCHAR_TYPE
#define WCHAR_TYPE "int"
#undef WCHAR_UNSIGNED
#define WCHAR_UNSIGNED 0
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE 32
#define HANDLE_SYSV_PRAGMA
/* We don't have any limit on the length as out debugger is GDB. */
#undef DBX_CONTIN_LENGTH
/* NetBSD does its profiling differently to the Acorn compiler. We
don't need a word following the mcount call; and to skip it
requires either an assembly stub or use of fomit-frame-pointer when
compiling the profiling functions. Since we break Acorn CC
compatibility below a little more won't hurt. */
#undef FUNCTION_PROFILER
#define FUNCTION_PROFILER(STREAM,LABELNO) \
{ \
fprintf(STREAM, "\tmov\t%sip, %slr\n", REGISTER_PREFIX, REGISTER_PREFIX); \
fprintf(STREAM, "\tbl\tmcount\n"); \
}
/* On the ARM `@' introduces a comment, so we must use something else
for .type directives. */
#undef TYPE_OPERAND_FMT
#define TYPE_OPERAND_FMT "%%%s"
/* NetBSD uses the old PCC style aggregate returning conventions. */
#undef DEFAULT_PCC_STRUCT_RETURN
#define DEFAULT_PCC_STRUCT_RETURN 1
/* Although not normally relevant (since by default, all aggregates
are returned in memory) compiling some parts of libc requires
non-APCS style struct returns. */
#undef RETURN_IN_MEMORY
/* VERY BIG NOTE : Change of structure alignment for RiscBSD.
There are consequences you should be aware of...
Normally GCC/arm uses a structure alignment of 32 for compatibility
with armcc. This means that structures are padded to a word
boundary. However this causes problems with bugged NetBSD kernel
code (possibly userland code as well - I have not checked every
binary). The nature of this bugged code is to rely on sizeof()
returning the correct size of various structures rounded to the
nearest byte (SCSI and ether code are two examples, the vm system
is another). This code breaks when the structure alignment is 32
as sizeof() will report a word=rounded size. By changing the
structure alignment to 8. GCC will conform to what is expected by
NetBSD.
This has several side effects that should be considered.
1. Structures will only be aligned to the size of the largest member.
i.e. structures containing only bytes will be byte aligned.
structures containing shorts will be half word alinged.
structures containing ints will be word aligned.
This means structures should be padded to a word boundary if
alignment of 32 is required for byte structures etc.
2. A potential performance penalty may exist if strings are no longer
word aligned. GCC will not be able to use word load/stores to copy
short strings.
This modification is not encouraged but with the present state of the
NetBSD source tree it is currently the only solution that meets the
requirements. */
#undef STRUCTURE_SIZE_BOUNDARY
#define STRUCTURE_SIZE_BOUNDARY 8

521
gcc_arm/config/arm/pe.c Executable file
View File

@ -0,0 +1,521 @@
/* CYGNUS LOCAL dje/pe, entire file */
/* Routines for GCC for ARM/pe.
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
Contributed by Doug Evans (dje@cygnus.com).
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <stdio.h>
#include <string.h>
#include "config.h"
#include "rtl.h"
#include "output.h"
#include "flags.h"
#include "tree.h"
#include "expr.h"
extern int current_function_anonymous_args;
/* ARM/PE specific attribute support.
ARM/PE has three new attributes:
naked - for interrupt functions
dllexport - for exporting a function/variable that will live in a dll
dllimport - for importing a function/variable from a dll
Microsoft allows multiple declspecs in one __declspec, separating
them with spaces. We do NOT support this. Instead, use __declspec
multiple times.
*/
/* Return nonzero if ATTR is a valid attribute for DECL.
ATTRIBUTES are any existing attributes and ARGS are the arguments
supplied with ATTR. */
int
arm_pe_valid_machine_decl_attribute (decl, attributes, attr, args)
tree decl;
tree attributes;
tree attr;
tree args;
{
if (args != NULL_TREE)
return 0;
if (is_attribute_p ("dllexport", attr))
return 1;
if (is_attribute_p ("dllimport", attr))
return 1;
return arm_valid_machine_decl_attribute (decl, attributes, attr, args);
}
#if 0 /* needed when we tried type attributes */
/* Return zero if TYPE1 and TYPE2 are incompatible, one if they are compatible,
and two if they are nearly compatible (which causes a warning to be
generated). */
int
arm_pe_comp_type_attributes (type1, type2)
tree type1, type2;
{
type1 = TYPE_ATTRIBUTES (type1);
type2 = TYPE_ATTRIBUTES (type2);
if (lookup_attribute ("dllimport", type1)
&& lookup_attribute ("dllexport", type2))
return 0;
if (lookup_attribute ("dllimport", type2)
&& lookup_attribute ("dllexport", type1))
return 0;
return 1;
}
#endif
/* Merge attributes in decls OLD and NEW.
This handles the following situation:
__declspec (dllimport) int foo;
int foo;
The second instance of `foo' nullifies the dllimport. */
tree
arm_pe_merge_machine_decl_attributes (old, new)
tree old, new;
{
tree a;
int delete_dllimport_p;
old = DECL_MACHINE_ATTRIBUTES (old);
new = DECL_MACHINE_ATTRIBUTES (new);
/* What we need to do here is remove from `old' dllimport if it doesn't
appear in `new'. dllimport behaves like extern: if a declaration is
marked dllimport and a definition appears later, then the object
is not dllimport'd. */
if (lookup_attribute ("dllimport", old) != NULL_TREE
&& lookup_attribute ("dllimport", new) == NULL_TREE)
delete_dllimport_p = 1;
else
delete_dllimport_p = 0;
a = merge_attributes (old, new);
if (delete_dllimport_p)
{
tree prev,t;
/* Scan the list for dllimport and delete it. */
for (prev = NULL_TREE, t = a; t; prev = t, t = TREE_CHAIN (t))
{
if (is_attribute_p ("dllimport", TREE_PURPOSE (t)))
{
if (prev == NULL_TREE)
a = TREE_CHAIN (a);
else
TREE_CHAIN (prev) = TREE_CHAIN (t);
break;
}
}
}
return a;
}
/* Check a type that has a virtual table, and see if any virtual methods are
marked for import or export, and if so, arrange for the vtable to
be imported or exported. */
static int
arm_check_vtable_importexport (type)
tree type;
{
tree methods = TYPE_METHODS (type);
tree fndecl;
if (TREE_CODE (methods) == FUNCTION_DECL)
fndecl = methods;
else if (TREE_VEC_ELT (methods, 0) != NULL_TREE)
fndecl = TREE_VEC_ELT (methods, 0);
else
fndecl = TREE_VEC_ELT (methods, 1);
while (fndecl)
{
if (DECL_VIRTUAL_P (fndecl) || DECL_VINDEX (fndecl) != NULL_TREE)
{
tree exp = lookup_attribute ("dllimport",
DECL_MACHINE_ATTRIBUTES (fndecl));
if (exp == 0)
exp = lookup_attribute ("dllexport",
DECL_MACHINE_ATTRIBUTES (fndecl));
if (exp)
return 1;
}
fndecl = TREE_CHAIN (fndecl);
}
return 0;
}
/* Return non-zero if DECL is a dllexport'd object. */
tree current_class_type; /* FIXME */
int
arm_dllexport_p (decl)
tree decl;
{
tree exp;
if (TREE_CODE (decl) != VAR_DECL
&& TREE_CODE (decl) != FUNCTION_DECL)
return 0;
exp = lookup_attribute ("dllexport", DECL_MACHINE_ATTRIBUTES (decl));
if (exp)
return 1;
#if 0 /* This was a hack to get vtable's exported or imported since only one
copy of them is ever output. Disabled pending better solution. */
/* For C++, the vtables might have to be marked. */
if (TREE_CODE (decl) == VAR_DECL && DECL_VIRTUAL_P (decl))
{
if (TREE_PUBLIC (decl)
&& DECL_EXTERNAL (decl) == 0
&& (DECL_CONTEXT (decl)
? arm_check_vtable_importexport (DECL_CONTEXT (decl))
: current_class_type
? arm_check_vtable_importexport (current_class_type)
: 0)
)
return 1;
}
#endif
return 0;
}
/* Return non-zero if DECL is a dllimport'd object. */
int
arm_dllimport_p (decl)
tree decl;
{
tree imp;
if (TREE_CODE (decl) == FUNCTION_DECL
&& TARGET_NOP_FUN_DLLIMPORT)
return 0;
if (TREE_CODE (decl) != VAR_DECL
&& TREE_CODE (decl) != FUNCTION_DECL)
return 0;
imp = lookup_attribute ("dllimport", DECL_MACHINE_ATTRIBUTES (decl));
if (imp)
return 1;
#if 0 /* This was a hack to get vtable's exported or imported since only one
copy of them is ever output. Disabled pending better solution. */
/* For C++, the vtables might have to be marked. */
if (TREE_CODE (decl) == VAR_DECL && DECL_VIRTUAL_P (decl))
{
if (TREE_PUBLIC (decl)
&& DECL_EXTERNAL (decl)
&& (DECL_CONTEXT (decl)
? arm_check_vtable_importexport (DECL_CONTEXT (decl))
: current_class_type
? arm_check_vtable_importexport (current_class_type)
: 0)
)
return 1;
}
#endif
return 0;
}
/* Return non-zero if SYMBOL is marked as being dllexport'd. */
int
arm_dllexport_name_p (symbol)
char *symbol;
{
return symbol[0] == '@' && symbol[1] == 'e' && symbol[2] == '.';
}
/* Return non-zero if SYMBOL is marked as being dllimport'd. */
int
arm_dllimport_name_p (symbol)
char *symbol;
{
return symbol[0] == '@' && symbol[1] == 'i' && symbol[2] == '.';
}
/* Mark a DECL as being dllexport'd.
Note that we override the previous setting (eg: dllimport). */
void
arm_mark_dllexport (decl)
tree decl;
{
char *oldname, *newname;
rtx rtlname;
tree idp;
rtlname = XEXP (DECL_RTL (decl), 0);
if (GET_CODE (rtlname) == SYMBOL_REF)
oldname = XSTR (rtlname, 0);
else if (GET_CODE (rtlname) == MEM
&& GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)
oldname = XSTR (XEXP (rtlname, 0), 0);
else
abort ();
if (arm_dllimport_name_p (oldname))
oldname += 9;
else if (arm_dllexport_name_p (oldname))
return; /* already done */
newname = alloca (strlen (oldname) + 4);
sprintf (newname, "@e.%s", oldname);
/* We pass newname through get_identifier to ensure it has a unique
address. RTL processing can sometimes peek inside the symbol ref
and compare the string's addresses to see if two symbols are
identical. */
/* ??? At least I think that's why we do this. */
idp = get_identifier (newname);
XEXP (DECL_RTL (decl), 0) =
gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (idp));
}
/* Mark a DECL as being dllimport'd. */
void
arm_mark_dllimport (decl)
tree decl;
{
char *oldname, *newname;
tree idp;
rtx rtlname, newrtl;
rtlname = XEXP (DECL_RTL (decl), 0);
if (GET_CODE (rtlname) == SYMBOL_REF)
oldname = XSTR (rtlname, 0);
else if (GET_CODE (rtlname) == MEM
&& GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)
oldname = XSTR (XEXP (rtlname, 0), 0);
else
abort ();
if (arm_dllexport_name_p (oldname))
abort (); /* this shouldn't happen */
else if (arm_dllimport_name_p (oldname))
return; /* already done */
/* ??? One can well ask why we're making these checks here,
and that would be a good question. */
/* Imported variables can't be initialized. */
if (TREE_CODE (decl) == VAR_DECL
&& !DECL_VIRTUAL_P (decl)
&& DECL_INITIAL (decl))
{
error_with_decl (decl, "initialized variable `%s' is marked dllimport");
return;
}
/* Nor can they be static. */
if (TREE_CODE (decl) == VAR_DECL
/* ??? Is this test for vtables needed? */
&& !DECL_VIRTUAL_P (decl)
&& 0 /*???*/)
{
error_with_decl (decl, "static variable `%s' is marked dllimport");
return;
}
/* `extern' needn't be specified with dllimport.
Specify `extern' now and hope for the best. Sigh. */
if (TREE_CODE (decl) == VAR_DECL
/* ??? Is this test for vtables needed? */
&& !DECL_VIRTUAL_P (decl))
{
DECL_EXTERNAL (decl) = 1;
TREE_PUBLIC (decl) = 1;
}
newname = alloca (strlen (oldname) + 11);
sprintf (newname, "@i.__imp_%s", oldname);
/* We pass newname through get_identifier to ensure it has a unique
address. RTL processing can sometimes peek inside the symbol ref
and compare the string's addresses to see if two symbols are
identical. */
/* ??? At least I think that's why we do this. */
idp = get_identifier (newname);
newrtl = gen_rtx (MEM, Pmode,
gen_rtx (SYMBOL_REF, Pmode,
IDENTIFIER_POINTER (idp)));
XEXP (DECL_RTL (decl), 0) = newrtl;
}
/* Cover function to implement ENCODE_SECTION_INFO. */
void
arm_pe_encode_section_info (decl)
tree decl;
{
/* This bit is copied from arm.h. */
if (optimize > 0 && TREE_CONSTANT (decl)
&& (!flag_writable_strings || TREE_CODE (decl) != STRING_CST))
{
rtx rtl = (TREE_CODE_CLASS (TREE_CODE (decl)) != 'd'
? TREE_CST_RTL (decl) : DECL_RTL (decl));
SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
}
/* Mark the decl so we can tell from the rtl whether the object is
dllexport'd or dllimport'd. */
if (arm_dllexport_p (decl))
arm_mark_dllexport (decl);
else if (arm_dllimport_p (decl))
arm_mark_dllimport (decl);
/* It might be that DECL has already been marked as dllimport, but a
subsequent definition nullified that. The attribute is gone but
DECL_RTL still has @i.__imp_foo. We need to remove that. */
else if ((TREE_CODE (decl) == FUNCTION_DECL
|| TREE_CODE (decl) == VAR_DECL)
&& DECL_RTL (decl) != NULL_RTX
&& GET_CODE (DECL_RTL (decl)) == MEM
&& GET_CODE (XEXP (DECL_RTL (decl), 0)) == MEM
&& GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == SYMBOL_REF
&& arm_dllimport_name_p (XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0)))
{
char *oldname = XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0);
tree idp = get_identifier (oldname + 9);
rtx newrtl = gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (idp));
XEXP (DECL_RTL (decl), 0) = newrtl;
/* We previously set TREE_PUBLIC and DECL_EXTERNAL.
??? We leave these alone for now. */
}
}
/* Cover function for UNIQUE_SECTION. */
void
arm_pe_unique_section (decl, reloc)
tree decl;
int reloc;
{
int len;
char *name,*string,*prefix;
name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
/* Strip off any encoding in fnname. */
STRIP_NAME_ENCODING (name, name);
/* The object is put in, for example, section .text$foo.
The linker will then ultimately place them in .text
(everything from the $ on is stripped). */
if (TREE_CODE (decl) == FUNCTION_DECL)
prefix = ".text$";
else if (DECL_READONLY_SECTION (decl, reloc))
prefix = ".rdata$";
else
prefix = ".data$";
len = strlen (name) + strlen (prefix);
string = alloca (len + 1);
sprintf (string, "%s%s", prefix, name);
DECL_SECTION_NAME (decl) = build_string (len, string);
}
/* This is to better conform to the ARM PCS.
Richard Earnshaw hasn't put this into FSF sources yet so it's here. */
int
arm_pe_return_in_memory (type)
tree type;
{
if (TREE_CODE (type) == RECORD_TYPE)
{
tree field;
int num_fields = 0;
/* For a record containing just a single element, we can be a little
less restrictive. */
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
{
if (TREE_CODE (field) == FIELD_DECL && ! TREE_STATIC (field))
{
if ((AGGREGATE_TYPE_P (TREE_TYPE (field))
&& RETURN_IN_MEMORY (TREE_TYPE (field)))
|| FLOAT_TYPE_P (TREE_TYPE (field)))
return 1;
num_fields++;
}
}
if (num_fields == 1)
return 0;
/* For a struct, we can return in a register if every element was a
bit-field and it all fits in one word. */
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
{
if (TREE_CODE (field) == FIELD_DECL
&& ! TREE_STATIC (field)
&& (! DECL_BIT_FIELD_TYPE (field)
|| (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field))
+ TREE_INT_CST_LOW (DECL_SIZE (field))) > 32))
return 1;
}
return 0;
}
else if (TREE_CODE (type) == UNION_TYPE
|| TREE_CODE (type) == QUAL_UNION_TYPE)
{
tree field;
/* Unions can be returned in registers if every element is
integral, or can be returned in an integer register. */
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
{
if (TREE_CODE (field) == FIELD_DECL
&& ! TREE_STATIC (field)
&& ((AGGREGATE_TYPE_P (TREE_TYPE (field))
&& RETURN_IN_MEMORY (TREE_TYPE (field)))
|| FLOAT_TYPE_P (TREE_TYPE (field))))
return 1;
}
return 0;
}
/* XXX Not sure what should be done for other aggregates, so put them in
memory. */
return 1;
}

295
gcc_arm/config/arm/pe.h Executable file
View File

@ -0,0 +1,295 @@
/* CYGNUS LOCAL entire file */
/* Definitions of target machine for GNU compiler, for ARM with PE obj format.
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
Contributed by Doug Evans (dje@cygnus.com).
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "arm/coff.h"
#undef USER_LABEL_PREFIX
#define USER_LABEL_PREFIX "_"
/* Run-time Target Specification. */
#undef TARGET_VERSION
#define TARGET_VERSION fputs (" (ARM/pe)", stderr)
/* Support the __declspec keyword by turning them into attributes.
We currently only support: naked, dllimport, and dllexport.
Note that the current way we do this may result in a collision with
predefined attributes later on. This can be solved by using one attribute,
say __declspec__, and passing args to it. The problem with that approach
is that args are not accumulated: each new appearance would clobber any
existing args. */
#undef CPP_PREDEFINES
#define CPP_PREDEFINES "\
-Darm -D__pe__ -Acpu(arm) -Amachine(arm) \
-D__declspec(x)=__attribute__((x)) \
"
/* Experimental addition for pr 7885.
Ignore dllimport for functions. */
#define TARGET_NOP_FUN_DLLIMPORT (target_flags & 0x20000)
#undef SUBTARGET_SWITCHES
#define SUBTARGET_SWITCHES \
{ "nop-fun-dllimport", 0x20000 }, \
{ "no-nop-fun-dllimport", -0x20000 },
#undef TARGET_DEFAULT
#define TARGET_DEFAULT (ARM_FLAG_SOFT_FLOAT + 0x20000)
#undef WCHAR_TYPE
#define WCHAR_TYPE "short unsigned int"
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE 16
/* Same as arm.h except r10 is call-saved, not fixed. */
#undef FIXED_REGISTERS
#define FIXED_REGISTERS \
{ \
0,0,0,0,0,0,0,0, \
0,0,0,1,0,1,0,1, \
0,0,0,0,0,0,0,0, \
1,1,1 \
}
/* Same as arm.h except r10 is call-saved, not fixed. */
#undef CALL_USED_REGISTERS
#define CALL_USED_REGISTERS \
{ \
1,1,1,1,0,0,0,0, \
0,0,0,1,1,1,1,1, \
1,1,1,1,0,0,0,0, \
1,1,1 \
}
/* This is to better conform to the ARM PCS.
Richard Earnshaw hasn't put this into FSF sources yet so it's here. */
#undef RETURN_IN_MEMORY
#define RETURN_IN_MEMORY(TYPE) \
((TYPE_MODE ((TYPE)) == BLKmode && ! TYPE_NO_FORCE_BLK (TYPE)) \
|| (AGGREGATE_TYPE_P ((TYPE)) && arm_pe_return_in_memory ((TYPE))))
/* A C expression whose value is nonzero if IDENTIFIER with arguments ARGS
is a valid machine specific attribute for DECL.
The attributes in ATTRIBUTES have previously been assigned to DECL. */
extern int arm_pe_valid_machine_decl_attribute ();
#undef VALID_MACHINE_DECL_ATTRIBUTE
#define VALID_MACHINE_DECL_ATTRIBUTE(DECL, ATTRIBUTES, IDENTIFIER, ARGS) \
arm_pe_valid_machine_decl_attribute (DECL, ATTRIBUTES, IDENTIFIER, ARGS)
#if 0 /* Needed when we tried type attributes. */
/* A C expression whose value is zero if the attributes on
TYPE1 and TYPE2 are incompatible, one if they are compatible,
and two if they are nearly compatible (which causes a warning to be
generated). */
extern int arm_pe_comp_type_attributes ();
#define COMP_TYPE_ATTRIBUTES(TYPE1, TYPE2) \
arm_pe_comp_type_attributes ((TYPE1), (TYPE2))
#endif
extern union tree_node *arm_pe_merge_machine_decl_attributes ();
#define MERGE_MACHINE_DECL_ATTRIBUTES(OLD, NEW) \
arm_pe_merge_machine_decl_attributes ((OLD), (NEW))
/* In addition to the stuff done in arm.h, we must mark dll symbols specially.
Definitions of dllexport'd objects install some info in the .drectve
section. References to dllimport'd objects are fetched indirectly via
__imp_. If both are declared, dllexport overrides.
This is also needed to implement one-only vtables: they go into their own
section and we need to set DECL_SECTION_NAME so we do that here.
Note that we can be called twice on the same decl. */
extern void arm_pe_encode_section_info ();
#undef ENCODE_SECTION_INFO
#define ENCODE_SECTION_INFO(DECL) \
arm_pe_encode_section_info (DECL)
/* Used to implement dllexport overriding dllimport semantics. It's also used
to handle vtables - the first pass won't do anything because
DECL_CONTEXT (DECL) will be 0 so arm_dll{ex,im}port_p will return 0.
It's also used to handle dllimport override semantics. */
#if 0
#define REDO_SECTION_INFO_P(DECL) \
((DECL_MACHINE_ATTRIBUTES (DECL) != NULL_TREE) \
|| (TREE_CODE (DECL) == VAR_DECL && DECL_VIRTUAL_P (DECL)))
#else
#define REDO_SECTION_INFO_P(DECL) 1
#endif
/* Utility used only in this file. */
#define ARM_STRIP_NAME_ENCODING(SYM_NAME) \
((SYM_NAME) + ((SYM_NAME)[0] == '@' ? 3 : 0))
/* Strip any text from SYM_NAME added by ENCODE_SECTION_INFO and store
the result in VAR. */
#undef STRIP_NAME_ENCODING
#define STRIP_NAME_ENCODING(VAR, SYM_NAME) \
(VAR) = ARM_STRIP_NAME_ENCODING (SYM_NAME)
/* Define this macro if in some cases global symbols from one translation
unit may not be bound to undefined symbols in another translation unit
without user intervention. For instance, under Microsoft Windows
symbols must be explicitly imported from shared libraries (DLLs). */
#define MULTIPLE_SYMBOL_SPACES
#define UNIQUE_SECTION_P(DECL) DECL_ONE_ONLY (DECL)
extern void arm_pe_unique_section ();
#define UNIQUE_SECTION(DECL,RELOC) arm_pe_unique_section (DECL, RELOC)
#define SUPPORTS_ONE_ONLY 1
/* A C statement to output something to the assembler file to switch to section
NAME for object DECL which is either a FUNCTION_DECL, a VAR_DECL or
NULL_TREE. Some target formats do not support arbitrary sections. Do not
define this macro in such cases. */
#undef ASM_OUTPUT_SECTION_NAME
#define ASM_OUTPUT_SECTION_NAME(STREAM, DECL, NAME, RELOC) \
do { \
if ((DECL) && TREE_CODE (DECL) == FUNCTION_DECL) \
fprintf (STREAM, "\t.section %s,\"x\"\n", (NAME)); \
else if ((DECL) && DECL_READONLY_SECTION (DECL, RELOC)) \
fprintf (STREAM, "\t.section %s,\"\"\n", (NAME)); \
else \
fprintf (STREAM, "\t.section %s,\"w\"\n", (NAME)); \
/* Functions may have been compiled at various levels of \
optimization so we can't use `same_size' here. Instead, \
have the linker pick one. */ \
if ((DECL) && DECL_ONE_ONLY (DECL)) \
fprintf (STREAM, "\t.linkonce %s\n", \
TREE_CODE (DECL) == FUNCTION_DECL \
? "discard" : "same_size"); \
} while (0)
/* This outputs a lot of .req's to define alias for various registers.
Let's try to avoid this. */
#undef ASM_FILE_START
#define ASM_FILE_START(STREAM) \
do { \
extern char *version_string; \
fprintf (STREAM, "%s Generated by gcc %s for ARM/pe\n", \
ASM_COMMENT_START, version_string); \
output_file_directive ((STREAM), main_input_filename); \
} while (0)
/* Output a reference to a label. */
#undef ASM_OUTPUT_LABELREF
#define ASM_OUTPUT_LABELREF(STREAM, NAME) \
fprintf (STREAM, "%s%s", USER_LABEL_PREFIX, ARM_STRIP_NAME_ENCODING (NAME))
/* Output a function definition label. */
#undef ASM_DECLARE_FUNCTION_NAME
#define ASM_DECLARE_FUNCTION_NAME(STREAM, NAME, DECL) \
do { \
if (arm_dllexport_name_p (NAME)) \
{ \
drectve_section (); \
fprintf (STREAM, "\t.ascii \" -export:%s\"\n", \
ARM_STRIP_NAME_ENCODING (NAME)); \
function_section (DECL); \
} \
ASM_OUTPUT_LABEL ((STREAM), (NAME)); \
} while (0)
/* Output a common block. */
#undef ASM_OUTPUT_COMMON
#define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED) \
do { \
if (arm_dllexport_name_p (NAME)) \
{ \
drectve_section (); \
fprintf ((STREAM), "\t.ascii \" -export:%s\"\n", \
ARM_STRIP_NAME_ENCODING (NAME)); \
} \
if (! arm_dllimport_name_p (NAME)) \
{ \
fprintf ((STREAM), "\t.comm\t"); \
assemble_name ((STREAM), (NAME)); \
fprintf ((STREAM), ", %d\t%s %d\n", \
(ROUNDED), ASM_COMMENT_START, (SIZE)); \
} \
} while (0)
/* Output the label for an initialized variable. */
#undef ASM_DECLARE_OBJECT_NAME
#define ASM_DECLARE_OBJECT_NAME(STREAM, NAME, DECL) \
do { \
if (arm_dllexport_name_p (NAME)) \
{ \
enum in_section save_section = in_section; \
drectve_section (); \
fprintf (STREAM, "\t.ascii \" -export:%s\"\n", \
ARM_STRIP_NAME_ENCODING (NAME)); \
switch_to_section (save_section, (DECL)); \
} \
ASM_OUTPUT_LABEL ((STREAM), (NAME)); \
} while (0)
/* Support the ctors/dtors and other sections. */
#define DRECTVE_SECTION_ASM_OP "\t.section .drectve"
/* A list of other sections which the compiler might be "in" at any
given time. */
#undef SUBTARGET_EXTRA_SECTIONS
#define SUBTARGET_EXTRA_SECTIONS in_drectve,
/* A list of extra section function definitions. */
#undef SUBTARGET_EXTRA_SECTION_FUNCTIONS
#define SUBTARGET_EXTRA_SECTION_FUNCTIONS \
DRECTVE_SECTION_FUNCTION \
SWITCH_TO_SECTION_FUNCTION
#define DRECTVE_SECTION_FUNCTION \
void \
drectve_section () \
{ \
if (in_section != in_drectve) \
{ \
fprintf (asm_out_file, "%s\n", DRECTVE_SECTION_ASM_OP); \
in_section = in_drectve; \
} \
}
/* Switch to SECTION (an `enum in_section').
??? This facility should be provided by GCC proper.
The problem is that we want to temporarily switch sections in
ASM_DECLARE_OBJECT_NAME and then switch back to the original section
afterwards. */
#define SWITCH_TO_SECTION_FUNCTION \
void \
switch_to_section (section, decl) \
enum in_section section; \
tree decl; \
{ \
switch (section) \
{ \
case in_text: text_section (); break; \
case in_data: data_section (); break; \
case in_named: named_section (decl, NULL, 0); break; \
case in_rdata: rdata_section (); break; \
case in_ctors: ctors_section (); break; \
case in_dtors: dtors_section (); break; \
case in_drectve: drectve_section (); break; \
default: abort (); break; \
} \
}

151
gcc_arm/config/arm/riscix.h Executable file
View File

@ -0,0 +1,151 @@
/* Definitions of target machine for GNU compiler. ARM RISCiX version.
Copyright (C) 1993, 1994, 1995, 1997 Free Software Foundation, Inc.
Contributed by Richard Earnshaw (rwe11@cl.cam.ac.uk), based on original
work by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
and Martin Simmons (@harleqn.co.uk).
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* Translation to find startup files. On RISC iX boxes,
crt0, mcrt0 and gcrt0.o are in /usr/lib. */
#define STARTFILE_SPEC "\
%{pg:/usr/lib/gcrt0.o%s}\
%{!pg:%{p:/usr/lib/mcrt0.o%s}\
%{!p:/usr/lib/crt0.o%s}}"
/* RISC iX has no concept of -lg */
/* If -static is specified then link with -lc_n */
#ifndef LIB_SPEC
#define LIB_SPEC "\
%{g*:-lg}\
%{!p:%{!pg:%{!static:-lc}%{static:-lc_n}}}\
%{p:-lc_p}\
%{pg:-lc_p}"
#endif
/* The RISC iX assembler never deletes any symbols from the object module;
and, by default, ld doesn't either. -X causes local symbols starting
with 'L' to be deleted, which is what we want. */
#ifndef LINK_SPEC
#define LINK_SPEC "-X"
#endif
#ifndef CPP_PREDEFINES
#define CPP_PREDEFINES \
"-Darm -Driscix -Dunix -Asystem(unix) -Acpu(arm) -Amachine(arm)"
#endif
#ifndef CPP_SPEC /* CYGNYS LOCAL */
#define CPP_SPEC "%{m6:-D__arm6__} \
%{mbsd:%{pedantic:%e-mbsd and -pedantic incompatible} -D_BSD_C} \
%{mxopen:%{mbsd:%e-mbsd and -mxopen incompatible} \
%{pedantic:%e-mxopen and -pedantic incompatible} -D_XOPEN_C} \
%{!mbsd:%{!mxopen:%{!ansi: -D_BSD_C}}}"
#endif /* END CYGNUS LOCAL */
/* RISCiX has some weird symbol name munging, that is done to the object module
after assembly, which enables multiple libraries to be supported within
one (possibly shared) library. It basically changes the symbol name of
certain symbols (for example _bcopy is converted to _$bcopy if using BSD)
Symrename's parameters are determined as follows:
-mno-symrename Don't run symrename
-mbsd symrename -BSD <file>
-mxopen symrename -XOPEN <file>
-ansi symrename - <file>
<none> symrename -BSD <file>
*/
#ifndef ASM_FINAL_SPEC
#if !defined (CROSS_COMPILE)
#define ASM_FINAL_SPEC "\
%{!mno-symrename: \
\n /usr/bin/symrename \
-%{mbsd:%{pedantic:%e-mbsd and -pedantic incompatible}BSD}\
%{mxopen:%{mbsd:%e-mbsd and -mxopen incompatible}\
%{pedantic:%e-mxopen and -pedantic incompatible}XOPEN}\
%{!mbsd:%{!mxopen:%{!ansi:BSD}}} %{c:%{o*:%*}%{!o*:%b.o}}%{!c:%U.o}}"
#endif
#endif
/* None of these is actually used in cc1. If we don't define them in target
switches cc1 complains about them. For the sake of argument lets allocate
bit 31 of target flags for such options. */
#define SUBTARGET_SWITCHES \
{"bsd", 0x80000000}, {"xopen", 0x80000000}, {"no-symrename", 0x80000000},
/* Run-time Target Specification. */
#define TARGET_VERSION \
fputs (" (ARM/RISCiX)", stderr);
/* This is used in ASM_FILE_START */
#define ARM_OS_NAME "RISCiX"
/* Unsigned chars produces much better code than signed. */
#define DEFAULT_SIGNED_CHAR 0
/* Define this if the target system supports the function atexit from the
ANSI C standard. If this is not defined, and INIT_SECTION_ASM_OP is not
defined, a default exit function will be provided to support C++.
The man page only describes on_exit, but atexit is also there. */
#define HAVE_ATEXIT 1
/* Some systems use __main in a way incompatible with its use in gcc, in these
cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
give the same symbol without quotes for an alternative entry point. You
must define both, or neither. */
#ifndef NAME__MAIN
#define NAME__MAIN "__gccmain"
#define SYMBOL__MAIN __gccmain
#endif
/* size_t is "unsigned int" in RISCiX */
#define SIZE_TYPE "unsigned int"
/* ptrdiff_t is "int" in RISCiX */
#define PTRDIFF_TYPE "int"
/* Maths operation domain error number, EDOM */
#define TARGET_EDOM 33
/* Override the normal default CPU */
#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm2
#include "arm/aout.h"
/* The RISCiX assembler does not understand .set */
#undef SET_ASM_OP
/* Override CPP_SPEC, there's no point handling endianness (and probably
not much point handling apcs_pc), and we want to add the right #defines
when using the include files. */
#undef CPP_SPEC
#define CPP_SPEC "%(cpp_cpu_arch) %(cpp_apcs_pc) %(cpp_float) \
%{mbsd:%{pedantic:%e-mbsd and -pedantic incompatible} -D_BSD_C} \
%{mxopen:%{mbsd:%e-mbsd and -mxopen incompatible} \
%{pedantic:%e-mxopen and -pedantic incompatible} -D_XOPEN_C} \
%{!mbsd:%{!mxopen:%{!ansi: -D_BSD_C}}}"
/* The native RISCiX assembler does not support stabs of any kind; because
the native assembler is not used by the compiler, Acorn didn't feel it was
necessary to put them in! */
#ifdef DBX_DEBUGGING_INFO
#undef DBX_DEBUGGING_INFO
#endif

100
gcc_arm/config/arm/riscix1-1.h Executable file
View File

@ -0,0 +1,100 @@
/* Definitions of target machine for GNU compiler. ARM RISCiX 1.1x version.
Copyright (C) 1993, 1995, 1997 Free Software Foundation, Inc.
Contributed by Richard Earnshaw (rwe11@cl.cam.ac.uk), based on original
work by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
and Martin Simmons (@harleqn.co.uk).
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* RISCiX 1.1x is basically the same as 1.2x except that it doesn't have
symrename or atexit. */
/* Translation to find startup files. On RISCiX boxes, gcrt0.o is in
/usr/lib. */
#define STARTFILE_SPEC \
"%{pg:/usr/lib/gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}"
#ifndef CPP_PREDEFINES
#define CPP_PREDEFINES "-Darm -Driscix -Dunix -Asystem(unix) -Acpu(arm) -Amachine(arm)"
#endif
#ifndef CPP_SPEC /* CYGNUS LOCAL */
#define CPP_SPEC "%{m6:-D__arm6__} %{!ansi: -D_BSD_C}"
#endif /* END CYGNUS LOCAL */
/* Riscix 1.1 doesn't have X/OPEN support, so only accept -mbsd (but ignore
it).
By not having -mxopen and -mno-symrename, we get warning messages,
but everything still compiles. */
/* None of these is actually used in cc1, so they modify bit 31 */
#define SUBTARGET_SWITCHES \
{"bsd", 0x80000000},
/* Run-time Target Specification. */
#define TARGET_VERSION \
fputs (" (ARM/RISCiX)", stderr);
/* This is used in ASM_FILE_START */
#define ARM_OS_NAME "RISCiX"
#ifdef riscos
#define TARGET_WHEN_DEBUGGING 3
#else
#define TARGET_WHEN_DEBUGGING 1
#endif
/* 'char' is signed by default on RISCiX, unsigned on RISCOS. */
#ifdef riscos
#define DEFAULT_SIGNED_CHAR 0
#else
#define DEFAULT_SIGNED_CHAR 1
#endif
/* Define this if the target system supports the function atexit form the
ANSI C standard. If this is not defined, and INIT_SECTION_ASM_OP is not
defined, a default exit function will be provided to support C++.
The man page only describes on_exit, but atexit is also there.
This seems to be missing in early versions. */
/*#define HAVE_ATEXIT 1 */
/* Some systems use __main in a way incompatible with its use in gcc, in these
cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
give the same symbol without quotes for an alternative entry point. You
must define both, or neither. */
#ifndef NAME__MAIN
#define NAME__MAIN "__gccmain"
#define SYMBOL__MAIN __gccmain
#endif
/* Override the normal default CPU */
#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm2
#include "arm/aout.h"
#undef CPP_SPEC
#define CPP_SPEC "\
%(cpp_cpu_arch) %(cpp_apcs_pc) %(cpp_float) %{!ansi: -D_BSD_C} \
"
/* The native RISCiX assembler does not support stabs of any kind; because
the native assembler is not used by the compiler, Acorn didn't feel it was
necessary to put them in! */
#ifdef DBX_DEBUGGING_INFO
#undef DBX_DEBUGGING_INFO
#endif

43
gcc_arm/config/arm/rix-gas.h Executable file
View File

@ -0,0 +1,43 @@
/* Definitions of target machine for GNU compiler. ARM RISCiX(stabs) version.
Copyright (C) 1993 Free Software Foundation, Inc.
Contributed by Richard Earnshaw (rwe11@cl.cam.ac.uk), based on original
work by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
and Martin Simmons (@harleqn.co.uk).
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* Limit the length of a stabs entry (for the broken Acorn assembler) */
#define DBX_CONTIN_LENGTH 80
#include "arm/riscix.h"
/* The native RISCiX assembler does not support stabs of any kind; because
the native assembler is not used by the compiler, Acorn didn't feel it was
necessary to put them in!
However, this file assumes that we have an assembler that does have stabs,
so we put them back in. */
#define DBX_DEBUGGING_INFO
/* Unfortunately dbx doesn't understand these */
/* Dbx on RISCiX is so broken that I've given up trying to support it.
lets just support gdb. */
/* #define DEFAULT_GDB_EXTENSIONS 0 */
/* RISCiX dbx doesn't accept xrefs */
/* #define DBX_NO_XREFS 1 */

55
gcc_arm/config/arm/semi.h Executable file
View File

@ -0,0 +1,55 @@
/* Definitions of target machine for GNU compiler. ARM on semi-hosted platform
Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
Contributed by Richard Earnshaw (richard.earnshaw@armltd.co.uk)
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* CYGNUS LOCAL */
/* Note: The definitions LOCAL_LABEL_PREFIX and USER_LABEL_PREFIX here
*must* match the definitions in bfd/coff-arm.c */
#undef LOCAL_LABEL_PREFIX
#define LOCAL_LABEL_PREFIX "."
/* #define LOCAL_LABEL_PREFIX "" */
/* #define NO_DOT_IN_LABEL */
#undef USER_LABEL_PREFIX
#define USER_LABEL_PREFIX ""
/* END CYGNUS LOCAL */
/* CYGNUS LOCAL */
#define STARTFILE_SPEC "%scrt0.o"
/* END CYGNUS LOCAL */
#define LIB_SPEC "-lc"
#define CPP_PREDEFINES \
"-Darm -D__semi__ -Acpu(arm) -Amachine(arm)"
/* CYGNUS LOCAL */
#define ASM_SPEC "%{mbig-endian:-EB} %{mcpu=*:-m%*} %{march=*:-m%*} \
%{mapcs-*:-mapcs-%*} %{mthumb-interwork:-mthumb-interwork}"
/* END CYGNUS LOCAL */
#define LINK_SPEC "%{mbig-endian:-EB} -X"
#define TARGET_VERSION fputs (" (ARM/semi-hosted)", stderr);
#define TARGET_DEFAULT ARM_FLAG_APCS_32
#undef CPP_APCS_PC_DEFAULT_SPEC
#define CPP_APCS_PC_DEFAULT_SPEC "-D__APCS_32__"

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