mirror of
https://github.com/pret/agbcc.git
synced 2026-03-21 17:44:20 -05:00
Merge pull request #30 from camthesaxman/arm_support
Build ARM compiler
This commit is contained in:
commit
74e171579e
50
.gitignore
vendored
50
.gitignore
vendored
|
|
@ -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
26
.travis.yml
Normal 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
|
||||
5
build.sh
5
build.sh
|
|
@ -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
87
config.if
Executable 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
1274
config.sub
vendored
Executable file
File diff suppressed because it is too large
Load Diff
340
gcc_arm/COPYING
Executable file
340
gcc_arm/COPYING
Executable 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
482
gcc_arm/COPYING.LIB
Executable 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
10905
gcc_arm/ChangeLog
Executable file
File diff suppressed because it is too large
Load Diff
13017
gcc_arm/ChangeLog.0
Executable file
13017
gcc_arm/ChangeLog.0
Executable file
File diff suppressed because it is too large
Load Diff
3393
gcc_arm/ChangeLog.Cygnus
Executable file
3393
gcc_arm/ChangeLog.Cygnus
Executable file
File diff suppressed because it is too large
Load Diff
3781
gcc_arm/ChangeLog.lib
Executable file
3781
gcc_arm/ChangeLog.lib
Executable file
File diff suppressed because it is too large
Load Diff
1503
gcc_arm/FSFChangeLog
Executable file
1503
gcc_arm/FSFChangeLog
Executable file
File diff suppressed because it is too large
Load Diff
10110
gcc_arm/FSFChangeLog.10
Executable file
10110
gcc_arm/FSFChangeLog.10
Executable file
File diff suppressed because it is too large
Load Diff
14493
gcc_arm/FSFChangeLog.11
Executable file
14493
gcc_arm/FSFChangeLog.11
Executable file
File diff suppressed because it is too large
Load Diff
1244
gcc_arm/FSFChangeLog.12
Executable file
1244
gcc_arm/FSFChangeLog.12
Executable file
File diff suppressed because it is too large
Load Diff
2188
gcc_arm/INSTALL
Executable file
2188
gcc_arm/INSTALL
Executable file
File diff suppressed because it is too large
Load Diff
91
gcc_arm/LANGUAGES
Executable file
91
gcc_arm/LANGUAGES
Executable 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
101
gcc_arm/LITERATURE
Executable 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
21
gcc_arm/Make-hooks
Normal 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
0
gcc_arm/Make-host
Normal file
0
gcc_arm/Make-lang
Normal file
0
gcc_arm/Make-lang
Normal file
35
gcc_arm/Make-target
Normal file
35
gcc_arm/Make-target
Normal 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
2800
gcc_arm/Makefile.in
Executable file
File diff suppressed because it is too large
Load Diff
1078
gcc_arm/NEWS
Executable file
1078
gcc_arm/NEWS
Executable file
File diff suppressed because it is too large
Load Diff
117
gcc_arm/PROBLEMS
Executable file
117
gcc_arm/PROBLEMS
Executable 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
435
gcc_arm/PROJECTS
Executable 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
26
gcc_arm/README
Executable 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
144
gcc_arm/README-bugs
Executable 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
9
gcc_arm/README-fixinc
Executable 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
39
gcc_arm/TESTS.FLUNK
Executable 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
96
gcc_arm/acconfig.h
Executable 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
237
gcc_arm/aclocal.m4
vendored
Executable 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
1545
gcc_arm/alias.c
Executable file
File diff suppressed because it is too large
Load Diff
54
gcc_arm/assert.h
Executable file
54
gcc_arm/assert.h
Executable 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
215
gcc_arm/basic-block.h
Executable 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
642
gcc_arm/bitmap.c
Executable 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
317
gcc_arm/bitmap.h
Executable 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
35
gcc_arm/build-make
Executable 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
322
gcc_arm/bytecode.def
Executable 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
82
gcc_arm/bytecode.h
Executable 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
35
gcc_arm/bytetypes.h
Executable 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
661
gcc_arm/c-aux-info.c
Executable 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
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
97
gcc_arm/c-convert.c
Executable 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
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
192
gcc_arm/c-gperf.h
Executable 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
604
gcc_arm/c-iterate.c
Executable 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
213
gcc_arm/c-lang.c
Executable 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
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
88
gcc_arm/c-lex.h
Executable 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
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
88
gcc_arm/c-parse.gperf
Executable 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
114
gcc_arm/c-parse.h
Normal 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
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
452
gcc_arm/c-pragma.c
Executable 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
100
gcc_arm/c-pragma.h
Executable 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
560
gcc_arm/c-tree.h
Executable 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
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
757
gcc_arm/caller-save.c
Executable 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
3743
gcc_arm/calls.c
Executable file
File diff suppressed because it is too large
Load Diff
674
gcc_arm/cccp.1
Executable file
674
gcc_arm/cccp.1
Executable 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
11450
gcc_arm/cccp.c
Executable file
File diff suppressed because it is too large
Load Diff
1248
gcc_arm/cexp.y
Executable file
1248
gcc_arm/cexp.y
Executable file
File diff suppressed because it is too large
Load Diff
12112
gcc_arm/combine.c
Executable file
12112
gcc_arm/combine.c
Executable file
File diff suppressed because it is too large
Load Diff
118
gcc_arm/conditions.h
Executable file
118
gcc_arm/conditions.h
Executable 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
4
gcc_arm/config.guess
vendored
Executable 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
12
gcc_arm/config.h
Normal 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
240
gcc_arm/config.in
Executable 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
1225
gcc_arm/config.sub
vendored
Executable file
File diff suppressed because it is too large
Load Diff
742
gcc_arm/config/arm/README-interworking
Executable file
742
gcc_arm/config/arm/README-interworking
Executable 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
453
gcc_arm/config/arm/aof.h
Executable 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
323
gcc_arm/config/arm/aout.h
Executable 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, \
|
||||
<ext_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
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
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
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
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
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
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
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
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
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
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
211
gcc_arm/config/arm/coff.h
Executable 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
29
gcc_arm/config/arm/ecos-elf.h
Executable 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
374
gcc_arm/config/arm/elf.h
Executable 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
580
gcc_arm/config/arm/lib1funcs.asm
Executable 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
572
gcc_arm/config/arm/lib1thumb.asm
Executable 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 */
|
||||
747
gcc_arm/config/arm/lib1thumb_981111.asm
Executable file
747
gcc_arm/config/arm/lib1thumb_981111.asm
Executable 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
58
gcc_arm/config/arm/linux-aout.h
Executable 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
204
gcc_arm/config/arm/linux-elf.h
Executable 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"
|
||||
32
gcc_arm/config/arm/linux-elf26.h
Executable file
32
gcc_arm/config/arm/linux-elf26.h
Executable 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
87
gcc_arm/config/arm/linux-gas.h
Executable 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
72
gcc_arm/config/arm/linux.h
Executable 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
161
gcc_arm/config/arm/netbsd.h
Executable 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
521
gcc_arm/config/arm/pe.c
Executable 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
295
gcc_arm/config/arm/pe.h
Executable 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
151
gcc_arm/config/arm/riscix.h
Executable 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
100
gcc_arm/config/arm/riscix1-1.h
Executable 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
43
gcc_arm/config/arm/rix-gas.h
Executable 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
55
gcc_arm/config/arm/semi.h
Executable 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
Loading…
Reference in New Issue
Block a user