newer version of tcc almost working
This commit is contained in:
parent
c42c5d94b8
commit
826d1afd58
442 changed files with 90400 additions and 24506 deletions
57
05/tcc-0.9.27/.gitignore
vendored
Normal file
57
05/tcc-0.9.27/.gitignore
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
*~
|
||||
\#*
|
||||
.#*
|
||||
*.o
|
||||
*.a
|
||||
*.exe
|
||||
*.dll
|
||||
*.obj
|
||||
*.pdb
|
||||
*.lib
|
||||
*.exp
|
||||
*.log
|
||||
*.bz2
|
||||
*.zip
|
||||
.gdb_history
|
||||
a.out
|
||||
tcc_g
|
||||
tcc
|
||||
*-tcc
|
||||
libtcc*.def
|
||||
|
||||
config*.h
|
||||
config*.mak
|
||||
config.texi
|
||||
conftest*
|
||||
tags
|
||||
TAGS
|
||||
tcc.1
|
||||
tcc.pod
|
||||
tcc-doc.html
|
||||
tcc-doc.info
|
||||
|
||||
win32/doc
|
||||
win32/libtcc
|
||||
win32/lib/32
|
||||
win32/lib/64
|
||||
win32/include/float.h
|
||||
win32/include/stdarg.h
|
||||
win32/include/stdbool.h
|
||||
win32/include/stddef.h
|
||||
win32/include/varargs.h
|
||||
win32/include/tcclib.h
|
||||
|
||||
tests/tcctest[1234]
|
||||
tests/tcctest.gcc
|
||||
tests/*.out*
|
||||
tests/*.ref
|
||||
tests/*.txt
|
||||
tests/*.gcc
|
||||
tests/*-cc*
|
||||
tests/*-tcc*
|
||||
tests/libtcc_test
|
||||
tests/asm-c-connect
|
||||
tests/asm-c-connect-sep
|
||||
tests/vla_test
|
||||
tests/hello
|
||||
tests/tests2/fred.txt
|
504
05/tcc-0.9.27/COPYING
Normal file
504
05/tcc-0.9.27/COPYING
Normal file
|
@ -0,0 +1,504 @@
|
|||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 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 Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
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 Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
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 and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
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 other code 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.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
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, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser 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 combine 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) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) 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.
|
||||
|
||||
d) 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.
|
||||
|
||||
e) 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 materials to be 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 with
|
||||
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 Lesser 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
|
||||
|
||||
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 Lesser 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser 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!
|
||||
|
||||
|
439
05/tcc-0.9.27/Changelog
Normal file
439
05/tcc-0.9.27/Changelog
Normal file
|
@ -0,0 +1,439 @@
|
|||
Version 0.9.27:
|
||||
|
||||
User interface:
|
||||
- -x[c|a|n] filetype option (Sergey Korshunoff)
|
||||
- -P[1], -dD, -dM preprocessor options (Sergey Korshunoff)
|
||||
- -Wl,-(no-)whole-archive linker option (Reuben Thomas)
|
||||
- -mms-bitfields option (David Mertens)
|
||||
- -include <file> option (Michael Matz)
|
||||
- -mno-sse on x86-64 disables use of SSE instructions
|
||||
- @listfile support (Vlad Vissoultchev)
|
||||
- tcc -ar/-impdef - formerly tiny_xxx tools integrated (grischka)
|
||||
- CPATH, C_INCLUDE_PATH and LIBRARY_PATH environment variables support
|
||||
(Andrew Aladjev, Urs Janssen)
|
||||
|
||||
Platforms:
|
||||
- new AARCH64 (arm64) target (Edmund Grimley Evans)
|
||||
- vastly improved support for ARM hard float calling convention
|
||||
(Thomas Preud'homme, Daniel Glöckner)
|
||||
- provide a runtime library for ARM (Thomas Preud'homme)
|
||||
- many x86_64 ABI fixes incl. XMM register passing and tests (James Lyon)
|
||||
- ABI tests with native compiler using libtcc (James Lyon)
|
||||
- UNICODE startup code supports wmain and wWinMain (YX Hao)
|
||||
- shared libraries for x86_64 (Michael Matz)
|
||||
- Bootstrap native Windows 32/64 compiler using Cygwin+gcc (Christian Jullien)
|
||||
|
||||
Features:
|
||||
- VLA (variable length array) improved (James Lyon, Pip Cet)
|
||||
- import functions by ordinal in .def files on windows (YX Hao)
|
||||
- x86/x86_64 assembler much improved (Michael Matz)
|
||||
- simple dead code suppression (Edmund Grimley Evans, Michael Matz, grischka)
|
||||
- implement round/fmin/fmax etc. math on windows (Avi Halachmi)
|
||||
- #pragma once support (Sergey Korshunoff, Vlad Vissoultchev, ...)
|
||||
- switch/case code improved (Zdenek Pavlas)
|
||||
- ~15% faster by TinyAlloc fast memory allocator (Vlad Vissoultchev)
|
||||
- standard conforming (and GCC compatible) struct initialization
|
||||
(Michael Matz)
|
||||
- bit-field layout made compatible with GCC (Michael Matz)
|
||||
- UTF8 in string literals supported (Zdenek Pavlas)
|
||||
_ _Generic(...) supported (Matthias Gatto)
|
||||
|
||||
Licensing:
|
||||
- TinyCC partly relicensed to MIT license (See RELICENSING file).
|
||||
|
||||
version 0.9.26:
|
||||
|
||||
User interface:
|
||||
- -MD/-MF (automatically generate dependencies for make)
|
||||
- -pthread option (same as -D_REENTRANT -lpthread) (Henry Kroll III)
|
||||
- -m32/-m64 to re-exec cross compiler (Henry Kroll III)
|
||||
- -Wl, Mimic all GNU -option forms supported by ld (Kirill Smelkov)
|
||||
- new LIBTCCAPI tcc_set_options() (grischka)
|
||||
|
||||
Platforms:
|
||||
- Many improvements for x86-64 target (Shinichiro Hamaji, Michael Matz, grischka)
|
||||
- x86-64 assembler (Frederic Feret)
|
||||
- Many improvements for ARM target (Daniel Glöckner, Thomas Preud'homme)
|
||||
- Support WinCE PE ARM (Timo VJ Lahde)
|
||||
- Support ARM hardfloat calling convention (Thomas Preud'homme)
|
||||
- Support SELinux (Security-Enhanced Linux) (Henry Kroll III)
|
||||
- Support Debian GNU/kFreeBSD kernels (Pierre Chifflier)
|
||||
- Support GNU/Hurd kernels (Thomas Preud'homme)
|
||||
- Support OSX (tcc -run only) (Milutin Jovanovic)
|
||||
- Support multiarch configuration (Thomas Preud'homme)
|
||||
- Support out-of-tree build (Akim Demaille)
|
||||
|
||||
Features:
|
||||
- C99 variable length arrays (Thomas Preud'homme & Joe Soroka)
|
||||
- Asm labels for variables and functions (Thomas Preud'homme)
|
||||
- STT_GNU_IFUNC (Indirect functions as externals) (Thomas Preud'homme)
|
||||
- More tests (tests2) (Milutin Jovanovic)
|
||||
|
||||
version 0.9.25:
|
||||
|
||||
- first support for x86-64 target (Shinichiro Hamaji)
|
||||
- support µClibc
|
||||
- split tcc.c into tcc.h libtcc.c tccpp.c tccgen.c tcc.c
|
||||
- improved preprocess output with linenumbers and spaces preserved
|
||||
- tcc_relocate now copies code into user buffer
|
||||
- fix bitfields with non-int types and in unions
|
||||
- improve ARM cross-compiling (Daniel Glöckner)
|
||||
- link stabstr sections from multiple objects
|
||||
- better (still limited) support for multiple TCCStates
|
||||
|
||||
version 0.9.24:
|
||||
|
||||
- added verbosity levels -v, -vv, -vvv
|
||||
- Accept standard input as an inputstream (Hanzac Chen)
|
||||
- Support c89 compilers other than gcc (Hanzac Chen)
|
||||
- -soname linker option (Marc Andre Tanner)
|
||||
- Just warn about unknown directives, ignore quotes in #error/#warning
|
||||
- Define __STDC_VERSION__=199901L (477)
|
||||
- Switch to newer tccpe.c (includes support for resources)
|
||||
- Handle backslashes within #include/#error/#warning
|
||||
- Import changesets (part 4) 428,457,460,467: defines for openbsd etc.
|
||||
- Use _WIN32 for a windows hosted tcc and define it for the PE target,
|
||||
otherwise define __unix / __linux (Detlef Riekenberg)
|
||||
- Import changesets (part 3) 409,410: ARM EABI by Daniel Glöckner
|
||||
- Some in-between fixes:
|
||||
TCC -E no longer hangs with macro calls involving newlines.
|
||||
(next_nomacro1 now advances the read-pointer with TOK_LINEFEED)
|
||||
Global cast (int g_i = 1LL;) no longer crashes tcc.
|
||||
(nocode_wanted is initially 1, and only 0 for gen_function)
|
||||
On win32 now tcc.exe finds 'include' & 'lib' even if itself is in 'bin'.
|
||||
(new function w32_tcc_lib_path removes 'bin' if detected)
|
||||
Added quick build batch file for mingw (win32/build-tcc.bat)
|
||||
Last added case label optimization (455) produced wrong code. Reverted.
|
||||
|
||||
- Import more changesets from Rob Landley's fork (part 2):
|
||||
487: Handle long long constants in gen_opic() (Rob Landley)
|
||||
484: Handle parentheses within __attribute__((...)) (Rob Landley)
|
||||
480: Remove a goto in decl_initializer_alloc (Rob Landley)
|
||||
475: Fix dereferences in inline assembly output (Joshua Phillips)
|
||||
474: Cast ptrs to ints of different sizes correctly (Joshua Phillips)
|
||||
473: Fix size of structs with empty array member (Joshua Phillips)
|
||||
470: No warning for && and || with mixed pointers/integers (Rob Landley)
|
||||
469: Fix symbol visibility problems in the linker (Vincent Pit)
|
||||
468: Allow && and || involving pointer arguments (Rob Landley)
|
||||
455: Optimize case labels with no code in between (Zdenek Pavlas)
|
||||
450: Implement alloca for x86 (grischka)
|
||||
415: Parse unicode escape sequences (Axel Liljencrantz)
|
||||
407: Add a simple va_copy() in stdarg.h (Hasso Tepper)
|
||||
400: Allow typedef names as symbols (Dave Dodge)
|
||||
|
||||
- Import some changesets from Rob Landley's fork (part 1):
|
||||
462: Use LGPL with bcheck.c and il-gen.c
|
||||
458: Fix global compound literals (in unary: case '&':) (Andrew Johnson)
|
||||
456: Use return code from tcc_output_file in main() (Michael Somos)
|
||||
442: Fix indirections with function pointers (***fn)() (grischka)
|
||||
441: Fix LL left shift in libtcc1.c:__shldi3 (grischka)
|
||||
440: Pass structures and function ptrs through ?: (grischka)
|
||||
439: Keep rvalue in bit assignment (bit2 = bit1 = x) (grischka)
|
||||
438: Degrade nonportable pointer assignment to warning (grischka)
|
||||
437: Call 'saveregs()' before jumping with logical and/or/not (grischka)
|
||||
435: Put local static variables into global memory (grischka)
|
||||
432/434: Cast double and ptr to bool (grischka)
|
||||
420: Zero pad x87 tenbyte long doubles (Felix Nawothnig)
|
||||
417: Make 'sizeof' unsigned (Rob Landley)
|
||||
397: Fix save_reg for longlongs (Daniel Glöckner)
|
||||
396: Fix "invalid relocation entry" problem on ubuntu - (Bernhard Fischer)
|
||||
|
||||
- ignore AS_NEEDED ld command
|
||||
- mark executable sections as executable when running in memory
|
||||
- added support for win32 wchar_t (Filip Navara)
|
||||
- segment override prefix support (Filip Navara)
|
||||
- normalized slashes in paths (Filip Navara)
|
||||
- windows style fastcall (Filip Navara)
|
||||
- support for empty input register section in asm (Filip Navara)
|
||||
- anonymous union/struct support (Filip Navara)
|
||||
- fixed parsing of function parameters
|
||||
- workaround for function pointers in conditional expressions (Dave Dodge)
|
||||
- initial '-E' option support to use the C preprocessor alone
|
||||
- discard type qualifiers when comparing function parameters (Dave Dodge)
|
||||
- Bug fix: A long long value used as a test expression ignores the
|
||||
upper 32 bits at runtime (Dave Dodge)
|
||||
- fixed multiple concatenation of PPNUM tokens (initial patch by Dave Dodge)
|
||||
- fixed multiple typedef specifiers handling
|
||||
- fixed sign extension in some type conversions (Dave Dodge)
|
||||
|
||||
version 0.9.23:
|
||||
|
||||
- initial PE executable format for windows version (grischka)
|
||||
- '#pragma pack' support (grischka)
|
||||
- '#include_next' support (Bernhard Fischer)
|
||||
- ignore '-pipe' option
|
||||
- added -f[no-]leading-underscore
|
||||
- preprocessor function macro parsing fix (grischka)
|
||||
|
||||
version 0.9.22:
|
||||
|
||||
- simple memory optimisations: kernel compilation is 30% faster
|
||||
- linker symbol definitions fixes
|
||||
- gcc 3.4 fixes
|
||||
- fixed value stack full error
|
||||
- 'packed' attribute support for variables and structure fields
|
||||
- ignore 'const' and 'volatile' in function prototypes
|
||||
- allow '_Bool' in bit fields
|
||||
|
||||
version 0.9.21:
|
||||
|
||||
- ARM target support (Daniel Glöckner)
|
||||
- added '-funsigned-char, '-fsigned-char' and
|
||||
'-Wimplicit-function-declaration'
|
||||
- fixed assignment of const struct in struct
|
||||
- line comment fix (reported by Bertram Felgenhauer)
|
||||
- initial TMS320C67xx target support (TK)
|
||||
- win32 configure
|
||||
- regparm() attribute
|
||||
- many built-in assembler fixes
|
||||
- added '.org', '.fill' and '.previous' assembler directives
|
||||
- '-fno-common' option
|
||||
- '-Ttext' linker option
|
||||
- section alignment fixes
|
||||
- bit fields fixes
|
||||
- do not generate code for unused inline functions
|
||||
- '-oformat' linker option.
|
||||
- added 'binary' output format.
|
||||
|
||||
version 0.9.20:
|
||||
|
||||
- added '-w' option
|
||||
- added '.gnu.linkonce' ELF sections support
|
||||
- fixed libc linking when running in memory (avoid 'stat' function
|
||||
errors).
|
||||
- extended '-run' option to be able to give several arguments to a C
|
||||
script.
|
||||
|
||||
version 0.9.19:
|
||||
|
||||
- "alacarte" linking (Dave Long)
|
||||
- simpler function call
|
||||
- more strict type checks
|
||||
- added 'const' and 'volatile' support and associated warnings
|
||||
- added -Werror, -Wunsupported, -Wwrite-strings, -Wall.
|
||||
- added __builtin_types_compatible_p() and __builtin_constant_p()
|
||||
- chars support in assembler (Dave Long)
|
||||
- .string, .globl, .section, .text, .data and .bss asm directive
|
||||
support (Dave Long)
|
||||
- man page generated from tcc-doc.texi
|
||||
- fixed macro argument substitution
|
||||
- fixed zero argument macro parsing
|
||||
- changed license to LGPL
|
||||
- added -rdynamic option support
|
||||
|
||||
version 0.9.18:
|
||||
|
||||
- header fix (time.h)
|
||||
- fixed inline asm without operand case
|
||||
- fixed 'default:' or 'case x:' with '}' after (incorrect C construct accepted
|
||||
by gcc)
|
||||
- added 'A' inline asm constraint.
|
||||
|
||||
version 0.9.17:
|
||||
|
||||
- PLT generation fix
|
||||
- tcc doc fixes (Peter Lund)
|
||||
- struct parse fix (signaled by Pedro A. Aranda Gutierrez)
|
||||
- better _Bool lvalue support (signaled by Alex Measday)
|
||||
- function parameters must be converted to pointers (signaled by Neil Brown)
|
||||
- sanitized string and character constant parsing
|
||||
- fixed comment parse (signaled by Damian M Gryski)
|
||||
- fixed macro function bug (signaled by Philippe Ribet)
|
||||
- added configure (initial patch by Mitchell N Charity)
|
||||
- added '-run' and '-v' options (initial patch by vlindos)
|
||||
- added real date report in __DATE__ and __TIME__ macros
|
||||
|
||||
version 0.9.16:
|
||||
|
||||
- added assembler language support
|
||||
- added GCC inline asm() support
|
||||
- fixed multiple variable definitions : uninitialized variables are
|
||||
created as COMMON symbols.
|
||||
- optimized macro processing
|
||||
- added GCC statement expressions support
|
||||
- added GCC local labels support
|
||||
- fixed array declaration in old style function parameters
|
||||
- support casts in static structure initializations
|
||||
- added various __xxx[__] keywords for GCC compatibility
|
||||
- ignore __extension__ GCC in an expression or in a type (still not perfect)
|
||||
- added '? :' GCC extension support
|
||||
|
||||
version 0.9.15:
|
||||
|
||||
- compilation fixes for glibc 2.2, gcc 2.95.3 and gcc 3.2.
|
||||
- FreeBSD compile fixes. Makefile patches still missing (Carl Drougge).
|
||||
- fixed file type guessing if '.' is in the path.
|
||||
- fixed tcc_compile_string()
|
||||
- add a dummy page in ELF files to fix RX/RW accesses (pageexec at
|
||||
freemail dot hu).
|
||||
|
||||
version 0.9.14:
|
||||
|
||||
- added #warning. error message if invalid preprocessing directive.
|
||||
- added CType structure to ease typing (faster parse).
|
||||
- suppressed secondary hash tables (faster parse).
|
||||
- rewrote parser by optimizing common cases (faster parse).
|
||||
- fixed signed long long comparisons.
|
||||
- fixed 'int a(), b();' declaration case.
|
||||
- fixed structure init without '{}'.
|
||||
- correct alignment support in structures.
|
||||
- empty structures support.
|
||||
- gcc testsuite now supported.
|
||||
- output only warning if implicit integer/pointer conversions.
|
||||
- added static bitfield init.
|
||||
|
||||
version 0.9.13:
|
||||
|
||||
- correct preprocessing token pasting (## operator) in all cases (added
|
||||
preprocessing number token).
|
||||
- fixed long long register spill.
|
||||
- fixed signed long long '>>'.
|
||||
- removed memory leaks.
|
||||
- better error handling : processing can continue on link errors. A
|
||||
custom callback can be added to display error messages. Most
|
||||
errors do not call exit() now.
|
||||
- ignore -O, -W, -m and -f options
|
||||
- added old style function declarations
|
||||
- added GCC __alignof__ support.
|
||||
- added GCC typeof support.
|
||||
- added GCC computed gotos support.
|
||||
- added stack backtrace in runtime error message. Improved runtime
|
||||
error position display.
|
||||
|
||||
version 0.9.12:
|
||||
|
||||
- more fixes for || and && handling.
|
||||
- improved '? :' type handling.
|
||||
- fixed bound checking generation with structures
|
||||
- force '#endif' to be in same file as matching '#if'
|
||||
- #include file optimization with '#ifndef #endif' construct detection
|
||||
- macro handling optimization
|
||||
- added tcc_relocate() and tcc_get_symbol() in libtcc.
|
||||
|
||||
version 0.9.11:
|
||||
|
||||
- stdarg.h fix for double type (thanks to Philippe Ribet).
|
||||
- correct white space characters and added MSDOS newline support.
|
||||
- fixed invalid implicit function call type declaration.
|
||||
- special macros such as __LINE__ are defined if tested with defined().
|
||||
- fixed '!' operator with relocated address.
|
||||
- added symbol + offset relocation (fixes some static variable initializers)
|
||||
- '-l' option can be specified anywhere. '-c' option yields default
|
||||
output name. added '-r' option for relocatable output.
|
||||
- fixed '\nnn' octal parsing.
|
||||
- fixed local extern variables declarations.
|
||||
|
||||
version 0.9.10:
|
||||
|
||||
- fixed lvalue type when saved in local stack.
|
||||
- fixed '#include' syntax when using macros.
|
||||
- fixed '#line' bug.
|
||||
- removed size limit on strings. Unified string constants handling
|
||||
with variable declarations.
|
||||
- added correct support for '\xX' in wchar_t strings.
|
||||
- added support for bound checking in generated executables
|
||||
- fixed -I include order.
|
||||
- fixed incorrect function displayed in runtime error.
|
||||
|
||||
version 0.9.9:
|
||||
|
||||
- fixed preprocessor expression parsing for #if/#elif.
|
||||
- relocated debug info (.stab section).
|
||||
- relocated bounds info (.bounds section).
|
||||
- fixed cast to char of char constants ('\377' is -1 instead of 255)
|
||||
- fixed implicit cast for unary plus.
|
||||
- strings and '__func__' have now 'char[]' type instead of 'char *'
|
||||
(fixes sizeof() return value).
|
||||
- added __start_xxx and __stop_xxx symbols in linker.
|
||||
- better DLL creation support (option -shared begins to work).
|
||||
- ELF sections and hash tables are resized dynamically.
|
||||
- executables and DLLs are stripped by default.
|
||||
|
||||
version 0.9.8:
|
||||
|
||||
- First version of full ELF linking support (generate objects, static
|
||||
executable, dynamic executable, dynamic libraries). Dynamic library
|
||||
support is not finished (need PIC support in compiler and some
|
||||
patches in symbol exporting).
|
||||
- First version of ELF loader for object (.o) and archive (.a) files.
|
||||
- Support of simple GNU ld scripts (GROUP and FILE commands)
|
||||
- Separated runtime library and bound check code from TCC (smaller
|
||||
compiler core).
|
||||
- fixed register reload in float compare.
|
||||
- fixed implicit char/short to int casting.
|
||||
- allow array type for address of ('&') operator.
|
||||
- fixed unused || or && result.
|
||||
- added GCC style variadic macro support.
|
||||
- optimized bound checking code for array access.
|
||||
- tcc includes are now in $(prefix)/lib/tcc/include.
|
||||
- more command line options - more consistent handling of multiple
|
||||
input files.
|
||||
- added tcc man page (thanks to Cyril Bouthors).
|
||||
- uClibc Makefile update
|
||||
- converted documentation to texinfo format.
|
||||
- added developper's guide in documentation.
|
||||
|
||||
version 0.9.7:
|
||||
|
||||
- added library API for easy dynamic compilation (see libtcc.h - first
|
||||
draft).
|
||||
- fixed long long register spill bug.
|
||||
- fixed '? :' register spill bug.
|
||||
|
||||
version 0.9.6:
|
||||
|
||||
- added floating point constant propagation (fixes negative floating
|
||||
point constants bug).
|
||||
|
||||
version 0.9.5:
|
||||
|
||||
- uClibc patches (submitted by Alfonso Martone).
|
||||
- error reporting fix
|
||||
- added CONFIG_TCC_BCHECK to get smaller code if needed.
|
||||
|
||||
version 0.9.4:
|
||||
|
||||
- windows port (currently cannot use -g, -b and dll functions).
|
||||
- faster and simpler I/O handling.
|
||||
- '-D' option works in all cases.
|
||||
- preprocessor fixes (#elif and empty macro args)
|
||||
- floating point fixes
|
||||
- first code for CIL generation (does not work yet)
|
||||
|
||||
version 0.9.3:
|
||||
|
||||
- better and smaller code generator.
|
||||
- full ISOC99 64 bit 'long long' support.
|
||||
- full 32 bit 'float', 64 bit 'double' and 96 bit 'long double' support.
|
||||
- added '-U' option.
|
||||
- added assembly sections support.
|
||||
- even faster startup time by mmaping sections instead of mallocing them.
|
||||
- added GNUC __attribute__ keyword support (currently supports
|
||||
'section' and 'aligned' attributes).
|
||||
- added ELF file output (only usable for debugging now)
|
||||
- added debug symbol generation (STAB format).
|
||||
- added integrated runtime error analysis ('-g' option: print clear
|
||||
run time error messages instead of "Segmentation fault").
|
||||
- added first version of tiny memory and bound checker ('-b' option).
|
||||
|
||||
version 0.9.2:
|
||||
|
||||
- even faster parsing.
|
||||
- various syntax parsing fixes.
|
||||
- fixed external relocation handling for variables or functions pointers.
|
||||
- better function pointers type handling.
|
||||
- can compile multiple files (-i option).
|
||||
- ANSI C bit fields are supported.
|
||||
- beginning of float/double/long double support.
|
||||
- beginning of long long support.
|
||||
|
||||
version 0.9.1:
|
||||
|
||||
- full ISOC99 initializers handling.
|
||||
- compound literals.
|
||||
- structures handle in assignments and as function param or return value.
|
||||
- wide chars and strings.
|
||||
- macro bug fix
|
||||
|
||||
version 0.9:
|
||||
- initial version.
|
71
05/tcc-0.9.27/CodingStyle
Normal file
71
05/tcc-0.9.27/CodingStyle
Normal file
|
@ -0,0 +1,71 @@
|
|||
|
||||
In general, use the same coding style as the surrounding code.
|
||||
|
||||
However, do not make any unnecessary changes as that complicates
|
||||
the VCS (git) history and makes it harder to merge patches. So
|
||||
do not modify code just to make it conform to a coding style.
|
||||
|
||||
Indentation
|
||||
|
||||
Turn on a "fill tabs with spaces" option in your editor.
|
||||
|
||||
Remove tabs and trailing spaces from any lines that are modified.
|
||||
|
||||
Note that some files are indented with 2 spaces (when they
|
||||
have large indentation) while most are indented with 4 spaces.
|
||||
|
||||
Language
|
||||
|
||||
TCC is mostly implemented in C90. Do not use any non-C90 features
|
||||
that are not already in use.
|
||||
|
||||
Non-C90 features currently in use, as revealed by
|
||||
./configure --extra-cflags="-std=c90 -Wpedantic":
|
||||
|
||||
- long long (including "LL" constants)
|
||||
- inline
|
||||
- very long string constants
|
||||
- assignment between function pointer and 'void *'
|
||||
- "//" comments
|
||||
- empty macro arguments (DEF_ASMTEST in i386-tok.h)
|
||||
- unnamed struct and union fields (in struct Sym), a C11 feature
|
||||
|
||||
Testing
|
||||
|
||||
A simple "make test" is sufficient for some simple changes. However,
|
||||
before committing a change consider performing some of the following
|
||||
additional tests:
|
||||
|
||||
- Build and run "make test" on several architectures.
|
||||
|
||||
- Build with ./configure --enable-cross.
|
||||
|
||||
- If the generation of relocations has been changed, try compiling
|
||||
with TCC and linking with GCC/Clang. If the linker has been
|
||||
modified, try compiling with GCC/Clang and linking with TCC.
|
||||
|
||||
- Test with ASan/UBSan to detect memory corruption and undefined behaviour:
|
||||
|
||||
make clean
|
||||
./configure
|
||||
make
|
||||
make test
|
||||
cp libtcc.a libtcc.a.hide
|
||||
|
||||
make clean
|
||||
./configure --extra-cflags="-fsanitize=address,undefined -g"
|
||||
make
|
||||
cp libtcc.a.hide libtcc.a
|
||||
make test
|
||||
|
||||
- Test with Valgrind to detect some uses of uninitialised values:
|
||||
|
||||
make clean
|
||||
./configure
|
||||
make
|
||||
# On Intel, because Valgrind does floating-point arithmetic differently:
|
||||
( cd tests && gcc -I.. tcctest.c && valgrind -q ./a.out > test.ref )
|
||||
make test TCC="valgrind -q --leak-check=full `pwd`/tcc -B`pwd` -I`pwd`"
|
||||
|
||||
(Because of how VLAs are implemented, invalid reads are expected
|
||||
with 79_vla_continue.)
|
403
05/tcc-0.9.27/Makefile
Normal file
403
05/tcc-0.9.27/Makefile
Normal file
|
@ -0,0 +1,403 @@
|
|||
# --------------------------------------------------------------------------
|
||||
#
|
||||
# Tiny C Compiler Makefile
|
||||
#
|
||||
|
||||
ifndef TOP
|
||||
TOP = .
|
||||
INCLUDED = no
|
||||
endif
|
||||
|
||||
include $(TOP)/config.mak
|
||||
|
||||
ifeq (-$(CC)-$(GCC_MAJOR)-$(findstring $(GCC_MINOR),56789)-,-gcc-4--)
|
||||
CFLAGS += -D_FORTIFY_SOURCE=0
|
||||
endif
|
||||
|
||||
LIBTCC = libtcc.a
|
||||
LIBTCC1 = libtcc1.a
|
||||
LINK_LIBTCC =
|
||||
LIBS =
|
||||
CFLAGS += -I$(TOP)
|
||||
CFLAGS += $(CPPFLAGS)
|
||||
VPATH = $(TOPSRC)
|
||||
|
||||
ifdef CONFIG_WIN32
|
||||
ifneq ($(CONFIG_static),yes)
|
||||
LIBTCC = libtcc$(DLLSUF)
|
||||
LIBTCCDEF = libtcc.def
|
||||
endif
|
||||
CFGWIN = -win
|
||||
NATIVE_TARGET = $(ARCH)-win$(if $(findstring arm,$(ARCH)),ce,32)
|
||||
else
|
||||
LIBS=-lm
|
||||
ifneq ($(CONFIG_ldl),no)
|
||||
LIBS+=-ldl
|
||||
endif
|
||||
# make libtcc as static or dynamic library?
|
||||
ifeq ($(CONFIG_static),no)
|
||||
LIBTCC=libtcc$(DLLSUF)
|
||||
export LD_LIBRARY_PATH := $(CURDIR)/$(TOP)
|
||||
ifneq ($(CONFIG_rpath),no)
|
||||
LINK_LIBTCC += -Wl,-rpath,"$(libdir)"
|
||||
endif
|
||||
endif
|
||||
CFGWIN =-unx
|
||||
NATIVE_TARGET = $(ARCH)
|
||||
ifdef CONFIG_OSX
|
||||
NATIVE_TARGET = $(ARCH)-osx
|
||||
LDFLAGS += -flat_namespace -undefined warning
|
||||
export MACOSX_DEPLOYMENT_TARGET := 10.2
|
||||
endif
|
||||
endif
|
||||
|
||||
# run local version of tcc with local libraries and includes
|
||||
TCCFLAGS-unx = -B$(TOP) -I$(TOPSRC)/include -I$(TOPSRC) -I$(TOP)
|
||||
TCCFLAGS-win = -B$(TOPSRC)/win32 -I$(TOPSRC)/include -I$(TOPSRC) -I$(TOP) -L$(TOP)
|
||||
TCCFLAGS = $(TCCFLAGS$(CFGWIN))
|
||||
TCC = $(TOP)/tcc$(EXESUF) $(TCCFLAGS)
|
||||
ifdef CONFIG_OSX
|
||||
TCCFLAGS += -D_ANSI_SOURCE
|
||||
endif
|
||||
|
||||
CFLAGS_P = $(CFLAGS) -pg -static -DCONFIG_TCC_STATIC -DTCC_PROFILE
|
||||
LIBS_P = $(LIBS)
|
||||
LDFLAGS_P = $(LDFLAGS)
|
||||
|
||||
CONFIG_$(ARCH) = yes
|
||||
NATIVE_DEFINES_$(CONFIG_i386) += -DTCC_TARGET_I386
|
||||
NATIVE_DEFINES_$(CONFIG_x86_64) += -DTCC_TARGET_X86_64
|
||||
NATIVE_DEFINES_$(CONFIG_WIN32) += -DTCC_TARGET_PE
|
||||
NATIVE_DEFINES_$(CONFIG_OSX) += -DTCC_TARGET_MACHO
|
||||
NATIVE_DEFINES_$(CONFIG_uClibc) += -DTCC_UCLIBC
|
||||
NATIVE_DEFINES_$(CONFIG_musl) += -DTCC_MUSL
|
||||
NATIVE_DEFINES_$(CONFIG_libgcc) += -DCONFIG_USE_LIBGCC
|
||||
NATIVE_DEFINES_$(CONFIG_selinux) += -DHAVE_SELINUX
|
||||
NATIVE_DEFINES_$(CONFIG_arm) += -DTCC_TARGET_ARM
|
||||
NATIVE_DEFINES_$(CONFIG_arm_eabihf) += -DTCC_ARM_EABI -DTCC_ARM_HARDFLOAT
|
||||
NATIVE_DEFINES_$(CONFIG_arm_eabi) += -DTCC_ARM_EABI
|
||||
NATIVE_DEFINES_$(CONFIG_arm_vfp) += -DTCC_ARM_VFP
|
||||
NATIVE_DEFINES_$(CONFIG_arm64) += -DTCC_TARGET_ARM64
|
||||
NATIVE_DEFINES += $(NATIVE_DEFINES_yes)
|
||||
|
||||
ifeq ($(INCLUDED),no)
|
||||
# --------------------------------------------------------------------------
|
||||
# running top Makefile
|
||||
|
||||
PROGS = tcc$(EXESUF)
|
||||
TCCLIBS = $(LIBTCC1) $(LIBTCC) $(LIBTCCDEF)
|
||||
TCCDOCS = tcc.1 tcc-doc.html tcc-doc.info
|
||||
|
||||
all: $(PROGS) $(TCCLIBS) $(TCCDOCS)
|
||||
|
||||
# cross compiler targets to build
|
||||
TCC_X = i386 x86_64 i386-win32 x86_64-win32 x86_64-osx arm arm64 arm-wince c67
|
||||
# TCC_X += arm-fpa arm-fpa-ld arm-vfp arm-eabi
|
||||
|
||||
# cross libtcc1.a targets to build
|
||||
LIBTCC1_X = i386 x86_64 i386-win32 x86_64-win32 x86_64-osx arm arm64 arm-wince
|
||||
|
||||
PROGS_CROSS = $(foreach X,$(TCC_X),$X-tcc$(EXESUF))
|
||||
LIBTCC1_CROSS = $(foreach X,$(LIBTCC1_X),$X-libtcc1.a)
|
||||
|
||||
# build cross compilers & libs
|
||||
cross: $(LIBTCC1_CROSS) $(PROGS_CROSS)
|
||||
|
||||
# build specific cross compiler & lib
|
||||
cross-%: %-tcc$(EXESUF) %-libtcc1.a ;
|
||||
|
||||
install: ; @$(MAKE) --no-print-directory install$(CFGWIN)
|
||||
install-strip: ; @$(MAKE) --no-print-directory install$(CFGWIN) CONFIG_strip=yes
|
||||
uninstall: ; @$(MAKE) --no-print-directory uninstall$(CFGWIN)
|
||||
|
||||
ifdef CONFIG_cross
|
||||
all : cross
|
||||
endif
|
||||
|
||||
# --------------------------------------------
|
||||
|
||||
T = $(or $(CROSS_TARGET),$(NATIVE_TARGET),unknown)
|
||||
X = $(if $(CROSS_TARGET),$(CROSS_TARGET)-)
|
||||
|
||||
DEF-i386 = -DTCC_TARGET_I386
|
||||
DEF-x86_64 = -DTCC_TARGET_X86_64
|
||||
DEF-i386-win32 = -DTCC_TARGET_PE -DTCC_TARGET_I386
|
||||
DEF-x86_64-win32= -DTCC_TARGET_PE -DTCC_TARGET_X86_64
|
||||
DEF-x86_64-osx = -DTCC_TARGET_MACHO -DTCC_TARGET_X86_64
|
||||
DEF-arm-wince = -DTCC_TARGET_PE -DTCC_TARGET_ARM -DTCC_ARM_EABI -DTCC_ARM_VFP -DTCC_ARM_HARDFLOAT
|
||||
DEF-arm64 = -DTCC_TARGET_ARM64
|
||||
DEF-c67 = -DTCC_TARGET_C67 -w # disable warnigs
|
||||
DEF-arm-fpa = -DTCC_TARGET_ARM
|
||||
DEF-arm-fpa-ld = -DTCC_TARGET_ARM -DLDOUBLE_SIZE=12
|
||||
DEF-arm-vfp = -DTCC_TARGET_ARM -DTCC_ARM_VFP
|
||||
DEF-arm-eabi = -DTCC_TARGET_ARM -DTCC_ARM_VFP -DTCC_ARM_EABI
|
||||
DEF-arm-eabihf = -DTCC_TARGET_ARM -DTCC_ARM_VFP -DTCC_ARM_EABI -DTCC_ARM_HARDFLOAT
|
||||
DEF-arm = $(DEF-arm-eabihf)
|
||||
DEF-$(NATIVE_TARGET) = $(NATIVE_DEFINES)
|
||||
|
||||
DEFINES += $(DEF-$T) $(DEF-all)
|
||||
DEFINES += $(if $(ROOT-$T),-DCONFIG_SYSROOT="\"$(ROOT-$T)\"")
|
||||
DEFINES += $(if $(CRT-$T),-DCONFIG_TCC_CRTPREFIX="\"$(CRT-$T)\"")
|
||||
DEFINES += $(if $(LIB-$T),-DCONFIG_TCC_LIBPATHS="\"$(LIB-$T)\"")
|
||||
DEFINES += $(if $(INC-$T),-DCONFIG_TCC_SYSINCLUDEPATHS="\"$(INC-$T)\"")
|
||||
DEFINES += $(DEF-$(or $(findstring win,$T),unx))
|
||||
|
||||
ifneq ($(X),)
|
||||
ifeq ($(CONFIG_WIN32),yes)
|
||||
DEF-win += -DTCC_LIBTCC1="\"$(X)libtcc1.a\""
|
||||
DEF-unx += -DTCC_LIBTCC1="\"lib/$(X)libtcc1.a\""
|
||||
else
|
||||
DEF-all += -DTCC_LIBTCC1="\"$(X)libtcc1.a\""
|
||||
DEF-win += -DCONFIG_TCCDIR="\"$(tccdir)/win32\""
|
||||
endif
|
||||
endif
|
||||
|
||||
# include custom configuration (see make help)
|
||||
-include config-extra.mak
|
||||
|
||||
CORE_FILES = tcc.c tcctools.c libtcc.c tccpp.c tccgen.c tccelf.c tccasm.c tccrun.c
|
||||
CORE_FILES += tcc.h config.h libtcc.h tcctok.h
|
||||
i386_FILES = $(CORE_FILES) i386-gen.c i386-link.c i386-asm.c i386-asm.h i386-tok.h
|
||||
i386-win32_FILES = $(i386_FILES) tccpe.c
|
||||
x86_64_FILES = $(CORE_FILES) x86_64-gen.c x86_64-link.c i386-asm.c x86_64-asm.h
|
||||
x86_64-win32_FILES = $(x86_64_FILES) tccpe.c
|
||||
x86_64-osx_FILES = $(x86_64_FILES)
|
||||
arm_FILES = $(CORE_FILES) arm-gen.c arm-link.c arm-asm.c
|
||||
arm-wince_FILES = $(arm_FILES) tccpe.c
|
||||
arm64_FILES = $(CORE_FILES) arm64-gen.c arm64-link.c
|
||||
c67_FILES = $(CORE_FILES) c67-gen.c c67-link.c tcccoff.c
|
||||
|
||||
# libtcc sources
|
||||
LIBTCC_SRC = $(filter-out tcc.c tcctools.c,$(filter %.c,$($T_FILES)))
|
||||
|
||||
ifeq ($(ONE_SOURCE),yes)
|
||||
LIBTCC_OBJ = $(X)libtcc.o
|
||||
LIBTCC_INC = $($T_FILES)
|
||||
TCC_FILES = $(X)tcc.o
|
||||
tcc.o : DEFINES += -DONE_SOURCE=0
|
||||
else
|
||||
LIBTCC_OBJ = $(patsubst %.c,$(X)%.o,$(LIBTCC_SRC))
|
||||
LIBTCC_INC = $(filter %.h %-gen.c %-link.c,$($T_FILES))
|
||||
TCC_FILES = $(X)tcc.o $(LIBTCC_OBJ)
|
||||
$(TCC_FILES) : DEFINES += -DONE_SOURCE=0
|
||||
endif
|
||||
|
||||
# target specific object rule
|
||||
$(X)%.o : %.c $(LIBTCC_INC)
|
||||
$(CC) -o $@ -c $< $(DEFINES) $(CFLAGS)
|
||||
|
||||
# additional dependencies
|
||||
$(X)tcc.o : tcctools.c
|
||||
|
||||
# Host Tiny C Compiler
|
||||
tcc$(EXESUF): tcc.o $(LIBTCC)
|
||||
$(CC) -o $@ $^ $(LIBS) $(LDFLAGS) $(LINK_LIBTCC)
|
||||
|
||||
# Cross Tiny C Compilers
|
||||
%-tcc$(EXESUF): FORCE
|
||||
@$(MAKE) --no-print-directory $@ CROSS_TARGET=$* ONE_SOURCE=$(or $(ONE_SOURCE),yes)
|
||||
|
||||
$(CROSS_TARGET)-tcc$(EXESUF): $(TCC_FILES)
|
||||
$(CC) -o $@ $^ $(LIBS) $(LDFLAGS)
|
||||
|
||||
# profiling version
|
||||
tcc_p$(EXESUF): $($T_FILES)
|
||||
$(CC) -o $@ $< $(DEFINES) $(CFLAGS_P) $(LIBS_P) $(LDFLAGS_P)
|
||||
|
||||
# static libtcc library
|
||||
libtcc.a: $(LIBTCC_OBJ)
|
||||
$(AR) rcs $@ $^
|
||||
|
||||
# dynamic libtcc library
|
||||
libtcc.so: $(LIBTCC_OBJ)
|
||||
$(CC) -shared -Wl,-soname,$@ -o $@ $^ $(LDFLAGS)
|
||||
|
||||
libtcc.so: CFLAGS+=-fPIC
|
||||
libtcc.so: LDFLAGS+=-fPIC
|
||||
|
||||
# windows dynamic libtcc library
|
||||
libtcc.dll : $(LIBTCC_OBJ)
|
||||
$(CC) -shared -o $@ $^ $(LDFLAGS)
|
||||
libtcc.dll : DEFINES += -DLIBTCC_AS_DLL
|
||||
|
||||
# import file for windows libtcc.dll
|
||||
libtcc.def : libtcc.dll tcc$(EXESUF)
|
||||
$(XTCC) -impdef $< -o $@
|
||||
XTCC ?= ./tcc$(EXESUF)
|
||||
|
||||
# TinyCC runtime libraries
|
||||
libtcc1.a : tcc$(EXESUF) FORCE
|
||||
@$(MAKE) -C lib DEFINES='$(DEF-$T)'
|
||||
|
||||
# Cross libtcc1.a
|
||||
%-libtcc1.a : %-tcc$(EXESUF) FORCE
|
||||
@$(MAKE) -C lib DEFINES='$(DEF-$*)' CROSS_TARGET=$*
|
||||
|
||||
.PRECIOUS: %-libtcc1.a
|
||||
FORCE:
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# documentation and man page
|
||||
tcc-doc.html: tcc-doc.texi
|
||||
makeinfo --no-split --html --number-sections -o $@ $< || true
|
||||
|
||||
tcc.1: tcc-doc.texi
|
||||
$(TOPSRC)/texi2pod.pl $< tcc.pod \
|
||||
&& pod2man --section=1 --center="Tiny C Compiler" --release="$(VERSION)" tcc.pod >tmp.1 \
|
||||
&& mv tmp.1 $@ || rm -f tmp.1
|
||||
|
||||
tcc-doc.info: tcc-doc.texi
|
||||
makeinfo $< || true
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# install
|
||||
|
||||
INSTALL = install -m644
|
||||
INSTALLBIN = install -m755 $(STRIP_$(CONFIG_strip))
|
||||
STRIP_yes = -s
|
||||
|
||||
LIBTCC1_W = $(filter %-win32-libtcc1.a %-wince-libtcc1.a,$(LIBTCC1_CROSS))
|
||||
LIBTCC1_U = $(filter-out $(LIBTCC1_W),$(LIBTCC1_CROSS))
|
||||
IB = $(if $1,mkdir -p $2 && $(INSTALLBIN) $1 $2)
|
||||
IBw = $(call IB,$(wildcard $1),$2)
|
||||
IF = $(if $1,mkdir -p $2 && $(INSTALL) $1 $2)
|
||||
IFw = $(call IF,$(wildcard $1),$2)
|
||||
IR = mkdir -p $2 && cp -r $1/. $2
|
||||
|
||||
# install progs & libs
|
||||
install-unx:
|
||||
$(call IBw,$(PROGS) $(PROGS_CROSS),"$(bindir)")
|
||||
$(call IFw,$(LIBTCC1) $(LIBTCC1_U),"$(tccdir)")
|
||||
$(call IF,$(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h,"$(tccdir)/include")
|
||||
$(call $(if $(findstring .so,$(LIBTCC)),IBw,IFw),$(LIBTCC),"$(libdir)")
|
||||
$(call IF,$(TOPSRC)/libtcc.h,"$(includedir)")
|
||||
$(call IFw,tcc.1,"$(mandir)/man1")
|
||||
$(call IFw,tcc-doc.info,"$(infodir)")
|
||||
$(call IFw,tcc-doc.html,"$(docdir)")
|
||||
ifneq "$(wildcard $(LIBTCC1_W))" ""
|
||||
$(call IFw,$(TOPSRC)/win32/lib/*.def $(LIBTCC1_W),"$(tccdir)/win32/lib")
|
||||
$(call IR,$(TOPSRC)/win32/include,"$(tccdir)/win32/include")
|
||||
$(call IF,$(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h,"$(tccdir)/win32/include")
|
||||
endif
|
||||
|
||||
# uninstall
|
||||
uninstall-unx:
|
||||
@rm -fv $(foreach P,$(PROGS) $(PROGS_CROSS),"$(bindir)/$P")
|
||||
@rm -fv "$(libdir)/libtcc.a" "$(libdir)/libtcc.so" "$(includedir)/libtcc.h"
|
||||
@rm -fv "$(mandir)/man1/tcc.1" "$(infodir)/tcc-doc.info"
|
||||
@rm -fv "$(docdir)/tcc-doc.html"
|
||||
rm -r "$(tccdir)"
|
||||
|
||||
# install progs & libs on windows
|
||||
install-win:
|
||||
$(call IBw,$(PROGS) $(PROGS_CROSS) $(subst libtcc.a,,$(LIBTCC)),"$(bindir)")
|
||||
$(call IF,$(TOPSRC)/win32/lib/*.def,"$(tccdir)/lib")
|
||||
$(call IFw,libtcc1.a $(LIBTCC1_W),"$(tccdir)/lib")
|
||||
$(call IF,$(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h,"$(tccdir)/include")
|
||||
$(call IR,$(TOPSRC)/win32/include,"$(tccdir)/include")
|
||||
$(call IR,$(TOPSRC)/win32/examples,"$(tccdir)/examples")
|
||||
$(call IF,$(TOPSRC)/tests/libtcc_test.c,"$(tccdir)/examples")
|
||||
$(call IFw,$(TOPSRC)/libtcc.h $(subst .dll,.def,$(LIBTCC)),"$(libdir)")
|
||||
$(call IFw,$(TOPSRC)/win32/tcc-win32.txt tcc-doc.html,"$(docdir)")
|
||||
ifneq "$(wildcard $(LIBTCC1_U))" ""
|
||||
$(call IFw,$(LIBTCC1_U),"$(tccdir)/lib")
|
||||
$(call IF,$(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h,"$(tccdir)/lib/include")
|
||||
endif
|
||||
|
||||
# the msys-git shell works to configure && make except it does not have install
|
||||
ifeq "$(and $(CONFIG_WIN32),$(shell which install >/dev/null 2>&1 || echo no))" "no"
|
||||
install-win : INSTALL = cp
|
||||
install-win : INSTALLBIN = cp
|
||||
endif
|
||||
|
||||
# uninstall on windows
|
||||
uninstall-win:
|
||||
@rm -fv $(foreach P,$(PROGS) $(PROGS_CROSS) libtcc.dll,"$(bindir)/$P")
|
||||
@rm -fv $(foreach F,tcc-doc.html tcc-win32.txt,"$(docdir)/$F")
|
||||
@rm -fv $(foreach F,libtcc.h libtcc.def libtcc.a,"$(libdir)/$F")
|
||||
rm -r "$(tccdir)"
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# other stuff
|
||||
|
||||
TAGFILES = *.[ch] include/*.h lib/*.[chS]
|
||||
tags : ; ctags $(TAGFILES)
|
||||
# cannot have both tags and TAGS on windows
|
||||
ETAGS : ; etags $(TAGFILES)
|
||||
|
||||
# create release tarball from *current* git branch (including tcc-doc.html
|
||||
# and converting two files to CRLF)
|
||||
TCC-VERSION = tcc-$(VERSION)
|
||||
tar: tcc-doc.html
|
||||
mkdir $(TCC-VERSION)
|
||||
( cd $(TCC-VERSION) && git --git-dir ../.git checkout -f )
|
||||
cp tcc-doc.html $(TCC-VERSION)
|
||||
for f in tcc-win32.txt build-tcc.bat ; do \
|
||||
cat win32/$$f | sed 's,\(.*\),\1\r,g' > $(TCC-VERSION)/win32/$$f ; \
|
||||
done
|
||||
tar cjf $(TCC-VERSION).tar.bz2 $(TCC-VERSION)
|
||||
rm -rf $(TCC-VERSION)
|
||||
git reset
|
||||
|
||||
config.mak:
|
||||
$(if $(wildcard $@),,@echo "Please run ./configure." && exit 1)
|
||||
|
||||
# run all tests
|
||||
test:
|
||||
$(MAKE) -C tests
|
||||
# run test(s) from tests2 subdir (see make help)
|
||||
tests2.%:
|
||||
$(MAKE) -C tests/tests2 $@
|
||||
|
||||
clean:
|
||||
rm -f tcc$(EXESUF) tcc_p$(EXESUF) *-tcc$(EXESUF) tcc.pod
|
||||
rm -f *~ *.o *.a *.so* *.out *.log lib*.def *.exe *.dll a.out tags TAGS
|
||||
@$(MAKE) -C lib $@
|
||||
@$(MAKE) -C tests $@
|
||||
|
||||
distclean: clean
|
||||
rm -f config.h config.mak config.texi tcc.1 tcc-doc.info tcc-doc.html
|
||||
|
||||
.PHONY: all clean test tar tags ETAGS distclean install uninstall FORCE
|
||||
|
||||
help:
|
||||
@echo "make"
|
||||
@echo " build native compiler (from separate objects)"
|
||||
@echo ""
|
||||
@echo "make cross"
|
||||
@echo " build cross compilers (from one source)"
|
||||
@echo ""
|
||||
@echo "make ONE_SOURCE=yes / no"
|
||||
@echo " force building from one source / separate objects"
|
||||
@echo ""
|
||||
@echo "make cross-TARGET"
|
||||
@echo " build one specific cross compiler for 'TARGET', as in"
|
||||
@echo " $(TCC_X)"
|
||||
@echo ""
|
||||
@echo "Custom configuration:"
|
||||
@echo " The makefile includes a file 'config-extra.mak' if it is present."
|
||||
@echo " This file may contain some custom configuration. For example:"
|
||||
@echo ""
|
||||
@echo " NATIVE_DEFINES += -D..."
|
||||
@echo ""
|
||||
@echo " Or for example to configure the search paths for a cross-compiler"
|
||||
@echo " that expects the linux files in <tccdir>/i386-linux:"
|
||||
@echo ""
|
||||
@echo " ROOT-i386 = {B}/i386-linux"
|
||||
@echo " CRT-i386 = {B}/i386-linux/usr/lib"
|
||||
@echo " LIB-i386 = {B}/i386-linux/lib:{B}/i386-linux/usr/lib"
|
||||
@echo " INC-i386 = {B}/lib/include:{B}/i386-linux/usr/include"
|
||||
@echo " DEF-i386 += -D__linux__"
|
||||
@echo ""
|
||||
@echo "make test"
|
||||
@echo " run all tests"
|
||||
@echo ""
|
||||
@echo "make tests2.all / make tests2.37 / make tests2.37+"
|
||||
@echo " run all/single test(s) from tests2, optionally update .expect"
|
||||
@echo ""
|
||||
@echo "Other supported make targets:"
|
||||
@echo " install install-strip tags ETAGS tar clean distclean help"
|
||||
@echo ""
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
endif # ($(INCLUDED),no)
|
95
05/tcc-0.9.27/README
Normal file
95
05/tcc-0.9.27/README
Normal file
|
@ -0,0 +1,95 @@
|
|||
Tiny C Compiler - C Scripting Everywhere - The Smallest ANSI C compiler
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
Features:
|
||||
--------
|
||||
|
||||
- SMALL! You can compile and execute C code everywhere, for example on
|
||||
rescue disks.
|
||||
|
||||
- FAST! tcc generates optimized x86 code. No byte code
|
||||
overhead. Compile, assemble and link about 7 times faster than 'gcc
|
||||
-O0'.
|
||||
|
||||
- UNLIMITED! Any C dynamic library can be used directly. TCC is
|
||||
heading torward full ISOC99 compliance. TCC can of course compile
|
||||
itself.
|
||||
|
||||
- SAFE! tcc includes an optional memory and bound checker. Bound
|
||||
checked code can be mixed freely with standard code.
|
||||
|
||||
- Compile and execute C source directly. No linking or assembly
|
||||
necessary. Full C preprocessor included.
|
||||
|
||||
- C script supported : just add '#!/usr/local/bin/tcc -run' at the first
|
||||
line of your C source, and execute it directly from the command
|
||||
line.
|
||||
|
||||
Documentation:
|
||||
-------------
|
||||
|
||||
1) Installation on a i386/x86_64/arm Linux/OSX/FreeBSD host
|
||||
|
||||
./configure
|
||||
make
|
||||
make test
|
||||
make install
|
||||
|
||||
Notes: For OSX and FreeBSD, gmake should be used instead of make.
|
||||
For Windows read tcc-win32.txt.
|
||||
|
||||
makeinfo must be installed to compile the doc. By default, tcc is
|
||||
installed in /usr/local/bin. ./configure --help shows configuration
|
||||
options.
|
||||
|
||||
|
||||
2) Introduction
|
||||
|
||||
We assume here that you know ANSI C. Look at the example ex1.c to know
|
||||
what the programs look like.
|
||||
|
||||
The include file <tcclib.h> can be used if you want a small basic libc
|
||||
include support (especially useful for floppy disks). Of course, you
|
||||
can also use standard headers, although they are slower to compile.
|
||||
|
||||
You can begin your C script with '#!/usr/local/bin/tcc -run' on the first
|
||||
line and set its execute bits (chmod a+x your_script). Then, you can
|
||||
launch the C code as a shell or perl script :-) The command line
|
||||
arguments are put in 'argc' and 'argv' of the main functions, as in
|
||||
ANSI C.
|
||||
|
||||
3) Examples
|
||||
|
||||
ex1.c: simplest example (hello world). Can also be launched directly
|
||||
as a script: './ex1.c'.
|
||||
|
||||
ex2.c: more complicated example: find a number with the four
|
||||
operations given a list of numbers (benchmark).
|
||||
|
||||
ex3.c: compute fibonacci numbers (benchmark).
|
||||
|
||||
ex4.c: more complicated: X11 program. Very complicated test in fact
|
||||
because standard headers are being used ! As for ex1.c, can also be launched
|
||||
directly as a script: './ex4.c'.
|
||||
|
||||
ex5.c: 'hello world' with standard glibc headers.
|
||||
|
||||
tcc.c: TCC can of course compile itself. Used to check the code
|
||||
generator.
|
||||
|
||||
tcctest.c: auto test for TCC which tests many subtle possible bugs. Used
|
||||
when doing 'make test'.
|
||||
|
||||
4) Full Documentation
|
||||
|
||||
Please read tcc-doc.html to have all the features of TCC.
|
||||
|
||||
Additional information is available for the Windows port in tcc-win32.txt.
|
||||
|
||||
License:
|
||||
-------
|
||||
|
||||
TCC is distributed under the GNU Lesser General Public License (see
|
||||
COPYING file).
|
||||
|
||||
Fabrice Bellard.
|
60
05/tcc-0.9.27/RELICENSING
Normal file
60
05/tcc-0.9.27/RELICENSING
Normal file
|
@ -0,0 +1,60 @@
|
|||
|
||||
Relicensing TinyCC
|
||||
------------------
|
||||
|
||||
The authors listed below hereby confirm their agreement to relicense TinyCC
|
||||
including their past contributions under the following terms:
|
||||
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
|
||||
|
||||
Author (name) I agree (YES/NO) Files/Features (optional)
|
||||
------------------------------------------------------------------------------
|
||||
Adam Sampson YES makefiles
|
||||
Daniel Glöckner NO arm-gen.c
|
||||
Daniel Glöckner YES not arm-gen.c
|
||||
Edmund Grimley Evans YES arm64
|
||||
Fabrice Bellard YES original author
|
||||
Frédéric Féret YES x86 64/16 bit asm
|
||||
grischka YES tccpe.c
|
||||
Henry Kroll YES
|
||||
Joe Soroka YES
|
||||
Kirill Smelkov YES
|
||||
mingodad YES
|
||||
Pip Cet YES
|
||||
Shinichiro Hamaji YES x86_64-gen.c
|
||||
Vincent Lefèvre YES
|
||||
Thomas Preud'homme YES arm-gen.c
|
||||
Timo VJ Lähde (Timppa) ? tiny_libmaker.c
|
||||
TK ? tcccoff.c c67-gen.c
|
||||
Urs Janssen YES
|
||||
waddlesplash YES
|
||||
Christian Jullien YES Windows Cygwin build and tests
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
Please add yourself to the list above (rsp. replace the question mark)
|
||||
and (after fetching the latest version) commit to the "mob" branch with
|
||||
commit message:
|
||||
|
||||
Relicensing TinyCC
|
||||
|
||||
Thanks.
|
100
05/tcc-0.9.27/TODO
Normal file
100
05/tcc-0.9.27/TODO
Normal file
|
@ -0,0 +1,100 @@
|
|||
TODO list:
|
||||
|
||||
Bugs:
|
||||
|
||||
- i386 fastcall is mostly wrong
|
||||
- FPU st(0) is left unclean (kwisatz haderach). Incompatible with
|
||||
optimized gcc/msc code
|
||||
- see transparent union pb in /urs/include/sys/socket.h
|
||||
- precise behaviour of typeof with arrays ? (__put_user macro)
|
||||
but should suffice for most cases)
|
||||
- handle '? x, y : z' in unsized variable initialization (',' is
|
||||
considered incorrectly as separator in preparser)
|
||||
- transform functions to function pointers in function parameters
|
||||
(net/ipv4/ip_output.c)
|
||||
- fix function pointer type display
|
||||
- check section alignment in C
|
||||
- fix invalid cast in comparison 'if (v == (int8_t)v)'
|
||||
- finish varargs.h support (gcc 3.2 testsuite issue)
|
||||
- fix static functions declared inside block
|
||||
- fix multiple unions init
|
||||
- make libtcc fully reentrant (except for the compilation stage itself).
|
||||
- struct/union/enum definitions in nested scopes (see also Debian bug #770657)
|
||||
- __STDC_IEC_559__: float f(void) { static float x = 0.0 / 0.0; return x; }
|
||||
- memory may be leaked after errors (longjmp).
|
||||
|
||||
Portability:
|
||||
|
||||
- it is assumed that int is 32-bit and sizeof(int) == 4
|
||||
- int is used when host or target size_t would make more sense
|
||||
- TCC handles target floating-point (fp) values using the host's fp
|
||||
arithmetic, which is simple and fast but may lead to exceptions
|
||||
and inaccuracy and wrong representations when cross-compiling
|
||||
|
||||
Linking:
|
||||
|
||||
- static linking (-static) does not work
|
||||
|
||||
Bound checking:
|
||||
|
||||
- fix bound exit on RedHat 7.3
|
||||
- setjmp is not supported properly in bound checking.
|
||||
- fix bound check code with '&' on local variables (currently done
|
||||
only for local arrays).
|
||||
- bound checking and float/long long/struct copy code. bound
|
||||
checking and symbol + offset optimization
|
||||
|
||||
Missing features:
|
||||
|
||||
- disable-asm and disable-bcheck options
|
||||
- __builtin_expect()
|
||||
- atexit (Nigel Horne)
|
||||
- C99: add complex types (gcc 3.2 testsuite issue)
|
||||
- postfix compound literals (see 20010124-1.c)
|
||||
- interactive mode / integrated debugger
|
||||
|
||||
Optimizations:
|
||||
|
||||
- suppress specific anonymous symbol handling
|
||||
- more parse optimizations (=even faster compilation)
|
||||
- memory alloc optimizations (=even faster compilation)
|
||||
- optimize VT_LOCAL + const
|
||||
- better local variables handling (needed for other targets)
|
||||
|
||||
Not critical:
|
||||
|
||||
- C99: fix multiple compound literals inits in blocks (ISOC99
|
||||
normative example - only relevant when using gotos! -> must add
|
||||
boolean variable to tell if compound literal was already
|
||||
initialized).
|
||||
- add PowerPC generator and improve codegen for RISC (need
|
||||
to suppress VT_LOCAL and use a base register instead).
|
||||
- fix preprocessor symbol redefinition
|
||||
- add portable byte code generator and interpreter for other
|
||||
unsupported architectures.
|
||||
- C++: variable declaration in for, minimal 'class' support.
|
||||
- win32: __intxx. use resolve for bchecked malloc et al.
|
||||
check exception code (exception filter func).
|
||||
- handle void (__attribute__() *ptr)()
|
||||
- VLAs are implemented in a way that is not compatible with signals:
|
||||
http://lists.gnu.org/archive/html/tinycc-devel/2015-11/msg00018.html
|
||||
|
||||
Fixed (probably):
|
||||
|
||||
- bug with defines:
|
||||
#define spin_lock(lock) do { } while (0)
|
||||
#define wq_spin_lock spin_lock
|
||||
#define TEST() wq_spin_lock(a)
|
||||
- typedefs can be structure fields
|
||||
- see bugfixes.diff + improvement.diff from Daniel Glockner
|
||||
- long long constant evaluation
|
||||
- add alloca()
|
||||
- gcc '-E' option.
|
||||
- #include_next support for /usr/include/limits ?
|
||||
- function pointers/lvalues in ? : (linux kernel net/core/dev.c)
|
||||
- win32: add __stdcall, check GetModuleHandle for dlls.
|
||||
- macro substitution with nested definitions (ShangHongzhang)
|
||||
- with "-run" and libtcc, a PLT is now built.
|
||||
- '-E' option was improved
|
||||
- packed attribute is now supported
|
||||
- ARM and ARM64 code generators have been added.
|
1
05/tcc-0.9.27/VERSION
Normal file
1
05/tcc-0.9.27/VERSION
Normal file
|
@ -0,0 +1 @@
|
|||
0.9.27
|
94
05/tcc-0.9.27/arm-asm.c
Normal file
94
05/tcc-0.9.27/arm-asm.c
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*************************************************************/
|
||||
/*
|
||||
* ARM dummy assembler for TCC
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef TARGET_DEFS_ONLY
|
||||
|
||||
#define CONFIG_TCC_ASM
|
||||
#define NB_ASM_REGS 16
|
||||
|
||||
ST_FUNC void g(int c);
|
||||
ST_FUNC void gen_le16(int c);
|
||||
ST_FUNC void gen_le32(int c);
|
||||
|
||||
/*************************************************************/
|
||||
#else
|
||||
/*************************************************************/
|
||||
|
||||
#include "tcc.h"
|
||||
|
||||
static void asm_error(void)
|
||||
{
|
||||
tcc_error("ARM asm not implemented.");
|
||||
}
|
||||
|
||||
/* XXX: make it faster ? */
|
||||
ST_FUNC void g(int c)
|
||||
{
|
||||
int ind1;
|
||||
if (nocode_wanted)
|
||||
return;
|
||||
ind1 = ind + 1;
|
||||
if (ind1 > cur_text_section->data_allocated)
|
||||
section_realloc(cur_text_section, ind1);
|
||||
cur_text_section->data[ind] = c;
|
||||
ind = ind1;
|
||||
}
|
||||
|
||||
ST_FUNC void gen_le16 (int i)
|
||||
{
|
||||
g(i);
|
||||
g(i>>8);
|
||||
}
|
||||
|
||||
ST_FUNC void gen_le32 (int i)
|
||||
{
|
||||
gen_le16(i);
|
||||
gen_le16(i>>16);
|
||||
}
|
||||
|
||||
ST_FUNC void gen_expr32(ExprValue *pe)
|
||||
{
|
||||
gen_le32(pe->v);
|
||||
}
|
||||
|
||||
ST_FUNC void asm_opcode(TCCState *s1, int opcode)
|
||||
{
|
||||
asm_error();
|
||||
}
|
||||
|
||||
ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier)
|
||||
{
|
||||
asm_error();
|
||||
}
|
||||
|
||||
/* generate prolog and epilog code for asm statement */
|
||||
ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands,
|
||||
int nb_outputs, int is_output,
|
||||
uint8_t *clobber_regs,
|
||||
int out_reg)
|
||||
{
|
||||
}
|
||||
|
||||
ST_FUNC void asm_compute_constraints(ASMOperand *operands,
|
||||
int nb_operands, int nb_outputs,
|
||||
const uint8_t *clobber_regs,
|
||||
int *pout_reg)
|
||||
{
|
||||
}
|
||||
|
||||
ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str)
|
||||
{
|
||||
asm_error();
|
||||
}
|
||||
|
||||
ST_FUNC int asm_parse_regvar (int t)
|
||||
{
|
||||
asm_error();
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*************************************************************/
|
||||
#endif /* ndef TARGET_DEFS_ONLY */
|
2151
05/tcc-0.9.27/arm-gen.c
Normal file
2151
05/tcc-0.9.27/arm-gen.c
Normal file
File diff suppressed because it is too large
Load diff
398
05/tcc-0.9.27/arm-link.c
Normal file
398
05/tcc-0.9.27/arm-link.c
Normal file
|
@ -0,0 +1,398 @@
|
|||
#ifdef TARGET_DEFS_ONLY
|
||||
|
||||
#define EM_TCC_TARGET EM_ARM
|
||||
|
||||
/* relocation type for 32 bit data relocation */
|
||||
#define R_DATA_32 R_ARM_ABS32
|
||||
#define R_DATA_PTR R_ARM_ABS32
|
||||
#define R_JMP_SLOT R_ARM_JUMP_SLOT
|
||||
#define R_GLOB_DAT R_ARM_GLOB_DAT
|
||||
#define R_COPY R_ARM_COPY
|
||||
#define R_RELATIVE R_ARM_RELATIVE
|
||||
|
||||
#define R_NUM R_ARM_NUM
|
||||
|
||||
#define ELF_START_ADDR 0x00008000
|
||||
#define ELF_PAGE_SIZE 0x1000
|
||||
|
||||
#define PCRELATIVE_DLLPLT 1
|
||||
#define RELOCATE_DLLPLT 0
|
||||
|
||||
enum float_abi {
|
||||
ARM_SOFTFP_FLOAT,
|
||||
ARM_HARD_FLOAT,
|
||||
};
|
||||
|
||||
#else /* !TARGET_DEFS_ONLY */
|
||||
|
||||
#include "tcc.h"
|
||||
|
||||
/* Returns 1 for a code relocation, 0 for a data relocation. For unknown
|
||||
relocations, returns -1. */
|
||||
int code_reloc (int reloc_type)
|
||||
{
|
||||
switch (reloc_type) {
|
||||
case R_ARM_MOVT_ABS:
|
||||
case R_ARM_MOVW_ABS_NC:
|
||||
case R_ARM_THM_MOVT_ABS:
|
||||
case R_ARM_THM_MOVW_ABS_NC:
|
||||
case R_ARM_ABS32:
|
||||
case R_ARM_REL32:
|
||||
case R_ARM_GOTPC:
|
||||
case R_ARM_GOTOFF:
|
||||
case R_ARM_GOT32:
|
||||
case R_ARM_COPY:
|
||||
case R_ARM_GLOB_DAT:
|
||||
case R_ARM_NONE:
|
||||
return 0;
|
||||
|
||||
case R_ARM_PC24:
|
||||
case R_ARM_CALL:
|
||||
case R_ARM_JUMP24:
|
||||
case R_ARM_PLT32:
|
||||
case R_ARM_THM_PC22:
|
||||
case R_ARM_THM_JUMP24:
|
||||
case R_ARM_PREL31:
|
||||
case R_ARM_V4BX:
|
||||
case R_ARM_JUMP_SLOT:
|
||||
return 1;
|
||||
}
|
||||
|
||||
tcc_error ("Unknown relocation type: %d", reloc_type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Returns an enumerator to describe whether and when the relocation needs a
|
||||
GOT and/or PLT entry to be created. See tcc.h for a description of the
|
||||
different values. */
|
||||
int gotplt_entry_type (int reloc_type)
|
||||
{
|
||||
switch (reloc_type) {
|
||||
case R_ARM_NONE:
|
||||
case R_ARM_COPY:
|
||||
case R_ARM_GLOB_DAT:
|
||||
case R_ARM_JUMP_SLOT:
|
||||
return NO_GOTPLT_ENTRY;
|
||||
|
||||
case R_ARM_PC24:
|
||||
case R_ARM_CALL:
|
||||
case R_ARM_JUMP24:
|
||||
case R_ARM_PLT32:
|
||||
case R_ARM_THM_PC22:
|
||||
case R_ARM_THM_JUMP24:
|
||||
case R_ARM_MOVT_ABS:
|
||||
case R_ARM_MOVW_ABS_NC:
|
||||
case R_ARM_THM_MOVT_ABS:
|
||||
case R_ARM_THM_MOVW_ABS_NC:
|
||||
case R_ARM_PREL31:
|
||||
case R_ARM_ABS32:
|
||||
case R_ARM_REL32:
|
||||
case R_ARM_V4BX:
|
||||
return AUTO_GOTPLT_ENTRY;
|
||||
|
||||
case R_ARM_GOTPC:
|
||||
case R_ARM_GOTOFF:
|
||||
return BUILD_GOT_ONLY;
|
||||
|
||||
case R_ARM_GOT32:
|
||||
return ALWAYS_GOTPLT_ENTRY;
|
||||
}
|
||||
|
||||
tcc_error ("Unknown relocation type: %d", reloc_type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
|
||||
{
|
||||
Section *plt = s1->plt;
|
||||
uint8_t *p;
|
||||
unsigned plt_offset;
|
||||
|
||||
/* when building a DLL, GOT entry accesses must be done relative to
|
||||
start of GOT (see x86_64 example above) */
|
||||
if (s1->output_type == TCC_OUTPUT_DLL)
|
||||
tcc_error("DLLs unimplemented!");
|
||||
|
||||
/* empty PLT: create PLT0 entry that push address of call site and
|
||||
jump to ld.so resolution routine (GOT + 8) */
|
||||
if (plt->data_offset == 0) {
|
||||
p = section_ptr_add(plt, 20);
|
||||
write32le(p, 0xe52de004); /* push {lr} */
|
||||
write32le(p+4, 0xe59fe004); /* ldr lr, [pc, #4] */
|
||||
write32le(p+8, 0xe08fe00e); /* add lr, pc, lr */
|
||||
write32le(p+12, 0xe5bef008); /* ldr pc, [lr, #8]! */
|
||||
/* p+16 is set in relocate_plt */
|
||||
}
|
||||
plt_offset = plt->data_offset;
|
||||
|
||||
if (attr->plt_thumb_stub) {
|
||||
p = section_ptr_add(plt, 4);
|
||||
write32le(p, 0x4778); /* bx pc */
|
||||
write32le(p+2, 0x46c0); /* nop */
|
||||
}
|
||||
p = section_ptr_add(plt, 16);
|
||||
/* Jump to GOT entry where ld.so initially put address of PLT0 */
|
||||
write32le(p, 0xe59fc004); /* ldr ip, [pc, #4] */
|
||||
write32le(p+4, 0xe08fc00c); /* add ip, pc, ip */
|
||||
write32le(p+8, 0xe59cf000); /* ldr pc, [ip] */
|
||||
/* p + 12 contains offset to GOT entry once patched by relocate_plt */
|
||||
write32le(p+12, got_offset);
|
||||
return plt_offset;
|
||||
}
|
||||
|
||||
/* relocate the PLT: compute addresses and offsets in the PLT now that final
|
||||
address for PLT and GOT are known (see fill_program_header) */
|
||||
ST_FUNC void relocate_plt(TCCState *s1)
|
||||
{
|
||||
uint8_t *p, *p_end;
|
||||
|
||||
if (!s1->plt)
|
||||
return;
|
||||
|
||||
p = s1->plt->data;
|
||||
p_end = p + s1->plt->data_offset;
|
||||
|
||||
if (p < p_end) {
|
||||
int x = s1->got->sh_addr - s1->plt->sh_addr - 12;
|
||||
write32le(s1->plt->data + 16, x - 16);
|
||||
p += 20;
|
||||
while (p < p_end) {
|
||||
if (read32le(p) == 0x46c04778) /* PLT Thumb stub present */
|
||||
p += 4;
|
||||
add32le(p + 12, x + s1->plt->data - p);
|
||||
p += 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void relocate_init(Section *sr) {}
|
||||
|
||||
void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
|
||||
{
|
||||
ElfW(Sym) *sym;
|
||||
int sym_index;
|
||||
|
||||
sym_index = ELFW(R_SYM)(rel->r_info);
|
||||
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
||||
|
||||
switch(type) {
|
||||
case R_ARM_PC24:
|
||||
case R_ARM_CALL:
|
||||
case R_ARM_JUMP24:
|
||||
case R_ARM_PLT32:
|
||||
{
|
||||
int x, is_thumb, is_call, h, blx_avail, is_bl, th_ko;
|
||||
x = (*(int *) ptr) & 0xffffff;
|
||||
#ifdef DEBUG_RELOC
|
||||
printf ("reloc %d: x=0x%x val=0x%x ", type, x, val);
|
||||
#endif
|
||||
(*(int *)ptr) &= 0xff000000;
|
||||
if (x & 0x800000)
|
||||
x -= 0x1000000;
|
||||
x <<= 2;
|
||||
blx_avail = (TCC_CPU_VERSION >= 5);
|
||||
is_thumb = val & 1;
|
||||
is_bl = (*(unsigned *) ptr) >> 24 == 0xeb;
|
||||
is_call = (type == R_ARM_CALL || (type == R_ARM_PC24 && is_bl));
|
||||
x += val - addr;
|
||||
#ifdef DEBUG_RELOC
|
||||
printf (" newx=0x%x name=%s\n", x,
|
||||
(char *) symtab_section->link->data + sym->st_name);
|
||||
#endif
|
||||
h = x & 2;
|
||||
th_ko = (x & 3) && (!blx_avail || !is_call);
|
||||
if (th_ko || x >= 0x2000000 || x < -0x2000000)
|
||||
tcc_error("can't relocate value at %x,%d",addr, type);
|
||||
x >>= 2;
|
||||
x &= 0xffffff;
|
||||
/* Only reached if blx is avail and it is a call */
|
||||
if (is_thumb) {
|
||||
x |= h << 24;
|
||||
(*(int *)ptr) = 0xfa << 24; /* bl -> blx */
|
||||
}
|
||||
(*(int *) ptr) |= x;
|
||||
}
|
||||
return;
|
||||
/* Since these relocations only concern Thumb-2 and blx instruction was
|
||||
introduced before Thumb-2, we can assume blx is available and not
|
||||
guard its use */
|
||||
case R_ARM_THM_PC22:
|
||||
case R_ARM_THM_JUMP24:
|
||||
{
|
||||
int x, hi, lo, s, j1, j2, i1, i2, imm10, imm11;
|
||||
int to_thumb, is_call, to_plt, blx_bit = 1 << 12;
|
||||
Section *plt;
|
||||
|
||||
/* weak reference */
|
||||
if (sym->st_shndx == SHN_UNDEF &&
|
||||
ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
|
||||
return;
|
||||
|
||||
/* Get initial offset */
|
||||
hi = (*(uint16_t *)ptr);
|
||||
lo = (*(uint16_t *)(ptr+2));
|
||||
s = (hi >> 10) & 1;
|
||||
j1 = (lo >> 13) & 1;
|
||||
j2 = (lo >> 11) & 1;
|
||||
i1 = (j1 ^ s) ^ 1;
|
||||
i2 = (j2 ^ s) ^ 1;
|
||||
imm10 = hi & 0x3ff;
|
||||
imm11 = lo & 0x7ff;
|
||||
x = (s << 24) | (i1 << 23) | (i2 << 22) |
|
||||
(imm10 << 12) | (imm11 << 1);
|
||||
if (x & 0x01000000)
|
||||
x -= 0x02000000;
|
||||
|
||||
/* Relocation infos */
|
||||
to_thumb = val & 1;
|
||||
plt = s1->plt;
|
||||
to_plt = (val >= plt->sh_addr) &&
|
||||
(val < plt->sh_addr + plt->data_offset);
|
||||
is_call = (type == R_ARM_THM_PC22);
|
||||
|
||||
if (!to_thumb && !to_plt && !is_call) {
|
||||
int index;
|
||||
uint8_t *p;
|
||||
char *name, buf[1024];
|
||||
Section *text_section;
|
||||
|
||||
name = (char *) symtab_section->link->data + sym->st_name;
|
||||
text_section = s1->sections[sym->st_shndx];
|
||||
/* Modify reloc to target a thumb stub to switch to ARM */
|
||||
snprintf(buf, sizeof(buf), "%s_from_thumb", name);
|
||||
index = put_elf_sym(symtab_section,
|
||||
text_section->data_offset + 1,
|
||||
sym->st_size, sym->st_info, 0,
|
||||
sym->st_shndx, buf);
|
||||
to_thumb = 1;
|
||||
val = text_section->data_offset + 1;
|
||||
rel->r_info = ELFW(R_INFO)(index, type);
|
||||
/* Create a thumb stub function to switch to ARM mode */
|
||||
put_elf_reloc(symtab_section, text_section,
|
||||
text_section->data_offset + 4, R_ARM_JUMP24,
|
||||
sym_index);
|
||||
p = section_ptr_add(text_section, 8);
|
||||
write32le(p, 0x4778); /* bx pc */
|
||||
write32le(p+2, 0x46c0); /* nop */
|
||||
write32le(p+4, 0xeafffffe); /* b $sym */
|
||||
}
|
||||
|
||||
/* Compute final offset */
|
||||
x += val - addr;
|
||||
if (!to_thumb && is_call) {
|
||||
blx_bit = 0; /* bl -> blx */
|
||||
x = (x + 3) & -4; /* Compute offset from aligned PC */
|
||||
}
|
||||
|
||||
/* Check that relocation is possible
|
||||
* offset must not be out of range
|
||||
* if target is to be entered in arm mode:
|
||||
- bit 1 must not set
|
||||
- instruction must be a call (bl) or a jump to PLT */
|
||||
if (!to_thumb || x >= 0x1000000 || x < -0x1000000)
|
||||
if (to_thumb || (val & 2) || (!is_call && !to_plt))
|
||||
tcc_error("can't relocate value at %x,%d",addr, type);
|
||||
|
||||
/* Compute and store final offset */
|
||||
s = (x >> 24) & 1;
|
||||
i1 = (x >> 23) & 1;
|
||||
i2 = (x >> 22) & 1;
|
||||
j1 = s ^ (i1 ^ 1);
|
||||
j2 = s ^ (i2 ^ 1);
|
||||
imm10 = (x >> 12) & 0x3ff;
|
||||
imm11 = (x >> 1) & 0x7ff;
|
||||
(*(uint16_t *)ptr) = (uint16_t) ((hi & 0xf800) |
|
||||
(s << 10) | imm10);
|
||||
(*(uint16_t *)(ptr+2)) = (uint16_t) ((lo & 0xc000) |
|
||||
(j1 << 13) | blx_bit | (j2 << 11) |
|
||||
imm11);
|
||||
}
|
||||
return;
|
||||
case R_ARM_MOVT_ABS:
|
||||
case R_ARM_MOVW_ABS_NC:
|
||||
{
|
||||
int x, imm4, imm12;
|
||||
if (type == R_ARM_MOVT_ABS)
|
||||
val >>= 16;
|
||||
imm12 = val & 0xfff;
|
||||
imm4 = (val >> 12) & 0xf;
|
||||
x = (imm4 << 16) | imm12;
|
||||
if (type == R_ARM_THM_MOVT_ABS)
|
||||
*(int *)ptr |= x;
|
||||
else
|
||||
*(int *)ptr += x;
|
||||
}
|
||||
return;
|
||||
case R_ARM_THM_MOVT_ABS:
|
||||
case R_ARM_THM_MOVW_ABS_NC:
|
||||
{
|
||||
int x, i, imm4, imm3, imm8;
|
||||
if (type == R_ARM_THM_MOVT_ABS)
|
||||
val >>= 16;
|
||||
imm8 = val & 0xff;
|
||||
imm3 = (val >> 8) & 0x7;
|
||||
i = (val >> 11) & 1;
|
||||
imm4 = (val >> 12) & 0xf;
|
||||
x = (imm3 << 28) | (imm8 << 16) | (i << 10) | imm4;
|
||||
if (type == R_ARM_THM_MOVT_ABS)
|
||||
*(int *)ptr |= x;
|
||||
else
|
||||
*(int *)ptr += x;
|
||||
}
|
||||
return;
|
||||
case R_ARM_PREL31:
|
||||
{
|
||||
int x;
|
||||
x = (*(int *)ptr) & 0x7fffffff;
|
||||
(*(int *)ptr) &= 0x80000000;
|
||||
x = (x * 2) / 2;
|
||||
x += val - addr;
|
||||
if((x^(x>>1))&0x40000000)
|
||||
tcc_error("can't relocate value at %x,%d",addr, type);
|
||||
(*(int *)ptr) |= x & 0x7fffffff;
|
||||
}
|
||||
case R_ARM_ABS32:
|
||||
*(int *)ptr += val;
|
||||
return;
|
||||
case R_ARM_REL32:
|
||||
*(int *)ptr += val - addr;
|
||||
return;
|
||||
case R_ARM_GOTPC:
|
||||
*(int *)ptr += s1->got->sh_addr - addr;
|
||||
return;
|
||||
case R_ARM_GOTOFF:
|
||||
*(int *)ptr += val - s1->got->sh_addr;
|
||||
return;
|
||||
case R_ARM_GOT32:
|
||||
/* we load the got offset */
|
||||
*(int *)ptr += s1->sym_attrs[sym_index].got_offset;
|
||||
return;
|
||||
case R_ARM_COPY:
|
||||
return;
|
||||
case R_ARM_V4BX:
|
||||
/* trade Thumb support for ARMv4 support */
|
||||
if ((0x0ffffff0 & *(int*)ptr) == 0x012FFF10)
|
||||
*(int*)ptr ^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */
|
||||
return;
|
||||
case R_ARM_GLOB_DAT:
|
||||
case R_ARM_JUMP_SLOT:
|
||||
*(addr_t *)ptr = val;
|
||||
return;
|
||||
case R_ARM_NONE:
|
||||
/* Nothing to do. Normally used to indicate a dependency
|
||||
on a certain symbol (like for exception handling under EABI). */
|
||||
return;
|
||||
case R_ARM_RELATIVE:
|
||||
#ifdef TCC_TARGET_PE
|
||||
add32le(ptr, val - s1->pe_imagebase);
|
||||
#endif
|
||||
/* do nothing */
|
||||
return;
|
||||
default:
|
||||
fprintf(stderr,"FIXME: handle reloc type %x at %x [%p] to %x\n",
|
||||
type, (unsigned)addr, ptr, (unsigned)val);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* !TARGET_DEFS_ONLY */
|
1837
05/tcc-0.9.27/arm64-gen.c
Normal file
1837
05/tcc-0.9.27/arm64-gen.c
Normal file
File diff suppressed because it is too large
Load diff
256
05/tcc-0.9.27/arm64-link.c
Normal file
256
05/tcc-0.9.27/arm64-link.c
Normal file
|
@ -0,0 +1,256 @@
|
|||
#ifdef TARGET_DEFS_ONLY
|
||||
|
||||
#define EM_TCC_TARGET EM_AARCH64
|
||||
|
||||
#define R_DATA_32 R_AARCH64_ABS32
|
||||
#define R_DATA_PTR R_AARCH64_ABS64
|
||||
#define R_JMP_SLOT R_AARCH64_JUMP_SLOT
|
||||
#define R_GLOB_DAT R_AARCH64_GLOB_DAT
|
||||
#define R_COPY R_AARCH64_COPY
|
||||
#define R_RELATIVE R_AARCH64_RELATIVE
|
||||
|
||||
#define R_NUM R_AARCH64_NUM
|
||||
|
||||
#define ELF_START_ADDR 0x00400000
|
||||
#define ELF_PAGE_SIZE 0x1000
|
||||
|
||||
#define PCRELATIVE_DLLPLT 1
|
||||
#define RELOCATE_DLLPLT 1
|
||||
|
||||
#else /* !TARGET_DEFS_ONLY */
|
||||
|
||||
#include "tcc.h"
|
||||
|
||||
/* Returns 1 for a code relocation, 0 for a data relocation. For unknown
|
||||
relocations, returns -1. */
|
||||
int code_reloc (int reloc_type)
|
||||
{
|
||||
switch (reloc_type) {
|
||||
case R_AARCH64_ABS32:
|
||||
case R_AARCH64_ABS64:
|
||||
case R_AARCH64_PREL32:
|
||||
case R_AARCH64_MOVW_UABS_G0_NC:
|
||||
case R_AARCH64_MOVW_UABS_G1_NC:
|
||||
case R_AARCH64_MOVW_UABS_G2_NC:
|
||||
case R_AARCH64_MOVW_UABS_G3:
|
||||
case R_AARCH64_ADR_PREL_PG_HI21:
|
||||
case R_AARCH64_ADD_ABS_LO12_NC:
|
||||
case R_AARCH64_ADR_GOT_PAGE:
|
||||
case R_AARCH64_LD64_GOT_LO12_NC:
|
||||
case R_AARCH64_GLOB_DAT:
|
||||
case R_AARCH64_COPY:
|
||||
return 0;
|
||||
|
||||
case R_AARCH64_JUMP26:
|
||||
case R_AARCH64_CALL26:
|
||||
case R_AARCH64_JUMP_SLOT:
|
||||
return 1;
|
||||
}
|
||||
|
||||
tcc_error ("Unknown relocation type: %d", reloc_type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Returns an enumerator to describe whether and when the relocation needs a
|
||||
GOT and/or PLT entry to be created. See tcc.h for a description of the
|
||||
different values. */
|
||||
int gotplt_entry_type (int reloc_type)
|
||||
{
|
||||
switch (reloc_type) {
|
||||
case R_AARCH64_PREL32:
|
||||
case R_AARCH64_MOVW_UABS_G0_NC:
|
||||
case R_AARCH64_MOVW_UABS_G1_NC:
|
||||
case R_AARCH64_MOVW_UABS_G2_NC:
|
||||
case R_AARCH64_MOVW_UABS_G3:
|
||||
case R_AARCH64_ADR_PREL_PG_HI21:
|
||||
case R_AARCH64_ADD_ABS_LO12_NC:
|
||||
case R_AARCH64_GLOB_DAT:
|
||||
case R_AARCH64_JUMP_SLOT:
|
||||
case R_AARCH64_COPY:
|
||||
return NO_GOTPLT_ENTRY;
|
||||
|
||||
case R_AARCH64_ABS32:
|
||||
case R_AARCH64_ABS64:
|
||||
case R_AARCH64_JUMP26:
|
||||
case R_AARCH64_CALL26:
|
||||
return AUTO_GOTPLT_ENTRY;
|
||||
|
||||
case R_AARCH64_ADR_GOT_PAGE:
|
||||
case R_AARCH64_LD64_GOT_LO12_NC:
|
||||
return ALWAYS_GOTPLT_ENTRY;
|
||||
}
|
||||
|
||||
tcc_error ("Unknown relocation type: %d", reloc_type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
|
||||
{
|
||||
Section *plt = s1->plt;
|
||||
uint8_t *p;
|
||||
unsigned plt_offset;
|
||||
|
||||
if (s1->output_type == TCC_OUTPUT_DLL)
|
||||
tcc_error("DLLs unimplemented!");
|
||||
|
||||
if (plt->data_offset == 0) {
|
||||
section_ptr_add(plt, 32);
|
||||
}
|
||||
plt_offset = plt->data_offset;
|
||||
|
||||
p = section_ptr_add(plt, 16);
|
||||
write32le(p, got_offset);
|
||||
write32le(p + 4, (uint64_t) got_offset >> 32);
|
||||
return plt_offset;
|
||||
}
|
||||
|
||||
/* relocate the PLT: compute addresses and offsets in the PLT now that final
|
||||
address for PLT and GOT are known (see fill_program_header) */
|
||||
ST_FUNC void relocate_plt(TCCState *s1)
|
||||
{
|
||||
uint8_t *p, *p_end;
|
||||
|
||||
if (!s1->plt)
|
||||
return;
|
||||
|
||||
p = s1->plt->data;
|
||||
p_end = p + s1->plt->data_offset;
|
||||
|
||||
if (p < p_end) {
|
||||
uint64_t plt = s1->plt->sh_addr;
|
||||
uint64_t got = s1->got->sh_addr;
|
||||
uint64_t off = (got >> 12) - (plt >> 12);
|
||||
if ((off + ((uint32_t)1 << 20)) >> 21)
|
||||
tcc_error("Failed relocating PLT (off=0x%lx, got=0x%lx, plt=0x%lx)", off, got, plt);
|
||||
write32le(p, 0xa9bf7bf0); // stp x16,x30,[sp,#-16]!
|
||||
write32le(p + 4, (0x90000010 | // adrp x16,...
|
||||
(off & 0x1ffffc) << 3 | (off & 3) << 29));
|
||||
write32le(p + 8, (0xf9400211 | // ldr x17,[x16,#...]
|
||||
(got & 0xff8) << 7));
|
||||
write32le(p + 12, (0x91000210 | // add x16,x16,#...
|
||||
(got & 0xfff) << 10));
|
||||
write32le(p + 16, 0xd61f0220); // br x17
|
||||
write32le(p + 20, 0xd503201f); // nop
|
||||
write32le(p + 24, 0xd503201f); // nop
|
||||
write32le(p + 28, 0xd503201f); // nop
|
||||
p += 32;
|
||||
while (p < p_end) {
|
||||
uint64_t pc = plt + (p - s1->plt->data);
|
||||
uint64_t addr = got + read64le(p);
|
||||
uint64_t off = (addr >> 12) - (pc >> 12);
|
||||
if ((off + ((uint32_t)1 << 20)) >> 21)
|
||||
tcc_error("Failed relocating PLT (off=0x%lx, addr=0x%lx, pc=0x%lx)", off, addr, pc);
|
||||
write32le(p, (0x90000010 | // adrp x16,...
|
||||
(off & 0x1ffffc) << 3 | (off & 3) << 29));
|
||||
write32le(p + 4, (0xf9400211 | // ldr x17,[x16,#...]
|
||||
(addr & 0xff8) << 7));
|
||||
write32le(p + 8, (0x91000210 | // add x16,x16,#...
|
||||
(addr & 0xfff) << 10));
|
||||
write32le(p + 12, 0xd61f0220); // br x17
|
||||
p += 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void relocate_init(Section *sr) {}
|
||||
|
||||
void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
|
||||
{
|
||||
int sym_index = ELFW(R_SYM)(rel->r_info);
|
||||
#ifdef DEBUG_RELOC
|
||||
ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
||||
#endif
|
||||
|
||||
switch(type) {
|
||||
case R_AARCH64_ABS64:
|
||||
write64le(ptr, val);
|
||||
return;
|
||||
case R_AARCH64_ABS32:
|
||||
write32le(ptr, val);
|
||||
return;
|
||||
case R_AARCH64_PREL32:
|
||||
write32le(ptr, val - addr);
|
||||
return;
|
||||
case R_AARCH64_MOVW_UABS_G0_NC:
|
||||
write32le(ptr, ((read32le(ptr) & 0xffe0001f) |
|
||||
(val & 0xffff) << 5));
|
||||
return;
|
||||
case R_AARCH64_MOVW_UABS_G1_NC:
|
||||
write32le(ptr, ((read32le(ptr) & 0xffe0001f) |
|
||||
(val >> 16 & 0xffff) << 5));
|
||||
return;
|
||||
case R_AARCH64_MOVW_UABS_G2_NC:
|
||||
write32le(ptr, ((read32le(ptr) & 0xffe0001f) |
|
||||
(val >> 32 & 0xffff) << 5));
|
||||
return;
|
||||
case R_AARCH64_MOVW_UABS_G3:
|
||||
write32le(ptr, ((read32le(ptr) & 0xffe0001f) |
|
||||
(val >> 48 & 0xffff) << 5));
|
||||
return;
|
||||
case R_AARCH64_ADR_PREL_PG_HI21: {
|
||||
uint64_t off = (val >> 12) - (addr >> 12);
|
||||
if ((off + ((uint64_t)1 << 20)) >> 21)
|
||||
tcc_error("R_AARCH64_ADR_PREL_PG_HI21 relocation failed");
|
||||
write32le(ptr, ((read32le(ptr) & 0x9f00001f) |
|
||||
(off & 0x1ffffc) << 3 | (off & 3) << 29));
|
||||
return;
|
||||
}
|
||||
case R_AARCH64_ADD_ABS_LO12_NC:
|
||||
write32le(ptr, ((read32le(ptr) & 0xffc003ff) |
|
||||
(val & 0xfff) << 10));
|
||||
return;
|
||||
case R_AARCH64_JUMP26:
|
||||
case R_AARCH64_CALL26:
|
||||
#ifdef DEBUG_RELOC
|
||||
printf ("reloc %d @ 0x%lx: val=0x%lx name=%s\n", type, addr, val,
|
||||
(char *) symtab_section->link->data + sym->st_name);
|
||||
#endif
|
||||
if (((val - addr) + ((uint64_t)1 << 27)) & ~(uint64_t)0xffffffc)
|
||||
tcc_error("R_AARCH64_(JUMP|CALL)26 relocation failed"
|
||||
" (val=%lx, addr=%lx)", val, addr);
|
||||
write32le(ptr, (0x14000000 |
|
||||
(uint32_t)(type == R_AARCH64_CALL26) << 31 |
|
||||
((val - addr) >> 2 & 0x3ffffff)));
|
||||
return;
|
||||
case R_AARCH64_ADR_GOT_PAGE: {
|
||||
uint64_t off =
|
||||
(((s1->got->sh_addr +
|
||||
s1->sym_attrs[sym_index].got_offset) >> 12) - (addr >> 12));
|
||||
if ((off + ((uint64_t)1 << 20)) >> 21)
|
||||
tcc_error("R_AARCH64_ADR_GOT_PAGE relocation failed");
|
||||
write32le(ptr, ((read32le(ptr) & 0x9f00001f) |
|
||||
(off & 0x1ffffc) << 3 | (off & 3) << 29));
|
||||
return;
|
||||
}
|
||||
case R_AARCH64_LD64_GOT_LO12_NC:
|
||||
write32le(ptr,
|
||||
((read32le(ptr) & 0xfff803ff) |
|
||||
((s1->got->sh_addr +
|
||||
s1->sym_attrs[sym_index].got_offset) & 0xff8) << 7));
|
||||
return;
|
||||
case R_AARCH64_COPY:
|
||||
return;
|
||||
case R_AARCH64_GLOB_DAT:
|
||||
case R_AARCH64_JUMP_SLOT:
|
||||
/* They don't need addend */
|
||||
#ifdef DEBUG_RELOC
|
||||
printf ("reloc %d @ 0x%lx: val=0x%lx name=%s\n", type, addr,
|
||||
val - rel->r_addend,
|
||||
(char *) symtab_section->link->data + sym->st_name);
|
||||
#endif
|
||||
write64le(ptr, val - rel->r_addend);
|
||||
return;
|
||||
case R_AARCH64_RELATIVE:
|
||||
#ifdef TCC_TARGET_PE
|
||||
add32le(ptr, val - s1->pe_imagebase);
|
||||
#endif
|
||||
/* do nothing */
|
||||
return;
|
||||
default:
|
||||
fprintf(stderr, "FIXME: handle reloc type %x at %x [%p] to %x\n",
|
||||
type, (unsigned)addr, ptr, (unsigned)val);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* !TARGET_DEFS_ONLY */
|
7
05/tcc-0.9.27/assert.h
Normal file
7
05/tcc-0.9.27/assert.h
Normal file
|
@ -0,0 +1,7 @@
|
|||
#ifndef _ASSERT_H
|
||||
#define _ASSERT_H
|
||||
|
||||
// assert is defined in stdc_common.h
|
||||
#include <stdc_common.h>
|
||||
|
||||
#endif // _ASSERT_H
|
2540
05/tcc-0.9.27/c67-gen.c
Normal file
2540
05/tcc-0.9.27/c67-gen.c
Normal file
File diff suppressed because it is too large
Load diff
131
05/tcc-0.9.27/c67-link.c
Normal file
131
05/tcc-0.9.27/c67-link.c
Normal file
|
@ -0,0 +1,131 @@
|
|||
#ifdef TARGET_DEFS_ONLY
|
||||
|
||||
#define EM_TCC_TARGET EM_C60
|
||||
|
||||
/* relocation type for 32 bit data relocation */
|
||||
#define R_DATA_32 R_C60_32
|
||||
#define R_DATA_PTR R_C60_32
|
||||
#define R_JMP_SLOT R_C60_JMP_SLOT
|
||||
#define R_GLOB_DAT R_C60_GLOB_DAT
|
||||
#define R_COPY R_C60_COPY
|
||||
#define R_RELATIVE R_C60_RELATIVE
|
||||
|
||||
#define R_NUM R_C60_NUM
|
||||
|
||||
#define ELF_START_ADDR 0x00000400
|
||||
#define ELF_PAGE_SIZE 0x1000
|
||||
|
||||
#define PCRELATIVE_DLLPLT 0
|
||||
#define RELOCATE_DLLPLT 0
|
||||
|
||||
#else /* !TARGET_DEFS_ONLY */
|
||||
|
||||
#include "tcc.h"
|
||||
|
||||
/* Returns 1 for a code relocation, 0 for a data relocation. For unknown
|
||||
relocations, returns -1. */
|
||||
int code_reloc (int reloc_type)
|
||||
{
|
||||
switch (reloc_type) {
|
||||
case R_C60_32:
|
||||
case R_C60LO16:
|
||||
case R_C60HI16:
|
||||
case R_C60_GOT32:
|
||||
case R_C60_GOTOFF:
|
||||
case R_C60_GOTPC:
|
||||
case R_C60_COPY:
|
||||
return 0;
|
||||
|
||||
case R_C60_PLT32:
|
||||
return 1;
|
||||
}
|
||||
|
||||
tcc_error ("Unknown relocation type: %d", reloc_type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Returns an enumerator to describe whether and when the relocation needs a
|
||||
GOT and/or PLT entry to be created. See tcc.h for a description of the
|
||||
different values. */
|
||||
int gotplt_entry_type (int reloc_type)
|
||||
{
|
||||
switch (reloc_type) {
|
||||
case R_C60_32:
|
||||
case R_C60LO16:
|
||||
case R_C60HI16:
|
||||
case R_C60_COPY:
|
||||
return NO_GOTPLT_ENTRY;
|
||||
|
||||
case R_C60_GOTOFF:
|
||||
case R_C60_GOTPC:
|
||||
return BUILD_GOT_ONLY;
|
||||
|
||||
case R_C60_PLT32:
|
||||
case R_C60_GOT32:
|
||||
return ALWAYS_GOTPLT_ENTRY;
|
||||
}
|
||||
|
||||
tcc_error ("Unknown relocation type: %d", reloc_type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
|
||||
{
|
||||
tcc_error("C67 got not implemented");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* relocate the PLT: compute addresses and offsets in the PLT now that final
|
||||
address for PLT and GOT are known (see fill_program_header) */
|
||||
ST_FUNC void relocate_plt(TCCState *s1)
|
||||
{
|
||||
uint8_t *p, *p_end;
|
||||
|
||||
if (!s1->plt)
|
||||
return;
|
||||
|
||||
p = s1->plt->data;
|
||||
p_end = p + s1->plt->data_offset;
|
||||
|
||||
if (p < p_end) {
|
||||
/* XXX: TODO */
|
||||
while (p < p_end) {
|
||||
/* XXX: TODO */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void relocate_init(Section *sr) {}
|
||||
|
||||
void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
|
||||
{
|
||||
switch(type) {
|
||||
case R_C60_32:
|
||||
*(int *)ptr += val;
|
||||
break;
|
||||
case R_C60LO16:
|
||||
{
|
||||
uint32_t orig;
|
||||
|
||||
/* put the low 16 bits of the absolute address add to what is
|
||||
already there */
|
||||
orig = ((*(int *)(ptr )) >> 7) & 0xffff;
|
||||
orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
|
||||
|
||||
/* patch both at once - assumes always in pairs Low - High */
|
||||
*(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) |
|
||||
(((val+orig) & 0xffff) << 7);
|
||||
*(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) |
|
||||
((((val+orig)>>16) & 0xffff) << 7);
|
||||
}
|
||||
break;
|
||||
case R_C60HI16:
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"FIXME: handle reloc type %x at %x [%p] to %x\n",
|
||||
type, (unsigned) addr, ptr, (unsigned) val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* !TARGET_DEFS_ONLY */
|
446
05/tcc-0.9.27/coff.h
Normal file
446
05/tcc-0.9.27/coff.h
Normal file
|
@ -0,0 +1,446 @@
|
|||
/**************************************************************************/
|
||||
/* COFF.H */
|
||||
/* COFF data structures and related definitions used by the linker */
|
||||
/**************************************************************************/
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* COFF FILE HEADER */
|
||||
/*------------------------------------------------------------------------*/
|
||||
struct filehdr {
|
||||
unsigned short f_magic; /* magic number */
|
||||
unsigned short f_nscns; /* number of sections */
|
||||
long f_timdat; /* time & date stamp */
|
||||
long f_symptr; /* file pointer to symtab */
|
||||
long f_nsyms; /* number of symtab entries */
|
||||
unsigned short f_opthdr; /* sizeof(optional hdr) */
|
||||
unsigned short f_flags; /* flags */
|
||||
unsigned short f_TargetID; /* for C6x = 0x0099 */
|
||||
};
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* File header flags */
|
||||
/*------------------------------------------------------------------------*/
|
||||
#define F_RELFLG 0x01 /* relocation info stripped from file */
|
||||
#define F_EXEC 0x02 /* file is executable (no unresolved refs) */
|
||||
#define F_LNNO 0x04 /* line numbers stripped from file */
|
||||
#define F_LSYMS 0x08 /* local symbols stripped from file */
|
||||
#define F_GSP10 0x10 /* 34010 version */
|
||||
#define F_GSP20 0x20 /* 34020 version */
|
||||
#define F_SWABD 0x40 /* bytes swabbed (in names) */
|
||||
#define F_AR16WR 0x80 /* byte ordering of an AR16WR (PDP-11) */
|
||||
#define F_LITTLE 0x100 /* byte ordering of an AR32WR (vax) */
|
||||
#define F_BIG 0x200 /* byte ordering of an AR32W (3B, maxi) */
|
||||
#define F_PATCH 0x400 /* contains "patch" list in optional header */
|
||||
#define F_NODF 0x400
|
||||
|
||||
#define F_VERSION (F_GSP10 | F_GSP20)
|
||||
#define F_BYTE_ORDER (F_LITTLE | F_BIG)
|
||||
#define FILHDR struct filehdr
|
||||
|
||||
/* #define FILHSZ sizeof(FILHDR) */
|
||||
#define FILHSZ 22 /* above rounds to align on 4 bytes which causes problems */
|
||||
|
||||
#define COFF_C67_MAGIC 0x00c2
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Macros to recognize magic numbers */
|
||||
/*------------------------------------------------------------------------*/
|
||||
#define ISMAGIC(x) (((unsigned short)(x))==(unsigned short)magic)
|
||||
#define ISARCHIVE(x) ((((unsigned short)(x))==(unsigned short)ARTYPE))
|
||||
#define BADMAGIC(x) (((unsigned short)(x) & 0x8080) && !ISMAGIC(x))
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* OPTIONAL FILE HEADER */
|
||||
/*------------------------------------------------------------------------*/
|
||||
typedef struct aouthdr {
|
||||
short magic; /* see magic.h */
|
||||
short vstamp; /* version stamp */
|
||||
long tsize; /* text size in bytes, padded to FW bdry*/
|
||||
long dsize; /* initialized data " " */
|
||||
long bsize; /* uninitialized data " " */
|
||||
long entrypt; /* entry pt. */
|
||||
long text_start; /* base of text used for this file */
|
||||
long data_start; /* base of data used for this file */
|
||||
} AOUTHDR;
|
||||
|
||||
#define AOUTSZ sizeof(AOUTHDR)
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* When a UNIX aout header is to be built in the optional header, */
|
||||
/* the following magic numbers can appear in that header: */
|
||||
/* */
|
||||
/* AOUT1MAGIC : default : readonly sharable text segment */
|
||||
/* AOUT2MAGIC: : writable text segment */
|
||||
/* PAGEMAGIC : : configured for paging */
|
||||
/*----------------------------------------------------------------------*/
|
||||
#define AOUT1MAGIC 0410
|
||||
#define AOUT2MAGIC 0407
|
||||
#define PAGEMAGIC 0413
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* COMMON ARCHIVE FILE STRUCTURES */
|
||||
/* */
|
||||
/* ARCHIVE File Organization: */
|
||||
/* _______________________________________________ */
|
||||
/* |__________ARCHIVE_MAGIC_STRING_______________| */
|
||||
/* |__________ARCHIVE_FILE_MEMBER_1______________| */
|
||||
/* | | */
|
||||
/* | Archive File Header "ar_hdr" | */
|
||||
/* |.............................................| */
|
||||
/* | Member Contents | */
|
||||
/* | 1. External symbol directory | */
|
||||
/* | 2. Text file | */
|
||||
/* |_____________________________________________| */
|
||||
/* |________ARCHIVE_FILE_MEMBER_2________________| */
|
||||
/* | "ar_hdr" | */
|
||||
/* |.............................................| */
|
||||
/* | Member Contents (.o or text file) | */
|
||||
/* |_____________________________________________| */
|
||||
/* | . . . | */
|
||||
/* | . . . | */
|
||||
/* | . . . | */
|
||||
/* |_____________________________________________| */
|
||||
/* |________ARCHIVE_FILE_MEMBER_n________________| */
|
||||
/* | "ar_hdr" | */
|
||||
/* |.............................................| */
|
||||
/* | Member Contents | */
|
||||
/* |_____________________________________________| */
|
||||
/* */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
#define COFF_ARMAG "!<arch>\n"
|
||||
#define SARMAG 8
|
||||
#define ARFMAG "`\n"
|
||||
|
||||
struct ar_hdr /* archive file member header - printable ascii */
|
||||
{
|
||||
char ar_name[16]; /* file member name - `/' terminated */
|
||||
char ar_date[12]; /* file member date - decimal */
|
||||
char ar_uid[6]; /* file member user id - decimal */
|
||||
char ar_gid[6]; /* file member group id - decimal */
|
||||
char ar_mode[8]; /* file member mode - octal */
|
||||
char ar_size[10]; /* file member size - decimal */
|
||||
char ar_fmag[2]; /* ARFMAG - string to end header */
|
||||
};
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* SECTION HEADER */
|
||||
/*------------------------------------------------------------------------*/
|
||||
struct scnhdr {
|
||||
char s_name[8]; /* section name */
|
||||
long s_paddr; /* physical address */
|
||||
long s_vaddr; /* virtual address */
|
||||
long s_size; /* section size */
|
||||
long s_scnptr; /* file ptr to raw data for section */
|
||||
long s_relptr; /* file ptr to relocation */
|
||||
long s_lnnoptr; /* file ptr to line numbers */
|
||||
unsigned int s_nreloc; /* number of relocation entries */
|
||||
unsigned int s_nlnno; /* number of line number entries */
|
||||
unsigned int s_flags; /* flags */
|
||||
unsigned short s_reserved; /* reserved byte */
|
||||
unsigned short s_page; /* memory page id */
|
||||
};
|
||||
|
||||
#define SCNHDR struct scnhdr
|
||||
#define SCNHSZ sizeof(SCNHDR)
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Define constants for names of "special" sections */
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* #define _TEXT ".text" */
|
||||
#define _DATA ".data"
|
||||
#define _BSS ".bss"
|
||||
#define _CINIT ".cinit"
|
||||
#define _TV ".tv"
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* The low 4 bits of s_flags is used as a section "type" */
|
||||
/*------------------------------------------------------------------------*/
|
||||
#define STYP_REG 0x00 /* "regular" : allocated, relocated, loaded */
|
||||
#define STYP_DSECT 0x01 /* "dummy" : not allocated, relocated, not loaded */
|
||||
#define STYP_NOLOAD 0x02 /* "noload" : allocated, relocated, not loaded */
|
||||
#define STYP_GROUP 0x04 /* "grouped" : formed of input sections */
|
||||
#define STYP_PAD 0x08 /* "padding" : not allocated, not relocated, loaded */
|
||||
#define STYP_COPY 0x10 /* "copy" : used for C init tables -
|
||||
not allocated, relocated,
|
||||
loaded; reloc & lineno
|
||||
entries processed normally */
|
||||
#define STYP_TEXT 0x20 /* section contains text only */
|
||||
#define STYP_DATA 0x40 /* section contains data only */
|
||||
#define STYP_BSS 0x80 /* section contains bss only */
|
||||
|
||||
#define STYP_ALIGN 0x100 /* align flag passed by old version assemblers */
|
||||
#define ALIGN_MASK 0x0F00 /* part of s_flags that is used for align vals */
|
||||
#define ALIGNSIZE(x) (1 << ((x & ALIGN_MASK) >> 8))
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* RELOCATION ENTRIES */
|
||||
/*------------------------------------------------------------------------*/
|
||||
struct reloc
|
||||
{
|
||||
long r_vaddr; /* (virtual) address of reference */
|
||||
short r_symndx; /* index into symbol table */
|
||||
unsigned short r_disp; /* additional bits for address calculation */
|
||||
unsigned short r_type; /* relocation type */
|
||||
};
|
||||
|
||||
#define RELOC struct reloc
|
||||
#define RELSZ 10 /* sizeof(RELOC) */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* define all relocation types */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
#define R_ABS 0 /* absolute address - no relocation */
|
||||
#define R_DIR16 01 /* UNUSED */
|
||||
#define R_REL16 02 /* UNUSED */
|
||||
#define R_DIR24 04 /* UNUSED */
|
||||
#define R_REL24 05 /* 24 bits, direct */
|
||||
#define R_DIR32 06 /* UNUSED */
|
||||
#define R_RELBYTE 017 /* 8 bits, direct */
|
||||
#define R_RELWORD 020 /* 16 bits, direct */
|
||||
#define R_RELLONG 021 /* 32 bits, direct */
|
||||
#define R_PCRBYTE 022 /* 8 bits, PC-relative */
|
||||
#define R_PCRWORD 023 /* 16 bits, PC-relative */
|
||||
#define R_PCRLONG 024 /* 32 bits, PC-relative */
|
||||
#define R_OCRLONG 030 /* GSP: 32 bits, one's complement direct */
|
||||
#define R_GSPPCR16 031 /* GSP: 16 bits, PC relative (in words) */
|
||||
#define R_GSPOPR32 032 /* GSP: 32 bits, direct big-endian */
|
||||
#define R_PARTLS16 040 /* Brahma: 16 bit offset of 24 bit address*/
|
||||
#define R_PARTMS8 041 /* Brahma: 8 bit page of 24 bit address */
|
||||
#define R_PARTLS7 050 /* DSP: 7 bit offset of 16 bit address */
|
||||
#define R_PARTMS9 051 /* DSP: 9 bit page of 16 bit address */
|
||||
#define R_REL13 052 /* DSP: 13 bits, direct */
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* LINE NUMBER ENTRIES */
|
||||
/*------------------------------------------------------------------------*/
|
||||
struct lineno
|
||||
{
|
||||
union
|
||||
{
|
||||
long l_symndx ; /* sym. table index of function name
|
||||
iff l_lnno == 0 */
|
||||
long l_paddr ; /* (physical) address of line number */
|
||||
} l_addr ;
|
||||
unsigned short l_lnno ; /* line number */
|
||||
};
|
||||
|
||||
#define LINENO struct lineno
|
||||
#define LINESZ 6 /* sizeof(LINENO) */
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* STORAGE CLASSES */
|
||||
/*------------------------------------------------------------------------*/
|
||||
#define C_EFCN -1 /* physical end of function */
|
||||
#define C_NULL 0
|
||||
#define C_AUTO 1 /* automatic variable */
|
||||
#define C_EXT 2 /* external symbol */
|
||||
#define C_STAT 3 /* static */
|
||||
#define C_REG 4 /* register variable */
|
||||
#define C_EXTDEF 5 /* external definition */
|
||||
#define C_LABEL 6 /* label */
|
||||
#define C_ULABEL 7 /* undefined label */
|
||||
#define C_MOS 8 /* member of structure */
|
||||
#define C_ARG 9 /* function argument */
|
||||
#define C_STRTAG 10 /* structure tag */
|
||||
#define C_MOU 11 /* member of union */
|
||||
#define C_UNTAG 12 /* union tag */
|
||||
#define C_TPDEF 13 /* type definition */
|
||||
#define C_USTATIC 14 /* undefined static */
|
||||
#define C_ENTAG 15 /* enumeration tag */
|
||||
#define C_MOE 16 /* member of enumeration */
|
||||
#define C_REGPARM 17 /* register parameter */
|
||||
#define C_FIELD 18 /* bit field */
|
||||
|
||||
#define C_BLOCK 100 /* ".bb" or ".eb" */
|
||||
#define C_FCN 101 /* ".bf" or ".ef" */
|
||||
#define C_EOS 102 /* end of structure */
|
||||
#define C_FILE 103 /* file name */
|
||||
#define C_LINE 104 /* dummy sclass for line number entry */
|
||||
#define C_ALIAS 105 /* duplicate tag */
|
||||
#define C_HIDDEN 106 /* special storage class for external */
|
||||
/* symbols in dmert public libraries */
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* SYMBOL TABLE ENTRIES */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
#define SYMNMLEN 8 /* Number of characters in a symbol name */
|
||||
#define FILNMLEN 14 /* Number of characters in a file name */
|
||||
#define DIMNUM 4 /* Number of array dimensions in auxiliary entry */
|
||||
|
||||
|
||||
struct syment
|
||||
{
|
||||
union
|
||||
{
|
||||
char _n_name[SYMNMLEN]; /* old COFF version */
|
||||
struct
|
||||
{
|
||||
long _n_zeroes; /* new == 0 */
|
||||
long _n_offset; /* offset into string table */
|
||||
} _n_n;
|
||||
char *_n_nptr[2]; /* allows for overlaying */
|
||||
} _n;
|
||||
long n_value; /* value of symbol */
|
||||
short n_scnum; /* section number */
|
||||
unsigned short n_type; /* type and derived type */
|
||||
char n_sclass; /* storage class */
|
||||
char n_numaux; /* number of aux. entries */
|
||||
};
|
||||
|
||||
#define n_name _n._n_name
|
||||
#define n_nptr _n._n_nptr[1]
|
||||
#define n_zeroes _n._n_n._n_zeroes
|
||||
#define n_offset _n._n_n._n_offset
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Relocatable symbols have a section number of the */
|
||||
/* section in which they are defined. Otherwise, section */
|
||||
/* numbers have the following meanings: */
|
||||
/*------------------------------------------------------------------------*/
|
||||
#define N_UNDEF 0 /* undefined symbol */
|
||||
#define N_ABS -1 /* value of symbol is absolute */
|
||||
#define N_DEBUG -2 /* special debugging symbol */
|
||||
#define N_TV (unsigned short)-3 /* needs transfer vector (preload) */
|
||||
#define P_TV (unsigned short)-4 /* needs transfer vector (postload) */
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* The fundamental type of a symbol packed into the low */
|
||||
/* 4 bits of the word. */
|
||||
/*------------------------------------------------------------------------*/
|
||||
#define _EF ".ef"
|
||||
|
||||
#define T_NULL 0 /* no type info */
|
||||
#define T_ARG 1 /* function argument (only used by compiler) */
|
||||
#define T_CHAR 2 /* character */
|
||||
#define T_SHORT 3 /* short integer */
|
||||
#define T_INT 4 /* integer */
|
||||
#define T_LONG 5 /* long integer */
|
||||
#define T_FLOAT 6 /* floating point */
|
||||
#define T_DOUBLE 7 /* double word */
|
||||
#define T_STRUCT 8 /* structure */
|
||||
#define T_UNION 9 /* union */
|
||||
#define T_ENUM 10 /* enumeration */
|
||||
#define T_MOE 11 /* member of enumeration */
|
||||
#define T_UCHAR 12 /* unsigned character */
|
||||
#define T_USHORT 13 /* unsigned short */
|
||||
#define T_UINT 14 /* unsigned integer */
|
||||
#define T_ULONG 15 /* unsigned long */
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* derived types are: */
|
||||
/*------------------------------------------------------------------------*/
|
||||
#define DT_NON 0 /* no derived type */
|
||||
#define DT_PTR 1 /* pointer */
|
||||
#define DT_FCN 2 /* function */
|
||||
#define DT_ARY 3 /* array */
|
||||
|
||||
#define MKTYPE(basic, d1,d2,d3,d4,d5,d6) \
|
||||
((basic) | ((d1) << 4) | ((d2) << 6) | ((d3) << 8) |\
|
||||
((d4) << 10) | ((d5) << 12) | ((d6) << 14))
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* type packing constants and macros */
|
||||
/*------------------------------------------------------------------------*/
|
||||
#define N_BTMASK_COFF 017
|
||||
#define N_TMASK_COFF 060
|
||||
#define N_TMASK1_COFF 0300
|
||||
#define N_TMASK2_COFF 0360
|
||||
#define N_BTSHFT_COFF 4
|
||||
#define N_TSHIFT_COFF 2
|
||||
|
||||
#define BTYPE_COFF(x) ((x) & N_BTMASK_COFF)
|
||||
#define ISINT(x) (((x) >= T_CHAR && (x) <= T_LONG) || \
|
||||
((x) >= T_UCHAR && (x) <= T_ULONG) || (x) == T_ENUM)
|
||||
#define ISFLT_COFF(x) ((x) == T_DOUBLE || (x) == T_FLOAT)
|
||||
#define ISPTR_COFF(x) (((x) & N_TMASK_COFF) == (DT_PTR << N_BTSHFT_COFF))
|
||||
#define ISFCN_COFF(x) (((x) & N_TMASK_COFF) == (DT_FCN << N_BTSHFT_COFF))
|
||||
#define ISARY_COFF(x) (((x) & N_TMASK_COFF) == (DT_ARY << N_BTSHFT_COFF))
|
||||
#define ISTAG_COFF(x) ((x)==C_STRTAG || (x)==C_UNTAG || (x)==C_ENTAG)
|
||||
|
||||
#define INCREF_COFF(x) ((((x)&~N_BTMASK_COFF)<<N_TSHIFT_COFF)|(DT_PTR<<N_BTSHFT_COFF)|(x&N_BTMASK_COFF))
|
||||
#define DECREF_COFF(x) ((((x)>>N_TSHIFT_COFF)&~N_BTMASK_COFF)|((x)&N_BTMASK_COFF))
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* AUXILIARY SYMBOL ENTRY */
|
||||
/*------------------------------------------------------------------------*/
|
||||
union auxent
|
||||
{
|
||||
struct
|
||||
{
|
||||
long x_tagndx; /* str, un, or enum tag indx */
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned short x_lnno; /* declaration line number */
|
||||
unsigned short x_size; /* str, union, array size */
|
||||
} x_lnsz;
|
||||
long x_fsize; /* size of function */
|
||||
} x_misc;
|
||||
union
|
||||
{
|
||||
struct /* if ISFCN, tag, or .bb */
|
||||
{
|
||||
long x_lnnoptr; /* ptr to fcn line # */
|
||||
long x_endndx; /* entry ndx past block end */
|
||||
} x_fcn;
|
||||
struct /* if ISARY, up to 4 dimen. */
|
||||
{
|
||||
unsigned short x_dimen[DIMNUM];
|
||||
} x_ary;
|
||||
} x_fcnary;
|
||||
unsigned short x_regcount; /* number of registers used by func */
|
||||
} x_sym;
|
||||
struct
|
||||
{
|
||||
char x_fname[FILNMLEN];
|
||||
} x_file;
|
||||
struct
|
||||
{
|
||||
long x_scnlen; /* section length */
|
||||
unsigned short x_nreloc; /* number of relocation entries */
|
||||
unsigned short x_nlinno; /* number of line numbers */
|
||||
} x_scn;
|
||||
};
|
||||
|
||||
#define SYMENT struct syment
|
||||
#define SYMESZ 18 /* sizeof(SYMENT) */
|
||||
|
||||
#define AUXENT union auxent
|
||||
#define AUXESZ 18 /* sizeof(AUXENT) */
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* NAMES OF "SPECIAL" SYMBOLS */
|
||||
/*------------------------------------------------------------------------*/
|
||||
#define _STEXT ".text"
|
||||
#define _ETEXT "etext"
|
||||
#define _SDATA ".data"
|
||||
#define _EDATA "edata"
|
||||
#define _SBSS ".bss"
|
||||
#define _END "end"
|
||||
#define _CINITPTR "cinit"
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* ENTRY POINT SYMBOLS */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
#define _START "_start"
|
||||
#define _MAIN "_main"
|
||||
/* _CSTART "_c_int00" (defined in params.h) */
|
||||
|
||||
|
||||
#define _TVORIG "_tvorig"
|
||||
#define _TORIGIN "_torigin"
|
||||
#define _DORIGIN "_dorigin"
|
||||
|
||||
#define _SORIGIN "_sorigin"
|
527
05/tcc-0.9.27/configure
vendored
Executable file
527
05/tcc-0.9.27/configure
vendored
Executable file
|
@ -0,0 +1,527 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# tcc configure script (c) 2003 Fabrice Bellard
|
||||
|
||||
# set temporary file name
|
||||
# if test ! -z "$TMPDIR" ; then
|
||||
# TMPDIR1="${TMPDIR}"
|
||||
# elif test ! -z "$TEMPDIR" ; then
|
||||
# TMPDIR1="${TEMPDIR}"
|
||||
# else
|
||||
# TMPDIR1="/tmp"
|
||||
# fi
|
||||
#
|
||||
# bashism: TMPN="${TMPDIR1}/tcc-conf-${RANDOM}-$$-${RANDOM}.c"
|
||||
|
||||
TMPN="./conftest-$$"
|
||||
TMPH=$TMPN.h
|
||||
|
||||
# default parameters
|
||||
prefix=""
|
||||
execprefix=""
|
||||
bindir=""
|
||||
libdir=""
|
||||
tccdir=""
|
||||
includedir=""
|
||||
mandir=""
|
||||
infodir=""
|
||||
sysroot=""
|
||||
cross_prefix=""
|
||||
cc="gcc"
|
||||
ar="ar"
|
||||
strip="strip"
|
||||
bigendian="no"
|
||||
mingw32="no"
|
||||
LIBSUF=".a"
|
||||
EXESUF=""
|
||||
DLLSUF=".so"
|
||||
tcc_sysincludepaths=""
|
||||
tcc_libpaths=""
|
||||
tcc_crtprefix=""
|
||||
tcc_elfinterp=""
|
||||
triplet=
|
||||
tcc_lddir=
|
||||
confvars=
|
||||
suggest="yes"
|
||||
cpu=
|
||||
cpuver=
|
||||
gcc_major=0
|
||||
gcc_minor=0
|
||||
|
||||
# OS specific
|
||||
targetos=`uname`
|
||||
case $targetos in
|
||||
Darwin)
|
||||
confvars="$confvars OSX"
|
||||
DLLSUF=".dylib"
|
||||
;;
|
||||
MINGW*|MSYS*|CYGWIN*)
|
||||
mingw32=yes
|
||||
;;
|
||||
DragonFly|OpenBSD|FreeBSD|NetBSD)
|
||||
confvars="$confvars ldl=no"
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
|
||||
# find source path
|
||||
source_path=${0%configure}
|
||||
source_path=${source_path%/}
|
||||
source_path_used="yes"
|
||||
if test -z "$source_path" -o "$source_path" = "." ; then
|
||||
source_path=`pwd`
|
||||
source_path_used="no"
|
||||
fi
|
||||
|
||||
for opt do
|
||||
eval opt=\"$opt\"
|
||||
case "$opt" in
|
||||
--prefix=*) prefix=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--exec-prefix=*) execprefix=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--tccdir=*) tccdir=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--bindir=*) bindir=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--libdir=*) libdir=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--includedir=*) includedir=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--sharedir=*) sharedir=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--mandir=*) mandir=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--infodir=*) infodir=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--docdir=*) docdir=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--sysroot=*) sysroot=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--source-path=*) source_path=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--cross-prefix=*) cross_prefix=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--cc=*) cc=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--ar=*) ar=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--extra-cflags=*) CFLAGS="${opt#--extra-cflags=}"
|
||||
;;
|
||||
--extra-ldflags=*) LDFLAGS="${opt#--extra-ldflags=}"
|
||||
;;
|
||||
--extra-libs=*) extralibs="${opt#--extra-libs=}"
|
||||
;;
|
||||
--sysincludepaths=*) tcc_sysincludepaths=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--libpaths=*) tcc_libpaths=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--crtprefix=*) tcc_crtprefix=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--elfinterp=*) tcc_elfinterp=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--triplet=*) triplet=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--cpu=*) cpu=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--enable-cross) confvars="$confvars cross"
|
||||
;;
|
||||
--disable-static) confvars="$confvars static=no"
|
||||
;;
|
||||
--enable-static) confvars="$confvars static"
|
||||
;;
|
||||
--disable-rpath) confvars="$confvars rpath=no"
|
||||
;;
|
||||
--strip-binaries) confvars="$confvars strip"
|
||||
;;
|
||||
--with-libgcc) confvars="$confvars libgcc"
|
||||
;;
|
||||
--with-selinux) confvars="$confvars selinux"
|
||||
;;
|
||||
--config-mingw32*) mingw32=$(echo "$opt=yes" | cut -d '=' -f 2)
|
||||
;;
|
||||
--config-*) confvars="$confvars ${opt#--config-}"; suggest="no"
|
||||
;;
|
||||
--help|-h) show_help="yes"
|
||||
;;
|
||||
*) echo "configure: WARNING: unrecognized option $opt"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if test -z "$cpu" ; then
|
||||
if test -n "$ARCH" ; then
|
||||
cpu="$ARCH"
|
||||
else
|
||||
cpu=`uname -m`
|
||||
fi
|
||||
fi
|
||||
|
||||
case "$cpu" in
|
||||
x86|i386|i486|i586|i686|i86pc|BePC|i686-AT386)
|
||||
cpu="i386"
|
||||
;;
|
||||
x86_64|amd64|x86-64)
|
||||
cpu="x86_64"
|
||||
;;
|
||||
arm*)
|
||||
case "$cpu" in
|
||||
arm|armv4l)
|
||||
cpuver=4
|
||||
;;
|
||||
armv5tel|armv5tejl)
|
||||
cpuver=5
|
||||
;;
|
||||
armv6j|armv6l)
|
||||
cpuver=6
|
||||
;;
|
||||
armv7a|armv7l)
|
||||
cpuver=7
|
||||
;;
|
||||
esac
|
||||
cpu="arm"
|
||||
;;
|
||||
aarch64)
|
||||
cpu="aarch64"
|
||||
;;
|
||||
alpha)
|
||||
cpu="alpha"
|
||||
;;
|
||||
"Power Macintosh"|ppc|ppc64)
|
||||
cpu="ppc"
|
||||
;;
|
||||
mips)
|
||||
cpu="mips"
|
||||
;;
|
||||
s390)
|
||||
cpu="s390"
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported CPU"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Checking for CFLAGS
|
||||
if test -z "$CFLAGS"; then
|
||||
CFLAGS="-Wall -g -O2"
|
||||
fi
|
||||
|
||||
if test "$mingw32" = "yes" ; then
|
||||
if test "$source_path_used" = "no"; then
|
||||
source_path="."
|
||||
fi
|
||||
if test "$cc" = gcc; then
|
||||
test -z "$LDFLAGS" && LDFLAGS="-static"
|
||||
fi
|
||||
test -z "$prefix" && prefix="C:/Program Files/tcc"
|
||||
test -z "$tccdir" && tccdir="${prefix}"
|
||||
test -z "$bindir" && bindir="${tccdir}"
|
||||
test -z "$docdir" && docdir="${tccdir}/doc"
|
||||
test -z "$libdir" && libdir="${tccdir}/libtcc"
|
||||
confvars="$confvars WIN32"
|
||||
LIBSUF=".lib"
|
||||
EXESUF=".exe"
|
||||
DLLSUF=".dll"
|
||||
else
|
||||
if test -z "$prefix" ; then
|
||||
prefix="/usr/local"
|
||||
fi
|
||||
if test -z "$sharedir" ; then
|
||||
sharedir="${prefix}/share"
|
||||
fi
|
||||
if test x"$execprefix" = x""; then
|
||||
execprefix="${prefix}"
|
||||
fi
|
||||
if test x"$libdir" = x""; then
|
||||
libdir="${execprefix}/lib"
|
||||
fi
|
||||
if test x"$bindir" = x""; then
|
||||
bindir="${execprefix}/bin"
|
||||
fi
|
||||
if test x"$docdir" = x""; then
|
||||
docdir="${sharedir}/doc"
|
||||
fi
|
||||
if test x"$mandir" = x""; then
|
||||
mandir="${sharedir}/man"
|
||||
fi
|
||||
if test x"$infodir" = x""; then
|
||||
infodir="${sharedir}/info"
|
||||
fi
|
||||
if test x"$tccdir" = x""; then
|
||||
tccdir="${libdir}/tcc"
|
||||
fi
|
||||
if test x"$includedir" = x""; then
|
||||
includedir="${prefix}/include"
|
||||
fi
|
||||
fi # mingw32
|
||||
|
||||
if test x"$show_help" = "xyes" ; then
|
||||
cat << EOF
|
||||
Usage: configure [options]
|
||||
Options: [defaults in brackets after descriptions]
|
||||
|
||||
Standard options:
|
||||
--help print this message
|
||||
--prefix=PREFIX install in PREFIX [$prefix]
|
||||
--exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
|
||||
[same as prefix]
|
||||
--bindir=DIR user executables in DIR [EPREFIX/bin]
|
||||
--libdir=DIR object code libraries in DIR [EPREFIX/lib]
|
||||
--tccdir=DIR installation directory [EPREFIX/lib/tcc]
|
||||
--includedir=DIR C header files in DIR [PREFIX/include]
|
||||
--sharedir=DIR documentation root DIR [PREFIX/share]
|
||||
--docdir=DIR documentation in DIR [SHAREDIR/doc/tcc]
|
||||
--mandir=DIR man documentation in DIR [SHAREDIR/man]
|
||||
--infodir=DIR info documentation in DIR [SHAREDIR/info]
|
||||
|
||||
Advanced options (experts only):
|
||||
--source-path=PATH path of source code [$source_path]
|
||||
--cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix]
|
||||
--sysroot=PREFIX prepend PREFIX to library/include paths []
|
||||
--cc=CC use C compiler CC [$cc]
|
||||
--ar=AR create archives using AR [$ar]
|
||||
--extra-cflags= specify compiler flags [$CFLAGS]
|
||||
--extra-ldflags= specify linker options []
|
||||
--cpu=CPU CPU [$cpu]
|
||||
--strip-binaries strip symbol tables from resulting binaries
|
||||
--disable-static make libtcc.so instead of libtcc.a
|
||||
--enable-static make libtcc.a instead of libtcc.dll (win32)
|
||||
--disable-rpath disable use of -rpath with the above
|
||||
--with-libgcc use libgcc_s.so.1 instead of libtcc1.a
|
||||
--enable-cross build cross compilers
|
||||
--with-selinux use mmap for executable memory (with tcc -run)
|
||||
--sysincludepaths=... specify system include paths, colon separated
|
||||
--libpaths=... specify system library paths, colon separated
|
||||
--crtprefix=... specify locations of crt?.o, colon separated
|
||||
--elfinterp=... specify elf interpreter
|
||||
--triplet=... specify system library/include directory triplet
|
||||
--config-uClibc,-musl,-mingw32... enable system specific configurations
|
||||
EOF
|
||||
#echo "NOTE: The object files are build at the place where configure is launched"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cc="${cross_prefix}${cc}"
|
||||
ar="${cross_prefix}${ar}"
|
||||
strip="${cross_prefix}${strip}"
|
||||
|
||||
if test -z "$cross_prefix" ; then
|
||||
CONFTEST=./conftest$EXESUF
|
||||
if ! $cc -o $CONFTEST $source_path/conftest.c 2>/dev/null ; then
|
||||
echo "configure: error: '$cc' failed to compile conftest.c."
|
||||
else
|
||||
gcc_major="$($CONFTEST version)"
|
||||
gcc_minor="$($CONFTEST minor)"
|
||||
fi
|
||||
bigendian="$($CONFTEST bigendian)"
|
||||
if test "$mingw32" = "no" ; then
|
||||
|
||||
if test -z "$triplet"; then
|
||||
tt="$($CONFTEST triplet)"
|
||||
if test -n "$tt" -a -f "/usr/lib/$tt/crti.o" ; then
|
||||
triplet="$tt"
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -z "$triplet"; then
|
||||
if test $cpu = "x86_64" -o $cpu = "aarch64" ; then
|
||||
if test -f "/usr/lib64/crti.o" ; then
|
||||
tcc_lddir="lib64"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$cpu" = "arm" ; then
|
||||
if test "${triplet%eabihf}" != "$triplet" ; then
|
||||
confvars="$confvars arm_eabihf"
|
||||
elif test "${triplet%eabi}" != "$triplet" ; then
|
||||
confvars="$confvars arm_eabi"
|
||||
fi
|
||||
if grep -s -q "^Features.* \(vfp\|iwmmxt\) " /proc/cpuinfo ; then
|
||||
confvars="$confvars arm_vfp"
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$suggest" = "yes"; then
|
||||
if test -f "/lib/ld-uClibc.so.0" ; then
|
||||
echo "Perhaps you want ./configure --config-uClibc"
|
||||
fi
|
||||
if test -f "/lib/ld-musl-$cpu.so.1"; then
|
||||
echo "Perhaps you want ./configure --config-musl"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
else
|
||||
# if cross compiling, cannot launch a program, so make a static guess
|
||||
case $cpu in
|
||||
ppc|mips|s390) bigendian=yes;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if test "$bigendian" = "yes" ; then
|
||||
confvars="$confvars BIGENDIAN"
|
||||
fi
|
||||
|
||||
# a final configuration tuning
|
||||
if ! echo "$cc" | grep -q "tcc"; then
|
||||
OPT1="-Wdeclaration-after-statement -fno-strict-aliasing"
|
||||
# we want -Wno- but gcc does not always reject unknown -Wno- options
|
||||
OPT2="-Wpointer-sign -Wsign-compare -Wunused-result"
|
||||
if echo "$cc" | grep -q "clang"; then
|
||||
OPT1="$OPT1 -fheinous-gnu-extensions"
|
||||
OPT2="$OPT2 -Wstring-plus-int"
|
||||
fi
|
||||
$cc $OPT1 $OPT2 -o a.out -c -xc - < /dev/null > cc_msg.txt 2>&1
|
||||
for o in $OPT1; do # enable these options
|
||||
if ! grep -q -- $o cc_msg.txt; then CFLAGS="$CFLAGS $o"; fi
|
||||
done
|
||||
for o in $OPT2; do # disable these options
|
||||
if ! grep -q -- $o cc_msg.txt; then CFLAGS="$CFLAGS -Wno-${o#-W*}"; fi
|
||||
done
|
||||
# cat cc_msg.txt
|
||||
# echo $CFLAGS
|
||||
rm -f cc_msg.txt a.out
|
||||
fi
|
||||
|
||||
fcho() { if test -n "$2"; then echo "$1$2"; fi }
|
||||
|
||||
fcho "Binary directory " "$bindir"
|
||||
fcho "TinyCC directory " "$tccdir"
|
||||
fcho "Library directory " "$libdir"
|
||||
fcho "Include directory " "$includedir"
|
||||
fcho "Manual directory " "$mandir"
|
||||
fcho "Info directory " "$infodir"
|
||||
fcho "Doc directory " "$docdir"
|
||||
fcho "Target root prefix " "$sysroot"
|
||||
echo "Source path $source_path"
|
||||
echo "C compiler $cc ($gcc_major.$gcc_minor)"
|
||||
echo "Target OS $targetos"
|
||||
echo "CPU $cpu"
|
||||
fcho "Triplet " "$triplet"
|
||||
fcho "Config " "${confvars# }"
|
||||
echo "Creating config.mak and config.h"
|
||||
|
||||
cat >config.mak <<EOF
|
||||
# Automatically generated by configure - do not modify
|
||||
prefix=$prefix
|
||||
bindir=\$(DESTDIR)$bindir
|
||||
tccdir=\$(DESTDIR)$tccdir
|
||||
libdir=\$(DESTDIR)$libdir
|
||||
includedir=\$(DESTDIR)$includedir
|
||||
mandir=\$(DESTDIR)$mandir
|
||||
infodir=\$(DESTDIR)$infodir
|
||||
docdir=\$(DESTDIR)$docdir
|
||||
CC=$cc
|
||||
GCC_MAJOR=$gcc_major
|
||||
GCC_MINOR=$gcc_minor
|
||||
AR=$ar
|
||||
STRIP=$strip -s -R .comment -R .note
|
||||
CFLAGS=$CFLAGS
|
||||
LDFLAGS=$LDFLAGS
|
||||
LIBSUF=$LIBSUF
|
||||
EXESUF=$EXESUF
|
||||
DLLSUF=$DLLSUF
|
||||
EOF
|
||||
|
||||
print_inc() {
|
||||
if test -n "$2"; then
|
||||
echo "#ifndef $1" >> $TMPH
|
||||
echo "# define $1 \"$2\"" >> $TMPH
|
||||
echo "#endif" >> $TMPH
|
||||
fi
|
||||
}
|
||||
|
||||
print_mak() {
|
||||
if test -n "$2"; then
|
||||
echo "NATIVE_DEFINES+=-D$1=\"\\\"$2\\\"\"" >> config.mak
|
||||
fi
|
||||
}
|
||||
|
||||
print_mak_int() {
|
||||
if test -n "$2"; then
|
||||
echo "NATIVE_DEFINES+=-D$1=$2" >> config.mak
|
||||
fi
|
||||
}
|
||||
|
||||
echo "/* Automatically generated by configure - do not modify */" > $TMPH
|
||||
|
||||
print_inc CONFIG_SYSROOT "$sysroot"
|
||||
print_inc CONFIG_TCCDIR "$tccdir"
|
||||
print_mak CONFIG_TCC_SYSINCLUDEPATHS "$tcc_sysincludepaths"
|
||||
print_mak CONFIG_TCC_LIBPATHS "$tcc_libpaths"
|
||||
print_mak CONFIG_TCC_CRTPREFIX "$tcc_crtprefix"
|
||||
print_mak CONFIG_TCC_ELFINTERP "$tcc_elfinterp"
|
||||
print_mak CONFIG_LDDIR "$tcc_lddir"
|
||||
print_mak CONFIG_TRIPLET "$triplet"
|
||||
print_mak_int TCC_CPU_VERSION "$cpuver"
|
||||
|
||||
if test "$cpu" = "aarch64" ; then
|
||||
echo "ARCH=arm64" >> config.mak
|
||||
else
|
||||
echo "ARCH=$cpu" >> config.mak
|
||||
fi
|
||||
echo "TARGETOS=$targetos" >> config.mak
|
||||
|
||||
for v in $confvars ; do
|
||||
if test "${v%=*}" = "$v"; then
|
||||
echo "CONFIG_$v=yes" >> config.mak
|
||||
else
|
||||
echo "CONFIG_$v" >> config.mak
|
||||
fi
|
||||
done
|
||||
|
||||
version=`head $source_path/VERSION`
|
||||
echo "VERSION = $version" >> config.mak
|
||||
echo "#define TCC_VERSION \"$version\"" >> $TMPH
|
||||
echo "@set VERSION $version" > config.texi
|
||||
|
||||
if test "$source_path_used" = "yes" ; then
|
||||
case $source_path in
|
||||
/*) echo "TOPSRC=$source_path";;
|
||||
*) echo "TOPSRC=\$(TOP)/$source_path";;
|
||||
esac >>config.mak
|
||||
else
|
||||
echo 'TOPSRC=$(TOP)' >>config.mak
|
||||
fi
|
||||
|
||||
diff $TMPH config.h >/dev/null 2>&1
|
||||
if test $? -ne 0 ; then
|
||||
mv -f $TMPH config.h
|
||||
else
|
||||
echo "config.h is unchanged"
|
||||
fi
|
||||
|
||||
rm -f $TMPN* $CONFTEST
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# build tree in object directory if source path is different from current one
|
||||
|
||||
fn_makelink()
|
||||
{
|
||||
tgt=$1/$2
|
||||
case $2 in
|
||||
*/*) dn=${2%/*}
|
||||
test -d $dn || mkdir -p $dn
|
||||
case $1 in
|
||||
/*) ;;
|
||||
*) while test $dn ; do
|
||||
tgt=../$tgt; dn=${dn#${dn%%/*}}; dn=${dn#/}
|
||||
done
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
|
||||
ln -sfn $tgt $2 || ( echo "ln failed. Using cp instead."; cp -f $1/$2 $2 )
|
||||
}
|
||||
|
||||
if test "$source_path_used" = "yes" ; then
|
||||
FILES="Makefile lib/Makefile tests/Makefile tests/tests2/Makefile tests/pp/Makefile"
|
||||
for f in $FILES ; do
|
||||
fn_makelink $source_path $f
|
||||
done
|
||||
fi
|
||||
|
||||
# ---------------------------------------------------------------------------
|
92
05/tcc-0.9.27/ctype.h
Normal file
92
05/tcc-0.9.27/ctype.h
Normal file
|
@ -0,0 +1,92 @@
|
|||
#ifndef _CTYPE_H
|
||||
#define _CTYPE_H
|
||||
|
||||
#include <stdc_common.h>
|
||||
|
||||
int islower(int c) {
|
||||
return c >= 'a' && c <= 'z';
|
||||
}
|
||||
|
||||
int isupper(int c) {
|
||||
return c >= 'A' && c <= 'Z';
|
||||
}
|
||||
|
||||
int isalpha(int c) {
|
||||
return isupper(c) || islower(c);
|
||||
}
|
||||
|
||||
int isalnum(int c) {
|
||||
return isalpha(c) || isdigit(c);
|
||||
}
|
||||
|
||||
int isprint(int c) {
|
||||
if (isalnum(c)) return 1;
|
||||
switch (c) {
|
||||
case '!': return 1;
|
||||
case '@': return 1;
|
||||
case '#': return 1;
|
||||
case '$': return 1;
|
||||
case '%': return 1;
|
||||
case '^': return 1;
|
||||
case '&': return 1;
|
||||
case '*': return 1;
|
||||
case '(': return 1;
|
||||
case ')': return 1;
|
||||
case '-': return 1;
|
||||
case '=': return 1;
|
||||
case '_': return 1;
|
||||
case '+': return 1;
|
||||
case '`': return 1;
|
||||
case '~': return 1;
|
||||
case '[': return 1;
|
||||
case '{': return 1;
|
||||
case ']': return 1;
|
||||
case '}': return 1;
|
||||
case '\\': return 1;
|
||||
case '|': return 1;
|
||||
case ';': return 1;
|
||||
case ':': return 1;
|
||||
case '\'': return 1;
|
||||
case '"': return 1;
|
||||
case ',': return 1;
|
||||
case '<': return 1;
|
||||
case '.': return 1;
|
||||
case '>': return 1;
|
||||
case '/': return 1;
|
||||
case '?': return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iscntrl(int c) {
|
||||
return !isprint(c);
|
||||
}
|
||||
|
||||
int isgraph(int c) {
|
||||
return isprint(c) && c != ' ';
|
||||
}
|
||||
|
||||
int ispunct(int c) {
|
||||
return isprint(c) && c != ' ' && !isalnum(c);
|
||||
}
|
||||
|
||||
int isxdigit(int c) {
|
||||
if (isdigit(c)) return 1;
|
||||
if (c >= 'a' && c <= 'f') return 1;
|
||||
if (c >= 'A' && c <= 'F') return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tolower(int c) {
|
||||
if (c >= 'A' && c <= 'Z')
|
||||
return c - 'A' + 'a';
|
||||
return c;
|
||||
}
|
||||
|
||||
int toupper(int c) {
|
||||
if (c >= 'a' && c <= 'z')
|
||||
return c - 'a' + 'A';
|
||||
return c;
|
||||
}
|
||||
|
||||
#endif // _CTYPE_H
|
3240
05/tcc-0.9.27/elf.h
Normal file
3240
05/tcc-0.9.27/elf.h
Normal file
File diff suppressed because it is too large
Load diff
6
05/tcc-0.9.27/errno.h
Normal file
6
05/tcc-0.9.27/errno.h
Normal file
|
@ -0,0 +1,6 @@
|
|||
#ifndef _ERRNO_H
|
||||
#define _ERRNO_H
|
||||
|
||||
#include <stdc_common.h> // we define all the relevant things here
|
||||
|
||||
#endif // _ERRNO_H
|
8
05/tcc-0.9.27/examples/ex1.c
Executable file
8
05/tcc-0.9.27/examples/ex1.c
Executable file
|
@ -0,0 +1,8 @@
|
|||
#!/usr/local/bin/tcc -run
|
||||
#include <tcclib.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
printf("Hello World\n");
|
||||
return 0;
|
||||
}
|
98
05/tcc-0.9.27/examples/ex2.c
Normal file
98
05/tcc-0.9.27/examples/ex2.c
Normal file
|
@ -0,0 +1,98 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define N 20
|
||||
|
||||
int nb_num;
|
||||
int tab[N];
|
||||
int stack_ptr;
|
||||
int stack_op[N];
|
||||
int stack_res[60];
|
||||
int result;
|
||||
|
||||
int find(int n, int i1, int a, int b, int op)
|
||||
{
|
||||
int i, j;
|
||||
int c;
|
||||
|
||||
if (stack_ptr >= 0) {
|
||||
stack_res[3*stack_ptr] = a;
|
||||
stack_op[stack_ptr] = op;
|
||||
stack_res[3*stack_ptr+1] = b;
|
||||
stack_res[3*stack_ptr+2] = n;
|
||||
if (n == result)
|
||||
return 1;
|
||||
tab[i1] = n;
|
||||
}
|
||||
|
||||
for(i=0;i<nb_num;i++) {
|
||||
for(j=i+1;j<nb_num;j++) {
|
||||
a = tab[i];
|
||||
b = tab[j];
|
||||
if (a != 0 && b != 0) {
|
||||
|
||||
tab[j] = 0;
|
||||
stack_ptr++;
|
||||
|
||||
if (find(a + b, i, a, b, '+'))
|
||||
return 1;
|
||||
if (find(a - b, i, a, b, '-'))
|
||||
return 1;
|
||||
if (find(b - a, i, b, a, '-'))
|
||||
return 1;
|
||||
if (find(a * b, i, a, b, '*'))
|
||||
return 1;
|
||||
if (b != 0) {
|
||||
c = a / b;
|
||||
if (find(c, i, a, b, '/'))
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (a != 0) {
|
||||
c = b / a;
|
||||
if (find(c, i, b, a, '/'))
|
||||
return 1;
|
||||
}
|
||||
|
||||
stack_ptr--;
|
||||
tab[i] = a;
|
||||
tab[j] = b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i, res, p;
|
||||
|
||||
if (argc < 3) {
|
||||
printf("usage: %s: result numbers...\n"
|
||||
"Try to find result from numbers with the 4 basic operations.\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
p = 1;
|
||||
result = atoi(argv[p]);
|
||||
printf("result=%d\n", result);
|
||||
nb_num = 0;
|
||||
for(i=p+1;i<argc;i++) {
|
||||
tab[nb_num++] = atoi(argv[i]);
|
||||
}
|
||||
|
||||
stack_ptr = -1;
|
||||
res = find(0, 0, 0, 0, ' ');
|
||||
if (res) {
|
||||
for(i=0;i<=stack_ptr;i++) {
|
||||
printf("%d %c %d = %d\n",
|
||||
stack_res[3*i], stack_op[i],
|
||||
stack_res[3*i+1], stack_res[3*i+2]);
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
printf("Impossible\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
23
05/tcc-0.9.27/examples/ex3.c
Normal file
23
05/tcc-0.9.27/examples/ex3.c
Normal file
|
@ -0,0 +1,23 @@
|
|||
#include <tcclib.h>
|
||||
|
||||
int fib(n)
|
||||
{
|
||||
if (n <= 2)
|
||||
return 1;
|
||||
else
|
||||
return fib(n-1) + fib(n-2);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int n;
|
||||
if (argc < 2) {
|
||||
printf("usage: fib n\n"
|
||||
"Compute nth Fibonacci number\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
n = atoi(argv[1]);
|
||||
printf("fib(%d) = %d\n", n, fib(n, 2));
|
||||
return 0;
|
||||
}
|
26
05/tcc-0.9.27/examples/ex4.c
Executable file
26
05/tcc-0.9.27/examples/ex4.c
Executable file
|
@ -0,0 +1,26 @@
|
|||
#!/usr/local/bin/tcc -run -L/usr/X11R6/lib -lX11
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
/* Yes, TCC can use X11 too ! */
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
Display *display;
|
||||
Screen *screen;
|
||||
|
||||
display = XOpenDisplay("");
|
||||
if (!display) {
|
||||
fprintf(stderr, "Could not open X11 display\n");
|
||||
exit(1);
|
||||
}
|
||||
printf("X11 display opened.\n");
|
||||
screen = XScreenOfDisplay(display, 0);
|
||||
printf("width = %d\nheight = %d\ndepth = %d\n",
|
||||
screen->width,
|
||||
screen->height,
|
||||
screen->root_depth);
|
||||
XCloseDisplay(display);
|
||||
return 0;
|
||||
}
|
8
05/tcc-0.9.27/examples/ex5.c
Normal file
8
05/tcc-0.9.27/examples/ex5.c
Normal file
|
@ -0,0 +1,8 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
printf("Hello World\n");
|
||||
return 0;
|
||||
}
|
34
05/tcc-0.9.27/float.h
Normal file
34
05/tcc-0.9.27/float.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
#ifndef _FLOAT_H
|
||||
#define _FLOAT_H
|
||||
|
||||
#define DBL_DIG 15
|
||||
#define DBL_EPSILON 2.2204460492503131e-16
|
||||
#define DBL_MANT_DIG 53
|
||||
#define DBL_MAX 1.7976931348623157e+308
|
||||
#define DBL_MAX_10_EXP 308
|
||||
#define DBL_MAX_EXP 1024
|
||||
#define DBL_MIN 2.2250738585072027e-308
|
||||
#define DBL_MIN_10_EXP (-307)
|
||||
#define DBL_MIN_EXP (-1021)
|
||||
#define FLT_DIG 6
|
||||
#define FLT_EPSILON 1.19209290e-07
|
||||
#define FLT_MANT_DIG 24
|
||||
#define FLT_MAX 3.40282347e+38
|
||||
#define FLT_MAX_10_EXP +38
|
||||
#define FLT_MAX_EXP 128
|
||||
#define FLT_MIN 1.17549435e-38
|
||||
#define FLT_MIN_10_EXP (-37)
|
||||
#define FLT_MIN_EXP (-125)
|
||||
#define FLT_RADIX 2
|
||||
#define FLT_ROUNDS 1
|
||||
#define LDBL_DIG DBL_DIG
|
||||
#define LDBL_EPSILON DBL_EPSILON
|
||||
#define LDBL_MANT_DIG DBL_MANT_DIG
|
||||
#define LDBL_MAX DBL_MAX
|
||||
#define LDBL_MAX_10_EXP DBL_MAX_10_EXP
|
||||
#define LDBL_MAX_EXP DBL_MAX_EXP
|
||||
#define LDBL_MIN DBL_MIN
|
||||
#define LDBL_MIN_10_EXP DBL_MIN_10_EXP
|
||||
#define LDBL_MIN_EXP DBL_MIN_EXP
|
||||
|
||||
#endif // _FLOAT_H
|
1725
05/tcc-0.9.27/i386-asm.c
Normal file
1725
05/tcc-0.9.27/i386-asm.c
Normal file
File diff suppressed because it is too large
Load diff
480
05/tcc-0.9.27/i386-asm.h
Normal file
480
05/tcc-0.9.27/i386-asm.h
Normal file
|
@ -0,0 +1,480 @@
|
|||
DEF_ASM_OP0(clc, 0xf8) /* must be first OP0 */
|
||||
DEF_ASM_OP0(cld, 0xfc)
|
||||
DEF_ASM_OP0(cli, 0xfa)
|
||||
DEF_ASM_OP0(clts, 0x0f06)
|
||||
DEF_ASM_OP0(cmc, 0xf5)
|
||||
DEF_ASM_OP0(lahf, 0x9f)
|
||||
DEF_ASM_OP0(sahf, 0x9e)
|
||||
DEF_ASM_OP0(pusha, 0x60)
|
||||
DEF_ASM_OP0(popa, 0x61)
|
||||
DEF_ASM_OP0(pushfl, 0x9c)
|
||||
DEF_ASM_OP0(popfl, 0x9d)
|
||||
DEF_ASM_OP0(pushf, 0x9c)
|
||||
DEF_ASM_OP0(popf, 0x9d)
|
||||
DEF_ASM_OP0(stc, 0xf9)
|
||||
DEF_ASM_OP0(std, 0xfd)
|
||||
DEF_ASM_OP0(sti, 0xfb)
|
||||
DEF_ASM_OP0(aaa, 0x37)
|
||||
DEF_ASM_OP0(aas, 0x3f)
|
||||
DEF_ASM_OP0(daa, 0x27)
|
||||
DEF_ASM_OP0(das, 0x2f)
|
||||
DEF_ASM_OP0(aad, 0xd50a)
|
||||
DEF_ASM_OP0(aam, 0xd40a)
|
||||
DEF_ASM_OP0(cbw, 0x6698)
|
||||
DEF_ASM_OP0(cwd, 0x6699)
|
||||
DEF_ASM_OP0(cwde, 0x98)
|
||||
DEF_ASM_OP0(cdq, 0x99)
|
||||
DEF_ASM_OP0(cbtw, 0x6698)
|
||||
DEF_ASM_OP0(cwtl, 0x98)
|
||||
DEF_ASM_OP0(cwtd, 0x6699)
|
||||
DEF_ASM_OP0(cltd, 0x99)
|
||||
DEF_ASM_OP0(int3, 0xcc)
|
||||
DEF_ASM_OP0(into, 0xce)
|
||||
DEF_ASM_OP0(iret, 0xcf)
|
||||
DEF_ASM_OP0(rsm, 0x0faa)
|
||||
DEF_ASM_OP0(hlt, 0xf4)
|
||||
DEF_ASM_OP0(nop, 0x90)
|
||||
DEF_ASM_OP0(pause, 0xf390)
|
||||
DEF_ASM_OP0(xlat, 0xd7)
|
||||
|
||||
/* strings */
|
||||
ALT(DEF_ASM_OP0L(cmpsb, 0xa6, 0, OPC_BWLX))
|
||||
ALT(DEF_ASM_OP0L(scmpb, 0xa6, 0, OPC_BWLX))
|
||||
|
||||
ALT(DEF_ASM_OP0L(insb, 0x6c, 0, OPC_BWL))
|
||||
ALT(DEF_ASM_OP0L(outsb, 0x6e, 0, OPC_BWL))
|
||||
|
||||
ALT(DEF_ASM_OP0L(lodsb, 0xac, 0, OPC_BWLX))
|
||||
ALT(DEF_ASM_OP0L(slodb, 0xac, 0, OPC_BWLX))
|
||||
|
||||
ALT(DEF_ASM_OP0L(movsb, 0xa4, 0, OPC_BWLX))
|
||||
ALT(DEF_ASM_OP0L(smovb, 0xa4, 0, OPC_BWLX))
|
||||
|
||||
ALT(DEF_ASM_OP0L(scasb, 0xae, 0, OPC_BWLX))
|
||||
ALT(DEF_ASM_OP0L(sscab, 0xae, 0, OPC_BWLX))
|
||||
|
||||
ALT(DEF_ASM_OP0L(stosb, 0xaa, 0, OPC_BWLX))
|
||||
ALT(DEF_ASM_OP0L(sstob, 0xaa, 0, OPC_BWLX))
|
||||
|
||||
/* bits */
|
||||
|
||||
ALT(DEF_ASM_OP2(bsfw, 0x0fbc, 0, OPC_MODRM | OPC_WLX, OPT_REGW | OPT_EA, OPT_REGW))
|
||||
ALT(DEF_ASM_OP2(bsrw, 0x0fbd, 0, OPC_MODRM | OPC_WLX, OPT_REGW | OPT_EA, OPT_REGW))
|
||||
|
||||
ALT(DEF_ASM_OP2(btw, 0x0fa3, 0, OPC_MODRM | OPC_WLX, OPT_REGW, OPT_REGW | OPT_EA))
|
||||
ALT(DEF_ASM_OP2(btw, 0x0fba, 4, OPC_MODRM | OPC_WLX, OPT_IM8, OPT_REGW | OPT_EA))
|
||||
|
||||
ALT(DEF_ASM_OP2(btsw, 0x0fab, 0, OPC_MODRM | OPC_WLX, OPT_REGW, OPT_REGW | OPT_EA))
|
||||
ALT(DEF_ASM_OP2(btsw, 0x0fba, 5, OPC_MODRM | OPC_WLX, OPT_IM8, OPT_REGW | OPT_EA))
|
||||
|
||||
ALT(DEF_ASM_OP2(btrw, 0x0fb3, 0, OPC_MODRM | OPC_WLX, OPT_REGW, OPT_REGW | OPT_EA))
|
||||
ALT(DEF_ASM_OP2(btrw, 0x0fba, 6, OPC_MODRM | OPC_WLX, OPT_IM8, OPT_REGW | OPT_EA))
|
||||
|
||||
ALT(DEF_ASM_OP2(btcw, 0x0fbb, 0, OPC_MODRM | OPC_WLX, OPT_REGW, OPT_REGW | OPT_EA))
|
||||
ALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WLX, OPT_IM8, OPT_REGW | OPT_EA))
|
||||
|
||||
/* prefixes */
|
||||
DEF_ASM_OP0(wait, 0x9b)
|
||||
DEF_ASM_OP0(fwait, 0x9b)
|
||||
DEF_ASM_OP0(aword, 0x67)
|
||||
DEF_ASM_OP0(addr16, 0x67)
|
||||
ALT(DEF_ASM_OP0(word, 0x66))
|
||||
DEF_ASM_OP0(data16, 0x66)
|
||||
DEF_ASM_OP0(lock, 0xf0)
|
||||
DEF_ASM_OP0(rep, 0xf3)
|
||||
DEF_ASM_OP0(repe, 0xf3)
|
||||
DEF_ASM_OP0(repz, 0xf3)
|
||||
DEF_ASM_OP0(repne, 0xf2)
|
||||
DEF_ASM_OP0(repnz, 0xf2)
|
||||
|
||||
DEF_ASM_OP0(invd, 0x0f08)
|
||||
DEF_ASM_OP0(wbinvd, 0x0f09)
|
||||
DEF_ASM_OP0(cpuid, 0x0fa2)
|
||||
DEF_ASM_OP0(wrmsr, 0x0f30)
|
||||
DEF_ASM_OP0(rdtsc, 0x0f31)
|
||||
DEF_ASM_OP0(rdmsr, 0x0f32)
|
||||
DEF_ASM_OP0(rdpmc, 0x0f33)
|
||||
DEF_ASM_OP0(ud2, 0x0f0b)
|
||||
|
||||
/* NOTE: we took the same order as gas opcode definition order */
|
||||
ALT(DEF_ASM_OP2(movb, 0xa0, 0, OPC_BWLX, OPT_ADDR, OPT_EAX))
|
||||
ALT(DEF_ASM_OP2(movb, 0xa2, 0, OPC_BWLX, OPT_EAX, OPT_ADDR))
|
||||
ALT(DEF_ASM_OP2(movb, 0x88, 0, OPC_MODRM | OPC_BWLX, OPT_REG, OPT_EA | OPT_REG))
|
||||
ALT(DEF_ASM_OP2(movb, 0x8a, 0, OPC_MODRM | OPC_BWLX, OPT_EA | OPT_REG, OPT_REG))
|
||||
ALT(DEF_ASM_OP2(movb, 0xb0, 0, OPC_REG | OPC_BWLX, OPT_IM, OPT_REG))
|
||||
ALT(DEF_ASM_OP2(movb, 0xc6, 0, OPC_MODRM | OPC_BWLX, OPT_IM, OPT_REG | OPT_EA))
|
||||
|
||||
ALT(DEF_ASM_OP2(movw, 0x8c, 0, OPC_MODRM | OPC_WLX, OPT_SEG, OPT_EA | OPT_REG))
|
||||
ALT(DEF_ASM_OP2(movw, 0x8e, 0, OPC_MODRM | OPC_WLX, OPT_EA | OPT_REG, OPT_SEG))
|
||||
|
||||
ALT(DEF_ASM_OP2(movw, 0x0f20, 0, OPC_MODRM | OPC_WLX, OPT_CR, OPT_REG32))
|
||||
ALT(DEF_ASM_OP2(movw, 0x0f21, 0, OPC_MODRM | OPC_WLX, OPT_DB, OPT_REG32))
|
||||
ALT(DEF_ASM_OP2(movw, 0x0f24, 0, OPC_MODRM | OPC_WLX, OPT_TR, OPT_REG32))
|
||||
ALT(DEF_ASM_OP2(movw, 0x0f22, 0, OPC_MODRM | OPC_WLX, OPT_REG32, OPT_CR))
|
||||
ALT(DEF_ASM_OP2(movw, 0x0f23, 0, OPC_MODRM | OPC_WLX, OPT_REG32, OPT_DB))
|
||||
ALT(DEF_ASM_OP2(movw, 0x0f26, 0, OPC_MODRM | OPC_WLX, OPT_REG32, OPT_TR))
|
||||
|
||||
ALT(DEF_ASM_OP2(movsbl, 0x0fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REG32))
|
||||
ALT(DEF_ASM_OP2(movsbw, 0x660fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REG16))
|
||||
ALT(DEF_ASM_OP2(movswl, 0x0fbf, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
|
||||
ALT(DEF_ASM_OP2(movzbw, 0x0fb6, 0, OPC_MODRM | OPC_WLX, OPT_REG8 | OPT_EA, OPT_REGW))
|
||||
ALT(DEF_ASM_OP2(movzwl, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
|
||||
|
||||
ALT(DEF_ASM_OP1(pushw, 0x50, 0, OPC_REG | OPC_WLX, OPT_REGW))
|
||||
ALT(DEF_ASM_OP1(pushw, 0xff, 6, OPC_MODRM | OPC_WLX, OPT_REGW | OPT_EA))
|
||||
ALT(DEF_ASM_OP1(pushw, 0x6a, 0, OPC_WLX, OPT_IM8S))
|
||||
ALT(DEF_ASM_OP1(pushw, 0x68, 0, OPC_WLX, OPT_IM32))
|
||||
ALT(DEF_ASM_OP1(pushw, 0x06, 0, OPC_WLX, OPT_SEG))
|
||||
|
||||
ALT(DEF_ASM_OP1(popw, 0x58, 0, OPC_REG | OPC_WLX, OPT_REGW))
|
||||
ALT(DEF_ASM_OP1(popw, 0x8f, 0, OPC_MODRM | OPC_WLX, OPT_REGW | OPT_EA))
|
||||
ALT(DEF_ASM_OP1(popw, 0x07, 0, OPC_WLX, OPT_SEG))
|
||||
|
||||
ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WLX, OPT_REGW, OPT_EAX))
|
||||
ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WLX, OPT_EAX, OPT_REGW))
|
||||
ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWLX, OPT_REG, OPT_EA | OPT_REG))
|
||||
ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWLX, OPT_EA | OPT_REG, OPT_REG))
|
||||
|
||||
ALT(DEF_ASM_OP2(inb, 0xe4, 0, OPC_BWL, OPT_IM8, OPT_EAX))
|
||||
ALT(DEF_ASM_OP1(inb, 0xe4, 0, OPC_BWL, OPT_IM8))
|
||||
ALT(DEF_ASM_OP2(inb, 0xec, 0, OPC_BWL, OPT_DX, OPT_EAX))
|
||||
ALT(DEF_ASM_OP1(inb, 0xec, 0, OPC_BWL, OPT_DX))
|
||||
|
||||
ALT(DEF_ASM_OP2(outb, 0xe6, 0, OPC_BWL, OPT_EAX, OPT_IM8))
|
||||
ALT(DEF_ASM_OP1(outb, 0xe6, 0, OPC_BWL, OPT_IM8))
|
||||
ALT(DEF_ASM_OP2(outb, 0xee, 0, OPC_BWL, OPT_EAX, OPT_DX))
|
||||
ALT(DEF_ASM_OP1(outb, 0xee, 0, OPC_BWL, OPT_DX))
|
||||
|
||||
ALT(DEF_ASM_OP2(leaw, 0x8d, 0, OPC_MODRM | OPC_WLX, OPT_EA, OPT_REG))
|
||||
|
||||
ALT(DEF_ASM_OP2(les, 0xc4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
|
||||
ALT(DEF_ASM_OP2(lds, 0xc5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
|
||||
ALT(DEF_ASM_OP2(lss, 0x0fb2, 0, OPC_MODRM, OPT_EA, OPT_REG32))
|
||||
ALT(DEF_ASM_OP2(lfs, 0x0fb4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
|
||||
ALT(DEF_ASM_OP2(lgs, 0x0fb5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
|
||||
|
||||
/* arith */
|
||||
ALT(DEF_ASM_OP2(addb, 0x00, 0, OPC_ARITH | OPC_MODRM | OPC_BWLX, OPT_REG, OPT_EA | OPT_REG)) /* XXX: use D bit ? */
|
||||
ALT(DEF_ASM_OP2(addb, 0x02, 0, OPC_ARITH | OPC_MODRM | OPC_BWLX, OPT_EA | OPT_REG, OPT_REG))
|
||||
ALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWLX, OPT_IM, OPT_EAX))
|
||||
ALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WLX, OPT_IM8S, OPT_EA | OPT_REGW))
|
||||
ALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWLX, OPT_IM, OPT_EA | OPT_REG))
|
||||
|
||||
ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWLX, OPT_REG, OPT_EA | OPT_REG))
|
||||
ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWLX, OPT_EA | OPT_REG, OPT_REG))
|
||||
ALT(DEF_ASM_OP2(testb, 0xa8, 0, OPC_BWLX, OPT_IM, OPT_EAX))
|
||||
ALT(DEF_ASM_OP2(testb, 0xf6, 0, OPC_MODRM | OPC_BWLX, OPT_IM, OPT_EA | OPT_REG))
|
||||
|
||||
ALT(DEF_ASM_OP1(incw, 0x40, 0, OPC_REG | OPC_WLX, OPT_REGW))
|
||||
ALT(DEF_ASM_OP1(incb, 0xfe, 0, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA))
|
||||
ALT(DEF_ASM_OP1(decw, 0x48, 0, OPC_REG | OPC_WLX, OPT_REGW))
|
||||
ALT(DEF_ASM_OP1(decb, 0xfe, 1, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA))
|
||||
|
||||
ALT(DEF_ASM_OP1(notb, 0xf6, 2, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA))
|
||||
ALT(DEF_ASM_OP1(negb, 0xf6, 3, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA))
|
||||
|
||||
ALT(DEF_ASM_OP1(mulb, 0xf6, 4, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA))
|
||||
ALT(DEF_ASM_OP1(imulb, 0xf6, 5, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA))
|
||||
|
||||
ALT(DEF_ASM_OP2(imulw, 0x0faf, 0, OPC_MODRM | OPC_WLX, OPT_REG | OPT_EA, OPT_REG))
|
||||
ALT(DEF_ASM_OP3(imulw, 0x6b, 0, OPC_MODRM | OPC_WLX, OPT_IM8S, OPT_REGW | OPT_EA, OPT_REGW))
|
||||
ALT(DEF_ASM_OP2(imulw, 0x6b, 0, OPC_MODRM | OPC_WLX, OPT_IM8S, OPT_REGW))
|
||||
ALT(DEF_ASM_OP3(imulw, 0x69, 0, OPC_MODRM | OPC_WLX, OPT_IMW, OPT_REGW | OPT_EA, OPT_REGW))
|
||||
ALT(DEF_ASM_OP2(imulw, 0x69, 0, OPC_MODRM | OPC_WLX, OPT_IMW, OPT_REGW))
|
||||
|
||||
ALT(DEF_ASM_OP1(divb, 0xf6, 6, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA))
|
||||
ALT(DEF_ASM_OP2(divb, 0xf6, 6, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA, OPT_EAX))
|
||||
ALT(DEF_ASM_OP1(idivb, 0xf6, 7, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA))
|
||||
ALT(DEF_ASM_OP2(idivb, 0xf6, 7, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA, OPT_EAX))
|
||||
|
||||
/* shifts */
|
||||
ALT(DEF_ASM_OP2(rolb, 0xc0, 0, OPC_MODRM | OPC_BWLX | OPC_SHIFT, OPT_IM8, OPT_EA | OPT_REG))
|
||||
ALT(DEF_ASM_OP2(rolb, 0xd2, 0, OPC_MODRM | OPC_BWLX | OPC_SHIFT, OPT_CL, OPT_EA | OPT_REG))
|
||||
ALT(DEF_ASM_OP1(rolb, 0xd0, 0, OPC_MODRM | OPC_BWLX | OPC_SHIFT, OPT_EA | OPT_REG))
|
||||
|
||||
ALT(DEF_ASM_OP3(shldw, 0x0fa4, 0, OPC_MODRM | OPC_WLX, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
|
||||
ALT(DEF_ASM_OP3(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WLX, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
|
||||
ALT(DEF_ASM_OP2(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WLX, OPT_REGW, OPT_EA | OPT_REGW))
|
||||
ALT(DEF_ASM_OP3(shrdw, 0x0fac, 0, OPC_MODRM | OPC_WLX, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
|
||||
ALT(DEF_ASM_OP3(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WLX, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
|
||||
ALT(DEF_ASM_OP2(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WLX, OPT_REGW, OPT_EA | OPT_REGW))
|
||||
|
||||
ALT(DEF_ASM_OP1(call, 0xff, 2, OPC_MODRM, OPT_INDIR))
|
||||
ALT(DEF_ASM_OP1(call, 0xe8, 0, 0, OPT_DISP))
|
||||
ALT(DEF_ASM_OP1(jmp, 0xff, 4, OPC_MODRM, OPT_INDIR))
|
||||
ALT(DEF_ASM_OP1(jmp, 0xeb, 0, 0, OPT_DISP8))
|
||||
|
||||
ALT(DEF_ASM_OP2(lcall, 0x9a, 0, 0, OPT_IM16, OPT_IM32))
|
||||
ALT(DEF_ASM_OP1(lcall, 0xff, 3, OPC_MODRM, OPT_EA))
|
||||
ALT(DEF_ASM_OP2(ljmp, 0xea, 0, 0, OPT_IM16, OPT_IM32))
|
||||
ALT(DEF_ASM_OP1(ljmp, 0xff, 5, OPC_MODRM, OPT_EA))
|
||||
|
||||
ALT(DEF_ASM_OP1(int, 0xcd, 0, 0, OPT_IM8))
|
||||
ALT(DEF_ASM_OP1(seto, 0x0f90, 0, OPC_MODRM | OPC_TEST, OPT_REG8 | OPT_EA))
|
||||
ALT(DEF_ASM_OP1(setob, 0x0f90, 0, OPC_MODRM | OPC_TEST, OPT_REG8 | OPT_EA))
|
||||
DEF_ASM_OP2(enter, 0xc8, 0, 0, OPT_IM16, OPT_IM8)
|
||||
DEF_ASM_OP0(leave, 0xc9)
|
||||
DEF_ASM_OP0(ret, 0xc3)
|
||||
DEF_ASM_OP0(retl,0xc3)
|
||||
ALT(DEF_ASM_OP1(retl,0xc2, 0, 0, OPT_IM16))
|
||||
ALT(DEF_ASM_OP1(ret, 0xc2, 0, 0, OPT_IM16))
|
||||
DEF_ASM_OP0(lret, 0xcb)
|
||||
ALT(DEF_ASM_OP1(lret, 0xca, 0, 0, OPT_IM16))
|
||||
|
||||
ALT(DEF_ASM_OP1(jo, 0x70, 0, OPC_TEST, OPT_DISP8))
|
||||
DEF_ASM_OP1(loopne, 0xe0, 0, 0, OPT_DISP8)
|
||||
DEF_ASM_OP1(loopnz, 0xe0, 0, 0, OPT_DISP8)
|
||||
DEF_ASM_OP1(loope, 0xe1, 0, 0, OPT_DISP8)
|
||||
DEF_ASM_OP1(loopz, 0xe1, 0, 0, OPT_DISP8)
|
||||
DEF_ASM_OP1(loop, 0xe2, 0, 0, OPT_DISP8)
|
||||
DEF_ASM_OP1(jecxz, 0xe3, 0, 0, OPT_DISP8)
|
||||
|
||||
/* float */
|
||||
/* specific fcomp handling */
|
||||
ALT(DEF_ASM_OP0L(fcomp, 0xd8d9, 0, 0))
|
||||
|
||||
ALT(DEF_ASM_OP1(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST))
|
||||
ALT(DEF_ASM_OP2(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
|
||||
ALT(DEF_ASM_OP2(fadd, 0xdcc0, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST))
|
||||
ALT(DEF_ASM_OP2(fmul, 0xdcc8, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST))
|
||||
ALT(DEF_ASM_OP0L(fadd, 0xdec1, 0, OPC_FARITH))
|
||||
ALT(DEF_ASM_OP1(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST))
|
||||
ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
|
||||
ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST))
|
||||
ALT(DEF_ASM_OP0L(faddp, 0xdec1, 0, OPC_FARITH))
|
||||
ALT(DEF_ASM_OP1(fadds, 0xd8, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
|
||||
ALT(DEF_ASM_OP1(fiaddl, 0xda, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
|
||||
ALT(DEF_ASM_OP1(faddl, 0xdc, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
|
||||
ALT(DEF_ASM_OP1(fiadds, 0xde, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
|
||||
|
||||
DEF_ASM_OP0(fucompp, 0xdae9)
|
||||
DEF_ASM_OP0(ftst, 0xd9e4)
|
||||
DEF_ASM_OP0(fxam, 0xd9e5)
|
||||
DEF_ASM_OP0(fld1, 0xd9e8)
|
||||
DEF_ASM_OP0(fldl2t, 0xd9e9)
|
||||
DEF_ASM_OP0(fldl2e, 0xd9ea)
|
||||
DEF_ASM_OP0(fldpi, 0xd9eb)
|
||||
DEF_ASM_OP0(fldlg2, 0xd9ec)
|
||||
DEF_ASM_OP0(fldln2, 0xd9ed)
|
||||
DEF_ASM_OP0(fldz, 0xd9ee)
|
||||
|
||||
DEF_ASM_OP0(f2xm1, 0xd9f0)
|
||||
DEF_ASM_OP0(fyl2x, 0xd9f1)
|
||||
DEF_ASM_OP0(fptan, 0xd9f2)
|
||||
DEF_ASM_OP0(fpatan, 0xd9f3)
|
||||
DEF_ASM_OP0(fxtract, 0xd9f4)
|
||||
DEF_ASM_OP0(fprem1, 0xd9f5)
|
||||
DEF_ASM_OP0(fdecstp, 0xd9f6)
|
||||
DEF_ASM_OP0(fincstp, 0xd9f7)
|
||||
DEF_ASM_OP0(fprem, 0xd9f8)
|
||||
DEF_ASM_OP0(fyl2xp1, 0xd9f9)
|
||||
DEF_ASM_OP0(fsqrt, 0xd9fa)
|
||||
DEF_ASM_OP0(fsincos, 0xd9fb)
|
||||
DEF_ASM_OP0(frndint, 0xd9fc)
|
||||
DEF_ASM_OP0(fscale, 0xd9fd)
|
||||
DEF_ASM_OP0(fsin, 0xd9fe)
|
||||
DEF_ASM_OP0(fcos, 0xd9ff)
|
||||
DEF_ASM_OP0(fchs, 0xd9e0)
|
||||
DEF_ASM_OP0(fabs, 0xd9e1)
|
||||
DEF_ASM_OP0(fninit, 0xdbe3)
|
||||
DEF_ASM_OP0(fnclex, 0xdbe2)
|
||||
DEF_ASM_OP0(fnop, 0xd9d0)
|
||||
|
||||
/* fp load */
|
||||
DEF_ASM_OP1(fld, 0xd9c0, 0, OPC_REG, OPT_ST)
|
||||
DEF_ASM_OP1(fldl, 0xd9c0, 0, OPC_REG, OPT_ST)
|
||||
DEF_ASM_OP1(flds, 0xd9, 0, OPC_MODRM, OPT_EA)
|
||||
ALT(DEF_ASM_OP1(fldl, 0xdd, 0, OPC_MODRM, OPT_EA))
|
||||
DEF_ASM_OP1(fildl, 0xdb, 0, OPC_MODRM, OPT_EA)
|
||||
DEF_ASM_OP1(fildq, 0xdf, 5, OPC_MODRM, OPT_EA)
|
||||
DEF_ASM_OP1(fildll, 0xdf, 5, OPC_MODRM,OPT_EA)
|
||||
DEF_ASM_OP1(fldt, 0xdb, 5, OPC_MODRM, OPT_EA)
|
||||
DEF_ASM_OP1(fbld, 0xdf, 4, OPC_MODRM, OPT_EA)
|
||||
|
||||
/* fp store */
|
||||
DEF_ASM_OP1(fst, 0xddd0, 0, OPC_REG, OPT_ST)
|
||||
DEF_ASM_OP1(fstl, 0xddd0, 0, OPC_REG, OPT_ST)
|
||||
DEF_ASM_OP1(fsts, 0xd9, 2, OPC_MODRM, OPT_EA)
|
||||
DEF_ASM_OP1(fstps, 0xd9, 3, OPC_MODRM, OPT_EA)
|
||||
ALT(DEF_ASM_OP1(fstl, 0xdd, 2, OPC_MODRM, OPT_EA))
|
||||
DEF_ASM_OP1(fstpl, 0xdd, 3, OPC_MODRM, OPT_EA)
|
||||
DEF_ASM_OP1(fist, 0xdf, 2, OPC_MODRM, OPT_EA)
|
||||
DEF_ASM_OP1(fistp, 0xdf, 3, OPC_MODRM, OPT_EA)
|
||||
DEF_ASM_OP1(fistl, 0xdb, 2, OPC_MODRM, OPT_EA)
|
||||
DEF_ASM_OP1(fistpl, 0xdb, 3, OPC_MODRM, OPT_EA)
|
||||
|
||||
DEF_ASM_OP1(fstp, 0xddd8, 0, OPC_REG, OPT_ST)
|
||||
DEF_ASM_OP1(fistpq, 0xdf, 7, OPC_MODRM, OPT_EA)
|
||||
DEF_ASM_OP1(fistpll, 0xdf, 7, OPC_MODRM, OPT_EA)
|
||||
DEF_ASM_OP1(fstpt, 0xdb, 7, OPC_MODRM, OPT_EA)
|
||||
DEF_ASM_OP1(fbstp, 0xdf, 6, OPC_MODRM, OPT_EA)
|
||||
|
||||
/* exchange */
|
||||
DEF_ASM_OP0(fxch, 0xd9c9)
|
||||
ALT(DEF_ASM_OP1(fxch, 0xd9c8, 0, OPC_REG, OPT_ST))
|
||||
|
||||
/* misc FPU */
|
||||
DEF_ASM_OP1(fucom, 0xdde0, 0, OPC_REG, OPT_ST )
|
||||
DEF_ASM_OP1(fucomp, 0xdde8, 0, OPC_REG, OPT_ST )
|
||||
|
||||
DEF_ASM_OP0L(finit, 0xdbe3, 0, OPC_FWAIT)
|
||||
DEF_ASM_OP1(fldcw, 0xd9, 5, OPC_MODRM, OPT_EA )
|
||||
DEF_ASM_OP1(fnstcw, 0xd9, 7, OPC_MODRM, OPT_EA )
|
||||
DEF_ASM_OP1(fstcw, 0xd9, 7, OPC_MODRM | OPC_FWAIT, OPT_EA )
|
||||
DEF_ASM_OP0(fnstsw, 0xdfe0)
|
||||
ALT(DEF_ASM_OP1(fnstsw, 0xdfe0, 0, 0, OPT_EAX ))
|
||||
ALT(DEF_ASM_OP1(fnstsw, 0xdd, 7, OPC_MODRM, OPT_EA ))
|
||||
DEF_ASM_OP1(fstsw, 0xdfe0, 0, OPC_FWAIT, OPT_EAX )
|
||||
ALT(DEF_ASM_OP0L(fstsw, 0xdfe0, 0, OPC_FWAIT))
|
||||
ALT(DEF_ASM_OP1(fstsw, 0xdd, 7, OPC_MODRM | OPC_FWAIT, OPT_EA ))
|
||||
DEF_ASM_OP0L(fclex, 0xdbe2, 0, OPC_FWAIT)
|
||||
DEF_ASM_OP1(fnstenv, 0xd9, 6, OPC_MODRM, OPT_EA )
|
||||
DEF_ASM_OP1(fstenv, 0xd9, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
|
||||
DEF_ASM_OP1(fldenv, 0xd9, 4, OPC_MODRM, OPT_EA )
|
||||
DEF_ASM_OP1(fnsave, 0xdd, 6, OPC_MODRM, OPT_EA )
|
||||
DEF_ASM_OP1(fsave, 0xdd, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
|
||||
DEF_ASM_OP1(frstor, 0xdd, 4, OPC_MODRM, OPT_EA )
|
||||
DEF_ASM_OP1(ffree, 0xddc0, 4, OPC_REG, OPT_ST )
|
||||
DEF_ASM_OP1(ffreep, 0xdfc0, 4, OPC_REG, OPT_ST )
|
||||
DEF_ASM_OP1(fxsave, 0x0fae, 0, OPC_MODRM, OPT_EA )
|
||||
DEF_ASM_OP1(fxrstor, 0x0fae, 1, OPC_MODRM, OPT_EA )
|
||||
|
||||
/* segments */
|
||||
DEF_ASM_OP2(arpl, 0x63, 0, OPC_MODRM, OPT_REG16, OPT_REG16 | OPT_EA)
|
||||
ALT(DEF_ASM_OP2(larw, 0x0f02, 0, OPC_MODRM | OPC_WLX, OPT_REG | OPT_EA, OPT_REG))
|
||||
DEF_ASM_OP1(lgdt, 0x0f01, 2, OPC_MODRM, OPT_EA)
|
||||
DEF_ASM_OP1(lidt, 0x0f01, 3, OPC_MODRM, OPT_EA)
|
||||
DEF_ASM_OP1(lldt, 0x0f00, 2, OPC_MODRM, OPT_EA | OPT_REG)
|
||||
DEF_ASM_OP1(lmsw, 0x0f01, 6, OPC_MODRM, OPT_EA | OPT_REG)
|
||||
ALT(DEF_ASM_OP2(lslw, 0x0f03, 0, OPC_MODRM | OPC_WLX, OPT_EA | OPT_REG, OPT_REG))
|
||||
DEF_ASM_OP1(ltr, 0x0f00, 3, OPC_MODRM, OPT_EA | OPT_REG)
|
||||
DEF_ASM_OP1(sgdt, 0x0f01, 0, OPC_MODRM, OPT_EA)
|
||||
DEF_ASM_OP1(sidt, 0x0f01, 1, OPC_MODRM, OPT_EA)
|
||||
DEF_ASM_OP1(sldt, 0x0f00, 0, OPC_MODRM, OPT_REG | OPT_EA)
|
||||
DEF_ASM_OP1(smsw, 0x0f01, 4, OPC_MODRM, OPT_REG | OPT_EA)
|
||||
DEF_ASM_OP1(str, 0x0f00, 1, OPC_MODRM, OPT_REG16| OPT_EA)
|
||||
DEF_ASM_OP1(verr, 0x0f00, 4, OPC_MODRM, OPT_REG | OPT_EA)
|
||||
DEF_ASM_OP1(verw, 0x0f00, 5, OPC_MODRM, OPT_REG | OPT_EA)
|
||||
|
||||
/* 486 */
|
||||
DEF_ASM_OP1(bswap, 0x0fc8, 0, OPC_REG, OPT_REG32 )
|
||||
ALT(DEF_ASM_OP2(xaddb, 0x0fc0, 0, OPC_MODRM | OPC_BWLX, OPT_REG, OPT_REG | OPT_EA ))
|
||||
ALT(DEF_ASM_OP2(cmpxchgb, 0x0fb0, 0, OPC_MODRM | OPC_BWLX, OPT_REG, OPT_REG | OPT_EA ))
|
||||
DEF_ASM_OP1(invlpg, 0x0f01, 7, OPC_MODRM, OPT_EA )
|
||||
|
||||
DEF_ASM_OP2(boundl, 0x62, 0, OPC_MODRM, OPT_REG32, OPT_EA)
|
||||
DEF_ASM_OP2(boundw, 0x6662, 0, OPC_MODRM, OPT_REG16, OPT_EA)
|
||||
|
||||
/* pentium */
|
||||
DEF_ASM_OP1(cmpxchg8b, 0x0fc7, 1, OPC_MODRM, OPT_EA )
|
||||
|
||||
/* pentium pro */
|
||||
ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST | OPC_WLX, OPT_REGW | OPT_EA, OPT_REGW))
|
||||
DEF_ASM_OP2(fcmovb, 0xdac0, 0, OPC_REG, OPT_ST, OPT_ST0 )
|
||||
DEF_ASM_OP2(fcmove, 0xdac8, 0, OPC_REG, OPT_ST, OPT_ST0 )
|
||||
DEF_ASM_OP2(fcmovbe, 0xdad0, 0, OPC_REG, OPT_ST, OPT_ST0 )
|
||||
DEF_ASM_OP2(fcmovu, 0xdad8, 0, OPC_REG, OPT_ST, OPT_ST0 )
|
||||
DEF_ASM_OP2(fcmovnb, 0xdbc0, 0, OPC_REG, OPT_ST, OPT_ST0 )
|
||||
DEF_ASM_OP2(fcmovne, 0xdbc8, 0, OPC_REG, OPT_ST, OPT_ST0 )
|
||||
DEF_ASM_OP2(fcmovnbe, 0xdbd0, 0, OPC_REG, OPT_ST, OPT_ST0 )
|
||||
DEF_ASM_OP2(fcmovnu, 0xdbd8, 0, OPC_REG, OPT_ST, OPT_ST0 )
|
||||
|
||||
DEF_ASM_OP2(fucomi, 0xdbe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
|
||||
DEF_ASM_OP2(fcomi, 0xdbf0, 0, OPC_REG, OPT_ST, OPT_ST0 )
|
||||
DEF_ASM_OP2(fucomip, 0xdfe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
|
||||
DEF_ASM_OP2(fcomip, 0xdff0, 0, OPC_REG, OPT_ST, OPT_ST0 )
|
||||
|
||||
/* mmx */
|
||||
DEF_ASM_OP0(emms, 0x0f77) /* must be last OP0 */
|
||||
DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(movq, 0x0f6f, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
|
||||
ALT(DEF_ASM_OP2(movd, 0x0f7e, 0, OPC_MODRM, OPT_MMXSSE, OPT_EA | OPT_REG32 ))
|
||||
ALT(DEF_ASM_OP2(movq, 0x0f7f, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_MMX ))
|
||||
ALT(DEF_ASM_OP2(movq, 0x660fd6, 0, OPC_MODRM, OPT_SSE, OPT_EA | OPT_SSE ))
|
||||
ALT(DEF_ASM_OP2(movq, 0xf30f7e, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE ))
|
||||
|
||||
DEF_ASM_OP2(packssdw, 0x0f6b, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(packsswb, 0x0f63, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(packuswb, 0x0f67, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(paddb, 0x0ffc, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(paddw, 0x0ffd, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(paddd, 0x0ffe, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(paddsb, 0x0fec, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(paddsw, 0x0fed, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(paddusb, 0x0fdc, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(paddusw, 0x0fdd, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(pand, 0x0fdb, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(pandn, 0x0fdf, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(pcmpeqb, 0x0f74, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(pcmpeqw, 0x0f75, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(pcmpeqd, 0x0f76, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(pcmpgtb, 0x0f64, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(pcmpgtw, 0x0f65, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(pcmpgtd, 0x0f66, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(pmaddwd, 0x0ff5, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(pmulhw, 0x0fe5, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(pmullw, 0x0fd5, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(por, 0x0feb, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(psllw, 0x0ff1, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
ALT(DEF_ASM_OP2(psllw, 0x0f71, 6, OPC_MODRM, OPT_IM8, OPT_MMXSSE ))
|
||||
DEF_ASM_OP2(pslld, 0x0ff2, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
ALT(DEF_ASM_OP2(pslld, 0x0f72, 6, OPC_MODRM, OPT_IM8, OPT_MMXSSE ))
|
||||
DEF_ASM_OP2(psllq, 0x0ff3, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
ALT(DEF_ASM_OP2(psllq, 0x0f73, 6, OPC_MODRM, OPT_IM8, OPT_MMXSSE ))
|
||||
DEF_ASM_OP2(psraw, 0x0fe1, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
ALT(DEF_ASM_OP2(psraw, 0x0f71, 4, OPC_MODRM, OPT_IM8, OPT_MMXSSE ))
|
||||
DEF_ASM_OP2(psrad, 0x0fe2, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
ALT(DEF_ASM_OP2(psrad, 0x0f72, 4, OPC_MODRM, OPT_IM8, OPT_MMXSSE ))
|
||||
DEF_ASM_OP2(psrlw, 0x0fd1, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
ALT(DEF_ASM_OP2(psrlw, 0x0f71, 2, OPC_MODRM, OPT_IM8, OPT_MMXSSE ))
|
||||
DEF_ASM_OP2(psrld, 0x0fd2, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
ALT(DEF_ASM_OP2(psrld, 0x0f72, 2, OPC_MODRM, OPT_IM8, OPT_MMXSSE ))
|
||||
DEF_ASM_OP2(psrlq, 0x0fd3, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
ALT(DEF_ASM_OP2(psrlq, 0x0f73, 2, OPC_MODRM, OPT_IM8, OPT_MMXSSE ))
|
||||
DEF_ASM_OP2(psubb, 0x0ff8, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(psubw, 0x0ff9, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(psubd, 0x0ffa, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(psubsb, 0x0fe8, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(psubsw, 0x0fe9, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(psubusb, 0x0fd8, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(psubusw, 0x0fd9, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(punpckhbw, 0x0f68, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(punpckhwd, 0x0f69, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(punpckhdq, 0x0f6a, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(punpcklbw, 0x0f60, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(punpcklwd, 0x0f61, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(punpckldq, 0x0f62, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(pxor, 0x0fef, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
|
||||
/* sse */
|
||||
DEF_ASM_OP2(movups, 0x0f10, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_SSE )
|
||||
ALT(DEF_ASM_OP2(movups, 0x0f11, 0, OPC_MODRM, OPT_SSE, OPT_EA | OPT_REG32 ))
|
||||
DEF_ASM_OP2(movaps, 0x0f28, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_SSE )
|
||||
ALT(DEF_ASM_OP2(movaps, 0x0f29, 0, OPC_MODRM, OPT_SSE, OPT_EA | OPT_REG32 ))
|
||||
DEF_ASM_OP2(movhps, 0x0f16, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_SSE )
|
||||
ALT(DEF_ASM_OP2(movhps, 0x0f17, 0, OPC_MODRM, OPT_SSE, OPT_EA | OPT_REG32 ))
|
||||
DEF_ASM_OP2(addps, 0x0f58, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
|
||||
DEF_ASM_OP2(cvtpi2ps, 0x0f2a, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_SSE )
|
||||
DEF_ASM_OP2(cvtps2pi, 0x0f2d, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_MMX )
|
||||
DEF_ASM_OP2(cvttps2pi, 0x0f2c, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_MMX )
|
||||
DEF_ASM_OP2(divps, 0x0f5e, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
|
||||
DEF_ASM_OP2(maxps, 0x0f5f, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
|
||||
DEF_ASM_OP2(minps, 0x0f5d, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
|
||||
DEF_ASM_OP2(mulps, 0x0f59, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
|
||||
DEF_ASM_OP2(pavgb, 0x0fe0, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
|
||||
DEF_ASM_OP2(pavgw, 0x0fe3, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
|
||||
DEF_ASM_OP2(pmaxsw, 0x0fee, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(pmaxub, 0x0fde, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(pminsw, 0x0fea, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(pminub, 0x0fda, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||
DEF_ASM_OP2(rcpss, 0x0f53, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
|
||||
DEF_ASM_OP2(rsqrtps, 0x0f52, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
|
||||
DEF_ASM_OP2(sqrtps, 0x0f51, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
|
||||
DEF_ASM_OP2(subps, 0x0f5c, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
|
||||
|
||||
#undef ALT
|
||||
#undef DEF_ASM_OP0
|
||||
#undef DEF_ASM_OP0L
|
||||
#undef DEF_ASM_OP1
|
||||
#undef DEF_ASM_OP2
|
||||
#undef DEF_ASM_OP3
|
1164
05/tcc-0.9.27/i386-gen.c
Normal file
1164
05/tcc-0.9.27/i386-gen.c
Normal file
File diff suppressed because it is too large
Load diff
247
05/tcc-0.9.27/i386-link.c
Normal file
247
05/tcc-0.9.27/i386-link.c
Normal file
|
@ -0,0 +1,247 @@
|
|||
#ifdef TARGET_DEFS_ONLY
|
||||
|
||||
#define EM_TCC_TARGET EM_386
|
||||
|
||||
/* relocation type for 32 bit data relocation */
|
||||
#define R_DATA_32 R_386_32
|
||||
#define R_DATA_PTR R_386_32
|
||||
#define R_JMP_SLOT R_386_JMP_SLOT
|
||||
#define R_GLOB_DAT R_386_GLOB_DAT
|
||||
#define R_COPY R_386_COPY
|
||||
#define R_RELATIVE R_386_RELATIVE
|
||||
|
||||
#define R_NUM R_386_NUM
|
||||
|
||||
#define ELF_START_ADDR 0x08048000
|
||||
#define ELF_PAGE_SIZE 0x1000
|
||||
|
||||
#define PCRELATIVE_DLLPLT 0
|
||||
#define RELOCATE_DLLPLT 0
|
||||
|
||||
#else /* !TARGET_DEFS_ONLY */
|
||||
|
||||
#include "tcc.h"
|
||||
|
||||
/* Returns 1 for a code relocation, 0 for a data relocation. For unknown
|
||||
relocations, returns -1. */
|
||||
int code_reloc (int reloc_type)
|
||||
{
|
||||
switch (reloc_type) {
|
||||
case R_386_RELATIVE:
|
||||
case R_386_16:
|
||||
case R_386_32:
|
||||
case R_386_GOTPC:
|
||||
case R_386_GOTOFF:
|
||||
case R_386_GOT32:
|
||||
case R_386_GOT32X:
|
||||
case R_386_GLOB_DAT:
|
||||
case R_386_COPY:
|
||||
return 0;
|
||||
|
||||
case R_386_PC16:
|
||||
case R_386_PC32:
|
||||
case R_386_PLT32:
|
||||
case R_386_JMP_SLOT:
|
||||
return 1;
|
||||
}
|
||||
|
||||
tcc_error ("Unknown relocation type: %d", reloc_type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Returns an enumerator to describe whether and when the relocation needs a
|
||||
GOT and/or PLT entry to be created. See tcc.h for a description of the
|
||||
different values. */
|
||||
int gotplt_entry_type (int reloc_type)
|
||||
{
|
||||
switch (reloc_type) {
|
||||
case R_386_RELATIVE:
|
||||
case R_386_16:
|
||||
case R_386_GLOB_DAT:
|
||||
case R_386_JMP_SLOT:
|
||||
case R_386_COPY:
|
||||
return NO_GOTPLT_ENTRY;
|
||||
|
||||
case R_386_32:
|
||||
/* This relocations shouldn't normally need GOT or PLT
|
||||
slots if it weren't for simplicity in the code generator.
|
||||
See our caller for comments. */
|
||||
return AUTO_GOTPLT_ENTRY;
|
||||
|
||||
case R_386_PC16:
|
||||
case R_386_PC32:
|
||||
return AUTO_GOTPLT_ENTRY;
|
||||
|
||||
case R_386_GOTPC:
|
||||
case R_386_GOTOFF:
|
||||
return BUILD_GOT_ONLY;
|
||||
|
||||
case R_386_GOT32:
|
||||
case R_386_GOT32X:
|
||||
case R_386_PLT32:
|
||||
return ALWAYS_GOTPLT_ENTRY;
|
||||
}
|
||||
|
||||
tcc_error ("Unknown relocation type: %d", reloc_type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
|
||||
{
|
||||
Section *plt = s1->plt;
|
||||
uint8_t *p;
|
||||
int modrm;
|
||||
unsigned plt_offset, relofs;
|
||||
|
||||
/* on i386 if we build a DLL, we add a %ebx offset */
|
||||
if (s1->output_type == TCC_OUTPUT_DLL)
|
||||
modrm = 0xa3;
|
||||
else
|
||||
modrm = 0x25;
|
||||
|
||||
/* empty PLT: create PLT0 entry that pushes the library identifier
|
||||
(GOT + PTR_SIZE) and jumps to ld.so resolution routine
|
||||
(GOT + 2 * PTR_SIZE) */
|
||||
if (plt->data_offset == 0) {
|
||||
p = section_ptr_add(plt, 16);
|
||||
p[0] = 0xff; /* pushl got + PTR_SIZE */
|
||||
p[1] = modrm + 0x10;
|
||||
write32le(p + 2, PTR_SIZE);
|
||||
p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
|
||||
p[7] = modrm;
|
||||
write32le(p + 8, PTR_SIZE * 2);
|
||||
}
|
||||
plt_offset = plt->data_offset;
|
||||
|
||||
/* The PLT slot refers to the relocation entry it needs via offset.
|
||||
The reloc entry is created below, so its offset is the current
|
||||
data_offset */
|
||||
relofs = s1->got->reloc ? s1->got->reloc->data_offset : 0;
|
||||
|
||||
/* Jump to GOT entry where ld.so initially put the address of ip + 4 */
|
||||
p = section_ptr_add(plt, 16);
|
||||
p[0] = 0xff; /* jmp *(got + x) */
|
||||
p[1] = modrm;
|
||||
write32le(p + 2, got_offset);
|
||||
p[6] = 0x68; /* push $xxx */
|
||||
write32le(p + 7, relofs);
|
||||
p[11] = 0xe9; /* jmp plt_start */
|
||||
write32le(p + 12, -(plt->data_offset));
|
||||
return plt_offset;
|
||||
}
|
||||
|
||||
/* relocate the PLT: compute addresses and offsets in the PLT now that final
|
||||
address for PLT and GOT are known (see fill_program_header) */
|
||||
ST_FUNC void relocate_plt(TCCState *s1)
|
||||
{
|
||||
uint8_t *p, *p_end;
|
||||
|
||||
if (!s1->plt)
|
||||
return;
|
||||
|
||||
p = s1->plt->data;
|
||||
p_end = p + s1->plt->data_offset;
|
||||
|
||||
if (p < p_end) {
|
||||
add32le(p + 2, s1->got->sh_addr);
|
||||
add32le(p + 8, s1->got->sh_addr);
|
||||
p += 16;
|
||||
while (p < p_end) {
|
||||
add32le(p + 2, s1->got->sh_addr);
|
||||
p += 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static ElfW_Rel *qrel; /* ptr to next reloc entry reused */
|
||||
|
||||
void relocate_init(Section *sr)
|
||||
{
|
||||
qrel = (ElfW_Rel *) sr->data;
|
||||
}
|
||||
|
||||
void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
|
||||
{
|
||||
int sym_index, esym_index;
|
||||
|
||||
sym_index = ELFW(R_SYM)(rel->r_info);
|
||||
|
||||
switch (type) {
|
||||
case R_386_32:
|
||||
if (s1->output_type == TCC_OUTPUT_DLL) {
|
||||
esym_index = s1->sym_attrs[sym_index].dyn_index;
|
||||
qrel->r_offset = rel->r_offset;
|
||||
if (esym_index) {
|
||||
qrel->r_info = ELFW(R_INFO)(esym_index, R_386_32);
|
||||
qrel++;
|
||||
return;
|
||||
} else {
|
||||
qrel->r_info = ELFW(R_INFO)(0, R_386_RELATIVE);
|
||||
qrel++;
|
||||
}
|
||||
}
|
||||
add32le(ptr, val);
|
||||
return;
|
||||
case R_386_PC32:
|
||||
if (s1->output_type == TCC_OUTPUT_DLL) {
|
||||
/* DLL relocation */
|
||||
esym_index = s1->sym_attrs[sym_index].dyn_index;
|
||||
if (esym_index) {
|
||||
qrel->r_offset = rel->r_offset;
|
||||
qrel->r_info = ELFW(R_INFO)(esym_index, R_386_PC32);
|
||||
qrel++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
add32le(ptr, val - addr);
|
||||
return;
|
||||
case R_386_PLT32:
|
||||
add32le(ptr, val - addr);
|
||||
return;
|
||||
case R_386_GLOB_DAT:
|
||||
case R_386_JMP_SLOT:
|
||||
write32le(ptr, val);
|
||||
return;
|
||||
case R_386_GOTPC:
|
||||
add32le(ptr, s1->got->sh_addr - addr);
|
||||
return;
|
||||
case R_386_GOTOFF:
|
||||
add32le(ptr, val - s1->got->sh_addr);
|
||||
return;
|
||||
case R_386_GOT32:
|
||||
case R_386_GOT32X:
|
||||
/* we load the got offset */
|
||||
add32le(ptr, s1->sym_attrs[sym_index].got_offset);
|
||||
return;
|
||||
case R_386_16:
|
||||
if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) {
|
||||
output_file:
|
||||
tcc_error("can only produce 16-bit binary files");
|
||||
}
|
||||
write16le(ptr, read16le(ptr) + val);
|
||||
return;
|
||||
case R_386_PC16:
|
||||
if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY)
|
||||
goto output_file;
|
||||
write16le(ptr, read16le(ptr) + val - addr);
|
||||
return;
|
||||
case R_386_RELATIVE:
|
||||
#ifdef TCC_TARGET_PE
|
||||
add32le(ptr, val - s1->pe_imagebase);
|
||||
#endif
|
||||
/* do nothing */
|
||||
return;
|
||||
case R_386_COPY:
|
||||
/* This relocation must copy initialized data from the library
|
||||
to the program .bss segment. Currently made like for ARM
|
||||
(to remove noise of default case). Is this true?
|
||||
*/
|
||||
return;
|
||||
default:
|
||||
fprintf(stderr,"FIXME: handle reloc type %d at %x [%p] to %x\n",
|
||||
type, (unsigned)addr, ptr, (unsigned)val);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* !TARGET_DEFS_ONLY */
|
253
05/tcc-0.9.27/i386-tok.h
Normal file
253
05/tcc-0.9.27/i386-tok.h
Normal file
|
@ -0,0 +1,253 @@
|
|||
/* ------------------------------------------------------------------ */
|
||||
/* WARNING: relative order of tokens is important. */
|
||||
|
||||
/* register */
|
||||
DEF_ASM(al)
|
||||
DEF_ASM(cl)
|
||||
DEF_ASM(dl)
|
||||
DEF_ASM(bl)
|
||||
DEF_ASM(ah)
|
||||
DEF_ASM(ch)
|
||||
DEF_ASM(dh)
|
||||
DEF_ASM(bh)
|
||||
DEF_ASM(ax)
|
||||
DEF_ASM(cx)
|
||||
DEF_ASM(dx)
|
||||
DEF_ASM(bx)
|
||||
DEF_ASM(sp)
|
||||
DEF_ASM(bp)
|
||||
DEF_ASM(si)
|
||||
DEF_ASM(di)
|
||||
DEF_ASM(eax)
|
||||
DEF_ASM(ecx)
|
||||
DEF_ASM(edx)
|
||||
DEF_ASM(ebx)
|
||||
DEF_ASM(esp)
|
||||
DEF_ASM(ebp)
|
||||
DEF_ASM(esi)
|
||||
DEF_ASM(edi)
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
DEF_ASM(rax)
|
||||
DEF_ASM(rcx)
|
||||
DEF_ASM(rdx)
|
||||
DEF_ASM(rbx)
|
||||
DEF_ASM(rsp)
|
||||
DEF_ASM(rbp)
|
||||
DEF_ASM(rsi)
|
||||
DEF_ASM(rdi)
|
||||
#endif
|
||||
DEF_ASM(mm0)
|
||||
DEF_ASM(mm1)
|
||||
DEF_ASM(mm2)
|
||||
DEF_ASM(mm3)
|
||||
DEF_ASM(mm4)
|
||||
DEF_ASM(mm5)
|
||||
DEF_ASM(mm6)
|
||||
DEF_ASM(mm7)
|
||||
DEF_ASM(xmm0)
|
||||
DEF_ASM(xmm1)
|
||||
DEF_ASM(xmm2)
|
||||
DEF_ASM(xmm3)
|
||||
DEF_ASM(xmm4)
|
||||
DEF_ASM(xmm5)
|
||||
DEF_ASM(xmm6)
|
||||
DEF_ASM(xmm7)
|
||||
DEF_ASM(cr0)
|
||||
DEF_ASM(cr1)
|
||||
DEF_ASM(cr2)
|
||||
DEF_ASM(cr3)
|
||||
DEF_ASM(cr4)
|
||||
DEF_ASM(cr5)
|
||||
DEF_ASM(cr6)
|
||||
DEF_ASM(cr7)
|
||||
DEF_ASM(tr0)
|
||||
DEF_ASM(tr1)
|
||||
DEF_ASM(tr2)
|
||||
DEF_ASM(tr3)
|
||||
DEF_ASM(tr4)
|
||||
DEF_ASM(tr5)
|
||||
DEF_ASM(tr6)
|
||||
DEF_ASM(tr7)
|
||||
DEF_ASM(db0)
|
||||
DEF_ASM(db1)
|
||||
DEF_ASM(db2)
|
||||
DEF_ASM(db3)
|
||||
DEF_ASM(db4)
|
||||
DEF_ASM(db5)
|
||||
DEF_ASM(db6)
|
||||
DEF_ASM(db7)
|
||||
DEF_ASM(dr0)
|
||||
DEF_ASM(dr1)
|
||||
DEF_ASM(dr2)
|
||||
DEF_ASM(dr3)
|
||||
DEF_ASM(dr4)
|
||||
DEF_ASM(dr5)
|
||||
DEF_ASM(dr6)
|
||||
DEF_ASM(dr7)
|
||||
DEF_ASM(es)
|
||||
DEF_ASM(cs)
|
||||
DEF_ASM(ss)
|
||||
DEF_ASM(ds)
|
||||
DEF_ASM(fs)
|
||||
DEF_ASM(gs)
|
||||
DEF_ASM(st)
|
||||
DEF_ASM(rip)
|
||||
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
/* The four low parts of sp/bp/si/di that exist only on
|
||||
x86-64 (encoding aliased to ah,ch,dh,dh when not using REX). */
|
||||
DEF_ASM(spl)
|
||||
DEF_ASM(bpl)
|
||||
DEF_ASM(sil)
|
||||
DEF_ASM(dil)
|
||||
#endif
|
||||
/* generic two operands */
|
||||
DEF_BWLX(mov)
|
||||
|
||||
DEF_BWLX(add)
|
||||
DEF_BWLX(or)
|
||||
DEF_BWLX(adc)
|
||||
DEF_BWLX(sbb)
|
||||
DEF_BWLX(and)
|
||||
DEF_BWLX(sub)
|
||||
DEF_BWLX(xor)
|
||||
DEF_BWLX(cmp)
|
||||
|
||||
/* unary ops */
|
||||
DEF_BWLX(inc)
|
||||
DEF_BWLX(dec)
|
||||
DEF_BWLX(not)
|
||||
DEF_BWLX(neg)
|
||||
DEF_BWLX(mul)
|
||||
DEF_BWLX(imul)
|
||||
DEF_BWLX(div)
|
||||
DEF_BWLX(idiv)
|
||||
|
||||
DEF_BWLX(xchg)
|
||||
DEF_BWLX(test)
|
||||
|
||||
/* shifts */
|
||||
DEF_BWLX(rol)
|
||||
DEF_BWLX(ror)
|
||||
DEF_BWLX(rcl)
|
||||
DEF_BWLX(rcr)
|
||||
DEF_BWLX(shl)
|
||||
DEF_BWLX(shr)
|
||||
DEF_BWLX(sar)
|
||||
|
||||
DEF_WLX(shld)
|
||||
DEF_WLX(shrd)
|
||||
|
||||
DEF_ASM(pushw)
|
||||
DEF_ASM(pushl)
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
DEF_ASM(pushq)
|
||||
#endif
|
||||
DEF_ASM(push)
|
||||
|
||||
DEF_ASM(popw)
|
||||
DEF_ASM(popl)
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
DEF_ASM(popq)
|
||||
#endif
|
||||
DEF_ASM(pop)
|
||||
|
||||
DEF_BWL(in)
|
||||
DEF_BWL(out)
|
||||
|
||||
DEF_WLX(movzb)
|
||||
DEF_ASM(movzwl)
|
||||
DEF_ASM(movsbw)
|
||||
DEF_ASM(movsbl)
|
||||
DEF_ASM(movswl)
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
DEF_ASM(movsbq)
|
||||
DEF_ASM(movswq)
|
||||
DEF_ASM(movzwq)
|
||||
DEF_ASM(movslq)
|
||||
#endif
|
||||
|
||||
DEF_WLX(lea)
|
||||
|
||||
DEF_ASM(les)
|
||||
DEF_ASM(lds)
|
||||
DEF_ASM(lss)
|
||||
DEF_ASM(lfs)
|
||||
DEF_ASM(lgs)
|
||||
|
||||
DEF_ASM(call)
|
||||
DEF_ASM(jmp)
|
||||
DEF_ASM(lcall)
|
||||
DEF_ASM(ljmp)
|
||||
|
||||
DEF_ASMTEST1(j)
|
||||
|
||||
DEF_ASMTEST1(set)
|
||||
DEF_ASMTEST(set,b)
|
||||
DEF_ASMTEST1(cmov)
|
||||
|
||||
DEF_WLX(bsf)
|
||||
DEF_WLX(bsr)
|
||||
DEF_WLX(bt)
|
||||
DEF_WLX(bts)
|
||||
DEF_WLX(btr)
|
||||
DEF_WLX(btc)
|
||||
|
||||
DEF_WLX(lar)
|
||||
DEF_WLX(lsl)
|
||||
|
||||
/* generic FP ops */
|
||||
DEF_FP(add)
|
||||
DEF_FP(mul)
|
||||
|
||||
DEF_ASM(fcom)
|
||||
DEF_ASM(fcom_1) /* non existent op, just to have a regular table */
|
||||
DEF_FP1(com)
|
||||
|
||||
DEF_FP(comp)
|
||||
DEF_FP(sub)
|
||||
DEF_FP(subr)
|
||||
DEF_FP(div)
|
||||
DEF_FP(divr)
|
||||
|
||||
DEF_BWLX(xadd)
|
||||
DEF_BWLX(cmpxchg)
|
||||
|
||||
/* string ops */
|
||||
DEF_BWLX(cmps)
|
||||
DEF_BWLX(scmp)
|
||||
DEF_BWL(ins)
|
||||
DEF_BWL(outs)
|
||||
DEF_BWLX(lods)
|
||||
DEF_BWLX(slod)
|
||||
DEF_BWLX(movs)
|
||||
DEF_BWLX(smov)
|
||||
DEF_BWLX(scas)
|
||||
DEF_BWLX(ssca)
|
||||
DEF_BWLX(stos)
|
||||
DEF_BWLX(ssto)
|
||||
|
||||
/* generic asm ops */
|
||||
#define ALT(x)
|
||||
#define DEF_ASM_OP0(name, opcode) DEF_ASM(name)
|
||||
#define DEF_ASM_OP0L(name, opcode, group, instr_type)
|
||||
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
|
||||
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
|
||||
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2)
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
# include "x86_64-asm.h"
|
||||
#else
|
||||
# include "i386-asm.h"
|
||||
#endif
|
||||
|
||||
#define ALT(x)
|
||||
#define DEF_ASM_OP0(name, opcode)
|
||||
#define DEF_ASM_OP0L(name, opcode, group, instr_type) DEF_ASM(name)
|
||||
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0) DEF_ASM(name)
|
||||
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) DEF_ASM(name)
|
||||
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) DEF_ASM(name)
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
# include "x86_64-asm.h"
|
||||
#else
|
||||
# include "i386-asm.h"
|
||||
#endif
|
657
05/tcc-0.9.27/il-gen.c
Normal file
657
05/tcc-0.9.27/il-gen.c
Normal file
|
@ -0,0 +1,657 @@
|
|||
/*
|
||||
* CIL code generator for TCC
|
||||
*
|
||||
* Copyright (c) 2002 Fabrice Bellard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser 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
|
||||
*/
|
||||
|
||||
#error this code has bit-rotted since 2003
|
||||
|
||||
/* number of available registers */
|
||||
#define NB_REGS 3
|
||||
|
||||
/* a register can belong to several classes. The classes must be
|
||||
sorted from more general to more precise (see gv2() code which does
|
||||
assumptions on it). */
|
||||
#define RC_ST 0x0001 /* any stack entry */
|
||||
#define RC_ST0 0x0002 /* top of stack */
|
||||
#define RC_ST1 0x0004 /* top - 1 */
|
||||
|
||||
#define RC_INT RC_ST
|
||||
#define RC_FLOAT RC_ST
|
||||
#define RC_IRET RC_ST0 /* function return: integer register */
|
||||
#define RC_LRET RC_ST0 /* function return: second integer register */
|
||||
#define RC_FRET RC_ST0 /* function return: float register */
|
||||
|
||||
/* pretty names for the registers */
|
||||
enum {
|
||||
REG_ST0 = 0,
|
||||
REG_ST1,
|
||||
REG_ST2,
|
||||
};
|
||||
|
||||
const int reg_classes[NB_REGS] = {
|
||||
/* ST0 */ RC_ST | RC_ST0,
|
||||
/* ST1 */ RC_ST | RC_ST1,
|
||||
/* ST2 */ RC_ST,
|
||||
};
|
||||
|
||||
/* return registers for function */
|
||||
#define REG_IRET REG_ST0 /* single word int return register */
|
||||
#define REG_LRET REG_ST0 /* second word return register (for long long) */
|
||||
#define REG_FRET REG_ST0 /* float return register */
|
||||
|
||||
/* defined if function parameters must be evaluated in reverse order */
|
||||
/* #define INVERT_FUNC_PARAMS */
|
||||
|
||||
/* defined if structures are passed as pointers. Otherwise structures
|
||||
are directly pushed on stack. */
|
||||
/* #define FUNC_STRUCT_PARAM_AS_PTR */
|
||||
|
||||
/* pointer size, in bytes */
|
||||
#define PTR_SIZE 4
|
||||
|
||||
/* long double size and alignment, in bytes */
|
||||
#define LDOUBLE_SIZE 8
|
||||
#define LDOUBLE_ALIGN 8
|
||||
|
||||
/* function call context */
|
||||
typedef struct GFuncContext {
|
||||
int func_call; /* func call type (FUNC_STDCALL or FUNC_CDECL) */
|
||||
} GFuncContext;
|
||||
|
||||
/******************************************************/
|
||||
/* opcode definitions */
|
||||
|
||||
#define IL_OP_PREFIX 0xFE
|
||||
|
||||
enum ILOPCodes {
|
||||
#define OP(name, str, n) IL_OP_ ## name = n,
|
||||
#include "il-opcodes.h"
|
||||
#undef OP
|
||||
};
|
||||
|
||||
char *il_opcodes_str[] = {
|
||||
#define OP(name, str, n) [n] = str,
|
||||
#include "il-opcodes.h"
|
||||
#undef OP
|
||||
};
|
||||
|
||||
/******************************************************/
|
||||
|
||||
/* arguments variable numbers start from there */
|
||||
#define ARG_BASE 0x70000000
|
||||
|
||||
static FILE *il_outfile;
|
||||
|
||||
static void out_byte(int c)
|
||||
{
|
||||
*(char *)ind++ = c;
|
||||
}
|
||||
|
||||
static void out_le32(int c)
|
||||
{
|
||||
out_byte(c);
|
||||
out_byte(c >> 8);
|
||||
out_byte(c >> 16);
|
||||
out_byte(c >> 24);
|
||||
}
|
||||
|
||||
static void init_outfile(void)
|
||||
{
|
||||
if (!il_outfile) {
|
||||
il_outfile = stdout;
|
||||
fprintf(il_outfile,
|
||||
".assembly extern mscorlib\n"
|
||||
"{\n"
|
||||
".ver 1:0:2411:0\n"
|
||||
"}\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void out_op1(int op)
|
||||
{
|
||||
if (op & 0x100)
|
||||
out_byte(IL_OP_PREFIX);
|
||||
out_byte(op & 0xff);
|
||||
}
|
||||
|
||||
/* output an opcode with prefix */
|
||||
static void out_op(int op)
|
||||
{
|
||||
out_op1(op);
|
||||
fprintf(il_outfile, " %s\n", il_opcodes_str[op]);
|
||||
}
|
||||
|
||||
static void out_opb(int op, int c)
|
||||
{
|
||||
out_op1(op);
|
||||
out_byte(c);
|
||||
fprintf(il_outfile, " %s %d\n", il_opcodes_str[op], c);
|
||||
}
|
||||
|
||||
static void out_opi(int op, int c)
|
||||
{
|
||||
out_op1(op);
|
||||
out_le32(c);
|
||||
fprintf(il_outfile, " %s 0x%x\n", il_opcodes_str[op], c);
|
||||
}
|
||||
|
||||
/* XXX: not complete */
|
||||
static void il_type_to_str(char *buf, int buf_size,
|
||||
int t, const char *varstr)
|
||||
{
|
||||
int bt;
|
||||
Sym *s, *sa;
|
||||
char buf1[256];
|
||||
const char *tstr;
|
||||
|
||||
t = t & VT_TYPE;
|
||||
bt = t & VT_BTYPE;
|
||||
buf[0] = '\0';
|
||||
if (t & VT_UNSIGNED)
|
||||
pstrcat(buf, buf_size, "unsigned ");
|
||||
switch(bt) {
|
||||
case VT_VOID:
|
||||
tstr = "void";
|
||||
goto add_tstr;
|
||||
case VT_BOOL:
|
||||
tstr = "bool";
|
||||
goto add_tstr;
|
||||
case VT_BYTE:
|
||||
tstr = "int8";
|
||||
goto add_tstr;
|
||||
case VT_SHORT:
|
||||
tstr = "int16";
|
||||
goto add_tstr;
|
||||
case VT_ENUM:
|
||||
case VT_INT:
|
||||
case VT_LONG:
|
||||
tstr = "int32";
|
||||
goto add_tstr;
|
||||
case VT_LLONG:
|
||||
tstr = "int64";
|
||||
goto add_tstr;
|
||||
case VT_FLOAT:
|
||||
tstr = "float32";
|
||||
goto add_tstr;
|
||||
case VT_DOUBLE:
|
||||
case VT_LDOUBLE:
|
||||
tstr = "float64";
|
||||
add_tstr:
|
||||
pstrcat(buf, buf_size, tstr);
|
||||
break;
|
||||
case VT_STRUCT:
|
||||
tcc_error("structures not handled yet");
|
||||
break;
|
||||
case VT_FUNC:
|
||||
s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
|
||||
il_type_to_str(buf, buf_size, s->t, varstr);
|
||||
pstrcat(buf, buf_size, "(");
|
||||
sa = s->next;
|
||||
while (sa != NULL) {
|
||||
il_type_to_str(buf1, sizeof(buf1), sa->t, NULL);
|
||||
pstrcat(buf, buf_size, buf1);
|
||||
sa = sa->next;
|
||||
if (sa)
|
||||
pstrcat(buf, buf_size, ", ");
|
||||
}
|
||||
pstrcat(buf, buf_size, ")");
|
||||
goto no_var;
|
||||
case VT_PTR:
|
||||
s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
|
||||
pstrcpy(buf1, sizeof(buf1), "*");
|
||||
if (varstr)
|
||||
pstrcat(buf1, sizeof(buf1), varstr);
|
||||
il_type_to_str(buf, buf_size, s->t, buf1);
|
||||
goto no_var;
|
||||
}
|
||||
if (varstr) {
|
||||
pstrcat(buf, buf_size, " ");
|
||||
pstrcat(buf, buf_size, varstr);
|
||||
}
|
||||
no_var: ;
|
||||
}
|
||||
|
||||
|
||||
/* patch relocation entry with value 'val' */
|
||||
void greloc_patch1(Reloc *p, int val)
|
||||
{
|
||||
}
|
||||
|
||||
/* output a symbol and patch all calls to it */
|
||||
void gsym_addr(t, a)
|
||||
{
|
||||
}
|
||||
|
||||
/* output jump and return symbol */
|
||||
static int out_opj(int op, int c)
|
||||
{
|
||||
out_op1(op);
|
||||
out_le32(0);
|
||||
if (c == 0) {
|
||||
c = ind - (int)cur_text_section->data;
|
||||
}
|
||||
fprintf(il_outfile, " %s L%d\n", il_opcodes_str[op], c);
|
||||
return c;
|
||||
}
|
||||
|
||||
void gsym(int t)
|
||||
{
|
||||
fprintf(il_outfile, "L%d:\n", t);
|
||||
}
|
||||
|
||||
/* load 'r' from value 'sv' */
|
||||
void load(int r, SValue *sv)
|
||||
{
|
||||
int v, fc, ft;
|
||||
|
||||
v = sv->r & VT_VALMASK;
|
||||
fc = sv->c.i;
|
||||
ft = sv->t;
|
||||
|
||||
if (sv->r & VT_LVAL) {
|
||||
if (v == VT_LOCAL) {
|
||||
if (fc >= ARG_BASE) {
|
||||
fc -= ARG_BASE;
|
||||
if (fc >= 0 && fc <= 4) {
|
||||
out_op(IL_OP_LDARG_0 + fc);
|
||||
} else if (fc <= 0xff) {
|
||||
out_opb(IL_OP_LDARG_S, fc);
|
||||
} else {
|
||||
out_opi(IL_OP_LDARG, fc);
|
||||
}
|
||||
} else {
|
||||
if (fc >= 0 && fc <= 4) {
|
||||
out_op(IL_OP_LDLOC_0 + fc);
|
||||
} else if (fc <= 0xff) {
|
||||
out_opb(IL_OP_LDLOC_S, fc);
|
||||
} else {
|
||||
out_opi(IL_OP_LDLOC, fc);
|
||||
}
|
||||
}
|
||||
} else if (v == VT_CONST) {
|
||||
/* XXX: handle globals */
|
||||
out_opi(IL_OP_LDSFLD, 0);
|
||||
} else {
|
||||
if ((ft & VT_BTYPE) == VT_FLOAT) {
|
||||
out_op(IL_OP_LDIND_R4);
|
||||
} else if ((ft & VT_BTYPE) == VT_DOUBLE) {
|
||||
out_op(IL_OP_LDIND_R8);
|
||||
} else if ((ft & VT_BTYPE) == VT_LDOUBLE) {
|
||||
out_op(IL_OP_LDIND_R8);
|
||||
} else if ((ft & VT_TYPE) == VT_BYTE)
|
||||
out_op(IL_OP_LDIND_I1);
|
||||
else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED))
|
||||
out_op(IL_OP_LDIND_U1);
|
||||
else if ((ft & VT_TYPE) == VT_SHORT)
|
||||
out_op(IL_OP_LDIND_I2);
|
||||
else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED))
|
||||
out_op(IL_OP_LDIND_U2);
|
||||
else
|
||||
out_op(IL_OP_LDIND_I4);
|
||||
}
|
||||
} else {
|
||||
if (v == VT_CONST) {
|
||||
/* XXX: handle globals */
|
||||
if (fc >= -1 && fc <= 8) {
|
||||
out_op(IL_OP_LDC_I4_M1 + fc + 1);
|
||||
} else {
|
||||
out_opi(IL_OP_LDC_I4, fc);
|
||||
}
|
||||
} else if (v == VT_LOCAL) {
|
||||
if (fc >= ARG_BASE) {
|
||||
fc -= ARG_BASE;
|
||||
if (fc <= 0xff) {
|
||||
out_opb(IL_OP_LDARGA_S, fc);
|
||||
} else {
|
||||
out_opi(IL_OP_LDARGA, fc);
|
||||
}
|
||||
} else {
|
||||
if (fc <= 0xff) {
|
||||
out_opb(IL_OP_LDLOCA_S, fc);
|
||||
} else {
|
||||
out_opi(IL_OP_LDLOCA, fc);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* XXX: do it */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* store register 'r' in lvalue 'v' */
|
||||
void store(int r, SValue *sv)
|
||||
{
|
||||
int v, fc, ft;
|
||||
|
||||
v = sv->r & VT_VALMASK;
|
||||
fc = sv->c.i;
|
||||
ft = sv->t;
|
||||
if (v == VT_LOCAL) {
|
||||
if (fc >= ARG_BASE) {
|
||||
fc -= ARG_BASE;
|
||||
/* XXX: check IL arg store semantics */
|
||||
if (fc <= 0xff) {
|
||||
out_opb(IL_OP_STARG_S, fc);
|
||||
} else {
|
||||
out_opi(IL_OP_STARG, fc);
|
||||
}
|
||||
} else {
|
||||
if (fc >= 0 && fc <= 4) {
|
||||
out_op(IL_OP_STLOC_0 + fc);
|
||||
} else if (fc <= 0xff) {
|
||||
out_opb(IL_OP_STLOC_S, fc);
|
||||
} else {
|
||||
out_opi(IL_OP_STLOC, fc);
|
||||
}
|
||||
}
|
||||
} else if (v == VT_CONST) {
|
||||
/* XXX: handle globals */
|
||||
out_opi(IL_OP_STSFLD, 0);
|
||||
} else {
|
||||
if ((ft & VT_BTYPE) == VT_FLOAT)
|
||||
out_op(IL_OP_STIND_R4);
|
||||
else if ((ft & VT_BTYPE) == VT_DOUBLE)
|
||||
out_op(IL_OP_STIND_R8);
|
||||
else if ((ft & VT_BTYPE) == VT_LDOUBLE)
|
||||
out_op(IL_OP_STIND_R8);
|
||||
else if ((ft & VT_BTYPE) == VT_BYTE)
|
||||
out_op(IL_OP_STIND_I1);
|
||||
else if ((ft & VT_BTYPE) == VT_SHORT)
|
||||
out_op(IL_OP_STIND_I2);
|
||||
else
|
||||
out_op(IL_OP_STIND_I4);
|
||||
}
|
||||
}
|
||||
|
||||
/* start function call and return function call context */
|
||||
void gfunc_start(GFuncContext *c, int func_call)
|
||||
{
|
||||
c->func_call = func_call;
|
||||
}
|
||||
|
||||
/* push function parameter which is in (vtop->t, vtop->c). Stack entry
|
||||
is then popped. */
|
||||
void gfunc_param(GFuncContext *c)
|
||||
{
|
||||
if ((vtop->t & VT_BTYPE) == VT_STRUCT) {
|
||||
tcc_error("structures passed as value not handled yet");
|
||||
} else {
|
||||
/* simply push on stack */
|
||||
gv(RC_ST0);
|
||||
}
|
||||
vtop--;
|
||||
}
|
||||
|
||||
/* generate function call with address in (vtop->t, vtop->c) and free function
|
||||
context. Stack entry is popped */
|
||||
void gfunc_call(GFuncContext *c)
|
||||
{
|
||||
char buf[1024];
|
||||
|
||||
if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
|
||||
/* XXX: more info needed from tcc */
|
||||
il_type_to_str(buf, sizeof(buf), vtop->t, "xxx");
|
||||
fprintf(il_outfile, " call %s\n", buf);
|
||||
} else {
|
||||
/* indirect call */
|
||||
gv(RC_INT);
|
||||
il_type_to_str(buf, sizeof(buf), vtop->t, NULL);
|
||||
fprintf(il_outfile, " calli %s\n", buf);
|
||||
}
|
||||
vtop--;
|
||||
}
|
||||
|
||||
/* generate function prolog of type 't' */
|
||||
void gfunc_prolog(int t)
|
||||
{
|
||||
int addr, u, func_call;
|
||||
Sym *sym;
|
||||
char buf[1024];
|
||||
|
||||
init_outfile();
|
||||
|
||||
/* XXX: pass function name to gfunc_prolog */
|
||||
il_type_to_str(buf, sizeof(buf), t, funcname);
|
||||
fprintf(il_outfile, ".method static %s il managed\n", buf);
|
||||
fprintf(il_outfile, "{\n");
|
||||
/* XXX: cannot do better now */
|
||||
fprintf(il_outfile, " .maxstack %d\n", NB_REGS);
|
||||
fprintf(il_outfile, " .locals (int32, int32, int32, int32, int32, int32, int32, int32)\n");
|
||||
|
||||
if (!strcmp(funcname, "main"))
|
||||
fprintf(il_outfile, " .entrypoint\n");
|
||||
|
||||
sym = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
|
||||
func_call = sym->r;
|
||||
|
||||
addr = ARG_BASE;
|
||||
/* if the function returns a structure, then add an
|
||||
implicit pointer parameter */
|
||||
func_vt = sym->t;
|
||||
func_var = (sym->c == FUNC_ELLIPSIS);
|
||||
if ((func_vt & VT_BTYPE) == VT_STRUCT) {
|
||||
func_vc = addr;
|
||||
addr++;
|
||||
}
|
||||
/* define parameters */
|
||||
while ((sym = sym->next) != NULL) {
|
||||
u = sym->t;
|
||||
sym_push(sym->v & ~SYM_FIELD, u,
|
||||
VT_LOCAL | lvalue_type(sym->type.t), addr);
|
||||
addr++;
|
||||
}
|
||||
}
|
||||
|
||||
/* generate function epilog */
|
||||
void gfunc_epilog(void)
|
||||
{
|
||||
out_op(IL_OP_RET);
|
||||
fprintf(il_outfile, "}\n\n");
|
||||
}
|
||||
|
||||
/* generate a jump to a label */
|
||||
int gjmp(int t)
|
||||
{
|
||||
return out_opj(IL_OP_BR, t);
|
||||
}
|
||||
|
||||
/* generate a jump to a fixed address */
|
||||
void gjmp_addr(int a)
|
||||
{
|
||||
/* XXX: handle syms */
|
||||
out_opi(IL_OP_BR, a);
|
||||
}
|
||||
|
||||
/* generate a test. set 'inv' to invert test. Stack entry is popped */
|
||||
int gtst(int inv, int t)
|
||||
{
|
||||
int v, *p, c;
|
||||
|
||||
v = vtop->r & VT_VALMASK;
|
||||
if (v == VT_CMP) {
|
||||
c = vtop->c.i ^ inv;
|
||||
switch(c) {
|
||||
case TOK_EQ:
|
||||
c = IL_OP_BEQ;
|
||||
break;
|
||||
case TOK_NE:
|
||||
c = IL_OP_BNE_UN;
|
||||
break;
|
||||
case TOK_LT:
|
||||
c = IL_OP_BLT;
|
||||
break;
|
||||
case TOK_LE:
|
||||
c = IL_OP_BLE;
|
||||
break;
|
||||
case TOK_GT:
|
||||
c = IL_OP_BGT;
|
||||
break;
|
||||
case TOK_GE:
|
||||
c = IL_OP_BGE;
|
||||
break;
|
||||
case TOK_ULT:
|
||||
c = IL_OP_BLT_UN;
|
||||
break;
|
||||
case TOK_ULE:
|
||||
c = IL_OP_BLE_UN;
|
||||
break;
|
||||
case TOK_UGT:
|
||||
c = IL_OP_BGT_UN;
|
||||
break;
|
||||
case TOK_UGE:
|
||||
c = IL_OP_BGE_UN;
|
||||
break;
|
||||
}
|
||||
t = out_opj(c, t);
|
||||
} else if (v == VT_JMP || v == VT_JMPI) {
|
||||
/* && or || optimization */
|
||||
if ((v & 1) == inv) {
|
||||
/* insert vtop->c jump list in t */
|
||||
p = &vtop->c.i;
|
||||
while (*p != 0)
|
||||
p = (int *)*p;
|
||||
*p = t;
|
||||
t = vtop->c.i;
|
||||
} else {
|
||||
t = gjmp(t);
|
||||
gsym(vtop->c.i);
|
||||
}
|
||||
}
|
||||
vtop--;
|
||||
return t;
|
||||
}
|
||||
|
||||
/* generate an integer binary operation */
|
||||
void gen_opi(int op)
|
||||
{
|
||||
gv2(RC_ST1, RC_ST0);
|
||||
switch(op) {
|
||||
case '+':
|
||||
out_op(IL_OP_ADD);
|
||||
goto std_op;
|
||||
case '-':
|
||||
out_op(IL_OP_SUB);
|
||||
goto std_op;
|
||||
case '&':
|
||||
out_op(IL_OP_AND);
|
||||
goto std_op;
|
||||
case '^':
|
||||
out_op(IL_OP_XOR);
|
||||
goto std_op;
|
||||
case '|':
|
||||
out_op(IL_OP_OR);
|
||||
goto std_op;
|
||||
case '*':
|
||||
out_op(IL_OP_MUL);
|
||||
goto std_op;
|
||||
case TOK_SHL:
|
||||
out_op(IL_OP_SHL);
|
||||
goto std_op;
|
||||
case TOK_SHR:
|
||||
out_op(IL_OP_SHR_UN);
|
||||
goto std_op;
|
||||
case TOK_SAR:
|
||||
out_op(IL_OP_SHR);
|
||||
goto std_op;
|
||||
case '/':
|
||||
case TOK_PDIV:
|
||||
out_op(IL_OP_DIV);
|
||||
goto std_op;
|
||||
case TOK_UDIV:
|
||||
out_op(IL_OP_DIV_UN);
|
||||
goto std_op;
|
||||
case '%':
|
||||
out_op(IL_OP_REM);
|
||||
goto std_op;
|
||||
case TOK_UMOD:
|
||||
out_op(IL_OP_REM_UN);
|
||||
std_op:
|
||||
vtop--;
|
||||
vtop[0].r = REG_ST0;
|
||||
break;
|
||||
case TOK_EQ:
|
||||
case TOK_NE:
|
||||
case TOK_LT:
|
||||
case TOK_LE:
|
||||
case TOK_GT:
|
||||
case TOK_GE:
|
||||
case TOK_ULT:
|
||||
case TOK_ULE:
|
||||
case TOK_UGT:
|
||||
case TOK_UGE:
|
||||
vtop--;
|
||||
vtop[0].r = VT_CMP;
|
||||
vtop[0].c.i = op;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* generate a floating point operation 'v = t1 op t2' instruction. The
|
||||
two operands are guaranteed to have the same floating point type */
|
||||
void gen_opf(int op)
|
||||
{
|
||||
/* same as integer */
|
||||
gen_opi(op);
|
||||
}
|
||||
|
||||
/* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
|
||||
and 'long long' cases. */
|
||||
void gen_cvt_itof(int t)
|
||||
{
|
||||
gv(RC_ST0);
|
||||
if (t == VT_FLOAT)
|
||||
out_op(IL_OP_CONV_R4);
|
||||
else
|
||||
out_op(IL_OP_CONV_R8);
|
||||
}
|
||||
|
||||
/* convert fp to int 't' type */
|
||||
/* XXX: handle long long case */
|
||||
void gen_cvt_ftoi(int t)
|
||||
{
|
||||
gv(RC_ST0);
|
||||
switch(t) {
|
||||
case VT_INT | VT_UNSIGNED:
|
||||
out_op(IL_OP_CONV_U4);
|
||||
break;
|
||||
case VT_LLONG:
|
||||
out_op(IL_OP_CONV_I8);
|
||||
break;
|
||||
case VT_LLONG | VT_UNSIGNED:
|
||||
out_op(IL_OP_CONV_U8);
|
||||
break;
|
||||
default:
|
||||
out_op(IL_OP_CONV_I4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* convert from one floating point type to another */
|
||||
void gen_cvt_ftof(int t)
|
||||
{
|
||||
gv(RC_ST0);
|
||||
if (t == VT_FLOAT) {
|
||||
out_op(IL_OP_CONV_R4);
|
||||
} else {
|
||||
out_op(IL_OP_CONV_R8);
|
||||
}
|
||||
}
|
||||
|
||||
/* end of CIL code generator */
|
||||
/*************************************************************/
|
||||
|
251
05/tcc-0.9.27/il-opcodes.h
Normal file
251
05/tcc-0.9.27/il-opcodes.h
Normal file
|
@ -0,0 +1,251 @@
|
|||
/*
|
||||
* CIL opcode definition
|
||||
*
|
||||
* Copyright (c) 2002 Fabrice Bellard
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
OP(NOP, "nop", 0x00)
|
||||
OP(BREAK, "break", 0x01)
|
||||
OP(LDARG_0, "ldarg.0", 0x02)
|
||||
OP(LDARG_1, "ldarg.1", 0x03)
|
||||
OP(LDARG_2, "ldarg.2", 0x04)
|
||||
OP(LDARG_3, "ldarg.3", 0x05)
|
||||
OP(LDLOC_0, "ldloc.0", 0x06)
|
||||
OP(LDLOC_1, "ldloc.1", 0x07)
|
||||
OP(LDLOC_2, "ldloc.2", 0x08)
|
||||
OP(LDLOC_3, "ldloc.3", 0x09)
|
||||
OP(STLOC_0, "stloc.0", 0x0a)
|
||||
OP(STLOC_1, "stloc.1", 0x0b)
|
||||
OP(STLOC_2, "stloc.2", 0x0c)
|
||||
OP(STLOC_3, "stloc.3", 0x0d)
|
||||
OP(LDARG_S, "ldarg.s", 0x0e)
|
||||
OP(LDARGA_S, "ldarga.s", 0x0f)
|
||||
OP(STARG_S, "starg.s", 0x10)
|
||||
OP(LDLOC_S, "ldloc.s", 0x11)
|
||||
OP(LDLOCA_S, "ldloca.s", 0x12)
|
||||
OP(STLOC_S, "stloc.s", 0x13)
|
||||
OP(LDNULL, "ldnull", 0x14)
|
||||
OP(LDC_I4_M1, "ldc.i4.m1", 0x15)
|
||||
OP(LDC_I4_0, "ldc.i4.0", 0x16)
|
||||
OP(LDC_I4_1, "ldc.i4.1", 0x17)
|
||||
OP(LDC_I4_2, "ldc.i4.2", 0x18)
|
||||
OP(LDC_I4_3, "ldc.i4.3", 0x19)
|
||||
OP(LDC_I4_4, "ldc.i4.4", 0x1a)
|
||||
OP(LDC_I4_5, "ldc.i4.5", 0x1b)
|
||||
OP(LDC_I4_6, "ldc.i4.6", 0x1c)
|
||||
OP(LDC_I4_7, "ldc.i4.7", 0x1d)
|
||||
OP(LDC_I4_8, "ldc.i4.8", 0x1e)
|
||||
OP(LDC_I4_S, "ldc.i4.s", 0x1f)
|
||||
OP(LDC_I4, "ldc.i4", 0x20)
|
||||
OP(LDC_I8, "ldc.i8", 0x21)
|
||||
OP(LDC_R4, "ldc.r4", 0x22)
|
||||
OP(LDC_R8, "ldc.r8", 0x23)
|
||||
OP(LDPTR, "ldptr", 0x24)
|
||||
OP(DUP, "dup", 0x25)
|
||||
OP(POP, "pop", 0x26)
|
||||
OP(JMP, "jmp", 0x27)
|
||||
OP(CALL, "call", 0x28)
|
||||
OP(CALLI, "calli", 0x29)
|
||||
OP(RET, "ret", 0x2a)
|
||||
OP(BR_S, "br.s", 0x2b)
|
||||
OP(BRFALSE_S, "brfalse.s", 0x2c)
|
||||
OP(BRTRUE_S, "brtrue.s", 0x2d)
|
||||
OP(BEQ_S, "beq.s", 0x2e)
|
||||
OP(BGE_S, "bge.s", 0x2f)
|
||||
OP(BGT_S, "bgt.s", 0x30)
|
||||
OP(BLE_S, "ble.s", 0x31)
|
||||
OP(BLT_S, "blt.s", 0x32)
|
||||
OP(BNE_UN_S, "bne.un.s", 0x33)
|
||||
OP(BGE_UN_S, "bge.un.s", 0x34)
|
||||
OP(BGT_UN_S, "bgt.un.s", 0x35)
|
||||
OP(BLE_UN_S, "ble.un.s", 0x36)
|
||||
OP(BLT_UN_S, "blt.un.s", 0x37)
|
||||
OP(BR, "br", 0x38)
|
||||
OP(BRFALSE, "brfalse", 0x39)
|
||||
OP(BRTRUE, "brtrue", 0x3a)
|
||||
OP(BEQ, "beq", 0x3b)
|
||||
OP(BGE, "bge", 0x3c)
|
||||
OP(BGT, "bgt", 0x3d)
|
||||
OP(BLE, "ble", 0x3e)
|
||||
OP(BLT, "blt", 0x3f)
|
||||
OP(BNE_UN, "bne.un", 0x40)
|
||||
OP(BGE_UN, "bge.un", 0x41)
|
||||
OP(BGT_UN, "bgt.un", 0x42)
|
||||
OP(BLE_UN, "ble.un", 0x43)
|
||||
OP(BLT_UN, "blt.un", 0x44)
|
||||
OP(SWITCH, "switch", 0x45)
|
||||
OP(LDIND_I1, "ldind.i1", 0x46)
|
||||
OP(LDIND_U1, "ldind.u1", 0x47)
|
||||
OP(LDIND_I2, "ldind.i2", 0x48)
|
||||
OP(LDIND_U2, "ldind.u2", 0x49)
|
||||
OP(LDIND_I4, "ldind.i4", 0x4a)
|
||||
OP(LDIND_U4, "ldind.u4", 0x4b)
|
||||
OP(LDIND_I8, "ldind.i8", 0x4c)
|
||||
OP(LDIND_I, "ldind.i", 0x4d)
|
||||
OP(LDIND_R4, "ldind.r4", 0x4e)
|
||||
OP(LDIND_R8, "ldind.r8", 0x4f)
|
||||
OP(LDIND_REF, "ldind.ref", 0x50)
|
||||
OP(STIND_REF, "stind.ref", 0x51)
|
||||
OP(STIND_I1, "stind.i1", 0x52)
|
||||
OP(STIND_I2, "stind.i2", 0x53)
|
||||
OP(STIND_I4, "stind.i4", 0x54)
|
||||
OP(STIND_I8, "stind.i8", 0x55)
|
||||
OP(STIND_R4, "stind.r4", 0x56)
|
||||
OP(STIND_R8, "stind.r8", 0x57)
|
||||
OP(ADD, "add", 0x58)
|
||||
OP(SUB, "sub", 0x59)
|
||||
OP(MUL, "mul", 0x5a)
|
||||
OP(DIV, "div", 0x5b)
|
||||
OP(DIV_UN, "div.un", 0x5c)
|
||||
OP(REM, "rem", 0x5d)
|
||||
OP(REM_UN, "rem.un", 0x5e)
|
||||
OP(AND, "and", 0x5f)
|
||||
OP(OR, "or", 0x60)
|
||||
OP(XOR, "xor", 0x61)
|
||||
OP(SHL, "shl", 0x62)
|
||||
OP(SHR, "shr", 0x63)
|
||||
OP(SHR_UN, "shr.un", 0x64)
|
||||
OP(NEG, "neg", 0x65)
|
||||
OP(NOT, "not", 0x66)
|
||||
OP(CONV_I1, "conv.i1", 0x67)
|
||||
OP(CONV_I2, "conv.i2", 0x68)
|
||||
OP(CONV_I4, "conv.i4", 0x69)
|
||||
OP(CONV_I8, "conv.i8", 0x6a)
|
||||
OP(CONV_R4, "conv.r4", 0x6b)
|
||||
OP(CONV_R8, "conv.r8", 0x6c)
|
||||
OP(CONV_U4, "conv.u4", 0x6d)
|
||||
OP(CONV_U8, "conv.u8", 0x6e)
|
||||
OP(CALLVIRT, "callvirt", 0x6f)
|
||||
OP(CPOBJ, "cpobj", 0x70)
|
||||
OP(LDOBJ, "ldobj", 0x71)
|
||||
OP(LDSTR, "ldstr", 0x72)
|
||||
OP(NEWOBJ, "newobj", 0x73)
|
||||
OP(CASTCLASS, "castclass", 0x74)
|
||||
OP(ISINST, "isinst", 0x75)
|
||||
OP(CONV_R_UN, "conv.r.un", 0x76)
|
||||
OP(ANN_DATA_S, "ann.data.s", 0x77)
|
||||
OP(UNBOX, "unbox", 0x79)
|
||||
OP(THROW, "throw", 0x7a)
|
||||
OP(LDFLD, "ldfld", 0x7b)
|
||||
OP(LDFLDA, "ldflda", 0x7c)
|
||||
OP(STFLD, "stfld", 0x7d)
|
||||
OP(LDSFLD, "ldsfld", 0x7e)
|
||||
OP(LDSFLDA, "ldsflda", 0x7f)
|
||||
OP(STSFLD, "stsfld", 0x80)
|
||||
OP(STOBJ, "stobj", 0x81)
|
||||
OP(CONV_OVF_I1_UN, "conv.ovf.i1.un", 0x82)
|
||||
OP(CONV_OVF_I2_UN, "conv.ovf.i2.un", 0x83)
|
||||
OP(CONV_OVF_I4_UN, "conv.ovf.i4.un", 0x84)
|
||||
OP(CONV_OVF_I8_UN, "conv.ovf.i8.un", 0x85)
|
||||
OP(CONV_OVF_U1_UN, "conv.ovf.u1.un", 0x86)
|
||||
OP(CONV_OVF_U2_UN, "conv.ovf.u2.un", 0x87)
|
||||
OP(CONV_OVF_U4_UN, "conv.ovf.u4.un", 0x88)
|
||||
OP(CONV_OVF_U8_UN, "conv.ovf.u8.un", 0x89)
|
||||
OP(CONV_OVF_I_UN, "conv.ovf.i.un", 0x8a)
|
||||
OP(CONV_OVF_U_UN, "conv.ovf.u.un", 0x8b)
|
||||
OP(BOX, "box", 0x8c)
|
||||
OP(NEWARR, "newarr", 0x8d)
|
||||
OP(LDLEN, "ldlen", 0x8e)
|
||||
OP(LDELEMA, "ldelema", 0x8f)
|
||||
OP(LDELEM_I1, "ldelem.i1", 0x90)
|
||||
OP(LDELEM_U1, "ldelem.u1", 0x91)
|
||||
OP(LDELEM_I2, "ldelem.i2", 0x92)
|
||||
OP(LDELEM_U2, "ldelem.u2", 0x93)
|
||||
OP(LDELEM_I4, "ldelem.i4", 0x94)
|
||||
OP(LDELEM_U4, "ldelem.u4", 0x95)
|
||||
OP(LDELEM_I8, "ldelem.i8", 0x96)
|
||||
OP(LDELEM_I, "ldelem.i", 0x97)
|
||||
OP(LDELEM_R4, "ldelem.r4", 0x98)
|
||||
OP(LDELEM_R8, "ldelem.r8", 0x99)
|
||||
OP(LDELEM_REF, "ldelem.ref", 0x9a)
|
||||
OP(STELEM_I, "stelem.i", 0x9b)
|
||||
OP(STELEM_I1, "stelem.i1", 0x9c)
|
||||
OP(STELEM_I2, "stelem.i2", 0x9d)
|
||||
OP(STELEM_I4, "stelem.i4", 0x9e)
|
||||
OP(STELEM_I8, "stelem.i8", 0x9f)
|
||||
OP(STELEM_R4, "stelem.r4", 0xa0)
|
||||
OP(STELEM_R8, "stelem.r8", 0xa1)
|
||||
OP(STELEM_REF, "stelem.ref", 0xa2)
|
||||
OP(CONV_OVF_I1, "conv.ovf.i1", 0xb3)
|
||||
OP(CONV_OVF_U1, "conv.ovf.u1", 0xb4)
|
||||
OP(CONV_OVF_I2, "conv.ovf.i2", 0xb5)
|
||||
OP(CONV_OVF_U2, "conv.ovf.u2", 0xb6)
|
||||
OP(CONV_OVF_I4, "conv.ovf.i4", 0xb7)
|
||||
OP(CONV_OVF_U4, "conv.ovf.u4", 0xb8)
|
||||
OP(CONV_OVF_I8, "conv.ovf.i8", 0xb9)
|
||||
OP(CONV_OVF_U8, "conv.ovf.u8", 0xba)
|
||||
OP(REFANYVAL, "refanyval", 0xc2)
|
||||
OP(CKFINITE, "ckfinite", 0xc3)
|
||||
OP(MKREFANY, "mkrefany", 0xc6)
|
||||
OP(ANN_CALL, "ann.call", 0xc7)
|
||||
OP(ANN_CATCH, "ann.catch", 0xc8)
|
||||
OP(ANN_DEAD, "ann.dead", 0xc9)
|
||||
OP(ANN_HOISTED, "ann.hoisted", 0xca)
|
||||
OP(ANN_HOISTED_CALL, "ann.hoisted.call", 0xcb)
|
||||
OP(ANN_LAB, "ann.lab", 0xcc)
|
||||
OP(ANN_DEF, "ann.def", 0xcd)
|
||||
OP(ANN_REF_S, "ann.ref.s", 0xce)
|
||||
OP(ANN_PHI, "ann.phi", 0xcf)
|
||||
OP(LDTOKEN, "ldtoken", 0xd0)
|
||||
OP(CONV_U2, "conv.u2", 0xd1)
|
||||
OP(CONV_U1, "conv.u1", 0xd2)
|
||||
OP(CONV_I, "conv.i", 0xd3)
|
||||
OP(CONV_OVF_I, "conv.ovf.i", 0xd4)
|
||||
OP(CONV_OVF_U, "conv.ovf.u", 0xd5)
|
||||
OP(ADD_OVF, "add.ovf", 0xd6)
|
||||
OP(ADD_OVF_UN, "add.ovf.un", 0xd7)
|
||||
OP(MUL_OVF, "mul.ovf", 0xd8)
|
||||
OP(MUL_OVF_UN, "mul.ovf.un", 0xd9)
|
||||
OP(SUB_OVF, "sub.ovf", 0xda)
|
||||
OP(SUB_OVF_UN, "sub.ovf.un", 0xdb)
|
||||
OP(ENDFINALLY, "endfinally", 0xdc)
|
||||
OP(LEAVE, "leave", 0xdd)
|
||||
OP(LEAVE_S, "leave.s", 0xde)
|
||||
OP(STIND_I, "stind.i", 0xdf)
|
||||
OP(CONV_U, "conv.u", 0xe0)
|
||||
|
||||
/* prefix instructions. we use an opcode >= 256 to ease coding */
|
||||
|
||||
OP(ARGLIST, "arglist", 0x100)
|
||||
OP(CEQ, "ceq", 0x101)
|
||||
OP(CGT, "cgt", 0x102)
|
||||
OP(CGT_UN, "cgt.un", 0x103)
|
||||
OP(CLT, "clt", 0x104)
|
||||
OP(CLT_UN, "clt.un", 0x105)
|
||||
OP(LDFTN, "ldftn", 0x106)
|
||||
OP(LDVIRTFTN, "ldvirtftn", 0x107)
|
||||
OP(JMPI, "jmpi", 0x108)
|
||||
OP(LDARG, "ldarg", 0x109)
|
||||
OP(LDARGA, "ldarga", 0x10a)
|
||||
OP(STARG, "starg", 0x10b)
|
||||
OP(LDLOC, "ldloc", 0x10c)
|
||||
OP(LDLOCA, "ldloca", 0x10d)
|
||||
OP(STLOC, "stloc", 0x10e)
|
||||
OP(LOCALLOC, "localloc", 0x10f)
|
||||
OP(ENDFILTER, "endfilter", 0x111)
|
||||
OP(UNALIGNED, "unaligned", 0x112)
|
||||
OP(VOLATILE, "volatile", 0x113)
|
||||
OP(TAIL, "tail", 0x114)
|
||||
OP(INITOBJ, "initobj", 0x115)
|
||||
OP(ANN_LIVE, "ann.live", 0x116)
|
||||
OP(CPBLK, "cpblk", 0x117)
|
||||
OP(INITBLK, "initblk", 0x118)
|
||||
OP(ANN_REF, "ann.ref", 0x119)
|
||||
OP(RETHROW, "rethrow", 0x11a)
|
||||
OP(SIZEOF, "sizeof", 0x11c)
|
||||
OP(REFANYTYPE, "refanytype", 0x11d)
|
||||
OP(ANN_DATA, "ann.data", 0x122)
|
||||
OP(ANN_ARG, "ann.arg", 0x123)
|
57
05/tcc-0.9.27/include/float.h
Normal file
57
05/tcc-0.9.27/include/float.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
#ifndef _FLOAT_H_
|
||||
#define _FLOAT_H_
|
||||
|
||||
#define FLT_RADIX 2
|
||||
|
||||
/* IEEE float */
|
||||
#define FLT_MANT_DIG 24
|
||||
#define FLT_DIG 6
|
||||
#define FLT_ROUNDS 1
|
||||
#define FLT_EPSILON 1.19209290e-07F
|
||||
#define FLT_MIN_EXP (-125)
|
||||
#define FLT_MIN 1.17549435e-38F
|
||||
#define FLT_MIN_10_EXP (-37)
|
||||
#define FLT_MAX_EXP 128
|
||||
#define FLT_MAX 3.40282347e+38F
|
||||
#define FLT_MAX_10_EXP 38
|
||||
|
||||
/* IEEE double */
|
||||
#define DBL_MANT_DIG 53
|
||||
#define DBL_DIG 15
|
||||
#define DBL_EPSILON 2.2204460492503131e-16
|
||||
#define DBL_MIN_EXP (-1021)
|
||||
#define DBL_MIN 2.2250738585072014e-308
|
||||
#define DBL_MIN_10_EXP (-307)
|
||||
#define DBL_MAX_EXP 1024
|
||||
#define DBL_MAX 1.7976931348623157e+308
|
||||
#define DBL_MAX_10_EXP 308
|
||||
|
||||
/* horrible intel long double */
|
||||
#if defined __i386__ || defined __x86_64__
|
||||
|
||||
#define LDBL_MANT_DIG 64
|
||||
#define LDBL_DIG 18
|
||||
#define LDBL_EPSILON 1.08420217248550443401e-19L
|
||||
#define LDBL_MIN_EXP (-16381)
|
||||
#define LDBL_MIN 3.36210314311209350626e-4932L
|
||||
#define LDBL_MIN_10_EXP (-4931)
|
||||
#define LDBL_MAX_EXP 16384
|
||||
#define LDBL_MAX 1.18973149535723176502e+4932L
|
||||
#define LDBL_MAX_10_EXP 4932
|
||||
|
||||
#else
|
||||
|
||||
/* same as IEEE double */
|
||||
#define LDBL_MANT_DIG 53
|
||||
#define LDBL_DIG 15
|
||||
#define LDBL_EPSILON 2.2204460492503131e-16
|
||||
#define LDBL_MIN_EXP (-1021)
|
||||
#define LDBL_MIN 2.2250738585072014e-308
|
||||
#define LDBL_MIN_10_EXP (-307)
|
||||
#define LDBL_MAX_EXP 1024
|
||||
#define LDBL_MAX 1.7976931348623157e+308
|
||||
#define LDBL_MAX_10_EXP 308
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _FLOAT_H_ */
|
79
05/tcc-0.9.27/include/stdarg.h
Normal file
79
05/tcc-0.9.27/include/stdarg.h
Normal file
|
@ -0,0 +1,79 @@
|
|||
#ifndef _STDARG_H
|
||||
#define _STDARG_H
|
||||
|
||||
#ifdef __x86_64__
|
||||
#ifndef _WIN64
|
||||
|
||||
//This should be in sync with the declaration on our lib/libtcc1.c
|
||||
/* GCC compatible definition of va_list. */
|
||||
typedef struct {
|
||||
unsigned int gp_offset;
|
||||
unsigned int fp_offset;
|
||||
union {
|
||||
unsigned int overflow_offset;
|
||||
char *overflow_arg_area;
|
||||
};
|
||||
char *reg_save_area;
|
||||
} __va_list_struct;
|
||||
|
||||
typedef __va_list_struct va_list[1];
|
||||
|
||||
void __va_start(__va_list_struct *ap, void *fp);
|
||||
void *__va_arg(__va_list_struct *ap, int arg_type, int size, int align);
|
||||
|
||||
#define va_start(ap, last) __va_start(ap, __builtin_frame_address(0))
|
||||
#define va_arg(ap, type) \
|
||||
(*(type *)(__va_arg(ap, __builtin_va_arg_types(type), sizeof(type), __alignof__(type))))
|
||||
#define va_copy(dest, src) (*(dest) = *(src))
|
||||
#define va_end(ap)
|
||||
|
||||
/* avoid conflicting definition for va_list on Macs. */
|
||||
#define _VA_LIST_T
|
||||
|
||||
#else /* _WIN64 */
|
||||
typedef char *va_list;
|
||||
#define va_start(ap,last) __builtin_va_start(ap,last)
|
||||
#define va_arg(ap, t) ((sizeof(t) > 8 || (sizeof(t) & (sizeof(t) - 1))) \
|
||||
? **(t **)((ap += 8) - 8) : *(t *)((ap += 8) - 8))
|
||||
#define va_copy(dest, src) ((dest) = (src))
|
||||
#define va_end(ap)
|
||||
#endif
|
||||
|
||||
#elif __arm__
|
||||
typedef char *va_list;
|
||||
#define _tcc_alignof(type) ((int)&((struct {char c;type x;} *)0)->x)
|
||||
#define _tcc_align(addr,type) (((unsigned)addr + _tcc_alignof(type) - 1) \
|
||||
& ~(_tcc_alignof(type) - 1))
|
||||
#define va_start(ap,last) ap = ((char *)&(last)) + ((sizeof(last)+3)&~3)
|
||||
#define va_arg(ap,type) (ap = (void *) ((_tcc_align(ap,type)+sizeof(type)+3) \
|
||||
&~3), *(type *)(ap - ((sizeof(type)+3)&~3)))
|
||||
#define va_copy(dest, src) (dest) = (src)
|
||||
#define va_end(ap)
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
typedef struct {
|
||||
void *__stack;
|
||||
void *__gr_top;
|
||||
void *__vr_top;
|
||||
int __gr_offs;
|
||||
int __vr_offs;
|
||||
} va_list;
|
||||
#define va_start(ap, last) __va_start(ap, last)
|
||||
#define va_arg(ap, type) __va_arg(ap, type)
|
||||
#define va_end(ap)
|
||||
#define va_copy(dest, src) ((dest) = (src))
|
||||
|
||||
#else /* __i386__ */
|
||||
typedef char *va_list;
|
||||
/* only correct for i386 */
|
||||
#define va_start(ap,last) ap = ((char *)&(last)) + ((sizeof(last)+3)&~3)
|
||||
#define va_arg(ap,type) (ap += (sizeof(type)+3)&~3, *(type *)(ap - ((sizeof(type)+3)&~3)))
|
||||
#define va_copy(dest, src) (dest) = (src)
|
||||
#define va_end(ap)
|
||||
#endif
|
||||
|
||||
/* fix a buggy dependency on GCC in libio.h */
|
||||
typedef va_list __gnuc_va_list;
|
||||
#define _VA_LIST_DEFINED
|
||||
|
||||
#endif /* _STDARG_H */
|
11
05/tcc-0.9.27/include/stdbool.h
Normal file
11
05/tcc-0.9.27/include/stdbool.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
#ifndef _STDBOOL_H
|
||||
#define _STDBOOL_H
|
||||
|
||||
/* ISOC99 boolean */
|
||||
|
||||
#define bool _Bool
|
||||
#define true 1
|
||||
#define false 0
|
||||
#define __bool_true_false_are_defined 1
|
||||
|
||||
#endif /* _STDBOOL_H */
|
54
05/tcc-0.9.27/include/stddef.h
Normal file
54
05/tcc-0.9.27/include/stddef.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
#ifndef _STDDEF_H
|
||||
#define _STDDEF_H
|
||||
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
typedef __PTRDIFF_TYPE__ ssize_t;
|
||||
typedef __WCHAR_TYPE__ wchar_t;
|
||||
typedef __PTRDIFF_TYPE__ ptrdiff_t;
|
||||
typedef __PTRDIFF_TYPE__ intptr_t;
|
||||
typedef __SIZE_TYPE__ uintptr_t;
|
||||
|
||||
#ifndef __int8_t_defined
|
||||
#define __int8_t_defined
|
||||
typedef signed char int8_t;
|
||||
typedef signed short int int16_t;
|
||||
typedef signed int int32_t;
|
||||
#ifdef __LP64__
|
||||
typedef signed long int int64_t;
|
||||
#else
|
||||
typedef signed long long int int64_t;
|
||||
#endif
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short int uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
#ifdef __LP64__
|
||||
typedef unsigned long int uint64_t;
|
||||
#else
|
||||
typedef unsigned long long int uint64_t;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL ((void*)0)
|
||||
#endif
|
||||
|
||||
#define offsetof(type, field) ((size_t)&((type *)0)->field)
|
||||
|
||||
void *alloca(size_t size);
|
||||
|
||||
#endif
|
||||
|
||||
/* Older glibc require a wint_t from <stddef.h> (when requested
|
||||
by __need_wint_t, as otherwise stddef.h isn't allowed to
|
||||
define this type). Note that this must be outside the normal
|
||||
_STDDEF_H guard, so that it works even when we've included the file
|
||||
already (without requiring wint_t). Some other libs define _WINT_T
|
||||
if they've already provided that type, so we can use that as guard.
|
||||
TCC defines __WINT_TYPE__ for us. */
|
||||
#if defined (__need_wint_t)
|
||||
#ifndef _WINT_T
|
||||
#define _WINT_T
|
||||
typedef __WINT_TYPE__ wint_t;
|
||||
#endif
|
||||
#undef __need_wint_t
|
||||
#endif
|
12
05/tcc-0.9.27/include/varargs.h
Normal file
12
05/tcc-0.9.27/include/varargs.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
/**
|
||||
* This file has no copyright assigned and is placed in the Public Domain.
|
||||
* This file is part of the w64 mingw-runtime package.
|
||||
* No warranty is given; refer to the file DISCLAIMER within this package.
|
||||
*/
|
||||
#ifndef _VARARGS_H
|
||||
#define _VARARGS_H
|
||||
|
||||
#error "TinyCC no longer implements <varargs.h>."
|
||||
#error "Revise your code to use <stdarg.h>."
|
||||
|
||||
#endif
|
73
05/tcc-0.9.27/lib/Makefile
Normal file
73
05/tcc-0.9.27/lib/Makefile
Normal file
|
@ -0,0 +1,73 @@
|
|||
#
|
||||
# Tiny C Compiler Makefile for libtcc1.a
|
||||
#
|
||||
|
||||
TOP = ..
|
||||
include $(TOP)/Makefile
|
||||
VPATH = $(TOPSRC)/lib $(TOPSRC)/win32/lib
|
||||
T = $(or $(CROSS_TARGET),$(NATIVE_TARGET),unknown)
|
||||
X = $(if $(CROSS_TARGET),$(CROSS_TARGET)-)
|
||||
BIN = $(TOP)/$(X)libtcc1.a
|
||||
|
||||
XTCC ?= $(TOP)/$(X)tcc$(EXESUF)
|
||||
XCC = $(XTCC)
|
||||
XAR = $(XTCC) -ar
|
||||
XFLAGS-unx = -B$(TOPSRC)
|
||||
XFLAGS-win = -B$(TOPSRC)/win32 -I$(TOPSRC)/include
|
||||
XFLAGS = $(XFLAGS$(XCFG))
|
||||
XCFG = $(or $(findstring -win,$T),-unx)
|
||||
|
||||
# in order to use gcc, tyoe: make <target>-libtcc1-usegcc=yes
|
||||
arm-libtcc1-usegcc ?= no
|
||||
|
||||
ifeq "$($(T)-libtcc1-usegcc)" "yes"
|
||||
XCC = $(CC)
|
||||
XAR = $(AR)
|
||||
XFLAGS = $(CFLAGS) -fPIC
|
||||
endif
|
||||
|
||||
# only for native compiler
|
||||
$(X)BCHECK_O = bcheck.o
|
||||
|
||||
ifeq ($(CONFIG_musl)$(CONFIG_uClibc),yes)
|
||||
BCHECK_O =
|
||||
endif
|
||||
|
||||
ifdef CONFIG_OSX
|
||||
XFLAGS += -D_ANSI_SOURCE
|
||||
endif
|
||||
|
||||
I386_O = libtcc1.o alloca86.o alloca86-bt.o
|
||||
X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o
|
||||
ARM_O = libtcc1.o armeabi.o alloca-arm.o armflush.o
|
||||
ARM64_O = lib-arm64.o
|
||||
WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o
|
||||
|
||||
OBJ-i386 = $(I386_O) $(BCHECK_O)
|
||||
OBJ-x86_64 = $(X86_64_O) va_list.o $(BCHECK_O)
|
||||
OBJ-x86_64-osx = $(X86_64_O) va_list.o
|
||||
OBJ-i386-win32 = $(I386_O) chkstk.o bcheck.o $(WIN_O)
|
||||
OBJ-x86_64-win32 = $(X86_64_O) chkstk.o bcheck.o $(WIN_O)
|
||||
OBJ-arm64 = $(ARM64_O)
|
||||
OBJ-arm = $(ARM_O)
|
||||
OBJ-arm-fpa = $(ARM_O)
|
||||
OBJ-arm-fpa-ld = $(ARM_O)
|
||||
OBJ-arm-vfp = $(ARM_O)
|
||||
OBJ-arm-eabi = $(ARM_O)
|
||||
OBJ-arm-eabihf = $(ARM_O)
|
||||
OBJ-arm-wince = $(ARM_O) $(WIN_O)
|
||||
|
||||
$(BIN) : $(patsubst %.o,$(X)%.o,$(OBJ-$T))
|
||||
$(XAR) rcs $@ $^
|
||||
|
||||
$(X)%.o : %.c
|
||||
$(XCC) -c $< -o $@ $(XFLAGS)
|
||||
|
||||
$(X)%.o : %.S
|
||||
$(XCC) -c $< -o $@ $(XFLAGS)
|
||||
|
||||
$(X)crt1w.o : crt1.c
|
||||
$(X)wincrt1w.o : wincrt1.c
|
||||
|
||||
clean :
|
||||
rm -f *.a *.o $(BIN)
|
17
05/tcc-0.9.27/lib/alloca-arm.S
Normal file
17
05/tcc-0.9.27/lib/alloca-arm.S
Normal file
|
@ -0,0 +1,17 @@
|
|||
.text
|
||||
.align 2
|
||||
.global alloca
|
||||
.type alloca, %function
|
||||
alloca:
|
||||
#ifdef __TINYC__
|
||||
.int 0xe060d00d
|
||||
.int 0xe3cdd007
|
||||
.int 0xe1a0000d
|
||||
.int 0xe1a0f00e
|
||||
#else
|
||||
rsb sp, r0, sp
|
||||
bic sp, sp, #7
|
||||
mov r0, sp
|
||||
mov pc, lr
|
||||
#endif
|
||||
.size alloca, .-alloca
|
47
05/tcc-0.9.27/lib/alloca86-bt.S
Normal file
47
05/tcc-0.9.27/lib/alloca86-bt.S
Normal file
|
@ -0,0 +1,47 @@
|
|||
/* ---------------------------------------------- */
|
||||
/* alloca86-bt.S */
|
||||
|
||||
.globl __bound_alloca
|
||||
|
||||
__bound_alloca:
|
||||
pop %edx
|
||||
pop %eax
|
||||
mov %eax, %ecx
|
||||
add $3,%eax
|
||||
and $-4,%eax
|
||||
jz p6
|
||||
|
||||
#ifdef _WIN32
|
||||
p4:
|
||||
cmp $4096,%eax
|
||||
jbe p5
|
||||
test %eax,-4096(%esp)
|
||||
sub $4096,%esp
|
||||
sub $4096,%eax
|
||||
jmp p4
|
||||
|
||||
p5:
|
||||
#endif
|
||||
|
||||
sub %eax,%esp
|
||||
mov %esp,%eax
|
||||
|
||||
push %edx
|
||||
push %eax
|
||||
push %ecx
|
||||
push %eax
|
||||
call __bound_new_region
|
||||
add $8, %esp
|
||||
pop %eax
|
||||
pop %edx
|
||||
|
||||
p6:
|
||||
push %edx
|
||||
push %edx
|
||||
ret
|
||||
|
||||
/* mark stack as nonexecutable */
|
||||
#if defined __ELF__ && defined __linux__
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
#endif
|
||||
/* ---------------------------------------------- */
|
31
05/tcc-0.9.27/lib/alloca86.S
Normal file
31
05/tcc-0.9.27/lib/alloca86.S
Normal file
|
@ -0,0 +1,31 @@
|
|||
/* ---------------------------------------------- */
|
||||
/* alloca86.S */
|
||||
|
||||
.globl alloca
|
||||
|
||||
alloca:
|
||||
pop %edx
|
||||
pop %eax
|
||||
add $3,%eax
|
||||
and $-4,%eax
|
||||
jz p3
|
||||
|
||||
#ifdef _WIN32
|
||||
p1:
|
||||
cmp $4096,%eax
|
||||
jbe p2
|
||||
test %eax,-4096(%esp)
|
||||
sub $4096,%esp
|
||||
sub $4096,%eax
|
||||
jmp p1
|
||||
p2:
|
||||
#endif
|
||||
|
||||
sub %eax,%esp
|
||||
mov %esp,%eax
|
||||
p3:
|
||||
push %edx
|
||||
push %edx
|
||||
ret
|
||||
|
||||
/* ---------------------------------------------- */
|
56
05/tcc-0.9.27/lib/alloca86_64-bt.S
Normal file
56
05/tcc-0.9.27/lib/alloca86_64-bt.S
Normal file
|
@ -0,0 +1,56 @@
|
|||
/* ---------------------------------------------- */
|
||||
/* alloca86_64.S */
|
||||
|
||||
.globl __bound_alloca
|
||||
__bound_alloca:
|
||||
|
||||
#ifdef _WIN32
|
||||
# bound checking is not implemented
|
||||
pop %rdx
|
||||
mov %rcx,%rax
|
||||
add $15,%rax
|
||||
and $-16,%rax
|
||||
jz p3
|
||||
|
||||
p1:
|
||||
cmp $4096,%rax
|
||||
jbe p2
|
||||
test %rax,-4096(%rsp)
|
||||
sub $4096,%rsp
|
||||
sub $4096,%rax
|
||||
jmp p1
|
||||
p2:
|
||||
|
||||
sub %rax,%rsp
|
||||
mov %rsp,%rax
|
||||
add $32,%rax
|
||||
|
||||
p3:
|
||||
push %rdx
|
||||
ret
|
||||
#else
|
||||
pop %rdx
|
||||
mov %rdi,%rax
|
||||
mov %rax,%rsi # size, a second parm to the __bound_new_region
|
||||
|
||||
add $15,%rax
|
||||
and $-16,%rax
|
||||
jz p3
|
||||
|
||||
|
||||
sub %rax,%rsp
|
||||
mov %rsp,%rdi # pointer, a first parm to the __bound_new_region
|
||||
mov %rsp,%rax
|
||||
|
||||
push %rdx
|
||||
push %rax
|
||||
call __bound_new_region
|
||||
pop %rax
|
||||
pop %rdx
|
||||
|
||||
p3:
|
||||
push %rdx
|
||||
ret
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------- */
|
34
05/tcc-0.9.27/lib/alloca86_64.S
Normal file
34
05/tcc-0.9.27/lib/alloca86_64.S
Normal file
|
@ -0,0 +1,34 @@
|
|||
/* ---------------------------------------------- */
|
||||
/* alloca86_64.S */
|
||||
|
||||
.globl alloca
|
||||
|
||||
alloca:
|
||||
pop %rdx
|
||||
#ifdef _WIN32
|
||||
mov %rcx,%rax
|
||||
#else
|
||||
mov %rdi,%rax
|
||||
#endif
|
||||
add $15,%rax
|
||||
and $-16,%rax
|
||||
jz p3
|
||||
|
||||
#ifdef _WIN32
|
||||
p1:
|
||||
cmp $4096,%rax
|
||||
jbe p2
|
||||
test %rax,-4096(%rsp)
|
||||
sub $4096,%rsp
|
||||
sub $4096,%rax
|
||||
jmp p1
|
||||
p2:
|
||||
#endif
|
||||
|
||||
sub %rax,%rsp
|
||||
mov %rsp,%rax
|
||||
p3:
|
||||
push %rdx
|
||||
ret
|
||||
|
||||
/* ---------------------------------------------- */
|
501
05/tcc-0.9.27/lib/armeabi.c
Normal file
501
05/tcc-0.9.27/lib/armeabi.c
Normal file
|
@ -0,0 +1,501 @@
|
|||
/* TCC ARM runtime EABI
|
||||
Copyright (C) 2013 Thomas Preud'homme
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.*/
|
||||
|
||||
#ifdef __TINYC__
|
||||
#define INT_MIN (-2147483647 - 1)
|
||||
#define INT_MAX 2147483647
|
||||
#define UINT_MAX 0xffffffff
|
||||
#define LONG_MIN (-2147483647L - 1)
|
||||
#define LONG_MAX 2147483647L
|
||||
#define ULONG_MAX 0xffffffffUL
|
||||
#define LLONG_MAX 9223372036854775807LL
|
||||
#define LLONG_MIN (-9223372036854775807LL - 1)
|
||||
#define ULLONG_MAX 0xffffffffffffffffULL
|
||||
#else
|
||||
#include <limits.h>
|
||||
#endif
|
||||
|
||||
/* We rely on the little endianness and EABI calling convention for this to
|
||||
work */
|
||||
|
||||
typedef struct double_unsigned_struct {
|
||||
unsigned low;
|
||||
unsigned high;
|
||||
} double_unsigned_struct;
|
||||
|
||||
typedef struct unsigned_int_struct {
|
||||
unsigned low;
|
||||
int high;
|
||||
} unsigned_int_struct;
|
||||
|
||||
#define REGS_RETURN(name, type) \
|
||||
void name ## _return(type ret) {}
|
||||
|
||||
|
||||
/* Float helper functions */
|
||||
|
||||
#define FLOAT_EXP_BITS 8
|
||||
#define FLOAT_FRAC_BITS 23
|
||||
|
||||
#define DOUBLE_EXP_BITS 11
|
||||
#define DOUBLE_FRAC_BITS 52
|
||||
|
||||
#define ONE_EXP(type) ((1 << (type ## _EXP_BITS - 1)) - 1)
|
||||
|
||||
REGS_RETURN(unsigned_int_struct, unsigned_int_struct)
|
||||
REGS_RETURN(double_unsigned_struct, double_unsigned_struct)
|
||||
|
||||
/* float -> integer: (sign) 1.fraction x 2^(exponent - exp_for_one) */
|
||||
|
||||
|
||||
/* float to [unsigned] long long conversion */
|
||||
#define DEFINE__AEABI_F2XLZ(name, with_sign) \
|
||||
void __aeabi_ ## name(unsigned val) \
|
||||
{ \
|
||||
int exp, high_shift, sign; \
|
||||
double_unsigned_struct ret; \
|
||||
\
|
||||
/* compute sign */ \
|
||||
sign = val >> 31; \
|
||||
\
|
||||
/* compute real exponent */ \
|
||||
exp = val >> FLOAT_FRAC_BITS; \
|
||||
exp &= (1 << FLOAT_EXP_BITS) - 1; \
|
||||
exp -= ONE_EXP(FLOAT); \
|
||||
\
|
||||
/* undefined behavior if truncated value cannot be represented */ \
|
||||
if (with_sign) { \
|
||||
if (exp > 62) /* |val| too big, double cannot represent LLONG_MAX */ \
|
||||
return; \
|
||||
} else { \
|
||||
if ((sign && exp >= 0) || exp > 63) /* if val < 0 || val too big */ \
|
||||
return; \
|
||||
} \
|
||||
\
|
||||
val &= (1 << FLOAT_FRAC_BITS) - 1; \
|
||||
if (exp >= 32) { \
|
||||
ret.high = 1 << (exp - 32); \
|
||||
if (exp - 32 >= FLOAT_FRAC_BITS) { \
|
||||
ret.high |= val << (exp - 32 - FLOAT_FRAC_BITS); \
|
||||
ret.low = 0; \
|
||||
} else { \
|
||||
high_shift = FLOAT_FRAC_BITS - (exp - 32); \
|
||||
ret.high |= val >> high_shift; \
|
||||
ret.low = val << (32 - high_shift); \
|
||||
} \
|
||||
} else { \
|
||||
ret.high = 0; \
|
||||
ret.low = 1 << exp; \
|
||||
if (exp > FLOAT_FRAC_BITS) \
|
||||
ret.low |= val << (exp - FLOAT_FRAC_BITS); \
|
||||
else \
|
||||
ret.low |= val >> (FLOAT_FRAC_BITS - exp); \
|
||||
} \
|
||||
\
|
||||
/* encode negative integer using 2's complement */ \
|
||||
if (with_sign && sign) { \
|
||||
ret.low = ~ret.low; \
|
||||
ret.high = ~ret.high; \
|
||||
if (ret.low == UINT_MAX) { \
|
||||
ret.low = 0; \
|
||||
ret.high++; \
|
||||
} else \
|
||||
ret.low++; \
|
||||
} \
|
||||
\
|
||||
double_unsigned_struct_return(ret); \
|
||||
}
|
||||
|
||||
/* float to unsigned long long conversion */
|
||||
DEFINE__AEABI_F2XLZ(f2ulz, 0)
|
||||
|
||||
/* float to long long conversion */
|
||||
DEFINE__AEABI_F2XLZ(f2lz, 1)
|
||||
|
||||
/* double to [unsigned] long long conversion */
|
||||
#define DEFINE__AEABI_D2XLZ(name, with_sign) \
|
||||
void __aeabi_ ## name(double_unsigned_struct val) \
|
||||
{ \
|
||||
int exp, high_shift, sign; \
|
||||
double_unsigned_struct ret; \
|
||||
\
|
||||
/* compute sign */ \
|
||||
sign = val.high >> 31; \
|
||||
\
|
||||
/* compute real exponent */ \
|
||||
exp = (val.high >> (DOUBLE_FRAC_BITS - 32)); \
|
||||
exp &= (1 << DOUBLE_EXP_BITS) - 1; \
|
||||
exp -= ONE_EXP(DOUBLE); \
|
||||
\
|
||||
/* undefined behavior if truncated value cannot be represented */ \
|
||||
if (with_sign) { \
|
||||
if (exp > 62) /* |val| too big, double cannot represent LLONG_MAX */ \
|
||||
return; \
|
||||
} else { \
|
||||
if ((sign && exp >= 0) || exp > 63) /* if val < 0 || val too big */ \
|
||||
return; \
|
||||
} \
|
||||
\
|
||||
val.high &= (1 << (DOUBLE_FRAC_BITS - 32)) - 1; \
|
||||
if (exp >= 32) { \
|
||||
ret.high = 1 << (exp - 32); \
|
||||
if (exp >= DOUBLE_FRAC_BITS) { \
|
||||
high_shift = exp - DOUBLE_FRAC_BITS; \
|
||||
ret.high |= val.high << high_shift; \
|
||||
ret.high |= val.low >> (32 - high_shift); \
|
||||
ret.low = val.low << high_shift; \
|
||||
} else { \
|
||||
high_shift = DOUBLE_FRAC_BITS - exp; \
|
||||
ret.high |= val.high >> high_shift; \
|
||||
ret.low = val.high << (32 - high_shift); \
|
||||
ret.low |= val.low >> high_shift; \
|
||||
} \
|
||||
} else { \
|
||||
ret.high = 0; \
|
||||
ret.low = 1 << exp; \
|
||||
if (exp > DOUBLE_FRAC_BITS - 32) { \
|
||||
high_shift = exp - DOUBLE_FRAC_BITS - 32; \
|
||||
ret.low |= val.high << high_shift; \
|
||||
ret.low |= val.low >> (32 - high_shift); \
|
||||
} else \
|
||||
ret.low |= val.high >> (DOUBLE_FRAC_BITS - 32 - exp); \
|
||||
} \
|
||||
\
|
||||
/* encode negative integer using 2's complement */ \
|
||||
if (with_sign && sign) { \
|
||||
ret.low = ~ret.low; \
|
||||
ret.high = ~ret.high; \
|
||||
if (ret.low == UINT_MAX) { \
|
||||
ret.low = 0; \
|
||||
ret.high++; \
|
||||
} else \
|
||||
ret.low++; \
|
||||
} \
|
||||
\
|
||||
double_unsigned_struct_return(ret); \
|
||||
}
|
||||
|
||||
/* double to unsigned long long conversion */
|
||||
DEFINE__AEABI_D2XLZ(d2ulz, 0)
|
||||
|
||||
/* double to long long conversion */
|
||||
DEFINE__AEABI_D2XLZ(d2lz, 1)
|
||||
|
||||
/* long long to float conversion */
|
||||
#define DEFINE__AEABI_XL2F(name, with_sign) \
|
||||
unsigned __aeabi_ ## name(unsigned long long v) \
|
||||
{ \
|
||||
int s /* shift */, flb /* first lost bit */, sign = 0; \
|
||||
unsigned p = 0 /* power */, ret; \
|
||||
double_unsigned_struct val; \
|
||||
\
|
||||
/* fraction in negative float is encoded in 1's complement */ \
|
||||
if (with_sign && (v & (1ULL << 63))) { \
|
||||
sign = 1; \
|
||||
v = ~v + 1; \
|
||||
} \
|
||||
val.low = v; \
|
||||
val.high = v >> 32; \
|
||||
/* fill fraction bits */ \
|
||||
for (s = 31, p = 1 << 31; p && !(val.high & p); s--, p >>= 1); \
|
||||
if (p) { \
|
||||
ret = val.high & (p - 1); \
|
||||
if (s < FLOAT_FRAC_BITS) { \
|
||||
ret <<= FLOAT_FRAC_BITS - s; \
|
||||
ret |= val.low >> (32 - (FLOAT_FRAC_BITS - s)); \
|
||||
flb = (val.low >> (32 - (FLOAT_FRAC_BITS - s - 1))) & 1; \
|
||||
} else { \
|
||||
flb = (ret >> (s - FLOAT_FRAC_BITS - 1)) & 1; \
|
||||
ret >>= s - FLOAT_FRAC_BITS; \
|
||||
} \
|
||||
s += 32; \
|
||||
} else { \
|
||||
for (s = 31, p = 1 << 31; p && !(val.low & p); s--, p >>= 1); \
|
||||
if (p) { \
|
||||
ret = val.low & (p - 1); \
|
||||
if (s <= FLOAT_FRAC_BITS) { \
|
||||
ret <<= FLOAT_FRAC_BITS - s; \
|
||||
flb = 0; \
|
||||
} else { \
|
||||
flb = (ret >> (s - FLOAT_FRAC_BITS - 1)) & 1; \
|
||||
ret >>= s - FLOAT_FRAC_BITS; \
|
||||
} \
|
||||
} else \
|
||||
return 0; \
|
||||
} \
|
||||
if (flb) \
|
||||
ret++; \
|
||||
\
|
||||
/* fill exponent bits */ \
|
||||
ret |= (s + ONE_EXP(FLOAT)) << FLOAT_FRAC_BITS; \
|
||||
\
|
||||
/* fill sign bit */ \
|
||||
ret |= sign << 31; \
|
||||
\
|
||||
return ret; \
|
||||
}
|
||||
|
||||
/* unsigned long long to float conversion */
|
||||
DEFINE__AEABI_XL2F(ul2f, 0)
|
||||
|
||||
/* long long to float conversion */
|
||||
DEFINE__AEABI_XL2F(l2f, 1)
|
||||
|
||||
/* long long to double conversion */
|
||||
#define __AEABI_XL2D(name, with_sign) \
|
||||
void __aeabi_ ## name(unsigned long long v) \
|
||||
{ \
|
||||
int s /* shift */, high_shift, sign = 0; \
|
||||
unsigned tmp, p = 0; \
|
||||
double_unsigned_struct val, ret; \
|
||||
\
|
||||
/* fraction in negative float is encoded in 1's complement */ \
|
||||
if (with_sign && (v & (1ULL << 63))) { \
|
||||
sign = 1; \
|
||||
v = ~v + 1; \
|
||||
} \
|
||||
val.low = v; \
|
||||
val.high = v >> 32; \
|
||||
\
|
||||
/* fill fraction bits */ \
|
||||
for (s = 31, p = 1 << 31; p && !(val.high & p); s--, p >>= 1); \
|
||||
if (p) { \
|
||||
tmp = val.high & (p - 1); \
|
||||
if (s < DOUBLE_FRAC_BITS - 32) { \
|
||||
high_shift = DOUBLE_FRAC_BITS - 32 - s; \
|
||||
ret.high = tmp << high_shift; \
|
||||
ret.high |= val.low >> (32 - high_shift); \
|
||||
ret.low = val.low << high_shift; \
|
||||
} else { \
|
||||
high_shift = s - (DOUBLE_FRAC_BITS - 32); \
|
||||
ret.high = tmp >> high_shift; \
|
||||
ret.low = tmp << (32 - high_shift); \
|
||||
ret.low |= val.low >> high_shift; \
|
||||
if ((val.low >> (high_shift - 1)) & 1) { \
|
||||
if (ret.low == UINT_MAX) { \
|
||||
ret.high++; \
|
||||
ret.low = 0; \
|
||||
} else \
|
||||
ret.low++; \
|
||||
} \
|
||||
} \
|
||||
s += 32; \
|
||||
} else { \
|
||||
for (s = 31, p = 1 << 31; p && !(val.low & p); s--, p >>= 1); \
|
||||
if (p) { \
|
||||
tmp = val.low & (p - 1); \
|
||||
if (s <= DOUBLE_FRAC_BITS - 32) { \
|
||||
high_shift = DOUBLE_FRAC_BITS - 32 - s; \
|
||||
ret.high = tmp << high_shift; \
|
||||
ret.low = 0; \
|
||||
} else { \
|
||||
high_shift = s - (DOUBLE_FRAC_BITS - 32); \
|
||||
ret.high = tmp >> high_shift; \
|
||||
ret.low = tmp << (32 - high_shift); \
|
||||
} \
|
||||
} else { \
|
||||
ret.high = ret.low = 0; \
|
||||
double_unsigned_struct_return(ret); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
/* fill exponent bits */ \
|
||||
ret.high |= (s + ONE_EXP(DOUBLE)) << (DOUBLE_FRAC_BITS - 32); \
|
||||
\
|
||||
/* fill sign bit */ \
|
||||
ret.high |= sign << 31; \
|
||||
\
|
||||
double_unsigned_struct_return(ret); \
|
||||
}
|
||||
|
||||
/* unsigned long long to double conversion */
|
||||
__AEABI_XL2D(ul2d, 0)
|
||||
|
||||
/* long long to double conversion */
|
||||
__AEABI_XL2D(l2d, 1)
|
||||
|
||||
|
||||
/* Long long helper functions */
|
||||
|
||||
/* TODO: add error in case of den == 0 (see §4.3.1 and §4.3.2) */
|
||||
|
||||
#define define_aeabi_xdivmod_signed_type(basetype, type) \
|
||||
typedef struct type { \
|
||||
basetype quot; \
|
||||
unsigned basetype rem; \
|
||||
} type
|
||||
|
||||
#define define_aeabi_xdivmod_unsigned_type(basetype, type) \
|
||||
typedef struct type { \
|
||||
basetype quot; \
|
||||
basetype rem; \
|
||||
} type
|
||||
|
||||
#define AEABI_UXDIVMOD(name,type, rettype, typemacro) \
|
||||
static inline rettype aeabi_ ## name (type num, type den) \
|
||||
{ \
|
||||
rettype ret; \
|
||||
type quot = 0; \
|
||||
\
|
||||
/* Increase quotient while it is less than numerator */ \
|
||||
while (num >= den) { \
|
||||
type q = 1; \
|
||||
\
|
||||
/* Find closest power of two */ \
|
||||
while ((q << 1) * den <= num && q * den <= typemacro ## _MAX / 2) \
|
||||
q <<= 1; \
|
||||
\
|
||||
/* Compute difference between current quotient and numerator */ \
|
||||
num -= q * den; \
|
||||
quot += q; \
|
||||
} \
|
||||
ret.quot = quot; \
|
||||
ret.rem = num; \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
#define __AEABI_XDIVMOD(name, type, uiname, rettype, urettype, typemacro) \
|
||||
void __aeabi_ ## name(type numerator, type denominator) \
|
||||
{ \
|
||||
unsigned type num, den; \
|
||||
urettype uxdiv_ret; \
|
||||
rettype ret; \
|
||||
\
|
||||
if (numerator >= 0) \
|
||||
num = numerator; \
|
||||
else \
|
||||
num = 0 - numerator; \
|
||||
if (denominator >= 0) \
|
||||
den = denominator; \
|
||||
else \
|
||||
den = 0 - denominator; \
|
||||
uxdiv_ret = aeabi_ ## uiname(num, den); \
|
||||
/* signs differ */ \
|
||||
if ((numerator & typemacro ## _MIN) != (denominator & typemacro ## _MIN)) \
|
||||
ret.quot = 0 - uxdiv_ret.quot; \
|
||||
else \
|
||||
ret.quot = uxdiv_ret.quot; \
|
||||
if (numerator < 0) \
|
||||
ret.rem = 0 - uxdiv_ret.rem; \
|
||||
else \
|
||||
ret.rem = uxdiv_ret.rem; \
|
||||
\
|
||||
rettype ## _return(ret); \
|
||||
}
|
||||
|
||||
define_aeabi_xdivmod_signed_type(long long, lldiv_t);
|
||||
define_aeabi_xdivmod_unsigned_type(unsigned long long, ulldiv_t);
|
||||
define_aeabi_xdivmod_signed_type(int, idiv_t);
|
||||
define_aeabi_xdivmod_unsigned_type(unsigned, uidiv_t);
|
||||
|
||||
REGS_RETURN(lldiv_t, lldiv_t)
|
||||
REGS_RETURN(ulldiv_t, ulldiv_t)
|
||||
REGS_RETURN(idiv_t, idiv_t)
|
||||
REGS_RETURN(uidiv_t, uidiv_t)
|
||||
|
||||
AEABI_UXDIVMOD(uldivmod, unsigned long long, ulldiv_t, ULLONG)
|
||||
|
||||
__AEABI_XDIVMOD(ldivmod, long long, uldivmod, lldiv_t, ulldiv_t, LLONG)
|
||||
|
||||
void __aeabi_uldivmod(unsigned long long num, unsigned long long den)
|
||||
{
|
||||
ulldiv_t_return(aeabi_uldivmod(num, den));
|
||||
}
|
||||
|
||||
void __aeabi_llsl(double_unsigned_struct val, int shift)
|
||||
{
|
||||
double_unsigned_struct ret;
|
||||
|
||||
if (shift >= 32) {
|
||||
val.high = val.low;
|
||||
val.low = 0;
|
||||
shift -= 32;
|
||||
}
|
||||
if (shift > 0) {
|
||||
ret.low = val.low << shift;
|
||||
ret.high = (val.high << shift) | (val.low >> (32 - shift));
|
||||
double_unsigned_struct_return(ret);
|
||||
return;
|
||||
}
|
||||
double_unsigned_struct_return(val);
|
||||
}
|
||||
|
||||
#define aeabi_lsr(val, shift, fill, type) \
|
||||
type ## _struct ret; \
|
||||
\
|
||||
if (shift >= 32) { \
|
||||
val.low = val.high; \
|
||||
val.high = fill; \
|
||||
shift -= 32; \
|
||||
} \
|
||||
if (shift > 0) { \
|
||||
ret.high = val.high >> shift; \
|
||||
ret.low = (val.high << (32 - shift)) | (val.low >> shift); \
|
||||
type ## _struct_return(ret); \
|
||||
return; \
|
||||
} \
|
||||
type ## _struct_return(val);
|
||||
|
||||
void __aeabi_llsr(double_unsigned_struct val, int shift)
|
||||
{
|
||||
aeabi_lsr(val, shift, 0, double_unsigned);
|
||||
}
|
||||
|
||||
void __aeabi_lasr(unsigned_int_struct val, int shift)
|
||||
{
|
||||
aeabi_lsr(val, shift, val.high >> 31, unsigned_int);
|
||||
}
|
||||
|
||||
|
||||
/* Integer division functions */
|
||||
|
||||
AEABI_UXDIVMOD(uidivmod, unsigned, uidiv_t, UINT)
|
||||
|
||||
int __aeabi_idiv(int numerator, int denominator)
|
||||
{
|
||||
unsigned num, den;
|
||||
uidiv_t ret;
|
||||
|
||||
if (numerator >= 0)
|
||||
num = numerator;
|
||||
else
|
||||
num = 0 - numerator;
|
||||
if (denominator >= 0)
|
||||
den = denominator;
|
||||
else
|
||||
den = 0 - denominator;
|
||||
ret = aeabi_uidivmod(num, den);
|
||||
if ((numerator & INT_MIN) != (denominator & INT_MIN)) /* signs differ */
|
||||
ret.quot *= -1;
|
||||
return ret.quot;
|
||||
}
|
||||
|
||||
unsigned __aeabi_uidiv(unsigned num, unsigned den)
|
||||
{
|
||||
return aeabi_uidivmod(num, den).quot;
|
||||
}
|
||||
|
||||
__AEABI_XDIVMOD(idivmod, int, uidivmod, idiv_t, uidiv_t, INT)
|
||||
|
||||
void __aeabi_uidivmod(unsigned num, unsigned den)
|
||||
{
|
||||
uidiv_t_return(aeabi_uidivmod(num, den));
|
||||
}
|
58
05/tcc-0.9.27/lib/armflush.c
Normal file
58
05/tcc-0.9.27/lib/armflush.c
Normal file
|
@ -0,0 +1,58 @@
|
|||
/* armflush.c - flush the instruction cache
|
||||
|
||||
__clear_cache is used in tccrun.c, It is a built-in
|
||||
intrinsic with gcc. However tcc in order to compile
|
||||
itself needs this function */
|
||||
|
||||
#ifdef __TINYC__
|
||||
|
||||
/* syscall wrapper */
|
||||
unsigned syscall(unsigned syscall_nr, ...);
|
||||
|
||||
/* arm-tcc supports only fake asm currently */
|
||||
__asm__(
|
||||
".global syscall\n"
|
||||
"syscall:\n"
|
||||
".int 0xe92d4080\n" // push {r7, lr}
|
||||
".int 0xe1a07000\n" // mov r7, r0
|
||||
".int 0xe1a00001\n" // mov r0, r1
|
||||
".int 0xe1a01002\n" // mov r1, r2
|
||||
".int 0xe1a02003\n" // mov r2, r3
|
||||
".int 0xef000000\n" // svc 0x00000000
|
||||
".int 0xe8bd8080\n" // pop {r7, pc}
|
||||
);
|
||||
|
||||
/* from unistd.h: */
|
||||
#if defined(__thumb__) || defined(__ARM_EABI__)
|
||||
# define __NR_SYSCALL_BASE 0x0
|
||||
#else
|
||||
# define __NR_SYSCALL_BASE 0x900000
|
||||
#endif
|
||||
#define __ARM_NR_BASE (__NR_SYSCALL_BASE+0x0f0000)
|
||||
#define __ARM_NR_cacheflush (__ARM_NR_BASE+2)
|
||||
|
||||
#else
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#endif
|
||||
|
||||
/* Flushing for tccrun */
|
||||
void __clear_cache(void *beginning, void *end)
|
||||
{
|
||||
/* __ARM_NR_cacheflush is kernel private and should not be used in user space.
|
||||
* However, there is no ARM asm parser in tcc so we use it for now */
|
||||
#if 1
|
||||
syscall(__ARM_NR_cacheflush, beginning, end, 0);
|
||||
#else
|
||||
__asm__ ("push {r7}\n\t"
|
||||
"mov r7, #0xf0002\n\t"
|
||||
"mov r2, #0\n\t"
|
||||
"swi 0\n\t"
|
||||
"pop {r7}\n\t"
|
||||
"ret");
|
||||
#endif
|
||||
}
|
979
05/tcc-0.9.27/lib/bcheck.c
Normal file
979
05/tcc-0.9.27/lib/bcheck.c
Normal file
|
@ -0,0 +1,979 @@
|
|||
/*
|
||||
* Tiny C Memory and bounds checker
|
||||
*
|
||||
* Copyright (c) 2002 Fabrice Bellard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser 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
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#if !defined(__FreeBSD__) \
|
||||
&& !defined(__FreeBSD_kernel__) \
|
||||
&& !defined(__DragonFly__) \
|
||||
&& !defined(__OpenBSD__) \
|
||||
&& !defined(__NetBSD__)
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
/* #define BOUND_DEBUG */
|
||||
|
||||
#ifdef BOUND_DEBUG
|
||||
#define dprintf(a...) fprintf(a)
|
||||
#else
|
||||
#define dprintf(a...)
|
||||
#endif
|
||||
|
||||
/* define so that bound array is static (faster, but use memory if
|
||||
bound checking not used) */
|
||||
/* #define BOUND_STATIC */
|
||||
|
||||
/* use malloc hooks. Currently the code cannot be reliable if no hooks */
|
||||
#define CONFIG_TCC_MALLOC_HOOKS
|
||||
#define HAVE_MEMALIGN
|
||||
|
||||
#if defined(__FreeBSD__) \
|
||||
|| defined(__FreeBSD_kernel__) \
|
||||
|| defined(__DragonFly__) \
|
||||
|| defined(__OpenBSD__) \
|
||||
|| defined(__NetBSD__) \
|
||||
|| defined(__dietlibc__) \
|
||||
|| defined(_WIN32)
|
||||
//#warning Bound checking does not support malloc (etc.) in this environment.
|
||||
#undef CONFIG_TCC_MALLOC_HOOKS
|
||||
#undef HAVE_MEMALIGN
|
||||
#endif
|
||||
|
||||
#define BOUND_T1_BITS 13
|
||||
#define BOUND_T2_BITS 11
|
||||
#define BOUND_T3_BITS (sizeof(size_t)*8 - BOUND_T1_BITS - BOUND_T2_BITS)
|
||||
#define BOUND_E_BITS (sizeof(size_t))
|
||||
|
||||
#define BOUND_T1_SIZE ((size_t)1 << BOUND_T1_BITS)
|
||||
#define BOUND_T2_SIZE ((size_t)1 << BOUND_T2_BITS)
|
||||
#define BOUND_T3_SIZE ((size_t)1 << BOUND_T3_BITS)
|
||||
|
||||
#define BOUND_T23_BITS (BOUND_T2_BITS + BOUND_T3_BITS)
|
||||
#define BOUND_T23_SIZE ((size_t)1 << BOUND_T23_BITS)
|
||||
|
||||
|
||||
/* this pointer is generated when bound check is incorrect */
|
||||
#define INVALID_POINTER ((void *)(-2))
|
||||
/* size of an empty region */
|
||||
#define EMPTY_SIZE ((size_t)(-1))
|
||||
/* size of an invalid region */
|
||||
#define INVALID_SIZE 0
|
||||
|
||||
typedef struct BoundEntry {
|
||||
size_t start;
|
||||
size_t size;
|
||||
struct BoundEntry *next;
|
||||
size_t is_invalid; /* true if pointers outside region are invalid */
|
||||
} BoundEntry;
|
||||
|
||||
/* external interface */
|
||||
void __bound_init(void);
|
||||
void __bound_new_region(void *p, size_t size);
|
||||
int __bound_delete_region(void *p);
|
||||
|
||||
#ifdef __attribute__
|
||||
/* an __attribute__ macro is defined in the system headers */
|
||||
#undef __attribute__
|
||||
#endif
|
||||
#define FASTCALL __attribute__((regparm(3)))
|
||||
|
||||
void *__bound_malloc(size_t size, const void *caller);
|
||||
void *__bound_memalign(size_t size, size_t align, const void *caller);
|
||||
void __bound_free(void *ptr, const void *caller);
|
||||
void *__bound_realloc(void *ptr, size_t size, const void *caller);
|
||||
static void *libc_malloc(size_t size);
|
||||
static void libc_free(void *ptr);
|
||||
static void install_malloc_hooks(void);
|
||||
static void restore_malloc_hooks(void);
|
||||
|
||||
#ifdef CONFIG_TCC_MALLOC_HOOKS
|
||||
static void *saved_malloc_hook;
|
||||
static void *saved_free_hook;
|
||||
static void *saved_realloc_hook;
|
||||
static void *saved_memalign_hook;
|
||||
#endif
|
||||
|
||||
/* TCC definitions */
|
||||
extern char __bounds_start; /* start of static bounds table */
|
||||
/* error message, just for TCC */
|
||||
const char *__bound_error_msg;
|
||||
|
||||
/* runtime error output */
|
||||
extern void rt_error(size_t pc, const char *fmt, ...);
|
||||
|
||||
#ifdef BOUND_STATIC
|
||||
static BoundEntry *__bound_t1[BOUND_T1_SIZE]; /* page table */
|
||||
#else
|
||||
static BoundEntry **__bound_t1; /* page table */
|
||||
#endif
|
||||
static BoundEntry *__bound_empty_t2; /* empty page, for unused pages */
|
||||
static BoundEntry *__bound_invalid_t2; /* invalid page, for invalid pointers */
|
||||
|
||||
static BoundEntry *__bound_find_region(BoundEntry *e1, void *p)
|
||||
{
|
||||
size_t addr, tmp;
|
||||
BoundEntry *e;
|
||||
|
||||
e = e1;
|
||||
while (e != NULL) {
|
||||
addr = (size_t)p;
|
||||
addr -= e->start;
|
||||
if (addr <= e->size) {
|
||||
/* put region at the head */
|
||||
tmp = e1->start;
|
||||
e1->start = e->start;
|
||||
e->start = tmp;
|
||||
tmp = e1->size;
|
||||
e1->size = e->size;
|
||||
e->size = tmp;
|
||||
return e1;
|
||||
}
|
||||
e = e->next;
|
||||
}
|
||||
/* no entry found: return empty entry or invalid entry */
|
||||
if (e1->is_invalid)
|
||||
return __bound_invalid_t2;
|
||||
else
|
||||
return __bound_empty_t2;
|
||||
}
|
||||
|
||||
/* print a bound error message */
|
||||
static void bound_error(const char *fmt, ...)
|
||||
{
|
||||
__bound_error_msg = fmt;
|
||||
fprintf(stderr,"%s %s: %s\n", __FILE__, __FUNCTION__, fmt);
|
||||
*(void **)0 = 0; /* force a runtime error */
|
||||
}
|
||||
|
||||
static void bound_alloc_error(void)
|
||||
{
|
||||
bound_error("not enough memory for bound checking code");
|
||||
}
|
||||
|
||||
/* return '(p + offset)' for pointer arithmetic (a pointer can reach
|
||||
the end of a region in this case */
|
||||
void * FASTCALL __bound_ptr_add(void *p, size_t offset)
|
||||
{
|
||||
size_t addr = (size_t)p;
|
||||
BoundEntry *e;
|
||||
|
||||
dprintf(stderr, "%s %s: %p %x\n",
|
||||
__FILE__, __FUNCTION__, p, (unsigned)offset);
|
||||
|
||||
__bound_init();
|
||||
|
||||
e = __bound_t1[addr >> (BOUND_T2_BITS + BOUND_T3_BITS)];
|
||||
e = (BoundEntry *)((char *)e +
|
||||
((addr >> (BOUND_T3_BITS - BOUND_E_BITS)) &
|
||||
((BOUND_T2_SIZE - 1) << BOUND_E_BITS)));
|
||||
addr -= e->start;
|
||||
if (addr > e->size) {
|
||||
e = __bound_find_region(e, p);
|
||||
addr = (size_t)p - e->start;
|
||||
}
|
||||
addr += offset;
|
||||
if (addr >= e->size) {
|
||||
fprintf(stderr,"%s %s: %p is outside of the region\n",
|
||||
__FILE__, __FUNCTION__, p + offset);
|
||||
return INVALID_POINTER; /* return an invalid pointer */
|
||||
}
|
||||
return p + offset;
|
||||
}
|
||||
|
||||
/* return '(p + offset)' for pointer indirection (the resulting must
|
||||
be strictly inside the region */
|
||||
#define BOUND_PTR_INDIR(dsize) \
|
||||
void * FASTCALL __bound_ptr_indir ## dsize (void *p, size_t offset) \
|
||||
{ \
|
||||
size_t addr = (size_t)p; \
|
||||
BoundEntry *e; \
|
||||
\
|
||||
dprintf(stderr, "%s %s: %p %x start\n", \
|
||||
__FILE__, __FUNCTION__, p, (unsigned)offset); \
|
||||
\
|
||||
__bound_init(); \
|
||||
e = __bound_t1[addr >> (BOUND_T2_BITS + BOUND_T3_BITS)]; \
|
||||
e = (BoundEntry *)((char *)e + \
|
||||
((addr >> (BOUND_T3_BITS - BOUND_E_BITS)) & \
|
||||
((BOUND_T2_SIZE - 1) << BOUND_E_BITS))); \
|
||||
addr -= e->start; \
|
||||
if (addr > e->size) { \
|
||||
e = __bound_find_region(e, p); \
|
||||
addr = (size_t)p - e->start; \
|
||||
} \
|
||||
addr += offset + dsize; \
|
||||
if (addr > e->size) { \
|
||||
fprintf(stderr,"%s %s: %p is outside of the region\n", \
|
||||
__FILE__, __FUNCTION__, p + offset); \
|
||||
return INVALID_POINTER; /* return an invalid pointer */ \
|
||||
} \
|
||||
dprintf(stderr, "%s %s: return p+offset = %p\n", \
|
||||
__FILE__, __FUNCTION__, p + offset); \
|
||||
return p + offset; \
|
||||
}
|
||||
|
||||
BOUND_PTR_INDIR(1)
|
||||
BOUND_PTR_INDIR(2)
|
||||
BOUND_PTR_INDIR(4)
|
||||
BOUND_PTR_INDIR(8)
|
||||
BOUND_PTR_INDIR(12)
|
||||
BOUND_PTR_INDIR(16)
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ >= 6)
|
||||
/*
|
||||
* At least gcc 6.2 complains when __builtin_frame_address is used with
|
||||
* nonzero argument.
|
||||
*/
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wframe-address"
|
||||
#endif
|
||||
|
||||
/* return the frame pointer of the caller */
|
||||
#define GET_CALLER_FP(fp)\
|
||||
{\
|
||||
fp = (size_t)__builtin_frame_address(1);\
|
||||
}
|
||||
|
||||
/* called when entering a function to add all the local regions */
|
||||
void FASTCALL __bound_local_new(void *p1)
|
||||
{
|
||||
size_t addr, size, fp, *p = p1;
|
||||
|
||||
dprintf(stderr, "%s, %s start p1=%p\n", __FILE__, __FUNCTION__, p);
|
||||
GET_CALLER_FP(fp);
|
||||
for(;;) {
|
||||
addr = p[0];
|
||||
if (addr == 0)
|
||||
break;
|
||||
addr += fp;
|
||||
size = p[1];
|
||||
p += 2;
|
||||
__bound_new_region((void *)addr, size);
|
||||
}
|
||||
dprintf(stderr, "%s, %s end\n", __FILE__, __FUNCTION__);
|
||||
}
|
||||
|
||||
/* called when leaving a function to delete all the local regions */
|
||||
void FASTCALL __bound_local_delete(void *p1)
|
||||
{
|
||||
size_t addr, fp, *p = p1;
|
||||
GET_CALLER_FP(fp);
|
||||
for(;;) {
|
||||
addr = p[0];
|
||||
if (addr == 0)
|
||||
break;
|
||||
addr += fp;
|
||||
p += 2;
|
||||
__bound_delete_region((void *)addr);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ >= 6)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
static BoundEntry *__bound_new_page(void)
|
||||
{
|
||||
BoundEntry *page;
|
||||
size_t i;
|
||||
|
||||
page = libc_malloc(sizeof(BoundEntry) * BOUND_T2_SIZE);
|
||||
if (!page)
|
||||
bound_alloc_error();
|
||||
for(i=0;i<BOUND_T2_SIZE;i++) {
|
||||
/* put empty entries */
|
||||
page[i].start = 0;
|
||||
page[i].size = EMPTY_SIZE;
|
||||
page[i].next = NULL;
|
||||
page[i].is_invalid = 0;
|
||||
}
|
||||
return page;
|
||||
}
|
||||
|
||||
/* currently we use malloc(). Should use bound_new_page() */
|
||||
static BoundEntry *bound_new_entry(void)
|
||||
{
|
||||
BoundEntry *e;
|
||||
e = libc_malloc(sizeof(BoundEntry));
|
||||
return e;
|
||||
}
|
||||
|
||||
static void bound_free_entry(BoundEntry *e)
|
||||
{
|
||||
libc_free(e);
|
||||
}
|
||||
|
||||
static BoundEntry *get_page(size_t index)
|
||||
{
|
||||
BoundEntry *page;
|
||||
page = __bound_t1[index];
|
||||
if (!page || page == __bound_empty_t2 || page == __bound_invalid_t2) {
|
||||
/* create a new page if necessary */
|
||||
page = __bound_new_page();
|
||||
__bound_t1[index] = page;
|
||||
}
|
||||
return page;
|
||||
}
|
||||
|
||||
/* mark a region as being invalid (can only be used during init) */
|
||||
static void mark_invalid(size_t addr, size_t size)
|
||||
{
|
||||
size_t start, end;
|
||||
BoundEntry *page;
|
||||
size_t t1_start, t1_end, i, j, t2_start, t2_end;
|
||||
|
||||
start = addr;
|
||||
end = addr + size;
|
||||
|
||||
t2_start = (start + BOUND_T3_SIZE - 1) >> BOUND_T3_BITS;
|
||||
if (end != 0)
|
||||
t2_end = end >> BOUND_T3_BITS;
|
||||
else
|
||||
t2_end = 1 << (BOUND_T1_BITS + BOUND_T2_BITS);
|
||||
|
||||
#if 0
|
||||
dprintf(stderr, "mark_invalid: start = %x %x\n", t2_start, t2_end);
|
||||
#endif
|
||||
|
||||
/* first we handle full pages */
|
||||
t1_start = (t2_start + BOUND_T2_SIZE - 1) >> BOUND_T2_BITS;
|
||||
t1_end = t2_end >> BOUND_T2_BITS;
|
||||
|
||||
i = t2_start & (BOUND_T2_SIZE - 1);
|
||||
j = t2_end & (BOUND_T2_SIZE - 1);
|
||||
|
||||
if (t1_start == t1_end) {
|
||||
page = get_page(t2_start >> BOUND_T2_BITS);
|
||||
for(; i < j; i++) {
|
||||
page[i].size = INVALID_SIZE;
|
||||
page[i].is_invalid = 1;
|
||||
}
|
||||
} else {
|
||||
if (i > 0) {
|
||||
page = get_page(t2_start >> BOUND_T2_BITS);
|
||||
for(; i < BOUND_T2_SIZE; i++) {
|
||||
page[i].size = INVALID_SIZE;
|
||||
page[i].is_invalid = 1;
|
||||
}
|
||||
}
|
||||
for(i = t1_start; i < t1_end; i++) {
|
||||
__bound_t1[i] = __bound_invalid_t2;
|
||||
}
|
||||
if (j != 0) {
|
||||
page = get_page(t1_end);
|
||||
for(i = 0; i < j; i++) {
|
||||
page[i].size = INVALID_SIZE;
|
||||
page[i].is_invalid = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __bound_init(void)
|
||||
{
|
||||
size_t i;
|
||||
BoundEntry *page;
|
||||
size_t start, size;
|
||||
size_t *p;
|
||||
|
||||
static int inited;
|
||||
if (inited)
|
||||
return;
|
||||
|
||||
inited = 1;
|
||||
|
||||
dprintf(stderr, "%s, %s() start\n", __FILE__, __FUNCTION__);
|
||||
|
||||
/* save malloc hooks and install bound check hooks */
|
||||
install_malloc_hooks();
|
||||
|
||||
#ifndef BOUND_STATIC
|
||||
__bound_t1 = libc_malloc(BOUND_T1_SIZE * sizeof(BoundEntry *));
|
||||
if (!__bound_t1)
|
||||
bound_alloc_error();
|
||||
#endif
|
||||
__bound_empty_t2 = __bound_new_page();
|
||||
for(i=0;i<BOUND_T1_SIZE;i++) {
|
||||
__bound_t1[i] = __bound_empty_t2;
|
||||
}
|
||||
|
||||
page = __bound_new_page();
|
||||
for(i=0;i<BOUND_T2_SIZE;i++) {
|
||||
/* put invalid entries */
|
||||
page[i].start = 0;
|
||||
page[i].size = INVALID_SIZE;
|
||||
page[i].next = NULL;
|
||||
page[i].is_invalid = 1;
|
||||
}
|
||||
__bound_invalid_t2 = page;
|
||||
|
||||
/* invalid pointer zone */
|
||||
start = (size_t)INVALID_POINTER & ~(BOUND_T23_SIZE - 1);
|
||||
size = BOUND_T23_SIZE;
|
||||
mark_invalid(start, size);
|
||||
|
||||
#if defined(CONFIG_TCC_MALLOC_HOOKS)
|
||||
/* malloc zone is also marked invalid. can only use that with
|
||||
* hooks because all libs should use the same malloc. The solution
|
||||
* would be to build a new malloc for tcc.
|
||||
*
|
||||
* usually heap (= malloc zone) comes right after bss, i.e. after _end, but
|
||||
* not always - either if we are running from under `tcc -b -run`, or if
|
||||
* address space randomization is turned on(a), heap start will be separated
|
||||
* from bss end.
|
||||
*
|
||||
* So sbrk(0) will be a good approximation for start_brk:
|
||||
*
|
||||
* - if we are a separately compiled program, __bound_init() runs early,
|
||||
* and sbrk(0) should be equal or very near to start_brk(b) (in case other
|
||||
* constructors malloc something), or
|
||||
*
|
||||
* - if we are running from under `tcc -b -run`, sbrk(0) will return
|
||||
* start of heap portion which is under this program control, and not
|
||||
* mark as invalid earlier allocated memory.
|
||||
*
|
||||
*
|
||||
* (a) /proc/sys/kernel/randomize_va_space = 2, on Linux;
|
||||
* usually turned on by default.
|
||||
*
|
||||
* (b) on Linux >= v3.3, the alternative is to read
|
||||
* start_brk from /proc/self/stat
|
||||
*/
|
||||
start = (size_t)sbrk(0);
|
||||
size = 128 * 0x100000;
|
||||
mark_invalid(start, size);
|
||||
#endif
|
||||
|
||||
/* add all static bound check values */
|
||||
p = (size_t *)&__bounds_start;
|
||||
while (p[0] != 0) {
|
||||
__bound_new_region((void *)p[0], p[1]);
|
||||
p += 2;
|
||||
}
|
||||
|
||||
dprintf(stderr, "%s, %s() end\n\n", __FILE__, __FUNCTION__);
|
||||
}
|
||||
|
||||
void __bound_main_arg(void **p)
|
||||
{
|
||||
void *start = p;
|
||||
while (*p++);
|
||||
|
||||
dprintf(stderr, "%s, %s calling __bound_new_region(%p %x)\n",
|
||||
__FILE__, __FUNCTION__, start, (unsigned)((void *)p - start));
|
||||
|
||||
__bound_new_region(start, (void *) p - start);
|
||||
}
|
||||
|
||||
void __bound_exit(void)
|
||||
{
|
||||
dprintf(stderr, "%s, %s()\n", __FILE__, __FUNCTION__);
|
||||
restore_malloc_hooks();
|
||||
}
|
||||
|
||||
static inline void add_region(BoundEntry *e,
|
||||
size_t start, size_t size)
|
||||
{
|
||||
BoundEntry *e1;
|
||||
if (e->start == 0) {
|
||||
/* no region : add it */
|
||||
e->start = start;
|
||||
e->size = size;
|
||||
} else {
|
||||
/* already regions in the list: add it at the head */
|
||||
e1 = bound_new_entry();
|
||||
e1->start = e->start;
|
||||
e1->size = e->size;
|
||||
e1->next = e->next;
|
||||
e->start = start;
|
||||
e->size = size;
|
||||
e->next = e1;
|
||||
}
|
||||
}
|
||||
|
||||
/* create a new region. It should not already exist in the region list */
|
||||
void __bound_new_region(void *p, size_t size)
|
||||
{
|
||||
size_t start, end;
|
||||
BoundEntry *page, *e, *e2;
|
||||
size_t t1_start, t1_end, i, t2_start, t2_end;
|
||||
|
||||
dprintf(stderr, "%s, %s(%p, %x) start\n",
|
||||
__FILE__, __FUNCTION__, p, (unsigned)size);
|
||||
|
||||
__bound_init();
|
||||
|
||||
start = (size_t)p;
|
||||
end = start + size;
|
||||
t1_start = start >> (BOUND_T2_BITS + BOUND_T3_BITS);
|
||||
t1_end = end >> (BOUND_T2_BITS + BOUND_T3_BITS);
|
||||
|
||||
/* start */
|
||||
page = get_page(t1_start);
|
||||
t2_start = (start >> (BOUND_T3_BITS - BOUND_E_BITS)) &
|
||||
((BOUND_T2_SIZE - 1) << BOUND_E_BITS);
|
||||
t2_end = (end >> (BOUND_T3_BITS - BOUND_E_BITS)) &
|
||||
((BOUND_T2_SIZE - 1) << BOUND_E_BITS);
|
||||
|
||||
|
||||
e = (BoundEntry *)((char *)page + t2_start);
|
||||
add_region(e, start, size);
|
||||
|
||||
if (t1_end == t1_start) {
|
||||
/* same ending page */
|
||||
e2 = (BoundEntry *)((char *)page + t2_end);
|
||||
if (e2 > e) {
|
||||
e++;
|
||||
for(;e<e2;e++) {
|
||||
e->start = start;
|
||||
e->size = size;
|
||||
}
|
||||
add_region(e, start, size);
|
||||
}
|
||||
} else {
|
||||
/* mark until end of page */
|
||||
e2 = page + BOUND_T2_SIZE;
|
||||
e++;
|
||||
for(;e<e2;e++) {
|
||||
e->start = start;
|
||||
e->size = size;
|
||||
}
|
||||
/* mark intermediate pages, if any */
|
||||
for(i=t1_start+1;i<t1_end;i++) {
|
||||
page = get_page(i);
|
||||
e2 = page + BOUND_T2_SIZE;
|
||||
for(e=page;e<e2;e++) {
|
||||
e->start = start;
|
||||
e->size = size;
|
||||
}
|
||||
}
|
||||
/* last page */
|
||||
page = get_page(t1_end);
|
||||
e2 = (BoundEntry *)((char *)page + t2_end);
|
||||
for(e=page;e<e2;e++) {
|
||||
e->start = start;
|
||||
e->size = size;
|
||||
}
|
||||
add_region(e, start, size);
|
||||
}
|
||||
|
||||
dprintf(stderr, "%s, %s end\n", __FILE__, __FUNCTION__);
|
||||
}
|
||||
|
||||
/* delete a region */
|
||||
static inline void delete_region(BoundEntry *e, void *p, size_t empty_size)
|
||||
{
|
||||
size_t addr;
|
||||
BoundEntry *e1;
|
||||
|
||||
addr = (size_t)p;
|
||||
addr -= e->start;
|
||||
if (addr <= e->size) {
|
||||
/* region found is first one */
|
||||
e1 = e->next;
|
||||
if (e1 == NULL) {
|
||||
/* no more region: mark it empty */
|
||||
e->start = 0;
|
||||
e->size = empty_size;
|
||||
} else {
|
||||
/* copy next region in head */
|
||||
e->start = e1->start;
|
||||
e->size = e1->size;
|
||||
e->next = e1->next;
|
||||
bound_free_entry(e1);
|
||||
}
|
||||
} else {
|
||||
/* find the matching region */
|
||||
for(;;) {
|
||||
e1 = e;
|
||||
e = e->next;
|
||||
/* region not found: do nothing */
|
||||
if (e == NULL)
|
||||
break;
|
||||
addr = (size_t)p - e->start;
|
||||
if (addr <= e->size) {
|
||||
/* found: remove entry */
|
||||
e1->next = e->next;
|
||||
bound_free_entry(e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* WARNING: 'p' must be the starting point of the region. */
|
||||
/* return non zero if error */
|
||||
int __bound_delete_region(void *p)
|
||||
{
|
||||
size_t start, end, addr, size, empty_size;
|
||||
BoundEntry *page, *e, *e2;
|
||||
size_t t1_start, t1_end, t2_start, t2_end, i;
|
||||
|
||||
dprintf(stderr, "%s %s() start\n", __FILE__, __FUNCTION__);
|
||||
|
||||
__bound_init();
|
||||
|
||||
start = (size_t)p;
|
||||
t1_start = start >> (BOUND_T2_BITS + BOUND_T3_BITS);
|
||||
t2_start = (start >> (BOUND_T3_BITS - BOUND_E_BITS)) &
|
||||
((BOUND_T2_SIZE - 1) << BOUND_E_BITS);
|
||||
|
||||
/* find region size */
|
||||
page = __bound_t1[t1_start];
|
||||
e = (BoundEntry *)((char *)page + t2_start);
|
||||
addr = start - e->start;
|
||||
if (addr > e->size)
|
||||
e = __bound_find_region(e, p);
|
||||
/* test if invalid region */
|
||||
if (e->size == EMPTY_SIZE || (size_t)p != e->start)
|
||||
return -1;
|
||||
/* compute the size we put in invalid regions */
|
||||
if (e->is_invalid)
|
||||
empty_size = INVALID_SIZE;
|
||||
else
|
||||
empty_size = EMPTY_SIZE;
|
||||
size = e->size;
|
||||
end = start + size;
|
||||
|
||||
/* now we can free each entry */
|
||||
t1_end = end >> (BOUND_T2_BITS + BOUND_T3_BITS);
|
||||
t2_end = (end >> (BOUND_T3_BITS - BOUND_E_BITS)) &
|
||||
((BOUND_T2_SIZE - 1) << BOUND_E_BITS);
|
||||
|
||||
delete_region(e, p, empty_size);
|
||||
if (t1_end == t1_start) {
|
||||
/* same ending page */
|
||||
e2 = (BoundEntry *)((char *)page + t2_end);
|
||||
if (e2 > e) {
|
||||
e++;
|
||||
for(;e<e2;e++) {
|
||||
e->start = 0;
|
||||
e->size = empty_size;
|
||||
}
|
||||
delete_region(e, p, empty_size);
|
||||
}
|
||||
} else {
|
||||
/* mark until end of page */
|
||||
e2 = page + BOUND_T2_SIZE;
|
||||
e++;
|
||||
for(;e<e2;e++) {
|
||||
e->start = 0;
|
||||
e->size = empty_size;
|
||||
}
|
||||
/* mark intermediate pages, if any */
|
||||
/* XXX: should free them */
|
||||
for(i=t1_start+1;i<t1_end;i++) {
|
||||
page = get_page(i);
|
||||
e2 = page + BOUND_T2_SIZE;
|
||||
for(e=page;e<e2;e++) {
|
||||
e->start = 0;
|
||||
e->size = empty_size;
|
||||
}
|
||||
}
|
||||
/* last page */
|
||||
page = get_page(t1_end);
|
||||
e2 = (BoundEntry *)((char *)page + t2_end);
|
||||
for(e=page;e<e2;e++) {
|
||||
e->start = 0;
|
||||
e->size = empty_size;
|
||||
}
|
||||
delete_region(e, p, empty_size);
|
||||
}
|
||||
|
||||
dprintf(stderr, "%s %s() end\n", __FILE__, __FUNCTION__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* return the size of the region starting at p, or EMPTY_SIZE if non
|
||||
existent region. */
|
||||
static size_t get_region_size(void *p)
|
||||
{
|
||||
size_t addr = (size_t)p;
|
||||
BoundEntry *e;
|
||||
|
||||
e = __bound_t1[addr >> (BOUND_T2_BITS + BOUND_T3_BITS)];
|
||||
e = (BoundEntry *)((char *)e +
|
||||
((addr >> (BOUND_T3_BITS - BOUND_E_BITS)) &
|
||||
((BOUND_T2_SIZE - 1) << BOUND_E_BITS)));
|
||||
addr -= e->start;
|
||||
if (addr > e->size)
|
||||
e = __bound_find_region(e, p);
|
||||
if (e->start != (size_t)p)
|
||||
return EMPTY_SIZE;
|
||||
return e->size;
|
||||
}
|
||||
|
||||
/* patched memory functions */
|
||||
|
||||
/* force compiler to perform stores coded up to this point */
|
||||
#define barrier() __asm__ __volatile__ ("": : : "memory")
|
||||
|
||||
static void install_malloc_hooks(void)
|
||||
{
|
||||
#ifdef CONFIG_TCC_MALLOC_HOOKS
|
||||
saved_malloc_hook = __malloc_hook;
|
||||
saved_free_hook = __free_hook;
|
||||
saved_realloc_hook = __realloc_hook;
|
||||
saved_memalign_hook = __memalign_hook;
|
||||
__malloc_hook = __bound_malloc;
|
||||
__free_hook = __bound_free;
|
||||
__realloc_hook = __bound_realloc;
|
||||
__memalign_hook = __bound_memalign;
|
||||
|
||||
barrier();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void restore_malloc_hooks(void)
|
||||
{
|
||||
#ifdef CONFIG_TCC_MALLOC_HOOKS
|
||||
__malloc_hook = saved_malloc_hook;
|
||||
__free_hook = saved_free_hook;
|
||||
__realloc_hook = saved_realloc_hook;
|
||||
__memalign_hook = saved_memalign_hook;
|
||||
|
||||
barrier();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void *libc_malloc(size_t size)
|
||||
{
|
||||
void *ptr;
|
||||
restore_malloc_hooks();
|
||||
ptr = malloc(size);
|
||||
install_malloc_hooks();
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static void libc_free(void *ptr)
|
||||
{
|
||||
restore_malloc_hooks();
|
||||
free(ptr);
|
||||
install_malloc_hooks();
|
||||
}
|
||||
|
||||
/* XXX: we should use a malloc which ensure that it is unlikely that
|
||||
two malloc'ed data have the same address if 'free' are made in
|
||||
between. */
|
||||
void *__bound_malloc(size_t size, const void *caller)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
/* we allocate one more byte to ensure the regions will be
|
||||
separated by at least one byte. With the glibc malloc, it may
|
||||
be in fact not necessary */
|
||||
ptr = libc_malloc(size + 1);
|
||||
|
||||
if (!ptr)
|
||||
return NULL;
|
||||
|
||||
dprintf(stderr, "%s, %s calling __bound_new_region(%p, %x)\n",
|
||||
__FILE__, __FUNCTION__, ptr, (unsigned)size);
|
||||
|
||||
__bound_new_region(ptr, size);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *__bound_memalign(size_t size, size_t align, const void *caller)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
restore_malloc_hooks();
|
||||
|
||||
#ifndef HAVE_MEMALIGN
|
||||
if (align > 4) {
|
||||
/* XXX: handle it ? */
|
||||
ptr = NULL;
|
||||
} else {
|
||||
/* we suppose that malloc aligns to at least four bytes */
|
||||
ptr = malloc(size + 1);
|
||||
}
|
||||
#else
|
||||
/* we allocate one more byte to ensure the regions will be
|
||||
separated by at least one byte. With the glibc malloc, it may
|
||||
be in fact not necessary */
|
||||
ptr = memalign(size + 1, align);
|
||||
#endif
|
||||
|
||||
install_malloc_hooks();
|
||||
|
||||
if (!ptr)
|
||||
return NULL;
|
||||
|
||||
dprintf(stderr, "%s, %s calling __bound_new_region(%p, %x)\n",
|
||||
__FILE__, __FUNCTION__, ptr, (unsigned)size);
|
||||
|
||||
__bound_new_region(ptr, size);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void __bound_free(void *ptr, const void *caller)
|
||||
{
|
||||
if (ptr == NULL)
|
||||
return;
|
||||
if (__bound_delete_region(ptr) != 0)
|
||||
bound_error("freeing invalid region");
|
||||
|
||||
libc_free(ptr);
|
||||
}
|
||||
|
||||
void *__bound_realloc(void *ptr, size_t size, const void *caller)
|
||||
{
|
||||
void *ptr1;
|
||||
size_t old_size;
|
||||
|
||||
if (size == 0) {
|
||||
__bound_free(ptr, caller);
|
||||
return NULL;
|
||||
} else {
|
||||
ptr1 = __bound_malloc(size, caller);
|
||||
if (ptr == NULL || ptr1 == NULL)
|
||||
return ptr1;
|
||||
old_size = get_region_size(ptr);
|
||||
if (old_size == EMPTY_SIZE)
|
||||
bound_error("realloc'ing invalid pointer");
|
||||
memcpy(ptr1, ptr, old_size);
|
||||
__bound_free(ptr, caller);
|
||||
return ptr1;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CONFIG_TCC_MALLOC_HOOKS
|
||||
void *__bound_calloc(size_t nmemb, size_t size)
|
||||
{
|
||||
void *ptr;
|
||||
size = size * nmemb;
|
||||
ptr = __bound_malloc(size, NULL);
|
||||
if (!ptr)
|
||||
return NULL;
|
||||
memset(ptr, 0, size);
|
||||
return ptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
static void bound_dump(void)
|
||||
{
|
||||
BoundEntry *page, *e;
|
||||
size_t i, j;
|
||||
|
||||
fprintf(stderr, "region dump:\n");
|
||||
for(i=0;i<BOUND_T1_SIZE;i++) {
|
||||
page = __bound_t1[i];
|
||||
for(j=0;j<BOUND_T2_SIZE;j++) {
|
||||
e = page + j;
|
||||
/* do not print invalid or empty entries */
|
||||
if (e->size != EMPTY_SIZE && e->start != 0) {
|
||||
fprintf(stderr, "%08x:",
|
||||
(i << (BOUND_T2_BITS + BOUND_T3_BITS)) +
|
||||
(j << BOUND_T3_BITS));
|
||||
do {
|
||||
fprintf(stderr, " %08lx:%08lx", e->start, e->start + e->size);
|
||||
e = e->next;
|
||||
} while (e != NULL);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* some useful checked functions */
|
||||
|
||||
/* check that (p ... p + size - 1) lies inside 'p' region, if any */
|
||||
static void __bound_check(const void *p, size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
return;
|
||||
p = __bound_ptr_add((void *)p, size - 1);
|
||||
if (p == INVALID_POINTER)
|
||||
bound_error("invalid pointer");
|
||||
}
|
||||
|
||||
void *__bound_memcpy(void *dst, const void *src, size_t size)
|
||||
{
|
||||
void* p;
|
||||
|
||||
dprintf(stderr, "%s %s: start, dst=%p src=%p size=%x\n",
|
||||
__FILE__, __FUNCTION__, dst, src, (unsigned)size);
|
||||
|
||||
__bound_check(dst, size);
|
||||
__bound_check(src, size);
|
||||
/* check also region overlap */
|
||||
if (src >= dst && src < dst + size)
|
||||
bound_error("overlapping regions in memcpy()");
|
||||
|
||||
p = memcpy(dst, src, size);
|
||||
|
||||
dprintf(stderr, "%s %s: end, p=%p\n", __FILE__, __FUNCTION__, p);
|
||||
return p;
|
||||
}
|
||||
|
||||
void *__bound_memmove(void *dst, const void *src, size_t size)
|
||||
{
|
||||
__bound_check(dst, size);
|
||||
__bound_check(src, size);
|
||||
return memmove(dst, src, size);
|
||||
}
|
||||
|
||||
void *__bound_memset(void *dst, int c, size_t size)
|
||||
{
|
||||
__bound_check(dst, size);
|
||||
return memset(dst, c, size);
|
||||
}
|
||||
|
||||
/* XXX: could be optimized */
|
||||
int __bound_strlen(const char *s)
|
||||
{
|
||||
const char *p;
|
||||
size_t len;
|
||||
|
||||
len = 0;
|
||||
for(;;) {
|
||||
p = __bound_ptr_indir1((char *)s, len);
|
||||
if (p == INVALID_POINTER)
|
||||
bound_error("bad pointer in strlen()");
|
||||
if (*p == '\0')
|
||||
break;
|
||||
len++;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
char *__bound_strcpy(char *dst, const char *src)
|
||||
{
|
||||
size_t len;
|
||||
void *p;
|
||||
|
||||
dprintf(stderr, "%s %s: strcpy start, dst=%p src=%p\n",
|
||||
__FILE__, __FUNCTION__, dst, src);
|
||||
len = __bound_strlen(src);
|
||||
p = __bound_memcpy(dst, src, len + 1);
|
||||
dprintf(stderr, "%s %s: strcpy end, p = %p\n",
|
||||
__FILE__, __FUNCTION__, p);
|
||||
return p;
|
||||
}
|
664
05/tcc-0.9.27/lib/lib-arm64.c
Normal file
664
05/tcc-0.9.27/lib/lib-arm64.c
Normal file
|
@ -0,0 +1,664 @@
|
|||
/*
|
||||
* TCC runtime library for arm64.
|
||||
*
|
||||
* Copyright (c) 2015 Edmund Grimley Evans
|
||||
*
|
||||
* Copying and distribution of this file, with or without modification,
|
||||
* are permitted in any medium without royalty provided the copyright
|
||||
* notice and this notice are preserved. This file is offered as-is,
|
||||
* without any warranty.
|
||||
*/
|
||||
|
||||
#ifdef __TINYC__
|
||||
typedef signed char int8_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef short int16_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef int int32_t;
|
||||
typedef unsigned uint32_t;
|
||||
typedef long long int64_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
void *memcpy(void*,void*,__SIZE_TYPE__);
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
void __clear_cache(void *beg, void *end)
|
||||
{
|
||||
__arm64_clear_cache(beg, end);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
uint64_t x0, x1;
|
||||
} u128_t;
|
||||
|
||||
static long double f3_zero(int sgn)
|
||||
{
|
||||
long double f;
|
||||
u128_t x = { 0, (uint64_t)sgn << 63 };
|
||||
memcpy(&f, &x, 16);
|
||||
return f;
|
||||
}
|
||||
|
||||
static long double f3_infinity(int sgn)
|
||||
{
|
||||
long double f;
|
||||
u128_t x = { 0, (uint64_t)sgn << 63 | 0x7fff000000000000 };
|
||||
memcpy(&f, &x, 16);
|
||||
return f;
|
||||
}
|
||||
|
||||
static long double f3_NaN(void)
|
||||
{
|
||||
long double f;
|
||||
#if 0
|
||||
// ARM's default NaN usually has just the top fraction bit set:
|
||||
u128_t x = { 0, 0x7fff800000000000 };
|
||||
#else
|
||||
// GCC's library sets all fraction bits:
|
||||
u128_t x = { -1, 0x7fffffffffffffff };
|
||||
#endif
|
||||
memcpy(&f, &x, 16);
|
||||
return f;
|
||||
}
|
||||
|
||||
static int fp3_convert_NaN(long double *f, int sgn, u128_t mnt)
|
||||
{
|
||||
u128_t x = { mnt.x0,
|
||||
mnt.x1 | 0x7fff800000000000 | (uint64_t)sgn << 63 };
|
||||
memcpy(f, &x, 16);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int fp3_detect_NaNs(long double *f,
|
||||
int a_sgn, int a_exp, u128_t a,
|
||||
int b_sgn, int b_exp, u128_t b)
|
||||
{
|
||||
// Detect signalling NaNs:
|
||||
if (a_exp == 32767 && (a.x0 | a.x1 << 16) && !(a.x1 >> 47 & 1))
|
||||
return fp3_convert_NaN(f, a_sgn, a);
|
||||
if (b_exp == 32767 && (b.x0 | b.x1 << 16) && !(b.x1 >> 47 & 1))
|
||||
return fp3_convert_NaN(f, b_sgn, b);
|
||||
|
||||
// Detect quiet NaNs:
|
||||
if (a_exp == 32767 && (a.x0 | a.x1 << 16))
|
||||
return fp3_convert_NaN(f, a_sgn, a);
|
||||
if (b_exp == 32767 && (b.x0 | b.x1 << 16))
|
||||
return fp3_convert_NaN(f, b_sgn, b);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void f3_unpack(int *sgn, int32_t *exp, u128_t *mnt, long double f)
|
||||
{
|
||||
u128_t x;
|
||||
memcpy(&x, &f, 16);
|
||||
*sgn = x.x1 >> 63;
|
||||
*exp = x.x1 >> 48 & 32767;
|
||||
x.x1 = x.x1 << 16 >> 16;
|
||||
if (*exp)
|
||||
x.x1 |= (uint64_t)1 << 48;
|
||||
else
|
||||
*exp = 1;
|
||||
*mnt = x;
|
||||
}
|
||||
|
||||
static u128_t f3_normalise(int32_t *exp, u128_t mnt)
|
||||
{
|
||||
int sh;
|
||||
if (!(mnt.x0 | mnt.x1))
|
||||
return mnt;
|
||||
if (!mnt.x1) {
|
||||
mnt.x1 = mnt.x0;
|
||||
mnt.x0 = 0;
|
||||
*exp -= 64;
|
||||
}
|
||||
for (sh = 32; sh; sh >>= 1) {
|
||||
if (!(mnt.x1 >> (64 - sh))) {
|
||||
mnt.x1 = mnt.x1 << sh | mnt.x0 >> (64 - sh);
|
||||
mnt.x0 = mnt.x0 << sh;
|
||||
*exp -= sh;
|
||||
}
|
||||
}
|
||||
return mnt;
|
||||
}
|
||||
|
||||
static u128_t f3_sticky_shift(int32_t sh, u128_t x)
|
||||
{
|
||||
if (sh >= 128) {
|
||||
x.x0 = !!(x.x0 | x.x1);
|
||||
x.x1 = 0;
|
||||
return x;
|
||||
}
|
||||
if (sh >= 64) {
|
||||
x.x0 = x.x1 | !!x.x0;
|
||||
x.x1 = 0;
|
||||
sh -= 64;
|
||||
}
|
||||
if (sh > 0) {
|
||||
x.x0 = x.x0 >> sh | x.x1 << (64 - sh) | !!(x.x0 << (64 - sh));
|
||||
x.x1 = x.x1 >> sh;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
static long double f3_round(int sgn, int32_t exp, u128_t x)
|
||||
{
|
||||
long double f;
|
||||
int error;
|
||||
|
||||
if (exp > 0) {
|
||||
x = f3_sticky_shift(13, x);
|
||||
}
|
||||
else {
|
||||
x = f3_sticky_shift(14 - exp, x);
|
||||
exp = 0;
|
||||
}
|
||||
|
||||
error = x.x0 & 3;
|
||||
x.x0 = x.x0 >> 2 | x.x1 << 62;
|
||||
x.x1 = x.x1 >> 2;
|
||||
|
||||
if (error == 3 || ((error == 2) & (x.x0 & 1))) {
|
||||
if (!++x.x0) {
|
||||
++x.x1;
|
||||
if (x.x1 == (uint64_t)1 << 48)
|
||||
exp = 1;
|
||||
else if (x.x1 == (uint64_t)1 << 49) {
|
||||
++exp;
|
||||
x.x0 = x.x0 >> 1 | x.x1 << 63;
|
||||
x.x1 = x.x1 >> 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (exp >= 32767)
|
||||
return f3_infinity(sgn);
|
||||
|
||||
x.x1 = x.x1 << 16 >> 16 | (uint64_t)exp << 48 | (uint64_t)sgn << 63;
|
||||
memcpy(&f, &x, 16);
|
||||
return f;
|
||||
}
|
||||
|
||||
static long double f3_add(long double fa, long double fb, int neg)
|
||||
{
|
||||
u128_t a, b, x;
|
||||
int32_t a_exp, b_exp, x_exp;
|
||||
int a_sgn, b_sgn, x_sgn;
|
||||
long double fx;
|
||||
|
||||
f3_unpack(&a_sgn, &a_exp, &a, fa);
|
||||
f3_unpack(&b_sgn, &b_exp, &b, fb);
|
||||
|
||||
if (fp3_detect_NaNs(&fx, a_sgn, a_exp, a, b_sgn, b_exp, b))
|
||||
return fx;
|
||||
|
||||
b_sgn ^= neg;
|
||||
|
||||
// Handle infinities and zeroes:
|
||||
if (a_exp == 32767 && b_exp == 32767 && a_sgn != b_sgn)
|
||||
return f3_NaN();
|
||||
if (a_exp == 32767)
|
||||
return f3_infinity(a_sgn);
|
||||
if (b_exp == 32767)
|
||||
return f3_infinity(b_sgn);
|
||||
if (!(a.x0 | a.x1 | b.x0 | b.x1))
|
||||
return f3_zero(a_sgn & b_sgn);
|
||||
|
||||
a.x1 = a.x1 << 3 | a.x0 >> 61;
|
||||
a.x0 = a.x0 << 3;
|
||||
b.x1 = b.x1 << 3 | b.x0 >> 61;
|
||||
b.x0 = b.x0 << 3;
|
||||
|
||||
if (a_exp <= b_exp) {
|
||||
a = f3_sticky_shift(b_exp - a_exp, a);
|
||||
a_exp = b_exp;
|
||||
}
|
||||
else {
|
||||
b = f3_sticky_shift(a_exp - b_exp, b);
|
||||
b_exp = a_exp;
|
||||
}
|
||||
|
||||
x_sgn = a_sgn;
|
||||
x_exp = a_exp;
|
||||
if (a_sgn == b_sgn) {
|
||||
x.x0 = a.x0 + b.x0;
|
||||
x.x1 = a.x1 + b.x1 + (x.x0 < a.x0);
|
||||
}
|
||||
else {
|
||||
x.x0 = a.x0 - b.x0;
|
||||
x.x1 = a.x1 - b.x1 - (x.x0 > a.x0);
|
||||
if (x.x1 >> 63) {
|
||||
x_sgn ^= 1;
|
||||
x.x0 = -x.x0;
|
||||
x.x1 = -x.x1 - !!x.x0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(x.x0 | x.x1))
|
||||
return f3_zero(0);
|
||||
|
||||
x = f3_normalise(&x_exp, x);
|
||||
|
||||
return f3_round(x_sgn, x_exp + 12, x);
|
||||
}
|
||||
|
||||
long double __addtf3(long double a, long double b)
|
||||
{
|
||||
return f3_add(a, b, 0);
|
||||
}
|
||||
|
||||
long double __subtf3(long double a, long double b)
|
||||
{
|
||||
return f3_add(a, b, 1);
|
||||
}
|
||||
|
||||
long double __multf3(long double fa, long double fb)
|
||||
{
|
||||
u128_t a, b, x;
|
||||
int32_t a_exp, b_exp, x_exp;
|
||||
int a_sgn, b_sgn, x_sgn;
|
||||
long double fx;
|
||||
|
||||
f3_unpack(&a_sgn, &a_exp, &a, fa);
|
||||
f3_unpack(&b_sgn, &b_exp, &b, fb);
|
||||
|
||||
if (fp3_detect_NaNs(&fx, a_sgn, a_exp, a, b_sgn, b_exp, b))
|
||||
return fx;
|
||||
|
||||
// Handle infinities and zeroes:
|
||||
if ((a_exp == 32767 && !(b.x0 | b.x1)) ||
|
||||
(b_exp == 32767 && !(a.x0 | a.x1)))
|
||||
return f3_NaN();
|
||||
if (a_exp == 32767 || b_exp == 32767)
|
||||
return f3_infinity(a_sgn ^ b_sgn);
|
||||
if (!(a.x0 | a.x1) || !(b.x0 | b.x1))
|
||||
return f3_zero(a_sgn ^ b_sgn);
|
||||
|
||||
a = f3_normalise(&a_exp, a);
|
||||
b = f3_normalise(&b_exp, b);
|
||||
|
||||
x_sgn = a_sgn ^ b_sgn;
|
||||
x_exp = a_exp + b_exp - 16352;
|
||||
|
||||
{
|
||||
// Convert to base (1 << 30), discarding bottom 6 bits, which are zero,
|
||||
// so there are (32, 30, 30, 30) bits in (a3, a2, a1, a0):
|
||||
uint64_t a0 = a.x0 << 28 >> 34;
|
||||
uint64_t b0 = b.x0 << 28 >> 34;
|
||||
uint64_t a1 = a.x0 >> 36 | a.x1 << 62 >> 34;
|
||||
uint64_t b1 = b.x0 >> 36 | b.x1 << 62 >> 34;
|
||||
uint64_t a2 = a.x1 << 32 >> 34;
|
||||
uint64_t b2 = b.x1 << 32 >> 34;
|
||||
uint64_t a3 = a.x1 >> 32;
|
||||
uint64_t b3 = b.x1 >> 32;
|
||||
// Use 16 small multiplications and additions that do not overflow:
|
||||
uint64_t x0 = a0 * b0;
|
||||
uint64_t x1 = (x0 >> 30) + a0 * b1 + a1 * b0;
|
||||
uint64_t x2 = (x1 >> 30) + a0 * b2 + a1 * b1 + a2 * b0;
|
||||
uint64_t x3 = (x2 >> 30) + a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0;
|
||||
uint64_t x4 = (x3 >> 30) + a1 * b3 + a2 * b2 + a3 * b1;
|
||||
uint64_t x5 = (x4 >> 30) + a2 * b3 + a3 * b2;
|
||||
uint64_t x6 = (x5 >> 30) + a3 * b3;
|
||||
// We now have (64, 30, 30, ...) bits in (x6, x5, x4, ...).
|
||||
// Take the top 128 bits, setting bottom bit if any lower bits were set:
|
||||
uint64_t y0 = (x5 << 34 | x4 << 34 >> 30 | x3 << 34 >> 60 |
|
||||
!!(x3 << 38 | (x2 | x1 | x0) << 34));
|
||||
uint64_t y1 = x6;
|
||||
// Top bit may be zero. Renormalise:
|
||||
if (!(y1 >> 63)) {
|
||||
y1 = y1 << 1 | y0 >> 63;
|
||||
y0 = y0 << 1;
|
||||
--x_exp;
|
||||
}
|
||||
x.x0 = y0;
|
||||
x.x1 = y1;
|
||||
}
|
||||
|
||||
return f3_round(x_sgn, x_exp, x);
|
||||
}
|
||||
|
||||
long double __divtf3(long double fa, long double fb)
|
||||
{
|
||||
u128_t a, b, x;
|
||||
int32_t a_exp, b_exp, x_exp;
|
||||
int a_sgn, b_sgn, x_sgn, i;
|
||||
long double fx;
|
||||
|
||||
f3_unpack(&a_sgn, &a_exp, &a, fa);
|
||||
f3_unpack(&b_sgn, &b_exp, &b, fb);
|
||||
|
||||
if (fp3_detect_NaNs(&fx, a_sgn, a_exp, a, b_sgn, b_exp, b))
|
||||
return fx;
|
||||
|
||||
// Handle infinities and zeroes:
|
||||
if ((a_exp == 32767 && b_exp == 32767) ||
|
||||
(!(a.x0 | a.x1) && !(b.x0 | b.x1)))
|
||||
return f3_NaN();
|
||||
if (a_exp == 32767 || !(b.x0 | b.x1))
|
||||
return f3_infinity(a_sgn ^ b_sgn);
|
||||
if (!(a.x0 | a.x1) || b_exp == 32767)
|
||||
return f3_zero(a_sgn ^ b_sgn);
|
||||
|
||||
a = f3_normalise(&a_exp, a);
|
||||
b = f3_normalise(&b_exp, b);
|
||||
|
||||
x_sgn = a_sgn ^ b_sgn;
|
||||
x_exp = a_exp - b_exp + 16395;
|
||||
|
||||
a.x0 = a.x0 >> 1 | a.x1 << 63;
|
||||
a.x1 = a.x1 >> 1;
|
||||
b.x0 = b.x0 >> 1 | b.x1 << 63;
|
||||
b.x1 = b.x1 >> 1;
|
||||
x.x0 = 0;
|
||||
x.x1 = 0;
|
||||
for (i = 0; i < 116; i++) {
|
||||
x.x1 = x.x1 << 1 | x.x0 >> 63;
|
||||
x.x0 = x.x0 << 1;
|
||||
if (a.x1 > b.x1 || (a.x1 == b.x1 && a.x0 >= b.x0)) {
|
||||
a.x1 = a.x1 - b.x1 - (a.x0 < b.x0);
|
||||
a.x0 = a.x0 - b.x0;
|
||||
x.x0 |= 1;
|
||||
}
|
||||
a.x1 = a.x1 << 1 | a.x0 >> 63;
|
||||
a.x0 = a.x0 << 1;
|
||||
}
|
||||
x.x0 |= !!(a.x0 | a.x1);
|
||||
|
||||
x = f3_normalise(&x_exp, x);
|
||||
|
||||
return f3_round(x_sgn, x_exp, x);
|
||||
}
|
||||
|
||||
long double __extendsftf2(float f)
|
||||
{
|
||||
long double fx;
|
||||
u128_t x;
|
||||
uint32_t a;
|
||||
uint64_t aa;
|
||||
memcpy(&a, &f, 4);
|
||||
aa = a;
|
||||
x.x0 = 0;
|
||||
if (!(a << 1))
|
||||
x.x1 = aa << 32;
|
||||
else if (a << 1 >> 24 == 255)
|
||||
x.x1 = (0x7fff000000000000 | aa >> 31 << 63 | aa << 41 >> 16 |
|
||||
(uint64_t)!!(a << 9) << 47);
|
||||
else
|
||||
x.x1 = (aa >> 31 << 63 | ((aa >> 23 & 255) + 16256) << 48 |
|
||||
aa << 41 >> 16);
|
||||
memcpy(&fx, &x, 16);
|
||||
return fx;
|
||||
}
|
||||
|
||||
long double __extenddftf2(double f)
|
||||
{
|
||||
long double fx;
|
||||
u128_t x;
|
||||
uint64_t a;
|
||||
memcpy(&a, &f, 8);
|
||||
x.x0 = a << 60;
|
||||
if (!(a << 1))
|
||||
x.x1 = a;
|
||||
else if (a << 1 >> 53 == 2047)
|
||||
x.x1 = (0x7fff000000000000 | a >> 63 << 63 | a << 12 >> 16 |
|
||||
(uint64_t)!!(a << 12) << 47);
|
||||
else
|
||||
x.x1 = a >> 63 << 63 | ((a >> 52 & 2047) + 15360) << 48 | a << 12 >> 16;
|
||||
memcpy(&fx, &x, 16);
|
||||
return fx;
|
||||
}
|
||||
|
||||
float __trunctfsf2(long double f)
|
||||
{
|
||||
u128_t mnt;
|
||||
int32_t exp;
|
||||
int sgn;
|
||||
uint32_t x;
|
||||
float fx;
|
||||
|
||||
f3_unpack(&sgn, &exp, &mnt, f);
|
||||
|
||||
if (exp == 32767 && (mnt.x0 | mnt.x1 << 16))
|
||||
x = 0x7fc00000 | (uint32_t)sgn << 31 | (mnt.x1 >> 25 & 0x007fffff);
|
||||
else if (exp > 16510)
|
||||
x = 0x7f800000 | (uint32_t)sgn << 31;
|
||||
else if (exp < 16233)
|
||||
x = (uint32_t)sgn << 31;
|
||||
else {
|
||||
exp -= 16257;
|
||||
x = mnt.x1 >> 23 | !!(mnt.x0 | mnt.x1 << 41);
|
||||
if (exp < 0) {
|
||||
x = x >> -exp | !!(x << (32 + exp));
|
||||
exp = 0;
|
||||
}
|
||||
if ((x & 3) == 3 || (x & 7) == 6)
|
||||
x += 4;
|
||||
x = ((x >> 2) + (exp << 23)) | (uint32_t)sgn << 31;
|
||||
}
|
||||
memcpy(&fx, &x, 4);
|
||||
return fx;
|
||||
}
|
||||
|
||||
double __trunctfdf2(long double f)
|
||||
{
|
||||
u128_t mnt;
|
||||
int32_t exp;
|
||||
int sgn;
|
||||
uint64_t x;
|
||||
double fx;
|
||||
|
||||
f3_unpack(&sgn, &exp, &mnt, f);
|
||||
|
||||
if (exp == 32767 && (mnt.x0 | mnt.x1 << 16))
|
||||
x = (0x7ff8000000000000 | (uint64_t)sgn << 63 |
|
||||
mnt.x1 << 16 >> 12 | mnt.x0 >> 60);
|
||||
else if (exp > 17406)
|
||||
x = 0x7ff0000000000000 | (uint64_t)sgn << 63;
|
||||
else if (exp < 15308)
|
||||
x = (uint64_t)sgn << 63;
|
||||
else {
|
||||
exp -= 15361;
|
||||
x = mnt.x1 << 6 | mnt.x0 >> 58 | !!(mnt.x0 << 6);
|
||||
if (exp < 0) {
|
||||
x = x >> -exp | !!(x << (64 + exp));
|
||||
exp = 0;
|
||||
}
|
||||
if ((x & 3) == 3 || (x & 7) == 6)
|
||||
x += 4;
|
||||
x = ((x >> 2) + ((uint64_t)exp << 52)) | (uint64_t)sgn << 63;
|
||||
}
|
||||
memcpy(&fx, &x, 8);
|
||||
return fx;
|
||||
}
|
||||
|
||||
int32_t __fixtfsi(long double fa)
|
||||
{
|
||||
u128_t a;
|
||||
int32_t a_exp;
|
||||
int a_sgn;
|
||||
int32_t x;
|
||||
f3_unpack(&a_sgn, &a_exp, &a, fa);
|
||||
if (a_exp < 16369)
|
||||
return 0;
|
||||
if (a_exp > 16413)
|
||||
return a_sgn ? -0x80000000 : 0x7fffffff;
|
||||
x = a.x1 >> (16431 - a_exp);
|
||||
return a_sgn ? -x : x;
|
||||
}
|
||||
|
||||
int64_t __fixtfdi(long double fa)
|
||||
{
|
||||
u128_t a;
|
||||
int32_t a_exp;
|
||||
int a_sgn;
|
||||
int64_t x;
|
||||
f3_unpack(&a_sgn, &a_exp, &a, fa);
|
||||
if (a_exp < 16383)
|
||||
return 0;
|
||||
if (a_exp > 16445)
|
||||
return a_sgn ? -0x8000000000000000 : 0x7fffffffffffffff;
|
||||
x = (a.x1 << 15 | a.x0 >> 49) >> (16446 - a_exp);
|
||||
return a_sgn ? -x : x;
|
||||
}
|
||||
|
||||
uint32_t __fixunstfsi(long double fa)
|
||||
{
|
||||
u128_t a;
|
||||
int32_t a_exp;
|
||||
int a_sgn;
|
||||
f3_unpack(&a_sgn, &a_exp, &a, fa);
|
||||
if (a_sgn || a_exp < 16369)
|
||||
return 0;
|
||||
if (a_exp > 16414)
|
||||
return -1;
|
||||
return a.x1 >> (16431 - a_exp);
|
||||
}
|
||||
|
||||
uint64_t __fixunstfdi(long double fa)
|
||||
{
|
||||
u128_t a;
|
||||
int32_t a_exp;
|
||||
int a_sgn;
|
||||
f3_unpack(&a_sgn, &a_exp, &a, fa);
|
||||
if (a_sgn || a_exp < 16383)
|
||||
return 0;
|
||||
if (a_exp > 16446)
|
||||
return -1;
|
||||
return (a.x1 << 15 | a.x0 >> 49) >> (16446 - a_exp);
|
||||
}
|
||||
|
||||
long double __floatsitf(int32_t a)
|
||||
{
|
||||
int sgn = 0;
|
||||
int exp = 16414;
|
||||
uint32_t mnt = a;
|
||||
u128_t x = { 0, 0 };
|
||||
long double f;
|
||||
int i;
|
||||
if (a) {
|
||||
if (a < 0) {
|
||||
sgn = 1;
|
||||
mnt = -mnt;
|
||||
}
|
||||
for (i = 16; i; i >>= 1)
|
||||
if (!(mnt >> (32 - i))) {
|
||||
mnt <<= i;
|
||||
exp -= i;
|
||||
}
|
||||
x.x1 = ((uint64_t)sgn << 63 | (uint64_t)exp << 48 |
|
||||
(uint64_t)(mnt << 1) << 16);
|
||||
}
|
||||
memcpy(&f, &x, 16);
|
||||
return f;
|
||||
}
|
||||
|
||||
long double __floatditf(int64_t a)
|
||||
{
|
||||
int sgn = 0;
|
||||
int exp = 16446;
|
||||
uint64_t mnt = a;
|
||||
u128_t x = { 0, 0 };
|
||||
long double f;
|
||||
int i;
|
||||
if (a) {
|
||||
if (a < 0) {
|
||||
sgn = 1;
|
||||
mnt = -mnt;
|
||||
}
|
||||
for (i = 32; i; i >>= 1)
|
||||
if (!(mnt >> (64 - i))) {
|
||||
mnt <<= i;
|
||||
exp -= i;
|
||||
}
|
||||
x.x0 = mnt << 49;
|
||||
x.x1 = (uint64_t)sgn << 63 | (uint64_t)exp << 48 | mnt << 1 >> 16;
|
||||
}
|
||||
memcpy(&f, &x, 16);
|
||||
return f;
|
||||
}
|
||||
|
||||
long double __floatunsitf(uint32_t a)
|
||||
{
|
||||
int exp = 16414;
|
||||
uint32_t mnt = a;
|
||||
u128_t x = { 0, 0 };
|
||||
long double f;
|
||||
int i;
|
||||
if (a) {
|
||||
for (i = 16; i; i >>= 1)
|
||||
if (!(mnt >> (32 - i))) {
|
||||
mnt <<= i;
|
||||
exp -= i;
|
||||
}
|
||||
x.x1 = (uint64_t)exp << 48 | (uint64_t)(mnt << 1) << 16;
|
||||
}
|
||||
memcpy(&f, &x, 16);
|
||||
return f;
|
||||
}
|
||||
|
||||
long double __floatunditf(uint64_t a)
|
||||
{
|
||||
int exp = 16446;
|
||||
uint64_t mnt = a;
|
||||
u128_t x = { 0, 0 };
|
||||
long double f;
|
||||
int i;
|
||||
if (a) {
|
||||
for (i = 32; i; i >>= 1)
|
||||
if (!(mnt >> (64 - i))) {
|
||||
mnt <<= i;
|
||||
exp -= i;
|
||||
}
|
||||
x.x0 = mnt << 49;
|
||||
x.x1 = (uint64_t)exp << 48 | mnt << 1 >> 16;
|
||||
}
|
||||
memcpy(&f, &x, 16);
|
||||
return f;
|
||||
}
|
||||
|
||||
static int f3_cmp(long double fa, long double fb)
|
||||
{
|
||||
u128_t a, b;
|
||||
memcpy(&a, &fa, 16);
|
||||
memcpy(&b, &fb, 16);
|
||||
return (!(a.x0 | a.x1 << 1 | b.x0 | b.x1 << 1) ? 0 :
|
||||
((a.x1 << 1 >> 49 == 0x7fff && (a.x0 | a.x1 << 16)) ||
|
||||
(b.x1 << 1 >> 49 == 0x7fff && (b.x0 | b.x1 << 16))) ? 2 :
|
||||
a.x1 >> 63 != b.x1 >> 63 ? (int)(b.x1 >> 63) - (int)(a.x1 >> 63) :
|
||||
a.x1 < b.x1 ? (int)(a.x1 >> 63 << 1) - 1 :
|
||||
a.x1 > b.x1 ? 1 - (int)(a.x1 >> 63 << 1) :
|
||||
a.x0 < b.x0 ? (int)(a.x1 >> 63 << 1) - 1 :
|
||||
b.x0 < a.x0 ? 1 - (int)(a.x1 >> 63 << 1) : 0);
|
||||
}
|
||||
|
||||
int __eqtf2(long double a, long double b)
|
||||
{
|
||||
return !!f3_cmp(a, b);
|
||||
}
|
||||
|
||||
int __netf2(long double a, long double b)
|
||||
{
|
||||
return !!f3_cmp(a, b);
|
||||
}
|
||||
|
||||
int __lttf2(long double a, long double b)
|
||||
{
|
||||
return f3_cmp(a, b);
|
||||
}
|
||||
|
||||
int __letf2(long double a, long double b)
|
||||
{
|
||||
return f3_cmp(a, b);
|
||||
}
|
||||
|
||||
int __gttf2(long double a, long double b)
|
||||
{
|
||||
return -f3_cmp(b, a);
|
||||
}
|
||||
|
||||
int __getf2(long double a, long double b)
|
||||
{
|
||||
return -f3_cmp(b, a);
|
||||
}
|
622
05/tcc-0.9.27/lib/libtcc1.c
Normal file
622
05/tcc-0.9.27/lib/libtcc1.c
Normal file
|
@ -0,0 +1,622 @@
|
|||
/* TCC runtime library.
|
||||
Parts of this code are (c) 2002 Fabrice Bellard
|
||||
|
||||
Copyright (C) 1987, 1988, 1992, 1994, 1995 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 into combinations with other programs,
|
||||
and to distribute those combinations 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 a combine
|
||||
executable.)
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#define W_TYPE_SIZE 32
|
||||
#define BITS_PER_UNIT 8
|
||||
|
||||
typedef int Wtype;
|
||||
typedef unsigned int UWtype;
|
||||
typedef unsigned int USItype;
|
||||
typedef long long DWtype;
|
||||
typedef unsigned long long UDWtype;
|
||||
|
||||
struct DWstruct {
|
||||
Wtype low, high;
|
||||
};
|
||||
|
||||
typedef union
|
||||
{
|
||||
struct DWstruct s;
|
||||
DWtype ll;
|
||||
} DWunion;
|
||||
|
||||
typedef long double XFtype;
|
||||
#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
|
||||
#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
|
||||
|
||||
/* the following deal with IEEE single-precision numbers */
|
||||
#define EXCESS 126
|
||||
#define SIGNBIT 0x80000000
|
||||
#define HIDDEN (1 << 23)
|
||||
#define SIGN(fp) ((fp) & SIGNBIT)
|
||||
#define EXP(fp) (((fp) >> 23) & 0xFF)
|
||||
#define MANT(fp) (((fp) & 0x7FFFFF) | HIDDEN)
|
||||
#define PACK(s,e,m) ((s) | ((e) << 23) | (m))
|
||||
|
||||
/* the following deal with IEEE double-precision numbers */
|
||||
#define EXCESSD 1022
|
||||
#define HIDDEND (1 << 20)
|
||||
#define EXPD(fp) (((fp.l.upper) >> 20) & 0x7FF)
|
||||
#define SIGND(fp) ((fp.l.upper) & SIGNBIT)
|
||||
#define MANTD(fp) (((((fp.l.upper) & 0xFFFFF) | HIDDEND) << 10) | \
|
||||
(fp.l.lower >> 22))
|
||||
#define HIDDEND_LL ((long long)1 << 52)
|
||||
#define MANTD_LL(fp) ((fp.ll & (HIDDEND_LL-1)) | HIDDEND_LL)
|
||||
#define PACKD_LL(s,e,m) (((long long)((s)+((e)<<20))<<32)|(m))
|
||||
|
||||
/* the following deal with x86 long double-precision numbers */
|
||||
#define EXCESSLD 16382
|
||||
#define EXPLD(fp) (fp.l.upper & 0x7fff)
|
||||
#define SIGNLD(fp) ((fp.l.upper) & 0x8000)
|
||||
|
||||
/* only for x86 */
|
||||
union ldouble_long {
|
||||
long double ld;
|
||||
struct {
|
||||
unsigned long long lower;
|
||||
unsigned short upper;
|
||||
} l;
|
||||
};
|
||||
|
||||
union double_long {
|
||||
double d;
|
||||
#if 1
|
||||
struct {
|
||||
unsigned int lower;
|
||||
int upper;
|
||||
} l;
|
||||
#else
|
||||
struct {
|
||||
int upper;
|
||||
unsigned int lower;
|
||||
} l;
|
||||
#endif
|
||||
long long ll;
|
||||
};
|
||||
|
||||
union float_long {
|
||||
float f;
|
||||
unsigned int l;
|
||||
};
|
||||
|
||||
/* XXX: we don't support several builtin supports for now */
|
||||
#if !defined __x86_64__ && !defined __arm__
|
||||
|
||||
/* XXX: use gcc/tcc intrinsic ? */
|
||||
#if defined __i386__
|
||||
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
|
||||
__asm__ ("subl %5,%1\n\tsbbl %3,%0" \
|
||||
: "=r" ((USItype) (sh)), \
|
||||
"=&r" ((USItype) (sl)) \
|
||||
: "0" ((USItype) (ah)), \
|
||||
"g" ((USItype) (bh)), \
|
||||
"1" ((USItype) (al)), \
|
||||
"g" ((USItype) (bl)))
|
||||
#define umul_ppmm(w1, w0, u, v) \
|
||||
__asm__ ("mull %3" \
|
||||
: "=a" ((USItype) (w0)), \
|
||||
"=d" ((USItype) (w1)) \
|
||||
: "%0" ((USItype) (u)), \
|
||||
"rm" ((USItype) (v)))
|
||||
#define udiv_qrnnd(q, r, n1, n0, dv) \
|
||||
__asm__ ("divl %4" \
|
||||
: "=a" ((USItype) (q)), \
|
||||
"=d" ((USItype) (r)) \
|
||||
: "0" ((USItype) (n0)), \
|
||||
"1" ((USItype) (n1)), \
|
||||
"rm" ((USItype) (dv)))
|
||||
#define count_leading_zeros(count, x) \
|
||||
do { \
|
||||
USItype __cbtmp; \
|
||||
__asm__ ("bsrl %1,%0" \
|
||||
: "=r" (__cbtmp) : "rm" ((USItype) (x))); \
|
||||
(count) = __cbtmp ^ 31; \
|
||||
} while (0)
|
||||
#else
|
||||
#error unsupported CPU type
|
||||
#endif
|
||||
|
||||
/* most of this code is taken from libgcc2.c from gcc */
|
||||
|
||||
static UDWtype __udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp)
|
||||
{
|
||||
DWunion ww;
|
||||
DWunion nn, dd;
|
||||
DWunion rr;
|
||||
UWtype d0, d1, n0, n1, n2;
|
||||
UWtype q0, q1;
|
||||
UWtype b, bm;
|
||||
|
||||
nn.ll = n;
|
||||
dd.ll = d;
|
||||
|
||||
d0 = dd.s.low;
|
||||
d1 = dd.s.high;
|
||||
n0 = nn.s.low;
|
||||
n1 = nn.s.high;
|
||||
|
||||
#if !defined(UDIV_NEEDS_NORMALIZATION)
|
||||
if (d1 == 0)
|
||||
{
|
||||
if (d0 > n1)
|
||||
{
|
||||
/* 0q = nn / 0D */
|
||||
|
||||
udiv_qrnnd (q0, n0, n1, n0, d0);
|
||||
q1 = 0;
|
||||
|
||||
/* Remainder in n0. */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* qq = NN / 0d */
|
||||
|
||||
if (d0 == 0)
|
||||
d0 = 1 / d0; /* Divide intentionally by zero. */
|
||||
|
||||
udiv_qrnnd (q1, n1, 0, n1, d0);
|
||||
udiv_qrnnd (q0, n0, n1, n0, d0);
|
||||
|
||||
/* Remainder in n0. */
|
||||
}
|
||||
|
||||
if (rp != 0)
|
||||
{
|
||||
rr.s.low = n0;
|
||||
rr.s.high = 0;
|
||||
*rp = rr.ll;
|
||||
}
|
||||
}
|
||||
|
||||
#else /* UDIV_NEEDS_NORMALIZATION */
|
||||
|
||||
if (d1 == 0)
|
||||
{
|
||||
if (d0 > n1)
|
||||
{
|
||||
/* 0q = nn / 0D */
|
||||
|
||||
count_leading_zeros (bm, d0);
|
||||
|
||||
if (bm != 0)
|
||||
{
|
||||
/* Normalize, i.e. make the most significant bit of the
|
||||
denominator set. */
|
||||
|
||||
d0 = d0 << bm;
|
||||
n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm));
|
||||
n0 = n0 << bm;
|
||||
}
|
||||
|
||||
udiv_qrnnd (q0, n0, n1, n0, d0);
|
||||
q1 = 0;
|
||||
|
||||
/* Remainder in n0 >> bm. */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* qq = NN / 0d */
|
||||
|
||||
if (d0 == 0)
|
||||
d0 = 1 / d0; /* Divide intentionally by zero. */
|
||||
|
||||
count_leading_zeros (bm, d0);
|
||||
|
||||
if (bm == 0)
|
||||
{
|
||||
/* From (n1 >= d0) /\ (the most significant bit of d0 is set),
|
||||
conclude (the most significant bit of n1 is set) /\ (the
|
||||
leading quotient digit q1 = 1).
|
||||
|
||||
This special case is necessary, not an optimization.
|
||||
(Shifts counts of W_TYPE_SIZE are undefined.) */
|
||||
|
||||
n1 -= d0;
|
||||
q1 = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Normalize. */
|
||||
|
||||
b = W_TYPE_SIZE - bm;
|
||||
|
||||
d0 = d0 << bm;
|
||||
n2 = n1 >> b;
|
||||
n1 = (n1 << bm) | (n0 >> b);
|
||||
n0 = n0 << bm;
|
||||
|
||||
udiv_qrnnd (q1, n1, n2, n1, d0);
|
||||
}
|
||||
|
||||
/* n1 != d0... */
|
||||
|
||||
udiv_qrnnd (q0, n0, n1, n0, d0);
|
||||
|
||||
/* Remainder in n0 >> bm. */
|
||||
}
|
||||
|
||||
if (rp != 0)
|
||||
{
|
||||
rr.s.low = n0 >> bm;
|
||||
rr.s.high = 0;
|
||||
*rp = rr.ll;
|
||||
}
|
||||
}
|
||||
#endif /* UDIV_NEEDS_NORMALIZATION */
|
||||
|
||||
else
|
||||
{
|
||||
if (d1 > n1)
|
||||
{
|
||||
/* 00 = nn / DD */
|
||||
|
||||
q0 = 0;
|
||||
q1 = 0;
|
||||
|
||||
/* Remainder in n1n0. */
|
||||
if (rp != 0)
|
||||
{
|
||||
rr.s.low = n0;
|
||||
rr.s.high = n1;
|
||||
*rp = rr.ll;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 0q = NN / dd */
|
||||
|
||||
count_leading_zeros (bm, d1);
|
||||
if (bm == 0)
|
||||
{
|
||||
/* From (n1 >= d1) /\ (the most significant bit of d1 is set),
|
||||
conclude (the most significant bit of n1 is set) /\ (the
|
||||
quotient digit q0 = 0 or 1).
|
||||
|
||||
This special case is necessary, not an optimization. */
|
||||
|
||||
/* The condition on the next line takes advantage of that
|
||||
n1 >= d1 (true due to program flow). */
|
||||
if (n1 > d1 || n0 >= d0)
|
||||
{
|
||||
q0 = 1;
|
||||
sub_ddmmss (n1, n0, n1, n0, d1, d0);
|
||||
}
|
||||
else
|
||||
q0 = 0;
|
||||
|
||||
q1 = 0;
|
||||
|
||||
if (rp != 0)
|
||||
{
|
||||
rr.s.low = n0;
|
||||
rr.s.high = n1;
|
||||
*rp = rr.ll;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UWtype m1, m0;
|
||||
/* Normalize. */
|
||||
|
||||
b = W_TYPE_SIZE - bm;
|
||||
|
||||
d1 = (d1 << bm) | (d0 >> b);
|
||||
d0 = d0 << bm;
|
||||
n2 = n1 >> b;
|
||||
n1 = (n1 << bm) | (n0 >> b);
|
||||
n0 = n0 << bm;
|
||||
|
||||
udiv_qrnnd (q0, n1, n2, n1, d1);
|
||||
umul_ppmm (m1, m0, q0, d0);
|
||||
|
||||
if (m1 > n1 || (m1 == n1 && m0 > n0))
|
||||
{
|
||||
q0--;
|
||||
sub_ddmmss (m1, m0, m1, m0, d1, d0);
|
||||
}
|
||||
|
||||
q1 = 0;
|
||||
|
||||
/* Remainder in (n1n0 - m1m0) >> bm. */
|
||||
if (rp != 0)
|
||||
{
|
||||
sub_ddmmss (n1, n0, n1, n0, m1, m0);
|
||||
rr.s.low = (n1 << b) | (n0 >> bm);
|
||||
rr.s.high = n1 >> bm;
|
||||
*rp = rr.ll;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ww.s.low = q0;
|
||||
ww.s.high = q1;
|
||||
return ww.ll;
|
||||
}
|
||||
|
||||
#define __negdi2(a) (-(a))
|
||||
|
||||
long long __divdi3(long long u, long long v)
|
||||
{
|
||||
int c = 0;
|
||||
DWunion uu, vv;
|
||||
DWtype w;
|
||||
|
||||
uu.ll = u;
|
||||
vv.ll = v;
|
||||
|
||||
if (uu.s.high < 0) {
|
||||
c = ~c;
|
||||
uu.ll = __negdi2 (uu.ll);
|
||||
}
|
||||
if (vv.s.high < 0) {
|
||||
c = ~c;
|
||||
vv.ll = __negdi2 (vv.ll);
|
||||
}
|
||||
w = __udivmoddi4 (uu.ll, vv.ll, (UDWtype *) 0);
|
||||
if (c)
|
||||
w = __negdi2 (w);
|
||||
return w;
|
||||
}
|
||||
|
||||
long long __moddi3(long long u, long long v)
|
||||
{
|
||||
int c = 0;
|
||||
DWunion uu, vv;
|
||||
DWtype w;
|
||||
|
||||
uu.ll = u;
|
||||
vv.ll = v;
|
||||
|
||||
if (uu.s.high < 0) {
|
||||
c = ~c;
|
||||
uu.ll = __negdi2 (uu.ll);
|
||||
}
|
||||
if (vv.s.high < 0)
|
||||
vv.ll = __negdi2 (vv.ll);
|
||||
|
||||
__udivmoddi4 (uu.ll, vv.ll, (UDWtype *) &w);
|
||||
if (c)
|
||||
w = __negdi2 (w);
|
||||
return w;
|
||||
}
|
||||
|
||||
unsigned long long __udivdi3(unsigned long long u, unsigned long long v)
|
||||
{
|
||||
return __udivmoddi4 (u, v, (UDWtype *) 0);
|
||||
}
|
||||
|
||||
unsigned long long __umoddi3(unsigned long long u, unsigned long long v)
|
||||
{
|
||||
UDWtype w;
|
||||
|
||||
__udivmoddi4 (u, v, &w);
|
||||
return w;
|
||||
}
|
||||
|
||||
/* XXX: fix tcc's code generator to do this instead */
|
||||
long long __ashrdi3(long long a, int b)
|
||||
{
|
||||
#ifdef __TINYC__
|
||||
DWunion u;
|
||||
u.ll = a;
|
||||
if (b >= 32) {
|
||||
u.s.low = u.s.high >> (b - 32);
|
||||
u.s.high = u.s.high >> 31;
|
||||
} else if (b != 0) {
|
||||
u.s.low = ((unsigned)u.s.low >> b) | (u.s.high << (32 - b));
|
||||
u.s.high = u.s.high >> b;
|
||||
}
|
||||
return u.ll;
|
||||
#else
|
||||
return a >> b;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* XXX: fix tcc's code generator to do this instead */
|
||||
unsigned long long __lshrdi3(unsigned long long a, int b)
|
||||
{
|
||||
#ifdef __TINYC__
|
||||
DWunion u;
|
||||
u.ll = a;
|
||||
if (b >= 32) {
|
||||
u.s.low = (unsigned)u.s.high >> (b - 32);
|
||||
u.s.high = 0;
|
||||
} else if (b != 0) {
|
||||
u.s.low = ((unsigned)u.s.low >> b) | (u.s.high << (32 - b));
|
||||
u.s.high = (unsigned)u.s.high >> b;
|
||||
}
|
||||
return u.ll;
|
||||
#else
|
||||
return a >> b;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* XXX: fix tcc's code generator to do this instead */
|
||||
long long __ashldi3(long long a, int b)
|
||||
{
|
||||
#ifdef __TINYC__
|
||||
DWunion u;
|
||||
u.ll = a;
|
||||
if (b >= 32) {
|
||||
u.s.high = (unsigned)u.s.low << (b - 32);
|
||||
u.s.low = 0;
|
||||
} else if (b != 0) {
|
||||
u.s.high = ((unsigned)u.s.high << b) | ((unsigned)u.s.low >> (32 - b));
|
||||
u.s.low = (unsigned)u.s.low << b;
|
||||
}
|
||||
return u.ll;
|
||||
#else
|
||||
return a << b;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* !__x86_64__ */
|
||||
|
||||
/* XXX: fix tcc's code generator to do this instead */
|
||||
float __floatundisf(unsigned long long a)
|
||||
{
|
||||
DWunion uu;
|
||||
XFtype r;
|
||||
|
||||
uu.ll = a;
|
||||
if (uu.s.high >= 0) {
|
||||
return (float)uu.ll;
|
||||
} else {
|
||||
r = (XFtype)uu.ll;
|
||||
r += 18446744073709551616.0;
|
||||
return (float)r;
|
||||
}
|
||||
}
|
||||
|
||||
double __floatundidf(unsigned long long a)
|
||||
{
|
||||
DWunion uu;
|
||||
XFtype r;
|
||||
|
||||
uu.ll = a;
|
||||
if (uu.s.high >= 0) {
|
||||
return (double)uu.ll;
|
||||
} else {
|
||||
r = (XFtype)uu.ll;
|
||||
r += 18446744073709551616.0;
|
||||
return (double)r;
|
||||
}
|
||||
}
|
||||
|
||||
long double __floatundixf(unsigned long long a)
|
||||
{
|
||||
DWunion uu;
|
||||
XFtype r;
|
||||
|
||||
uu.ll = a;
|
||||
if (uu.s.high >= 0) {
|
||||
return (long double)uu.ll;
|
||||
} else {
|
||||
r = (XFtype)uu.ll;
|
||||
r += 18446744073709551616.0;
|
||||
return (long double)r;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long long __fixunssfdi (float a1)
|
||||
{
|
||||
register union float_long fl1;
|
||||
register int exp;
|
||||
register unsigned long l;
|
||||
|
||||
fl1.f = a1;
|
||||
|
||||
if (fl1.l == 0)
|
||||
return (0);
|
||||
|
||||
exp = EXP (fl1.l) - EXCESS - 24;
|
||||
|
||||
l = MANT(fl1.l);
|
||||
if (exp >= 41)
|
||||
return (unsigned long long)-1;
|
||||
else if (exp >= 0)
|
||||
return (unsigned long long)l << exp;
|
||||
else if (exp >= -23)
|
||||
return l >> -exp;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
long long __fixsfdi (float a1)
|
||||
{
|
||||
long long ret; int s;
|
||||
ret = __fixunssfdi((s = a1 >= 0) ? a1 : -a1);
|
||||
return s ? ret : -ret;
|
||||
}
|
||||
|
||||
unsigned long long __fixunsdfdi (double a1)
|
||||
{
|
||||
register union double_long dl1;
|
||||
register int exp;
|
||||
register unsigned long long l;
|
||||
|
||||
dl1.d = a1;
|
||||
|
||||
if (dl1.ll == 0)
|
||||
return (0);
|
||||
|
||||
exp = EXPD (dl1) - EXCESSD - 53;
|
||||
|
||||
l = MANTD_LL(dl1);
|
||||
|
||||
if (exp >= 12)
|
||||
return (unsigned long long)-1;
|
||||
else if (exp >= 0)
|
||||
return l << exp;
|
||||
else if (exp >= -52)
|
||||
return l >> -exp;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
long long __fixdfdi (double a1)
|
||||
{
|
||||
long long ret; int s;
|
||||
ret = __fixunsdfdi((s = a1 >= 0) ? a1 : -a1);
|
||||
return s ? ret : -ret;
|
||||
}
|
||||
|
||||
#ifndef __arm__
|
||||
unsigned long long __fixunsxfdi (long double a1)
|
||||
{
|
||||
register union ldouble_long dl1;
|
||||
register int exp;
|
||||
register unsigned long long l;
|
||||
|
||||
dl1.ld = a1;
|
||||
|
||||
if (dl1.l.lower == 0 && dl1.l.upper == 0)
|
||||
return (0);
|
||||
|
||||
exp = EXPLD (dl1) - EXCESSLD - 64;
|
||||
|
||||
l = dl1.l.lower;
|
||||
|
||||
if (exp > 0)
|
||||
return (unsigned long long)-1;
|
||||
else if (exp >= -63)
|
||||
return l >> -exp;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
long long __fixxfdi (long double a1)
|
||||
{
|
||||
long long ret; int s;
|
||||
ret = __fixunsxfdi((s = a1 >= 0) ? a1 : -a1);
|
||||
return s ? ret : -ret;
|
||||
}
|
||||
#endif /* !ARM */
|
65
05/tcc-0.9.27/lib/va_list.c
Normal file
65
05/tcc-0.9.27/lib/va_list.c
Normal file
|
@ -0,0 +1,65 @@
|
|||
/* va_list.c - tinycc support for va_list on X86_64 */
|
||||
|
||||
#if defined __x86_64__
|
||||
|
||||
/* Avoid include files, they may not be available when cross compiling */
|
||||
extern void *memset(void *s, int c, __SIZE_TYPE__ n);
|
||||
extern void abort(void);
|
||||
|
||||
/* This should be in sync with our include/stdarg.h */
|
||||
enum __va_arg_type {
|
||||
__va_gen_reg, __va_float_reg, __va_stack
|
||||
};
|
||||
|
||||
/* GCC compatible definition of va_list. */
|
||||
typedef struct {
|
||||
unsigned int gp_offset;
|
||||
unsigned int fp_offset;
|
||||
union {
|
||||
unsigned int overflow_offset;
|
||||
char *overflow_arg_area;
|
||||
};
|
||||
char *reg_save_area;
|
||||
} __va_list_struct;
|
||||
|
||||
void __va_start(__va_list_struct *ap, void *fp)
|
||||
{
|
||||
memset(ap, 0, sizeof(__va_list_struct));
|
||||
*ap = *(__va_list_struct *)((char *)fp - 16);
|
||||
ap->overflow_arg_area = (char *)fp + ap->overflow_offset;
|
||||
ap->reg_save_area = (char *)fp - 176 - 16;
|
||||
}
|
||||
|
||||
void *__va_arg(__va_list_struct *ap,
|
||||
enum __va_arg_type arg_type,
|
||||
int size, int align)
|
||||
{
|
||||
size = (size + 7) & ~7;
|
||||
align = (align + 7) & ~7;
|
||||
switch (arg_type) {
|
||||
case __va_gen_reg:
|
||||
if (ap->gp_offset + size <= 48) {
|
||||
ap->gp_offset += size;
|
||||
return ap->reg_save_area + ap->gp_offset - size;
|
||||
}
|
||||
goto use_overflow_area;
|
||||
|
||||
case __va_float_reg:
|
||||
if (ap->fp_offset < 128 + 48) {
|
||||
ap->fp_offset += 16;
|
||||
return ap->reg_save_area + ap->fp_offset - 16;
|
||||
}
|
||||
size = 8;
|
||||
goto use_overflow_area;
|
||||
|
||||
case __va_stack:
|
||||
use_overflow_area:
|
||||
ap->overflow_arg_area += size;
|
||||
ap->overflow_arg_area = (char*)((long long)(ap->overflow_arg_area + align - 1) & -align);
|
||||
return ap->overflow_arg_area - size;
|
||||
|
||||
default: /* should never happen */
|
||||
abort();
|
||||
}
|
||||
}
|
||||
#endif
|
1998
05/tcc-0.9.27/libtcc.c
Normal file
1998
05/tcc-0.9.27/libtcc.c
Normal file
File diff suppressed because it is too large
Load diff
100
05/tcc-0.9.27/libtcc.h
Normal file
100
05/tcc-0.9.27/libtcc.h
Normal file
|
@ -0,0 +1,100 @@
|
|||
#ifndef LIBTCC_H
|
||||
#define LIBTCC_H
|
||||
|
||||
#ifndef LIBTCCAPI
|
||||
# define LIBTCCAPI
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct TCCState;
|
||||
|
||||
typedef struct TCCState TCCState;
|
||||
|
||||
/* create a new TCC compilation context */
|
||||
LIBTCCAPI TCCState *tcc_new(void);
|
||||
|
||||
/* free a TCC compilation context */
|
||||
LIBTCCAPI void tcc_delete(TCCState *s);
|
||||
|
||||
/* set CONFIG_TCCDIR at runtime */
|
||||
LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path);
|
||||
|
||||
/* set error/warning display callback */
|
||||
LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque,
|
||||
void (*error_func)(void *opaque, const char *msg));
|
||||
|
||||
/* set options as from command line (multiple supported) */
|
||||
LIBTCCAPI void tcc_set_options(TCCState *s, const char *str);
|
||||
|
||||
/*****************************/
|
||||
/* preprocessor */
|
||||
|
||||
/* add include path */
|
||||
LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname);
|
||||
|
||||
/* add in system include path */
|
||||
LIBTCCAPI int tcc_add_sysinclude_path(TCCState *s, const char *pathname);
|
||||
|
||||
/* define preprocessor symbol 'sym'. Can put optional value */
|
||||
LIBTCCAPI void tcc_define_symbol(TCCState *s, const char *sym, const char *value);
|
||||
|
||||
/* undefine preprocess symbol 'sym' */
|
||||
LIBTCCAPI void tcc_undefine_symbol(TCCState *s, const char *sym);
|
||||
|
||||
/*****************************/
|
||||
/* compiling */
|
||||
|
||||
/* add a file (C file, dll, object, library, ld script). Return -1 if error. */
|
||||
LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename);
|
||||
|
||||
/* compile a string containing a C source. Return -1 if error. */
|
||||
LIBTCCAPI int tcc_compile_string(TCCState *s, const char *buf);
|
||||
|
||||
/*****************************/
|
||||
/* linking commands */
|
||||
|
||||
/* set output type. MUST BE CALLED before any compilation */
|
||||
LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type);
|
||||
#define TCC_OUTPUT_MEMORY 1 /* output will be run in memory (default) */
|
||||
#define TCC_OUTPUT_EXE 2 /* executable file */
|
||||
#define TCC_OUTPUT_DLL 3 /* dynamic library */
|
||||
#define TCC_OUTPUT_OBJ 4 /* object file */
|
||||
#define TCC_OUTPUT_PREPROCESS 5 /* only preprocess (used internally) */
|
||||
|
||||
/* equivalent to -Lpath option */
|
||||
LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname);
|
||||
|
||||
/* the library name is the same as the argument of the '-l' option */
|
||||
LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname);
|
||||
|
||||
/* add a symbol to the compiled program */
|
||||
LIBTCCAPI int tcc_add_symbol(TCCState *s, const char *name, const void *val);
|
||||
|
||||
/* output an executable, library or object file. DO NOT call
|
||||
tcc_relocate() before. */
|
||||
LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename);
|
||||
|
||||
/* link and run main() function and return its value. DO NOT call
|
||||
tcc_relocate() before. */
|
||||
LIBTCCAPI int tcc_run(TCCState *s, int argc, char **argv);
|
||||
|
||||
/* do all relocations (needed before using tcc_get_symbol()) */
|
||||
LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr);
|
||||
/* possible values for 'ptr':
|
||||
- TCC_RELOCATE_AUTO : Allocate and manage memory internally
|
||||
- NULL : return required memory size for the step below
|
||||
- memory address : copy code to memory passed by the caller
|
||||
returns -1 if error. */
|
||||
#define TCC_RELOCATE_AUTO (void*)1
|
||||
|
||||
/* return symbol value or NULL if not found */
|
||||
LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
6
05/tcc-0.9.27/limits.h
Normal file
6
05/tcc-0.9.27/limits.h
Normal file
|
@ -0,0 +1,6 @@
|
|||
#ifndef _LIMITS_H
|
||||
#define _LIMITS_H
|
||||
|
||||
#include <stdc_common.h> // we define all the relevant constants here
|
||||
|
||||
#endif // _LIMITS_H
|
60
05/tcc-0.9.27/locale.h
Normal file
60
05/tcc-0.9.27/locale.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
#ifndef _LOCALE_H
|
||||
#define _LOCALE_H
|
||||
|
||||
#include <stdc_common.h>
|
||||
|
||||
struct lconv {
|
||||
char *decimal_point; /* "." */
|
||||
char *thousands_sep; /* "" */
|
||||
char *grouping; /* "" */
|
||||
char *int_curr_symbol; /* "" */
|
||||
char *currency_symbol; /* "" */
|
||||
char *mon_decimal_point; /* "" */
|
||||
char *mon_thousands_sep; /* "" */
|
||||
char *mon_grouping; /* "" */
|
||||
char *positive_sign; /* "" */
|
||||
char *negative_sign; /* "" */
|
||||
char int_frac_digits; /* CHAR_MAX */
|
||||
char frac_digits; /* CHAR_MAX */
|
||||
char p_cs_precedes; /* CHAR_MAX */
|
||||
char p_sep_by_space; /* CHAR_MAX */
|
||||
char n_cs_precedes; /* CHAR_MAX */
|
||||
char n_sep_by_space; /* CHAR_MAX */
|
||||
char p_sign_posn; /* CHAR_MAX */
|
||||
char n_sign_posn; /* CHAR_MAX */
|
||||
};
|
||||
|
||||
// these are GCC's constants, but it doesn't really matter which constants we use.
|
||||
#define LC_ALL 6
|
||||
#define LC_COLLATE 3
|
||||
#define LC_CTYPE 0
|
||||
#define LC_MONETARY 4
|
||||
#define LC_NUMERIC 1
|
||||
#define LC_TIME 2
|
||||
|
||||
char *setlocale(int category, char *locale) {
|
||||
if (!locale) return "C";
|
||||
if (*locale == 'C' && !locale[1]) {
|
||||
// yep
|
||||
return "C";
|
||||
}
|
||||
|
||||
// we only support the C locale
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
struct lconv *localeconv(void) {
|
||||
static struct lconv conv = {
|
||||
".",
|
||||
"", "", "",
|
||||
"", "", "",
|
||||
"", "", "",
|
||||
CHAR_MAX, CHAR_MAX, CHAR_MAX,
|
||||
CHAR_MAX, CHAR_MAX, CHAR_MAX,
|
||||
CHAR_MAX, CHAR_MAX
|
||||
};
|
||||
return &conv;
|
||||
}
|
||||
|
||||
#endif // _LOCALE_H
|
409
05/tcc-0.9.27/math.h
Normal file
409
05/tcc-0.9.27/math.h
Normal file
|
@ -0,0 +1,409 @@
|
|||
#ifndef _MATH_H
|
||||
#define _MATH_H
|
||||
|
||||
#include <stdc_common.h>
|
||||
#define HUGE_VAL _INFINITY // glibc defines HUGE_VAL as infinity (the C standard only requires it to be positive, funnily enough)
|
||||
#define _NAN (-(_INFINITY-_INFINITY))
|
||||
#define _PI 3.141592653589793
|
||||
#define _2PI 6.283185307179586
|
||||
#define _HALF_PI 1.5707963267948966
|
||||
#define _THREE_HALVES_PI 4.71238898038469
|
||||
|
||||
// NOTE: these functions are not IEEE 754-compliant (the C standard doesn't require them to be), but they're pretty good
|
||||
|
||||
double frexp(double value, int *exp) {
|
||||
if (value == 0) {
|
||||
*exp = 0;
|
||||
return 0;
|
||||
}
|
||||
unsigned long u = *(unsigned long *)&value, significand;
|
||||
*exp = ((u >> 52) & 0x7ff) - 1022;
|
||||
// replace exponent with 1022
|
||||
u &= 0x800fffffffffffff;
|
||||
u |= 0x3fe0000000000000;
|
||||
return *(double *)&u;
|
||||
}
|
||||
|
||||
double ldexp(double x, int exp) {
|
||||
int e;
|
||||
double y = frexp(x, &e);
|
||||
// since x = y * 2^e, x * 2^exp = y * 2^(e+exp)
|
||||
exp += e;
|
||||
if (exp < -1022) return 0;
|
||||
if (exp > 1023) return _INFINITY;
|
||||
unsigned long pow2 = (unsigned long)(exp + 1023) << 52;
|
||||
return y * *(double *)&pow2;
|
||||
}
|
||||
|
||||
double floor(double x) {
|
||||
if (x >= 0.0) {
|
||||
if (x > 1073741824.0 * 1073741824.0)
|
||||
return x; // floats this big must be integers
|
||||
return (unsigned long)x;
|
||||
} else {
|
||||
if (x < -1073741824.0 * 1073741824.0)
|
||||
return x; // floats this big must be integers
|
||||
double i = (long)x;
|
||||
if (x == i) return x;
|
||||
return i - 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
double ceil(double x) {
|
||||
double f = floor(x);
|
||||
if (x == f) return f;
|
||||
return f + 1.;
|
||||
}
|
||||
|
||||
double fabs(double x) {
|
||||
// this is better than x >= 0 ? x : -x because it deals with -0 properly
|
||||
unsigned long u = *(unsigned long *)&x;
|
||||
u &= 0x7fffffffffffffff;
|
||||
return *(double *)&u;
|
||||
}
|
||||
|
||||
double fmod(double x, double y) {
|
||||
if (y == 0.0) {
|
||||
errno = EDOM;
|
||||
return 0.0;
|
||||
}
|
||||
return x - (floor(x / y) * y);
|
||||
}
|
||||
|
||||
double _sin_taylor(double x) {
|
||||
double i;
|
||||
double term = x;
|
||||
// taylor expansion for sin: x - x³/3! + x⁵/5! - ...
|
||||
|
||||
// https://en.wikipedia.org/wiki/Kahan_summation_algorithm
|
||||
double prev = -1.0;
|
||||
double sum = 0.0;
|
||||
double c = 0.0;
|
||||
for (i = 0.0; i < 100.0 && sum != prev; ++i) {
|
||||
prev = sum;
|
||||
double y = term - c;
|
||||
double t = sum + y;
|
||||
c = (t - sum) - y;
|
||||
sum = t;
|
||||
term *= -(x * x) / ((2.0*i+2.0)*(2.0*i+3.0));
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
double _cos_taylor(double x) {
|
||||
double i;
|
||||
double term = 1.0;
|
||||
// taylor expansion for cos: 1 - x²/2! + x⁴/4! - ...
|
||||
|
||||
// https://en.wikipedia.org/wiki/Kahan_summation_algorithm
|
||||
double prev = -1.0;
|
||||
double sum = 0.0;
|
||||
double c = 0.0;
|
||||
for (i = 0.0; i < 100.0 && sum != prev; ++i) {
|
||||
prev = sum;
|
||||
double y = term - c;
|
||||
double t = sum + y;
|
||||
c = (t - sum) - y;
|
||||
sum = t;
|
||||
term *= -(x * x) / ((2.0*i+1.0)*(2.0*i+2.0));
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
double sin(double x) {
|
||||
x = fmod(x, 2.0*_PI);
|
||||
// the Taylor series works best for small inputs. so, provide _sin_taylor with a value in the range [0,π/2]
|
||||
if (x < _HALF_PI)
|
||||
return _sin_taylor(x);
|
||||
if (x < _PI)
|
||||
return _sin_taylor(_PI - x);
|
||||
if (x < _THREE_HALVES_PI)
|
||||
return -_sin_taylor(x - _PI);
|
||||
return -_sin_taylor(_2PI - x);
|
||||
}
|
||||
|
||||
double cos(double x) {
|
||||
x = fmod(x, 2.0*_PI);
|
||||
// the Taylor series works best for small inputs. so, provide _cos_taylor with a value in the range [0,π/2]
|
||||
if (x < _HALF_PI)
|
||||
return _cos_taylor(x);
|
||||
if (x < _PI)
|
||||
return -_cos_taylor(_PI - x);
|
||||
if (x < _THREE_HALVES_PI)
|
||||
return -_cos_taylor(x - _PI);
|
||||
return _cos_taylor(_2PI - x);
|
||||
}
|
||||
|
||||
double tan(double x) {
|
||||
return sin(x)/cos(x);
|
||||
}
|
||||
|
||||
// for sqrt and the inverse trigonometric functions, we use Newton's method
|
||||
// https://en.wikipedia.org/wiki/Newton%27s_method
|
||||
|
||||
double sqrt(double x) {
|
||||
if (x < 0.0) {
|
||||
errno = EDOM;
|
||||
return _NAN;
|
||||
}
|
||||
if (x == 0.0) return 0.0;
|
||||
if (x == _INFINITY) return _INFINITY;
|
||||
// we want to find the root of: f(t) = t² - x
|
||||
// f'(t) = 2t
|
||||
int exp;
|
||||
double y = frexp(x, &exp);
|
||||
if (exp & 1) {
|
||||
y *= 2;
|
||||
--exp;
|
||||
}
|
||||
// newton's method will be slow for very small or very large numbers.
|
||||
// so we have ensured that
|
||||
// 0.5 ≤ y < 2
|
||||
// and also x = y * 2^exp; sqrt(x) = sqrt(y) * 2^(exp/2) NB: we've ensured that exp is even
|
||||
|
||||
// 7 iterations seems to be more than enough for any number
|
||||
double t = y;
|
||||
t = (y / t + t) * 0.5;
|
||||
t = (y / t + t) * 0.5;
|
||||
t = (y / t + t) * 0.5;
|
||||
t = (y / t + t) * 0.5;
|
||||
t = (y / t + t) * 0.5;
|
||||
t = (y / t + t) * 0.5;
|
||||
t = (y / t + t) * 0.5;
|
||||
|
||||
return ldexp(t, exp>>1);
|
||||
|
||||
}
|
||||
|
||||
double _acos_newton(double x) {
|
||||
// we want to find the root of: f(t) = cos(t) - x
|
||||
// f'(t) = -sin(t)
|
||||
double t = _HALF_PI - x; // reasonably good first approximation
|
||||
double prev_t = -100.0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 100 && prev_t != t; ++i) {
|
||||
prev_t = t;
|
||||
t += (cos(t) - x) / sin(t);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
double _asin_newton(double x) {
|
||||
// we want to find the root of: f(t) = sin(t) - x
|
||||
// f'(t) = cos(t)
|
||||
double t = x; // reasonably good first approximation
|
||||
double prev_t = -100.0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 100 && prev_t != t; ++i) {
|
||||
prev_t = t;
|
||||
t += (x - sin(t)) / cos(t);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
double acos(double x) {
|
||||
if (x > 1.0 || x < -1.0) {
|
||||
errno = EDOM;
|
||||
return _NAN;
|
||||
}
|
||||
// Newton's method doesn't work well near -1 and 1, because f(x) / f'(x) is very large.
|
||||
if (x > 0.8)
|
||||
return _asin_newton(sqrt(1-x*x));
|
||||
if (x < -0.8)
|
||||
return _PI-_asin_newton(sqrt(1-x*x));
|
||||
|
||||
return _acos_newton(x);
|
||||
}
|
||||
|
||||
double asin(double x) {
|
||||
if (x > 1.0 || x < -1.0) {
|
||||
errno = EDOM;
|
||||
return _NAN;
|
||||
}
|
||||
// Newton's method doesn't work well near -1 and 1, because f(x) / f'(x) is very large.
|
||||
if (x > 0.8)
|
||||
return _acos_newton(sqrt(1.0-x*x));
|
||||
if (x < -0.8)
|
||||
return -_acos_newton(sqrt(1.0-x*x));
|
||||
|
||||
return _asin_newton(x);
|
||||
}
|
||||
|
||||
double atan(double x) {
|
||||
// the formula below breaks for really large inputs; tan(10^20) as a double is indistinguishable from pi/2 anyways
|
||||
if (x > 1e20) return _HALF_PI;
|
||||
if (x < -1e20) return -_HALF_PI;
|
||||
|
||||
// we can use a nice trigonometric identity here
|
||||
return asin(x / sqrt(1+x*x));
|
||||
}
|
||||
|
||||
double atan2(double y, double x) {
|
||||
if (x == 0.0) {
|
||||
if (y > 0.0) return _HALF_PI;
|
||||
if (y < 0.0) return -_HALF_PI;
|
||||
return 0.0; // this is what IEEE 754 does
|
||||
}
|
||||
|
||||
double a = atan(y/x);
|
||||
if (x > 0.0) {
|
||||
return a;
|
||||
} else if (y > 0.0) {
|
||||
return a + _PI;
|
||||
} else {
|
||||
return a - _PI;
|
||||
}
|
||||
}
|
||||
|
||||
double _exp_taylor(double x) {
|
||||
double i;
|
||||
double term = 1.0;
|
||||
// taylor expansion for exp: 1 + x/1! + x²/2! + ...
|
||||
|
||||
// https://en.wikipedia.org/wiki/Kahan_summation_algorithm
|
||||
double prev = -1.0;
|
||||
double sum = 0.0;
|
||||
double c = 0.0;
|
||||
for (i = 1.0; i < 100.0 && sum != prev; ++i) {
|
||||
prev = sum;
|
||||
double y = term - c;
|
||||
double t = sum + y;
|
||||
c = (t - sum) - y;
|
||||
sum = t;
|
||||
term *= x / i;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
double exp(double x) {
|
||||
if (x > 709.782712893384) {
|
||||
errno = ERANGE;
|
||||
return _INFINITY;
|
||||
}
|
||||
if (x == 0.0) return 1;
|
||||
if (x < -744.4400719213812)
|
||||
return 0;
|
||||
int i, e;
|
||||
double y = frexp(x, &e);
|
||||
if (e < 1.0) return _exp_taylor(x);
|
||||
// the taylor series doesn't work well for large x (positive or negative),
|
||||
// so we use the fact that exp(y*2^e) = exp(y)^(2^e)
|
||||
double value = _exp_taylor(y);
|
||||
for (i = 0; i < e; ++i)
|
||||
value *= value;
|
||||
return value;
|
||||
}
|
||||
|
||||
#define _LOG2 0.6931471805599453
|
||||
|
||||
double log(double x) {
|
||||
if (x < 0.0) {
|
||||
errno = EDOM;
|
||||
return _NAN;
|
||||
}
|
||||
if (x == 0.0) return -_INFINITY;
|
||||
if (x == 1.0) return 0.0;
|
||||
int e;
|
||||
double sum;
|
||||
double a = frexp(x, &e);
|
||||
// since x = a * 2^e, log(x) = log(a) + log(2^e) = log(a) + e log(2)
|
||||
sum = e * _LOG2;
|
||||
// now that a is in [1/2,1), the series log(a) = (a-1) - (a-1)²/2 + (a-1)³/3 - ... converges quickly
|
||||
|
||||
a -= 1;
|
||||
// https://en.wikipedia.org/wiki/Kahan_summation_algorithm
|
||||
double prev = HUGE_VAL;
|
||||
double c = 0;
|
||||
double term = a;
|
||||
double i;
|
||||
for (i = 1.0; i < 100.0 && sum != prev; ++i) {
|
||||
prev = sum;
|
||||
double y = term / i - c;
|
||||
double t = sum + y;
|
||||
c = (t - sum) - y;
|
||||
sum = t;
|
||||
term *= -a;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
#define _INVLOG10 0.43429448190325176 // = 1/log(10)
|
||||
double log10(double x) {
|
||||
return log(x) * _INVLOG10;
|
||||
}
|
||||
|
||||
double modf(double value, double *iptr) {
|
||||
double m = fmod(value, 1.0);
|
||||
if (value >= 0.0) {
|
||||
*iptr = value - m;
|
||||
return m;
|
||||
} else if (m == 0.0) {
|
||||
*iptr = value;
|
||||
return 0.0;
|
||||
} else {
|
||||
*iptr = value - m + 1.0;
|
||||
return m - 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
// double raised to the power of an integer
|
||||
double _dpowi(double x, unsigned long y) {
|
||||
double result = 1.0;
|
||||
if (y & 1) {
|
||||
--y;
|
||||
result *= x;
|
||||
}
|
||||
if (y > 0) {
|
||||
double p = _dpowi(x, y >> 1);
|
||||
result *= p * p;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
double pow(double x, double y) {
|
||||
if (x > 0.0) {
|
||||
return exp(y * log(x));
|
||||
} else if (x < 0.0) {
|
||||
if (fmod(y, 1.0) != 0) {
|
||||
errno = EDOM;
|
||||
return _NAN;
|
||||
}
|
||||
if (y > 1.6602069666338597e+19)
|
||||
return x < -1. ? -_INFINITY : 0.;
|
||||
if (y < -1.6602069666338597e+19)
|
||||
return x < -1. ? 0. : -_INFINITY;
|
||||
return _dpowi(x, (unsigned long)y);
|
||||
} else {
|
||||
if (y < 0) {
|
||||
errno = EDOM;
|
||||
return _NAN;
|
||||
}
|
||||
if (y > 0) {
|
||||
// 0^x = 0 for x>0
|
||||
return 0.;
|
||||
}
|
||||
// 0^0 = 1
|
||||
return 1.;
|
||||
}
|
||||
}
|
||||
|
||||
double cosh(double x) {
|
||||
double e = exp(x);
|
||||
return (e + 1./e) * 0.5;
|
||||
}
|
||||
|
||||
double sinh(double x) {
|
||||
double e = exp(x);
|
||||
return (e - 1./e) * 0.5;
|
||||
}
|
||||
|
||||
double tanh(double x) {
|
||||
if (x > 20.0) return 1.;
|
||||
if (x < -20.0) return -1.;
|
||||
double e = exp(x);
|
||||
double f = 1./e;
|
||||
return (e - f) / (e + f);
|
||||
}
|
||||
#endif // _MATH_H
|
21
05/tcc-0.9.27/setjmp.h
Normal file
21
05/tcc-0.9.27/setjmp.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
#ifndef _SETJMP_H
|
||||
#define _SETJMP_H
|
||||
|
||||
#include <stdc_common.h>
|
||||
|
||||
typedef long jmp_buf[3];
|
||||
|
||||
// @NONSTANDARD: we don't actually support setjmp
|
||||
|
||||
int setjmp(jmp_buf env) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __longjmp(jmp_buf env, int val, const char *filename, int line) {
|
||||
fprintf(stderr, "Error: Tried to longjmp from %s:%d with value %d\n", filename, line, val);
|
||||
_Exit(-1);
|
||||
}
|
||||
|
||||
#define longjmp(env, val) __longjmp(env, val, __FILE__, __LINE__)
|
||||
|
||||
#endif
|
253
05/tcc-0.9.27/signal.h
Normal file
253
05/tcc-0.9.27/signal.h
Normal file
|
@ -0,0 +1,253 @@
|
|||
#ifndef _SIGNAL_H
|
||||
#define _SIGNAL_H
|
||||
|
||||
|
||||
#include <stdc_common.h>
|
||||
|
||||
typedef long sig_atomic_t; // there are no "asynchronous interrupts"
|
||||
|
||||
#define SIG_DFL ((void *)0)
|
||||
#define SIG_IGN _sig_ign
|
||||
#define SIG_ERR ((void *)-1)
|
||||
|
||||
typedef void (*_Sighandler)(int);
|
||||
|
||||
struct sigaction {
|
||||
void (*sa_handler)(int);
|
||||
#define sa_sigaction sa_handler
|
||||
unsigned long sa_flags;
|
||||
void (*sa_restorer)(void);
|
||||
unsigned long sa_mask;
|
||||
};
|
||||
|
||||
unsigned char _signal_restorer[] = {
|
||||
0x48,0xb8,15,0,0,0,0,0,0,0, // mov rax, 15 (sigreturn)
|
||||
0x0f,0x05 // syscall
|
||||
};
|
||||
|
||||
#define _SIGNAL_HANDLERS 0xfff000
|
||||
#define _LE64(x) (x)&0xff, ((x)>> 8)&0xff, ((x)>>16)&0xff, ((x)>>24)&0xff, \
|
||||
((x)>>32)&0xff, ((x)>>40)&0xff, ((x)>>48)&0xff, (x)>>56
|
||||
|
||||
// we need to do this weird indirection because linux has a different
|
||||
// calling convention from us.
|
||||
|
||||
unsigned char _signal_handler[] = {
|
||||
// signal # passed in rdi
|
||||
0x48,0x89,0xf8, // mov rax, rdi (signal #)
|
||||
0x50, // push rax
|
||||
0x50, // push rax (allocate space for return value)
|
||||
0x48,0xb8,_LE64(_SIGNAL_HANDLERS), // mov rax, _SIGNAL_HANDLERS
|
||||
0x48,0x89,0xc3, // mov rbx, rax
|
||||
0x48,0x89,0xf8, // mov rax, rdi (signal #)
|
||||
0x48,0xc1,0xe0,0x03, // shl rax, 3
|
||||
0x48,0x01,0xd8, // add rax, rbx
|
||||
0x48,0x89,0xc3, // mov rbx, rax
|
||||
0x48,0x8b,0x03, // mov rax, [rbx]
|
||||
0xff,0xd0, // call rax
|
||||
0x48,0x81,0xc4,16,0,0,0, // add rsp, 16
|
||||
0xc3 // ret
|
||||
};
|
||||
|
||||
#define _SA_RESTORER 0x04000000
|
||||
#define SA_SIGINFO 4
|
||||
#define SA_RESETHAND 0x80000000
|
||||
|
||||
int __sigaction(int signum, const struct sigaction *act, struct sigaction *oldact) {
|
||||
return __syscall(13, signum, act, oldact, 8, 0, 0);
|
||||
}
|
||||
|
||||
void sigemptyset(unsigned long *set) {
|
||||
*set = 0;
|
||||
}
|
||||
|
||||
void _sig_ign(int signal) {
|
||||
return;
|
||||
}
|
||||
|
||||
static unsigned long _sig_mask = 0;
|
||||
|
||||
_Sighandler signal(int sig, _Sighandler func) {
|
||||
void **handlers = _SIGNAL_HANDLERS;
|
||||
_Sighandler ret = handlers[sig];
|
||||
if (func == SIG_IGN) {
|
||||
func = _sig_ign;
|
||||
}
|
||||
handlers[sig] = func;
|
||||
|
||||
if (func == SIG_DFL) {
|
||||
_sig_mask &= ~(1ul << (sig-1));
|
||||
} else {
|
||||
_sig_mask |= 1ul << (sig-1);
|
||||
}
|
||||
struct sigaction act = {0};
|
||||
act.sa_handler = func == SIG_DFL ? SIG_DFL : (void*)_signal_handler;
|
||||
act.sa_mask = _sig_mask;
|
||||
act.sa_flags = _SA_RESTORER;
|
||||
act.sa_restorer = _signal_restorer;
|
||||
__sigaction(sig, &act, NULL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int raise(int signal) {
|
||||
return kill(getpid(), signal);
|
||||
}
|
||||
|
||||
#define FPE_INTDIV 1
|
||||
#define FPE_FLTDIV 3
|
||||
|
||||
#define __SI_MAX_SIZE 128
|
||||
#if __WORDSIZE == 64
|
||||
# define __SI_PAD_SIZE ((__SI_MAX_SIZE / sizeof (int)) - 4)
|
||||
#else
|
||||
# define __SI_PAD_SIZE ((__SI_MAX_SIZE / sizeof (int)) - 3)
|
||||
#endif
|
||||
|
||||
#ifndef __SI_ALIGNMENT
|
||||
# define __SI_ALIGNMENT /* nothing */
|
||||
#endif
|
||||
#ifndef __SI_BAND_TYPE
|
||||
# define __SI_BAND_TYPE long int
|
||||
#endif
|
||||
#ifndef __SI_CLOCK_T
|
||||
# define __SI_CLOCK_T __clock_t
|
||||
#endif
|
||||
#ifndef __SI_ERRNO_THEN_CODE
|
||||
# define __SI_ERRNO_THEN_CODE 1
|
||||
#endif
|
||||
#ifndef __SI_HAVE_SIGSYS
|
||||
# define __SI_HAVE_SIGSYS 1
|
||||
#endif
|
||||
#ifndef __SI_SIGFAULT_ADDL
|
||||
# define __SI_SIGFAULT_ADDL /* nothing */
|
||||
#endif
|
||||
|
||||
typedef int __pid_t;
|
||||
typedef unsigned __uid_t;
|
||||
|
||||
union __sigval
|
||||
{
|
||||
int __sival_int;
|
||||
void *__sival_ptr;
|
||||
};
|
||||
|
||||
typedef union __sigval __sigval_t;
|
||||
typedef long __clock_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int si_signo; /* Signal number. */
|
||||
#if __SI_ERRNO_THEN_CODE
|
||||
int si_errno; /* If non-zero, an errno value associated with
|
||||
this signal, as defined in <errno.h>. */
|
||||
int si_code; /* Signal code. */
|
||||
#else
|
||||
int si_code;
|
||||
int si_errno;
|
||||
#endif
|
||||
#if __WORDSIZE == 64
|
||||
int __pad0; /* Explicit padding. */
|
||||
#endif
|
||||
|
||||
union
|
||||
{
|
||||
int _pad[__SI_PAD_SIZE];
|
||||
|
||||
/* kill(). */
|
||||
struct
|
||||
{
|
||||
__pid_t si_pid; /* Sending process ID. */
|
||||
__uid_t si_uid; /* Real user ID of sending process. */
|
||||
} _kill;
|
||||
|
||||
/* POSIX.1b timers. */
|
||||
struct
|
||||
{
|
||||
int si_tid; /* Timer ID. */
|
||||
int si_overrun; /* Overrun count. */
|
||||
__sigval_t si_sigval; /* Signal value. */
|
||||
} _timer;
|
||||
|
||||
/* POSIX.1b signals. */
|
||||
struct
|
||||
{
|
||||
__pid_t si_pid; /* Sending process ID. */
|
||||
__uid_t si_uid; /* Real user ID of sending process. */
|
||||
__sigval_t si_sigval; /* Signal value. */
|
||||
} _rt;
|
||||
|
||||
/* SIGCHLD. */
|
||||
struct
|
||||
{
|
||||
__pid_t si_pid; /* Which child. */
|
||||
__uid_t si_uid; /* Real user ID of sending process. */
|
||||
int si_status; /* Exit value or signal. */
|
||||
__SI_CLOCK_T si_utime;
|
||||
__SI_CLOCK_T si_stime;
|
||||
} _sigchld;
|
||||
|
||||
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS. */
|
||||
struct
|
||||
{
|
||||
void *si_addr; /* Faulting insn/memory ref. */
|
||||
__SI_SIGFAULT_ADDL
|
||||
short int si_addr_lsb; /* Valid LSB of the reported address. */
|
||||
union
|
||||
{
|
||||
/* used when si_code=SEGV_BNDERR */
|
||||
struct
|
||||
{
|
||||
void *_lower;
|
||||
void *_upper;
|
||||
} _addr_bnd;
|
||||
/* used when si_code=SEGV_PKUERR */
|
||||
uint32_t _pkey;
|
||||
} _bounds;
|
||||
} _sigfault;
|
||||
|
||||
/* SIGPOLL. */
|
||||
struct
|
||||
{
|
||||
__SI_BAND_TYPE si_band; /* Band event for SIGPOLL. */
|
||||
int si_fd;
|
||||
} _sigpoll;
|
||||
|
||||
/* SIGSYS. */
|
||||
#if __SI_HAVE_SIGSYS
|
||||
struct
|
||||
{
|
||||
void *_call_addr; /* Calling user insn. */
|
||||
int _syscall; /* Triggering system call number. */
|
||||
unsigned int _arch; /* AUDIT_ARCH_* of syscall. */
|
||||
} _sigsys;
|
||||
#endif
|
||||
} _sifields;
|
||||
} siginfo_t __SI_ALIGNMENT;
|
||||
|
||||
|
||||
/* X/Open requires some more fields with fixed names. */
|
||||
#define si_pid _sifields._kill.si_pid
|
||||
#define si_uid _sifields._kill.si_uid
|
||||
#define si_timerid _sifields._timer.si_tid
|
||||
#define si_overrun _sifields._timer.si_overrun
|
||||
#define si_status _sifields._sigchld.si_status
|
||||
#define si_utime _sifields._sigchld.si_utime
|
||||
#define si_stime _sifields._sigchld.si_stime
|
||||
#define si_value _sifields._rt.si_sigval
|
||||
#define si_int _sifields._rt.si_sigval.sival_int
|
||||
#define si_ptr _sifields._rt.si_sigval.sival_ptr
|
||||
#define si_addr _sifields._sigfault.si_addr
|
||||
#define si_addr_lsb _sifields._sigfault.si_addr_lsb
|
||||
#define si_lower _sifields._sigfault._bounds._addr_bnd._lower
|
||||
#define si_upper _sifields._sigfault._bounds._addr_bnd._upper
|
||||
#define si_pkey _sifields._sigfault._bounds._pkey
|
||||
#define si_band _sifields._sigpoll.si_band
|
||||
#define si_fd _sifields._sigpoll.si_fd
|
||||
#if __SI_HAVE_SIGSYS
|
||||
# define si_call_addr _sifields._sigsys._call_addr
|
||||
# define si_syscall _sifields._sigsys._syscall
|
||||
# define si_arch _sifields._sigsys._arch
|
||||
#endif
|
||||
|
||||
|
||||
#endif // _SIGNAL_H
|
234
05/tcc-0.9.27/stab.def
Normal file
234
05/tcc-0.9.27/stab.def
Normal file
|
@ -0,0 +1,234 @@
|
|||
/* Table of DBX symbol codes for the GNU system.
|
||||
Copyright (C) 1988, 1997 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C 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.
|
||||
|
||||
The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* This contains contribution from Cygnus Support. */
|
||||
// random page break character for some reason
|
||||
/* Global variable. Only the name is significant.
|
||||
To find the address, look in the corresponding external symbol. */
|
||||
__define_stab (N_GSYM, 0x20, "GSYM")
|
||||
|
||||
/* Function name for BSD Fortran. Only the name is significant.
|
||||
To find the address, look in the corresponding external symbol. */
|
||||
__define_stab (N_FNAME, 0x22, "FNAME")
|
||||
|
||||
/* Function name or text-segment variable for C. Value is its address.
|
||||
Desc is supposedly starting line number, but GCC doesn't set it
|
||||
and DBX seems not to miss it. */
|
||||
__define_stab (N_FUN, 0x24, "FUN")
|
||||
|
||||
/* Data-segment variable with internal linkage. Value is its address.
|
||||
"Static Sym". */
|
||||
__define_stab (N_STSYM, 0x26, "STSYM")
|
||||
|
||||
/* BSS-segment variable with internal linkage. Value is its address. */
|
||||
__define_stab (N_LCSYM, 0x28, "LCSYM")
|
||||
|
||||
/* Name of main routine. Only the name is significant.
|
||||
This is not used in C. */
|
||||
__define_stab (N_MAIN, 0x2a, "MAIN")
|
||||
|
||||
/* Global symbol in Pascal.
|
||||
Supposedly the value is its line number; I'm skeptical. */
|
||||
__define_stab (N_PC, 0x30, "PC")
|
||||
|
||||
/* Number of symbols: 0, files,,funcs,lines according to Ultrix V4.0. */
|
||||
__define_stab (N_NSYMS, 0x32, "NSYMS")
|
||||
|
||||
/* "No DST map for sym: name, ,0,type,ignored" according to Ultrix V4.0. */
|
||||
__define_stab (N_NOMAP, 0x34, "NOMAP")
|
||||
|
||||
/* New stab from Solaris. I don't know what it means, but it
|
||||
don't seem to contain useful information. */
|
||||
__define_stab (N_OBJ, 0x38, "OBJ")
|
||||
|
||||
/* New stab from Solaris. I don't know what it means, but it
|
||||
don't seem to contain useful information. Possibly related to the
|
||||
optimization flags used in this module. */
|
||||
__define_stab (N_OPT, 0x3c, "OPT")
|
||||
|
||||
/* Register variable. Value is number of register. */
|
||||
__define_stab (N_RSYM, 0x40, "RSYM")
|
||||
|
||||
/* Modula-2 compilation unit. Can someone say what info it contains? */
|
||||
__define_stab (N_M2C, 0x42, "M2C")
|
||||
|
||||
/* Line number in text segment. Desc is the line number;
|
||||
value is corresponding address. */
|
||||
__define_stab (N_SLINE, 0x44, "SLINE")
|
||||
|
||||
/* Similar, for data segment. */
|
||||
__define_stab (N_DSLINE, 0x46, "DSLINE")
|
||||
|
||||
/* Similar, for bss segment. */
|
||||
__define_stab (N_BSLINE, 0x48, "BSLINE")
|
||||
|
||||
/* Sun's source-code browser stabs. ?? Don't know what the fields are.
|
||||
Supposedly the field is "path to associated .cb file". THIS VALUE
|
||||
OVERLAPS WITH N_BSLINE! */
|
||||
__define_stab (N_BROWS, 0x48, "BROWS")
|
||||
|
||||
/* GNU Modula-2 definition module dependency. Value is the modification time
|
||||
of the definition file. Other is non-zero if it is imported with the
|
||||
GNU M2 keyword %INITIALIZE. Perhaps N_M2C can be used if there
|
||||
are enough empty fields? */
|
||||
__define_stab(N_DEFD, 0x4a, "DEFD")
|
||||
|
||||
/* THE FOLLOWING TWO STAB VALUES CONFLICT. Happily, one is for Modula-2
|
||||
and one is for C++. Still,... */
|
||||
/* GNU C++ exception variable. Name is variable name. */
|
||||
__define_stab (N_EHDECL, 0x50, "EHDECL")
|
||||
/* Modula2 info "for imc": name,,0,0,0 according to Ultrix V4.0. */
|
||||
__define_stab (N_MOD2, 0x50, "MOD2")
|
||||
|
||||
/* GNU C++ `catch' clause. Value is its address. Desc is nonzero if
|
||||
this entry is immediately followed by a CAUGHT stab saying what exception
|
||||
was caught. Multiple CAUGHT stabs means that multiple exceptions
|
||||
can be caught here. If Desc is 0, it means all exceptions are caught
|
||||
here. */
|
||||
__define_stab (N_CATCH, 0x54, "CATCH")
|
||||
|
||||
/* Structure or union element. Value is offset in the structure. */
|
||||
__define_stab (N_SSYM, 0x60, "SSYM")
|
||||
|
||||
/* Name of main source file.
|
||||
Value is starting text address of the compilation. */
|
||||
__define_stab (N_SO, 0x64, "SO")
|
||||
|
||||
/* Automatic variable in the stack. Value is offset from frame pointer.
|
||||
Also used for type descriptions. */
|
||||
__define_stab (N_LSYM, 0x80, "LSYM")
|
||||
|
||||
/* Beginning of an include file. Only Sun uses this.
|
||||
In an object file, only the name is significant.
|
||||
The Sun linker puts data into some of the other fields. */
|
||||
__define_stab (N_BINCL, 0x82, "BINCL")
|
||||
|
||||
/* Name of sub-source file (#include file).
|
||||
Value is starting text address of the compilation. */
|
||||
__define_stab (N_SOL, 0x84, "SOL")
|
||||
|
||||
/* Parameter variable. Value is offset from argument pointer.
|
||||
(On most machines the argument pointer is the same as the frame pointer. */
|
||||
__define_stab (N_PSYM, 0xa0, "PSYM")
|
||||
|
||||
/* End of an include file. No name.
|
||||
This and N_BINCL act as brackets around the file's output.
|
||||
In an object file, there is no significant data in this entry.
|
||||
The Sun linker puts data into some of the fields. */
|
||||
__define_stab (N_EINCL, 0xa2, "EINCL")
|
||||
|
||||
/* Alternate entry point. Value is its address. */
|
||||
__define_stab (N_ENTRY, 0xa4, "ENTRY")
|
||||
|
||||
/* Beginning of lexical block.
|
||||
The desc is the nesting level in lexical blocks.
|
||||
The value is the address of the start of the text for the block.
|
||||
The variables declared inside the block *precede* the N_LBRAC symbol. */
|
||||
__define_stab (N_LBRAC, 0xc0, "LBRAC")
|
||||
|
||||
/* Place holder for deleted include file. Replaces a N_BINCL and everything
|
||||
up to the corresponding N_EINCL. The Sun linker generates these when
|
||||
it finds multiple identical copies of the symbols from an include file.
|
||||
This appears only in output from the Sun linker. */
|
||||
__define_stab (N_EXCL, 0xc2, "EXCL")
|
||||
|
||||
/* Modula-2 scope information. Can someone say what info it contains? */
|
||||
__define_stab (N_SCOPE, 0xc4, "SCOPE")
|
||||
|
||||
/* End of a lexical block. Desc matches the N_LBRAC's desc.
|
||||
The value is the address of the end of the text for the block. */
|
||||
__define_stab (N_RBRAC, 0xe0, "RBRAC")
|
||||
|
||||
/* Begin named common block. Only the name is significant. */
|
||||
__define_stab (N_BCOMM, 0xe2, "BCOMM")
|
||||
|
||||
/* End named common block. Only the name is significant
|
||||
(and it should match the N_BCOMM). */
|
||||
__define_stab (N_ECOMM, 0xe4, "ECOMM")
|
||||
|
||||
/* End common (local name): value is address.
|
||||
I'm not sure how this is used. */
|
||||
__define_stab (N_ECOML, 0xe8, "ECOML")
|
||||
|
||||
/* These STAB's are used on Gould systems for Non-Base register symbols
|
||||
or something like that. FIXME. I have assigned the values at random
|
||||
since I don't have a Gould here. Fixups from Gould folk welcome... */
|
||||
__define_stab (N_NBTEXT, 0xF0, "NBTEXT")
|
||||
__define_stab (N_NBDATA, 0xF2, "NBDATA")
|
||||
__define_stab (N_NBBSS, 0xF4, "NBBSS")
|
||||
__define_stab (N_NBSTS, 0xF6, "NBSTS")
|
||||
__define_stab (N_NBLCS, 0xF8, "NBLCS")
|
||||
|
||||
/* Second symbol entry containing a length-value for the preceding entry.
|
||||
The value is the length. */
|
||||
__define_stab (N_LENG, 0xfe, "LENG")
|
||||
// random page break character for some reason
|
||||
/* The above information, in matrix format.
|
||||
|
||||
STAB MATRIX
|
||||
_________________________________________________
|
||||
| 00 - 1F are not dbx stab symbols |
|
||||
| In most cases, the low bit is the EXTernal bit|
|
||||
|
||||
| 00 UNDEF | 02 ABS | 04 TEXT | 06 DATA |
|
||||
| 01 |EXT | 03 |EXT | 05 |EXT | 07 |EXT |
|
||||
|
||||
| 08 BSS | 0A INDR | 0C FN_SEQ | 0E |
|
||||
| 09 |EXT | 0B | 0D | 0F |
|
||||
|
||||
| 10 | 12 COMM | 14 SETA | 16 SETT |
|
||||
| 11 | 13 | 15 | 17 |
|
||||
|
||||
| 18 SETD | 1A SETB | 1C SETV | 1E WARNING|
|
||||
| 19 | 1B | 1D | 1F FN |
|
||||
|
||||
|_______________________________________________|
|
||||
| Debug entries with bit 01 set are unused. |
|
||||
| 20 GSYM | 22 FNAME | 24 FUN | 26 STSYM |
|
||||
| 28 LCSYM | 2A MAIN | 2C | 2E |
|
||||
| 30 PC | 32 NSYMS | 34 NOMAP | 36 |
|
||||
| 38 OBJ | 3A | 3C OPT | 3E |
|
||||
| 40 RSYM | 42 M2C | 44 SLINE | 46 DSLINE |
|
||||
| 48 BSLINE*| 4A DEFD | 4C | 4E |
|
||||
| 50 EHDECL*| 52 | 54 CATCH | 56 |
|
||||
| 58 | 5A | 5C | 5E |
|
||||
| 60 SSYM | 62 | 64 SO | 66 |
|
||||
| 68 | 6A | 6C | 6E |
|
||||
| 70 | 72 | 74 | 76 |
|
||||
| 78 | 7A | 7C | 7E |
|
||||
| 80 LSYM | 82 BINCL | 84 SOL | 86 |
|
||||
| 88 | 8A | 8C | 8E |
|
||||
| 90 | 92 | 94 | 96 |
|
||||
| 98 | 9A | 9C | 9E |
|
||||
| A0 PSYM | A2 EINCL | A4 ENTRY | A6 |
|
||||
| A8 | AA | AC | AE |
|
||||
| B0 | B2 | B4 | B6 |
|
||||
| B8 | BA | BC | BE |
|
||||
| C0 LBRAC | C2 EXCL | C4 SCOPE | C6 |
|
||||
| C8 | CA | CC | CE |
|
||||
| D0 | D2 | D4 | D6 |
|
||||
| D8 | DA | DC | DE |
|
||||
| E0 RBRAC | E2 BCOMM | E4 ECOMM | E6 |
|
||||
| E8 ECOML | EA | EC | EE |
|
||||
| F0 | F2 | F4 | F6 |
|
||||
| F8 | FA | FC | FE LENG |
|
||||
+-----------------------------------------------+
|
||||
* 50 EHDECL is also MOD2.
|
||||
* 48 BSLINE is also BROWS.
|
||||
*/
|
17
05/tcc-0.9.27/stab.h
Normal file
17
05/tcc-0.9.27/stab.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
#ifndef __GNU_STAB__
|
||||
|
||||
/* Indicate the GNU stab.h is in use. */
|
||||
|
||||
#define __GNU_STAB__
|
||||
|
||||
#define __define_stab(NAME, CODE, STRING) NAME=CODE,
|
||||
|
||||
enum __stab_debug_code
|
||||
{
|
||||
#include "stab.def"
|
||||
LAST_UNUSED_STAB_CODE
|
||||
};
|
||||
|
||||
#undef __define_stab
|
||||
|
||||
#endif /* __GNU_STAB_ */
|
10
05/tcc-0.9.27/stdarg.h
Normal file
10
05/tcc-0.9.27/stdarg.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#ifndef _STDARG_H
|
||||
#define _STDARG_H
|
||||
|
||||
typedef unsigned long va_list;
|
||||
|
||||
#define va_start(list, arg) ((list) = (unsigned long)&arg)
|
||||
#define va_arg(list, type) (*((type *)(list += ((sizeof(type) + 7) & 0xfffffffffffffff8))))
|
||||
#define va_end(list)
|
||||
|
||||
#endif // _STDARG_H
|
693
05/tcc-0.9.27/stdc_common.h
Normal file
693
05/tcc-0.9.27/stdc_common.h
Normal file
|
@ -0,0 +1,693 @@
|
|||
#ifndef _STDC_COMMON_H
|
||||
#define _STDC_COMMON_H
|
||||
|
||||
#define signed
|
||||
#define volatile
|
||||
#define register
|
||||
#define const
|
||||
#define NULL ((void*)0)
|
||||
|
||||
typedef unsigned char uint8_t;
|
||||
typedef char int8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef short int16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef int int32_t;
|
||||
typedef unsigned long uint64_t;
|
||||
typedef long int64_t;
|
||||
typedef unsigned long size_t;
|
||||
typedef long ptrdiff_t;
|
||||
typedef unsigned long uintptr_t;
|
||||
typedef long intptr_t;
|
||||
typedef long ssize_t;
|
||||
|
||||
#define INT8_MAX 0x7f
|
||||
#define INT8_MIN (-0x80)
|
||||
#define INT16_MAX 0x7fff
|
||||
#define INT16_MIN (-0x8000)
|
||||
#define INT32_MAX 0x7fffffff
|
||||
#define INT32_MIN (-0x80000000)
|
||||
#define INT64_MAX 0x7fffffffffffffff
|
||||
#define INT64_MIN (-0x8000000000000000)
|
||||
#define UINT8_MAX 0xff
|
||||
#define UINT16_MAX 0xffff
|
||||
#define UINT32_MAX 0xffffffff
|
||||
#define UINT64_MAX 0xffffffffffffffff
|
||||
#define CHAR_BIT 8
|
||||
#define MB_LEN_MAX 4
|
||||
#define CHAR_MIN INT8_MIN
|
||||
#define CHAR_MAX INT8_MAX
|
||||
#define SCHAR_MIN INT8_MIN
|
||||
#define SCHAR_MAX INT8_MAX
|
||||
#define INT_MIN INT32_MIN
|
||||
#define INT_MAX INT32_MAX
|
||||
#define LONG_MIN INT64_MIN
|
||||
#define LONG_MAX INT64_MAX
|
||||
#define SHRT_MIN INT16_MIN
|
||||
#define SHRT_MAX INT16_MAX
|
||||
#define UCHAR_MAX UINT8_MAX
|
||||
#define USHRT_MAX UINT16_MAX
|
||||
#define UINT_MAX UINT32_MAX
|
||||
#define ULONG_MAX UINT64_MAX
|
||||
|
||||
static unsigned char __syscall_data[] = {
|
||||
// mov rax, [rsp+24]
|
||||
0x48, 0x8b, 0x84, 0x24, 24, 0, 0, 0,
|
||||
// mov rdi, rax
|
||||
0x48, 0x89, 0xc7,
|
||||
// mov rax, [rsp+32]
|
||||
0x48, 0x8b, 0x84, 0x24, 32, 0, 0, 0,
|
||||
// mov rsi, rax
|
||||
0x48, 0x89, 0xc6,
|
||||
// mov rax, [rsp+40]
|
||||
0x48, 0x8b, 0x84, 0x24, 40, 0, 0, 0,
|
||||
// mov rdx, rax
|
||||
0x48, 0x89, 0xc2,
|
||||
// mov rax, [rsp+48]
|
||||
0x48, 0x8b, 0x84, 0x24, 48, 0, 0, 0,
|
||||
// mov r10, rax
|
||||
0x49, 0x89, 0xc2,
|
||||
// mov rax, [rsp+56]
|
||||
0x48, 0x8b, 0x84, 0x24, 56, 0, 0, 0,
|
||||
// mov r8, rax
|
||||
0x49, 0x89, 0xc0,
|
||||
// mov rax, [rsp+64]
|
||||
0x48, 0x8b, 0x84, 0x24, 64, 0, 0, 0,
|
||||
// mov r9, rax
|
||||
0x49, 0x89, 0xc1,
|
||||
// mov rax, [rsp+16]
|
||||
0x48, 0x8b, 0x84, 0x24, 16, 0, 0, 0,
|
||||
// syscall
|
||||
0x0f, 0x05,
|
||||
// mov [rsp+8], rax
|
||||
0x48, 0x89, 0x84, 0x24, 8, 0, 0, 0,
|
||||
// ret
|
||||
0xc3
|
||||
};
|
||||
|
||||
#define __syscall(no, arg1, arg2, arg3, arg4, arg5, arg6)\
|
||||
(((unsigned long (*)(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long))__syscall_data)\
|
||||
(no, arg1, arg2, arg3, arg4, arg5, arg6))
|
||||
|
||||
// we need to define ucontext_t
|
||||
# define __ctx(fld) fld
|
||||
typedef long long int greg_t;
|
||||
#define __NGREG 23
|
||||
typedef greg_t gregset_t[__NGREG];
|
||||
#define _SIGSET_NWORDS (1024 / (8 * sizeof (unsigned long int)))
|
||||
typedef struct
|
||||
{
|
||||
unsigned long int __val[_SIGSET_NWORDS];
|
||||
} __sigset_t, sigset_t;
|
||||
typedef struct
|
||||
{
|
||||
void *ss_sp;
|
||||
int ss_flags;
|
||||
size_t ss_size;
|
||||
} stack_t;
|
||||
enum
|
||||
{
|
||||
REG_R8 = 0,
|
||||
# define REG_R8 REG_R8
|
||||
REG_R9,
|
||||
# define REG_R9 REG_R9
|
||||
REG_R10,
|
||||
# define REG_R10 REG_R10
|
||||
REG_R11,
|
||||
# define REG_R11 REG_R11
|
||||
REG_R12,
|
||||
# define REG_R12 REG_R12
|
||||
REG_R13,
|
||||
# define REG_R13 REG_R13
|
||||
REG_R14,
|
||||
# define REG_R14 REG_R14
|
||||
REG_R15,
|
||||
# define REG_R15 REG_R15
|
||||
REG_RDI,
|
||||
# define REG_RDI REG_RDI
|
||||
REG_RSI,
|
||||
# define REG_RSI REG_RSI
|
||||
REG_RBP,
|
||||
# define REG_RBP REG_RBP
|
||||
REG_RBX,
|
||||
# define REG_RBX REG_RBX
|
||||
REG_RDX,
|
||||
# define REG_RDX REG_RDX
|
||||
REG_RAX,
|
||||
# define REG_RAX REG_RAX
|
||||
REG_RCX,
|
||||
# define REG_RCX REG_RCX
|
||||
REG_RSP,
|
||||
# define REG_RSP REG_RSP
|
||||
REG_RIP,
|
||||
# define REG_RIP REG_RIP
|
||||
REG_EFL,
|
||||
# define REG_EFL REG_EFL
|
||||
REG_CSGSFS, /* Actually short cs, gs, fs, __pad0. */
|
||||
# define REG_CSGSFS REG_CSGSFS
|
||||
REG_ERR,
|
||||
# define REG_ERR REG_ERR
|
||||
REG_TRAPNO,
|
||||
# define REG_TRAPNO REG_TRAPNO
|
||||
REG_OLDMASK,
|
||||
# define REG_OLDMASK REG_OLDMASK
|
||||
REG_CR2
|
||||
# define REG_CR2 REG_CR2
|
||||
};
|
||||
struct _libc_fpxreg
|
||||
{
|
||||
unsigned short int __ctx(significand)[4];
|
||||
unsigned short int __ctx(exponent);
|
||||
unsigned short int __glibc_reserved1[3];
|
||||
};
|
||||
struct _libc_xmmreg
|
||||
{
|
||||
uint32_t __ctx(element)[4];
|
||||
};
|
||||
struct _libc_fpstate
|
||||
{
|
||||
uint16_t __ctx(cwd);
|
||||
uint16_t __ctx(swd);
|
||||
uint16_t __ctx(ftw);
|
||||
uint16_t __ctx(fop);
|
||||
uint64_t __ctx(rip);
|
||||
uint64_t __ctx(rdp);
|
||||
uint32_t __ctx(mxcsr);
|
||||
uint32_t __ctx(mxcr_mask);
|
||||
struct _libc_fpxreg _st[8];
|
||||
struct _libc_xmmreg _xmm[16];
|
||||
uint32_t __glibc_reserved1[24];
|
||||
};
|
||||
typedef struct _libc_fpstate *fpregset_t;
|
||||
typedef struct {
|
||||
gregset_t __ctx(gregs);
|
||||
fpregset_t __ctx(fpregs);
|
||||
unsigned long long __reserved1 [8];
|
||||
} mcontext_t;
|
||||
typedef struct ucontext_t {
|
||||
unsigned long int __ctx(uc_flags);
|
||||
struct ucontext_t *uc_link;
|
||||
stack_t uc_stack;
|
||||
mcontext_t uc_mcontext;
|
||||
sigset_t uc_sigmask;
|
||||
struct _libc_fpstate __fpregs_mem;
|
||||
unsigned long long int __ssp[4];
|
||||
} ucontext_t;
|
||||
|
||||
long read(int fd, void *buf, size_t count) {
|
||||
return __syscall(0, fd, buf, count, 0, 0, 0);
|
||||
}
|
||||
|
||||
long write(int fd, void *buf, size_t count) {
|
||||
return __syscall(1, fd, buf, count, 0, 0, 0);
|
||||
}
|
||||
|
||||
void _Exit(int status) {
|
||||
return __syscall(60, status, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
int kill(int pid, int sig) {
|
||||
return __syscall(62, pid, sig, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
int getpid(void) {
|
||||
return __syscall(39, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
int fork(void) {
|
||||
return __syscall(57, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
int execve(const char *pathname, char *const argv[], char *const envp[]) {
|
||||
return __syscall(59, pathname, argv, envp, 0, 0, 0);
|
||||
}
|
||||
|
||||
int gettimeofday(struct timeval *tv, struct timezone *tz) {
|
||||
return __syscall(96, tv, tz, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
typedef long time_t;
|
||||
|
||||
struct timespec {
|
||||
time_t tv_sec;
|
||||
long tv_nsec;
|
||||
};
|
||||
|
||||
struct timeval {
|
||||
time_t tv_sec;
|
||||
long tv_usec;
|
||||
};
|
||||
|
||||
struct timezone {
|
||||
int tz_minuteswest;
|
||||
int tz_dsttime;
|
||||
};
|
||||
|
||||
char *getcwd(char *buf, size_t size) {
|
||||
long n = __syscall(79, buf, size, 0, 0, 0, 0);
|
||||
if (n < 0) return NULL;
|
||||
return buf;
|
||||
}
|
||||
|
||||
#define _WEXITSTATUS(status) (((status) & 0xff00) >> 8)
|
||||
#define _WIFEXITED(status) (__WTERMSIG(status) == 0)
|
||||
#define _WIFSIGNALED(status) \
|
||||
(((signed char) (((status) & 0x7f) + 1) >> 1) > 0)
|
||||
int wait4(int pid, int *status, int options, struct rusage *rusage) {
|
||||
return __syscall(61, pid, status, options, rusage, 0, 0);
|
||||
}
|
||||
|
||||
#define SIGABRT 6
|
||||
#define SIGFPE 8
|
||||
#define SIGKILL 9
|
||||
#define SIGILL 4
|
||||
#define SIGINT 2
|
||||
#define SIGSEGV 11
|
||||
#define SIGTERM 15
|
||||
#define SIGBUS 7
|
||||
#define SIGTRAP 5
|
||||
void abort(void) {
|
||||
kill(getpid(), SIGABRT);
|
||||
}
|
||||
|
||||
|
||||
#define CLOCK_REALTIME 0
|
||||
#define CLOCK_MONOTONIC 1
|
||||
int clock_gettime(int clock, struct timespec *tp) {
|
||||
return __syscall(228, clock, tp, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
#define F_OK 0
|
||||
#define R_OK 4
|
||||
#define W_OK 2
|
||||
#define X_OK 1
|
||||
int access(const char *pathname, int mode) {
|
||||
return __syscall(21, pathname, mode, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int fd;
|
||||
unsigned char eof;
|
||||
unsigned char err;
|
||||
unsigned char has_ungetc;
|
||||
char ungetc; // character which was pushed by ungetc()
|
||||
} FILE;
|
||||
|
||||
int errno;
|
||||
int printf(char *, ...);
|
||||
int fprintf(FILE *, char *, ...); // needed now for assert()
|
||||
|
||||
FILE _stdin = {0}, *stdin;
|
||||
FILE _stdout = {1}, *stdout;
|
||||
FILE _stderr = {2}, *stderr;
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define assert(x) ((void)0)
|
||||
#else
|
||||
int __assert_failed(const char *file, int line, const char *expr) {
|
||||
fprintf(stderr, "Assertion failed at %s:%d: %s\n", file, line, expr);
|
||||
abort();
|
||||
}
|
||||
#define assert(x) (void)((x) || __assert_failed(__FILE__, __LINE__, #x))
|
||||
#endif
|
||||
|
||||
|
||||
int _clamp_long_to_int(long x) {
|
||||
if (x < INT_MIN) return INT_MIN;
|
||||
if (x > INT_MAX) return INT_MAX;
|
||||
return x;
|
||||
}
|
||||
|
||||
short _clamp_long_to_short(long x) {
|
||||
if (x < SHRT_MIN) return SHRT_MIN;
|
||||
if (x > SHRT_MAX) return SHRT_MAX;
|
||||
return x;
|
||||
}
|
||||
|
||||
unsigned _clamp_ulong_to_uint(unsigned long x) {
|
||||
if (x > UINT_MAX) return UINT_MAX;
|
||||
return x;
|
||||
}
|
||||
|
||||
unsigned short _clamp_ulong_to_ushort(unsigned long x) {
|
||||
if (x > USHRT_MAX) return USHRT_MAX;
|
||||
return x;
|
||||
}
|
||||
|
||||
#define EIO 5
|
||||
#define EDOM 33
|
||||
#define ERANGE 34
|
||||
|
||||
#define PROT_READ 1
|
||||
#define PROT_WRITE 2
|
||||
#define PROT_EXEC 4
|
||||
#define MAP_SHARED 0x01
|
||||
#define MAP_ANONYMOUS 0x20
|
||||
#define MAP_PRIVATE 0x02
|
||||
void *mmap(void *addr, size_t length, int prot, int flags, int fd, long offset) {
|
||||
return __syscall(9, addr, length, prot, flags, fd, offset);
|
||||
}
|
||||
|
||||
int munmap(void *addr, size_t length) {
|
||||
return __syscall(11, addr, length, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
int mprotect(void *addr, size_t len, int prot) {
|
||||
return __syscall(10, addr, len, prot, 0, 0, 0);
|
||||
}
|
||||
|
||||
#define MREMAP_MAYMOVE 1
|
||||
void *_mremap(void *addr, size_t old_size, size_t new_size, int flags) {
|
||||
return __syscall(25, addr, old_size, new_size, flags, 0, 0);
|
||||
}
|
||||
|
||||
void *malloc(size_t n) {
|
||||
if (!n) return NULL;
|
||||
void *memory;
|
||||
size_t bytes = n + 16;
|
||||
memory = mmap(0, bytes, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
|
||||
if ((uint64_t)memory > 0xffffffffffff0000) return NULL;
|
||||
*(uint64_t *)memory = bytes;
|
||||
return (char *)memory + 16;
|
||||
}
|
||||
|
||||
void free(void *ptr) {
|
||||
if (!ptr) return;
|
||||
uint64_t *memory = (char *)ptr - 16;
|
||||
uint64_t size = *memory;
|
||||
munmap(memory, size);
|
||||
}
|
||||
|
||||
|
||||
size_t strlen(char *s) {
|
||||
char *t = s;
|
||||
while (*t) ++t;
|
||||
return t - s;
|
||||
}
|
||||
|
||||
void *memcpy(void *s1, const void *s2, size_t n) {
|
||||
char *p = s1, *end = p + n, *q = s2;
|
||||
while (p < end)
|
||||
*p++ = *q++;
|
||||
return s1;
|
||||
}
|
||||
|
||||
int isspace(int c) {
|
||||
return c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v';
|
||||
}
|
||||
|
||||
int isdigit(int c) {
|
||||
return c >= '0' && c <= '9';
|
||||
}
|
||||
|
||||
int _isdigit_in_base(int c, int base) {
|
||||
if (c >= '0' && c <= '9') {
|
||||
return c - '0' < base;
|
||||
} else if (c >= 'a' && c <= 'z') {
|
||||
return c - 'a' + 10 < base;
|
||||
} else if (c >= 'A' && c <= 'Z') {
|
||||
return c - 'A' + 10 < base;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *memset(void *s, int c, size_t n) {
|
||||
char *p = s, *end = p + n;
|
||||
while (p < end)
|
||||
*p++ = c;
|
||||
return s;
|
||||
}
|
||||
|
||||
unsigned long strtoul(const char *nptr, char **endptr, int base) {
|
||||
unsigned long value = 0, newvalue;
|
||||
int overflow = 0;
|
||||
|
||||
while (isspace(*nptr)) ++nptr;
|
||||
if (*nptr == '+') ++nptr;
|
||||
if (base == 0) {
|
||||
if (*nptr == '0') {
|
||||
++nptr;
|
||||
switch (*nptr) {
|
||||
case 'x':
|
||||
case 'X':
|
||||
base = 16;
|
||||
++nptr;
|
||||
break;
|
||||
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7':
|
||||
base = 8;
|
||||
break;
|
||||
default:
|
||||
// this must just be the number 0.
|
||||
if (endptr) *endptr = nptr;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
base = 10;
|
||||
}
|
||||
}
|
||||
|
||||
while (1) {
|
||||
int c = *nptr;
|
||||
unsigned v;
|
||||
if (c >= '0' && c <= '9')
|
||||
v = c - '0';
|
||||
else if (c >= 'a' && c <= 'z')
|
||||
v = c - 'a' + 10;
|
||||
else if (c >= 'A' && c <= 'Z')
|
||||
v = c - 'A' + 10;
|
||||
else break;
|
||||
if (v >= base) break;
|
||||
unsigned long newvalue = value * base + v;
|
||||
if (newvalue < value) overflow = 1;
|
||||
value = newvalue;
|
||||
++nptr;
|
||||
}
|
||||
if (endptr) *endptr = nptr;
|
||||
if (overflow) {
|
||||
errno = ERANGE;
|
||||
return ULONG_MAX;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
long strtol(const char *nptr, char **endptr, int base) {
|
||||
int sign = 1;
|
||||
while (isspace(*nptr)) ++nptr;
|
||||
if (*nptr == '-') {
|
||||
sign = -1;
|
||||
++nptr;
|
||||
}
|
||||
unsigned long mag = strtoul(nptr, endptr, base);
|
||||
if (sign > 0) {
|
||||
if (mag > LONG_MAX) {
|
||||
errno = ERANGE;
|
||||
return LONG_MAX;
|
||||
}
|
||||
return (long)mag;
|
||||
} else {
|
||||
if (mag > (unsigned long)LONG_MAX + 1) {
|
||||
errno = ERANGE;
|
||||
return LONG_MIN;
|
||||
}
|
||||
return -(long)mag;
|
||||
}
|
||||
}
|
||||
|
||||
long long strtoll(const char *nptr, char **endptr, int base) {
|
||||
return strtol(nptr, endptr, base);
|
||||
}
|
||||
|
||||
unsigned long long strtoull(const char *nptr, char **endptr, int base) {
|
||||
return strtoul(nptr, endptr, base);
|
||||
}
|
||||
|
||||
long _strtol_clamped(const char *nptr, char **endptr, int base, int min, int max) {
|
||||
long l = strtol(nptr, endptr, base);
|
||||
if (l < min) return min;
|
||||
if (l > max) return max;
|
||||
return l;
|
||||
}
|
||||
|
||||
#define _NPOW10 310
|
||||
#define _INFINITY 1e1000
|
||||
// non-negative floating-point number with more precision than a double
|
||||
// its value is equal to fraction * 2^exponent
|
||||
typedef struct {
|
||||
unsigned long fraction;
|
||||
int exponent;
|
||||
} _Float;
|
||||
|
||||
// ensure that f->fraction >= 2^64 / 2
|
||||
static void _normalize_float(_Float *f) {
|
||||
if (!f->fraction) return;
|
||||
while (f->fraction < 0x8000000000000000) {
|
||||
f->exponent -= 1;
|
||||
f->fraction <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
static double _Float_to_double(_Float f) {
|
||||
unsigned long dbl_fraction;
|
||||
int dbl_exponent;
|
||||
unsigned long dbl_value;
|
||||
if (f.fraction == 0) return 0;
|
||||
_normalize_float(&f);
|
||||
f.fraction &= 0x7fffffffffffffff; // remove the "1." in 1.01101110111... to get 63-bit significand
|
||||
dbl_fraction = (f.fraction + 0x3ff) >> 11;
|
||||
dbl_exponent = f.exponent + 63;
|
||||
if (dbl_exponent < -1022) return 0;
|
||||
if (dbl_exponent > 1023) return _INFINITY;
|
||||
dbl_exponent += 1023;
|
||||
dbl_value = (unsigned long)dbl_exponent << 52 | dbl_fraction;
|
||||
return *(double *)&dbl_value;
|
||||
}
|
||||
|
||||
static _Float _powers_of_10_dat[2*_NPOW10+1];
|
||||
static _Float *_powers_of_10;
|
||||
static _Float _Float_ZERO = {0, 1};
|
||||
static _Float _Float_INFINITY = {0x8000000000000000, 100000};
|
||||
|
||||
|
||||
_Float _int_pow10(int x) {
|
||||
if (x <= -_NPOW10) return _Float_ZERO;
|
||||
if (x >= _NPOW10) return _Float_INFINITY;
|
||||
return _powers_of_10[x];
|
||||
}
|
||||
|
||||
double strtod(const char *nptr, char **endptr) {
|
||||
const char *flt, *dot, *p, *number_end;
|
||||
double sign = 1;
|
||||
int exponent = 0;
|
||||
while (isspace(*nptr)) ++nptr;
|
||||
|
||||
flt = nptr; // start of float
|
||||
if (*flt == '+') ++flt;
|
||||
else if (*flt == '-') sign = -1, ++flt;
|
||||
|
||||
if (*flt != '.' && (*flt < '0' || *flt > '9')) {
|
||||
// this isn't a float
|
||||
*endptr = nptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// find the decimal point, if any
|
||||
dot = flt;
|
||||
while (*dot >= '0' && *dot <= '9') ++dot;
|
||||
|
||||
nptr = dot + (*dot == '.');
|
||||
// skip digits after the dot
|
||||
while (*nptr >= '0' && *nptr <= '9') ++nptr;
|
||||
number_end = nptr;
|
||||
|
||||
if (*nptr == 'e') {
|
||||
++nptr;
|
||||
exponent = 1;
|
||||
if (*nptr == '+') ++nptr;
|
||||
else if (*nptr == '-') ++nptr, exponent = -1;
|
||||
exponent *= _strtol_clamped(nptr, &nptr, 10, -10000, 10000); // use _strtol_clamped to prevent problems with -LONG_MIN
|
||||
}
|
||||
|
||||
// construct the value using the Kahan summation algorithm (https://en.wikipedia.org/wiki/Kahan_summation_algorithm)
|
||||
double sum = 0;
|
||||
double c = 0;
|
||||
for (p = flt; p < number_end; ++p) {
|
||||
if (*p == '.') continue;
|
||||
int n = *p - '0';
|
||||
assert(n >= 0 && n <= 9);
|
||||
int pow10 = dot - p;
|
||||
pow10 -= pow10 > 0;
|
||||
pow10 += exponent;
|
||||
_Float f_val = _int_pow10(pow10);
|
||||
f_val.fraction >>= 4;
|
||||
f_val.exponent += 4;
|
||||
f_val.fraction *= n;
|
||||
double value = _Float_to_double(f_val);
|
||||
if (value == _INFINITY || sum == _INFINITY) {
|
||||
sum = _INFINITY;
|
||||
break;
|
||||
}
|
||||
double y = value - c;
|
||||
double t = sum + y;
|
||||
c = (t - sum) - y;
|
||||
sum = t;
|
||||
}
|
||||
|
||||
if (sum == _INFINITY) errno = ERANGE;
|
||||
if (endptr) *endptr = nptr;
|
||||
return sum * sign;
|
||||
}
|
||||
|
||||
float strtof(const char *nptr, char **endptr) {
|
||||
return strtod(nptr, endptr);
|
||||
}
|
||||
|
||||
long double strtold(const char *nptr, char **endptr) {
|
||||
return strtod(nptr, endptr);
|
||||
}
|
||||
|
||||
char *strerror(int errnum) {
|
||||
switch (errnum) {
|
||||
case ERANGE: return "Range error";
|
||||
case EDOM: return "Domain error";
|
||||
case EIO: return "I/O error";
|
||||
}
|
||||
return "Other error";
|
||||
}
|
||||
|
||||
typedef void (*_ExitHandler)(void);
|
||||
_ExitHandler _exit_handlers[33];
|
||||
int _n_exit_handlers;
|
||||
|
||||
void exit(int status) {
|
||||
int i;
|
||||
for (i = _n_exit_handlers - 1; i >= 0; --i)
|
||||
_exit_handlers[i]();
|
||||
_Exit(status);
|
||||
}
|
||||
|
||||
int main();
|
||||
|
||||
static char **_envp;
|
||||
static uint64_t _rand_seed;
|
||||
|
||||
int _main(int argc, char **argv) {
|
||||
int i;
|
||||
_Float p = {1, 0};
|
||||
|
||||
_envp = argv + argc + 1; // this is where the environment variables will be
|
||||
|
||||
stdin = &_stdin;
|
||||
stdout = &_stdout;
|
||||
stderr = &_stderr;
|
||||
|
||||
/*
|
||||
"If rand is called before any calls to srand have been made,
|
||||
the same sequence shall be generated as when srand is first
|
||||
called with a seed value of 1." C89 § 4.10.2.2
|
||||
*/
|
||||
_rand_seed = 1;
|
||||
// initialize powers of 10
|
||||
_powers_of_10 = _powers_of_10_dat + _NPOW10;
|
||||
for (i = 0; i < _NPOW10; ++i) {
|
||||
_normalize_float(&p);
|
||||
_powers_of_10[i] = p;
|
||||
p.exponent += 4;
|
||||
p.fraction >>= 4;
|
||||
p.fraction *= 10;
|
||||
}
|
||||
|
||||
p.fraction = 1;
|
||||
p.exponent = 0;
|
||||
for (i = 0; i > -_NPOW10; --i) {
|
||||
_normalize_float(&p);
|
||||
_powers_of_10[i] = p;
|
||||
p.fraction /= 5;
|
||||
p.exponent -= 1;
|
||||
}
|
||||
|
||||
exit(main(argc, argv));
|
||||
}
|
||||
|
||||
|
||||
#endif // _STDC_COMMON_H
|
8
05/tcc-0.9.27/stddef.h
Normal file
8
05/tcc-0.9.27/stddef.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
#ifndef _STDDEF_H
|
||||
#define _STDDEF_H
|
||||
|
||||
#include <stdc_common.h>
|
||||
#define offsetof(struct, member) ((size_t)(&((struct *)NULL)->member))
|
||||
// @NONSTANDARD: we don't have wchar_t
|
||||
|
||||
#endif // _STDDEF_H
|
2270
05/tcc-0.9.27/stdio.h
Normal file
2270
05/tcc-0.9.27/stdio.h
Normal file
File diff suppressed because it is too large
Load diff
199
05/tcc-0.9.27/stdlib.h
Normal file
199
05/tcc-0.9.27/stdlib.h
Normal file
|
@ -0,0 +1,199 @@
|
|||
#ifndef _STDLIB_H
|
||||
#define _STDLIB_H
|
||||
|
||||
#include <stdc_common.h>
|
||||
|
||||
#define EXIT_FAILURE (-1)
|
||||
#define EXIT_SUCCESS 0
|
||||
#define RAND_MAX 2147483647
|
||||
// @NONSTANDARD: we don't define MB_CUR_MAX or any of the mbtowc functions
|
||||
|
||||
typedef struct {
|
||||
int quot;
|
||||
int rem;
|
||||
} div_t;
|
||||
|
||||
typedef struct {
|
||||
long quot;
|
||||
long rem;
|
||||
} ldiv_t;
|
||||
|
||||
|
||||
int execvp(const char *pathname, char *const argv[]) {
|
||||
return execve(pathname, argv, _envp);
|
||||
}
|
||||
|
||||
|
||||
char *getenv(const char *name) {
|
||||
int i, j;
|
||||
for (i = 0; _envp[i]; ++i) {
|
||||
char *key = _envp[i];
|
||||
for (j = 0; key[j] != '=' && name[j]; ++j)
|
||||
if (name[j] != key[j])
|
||||
break;
|
||||
if (key[j] == '=' && !name[j])
|
||||
return key + (j+1);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
double atof(const char *nptr) {
|
||||
return strtod(nptr, NULL);
|
||||
}
|
||||
|
||||
int atoi(const char *nptr) {
|
||||
return _clamp_long_to_int(strtol(nptr, NULL, 10));
|
||||
}
|
||||
|
||||
long atol(const char *nptr) {
|
||||
return strtol(nptr, NULL, 10);
|
||||
}
|
||||
|
||||
int rand(void) {
|
||||
// https://en.wikipedia.org/wiki/Linear_congruential_generator
|
||||
// we're using musl/newlib's constants
|
||||
_rand_seed = 6364136223846793005 * _rand_seed + 1;
|
||||
return _rand_seed >> 33;
|
||||
}
|
||||
|
||||
void srand(unsigned seed) {
|
||||
_rand_seed = seed;
|
||||
}
|
||||
|
||||
void *calloc(size_t nmemb, size_t size) {
|
||||
if (nmemb > 0xffffffffffffffff / size)
|
||||
return NULL;
|
||||
// NB: our malloc implementation returns zeroed memory
|
||||
return malloc(nmemb * size);
|
||||
}
|
||||
|
||||
void *realloc(void *ptr, size_t size) {
|
||||
if (!ptr) return malloc(size);
|
||||
if (!size) {
|
||||
free(ptr);
|
||||
return NULL;
|
||||
}
|
||||
uint64_t *memory = (char *)ptr - 16;
|
||||
uint64_t old_size = *memory;
|
||||
uint64_t *new_memory = _mremap(memory, old_size, size, MREMAP_MAYMOVE);
|
||||
if ((uint64_t)new_memory > 0xffffffffffff0000) return NULL;
|
||||
*new_memory = size;
|
||||
return (char *)new_memory + 16;
|
||||
}
|
||||
|
||||
|
||||
int atexit(void (*func)(void)) {
|
||||
if (_n_exit_handlers >= 32) return -1;
|
||||
_exit_handlers[_n_exit_handlers++] = func;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int system(const char *string) {
|
||||
if (!string) return 1;
|
||||
|
||||
int pid = fork();
|
||||
if (pid < 0) {
|
||||
return -1;
|
||||
} else if (pid == 0) {
|
||||
// child
|
||||
char *argv[] = {
|
||||
"/bin/sh",
|
||||
"-c",
|
||||
0,
|
||||
0
|
||||
};
|
||||
argv[2] = string;
|
||||
execve("/bin/sh", argv, _envp);
|
||||
// on success, execve does not return.
|
||||
_Exit(-1);
|
||||
} else {
|
||||
// parent
|
||||
int status = 0;
|
||||
int ret = wait4(pid, &status, 0, NULL);
|
||||
if (ret != pid) return -1;
|
||||
if (_WIFSIGNALED(status)) return -1;
|
||||
return _WEXITSTATUS(status);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void *bsearch(const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)) {
|
||||
size_t lo = 0;
|
||||
size_t hi = nmemb;
|
||||
while (lo < hi) {
|
||||
size_t mid = (lo + hi) >> 1;
|
||||
void *elem = (char *)base + mid * size;
|
||||
int cmp = compar(key, elem);
|
||||
if (cmp < 0) {
|
||||
// key < elem
|
||||
hi = mid;
|
||||
} else if (cmp) {
|
||||
// key > elem
|
||||
lo = mid + 1;
|
||||
} else {
|
||||
return elem;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)) {
|
||||
// quicksort
|
||||
if (nmemb < 2) return;
|
||||
|
||||
void *temp = malloc(size);
|
||||
void *mid = (char *)base + ((nmemb >> 1) * size); // choose middle element to speed up sorting an already-sorted array
|
||||
size_t pivot_index = 0, i;
|
||||
for (i = 0; i < nmemb; ++i) {
|
||||
void *elem = (char *)base + i * size;
|
||||
if (compar(elem, mid) < 0)
|
||||
++pivot_index;
|
||||
}
|
||||
void *pivot = (char *)base + pivot_index * size;
|
||||
memcpy(temp, pivot, size);
|
||||
memcpy(pivot, mid, size);
|
||||
memcpy(mid, temp, size);
|
||||
|
||||
char *l, *r = (char *)base + (nmemb-1) * size;
|
||||
for (l = base; l < r;) {
|
||||
if (compar(l, pivot) > 0) {
|
||||
// swap l and r
|
||||
memcpy(temp, l, size);
|
||||
memcpy(l, r, size);
|
||||
memcpy(r, temp, size);
|
||||
r -= size;
|
||||
} else {
|
||||
// l is already in the right place
|
||||
l += size;
|
||||
}
|
||||
}
|
||||
|
||||
qsort(base, pivot_index, size, compar);
|
||||
qsort((char *)pivot + size, nmemb - 1 - pivot_index, size, compar);
|
||||
|
||||
free(temp);
|
||||
}
|
||||
|
||||
int abs(int x) {
|
||||
return x >= 0 ? x : -x;
|
||||
}
|
||||
|
||||
long labs(long x) {
|
||||
return x >= 0 ? x : -x;
|
||||
}
|
||||
|
||||
div_t div(int numer, int denom) {
|
||||
div_t d;
|
||||
d.quot = numer / denom;
|
||||
d.rem = numer % denom;
|
||||
return d;
|
||||
}
|
||||
|
||||
ldiv_t ldiv(long numer, long denom) {
|
||||
ldiv_t d;
|
||||
d.quot = numer / denom;
|
||||
d.rem = numer % denom;
|
||||
return d;
|
||||
}
|
||||
|
||||
#endif // _STDLIB_H
|
185
05/tcc-0.9.27/string.h
Normal file
185
05/tcc-0.9.27/string.h
Normal file
|
@ -0,0 +1,185 @@
|
|||
#ifndef _STRING_H
|
||||
#define _STRING_H
|
||||
|
||||
#include <stdc_common.h>
|
||||
|
||||
|
||||
void *memmove(void *s1, const void *s2, size_t n) {
|
||||
if (s1 < s2) return memcpy(s1, s2, n); // our memcpy does a forwards copy
|
||||
// backwards copy
|
||||
char *p = (char*)s1 + n, *q = (char*)s2 + n;
|
||||
while (p > s1)
|
||||
*--p = *--q;
|
||||
return s1;
|
||||
}
|
||||
|
||||
char *strcpy(char *s1, const char *s2) {
|
||||
char *p = s1 - 1, *q = s2 - 1;
|
||||
while ((*++p = *++q));
|
||||
return s1;
|
||||
}
|
||||
|
||||
char *strncpy(char *s1, const char *s2, size_t n) {
|
||||
char *p = s1 - 1, *q = s2 - 1;
|
||||
size_t i;
|
||||
for (i = 0; i < n; ++i)
|
||||
if (!(*++p = *++q))
|
||||
break;
|
||||
for (; i < n; ++i)
|
||||
*++p = 0;
|
||||
return s1;
|
||||
}
|
||||
|
||||
char *strcat(char *s1, const char *s2) {
|
||||
return strcpy(s1 + strlen(s1), s2);
|
||||
}
|
||||
|
||||
char *strncat(char *s1, const char *s2, size_t n) {
|
||||
// oddly, not equivalent to strncpy(s1 + strlen(s1), s2, n)
|
||||
char *p = s1 + strlen(s1) - 1, *q = s2 - 1;
|
||||
size_t i;
|
||||
for (i = 0; i < n; ++i)
|
||||
if (!(*++p = *++q))
|
||||
break;
|
||||
*++p = 0;
|
||||
return s1;
|
||||
}
|
||||
|
||||
int memcmp(const void *s1, const void *s2, size_t n) {
|
||||
char *p = s1, *q = s2;
|
||||
size_t i;
|
||||
for (i = 0; i < n; ++i, ++p, ++q) {
|
||||
if (*p > *q)
|
||||
return 1;
|
||||
if (*p < *q)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int strcmp(const char *s1, const char *s2) {
|
||||
char *p = s1, *q = s2;
|
||||
for (; ; ++p, ++q) {
|
||||
if (*p > *q)
|
||||
return 1;
|
||||
if (*p < *q)
|
||||
return -1;
|
||||
if (!*p) break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int strcoll(const char *s1, const char *s2) {
|
||||
// we only support the C locale
|
||||
return strcmp(s1, s2);
|
||||
}
|
||||
|
||||
int strncmp(const char *s1, const char *s2, size_t n) {
|
||||
char *p = s1, *q = s2;
|
||||
size_t i;
|
||||
for (i = 0; i < n; ++i, ++p, ++q) {
|
||||
if (*p > *q)
|
||||
return 1;
|
||||
if (*p < *q)
|
||||
return -1;
|
||||
if (!*p) break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t strxfrm(char *s1, const char *s2, size_t n) {
|
||||
// we only support the C locale
|
||||
size_t l = strlen(s2);
|
||||
if (l >= n) return l;
|
||||
strcpy(s1, s2);
|
||||
return l;
|
||||
}
|
||||
|
||||
void *memchr(const void *s, int c, size_t n) {
|
||||
char *p = s, *end = p + n;
|
||||
while (p < end) {
|
||||
if ((unsigned char)*p == c)
|
||||
return p;
|
||||
++p;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *strchr(const char *s, int c) {
|
||||
return memchr(s, c, strlen(s)+1);
|
||||
}
|
||||
|
||||
|
||||
size_t strcspn(const char *s1, const char *s2) {
|
||||
const char *p, *q;
|
||||
for (p = s1; *p; ++p) {
|
||||
for (q = s2; *q; ++q) {
|
||||
if (*p == *q)
|
||||
goto ret;
|
||||
}
|
||||
}
|
||||
ret:
|
||||
return p - s1;
|
||||
}
|
||||
|
||||
char *strpbrk(const char *s1, const char *s2) {
|
||||
const char *p, *q;
|
||||
for (p = s1; *p; ++p) {
|
||||
for (q = s2; *q; ++q) {
|
||||
if (*p == *q)
|
||||
return p;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *strrchr(const char *s, int c) {
|
||||
char *p;
|
||||
for (p = s + strlen(s); p >= s; --p) {
|
||||
if (*p == c)
|
||||
return p;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t strspn(const char *s1, const char *s2) {
|
||||
const char *p, *q;
|
||||
for (p = s1; *p; ++p) {
|
||||
for (q = s2; *q; ++q) {
|
||||
if (*p == *q) break;
|
||||
}
|
||||
if (!*q) break;
|
||||
}
|
||||
return p - s1;
|
||||
}
|
||||
|
||||
char *strstr(const char *s1, const char *s2) {
|
||||
char *p;
|
||||
size_t l = strlen(s2);
|
||||
for (p = s1; *p; ++p) {
|
||||
if (memcmp(p, s2, l) == 0)
|
||||
return p;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *strtok(char *s1, const char *s2) {
|
||||
static char *str;
|
||||
if (s1) str = s1;
|
||||
if (!str) return NULL;
|
||||
char *p = str + strspn(str, s2);
|
||||
if (!*p) {
|
||||
str = NULL;
|
||||
return NULL;
|
||||
}
|
||||
char *q = strpbrk(p, s2);
|
||||
if (q) {
|
||||
*q = 0;
|
||||
str = q + 1;
|
||||
} else {
|
||||
str = NULL;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
#endif // _STRING_H
|
1326
05/tcc-0.9.27/tcc-doc.texi
Normal file
1326
05/tcc-0.9.27/tcc-doc.texi
Normal file
File diff suppressed because it is too large
Load diff
371
05/tcc-0.9.27/tcc.c
Normal file
371
05/tcc-0.9.27/tcc.c
Normal file
|
@ -0,0 +1,371 @@
|
|||
/*
|
||||
* TCC - Tiny C Compiler
|
||||
*
|
||||
* Copyright (c) 2001-2004 Fabrice Bellard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser 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
|
||||
*/
|
||||
|
||||
#include "tcc.h"
|
||||
#if ONE_SOURCE
|
||||
# include "libtcc.c"
|
||||
#endif
|
||||
#include "tcctools.c"
|
||||
|
||||
static const char help[] =
|
||||
"Tiny C Compiler "TCC_VERSION" - Copyright (C) 2001-2006 Fabrice Bellard\n"
|
||||
"Usage: tcc [options...] [-o outfile] [-c] infile(s)...\n"
|
||||
" tcc [options...] -run infile [arguments...]\n"
|
||||
"General options:\n"
|
||||
" -c compile only - generate an object file\n"
|
||||
" -o outfile set output filename\n"
|
||||
" -run run compiled source\n"
|
||||
" -fflag set or reset (with 'no-' prefix) 'flag' (see tcc -hh)\n"
|
||||
" -Wwarning set or reset (with 'no-' prefix) 'warning' (see tcc -hh)\n"
|
||||
" -w disable all warnings\n"
|
||||
" -v -vv show version, show search paths or loaded files\n"
|
||||
" -h -hh show this, show more help\n"
|
||||
" -bench show compilation statistics\n"
|
||||
" - use stdin pipe as infile\n"
|
||||
" @listfile read arguments from listfile\n"
|
||||
"Preprocessor options:\n"
|
||||
" -Idir add include path 'dir'\n"
|
||||
" -Dsym[=val] define 'sym' with value 'val'\n"
|
||||
" -Usym undefine 'sym'\n"
|
||||
" -E preprocess only\n"
|
||||
"Linker options:\n"
|
||||
" -Ldir add library path 'dir'\n"
|
||||
" -llib link with dynamic or static library 'lib'\n"
|
||||
" -r generate (relocatable) object file\n"
|
||||
" -shared generate a shared library/dll\n"
|
||||
" -rdynamic export all global symbols to dynamic linker\n"
|
||||
" -soname set name for shared library to be used at runtime\n"
|
||||
" -Wl,-opt[=val] set linker option (see tcc -hh)\n"
|
||||
"Debugger options:\n"
|
||||
" -g generate runtime debug info\n"
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
" -b compile with built-in memory and bounds checker (implies -g)\n"
|
||||
#endif
|
||||
#ifdef CONFIG_TCC_BACKTRACE
|
||||
" -bt N show N callers in stack traces\n"
|
||||
#endif
|
||||
"Misc. options:\n"
|
||||
" -x[c|a|n] specify type of the next infile\n"
|
||||
" -nostdinc do not use standard system include paths\n"
|
||||
" -nostdlib do not link with standard crt and libraries\n"
|
||||
" -Bdir set tcc's private include/library dir\n"
|
||||
" -MD generate dependency file for make\n"
|
||||
" -MF file specify dependency file name\n"
|
||||
" -m32/64 defer to i386/x86_64 cross compiler\n"
|
||||
"Tools:\n"
|
||||
" create library : tcc -ar [rcsv] lib.a files\n"
|
||||
#ifdef TCC_TARGET_PE
|
||||
" create def file : tcc -impdef lib.dll [-v] [-o lib.def]\n"
|
||||
#endif
|
||||
;
|
||||
|
||||
static const char help2[] =
|
||||
"Tiny C Compiler "TCC_VERSION" - More Options\n"
|
||||
"Special options:\n"
|
||||
" -P -P1 with -E: no/alternative #line output\n"
|
||||
" -dD -dM with -E: output #define directives\n"
|
||||
" -pthread same as -D_REENTRANT and -lpthread\n"
|
||||
" -On same as -D__OPTIMIZE__ for n > 0\n"
|
||||
" -Wp,-opt same as -opt\n"
|
||||
" -include file include 'file' above each input file\n"
|
||||
" -isystem dir add 'dir' to system include path\n"
|
||||
" -static link to static libraries (not recommended)\n"
|
||||
" -dumpversion print version\n"
|
||||
" -print-search-dirs print search paths\n"
|
||||
" -dt with -run/-E: auto-define 'test_...' macros\n"
|
||||
"Ignored options:\n"
|
||||
" --param -pedantic -pipe -s -std -traditional\n"
|
||||
"-W... warnings:\n"
|
||||
" all turn on some (*) warnings\n"
|
||||
" error stop after first warning\n"
|
||||
" unsupported warn about ignored options, pragmas, etc.\n"
|
||||
" write-strings strings are const\n"
|
||||
" implicit-function-declaration warn for missing prototype (*)\n"
|
||||
"-f[no-]... flags:\n"
|
||||
" unsigned-char default char is unsigned\n"
|
||||
" signed-char default char is signed\n"
|
||||
" common use common section instead of bss\n"
|
||||
" leading-underscore decorate extern symbols\n"
|
||||
" ms-extensions allow anonymous struct in struct\n"
|
||||
" dollars-in-identifiers allow '$' in C symbols\n"
|
||||
"-m... target specific options:\n"
|
||||
" ms-bitfields use MSVC bitfield layout\n"
|
||||
#ifdef TCC_TARGET_ARM
|
||||
" float-abi hard/softfp on arm\n"
|
||||
#endif
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
" no-sse disable floats on x86_64\n"
|
||||
#endif
|
||||
"-Wl,... linker options:\n"
|
||||
" -nostdlib do not link with standard crt/libs\n"
|
||||
" -[no-]whole-archive load lib(s) fully/only as needed\n"
|
||||
" -export-all-symbols same as -rdynamic\n"
|
||||
" -image-base= -Ttext= set base address of executable\n"
|
||||
" -section-alignment= set section alignment in executable\n"
|
||||
#ifdef TCC_TARGET_PE
|
||||
" -file-alignment= set PE file alignment\n"
|
||||
" -stack= set PE stack reserve\n"
|
||||
" -large-address-aware set related PE option\n"
|
||||
" -subsystem=[console/windows] set PE subsystem\n"
|
||||
" -oformat=[pe-* binary] set executable output format\n"
|
||||
"Predefined macros:\n"
|
||||
" tcc -E -dM - < nul\n"
|
||||
#else
|
||||
" -rpath= set dynamic library search path\n"
|
||||
" -enable-new-dtags set DT_RUNPATH instead of DT_RPATH\n"
|
||||
" -soname= set DT_SONAME elf tag\n"
|
||||
" -Bsymbolic set DT_SYMBOLIC elf tag\n"
|
||||
" -oformat=[elf32/64-* binary] set executable output format\n"
|
||||
" -init= -fini= -as-needed -O (ignored)\n"
|
||||
"Predefined macros:\n"
|
||||
" tcc -E -dM - < /dev/null\n"
|
||||
#endif
|
||||
"See also the manual for more details.\n"
|
||||
;
|
||||
|
||||
static const char version[] =
|
||||
"tcc version "TCC_VERSION" ("
|
||||
#ifdef TCC_TARGET_I386
|
||||
"i386"
|
||||
#elif defined TCC_TARGET_X86_64
|
||||
"x86_64"
|
||||
#elif defined TCC_TARGET_C67
|
||||
"C67"
|
||||
#elif defined TCC_TARGET_ARM
|
||||
"ARM"
|
||||
#elif defined TCC_TARGET_ARM64
|
||||
"AArch64"
|
||||
#endif
|
||||
#ifdef TCC_ARM_HARDFLOAT
|
||||
" Hard Float"
|
||||
#endif
|
||||
#ifdef TCC_TARGET_PE
|
||||
" Windows"
|
||||
#elif defined(TCC_TARGET_MACHO)
|
||||
" Darwin"
|
||||
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||
" FreeBSD"
|
||||
#else
|
||||
" Linux"
|
||||
#endif
|
||||
")\n"
|
||||
;
|
||||
|
||||
static void print_dirs(const char *msg, char **paths, int nb_paths)
|
||||
{
|
||||
int i;
|
||||
printf("%s:\n%s", msg, nb_paths ? "" : " -\n");
|
||||
for(i = 0; i < nb_paths; i++)
|
||||
printf(" %s\n", paths[i]);
|
||||
}
|
||||
|
||||
static void print_search_dirs(TCCState *s)
|
||||
{
|
||||
printf("install: %s\n", s->tcc_lib_path);
|
||||
/* print_dirs("programs", NULL, 0); */
|
||||
print_dirs("include", s->sysinclude_paths, s->nb_sysinclude_paths);
|
||||
print_dirs("libraries", s->library_paths, s->nb_library_paths);
|
||||
printf("libtcc1:\n %s/"TCC_LIBTCC1"\n", s->tcc_lib_path);
|
||||
#ifndef TCC_TARGET_PE
|
||||
print_dirs("crt", s->crt_paths, s->nb_crt_paths);
|
||||
printf("elfinterp:\n %s\n", DEFAULT_ELFINTERP(s));
|
||||
#endif
|
||||
}
|
||||
|
||||
static void set_environment(TCCState *s)
|
||||
{
|
||||
char * path;
|
||||
|
||||
path = getenv("C_INCLUDE_PATH");
|
||||
if(path != NULL) {
|
||||
tcc_add_sysinclude_path(s, path);
|
||||
}
|
||||
path = getenv("CPATH");
|
||||
if(path != NULL) {
|
||||
tcc_add_include_path(s, path);
|
||||
}
|
||||
path = getenv("LIBRARY_PATH");
|
||||
if(path != NULL) {
|
||||
tcc_add_library_path(s, path);
|
||||
}
|
||||
}
|
||||
|
||||
static char *default_outputfile(TCCState *s, const char *first_file)
|
||||
{
|
||||
char buf[1024];
|
||||
char *ext;
|
||||
const char *name = "a";
|
||||
|
||||
if (first_file && strcmp(first_file, "-"))
|
||||
name = tcc_basename(first_file);
|
||||
snprintf(buf, sizeof(buf), "%s", name);
|
||||
ext = tcc_fileextension(buf);
|
||||
#ifdef TCC_TARGET_PE
|
||||
if (s->output_type == TCC_OUTPUT_DLL)
|
||||
strcpy(ext, ".dll");
|
||||
else
|
||||
if (s->output_type == TCC_OUTPUT_EXE)
|
||||
strcpy(ext, ".exe");
|
||||
else
|
||||
#endif
|
||||
if (s->output_type == TCC_OUTPUT_OBJ && !s->option_r && *ext)
|
||||
strcpy(ext, ".o");
|
||||
else
|
||||
strcpy(buf, "a.out");
|
||||
return tcc_strdup(buf);
|
||||
}
|
||||
|
||||
static unsigned getclock_ms(void)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return GetTickCount();
|
||||
#else
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
return tv.tv_sec*1000 + (tv.tv_usec+500)/1000;
|
||||
#endif
|
||||
}
|
||||
|
||||
int main(int argc0, char **argv0)
|
||||
{
|
||||
TCCState *s;
|
||||
int ret, opt, n = 0, t = 0;
|
||||
unsigned start_time = 0;
|
||||
const char *first_file;
|
||||
int argc; char **argv;
|
||||
FILE *ppfp = stdout;
|
||||
_init_options();
|
||||
redo:
|
||||
argc = argc0, argv = argv0;
|
||||
s = tcc_new();
|
||||
opt = tcc_parse_args(s, &argc, &argv, 1);
|
||||
|
||||
if ((n | t) == 0) {
|
||||
if (opt == OPT_HELP)
|
||||
return printf(help), 1;
|
||||
if (opt == OPT_HELP2)
|
||||
return printf(help2), 1;
|
||||
if (opt == OPT_M32 || opt == OPT_M64)
|
||||
tcc_tool_cross(s, argv, opt); /* never returns */
|
||||
if (s->verbose)
|
||||
printf(version);
|
||||
if (opt == OPT_AR)
|
||||
return tcc_tool_ar(s, argc, argv);
|
||||
#ifdef TCC_TARGET_PE
|
||||
if (opt == OPT_IMPDEF)
|
||||
return tcc_tool_impdef(s, argc, argv);
|
||||
#endif
|
||||
if (opt == OPT_V)
|
||||
return 0;
|
||||
if (opt == OPT_PRINT_DIRS) {
|
||||
/* initialize search dirs */
|
||||
set_environment(s);
|
||||
tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
|
||||
print_search_dirs(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
n = s->nb_files;
|
||||
if (n == 0)
|
||||
tcc_error("no input files\n");
|
||||
|
||||
if (s->output_type == TCC_OUTPUT_PREPROCESS) {
|
||||
if (s->outfile) {
|
||||
ppfp = fopen(s->outfile, "w");
|
||||
if (!ppfp)
|
||||
tcc_error("could not write '%s'", s->outfile);
|
||||
}
|
||||
} else if (s->output_type == TCC_OUTPUT_OBJ && !s->option_r) {
|
||||
if (s->nb_libraries)
|
||||
tcc_error("cannot specify libraries with -c");
|
||||
if (n > 1 && s->outfile)
|
||||
tcc_error("cannot specify output file with -c many files");
|
||||
} else {
|
||||
if (s->option_pthread)
|
||||
tcc_set_options(s, "-lpthread");
|
||||
}
|
||||
|
||||
if (s->do_bench)
|
||||
start_time = getclock_ms();
|
||||
}
|
||||
|
||||
set_environment(s);
|
||||
if (s->output_type == 0)
|
||||
s->output_type = TCC_OUTPUT_EXE;
|
||||
tcc_set_output_type(s, s->output_type);
|
||||
s->ppfp = ppfp;
|
||||
|
||||
if ((s->output_type == TCC_OUTPUT_MEMORY
|
||||
|| s->output_type == TCC_OUTPUT_PREPROCESS) && (s->dflag & 16))
|
||||
s->dflag |= t ? 32 : 0, s->run_test = ++t, n = s->nb_files;
|
||||
|
||||
/* compile or add each files or library */
|
||||
for (first_file = NULL, ret = 0;;) {
|
||||
struct filespec *f = s->files[s->nb_files - n];
|
||||
s->filetype = f->type;
|
||||
s->alacarte_link = f->alacarte;
|
||||
if (f->type == AFF_TYPE_LIB) {
|
||||
if (tcc_add_library_err(s, f->name) < 0)
|
||||
ret = 1;
|
||||
} else {
|
||||
if (1 == s->verbose)
|
||||
printf("-> %s\n", f->name);
|
||||
if (!first_file)
|
||||
first_file = f->name;
|
||||
if (tcc_add_file(s, f->name) < 0)
|
||||
ret = 1;
|
||||
}
|
||||
s->filetype = 0;
|
||||
s->alacarte_link = 1;
|
||||
if (--n == 0 || ret
|
||||
|| (s->output_type == TCC_OUTPUT_OBJ && !s->option_r))
|
||||
break;
|
||||
}
|
||||
|
||||
if (s->run_test) {
|
||||
t = 0;
|
||||
} else if (s->output_type == TCC_OUTPUT_PREPROCESS) {
|
||||
;
|
||||
} else if (0 == ret) {
|
||||
if (s->output_type == TCC_OUTPUT_MEMORY) {
|
||||
#ifdef TCC_IS_NATIVE
|
||||
ret = tcc_run(s, argc, argv);
|
||||
#endif
|
||||
} else {
|
||||
if (!s->outfile)
|
||||
s->outfile = default_outputfile(s, first_file);
|
||||
if (tcc_output_file(s, s->outfile))
|
||||
ret = 1;
|
||||
else if (s->gen_deps)
|
||||
gen_makedeps(s, s->outfile, s->deps_outfile);
|
||||
}
|
||||
}
|
||||
|
||||
if (s->do_bench && (n | t | ret) == 0)
|
||||
tcc_print_stats(s, getclock_ms() - start_time);
|
||||
tcc_delete(s);
|
||||
if (ret == 0 && n)
|
||||
goto redo; /* compile more files with -c */
|
||||
if (t)
|
||||
goto redo; /* run more tests with -dt -run */
|
||||
if (ppfp && ppfp != stdout)
|
||||
fclose(ppfp);
|
||||
return ret;
|
||||
}
|
1754
05/tcc-0.9.27/tcc.h
Normal file
1754
05/tcc-0.9.27/tcc.h
Normal file
File diff suppressed because it is too large
Load diff
1277
05/tcc-0.9.27/tccasm.c
Normal file
1277
05/tcc-0.9.27/tccasm.c
Normal file
File diff suppressed because it is too large
Load diff
948
05/tcc-0.9.27/tcccoff.c
Normal file
948
05/tcc-0.9.27/tcccoff.c
Normal file
|
@ -0,0 +1,948 @@
|
|||
/*
|
||||
* COFF file handling for TCC
|
||||
*
|
||||
* Copyright (c) 2003, 2004 TK
|
||||
* Copyright (c) 2004 Fabrice Bellard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser 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
|
||||
*/
|
||||
|
||||
#include "tcc.h"
|
||||
|
||||
#define MAXNSCNS 255 /* MAXIMUM NUMBER OF SECTIONS */
|
||||
#define MAX_STR_TABLE 1000000
|
||||
AOUTHDR o_filehdr; /* OPTIONAL (A.OUT) FILE HEADER */
|
||||
|
||||
SCNHDR section_header[MAXNSCNS];
|
||||
|
||||
#define MAX_FUNCS 1000
|
||||
#define MAX_FUNC_NAME_LENGTH 128
|
||||
|
||||
int nFuncs;
|
||||
char Func[MAX_FUNCS][MAX_FUNC_NAME_LENGTH];
|
||||
char AssociatedFile[MAX_FUNCS][MAX_FUNC_NAME_LENGTH];
|
||||
int LineNoFilePtr[MAX_FUNCS];
|
||||
int EndAddress[MAX_FUNCS];
|
||||
int LastLineNo[MAX_FUNCS];
|
||||
int FuncEntries[MAX_FUNCS];
|
||||
|
||||
int OutputTheSection(Section * sect);
|
||||
short int GetCoffFlags(const char *s);
|
||||
void SortSymbolTable(void);
|
||||
Section *FindSection(TCCState * s1, const char *sname);
|
||||
|
||||
int C67_main_entry_point;
|
||||
|
||||
int FindCoffSymbolIndex(const char *func_name);
|
||||
int nb_syms;
|
||||
|
||||
typedef struct {
|
||||
long tag;
|
||||
long size;
|
||||
long fileptr;
|
||||
long nextsym;
|
||||
short int dummy;
|
||||
} AUXFUNC;
|
||||
|
||||
typedef struct {
|
||||
long regmask;
|
||||
unsigned short lineno;
|
||||
unsigned short nentries;
|
||||
int localframe;
|
||||
int nextentry;
|
||||
short int dummy;
|
||||
} AUXBF;
|
||||
|
||||
typedef struct {
|
||||
long dummy;
|
||||
unsigned short lineno;
|
||||
unsigned short dummy1;
|
||||
int dummy2;
|
||||
int dummy3;
|
||||
unsigned short dummy4;
|
||||
} AUXEF;
|
||||
|
||||
ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f)
|
||||
{
|
||||
Section *tcc_sect;
|
||||
SCNHDR *coff_sec;
|
||||
int file_pointer;
|
||||
char *Coff_str_table, *pCoff_str_table;
|
||||
int CoffTextSectionNo, coff_nb_syms;
|
||||
FILHDR file_hdr; /* FILE HEADER STRUCTURE */
|
||||
Section *stext, *sdata, *sbss;
|
||||
int i, NSectionsToOutput = 0;
|
||||
|
||||
Coff_str_table = pCoff_str_table = NULL;
|
||||
|
||||
stext = FindSection(s1, ".text");
|
||||
sdata = FindSection(s1, ".data");
|
||||
sbss = FindSection(s1, ".bss");
|
||||
|
||||
nb_syms = symtab_section->data_offset / sizeof(Elf32_Sym);
|
||||
coff_nb_syms = FindCoffSymbolIndex("XXXXXXXXXX1");
|
||||
|
||||
file_hdr.f_magic = COFF_C67_MAGIC; /* magic number */
|
||||
file_hdr.f_timdat = 0; /* time & date stamp */
|
||||
file_hdr.f_opthdr = sizeof(AOUTHDR); /* sizeof(optional hdr) */
|
||||
file_hdr.f_flags = 0x1143; /* flags (copied from what code composer does) */
|
||||
file_hdr.f_TargetID = 0x99; /* for C6x = 0x0099 */
|
||||
|
||||
o_filehdr.magic = 0x0108; /* see magic.h */
|
||||
o_filehdr.vstamp = 0x0190; /* version stamp */
|
||||
o_filehdr.tsize = stext->data_offset; /* text size in bytes, padded to FW bdry */
|
||||
o_filehdr.dsize = sdata->data_offset; /* initialized data " " */
|
||||
o_filehdr.bsize = sbss->data_offset; /* uninitialized data " " */
|
||||
o_filehdr.entrypt = C67_main_entry_point; /* entry pt. */
|
||||
o_filehdr.text_start = stext->sh_addr; /* base of text used for this file */
|
||||
o_filehdr.data_start = sdata->sh_addr; /* base of data used for this file */
|
||||
|
||||
|
||||
// create all the section headers
|
||||
|
||||
file_pointer = FILHSZ + sizeof(AOUTHDR);
|
||||
|
||||
CoffTextSectionNo = -1;
|
||||
|
||||
for (i = 1; i < s1->nb_sections; i++) {
|
||||
coff_sec = §ion_header[i];
|
||||
tcc_sect = s1->sections[i];
|
||||
|
||||
if (OutputTheSection(tcc_sect)) {
|
||||
NSectionsToOutput++;
|
||||
|
||||
if (CoffTextSectionNo == -1 && tcc_sect == stext)
|
||||
CoffTextSectionNo = NSectionsToOutput; // rem which coff sect number the .text sect is
|
||||
|
||||
strcpy(coff_sec->s_name, tcc_sect->name); /* section name */
|
||||
|
||||
coff_sec->s_paddr = tcc_sect->sh_addr; /* physical address */
|
||||
coff_sec->s_vaddr = tcc_sect->sh_addr; /* virtual address */
|
||||
coff_sec->s_size = tcc_sect->data_offset; /* section size */
|
||||
coff_sec->s_scnptr = 0; /* file ptr to raw data for section */
|
||||
coff_sec->s_relptr = 0; /* file ptr to relocation */
|
||||
coff_sec->s_lnnoptr = 0; /* file ptr to line numbers */
|
||||
coff_sec->s_nreloc = 0; /* number of relocation entries */
|
||||
coff_sec->s_flags = GetCoffFlags(coff_sec->s_name); /* flags */
|
||||
coff_sec->s_reserved = 0; /* reserved byte */
|
||||
coff_sec->s_page = 0; /* memory page id */
|
||||
|
||||
file_pointer += sizeof(SCNHDR);
|
||||
}
|
||||
}
|
||||
|
||||
file_hdr.f_nscns = NSectionsToOutput; /* number of sections */
|
||||
|
||||
// now loop through and determine file pointer locations
|
||||
// for the raw data
|
||||
|
||||
|
||||
for (i = 1; i < s1->nb_sections; i++) {
|
||||
coff_sec = §ion_header[i];
|
||||
tcc_sect = s1->sections[i];
|
||||
|
||||
if (OutputTheSection(tcc_sect)) {
|
||||
// put raw data
|
||||
coff_sec->s_scnptr = file_pointer; /* file ptr to raw data for section */
|
||||
file_pointer += coff_sec->s_size;
|
||||
}
|
||||
}
|
||||
|
||||
// now loop through and determine file pointer locations
|
||||
// for the relocation data
|
||||
|
||||
for (i = 1; i < s1->nb_sections; i++) {
|
||||
coff_sec = §ion_header[i];
|
||||
tcc_sect = s1->sections[i];
|
||||
|
||||
if (OutputTheSection(tcc_sect)) {
|
||||
// put relocations data
|
||||
if (coff_sec->s_nreloc > 0) {
|
||||
coff_sec->s_relptr = file_pointer; /* file ptr to relocation */
|
||||
file_pointer += coff_sec->s_nreloc * sizeof(struct reloc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now loop through and determine file pointer locations
|
||||
// for the line number data
|
||||
|
||||
for (i = 1; i < s1->nb_sections; i++) {
|
||||
coff_sec = §ion_header[i];
|
||||
tcc_sect = s1->sections[i];
|
||||
|
||||
coff_sec->s_nlnno = 0;
|
||||
coff_sec->s_lnnoptr = 0;
|
||||
|
||||
if (s1->do_debug && tcc_sect == stext) {
|
||||
// count how many line nos data
|
||||
|
||||
// also find association between source file name and function
|
||||
// so we can sort the symbol table
|
||||
|
||||
|
||||
Stab_Sym *sym, *sym_end;
|
||||
char func_name[MAX_FUNC_NAME_LENGTH],
|
||||
last_func_name[MAX_FUNC_NAME_LENGTH];
|
||||
unsigned long func_addr, last_pc, pc;
|
||||
const char *incl_files[INCLUDE_STACK_SIZE];
|
||||
int incl_index, len, last_line_num;
|
||||
const char *str, *p;
|
||||
|
||||
coff_sec->s_lnnoptr = file_pointer; /* file ptr to linno */
|
||||
|
||||
|
||||
func_name[0] = '\0';
|
||||
func_addr = 0;
|
||||
incl_index = 0;
|
||||
last_func_name[0] = '\0';
|
||||
last_pc = 0xffffffff;
|
||||
last_line_num = 1;
|
||||
sym = (Stab_Sym *) stab_section->data + 1;
|
||||
sym_end =
|
||||
(Stab_Sym *) (stab_section->data +
|
||||
stab_section->data_offset);
|
||||
|
||||
nFuncs = 0;
|
||||
while (sym < sym_end) {
|
||||
switch (sym->n_type) {
|
||||
/* function start or end */
|
||||
case N_FUN:
|
||||
if (sym->n_strx == 0) {
|
||||
// end of function
|
||||
|
||||
coff_sec->s_nlnno++;
|
||||
file_pointer += LINESZ;
|
||||
|
||||
pc = sym->n_value + func_addr;
|
||||
func_name[0] = '\0';
|
||||
func_addr = 0;
|
||||
EndAddress[nFuncs] = pc;
|
||||
FuncEntries[nFuncs] =
|
||||
(file_pointer -
|
||||
LineNoFilePtr[nFuncs]) / LINESZ - 1;
|
||||
LastLineNo[nFuncs++] = last_line_num + 1;
|
||||
} else {
|
||||
// beginning of function
|
||||
|
||||
LineNoFilePtr[nFuncs] = file_pointer;
|
||||
coff_sec->s_nlnno++;
|
||||
file_pointer += LINESZ;
|
||||
|
||||
str =
|
||||
(const char *) stabstr_section->data +
|
||||
sym->n_strx;
|
||||
|
||||
p = strchr(str, ':');
|
||||
if (!p) {
|
||||
pstrcpy(func_name, sizeof(func_name), str);
|
||||
pstrcpy(Func[nFuncs], sizeof(func_name), str);
|
||||
} else {
|
||||
len = p - str;
|
||||
if (len > sizeof(func_name) - 1)
|
||||
len = sizeof(func_name) - 1;
|
||||
memcpy(func_name, str, len);
|
||||
memcpy(Func[nFuncs], str, len);
|
||||
func_name[len] = '\0';
|
||||
}
|
||||
|
||||
// save the file that it came in so we can sort later
|
||||
pstrcpy(AssociatedFile[nFuncs], sizeof(func_name),
|
||||
incl_files[incl_index - 1]);
|
||||
|
||||
func_addr = sym->n_value;
|
||||
}
|
||||
break;
|
||||
|
||||
/* line number info */
|
||||
case N_SLINE:
|
||||
pc = sym->n_value + func_addr;
|
||||
|
||||
last_pc = pc;
|
||||
last_line_num = sym->n_desc;
|
||||
|
||||
/* XXX: slow! */
|
||||
strcpy(last_func_name, func_name);
|
||||
|
||||
coff_sec->s_nlnno++;
|
||||
file_pointer += LINESZ;
|
||||
break;
|
||||
/* include files */
|
||||
case N_BINCL:
|
||||
str =
|
||||
(const char *) stabstr_section->data + sym->n_strx;
|
||||
add_incl:
|
||||
if (incl_index < INCLUDE_STACK_SIZE) {
|
||||
incl_files[incl_index++] = str;
|
||||
}
|
||||
break;
|
||||
case N_EINCL:
|
||||
if (incl_index > 1)
|
||||
incl_index--;
|
||||
break;
|
||||
case N_SO:
|
||||
if (sym->n_strx == 0) {
|
||||
incl_index = 0; /* end of translation unit */
|
||||
} else {
|
||||
str =
|
||||
(const char *) stabstr_section->data +
|
||||
sym->n_strx;
|
||||
/* do not add path */
|
||||
len = strlen(str);
|
||||
if (len > 0 && str[len - 1] != '/')
|
||||
goto add_incl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
sym++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
file_hdr.f_symptr = file_pointer; /* file pointer to symtab */
|
||||
|
||||
if (s1->do_debug)
|
||||
file_hdr.f_nsyms = coff_nb_syms; /* number of symtab entries */
|
||||
else
|
||||
file_hdr.f_nsyms = 0;
|
||||
|
||||
file_pointer += file_hdr.f_nsyms * SYMNMLEN;
|
||||
|
||||
// OK now we are all set to write the file
|
||||
|
||||
|
||||
fwrite(&file_hdr, FILHSZ, 1, f);
|
||||
fwrite(&o_filehdr, sizeof(o_filehdr), 1, f);
|
||||
|
||||
// write section headers
|
||||
for (i = 1; i < s1->nb_sections; i++) {
|
||||
coff_sec = §ion_header[i];
|
||||
tcc_sect = s1->sections[i];
|
||||
|
||||
if (OutputTheSection(tcc_sect)) {
|
||||
fwrite(coff_sec, sizeof(SCNHDR), 1, f);
|
||||
}
|
||||
}
|
||||
|
||||
// write raw data
|
||||
for (i = 1; i < s1->nb_sections; i++) {
|
||||
coff_sec = §ion_header[i];
|
||||
tcc_sect = s1->sections[i];
|
||||
|
||||
if (OutputTheSection(tcc_sect)) {
|
||||
fwrite(tcc_sect->data, tcc_sect->data_offset, 1, f);
|
||||
}
|
||||
}
|
||||
|
||||
// write relocation data
|
||||
for (i = 1; i < s1->nb_sections; i++) {
|
||||
coff_sec = §ion_header[i];
|
||||
tcc_sect = s1->sections[i];
|
||||
|
||||
if (OutputTheSection(tcc_sect)) {
|
||||
// put relocations data
|
||||
if (coff_sec->s_nreloc > 0) {
|
||||
fwrite(tcc_sect->reloc,
|
||||
coff_sec->s_nreloc * sizeof(struct reloc), 1, f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// group the symbols in order of filename, func1, func2, etc
|
||||
// finally global symbols
|
||||
|
||||
if (s1->do_debug)
|
||||
SortSymbolTable();
|
||||
|
||||
// write line no data
|
||||
|
||||
for (i = 1; i < s1->nb_sections; i++) {
|
||||
coff_sec = §ion_header[i];
|
||||
tcc_sect = s1->sections[i];
|
||||
|
||||
if (s1->do_debug && tcc_sect == stext) {
|
||||
// count how many line nos data
|
||||
|
||||
|
||||
Stab_Sym *sym, *sym_end;
|
||||
char func_name[128], last_func_name[128];
|
||||
unsigned long func_addr, last_pc, pc;
|
||||
const char *incl_files[INCLUDE_STACK_SIZE];
|
||||
int incl_index, len, last_line_num;
|
||||
const char *str, *p;
|
||||
|
||||
LINENO CoffLineNo;
|
||||
|
||||
func_name[0] = '\0';
|
||||
func_addr = 0;
|
||||
incl_index = 0;
|
||||
last_func_name[0] = '\0';
|
||||
last_pc = 0;
|
||||
last_line_num = 1;
|
||||
sym = (Stab_Sym *) stab_section->data + 1;
|
||||
sym_end =
|
||||
(Stab_Sym *) (stab_section->data +
|
||||
stab_section->data_offset);
|
||||
|
||||
while (sym < sym_end) {
|
||||
switch (sym->n_type) {
|
||||
/* function start or end */
|
||||
case N_FUN:
|
||||
if (sym->n_strx == 0) {
|
||||
// end of function
|
||||
|
||||
CoffLineNo.l_addr.l_paddr = last_pc;
|
||||
CoffLineNo.l_lnno = last_line_num + 1;
|
||||
fwrite(&CoffLineNo, 6, 1, f);
|
||||
|
||||
pc = sym->n_value + func_addr;
|
||||
func_name[0] = '\0';
|
||||
func_addr = 0;
|
||||
} else {
|
||||
// beginning of function
|
||||
|
||||
str =
|
||||
(const char *) stabstr_section->data +
|
||||
sym->n_strx;
|
||||
|
||||
|
||||
p = strchr(str, ':');
|
||||
if (!p) {
|
||||
pstrcpy(func_name, sizeof(func_name), str);
|
||||
} else {
|
||||
len = p - str;
|
||||
if (len > sizeof(func_name) - 1)
|
||||
len = sizeof(func_name) - 1;
|
||||
memcpy(func_name, str, len);
|
||||
func_name[len] = '\0';
|
||||
}
|
||||
func_addr = sym->n_value;
|
||||
last_pc = func_addr;
|
||||
last_line_num = -1;
|
||||
|
||||
// output a function begin
|
||||
|
||||
CoffLineNo.l_addr.l_symndx =
|
||||
FindCoffSymbolIndex(func_name);
|
||||
CoffLineNo.l_lnno = 0;
|
||||
|
||||
fwrite(&CoffLineNo, 6, 1, f);
|
||||
}
|
||||
break;
|
||||
|
||||
/* line number info */
|
||||
case N_SLINE:
|
||||
pc = sym->n_value + func_addr;
|
||||
|
||||
|
||||
/* XXX: slow! */
|
||||
strcpy(last_func_name, func_name);
|
||||
|
||||
// output a line reference
|
||||
|
||||
CoffLineNo.l_addr.l_paddr = last_pc;
|
||||
|
||||
if (last_line_num == -1) {
|
||||
CoffLineNo.l_lnno = sym->n_desc;
|
||||
} else {
|
||||
CoffLineNo.l_lnno = last_line_num + 1;
|
||||
}
|
||||
|
||||
fwrite(&CoffLineNo, 6, 1, f);
|
||||
|
||||
last_pc = pc;
|
||||
last_line_num = sym->n_desc;
|
||||
|
||||
break;
|
||||
|
||||
/* include files */
|
||||
case N_BINCL:
|
||||
str =
|
||||
(const char *) stabstr_section->data + sym->n_strx;
|
||||
add_incl2:
|
||||
if (incl_index < INCLUDE_STACK_SIZE) {
|
||||
incl_files[incl_index++] = str;
|
||||
}
|
||||
break;
|
||||
case N_EINCL:
|
||||
if (incl_index > 1)
|
||||
incl_index--;
|
||||
break;
|
||||
case N_SO:
|
||||
if (sym->n_strx == 0) {
|
||||
incl_index = 0; /* end of translation unit */
|
||||
} else {
|
||||
str =
|
||||
(const char *) stabstr_section->data +
|
||||
sym->n_strx;
|
||||
/* do not add path */
|
||||
len = strlen(str);
|
||||
if (len > 0 && str[len - 1] != '/')
|
||||
goto add_incl2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
sym++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// write symbol table
|
||||
if (s1->do_debug) {
|
||||
int k;
|
||||
struct syment csym;
|
||||
AUXFUNC auxfunc;
|
||||
AUXBF auxbf;
|
||||
AUXEF auxef;
|
||||
int i;
|
||||
Elf32_Sym *p;
|
||||
const char *name;
|
||||
int nstr;
|
||||
int n = 0;
|
||||
|
||||
Coff_str_table = (char *) tcc_malloc(MAX_STR_TABLE);
|
||||
pCoff_str_table = Coff_str_table;
|
||||
nstr = 0;
|
||||
|
||||
p = (Elf32_Sym *) symtab_section->data;
|
||||
|
||||
|
||||
for (i = 0; i < nb_syms; i++) {
|
||||
|
||||
name = symtab_section->link->data + p->st_name;
|
||||
|
||||
for (k = 0; k < 8; k++)
|
||||
csym._n._n_name[k] = 0;
|
||||
|
||||
if (strlen(name) <= 8) {
|
||||
strcpy(csym._n._n_name, name);
|
||||
} else {
|
||||
if (pCoff_str_table - Coff_str_table + strlen(name) >
|
||||
MAX_STR_TABLE - 1)
|
||||
tcc_error("String table too large");
|
||||
|
||||
csym._n._n_n._n_zeroes = 0;
|
||||
csym._n._n_n._n_offset =
|
||||
pCoff_str_table - Coff_str_table + 4;
|
||||
|
||||
strcpy(pCoff_str_table, name);
|
||||
pCoff_str_table += strlen(name) + 1; // skip over null
|
||||
nstr++;
|
||||
}
|
||||
|
||||
if (p->st_info == 4) {
|
||||
// put a filename symbol
|
||||
csym.n_value = 33; // ?????
|
||||
csym.n_scnum = N_DEBUG;
|
||||
csym.n_type = 0;
|
||||
csym.n_sclass = C_FILE;
|
||||
csym.n_numaux = 0;
|
||||
fwrite(&csym, 18, 1, f);
|
||||
n++;
|
||||
|
||||
} else if (p->st_info == 0x12) {
|
||||
// find the function data
|
||||
|
||||
for (k = 0; k < nFuncs; k++) {
|
||||
if (strcmp(name, Func[k]) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (k >= nFuncs) {
|
||||
tcc_error("debug info can't find function: %s", name);
|
||||
}
|
||||
// put a Function Name
|
||||
|
||||
csym.n_value = p->st_value; // physical address
|
||||
csym.n_scnum = CoffTextSectionNo;
|
||||
csym.n_type = MKTYPE(T_INT, DT_FCN, 0, 0, 0, 0, 0);
|
||||
csym.n_sclass = C_EXT;
|
||||
csym.n_numaux = 1;
|
||||
fwrite(&csym, 18, 1, f);
|
||||
|
||||
// now put aux info
|
||||
|
||||
auxfunc.tag = 0;
|
||||
auxfunc.size = EndAddress[k] - p->st_value;
|
||||
auxfunc.fileptr = LineNoFilePtr[k];
|
||||
auxfunc.nextsym = n + 6; // tktk
|
||||
auxfunc.dummy = 0;
|
||||
fwrite(&auxfunc, 18, 1, f);
|
||||
|
||||
// put a .bf
|
||||
|
||||
strcpy(csym._n._n_name, ".bf");
|
||||
csym.n_value = p->st_value; // physical address
|
||||
csym.n_scnum = CoffTextSectionNo;
|
||||
csym.n_type = 0;
|
||||
csym.n_sclass = C_FCN;
|
||||
csym.n_numaux = 1;
|
||||
fwrite(&csym, 18, 1, f);
|
||||
|
||||
// now put aux info
|
||||
|
||||
auxbf.regmask = 0;
|
||||
auxbf.lineno = 0;
|
||||
auxbf.nentries = FuncEntries[k];
|
||||
auxbf.localframe = 0;
|
||||
auxbf.nextentry = n + 6;
|
||||
auxbf.dummy = 0;
|
||||
fwrite(&auxbf, 18, 1, f);
|
||||
|
||||
// put a .ef
|
||||
|
||||
strcpy(csym._n._n_name, ".ef");
|
||||
csym.n_value = EndAddress[k]; // physical address
|
||||
csym.n_scnum = CoffTextSectionNo;
|
||||
csym.n_type = 0;
|
||||
csym.n_sclass = C_FCN;
|
||||
csym.n_numaux = 1;
|
||||
fwrite(&csym, 18, 1, f);
|
||||
|
||||
// now put aux info
|
||||
|
||||
auxef.dummy = 0;
|
||||
auxef.lineno = LastLineNo[k];
|
||||
auxef.dummy1 = 0;
|
||||
auxef.dummy2 = 0;
|
||||
auxef.dummy3 = 0;
|
||||
auxef.dummy4 = 0;
|
||||
fwrite(&auxef, 18, 1, f);
|
||||
|
||||
n += 6;
|
||||
|
||||
} else {
|
||||
// try an put some type info
|
||||
|
||||
if ((p->st_other & VT_BTYPE) == VT_DOUBLE) {
|
||||
csym.n_type = T_DOUBLE; // int
|
||||
csym.n_sclass = C_EXT;
|
||||
} else if ((p->st_other & VT_BTYPE) == VT_FLOAT) {
|
||||
csym.n_type = T_FLOAT;
|
||||
csym.n_sclass = C_EXT;
|
||||
} else if ((p->st_other & VT_BTYPE) == VT_INT) {
|
||||
csym.n_type = T_INT; // int
|
||||
csym.n_sclass = C_EXT;
|
||||
} else if ((p->st_other & VT_BTYPE) == VT_SHORT) {
|
||||
csym.n_type = T_SHORT;
|
||||
csym.n_sclass = C_EXT;
|
||||
} else if ((p->st_other & VT_BTYPE) == VT_BYTE) {
|
||||
csym.n_type = T_CHAR;
|
||||
csym.n_sclass = C_EXT;
|
||||
} else {
|
||||
csym.n_type = T_INT; // just mark as a label
|
||||
csym.n_sclass = C_LABEL;
|
||||
}
|
||||
|
||||
|
||||
csym.n_value = p->st_value;
|
||||
csym.n_scnum = 2;
|
||||
csym.n_numaux = 1;
|
||||
fwrite(&csym, 18, 1, f);
|
||||
|
||||
auxfunc.tag = 0;
|
||||
auxfunc.size = 0x20;
|
||||
auxfunc.fileptr = 0;
|
||||
auxfunc.nextsym = 0;
|
||||
auxfunc.dummy = 0;
|
||||
fwrite(&auxfunc, 18, 1, f);
|
||||
n++;
|
||||
n++;
|
||||
|
||||
}
|
||||
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
if (s1->do_debug) {
|
||||
// write string table
|
||||
|
||||
// first write the size
|
||||
i = pCoff_str_table - Coff_str_table;
|
||||
fwrite(&i, 4, 1, f);
|
||||
|
||||
// then write the strings
|
||||
fwrite(Coff_str_table, i, 1, f);
|
||||
|
||||
tcc_free(Coff_str_table);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// group the symbols in order of filename, func1, func2, etc
|
||||
// finally global symbols
|
||||
|
||||
void SortSymbolTable(void)
|
||||
{
|
||||
int i, j, k, n = 0;
|
||||
Elf32_Sym *p, *p2, *NewTable;
|
||||
char *name, *name2;
|
||||
|
||||
NewTable = (Elf32_Sym *) tcc_malloc(nb_syms * sizeof(Elf32_Sym));
|
||||
|
||||
p = (Elf32_Sym *) symtab_section->data;
|
||||
|
||||
|
||||
// find a file symbol, copy it over
|
||||
// then scan the whole symbol list and copy any function
|
||||
// symbols that match the file association
|
||||
|
||||
for (i = 0; i < nb_syms; i++) {
|
||||
if (p->st_info == 4) {
|
||||
name = (char *) symtab_section->link->data + p->st_name;
|
||||
|
||||
// this is a file symbol, copy it over
|
||||
|
||||
NewTable[n++] = *p;
|
||||
|
||||
p2 = (Elf32_Sym *) symtab_section->data;
|
||||
|
||||
for (j = 0; j < nb_syms; j++) {
|
||||
if (p2->st_info == 0x12) {
|
||||
// this is a func symbol
|
||||
|
||||
name2 =
|
||||
(char *) symtab_section->link->data + p2->st_name;
|
||||
|
||||
// find the function data index
|
||||
|
||||
for (k = 0; k < nFuncs; k++) {
|
||||
if (strcmp(name2, Func[k]) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (k >= nFuncs) {
|
||||
tcc_error("debug (sort) info can't find function: %s", name2);
|
||||
}
|
||||
|
||||
if (strcmp(AssociatedFile[k], name) == 0) {
|
||||
// yes they match copy it over
|
||||
|
||||
NewTable[n++] = *p2;
|
||||
}
|
||||
}
|
||||
p2++;
|
||||
}
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
// now all the filename and func symbols should have been copied over
|
||||
// copy all the rest over (all except file and funcs)
|
||||
|
||||
p = (Elf32_Sym *) symtab_section->data;
|
||||
for (i = 0; i < nb_syms; i++) {
|
||||
if (p->st_info != 4 && p->st_info != 0x12) {
|
||||
NewTable[n++] = *p;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
if (n != nb_syms)
|
||||
tcc_error("Internal Compiler error, debug info");
|
||||
|
||||
// copy it all back
|
||||
|
||||
p = (Elf32_Sym *) symtab_section->data;
|
||||
for (i = 0; i < nb_syms; i++) {
|
||||
*p++ = NewTable[i];
|
||||
}
|
||||
|
||||
tcc_free(NewTable);
|
||||
}
|
||||
|
||||
|
||||
int FindCoffSymbolIndex(const char *func_name)
|
||||
{
|
||||
int i, n = 0;
|
||||
Elf32_Sym *p;
|
||||
char *name;
|
||||
|
||||
p = (Elf32_Sym *) symtab_section->data;
|
||||
|
||||
for (i = 0; i < nb_syms; i++) {
|
||||
|
||||
name = (char *) symtab_section->link->data + p->st_name;
|
||||
|
||||
if (p->st_info == 4) {
|
||||
// put a filename symbol
|
||||
n++;
|
||||
} else if (p->st_info == 0x12) {
|
||||
|
||||
if (strcmp(func_name, name) == 0)
|
||||
return n;
|
||||
|
||||
n += 6;
|
||||
|
||||
// put a Function Name
|
||||
|
||||
// now put aux info
|
||||
|
||||
// put a .bf
|
||||
|
||||
// now put aux info
|
||||
|
||||
// put a .ef
|
||||
|
||||
// now put aux info
|
||||
|
||||
} else {
|
||||
n += 2;
|
||||
}
|
||||
|
||||
p++;
|
||||
}
|
||||
|
||||
return n; // total number of symbols
|
||||
}
|
||||
|
||||
int OutputTheSection(Section * sect)
|
||||
{
|
||||
const char *s = sect->name;
|
||||
|
||||
if (!strcmp(s, ".text"))
|
||||
return 1;
|
||||
else if (!strcmp(s, ".data"))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
short int GetCoffFlags(const char *s)
|
||||
{
|
||||
if (!strcmp(s, ".text"))
|
||||
return STYP_TEXT | STYP_DATA | STYP_ALIGN | 0x400;
|
||||
else if (!strcmp(s, ".data"))
|
||||
return STYP_DATA;
|
||||
else if (!strcmp(s, ".bss"))
|
||||
return STYP_BSS;
|
||||
else if (!strcmp(s, ".stack"))
|
||||
return STYP_BSS | STYP_ALIGN | 0x200;
|
||||
else if (!strcmp(s, ".cinit"))
|
||||
return STYP_COPY | STYP_DATA | STYP_ALIGN | 0x200;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
Section *FindSection(TCCState * s1, const char *sname)
|
||||
{
|
||||
Section *s;
|
||||
int i;
|
||||
|
||||
for (i = 1; i < s1->nb_sections; i++) {
|
||||
s = s1->sections[i];
|
||||
|
||||
if (!strcmp(sname, s->name))
|
||||
return s;
|
||||
}
|
||||
|
||||
tcc_error("could not find section %s", sname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ST_FUNC int tcc_load_coff(TCCState * s1, int fd)
|
||||
{
|
||||
// tktk TokenSym *ts;
|
||||
|
||||
FILE *f;
|
||||
unsigned int str_size;
|
||||
char *Coff_str_table, *name;
|
||||
int i, k;
|
||||
struct syment csym;
|
||||
char name2[9];
|
||||
FILHDR file_hdr; /* FILE HEADER STRUCTURE */
|
||||
|
||||
f = fdopen(fd, "rb");
|
||||
if (!f) {
|
||||
tcc_error("Unable to open .out file for input");
|
||||
}
|
||||
|
||||
if (fread(&file_hdr, FILHSZ, 1, f) != 1)
|
||||
tcc_error("error reading .out file for input");
|
||||
|
||||
if (fread(&o_filehdr, sizeof(o_filehdr), 1, f) != 1)
|
||||
tcc_error("error reading .out file for input");
|
||||
|
||||
// first read the string table
|
||||
|
||||
if (fseek(f, file_hdr.f_symptr + file_hdr.f_nsyms * SYMESZ, SEEK_SET))
|
||||
tcc_error("error reading .out file for input");
|
||||
|
||||
if (fread(&str_size, sizeof(int), 1, f) != 1)
|
||||
tcc_error("error reading .out file for input");
|
||||
|
||||
|
||||
Coff_str_table = (char *) tcc_malloc(str_size);
|
||||
|
||||
if (fread(Coff_str_table, str_size - 4, 1, f) != 1)
|
||||
tcc_error("error reading .out file for input");
|
||||
|
||||
// read/process all the symbols
|
||||
|
||||
// seek back to symbols
|
||||
|
||||
if (fseek(f, file_hdr.f_symptr, SEEK_SET))
|
||||
tcc_error("error reading .out file for input");
|
||||
|
||||
for (i = 0; i < file_hdr.f_nsyms; i++) {
|
||||
if (fread(&csym, SYMESZ, 1, f) != 1)
|
||||
tcc_error("error reading .out file for input");
|
||||
|
||||
if (csym._n._n_n._n_zeroes == 0) {
|
||||
name = Coff_str_table + csym._n._n_n._n_offset - 4;
|
||||
} else {
|
||||
name = csym._n._n_name;
|
||||
|
||||
if (name[7] != 0) {
|
||||
for (k = 0; k < 8; k++)
|
||||
name2[k] = name[k];
|
||||
|
||||
name2[8] = 0;
|
||||
|
||||
name = name2;
|
||||
}
|
||||
}
|
||||
// if (strcmp("_DAC_Buffer",name)==0) // tktk
|
||||
// name[0]=0;
|
||||
|
||||
if (((csym.n_type & 0x30) == 0x20 && csym.n_sclass == 0x2) || ((csym.n_type & 0x30) == 0x30 && csym.n_sclass == 0x2) || (csym.n_type == 0x4 && csym.n_sclass == 0x2) || (csym.n_type == 0x8 && csym.n_sclass == 0x2) || // structures
|
||||
(csym.n_type == 0x18 && csym.n_sclass == 0x2) || // pointer to structure
|
||||
(csym.n_type == 0x7 && csym.n_sclass == 0x2) || // doubles
|
||||
(csym.n_type == 0x6 && csym.n_sclass == 0x2)) // floats
|
||||
{
|
||||
// strip off any leading underscore (except for other main routine)
|
||||
|
||||
if (name[0] == '_' && strcmp(name, "_main") != 0)
|
||||
name++;
|
||||
|
||||
tcc_add_symbol(s1, name, (void*)(uintptr_t)csym.n_value);
|
||||
}
|
||||
// skip any aux records
|
||||
|
||||
if (csym.n_numaux == 1) {
|
||||
if (fread(&csym, SYMESZ, 1, f) != 1)
|
||||
tcc_error("error reading .out file for input");
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
3060
05/tcc-0.9.27/tccelf.c
Normal file
3060
05/tcc-0.9.27/tccelf.c
Normal file
File diff suppressed because it is too large
Load diff
7388
05/tcc-0.9.27/tccgen.c
Normal file
7388
05/tcc-0.9.27/tccgen.c
Normal file
File diff suppressed because it is too large
Load diff
80
05/tcc-0.9.27/tcclib.h
Normal file
80
05/tcc-0.9.27/tcclib.h
Normal file
|
@ -0,0 +1,80 @@
|
|||
/* Simple libc header for TCC
|
||||
*
|
||||
* Add any function you want from the libc there. This file is here
|
||||
* only for your convenience so that you do not need to put the whole
|
||||
* glibc include files on your floppy disk
|
||||
*/
|
||||
#ifndef _TCCLIB_H
|
||||
#define _TCCLIB_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
/* stdlib.h */
|
||||
void *calloc(size_t nmemb, size_t size);
|
||||
void *malloc(size_t size);
|
||||
void free(void *ptr);
|
||||
void *realloc(void *ptr, size_t size);
|
||||
int atoi(const char *nptr);
|
||||
long int strtol(const char *nptr, char **endptr, int base);
|
||||
unsigned long int strtoul(const char *nptr, char **endptr, int base);
|
||||
void exit(int);
|
||||
|
||||
/* stdio.h */
|
||||
typedef struct __FILE FILE;
|
||||
#define EOF (-1)
|
||||
extern FILE *stdin;
|
||||
extern FILE *stdout;
|
||||
extern FILE *stderr;
|
||||
FILE *fopen(const char *path, const char *mode);
|
||||
FILE *fdopen(int fildes, const char *mode);
|
||||
FILE *freopen(const char *path, const char *mode, FILE *stream);
|
||||
int fclose(FILE *stream);
|
||||
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
|
||||
size_t fwrite(void *ptr, size_t size, size_t nmemb, FILE *stream);
|
||||
int fgetc(FILE *stream);
|
||||
char *fgets(char *s, int size, FILE *stream);
|
||||
int getc(FILE *stream);
|
||||
int getchar(void);
|
||||
char *gets(char *s);
|
||||
int ungetc(int c, FILE *stream);
|
||||
int fflush(FILE *stream);
|
||||
int putchar (int c);
|
||||
|
||||
int printf(const char *format, ...);
|
||||
int fprintf(FILE *stream, const char *format, ...);
|
||||
int sprintf(char *str, const char *format, ...);
|
||||
int snprintf(char *str, size_t size, const char *format, ...);
|
||||
int asprintf(char **strp, const char *format, ...);
|
||||
int dprintf(int fd, const char *format, ...);
|
||||
int vprintf(const char *format, va_list ap);
|
||||
int vfprintf(FILE *stream, const char *format, va_list ap);
|
||||
int vsprintf(char *str, const char *format, va_list ap);
|
||||
int vsnprintf(char *str, size_t size, const char *format, va_list ap);
|
||||
int vasprintf(char **strp, const char *format, va_list ap);
|
||||
int vdprintf(int fd, const char *format, va_list ap);
|
||||
|
||||
void perror(const char *s);
|
||||
|
||||
/* string.h */
|
||||
char *strcat(char *dest, const char *src);
|
||||
char *strchr(const char *s, int c);
|
||||
char *strrchr(const char *s, int c);
|
||||
char *strcpy(char *dest, const char *src);
|
||||
void *memcpy(void *dest, const void *src, size_t n);
|
||||
void *memmove(void *dest, const void *src, size_t n);
|
||||
void *memset(void *s, int c, size_t n);
|
||||
char *strdup(const char *s);
|
||||
size_t strlen(const char *s);
|
||||
|
||||
/* dlfcn.h */
|
||||
#define RTLD_LAZY 0x001
|
||||
#define RTLD_NOW 0x002
|
||||
#define RTLD_GLOBAL 0x100
|
||||
|
||||
void *dlopen(const char *filename, int flag);
|
||||
const char *dlerror(void);
|
||||
void *dlsym(void *handle, char *symbol);
|
||||
int dlclose(void *handle);
|
||||
|
||||
#endif /* _TCCLIB_H */
|
1996
05/tcc-0.9.27/tccpe.c
Normal file
1996
05/tcc-0.9.27/tccpe.c
Normal file
File diff suppressed because it is too large
Load diff
3907
05/tcc-0.9.27/tccpp.c
Normal file
3907
05/tcc-0.9.27/tccpp.c
Normal file
File diff suppressed because it is too large
Load diff
844
05/tcc-0.9.27/tccrun.c
Normal file
844
05/tcc-0.9.27/tccrun.c
Normal file
|
@ -0,0 +1,844 @@
|
|||
/*
|
||||
* TCC - Tiny C Compiler - Support for -run switch
|
||||
*
|
||||
* Copyright (c) 2001-2004 Fabrice Bellard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser 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
|
||||
*/
|
||||
|
||||
#include "tcc.h"
|
||||
|
||||
/* only native compiler supports -run */
|
||||
#ifdef TCC_IS_NATIVE
|
||||
|
||||
#ifndef _WIN32
|
||||
# include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_TCC_BACKTRACE
|
||||
# ifndef _WIN32
|
||||
# include <signal.h>
|
||||
# ifndef __OpenBSD__
|
||||
# include <sys/ucontext.h>
|
||||
# endif
|
||||
# else
|
||||
# define ucontext_t CONTEXT
|
||||
# endif
|
||||
ST_DATA int rt_num_callers = 6;
|
||||
ST_DATA const char **rt_bound_error_msg;
|
||||
ST_DATA void *rt_prog_main;
|
||||
static int rt_get_caller_pc(addr_t *paddr, ucontext_t *uc, int level);
|
||||
static void rt_error(ucontext_t *uc, const char *fmt, ...);
|
||||
static void set_exception_handler(void);
|
||||
#endif
|
||||
|
||||
static void set_pages_executable(void *ptr, unsigned long length);
|
||||
static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff);
|
||||
|
||||
#ifdef _WIN64
|
||||
static void *win64_add_function_table(TCCState *s1);
|
||||
static void win64_del_function_table(void *);
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
/* Do all relocations (needed before using tcc_get_symbol())
|
||||
Returns -1 on error. */
|
||||
|
||||
LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr)
|
||||
{
|
||||
int size;
|
||||
addr_t ptr_diff = 0;
|
||||
|
||||
if (TCC_RELOCATE_AUTO != ptr)
|
||||
return tcc_relocate_ex(s1, ptr, 0);
|
||||
|
||||
size = tcc_relocate_ex(s1, NULL, 0);
|
||||
if (size < 0)
|
||||
return -1;
|
||||
|
||||
#ifdef HAVE_SELINUX
|
||||
{
|
||||
/* Using mmap instead of malloc */
|
||||
void *prx;
|
||||
char tmpfname[] = "/tmp/.tccrunXXXXXX";
|
||||
int fd = mkstemp(tmpfname);
|
||||
unlink(tmpfname);
|
||||
ftruncate(fd, size);
|
||||
|
||||
ptr = mmap (NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
prx = mmap (NULL, size, PROT_READ|PROT_EXEC, MAP_SHARED, fd, 0);
|
||||
if (ptr == MAP_FAILED || prx == MAP_FAILED)
|
||||
tcc_error("tccrun: could not map memory");
|
||||
dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, (void*)(addr_t)size);
|
||||
dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, prx);
|
||||
ptr_diff = (char*)prx - (char*)ptr;
|
||||
}
|
||||
#else
|
||||
ptr = tcc_malloc(size);
|
||||
#endif
|
||||
tcc_relocate_ex(s1, ptr, ptr_diff); /* no more errors expected */
|
||||
dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, ptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ST_FUNC void tcc_run_free(TCCState *s1)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < s1->nb_runtime_mem; ++i) {
|
||||
#ifdef HAVE_SELINUX
|
||||
unsigned size = (unsigned)(addr_t)s1->runtime_mem[i++];
|
||||
munmap(s1->runtime_mem[i++], size);
|
||||
munmap(s1->runtime_mem[i], size);
|
||||
#else
|
||||
#ifdef _WIN64
|
||||
win64_del_function_table(*(void**)s1->runtime_mem[i]);
|
||||
#endif
|
||||
tcc_free(s1->runtime_mem[i]);
|
||||
#endif
|
||||
}
|
||||
tcc_free(s1->runtime_mem);
|
||||
}
|
||||
|
||||
/* launch the compiled program with the given arguments */
|
||||
LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
|
||||
{
|
||||
int (*prog_main)(int, char **);
|
||||
|
||||
s1->runtime_main = "main";
|
||||
if ((s1->dflag & 16) && !find_elf_sym(s1->symtab, s1->runtime_main))
|
||||
return 0;
|
||||
if (tcc_relocate(s1, TCC_RELOCATE_AUTO) < 0)
|
||||
return -1;
|
||||
prog_main = tcc_get_symbol_err(s1, s1->runtime_main);
|
||||
|
||||
#ifdef CONFIG_TCC_BACKTRACE
|
||||
if (s1->do_debug) {
|
||||
set_exception_handler();
|
||||
rt_prog_main = prog_main;
|
||||
}
|
||||
#endif
|
||||
|
||||
errno = 0; /* clean errno value */
|
||||
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
if (s1->do_bounds_check) {
|
||||
void (*bound_init)(void);
|
||||
void (*bound_exit)(void);
|
||||
void (*bound_new_region)(void *p, addr_t size);
|
||||
int (*bound_delete_region)(void *p);
|
||||
int i, ret;
|
||||
|
||||
/* set error function */
|
||||
rt_bound_error_msg = tcc_get_symbol_err(s1, "__bound_error_msg");
|
||||
/* XXX: use .init section so that it also work in binary ? */
|
||||
bound_init = tcc_get_symbol_err(s1, "__bound_init");
|
||||
bound_exit = tcc_get_symbol_err(s1, "__bound_exit");
|
||||
bound_new_region = tcc_get_symbol_err(s1, "__bound_new_region");
|
||||
bound_delete_region = tcc_get_symbol_err(s1, "__bound_delete_region");
|
||||
|
||||
bound_init();
|
||||
/* mark argv area as valid */
|
||||
bound_new_region(argv, argc*sizeof(argv[0]));
|
||||
for (i=0; i<argc; ++i)
|
||||
bound_new_region(argv[i], strlen(argv[i]) + 1);
|
||||
|
||||
ret = (*prog_main)(argc, argv);
|
||||
|
||||
/* unmark argv area */
|
||||
for (i=0; i<argc; ++i)
|
||||
bound_delete_region(argv[i]);
|
||||
bound_delete_region(argv);
|
||||
bound_exit();
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
return (*prog_main)(argc, argv);
|
||||
}
|
||||
|
||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
|
||||
#define RUN_SECTION_ALIGNMENT 63
|
||||
#else
|
||||
#define RUN_SECTION_ALIGNMENT 15
|
||||
#endif
|
||||
|
||||
/* relocate code. Return -1 on error, required size if ptr is NULL,
|
||||
otherwise copy code into buffer passed by the caller */
|
||||
static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff)
|
||||
{
|
||||
Section *s;
|
||||
unsigned offset, length, fill, i, k;
|
||||
addr_t mem;
|
||||
|
||||
if (NULL == ptr) {
|
||||
s1->nb_errors = 0;
|
||||
#ifdef TCC_TARGET_PE
|
||||
pe_output_file(s1, NULL);
|
||||
#else
|
||||
tcc_add_runtime(s1);
|
||||
resolve_common_syms(s1);
|
||||
build_got_entries(s1);
|
||||
#endif
|
||||
if (s1->nb_errors)
|
||||
return -1;
|
||||
}
|
||||
|
||||
offset = 0, mem = (addr_t)ptr;
|
||||
fill = -mem & RUN_SECTION_ALIGNMENT;
|
||||
#ifdef _WIN64
|
||||
offset += sizeof (void*);
|
||||
#endif
|
||||
for (k = 0; k < 2; ++k) {
|
||||
for(i = 1; i < s1->nb_sections; i++) {
|
||||
s = s1->sections[i];
|
||||
if (0 == (s->sh_flags & SHF_ALLOC))
|
||||
continue;
|
||||
if (k != !(s->sh_flags & SHF_EXECINSTR))
|
||||
continue;
|
||||
offset += fill;
|
||||
if (!mem)
|
||||
s->sh_addr = 0;
|
||||
else if (s->sh_flags & SHF_EXECINSTR)
|
||||
s->sh_addr = mem + offset + ptr_diff;
|
||||
else
|
||||
s->sh_addr = mem + offset;
|
||||
#if 0
|
||||
if (mem)
|
||||
printf("%-16s +%02lx %p %04x\n",
|
||||
s->name, fill, (void*)s->sh_addr, (unsigned)s->data_offset);
|
||||
#endif
|
||||
offset += s->data_offset;
|
||||
fill = -(mem + offset) & 15;
|
||||
}
|
||||
#if RUN_SECTION_ALIGNMENT > 15
|
||||
/* To avoid that x86 processors would reload cached instructions each time
|
||||
when data is written in the near, we need to make sure that code and data
|
||||
do not share the same 64 byte unit */
|
||||
fill = -(mem + offset) & RUN_SECTION_ALIGNMENT;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* relocate symbols */
|
||||
relocate_syms(s1, s1->symtab, 1);
|
||||
if (s1->nb_errors)
|
||||
return -1;
|
||||
|
||||
if (0 == mem)
|
||||
return offset + RUN_SECTION_ALIGNMENT;
|
||||
|
||||
#ifdef TCC_TARGET_PE
|
||||
s1->pe_imagebase = mem;
|
||||
#endif
|
||||
|
||||
/* relocate each section */
|
||||
for(i = 1; i < s1->nb_sections; i++) {
|
||||
s = s1->sections[i];
|
||||
if (s->reloc)
|
||||
relocate_section(s1, s);
|
||||
}
|
||||
relocate_plt(s1);
|
||||
|
||||
for(i = 1; i < s1->nb_sections; i++) {
|
||||
s = s1->sections[i];
|
||||
if (0 == (s->sh_flags & SHF_ALLOC))
|
||||
continue;
|
||||
length = s->data_offset;
|
||||
ptr = (void*)s->sh_addr;
|
||||
if (s->sh_flags & SHF_EXECINSTR)
|
||||
ptr = (char*)ptr - ptr_diff;
|
||||
if (NULL == s->data || s->sh_type == SHT_NOBITS)
|
||||
memset(ptr, 0, length);
|
||||
else
|
||||
memcpy(ptr, s->data, length);
|
||||
/* mark executable sections as executable in memory */
|
||||
if (s->sh_flags & SHF_EXECINSTR)
|
||||
set_pages_executable((char*)ptr + ptr_diff, length);
|
||||
}
|
||||
|
||||
#ifdef _WIN64
|
||||
*(void**)mem = win64_add_function_table(s1);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
/* allow to run code in memory */
|
||||
|
||||
static void set_pages_executable(void *ptr, unsigned long length)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
unsigned long old_protect;
|
||||
VirtualProtect(ptr, length, PAGE_EXECUTE_READWRITE, &old_protect);
|
||||
#else
|
||||
void __clear_cache(void *beginning, void *end);
|
||||
# ifndef HAVE_SELINUX
|
||||
addr_t start, end;
|
||||
# ifndef PAGESIZE
|
||||
# define PAGESIZE 4096
|
||||
# endif
|
||||
start = (addr_t)ptr & ~(PAGESIZE - 1);
|
||||
end = (addr_t)ptr + length;
|
||||
end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1);
|
||||
if (mprotect((void *)start, end - start, PROT_READ | PROT_WRITE | PROT_EXEC))
|
||||
tcc_error("mprotect failed: did you mean to configure --with-selinux?");
|
||||
# endif
|
||||
# if defined TCC_TARGET_ARM || defined TCC_TARGET_ARM64
|
||||
__clear_cache(ptr, (char *)ptr + length);
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _WIN64
|
||||
static void *win64_add_function_table(TCCState *s1)
|
||||
{
|
||||
void *p = NULL;
|
||||
if (s1->uw_pdata) {
|
||||
p = (void*)s1->uw_pdata->sh_addr;
|
||||
RtlAddFunctionTable(
|
||||
(RUNTIME_FUNCTION*)p,
|
||||
s1->uw_pdata->data_offset / sizeof (RUNTIME_FUNCTION),
|
||||
s1->pe_imagebase
|
||||
);
|
||||
s1->uw_pdata = NULL;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
static void win64_del_function_table(void *p)
|
||||
{
|
||||
if (p) {
|
||||
RtlDeleteFunctionTable((RUNTIME_FUNCTION*)p);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
#ifdef CONFIG_TCC_BACKTRACE
|
||||
|
||||
ST_FUNC void tcc_set_num_callers(int n)
|
||||
{
|
||||
rt_num_callers = n;
|
||||
}
|
||||
|
||||
/* print the position in the source file of PC value 'pc' by reading
|
||||
the stabs debug information */
|
||||
static addr_t rt_printline(addr_t wanted_pc, const char *msg)
|
||||
{
|
||||
char func_name[128], last_func_name[128];
|
||||
addr_t func_addr, last_pc, pc;
|
||||
const char *incl_files[INCLUDE_STACK_SIZE];
|
||||
int incl_index, len, last_line_num, i;
|
||||
const char *str, *p;
|
||||
|
||||
Stab_Sym *stab_sym = NULL, *stab_sym_end, *sym;
|
||||
int stab_len = 0;
|
||||
char *stab_str = NULL;
|
||||
|
||||
if (stab_section) {
|
||||
stab_len = stab_section->data_offset;
|
||||
stab_sym = (Stab_Sym *)stab_section->data;
|
||||
stab_str = (char *) stabstr_section->data;
|
||||
}
|
||||
|
||||
func_name[0] = '\0';
|
||||
func_addr = 0;
|
||||
incl_index = 0;
|
||||
last_func_name[0] = '\0';
|
||||
last_pc = (addr_t)-1;
|
||||
last_line_num = 1;
|
||||
|
||||
if (!stab_sym)
|
||||
goto no_stabs;
|
||||
|
||||
stab_sym_end = (Stab_Sym*)((char*)stab_sym + stab_len);
|
||||
for (sym = stab_sym + 1; sym < stab_sym_end; ++sym) {
|
||||
switch(sym->n_type) {
|
||||
/* function start or end */
|
||||
case N_FUN:
|
||||
if (sym->n_strx == 0) {
|
||||
/* we test if between last line and end of function */
|
||||
pc = sym->n_value + func_addr;
|
||||
if (wanted_pc >= last_pc && wanted_pc < pc)
|
||||
goto found;
|
||||
func_name[0] = '\0';
|
||||
func_addr = 0;
|
||||
} else {
|
||||
str = stab_str + sym->n_strx;
|
||||
p = strchr(str, ':');
|
||||
if (!p) {
|
||||
pstrcpy(func_name, sizeof(func_name), str);
|
||||
} else {
|
||||
len = p - str;
|
||||
if (len > sizeof(func_name) - 1)
|
||||
len = sizeof(func_name) - 1;
|
||||
memcpy(func_name, str, len);
|
||||
func_name[len] = '\0';
|
||||
}
|
||||
func_addr = sym->n_value;
|
||||
}
|
||||
break;
|
||||
/* line number info */
|
||||
case N_SLINE:
|
||||
pc = sym->n_value + func_addr;
|
||||
if (wanted_pc >= last_pc && wanted_pc < pc)
|
||||
goto found;
|
||||
last_pc = pc;
|
||||
last_line_num = sym->n_desc;
|
||||
/* XXX: slow! */
|
||||
strcpy(last_func_name, func_name);
|
||||
break;
|
||||
/* include files */
|
||||
case N_BINCL:
|
||||
str = stab_str + sym->n_strx;
|
||||
add_incl:
|
||||
if (incl_index < INCLUDE_STACK_SIZE) {
|
||||
incl_files[incl_index++] = str;
|
||||
}
|
||||
break;
|
||||
case N_EINCL:
|
||||
if (incl_index > 1)
|
||||
incl_index--;
|
||||
break;
|
||||
case N_SO:
|
||||
if (sym->n_strx == 0) {
|
||||
incl_index = 0; /* end of translation unit */
|
||||
} else {
|
||||
str = stab_str + sym->n_strx;
|
||||
/* do not add path */
|
||||
len = strlen(str);
|
||||
if (len > 0 && str[len - 1] != '/')
|
||||
goto add_incl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
no_stabs:
|
||||
/* second pass: we try symtab symbols (no line number info) */
|
||||
incl_index = 0;
|
||||
if (symtab_section)
|
||||
{
|
||||
ElfW(Sym) *sym, *sym_end;
|
||||
int type;
|
||||
|
||||
sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
|
||||
for(sym = (ElfW(Sym) *)symtab_section->data + 1;
|
||||
sym < sym_end;
|
||||
sym++) {
|
||||
type = ELFW(ST_TYPE)(sym->st_info);
|
||||
if (type == STT_FUNC || type == STT_GNU_IFUNC) {
|
||||
if (wanted_pc >= sym->st_value &&
|
||||
wanted_pc < sym->st_value + sym->st_size) {
|
||||
pstrcpy(last_func_name, sizeof(last_func_name),
|
||||
(char *) symtab_section->link->data + sym->st_name);
|
||||
func_addr = sym->st_value;
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* did not find any info: */
|
||||
fprintf(stderr, "%s %p ???\n", msg, (void*)wanted_pc);
|
||||
fflush(stderr);
|
||||
return 0;
|
||||
found:
|
||||
i = incl_index;
|
||||
if (i > 0)
|
||||
fprintf(stderr, "%s:%d: ", incl_files[--i], last_line_num);
|
||||
fprintf(stderr, "%s %p", msg, (void*)wanted_pc);
|
||||
if (last_func_name[0] != '\0')
|
||||
fprintf(stderr, " %s()", last_func_name);
|
||||
if (--i >= 0) {
|
||||
fprintf(stderr, " (included from ");
|
||||
for (;;) {
|
||||
fprintf(stderr, "%s", incl_files[i]);
|
||||
if (--i < 0)
|
||||
break;
|
||||
fprintf(stderr, ", ");
|
||||
}
|
||||
fprintf(stderr, ")");
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
fflush(stderr);
|
||||
return func_addr;
|
||||
}
|
||||
|
||||
/* emit a run time error at position 'pc' */
|
||||
static void rt_error(ucontext_t *uc, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
addr_t pc;
|
||||
int i;
|
||||
|
||||
fprintf(stderr, "Runtime error: ");
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
for(i=0;i<rt_num_callers;i++) {
|
||||
if (rt_get_caller_pc(&pc, uc, i) < 0)
|
||||
break;
|
||||
pc = rt_printline(pc, i ? "by" : "at");
|
||||
if (pc == (addr_t)rt_prog_main && pc)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
#ifndef _WIN32
|
||||
|
||||
/* signal handler for fatal errors */
|
||||
static void sig_error(int signum, siginfo_t *siginf, void *puc)
|
||||
{
|
||||
ucontext_t *uc = puc;
|
||||
|
||||
switch(signum) {
|
||||
case SIGFPE:
|
||||
switch(siginf->si_code) {
|
||||
case FPE_INTDIV:
|
||||
case FPE_FLTDIV:
|
||||
rt_error(uc, "division by zero");
|
||||
break;
|
||||
default:
|
||||
rt_error(uc, "floating point exception");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SIGBUS:
|
||||
case SIGSEGV:
|
||||
if (rt_bound_error_msg && *rt_bound_error_msg)
|
||||
rt_error(uc, *rt_bound_error_msg);
|
||||
else
|
||||
rt_error(uc, "dereferencing invalid pointer");
|
||||
break;
|
||||
case SIGILL:
|
||||
rt_error(uc, "illegal instruction");
|
||||
break;
|
||||
case SIGABRT:
|
||||
rt_error(uc, "abort() called");
|
||||
break;
|
||||
default:
|
||||
rt_error(uc, "caught signal %d", signum);
|
||||
break;
|
||||
}
|
||||
exit(255);
|
||||
}
|
||||
|
||||
#ifndef SA_SIGINFO
|
||||
# define SA_SIGINFO 0x00000004u
|
||||
#endif
|
||||
|
||||
/* Generate a stack backtrace when a CPU exception occurs. */
|
||||
static void set_exception_handler(void)
|
||||
{
|
||||
struct sigaction sigact;
|
||||
/* install TCC signal handlers to print debug info on fatal
|
||||
runtime errors */
|
||||
sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
|
||||
sigact.sa_sigaction = sig_error;
|
||||
sigemptyset(&sigact.sa_mask);
|
||||
sigaction(SIGFPE, &sigact, NULL);
|
||||
sigaction(SIGILL, &sigact, NULL);
|
||||
sigaction(SIGSEGV, &sigact, NULL);
|
||||
sigaction(SIGBUS, &sigact, NULL);
|
||||
sigaction(SIGABRT, &sigact, NULL);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
#ifdef __i386__
|
||||
|
||||
/* fix for glibc 2.1 */
|
||||
#ifndef REG_EIP
|
||||
#define REG_EIP EIP
|
||||
#define REG_EBP EBP
|
||||
#endif
|
||||
|
||||
/* return the PC at frame level 'level'. Return negative if not found */
|
||||
static int rt_get_caller_pc(addr_t *paddr, ucontext_t *uc, int level)
|
||||
{
|
||||
addr_t fp;
|
||||
int i;
|
||||
|
||||
if (level == 0) {
|
||||
#if defined(__APPLE__)
|
||||
*paddr = uc->uc_mcontext->__ss.__eip;
|
||||
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
|
||||
*paddr = uc->uc_mcontext.mc_eip;
|
||||
#elif defined(__dietlibc__)
|
||||
*paddr = uc->uc_mcontext.eip;
|
||||
#elif defined(__NetBSD__)
|
||||
*paddr = uc->uc_mcontext.__gregs[_REG_EIP];
|
||||
#elif defined(__OpenBSD__)
|
||||
*paddr = uc->sc_eip;
|
||||
#else
|
||||
*paddr = uc->uc_mcontext.gregs[REG_EIP];
|
||||
#endif
|
||||
return 0;
|
||||
} else {
|
||||
#if defined(__APPLE__)
|
||||
fp = uc->uc_mcontext->__ss.__ebp;
|
||||
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
|
||||
fp = uc->uc_mcontext.mc_ebp;
|
||||
#elif defined(__dietlibc__)
|
||||
fp = uc->uc_mcontext.ebp;
|
||||
#elif defined(__NetBSD__)
|
||||
fp = uc->uc_mcontext.__gregs[_REG_EBP];
|
||||
#elif defined(__OpenBSD__)
|
||||
*paddr = uc->sc_ebp;
|
||||
#else
|
||||
fp = uc->uc_mcontext.gregs[REG_EBP];
|
||||
#endif
|
||||
for(i=1;i<level;i++) {
|
||||
/* XXX: check address validity with program info */
|
||||
if (fp <= 0x1000 || fp >= 0xc0000000)
|
||||
return -1;
|
||||
fp = ((addr_t *)fp)[0];
|
||||
}
|
||||
*paddr = ((addr_t *)fp)[1];
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
#elif defined(__x86_64__)
|
||||
|
||||
/* return the PC at frame level 'level'. Return negative if not found */
|
||||
static int rt_get_caller_pc(addr_t *paddr, ucontext_t *uc, int level)
|
||||
{
|
||||
addr_t fp;
|
||||
int i;
|
||||
|
||||
if (level == 0) {
|
||||
/* XXX: only support linux */
|
||||
#if defined(__APPLE__)
|
||||
*paddr = uc->uc_mcontext->__ss.__rip;
|
||||
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
|
||||
*paddr = uc->uc_mcontext.mc_rip;
|
||||
#elif defined(__NetBSD__)
|
||||
*paddr = uc->uc_mcontext.__gregs[_REG_RIP];
|
||||
#else
|
||||
*paddr = uc->uc_mcontext.gregs[REG_RIP];
|
||||
#endif
|
||||
return 0;
|
||||
} else {
|
||||
#if defined(__APPLE__)
|
||||
fp = uc->uc_mcontext->__ss.__rbp;
|
||||
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
|
||||
fp = uc->uc_mcontext.mc_rbp;
|
||||
#elif defined(__NetBSD__)
|
||||
fp = uc->uc_mcontext.__gregs[_REG_RBP];
|
||||
#else
|
||||
fp = uc->uc_mcontext.gregs[REG_RBP];
|
||||
#endif
|
||||
for(i=1;i<level;i++) {
|
||||
/* XXX: check address validity with program info */
|
||||
if (fp <= 0x1000)
|
||||
return -1;
|
||||
fp = ((addr_t *)fp)[0];
|
||||
}
|
||||
*paddr = ((addr_t *)fp)[1];
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
#elif defined(__arm__)
|
||||
|
||||
/* return the PC at frame level 'level'. Return negative if not found */
|
||||
static int rt_get_caller_pc(addr_t *paddr, ucontext_t *uc, int level)
|
||||
{
|
||||
addr_t fp, sp;
|
||||
int i;
|
||||
|
||||
if (level == 0) {
|
||||
/* XXX: only supports linux */
|
||||
#if defined(__linux__)
|
||||
*paddr = uc->uc_mcontext.arm_pc;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
return 0;
|
||||
} else {
|
||||
#if defined(__linux__)
|
||||
fp = uc->uc_mcontext.arm_fp;
|
||||
sp = uc->uc_mcontext.arm_sp;
|
||||
if (sp < 0x1000)
|
||||
sp = 0x1000;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
/* XXX: specific to tinycc stack frames */
|
||||
if (fp < sp + 12 || fp & 3)
|
||||
return -1;
|
||||
for(i = 1; i < level; i++) {
|
||||
sp = ((addr_t *)fp)[-2];
|
||||
if (sp < fp || sp - fp > 16 || sp & 3)
|
||||
return -1;
|
||||
fp = ((addr_t *)fp)[-3];
|
||||
if (fp <= sp || fp - sp < 12 || fp & 3)
|
||||
return -1;
|
||||
}
|
||||
/* XXX: check address validity with program info */
|
||||
*paddr = ((addr_t *)fp)[-1];
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
#elif defined(__aarch64__)
|
||||
|
||||
static int rt_get_caller_pc(addr_t *paddr, ucontext_t *uc, int level)
|
||||
{
|
||||
if (level < 0)
|
||||
return -1;
|
||||
else if (level == 0) {
|
||||
*paddr = uc->uc_mcontext.pc;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
addr_t *fp = (addr_t *)uc->uc_mcontext.regs[29];
|
||||
int i;
|
||||
for (i = 1; i < level; i++)
|
||||
fp = (addr_t *)fp[0];
|
||||
*paddr = fp[1];
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
#else
|
||||
|
||||
#warning add arch specific rt_get_caller_pc()
|
||||
static int rt_get_caller_pc(addr_t *paddr, ucontext_t *uc, int level)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif /* !__i386__ */
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
#else /* WIN32 */
|
||||
|
||||
static long __stdcall cpu_exception_handler(EXCEPTION_POINTERS *ex_info)
|
||||
{
|
||||
EXCEPTION_RECORD *er = ex_info->ExceptionRecord;
|
||||
CONTEXT *uc = ex_info->ContextRecord;
|
||||
switch (er->ExceptionCode) {
|
||||
case EXCEPTION_ACCESS_VIOLATION:
|
||||
if (rt_bound_error_msg && *rt_bound_error_msg)
|
||||
rt_error(uc, *rt_bound_error_msg);
|
||||
else
|
||||
rt_error(uc, "access violation");
|
||||
break;
|
||||
case EXCEPTION_STACK_OVERFLOW:
|
||||
rt_error(uc, "stack overflow");
|
||||
break;
|
||||
case EXCEPTION_INT_DIVIDE_BY_ZERO:
|
||||
rt_error(uc, "division by zero");
|
||||
break;
|
||||
default:
|
||||
rt_error(uc, "exception caught");
|
||||
break;
|
||||
}
|
||||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
}
|
||||
|
||||
/* Generate a stack backtrace when a CPU exception occurs. */
|
||||
static void set_exception_handler(void)
|
||||
{
|
||||
SetUnhandledExceptionFilter(cpu_exception_handler);
|
||||
}
|
||||
|
||||
/* return the PC at frame level 'level'. Return non zero if not found */
|
||||
static int rt_get_caller_pc(addr_t *paddr, CONTEXT *uc, int level)
|
||||
{
|
||||
addr_t fp, pc;
|
||||
int i;
|
||||
#ifdef _WIN64
|
||||
pc = uc->Rip;
|
||||
fp = uc->Rbp;
|
||||
#else
|
||||
pc = uc->Eip;
|
||||
fp = uc->Ebp;
|
||||
#endif
|
||||
if (level > 0) {
|
||||
for(i=1;i<level;i++) {
|
||||
/* XXX: check address validity with program info */
|
||||
if (fp <= 0x1000 || fp >= 0xc0000000)
|
||||
return -1;
|
||||
fp = ((addr_t*)fp)[0];
|
||||
}
|
||||
pc = ((addr_t*)fp)[1];
|
||||
}
|
||||
*paddr = pc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* _WIN32 */
|
||||
#endif /* CONFIG_TCC_BACKTRACE */
|
||||
/* ------------------------------------------------------------- */
|
||||
#ifdef CONFIG_TCC_STATIC
|
||||
|
||||
/* dummy function for profiling */
|
||||
ST_FUNC void *dlopen(const char *filename, int flag)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ST_FUNC void dlclose(void *p)
|
||||
{
|
||||
}
|
||||
|
||||
ST_FUNC const char *dlerror(void)
|
||||
{
|
||||
return "error";
|
||||
}
|
||||
|
||||
typedef struct TCCSyms {
|
||||
char *str;
|
||||
void *ptr;
|
||||
} TCCSyms;
|
||||
|
||||
|
||||
/* add the symbol you want here if no dynamic linking is done */
|
||||
static TCCSyms tcc_syms[] = {
|
||||
#if !defined(CONFIG_TCCBOOT)
|
||||
#define TCCSYM(a) { #a, &a, },
|
||||
TCCSYM(printf)
|
||||
TCCSYM(fprintf)
|
||||
TCCSYM(fopen)
|
||||
TCCSYM(fclose)
|
||||
#undef TCCSYM
|
||||
#endif
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
ST_FUNC void *dlsym(void *handle, const char *symbol)
|
||||
{
|
||||
TCCSyms *p;
|
||||
p = tcc_syms;
|
||||
while (p->str != NULL) {
|
||||
if (!strcmp(p->str, symbol))
|
||||
return p->ptr;
|
||||
p++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_TCC_STATIC */
|
||||
#endif /* TCC_IS_NATIVE */
|
||||
/* ------------------------------------------------------------- */
|
1641
05/tcc-0.9.27/tcctok.h
Normal file
1641
05/tcc-0.9.27/tcctok.h
Normal file
File diff suppressed because it is too large
Load diff
546
05/tcc-0.9.27/tcctools.c
Normal file
546
05/tcc-0.9.27/tcctools.c
Normal file
|
@ -0,0 +1,546 @@
|
|||
/* -------------------------------------------------------------- */
|
||||
/*
|
||||
* TCC - Tiny C Compiler
|
||||
*
|
||||
* tcctools.c - extra tools and and -m32/64 support
|
||||
*
|
||||
*/
|
||||
|
||||
/* -------------------------------------------------------------- */
|
||||
/*
|
||||
* This program is for making libtcc1.a without ar
|
||||
* tiny_libmaker - tiny elf lib maker
|
||||
* usage: tiny_libmaker [lib] files...
|
||||
* Copyright (c) 2007 Timppa
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "tcc.h"
|
||||
|
||||
//#define ARMAG "!<arch>\n"
|
||||
#define ARFMAG "`\n"
|
||||
|
||||
typedef struct {
|
||||
char ar_name[16];
|
||||
char ar_date[12];
|
||||
char ar_uid[6];
|
||||
char ar_gid[6];
|
||||
char ar_mode[8];
|
||||
char ar_size[10];
|
||||
char ar_fmag[2];
|
||||
} ArHdr;
|
||||
|
||||
static unsigned long le2belong(unsigned long ul) {
|
||||
return ((ul & 0xFF0000)>>8)+((ul & 0xFF000000)>>24) +
|
||||
((ul & 0xFF)<<24)+((ul & 0xFF00)<<8);
|
||||
}
|
||||
|
||||
/* Returns 1 if s contains any of the chars of list, else 0 */
|
||||
static int contains_any(const char *s, const char *list) {
|
||||
const char *l;
|
||||
for (; *s; s++) {
|
||||
for (l = list; *l; l++) {
|
||||
if (*s == *l)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ar_usage(int ret) {
|
||||
fprintf(stderr, "usage: tcc -ar [rcsv] lib file...\n");
|
||||
fprintf(stderr, "create library ([abdioptxN] not supported).\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv)
|
||||
{
|
||||
static ArHdr arhdr = {
|
||||
"/ ",
|
||||
" ",
|
||||
"0 ",
|
||||
"0 ",
|
||||
"0 ",
|
||||
" ",
|
||||
ARFMAG
|
||||
};
|
||||
|
||||
static ArHdr arhdro = {
|
||||
" ",
|
||||
" ",
|
||||
"0 ",
|
||||
"0 ",
|
||||
"0 ",
|
||||
" ",
|
||||
ARFMAG
|
||||
};
|
||||
|
||||
FILE *fi, *fh = NULL, *fo = NULL;
|
||||
ElfW(Ehdr) *ehdr;
|
||||
ElfW(Shdr) *shdr;
|
||||
ElfW(Sym) *sym;
|
||||
int i, fsize, i_lib, i_obj;
|
||||
char *buf, *shstr, *symtab = NULL, *strtab = NULL;
|
||||
int symtabsize = 0;//, strtabsize = 0;
|
||||
char *anames = NULL;
|
||||
int *afpos = NULL;
|
||||
int istrlen, strpos = 0, fpos = 0, funccnt = 0, funcmax, hofs;
|
||||
char tfile[260], stmp[20];
|
||||
char *file, *name;
|
||||
int ret = 2;
|
||||
const char *ops_conflict = "habdioptxN"; // unsupported but destructive if ignored.
|
||||
int verbose = 0;
|
||||
|
||||
i_lib = 0; i_obj = 0; // will hold the index of the lib and first obj
|
||||
for (i = 1; i < argc; i++) {
|
||||
const char *a = argv[i];
|
||||
if (*a == '-' && strstr(a, "."))
|
||||
ret = 1; // -x.y is always invalid (same as gnu ar)
|
||||
if ((*a == '-') || (i == 1 && !strstr(a, "."))) { // options argument
|
||||
if (contains_any(a, ops_conflict))
|
||||
ret = 1;
|
||||
if (strstr(a, "v"))
|
||||
verbose = 1;
|
||||
} else { // lib or obj files: don't abort - keep validating all args.
|
||||
if (!i_lib) // first file is the lib
|
||||
i_lib = i;
|
||||
else if (!i_obj) // second file is the first obj
|
||||
i_obj = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (!i_obj) // i_obj implies also i_lib. we require both.
|
||||
ret = 1;
|
||||
|
||||
if (ret == 1)
|
||||
return ar_usage(ret);
|
||||
|
||||
if ((fh = fopen(argv[i_lib], "wb")) == NULL)
|
||||
{
|
||||
fprintf(stderr, "tcc: ar: can't open file %s \n", argv[i_lib]);
|
||||
goto the_end;
|
||||
}
|
||||
|
||||
sprintf(tfile, "%s.tmp", argv[i_lib]);
|
||||
if ((fo = fopen(tfile, "wb+")) == NULL)
|
||||
{
|
||||
fprintf(stderr, "tcc: ar: can't create temporary file %s\n", tfile);
|
||||
goto the_end;
|
||||
}
|
||||
|
||||
funcmax = 250;
|
||||
afpos = tcc_realloc(NULL, funcmax * sizeof *afpos); // 250 func
|
||||
memcpy(&arhdro.ar_mode, "100666", 6);
|
||||
|
||||
// i_obj = first input object file
|
||||
while (i_obj < argc)
|
||||
{
|
||||
if (*argv[i_obj] == '-') { // by now, all options start with '-'
|
||||
i_obj++;
|
||||
continue;
|
||||
}
|
||||
if ((fi = fopen(argv[i_obj], "rb")) == NULL) {
|
||||
fprintf(stderr, "tcc: ar: can't open file %s \n", argv[i_obj]);
|
||||
goto the_end;
|
||||
}
|
||||
if (verbose)
|
||||
printf("a - %s\n", argv[i_obj]);
|
||||
|
||||
fseek(fi, 0, SEEK_END);
|
||||
fsize = ftell(fi);
|
||||
fseek(fi, 0, SEEK_SET);
|
||||
buf = tcc_malloc(fsize + 1);
|
||||
fread(buf, fsize, 1, fi);
|
||||
fclose(fi);
|
||||
|
||||
// elf header
|
||||
ehdr = (ElfW(Ehdr) *)buf;
|
||||
if (ehdr->e_ident[4] != ELFCLASSW)
|
||||
{
|
||||
fprintf(stderr, "tcc: ar: Unsupported Elf Class: %s\n", argv[i_obj]);
|
||||
goto the_end;
|
||||
}
|
||||
|
||||
shdr = (ElfW(Shdr) *) (buf + ehdr->e_shoff + ehdr->e_shstrndx * ehdr->e_shentsize);
|
||||
shstr = (char *)(buf + shdr->sh_offset);
|
||||
for (i = 0; i < ehdr->e_shnum; i++)
|
||||
{
|
||||
shdr = (ElfW(Shdr) *) (buf + ehdr->e_shoff + i * ehdr->e_shentsize);
|
||||
if (!shdr->sh_offset)
|
||||
continue;
|
||||
if (shdr->sh_type == SHT_SYMTAB)
|
||||
{
|
||||
symtab = (char *)(buf + shdr->sh_offset);
|
||||
symtabsize = shdr->sh_size;
|
||||
}
|
||||
if (shdr->sh_type == SHT_STRTAB)
|
||||
{
|
||||
if (!strcmp(shstr + shdr->sh_name, ".strtab"))
|
||||
{
|
||||
strtab = (char *)(buf + shdr->sh_offset);
|
||||
//strtabsize = shdr->sh_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (symtab && symtabsize)
|
||||
{
|
||||
int nsym = symtabsize / sizeof(ElfW(Sym));
|
||||
//printf("symtab: info size shndx name\n");
|
||||
for (i = 1; i < nsym; i++)
|
||||
{
|
||||
sym = (ElfW(Sym) *) (symtab + i * sizeof(ElfW(Sym)));
|
||||
if (sym->st_shndx &&
|
||||
(sym->st_info == 0x10
|
||||
|| sym->st_info == 0x11
|
||||
|| sym->st_info == 0x12
|
||||
)) {
|
||||
//printf("symtab: %2Xh %4Xh %2Xh %s\n", sym->st_info, sym->st_size, sym->st_shndx, strtab + sym->st_name);
|
||||
istrlen = strlen(strtab + sym->st_name)+1;
|
||||
anames = tcc_realloc(anames, strpos+istrlen);
|
||||
strcpy(anames + strpos, strtab + sym->st_name);
|
||||
strpos += istrlen;
|
||||
if (++funccnt >= funcmax) {
|
||||
funcmax += 250;
|
||||
afpos = tcc_realloc(afpos, funcmax * sizeof *afpos); // 250 func more
|
||||
}
|
||||
afpos[funccnt] = fpos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
file = argv[i_obj];
|
||||
for (name = strchr(file, 0);
|
||||
name > file && name[-1] != '/' && name[-1] != '\\';
|
||||
--name);
|
||||
istrlen = strlen(name);
|
||||
if (istrlen >= sizeof(arhdro.ar_name))
|
||||
istrlen = sizeof(arhdro.ar_name) - 1;
|
||||
memset(arhdro.ar_name, ' ', sizeof(arhdro.ar_name));
|
||||
memcpy(arhdro.ar_name, name, istrlen);
|
||||
arhdro.ar_name[istrlen] = '/';
|
||||
sprintf(stmp, "%-10d", fsize);
|
||||
memcpy(&arhdro.ar_size, stmp, 10);
|
||||
fwrite(&arhdro, sizeof(arhdro), 1, fo);
|
||||
fwrite(buf, fsize, 1, fo);
|
||||
tcc_free(buf);
|
||||
i_obj++;
|
||||
fpos += (fsize + sizeof(arhdro));
|
||||
}
|
||||
hofs = 8 + sizeof(arhdr) + strpos + (funccnt+1) * sizeof(int);
|
||||
fpos = 0;
|
||||
if ((hofs & 1)) // align
|
||||
hofs++, fpos = 1;
|
||||
// write header
|
||||
fwrite("!<arch>\n", 8, 1, fh);
|
||||
sprintf(stmp, "%-10d", (int)(strpos + (funccnt+1) * sizeof(int)));
|
||||
memcpy(&arhdr.ar_size, stmp, 10);
|
||||
fwrite(&arhdr, sizeof(arhdr), 1, fh);
|
||||
afpos[0] = le2belong(funccnt);
|
||||
for (i=1; i<=funccnt; i++)
|
||||
afpos[i] = le2belong(afpos[i] + hofs);
|
||||
fwrite(afpos, (funccnt+1) * sizeof(int), 1, fh);
|
||||
fwrite(anames, strpos, 1, fh);
|
||||
if (fpos)
|
||||
fwrite("", 1, 1, fh);
|
||||
// write objects
|
||||
fseek(fo, 0, SEEK_END);
|
||||
fsize = ftell(fo);
|
||||
fseek(fo, 0, SEEK_SET);
|
||||
buf = tcc_malloc(fsize + 1);
|
||||
fread(buf, fsize, 1, fo);
|
||||
fwrite(buf, fsize, 1, fh);
|
||||
tcc_free(buf);
|
||||
ret = 0;
|
||||
the_end:
|
||||
if (anames)
|
||||
tcc_free(anames);
|
||||
if (afpos)
|
||||
tcc_free(afpos);
|
||||
if (fh)
|
||||
fclose(fh);
|
||||
if (fo)
|
||||
fclose(fo), remove(tfile);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------- */
|
||||
/*
|
||||
* tiny_impdef creates an export definition file (.def) from a dll
|
||||
* on MS-Windows. Usage: tiny_impdef library.dll [-o outputfile]"
|
||||
*
|
||||
* Copyright (c) 2005,2007 grischka
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifdef TCC_TARGET_PE
|
||||
|
||||
ST_FUNC int tcc_tool_impdef(TCCState *s1, int argc, char **argv)
|
||||
{
|
||||
int ret, v, i;
|
||||
char infile[260];
|
||||
char outfile[260];
|
||||
|
||||
const char *file;
|
||||
char *p, *q;
|
||||
FILE *fp, *op;
|
||||
|
||||
#ifdef _WIN32
|
||||
char path[260];
|
||||
#endif
|
||||
|
||||
infile[0] = outfile[0] = 0;
|
||||
fp = op = NULL;
|
||||
ret = 1;
|
||||
p = NULL;
|
||||
v = 0;
|
||||
|
||||
for (i = 1; i < argc; ++i) {
|
||||
const char *a = argv[i];
|
||||
if ('-' == a[0]) {
|
||||
if (0 == strcmp(a, "-v")) {
|
||||
v = 1;
|
||||
} else if (0 == strcmp(a, "-o")) {
|
||||
if (++i == argc)
|
||||
goto usage;
|
||||
strcpy(outfile, argv[i]);
|
||||
} else
|
||||
goto usage;
|
||||
} else if (0 == infile[0])
|
||||
strcpy(infile, a);
|
||||
else
|
||||
goto usage;
|
||||
}
|
||||
|
||||
if (0 == infile[0]) {
|
||||
usage:
|
||||
fprintf(stderr,
|
||||
"usage: tcc -impdef library.dll [-v] [-o outputfile]\n"
|
||||
"create export definition file (.def) from dll\n"
|
||||
);
|
||||
goto the_end;
|
||||
}
|
||||
|
||||
if (0 == outfile[0]) {
|
||||
strcpy(outfile, tcc_basename(infile));
|
||||
q = strrchr(outfile, '.');
|
||||
if (NULL == q)
|
||||
q = strchr(outfile, 0);
|
||||
strcpy(q, ".def");
|
||||
}
|
||||
|
||||
file = infile;
|
||||
#ifdef _WIN32
|
||||
if (SearchPath(NULL, file, ".dll", sizeof path, path, NULL))
|
||||
file = path;
|
||||
#endif
|
||||
ret = tcc_get_dllexports(file, &p);
|
||||
if (ret || !p) {
|
||||
fprintf(stderr, "tcc: impdef: %s '%s'\n",
|
||||
ret == -1 ? "can't find file" :
|
||||
ret == 1 ? "can't read symbols" :
|
||||
ret == 0 ? "no symbols found in" :
|
||||
"unknown file type", file);
|
||||
ret = 1;
|
||||
goto the_end;
|
||||
}
|
||||
|
||||
if (v)
|
||||
printf("-> %s\n", file);
|
||||
|
||||
op = fopen(outfile, "wb");
|
||||
if (NULL == op) {
|
||||
fprintf(stderr, "tcc: impdef: could not create output file: %s\n", outfile);
|
||||
goto the_end;
|
||||
}
|
||||
|
||||
fprintf(op, "LIBRARY %s\n\nEXPORTS\n", tcc_basename(file));
|
||||
for (q = p, i = 0; *q; ++i) {
|
||||
fprintf(op, "%s\n", q);
|
||||
q += strlen(q) + 1;
|
||||
}
|
||||
|
||||
if (v)
|
||||
printf("<- %s (%d symbol%s)\n", outfile, i, &"s"[i<2]);
|
||||
|
||||
ret = 0;
|
||||
|
||||
the_end:
|
||||
/* cannot free memory received from tcc_get_dllexports
|
||||
if it came from a dll */
|
||||
/* if (p)
|
||||
tcc_free(p); */
|
||||
if (fp)
|
||||
fclose(fp);
|
||||
if (op)
|
||||
fclose(op);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* TCC_TARGET_PE */
|
||||
|
||||
/* -------------------------------------------------------------- */
|
||||
/*
|
||||
* TCC - Tiny C Compiler
|
||||
*
|
||||
* Copyright (c) 2001-2004 Fabrice Bellard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser 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
|
||||
*/
|
||||
|
||||
/* re-execute the i386/x86_64 cross-compilers with tcc -m32/-m64: */
|
||||
|
||||
#if !defined TCC_TARGET_I386 && !defined TCC_TARGET_X86_64
|
||||
|
||||
ST_FUNC void tcc_tool_cross(TCCState *s, char **argv, int option)
|
||||
{
|
||||
tcc_error("-m%d not implemented.", option);
|
||||
}
|
||||
|
||||
#else
|
||||
#ifdef _WIN32
|
||||
#include <process.h>
|
||||
|
||||
static char *str_replace(const char *str, const char *p, const char *r)
|
||||
{
|
||||
const char *s, *s0;
|
||||
char *d, *d0;
|
||||
int sl, pl, rl;
|
||||
|
||||
sl = strlen(str);
|
||||
pl = strlen(p);
|
||||
rl = strlen(r);
|
||||
for (d0 = NULL;; d0 = tcc_malloc(sl + 1)) {
|
||||
for (d = d0, s = str; s0 = s, s = strstr(s, p), s; s += pl) {
|
||||
if (d) {
|
||||
memcpy(d, s0, sl = s - s0), d += sl;
|
||||
memcpy(d, r, rl), d += rl;
|
||||
} else
|
||||
sl += rl - pl;
|
||||
}
|
||||
if (d) {
|
||||
strcpy(d, s0);
|
||||
return d0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int execvp_win32(const char *prog, char **argv)
|
||||
{
|
||||
int ret; char **p;
|
||||
/* replace all " by \" */
|
||||
for (p = argv; *p; ++p)
|
||||
if (strchr(*p, '"'))
|
||||
*p = str_replace(*p, "\"", "\\\"");
|
||||
ret = _spawnvp(P_NOWAIT, prog, (const char *const*)argv);
|
||||
if (-1 == ret)
|
||||
return ret;
|
||||
_cwait(&ret, ret, WAIT_CHILD);
|
||||
exit(ret);
|
||||
}
|
||||
#define execvp execvp_win32
|
||||
#endif /* _WIN32 */
|
||||
|
||||
ST_FUNC void tcc_tool_cross(TCCState *s, char **argv, int target)
|
||||
{
|
||||
char program[4096];
|
||||
char *a0 = argv[0];
|
||||
int prefix = tcc_basename(a0) - a0;
|
||||
|
||||
snprintf(program, sizeof program,
|
||||
"%.*s%s"
|
||||
#ifdef TCC_TARGET_PE
|
||||
"-win32"
|
||||
#endif
|
||||
"-tcc"
|
||||
#ifdef _WIN32
|
||||
".exe"
|
||||
#endif
|
||||
, prefix, a0, target == 64 ? "x86_64" : "i386");
|
||||
|
||||
if (strcmp(a0, program))
|
||||
execvp(argv[0] = program, argv);
|
||||
tcc_error("could not run '%s'", program);
|
||||
}
|
||||
|
||||
#endif /* TCC_TARGET_I386 && TCC_TARGET_X86_64 */
|
||||
/* -------------------------------------------------------------- */
|
||||
/* enable commandline wildcard expansion (tcc -o x.exe *.c) */
|
||||
|
||||
#ifdef _WIN32
|
||||
int _CRT_glob = 1;
|
||||
#ifndef _CRT_glob
|
||||
int _dowildcard = 1;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* -------------------------------------------------------------- */
|
||||
/* generate xxx.d file */
|
||||
|
||||
ST_FUNC void gen_makedeps(TCCState *s, const char *target, const char *filename)
|
||||
{
|
||||
FILE *depout;
|
||||
char buf[1024];
|
||||
int i;
|
||||
|
||||
if (!filename) {
|
||||
/* compute filename automatically: dir/file.o -> dir/file.d */
|
||||
snprintf(buf, sizeof buf, "%.*s.d",
|
||||
(int)(tcc_fileextension(target) - target), target);
|
||||
filename = buf;
|
||||
}
|
||||
|
||||
if (s->verbose)
|
||||
printf("<- %s\n", filename);
|
||||
|
||||
/* XXX return err codes instead of error() ? */
|
||||
depout = fopen(filename, "w");
|
||||
if (!depout)
|
||||
tcc_error("could not open '%s'", filename);
|
||||
|
||||
fprintf(depout, "%s: \\\n", target);
|
||||
for (i=0; i<s->nb_target_deps; ++i)
|
||||
fprintf(depout, " %s \\\n", s->target_deps[i]);
|
||||
fprintf(depout, "\n");
|
||||
fclose(depout);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------- */
|
13
05/tcc-0.9.27/tests/42test.h
Normal file
13
05/tcc-0.9.27/tests/42test.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
/* This file is to test compute #include directives. It's named so
|
||||
that it starts with a pre-processing number which isn't a valid
|
||||
number (42test.h). Including this must work. */
|
||||
#ifndef INC42_FIRST
|
||||
int have_included_42test_h;
|
||||
#define INC42_FIRST
|
||||
#elif !defined INC42_SECOND
|
||||
#define INC42_SECOND
|
||||
int have_included_42test_h_second;
|
||||
#else
|
||||
#define INC42_THIRD
|
||||
int have_included_42test_h_third;
|
||||
#endif
|
289
05/tcc-0.9.27/tests/Makefile
Normal file
289
05/tcc-0.9.27/tests/Makefile
Normal file
|
@ -0,0 +1,289 @@
|
|||
#
|
||||
# Tiny C Compiler Makefile - tests
|
||||
#
|
||||
|
||||
TOP = ..
|
||||
include $(TOP)/Makefile
|
||||
VPATH = $(TOPSRC)/tests $(TOPSRC) $(TOP)
|
||||
CFLAGS := $(filter-out -W% -g% -O%,$(CFLAGS)) -I$(TOPSRC) $(LDFLAGS)
|
||||
|
||||
# what tests to run
|
||||
TESTS = \
|
||||
hello-exe \
|
||||
hello-run \
|
||||
libtest \
|
||||
test3 \
|
||||
memtest \
|
||||
dlltest \
|
||||
abitest \
|
||||
asm-c-connect-test \
|
||||
vla_test-run \
|
||||
cross-test \
|
||||
tests2-dir \
|
||||
pp-dir
|
||||
|
||||
BTESTS = test1b test3b btest
|
||||
|
||||
# test4 -- problem with -static
|
||||
# asmtest / asmtest2 -- minor differences with gcc
|
||||
# btest -- works on i386 (including win32)
|
||||
|
||||
# bounds-checking is supported only on i386
|
||||
ifneq ($(ARCH),i386)
|
||||
TESTS := $(filter-out $(BTESTS),$(TESTS))
|
||||
endif
|
||||
ifdef CONFIG_WIN32
|
||||
TESTS := $(filter-out $(BTESTS),$(TESTS))
|
||||
endif
|
||||
ifdef CONFIG_OSX # -run only
|
||||
TESTS := hello-run libtest tests2-dir pp-dir
|
||||
endif
|
||||
ifeq (,$(filter arm64 i386 x86_64,$(ARCH)))
|
||||
TESTS := $(filter-out vla_test-run,$(TESTS))
|
||||
endif
|
||||
ifeq ($(CONFIG_arm_eabi),yes)
|
||||
TESTS := $(filter-out test3,$(TESTS))
|
||||
endif
|
||||
ifeq (,$(filter i386 x86_64,$(ARCH)))
|
||||
TESTS := $(filter-out dlltest asm-c-connect-test,$(TESTS))
|
||||
endif
|
||||
ifndef CONFIG_cross
|
||||
TESTS := $(filter-out cross-%,$(TESTS))
|
||||
endif
|
||||
|
||||
ifeq ($(OS),Windows_NT) # for libtcc_test to find libtcc.dll
|
||||
PATH := $(CURDIR)/$(TOP)$(if $(findstring :\,$(PATH)),;,:)$(PATH)
|
||||
endif
|
||||
|
||||
RUN_TCC = $(NATIVE_DEFINES) -run $(TOPSRC)/tcc.c $(TCCFLAGS)
|
||||
DISAS = objdump -d
|
||||
DUMPTCC = (set -x; $(TOP)/tcc -vv; ldd $(TOP)/tcc; exit 1)
|
||||
|
||||
all test : clean-s $(TESTS)
|
||||
|
||||
hello-exe: ../examples/ex1.c
|
||||
@echo ------------ $@ ------------
|
||||
$(TCC) $< -o hello$(EXESUF) && ./hello$(EXESUF) || $(DUMPTCC)
|
||||
|
||||
hello-run: ../examples/ex1.c
|
||||
@echo ------------ $@ ------------
|
||||
$(TCC) -run $< || $(DUMPTCC)
|
||||
|
||||
libtest: libtcc_test$(EXESUF)
|
||||
@echo ------------ $@ ------------
|
||||
./libtcc_test$(EXESUF) $(TCCFLAGS)
|
||||
|
||||
libtcc_test$(EXESUF): libtcc_test.c $(LIBTCC)
|
||||
$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
|
||||
|
||||
%-dir:
|
||||
@echo ------------ $@ ------------
|
||||
$(MAKE) -k -C $*
|
||||
|
||||
# test.ref - generate using cc
|
||||
test.ref: tcctest.c
|
||||
$(CC) -o tcctest.gcc $< $(NATIVE_DEFINES) $(CFLAGS) -w -O0 -std=gnu99 -fno-omit-frame-pointer
|
||||
./tcctest.gcc > $@
|
||||
|
||||
# auto test
|
||||
test1 test1b: tcctest.c test.ref
|
||||
@echo ------------ $@ ------------
|
||||
$(TCC) -run $< > test.out1
|
||||
@diff -u test.ref test.out1 && echo "Auto Test OK"
|
||||
|
||||
# iterated test2 (compile tcc then compile tcctest.c !)
|
||||
test2 test2b: tcctest.c test.ref
|
||||
@echo ------------ $@ ------------
|
||||
$(TCC) $(RUN_TCC) $(RUN_TCC) -run $< > test.out2
|
||||
@diff -u test.ref test.out2 && echo "Auto Test2 OK"
|
||||
|
||||
# iterated test3 (compile tcc then compile tcc then compile tcctest.c !)
|
||||
test3 test3b: tcctest.c test.ref
|
||||
@echo ------------ $@ ------------
|
||||
$(TCC) $(RUN_TCC) $(RUN_TCC) $(RUN_TCC) -run $< > test.out3
|
||||
@diff -u test.ref test.out3 && echo "Auto Test3 OK"
|
||||
|
||||
test%b : TCCFLAGS += -b
|
||||
|
||||
# binary output test
|
||||
test4: tcctest.c test.ref
|
||||
@echo ------------ $@ ------------
|
||||
# object + link output
|
||||
$(TCC) -c -o tcctest3.o $<
|
||||
$(TCC) -o tcctest3 tcctest3.o
|
||||
./tcctest3 > test3.out
|
||||
@if diff -u test.ref test3.out ; then echo "Object Auto Test OK"; fi
|
||||
# dynamic output
|
||||
$(TCC) -o tcctest1 $<
|
||||
./tcctest1 > test1.out
|
||||
@if diff -u test.ref test1.out ; then echo "Dynamic Auto Test OK"; fi
|
||||
# dynamic output + bound check
|
||||
$(TCC) -b -o tcctest4 $<
|
||||
./tcctest4 > test4.out
|
||||
@if diff -u test.ref test4.out ; then echo "BCheck Auto Test OK"; fi
|
||||
# static output
|
||||
$(TCC) -static -o tcctest2 $<
|
||||
./tcctest2 > test2.out
|
||||
@if diff -u test.ref test2.out ; then echo "Static Auto Test OK"; fi
|
||||
|
||||
# use tcc to create libtcc.so/.dll and the tcc(.exe) frontend and run them
|
||||
dlltest:
|
||||
@echo ------------ $@ ------------
|
||||
$(TCC) $(NATIVE_DEFINES) -DLIBTCC_AS_DLL $(TOPSRC)/libtcc.c $(LIBS) -shared -o libtcc2$(DLLSUF)
|
||||
$(TCC) $(NATIVE_DEFINES) -DONE_SOURCE=0 $(TOPSRC)/tcc.c libtcc2$(DLLSUF) $(LIBS) -Wl,-rpath=. -o tcc2$(EXESUF)
|
||||
./tcc2$(EXESUF) $(TCCFLAGS) $(RUN_TCC) -run $(TOPSRC)/examples/ex1.c
|
||||
ifndef CONFIG_WIN32
|
||||
@echo ------------ $@ with PIC ------------
|
||||
$(CC) $(CFLAGS) -fPIC $(NATIVE_DEFINES) -DLIBTCC_AS_DLL -c $(TOPSRC)/libtcc.c
|
||||
$(TCC) libtcc.o $(LIBS) -shared -o libtcc2$(DLLSUF)
|
||||
$(TCC) $(NATIVE_DEFINES) -DONE_SOURCE=0 $(TOPSRC)/tcc.c libtcc2$(DLLSUF) $(LIBS) -Wl,-rpath=. -o tcc2$(EXESUF)
|
||||
./tcc2$(EXESUF) $(TCCFLAGS) $(RUN_TCC) -run $(TOPSRC)/examples/ex1.c
|
||||
endif
|
||||
@rm tcc2$(EXESUF) libtcc2$(DLLSUF)
|
||||
|
||||
memtest:
|
||||
@echo ------------ $@ ------------
|
||||
$(CC) $(CFLAGS) $(NATIVE_DEFINES) -DMEM_DEBUG=2 $(TOPSRC)/tcc.c $(LIBS) -o memtest-tcc$(EXESUF)
|
||||
./memtest-tcc$(EXESUF) $(TCCFLAGS) $(NATIVE_DEFINES) $(TOPSRC)/tcc.c $(LIBS)
|
||||
./memtest-tcc$(EXESUF) $(TCCFLAGS) $(NATIVE_DEFINES) -run $(TOPSRC)/tcc.c $(TCCFLAGS) $(TOPSRC)/tests/tcctest.c
|
||||
|
||||
|
||||
# memory and bound check auto test
|
||||
BOUNDS_OK = 1 4 8 10 14
|
||||
BOUNDS_FAIL= 2 5 7 9 11 12 13 15
|
||||
|
||||
btest: boundtest.c
|
||||
@echo ------------ $@ ------------
|
||||
@for i in $(BOUNDS_OK); do \
|
||||
echo ; echo --- boundtest $$i ---; \
|
||||
if $(TCC) -b -run $< $$i ; then \
|
||||
echo succeeded as expected; \
|
||||
else\
|
||||
echo Failed positive test $$i ; exit 1 ; \
|
||||
fi ;\
|
||||
done ;\
|
||||
for i in $(BOUNDS_FAIL); do \
|
||||
echo ; echo --- boundtest $$i ---; \
|
||||
if $(TCC) -b -run $< $$i ; then \
|
||||
echo Failed negative test $$i ; exit 1 ;\
|
||||
else\
|
||||
echo failed as expected; \
|
||||
fi ;\
|
||||
done ;\
|
||||
echo; echo Bound test OK
|
||||
|
||||
# speed test
|
||||
speedtest: ex2 ex3
|
||||
@echo ------------ $@ ------------
|
||||
time ./ex2 1238 2 3 4 10 13 4
|
||||
time $(TCC) -run $(TOPSRC)/examples/ex2.c 1238 2 3 4 10 13 4
|
||||
time ./ex3 35
|
||||
time $(TCC) -run $(TOPSRC)/examples/ex3.c 35
|
||||
|
||||
weaktest: tcctest.c test.ref
|
||||
$(TCC) -c $< -o weaktest.tcc.o
|
||||
$(CC) -c $< -o weaktest.gcc.o $(NATIVE_DEFINES) $(CFLAGS) -w -O0 -std=gnu99 -fno-omit-frame-pointer
|
||||
objdump -t weaktest.tcc.o | grep ' w ' | sed -e 's/.* \([a-zA-Z0-9_]*\)$$/\1/' | LC_ALL=C sort > weaktest.tcc.o.txt
|
||||
objdump -t weaktest.gcc.o | grep ' w ' | sed -e 's/.* \([a-zA-Z0-9_]*\)$$/\1/' | LC_ALL=C sort > weaktest.gcc.o.txt
|
||||
diff weaktest.gcc.o.txt weaktest.tcc.o.txt && echo "Weak Auto Test OK"
|
||||
|
||||
ex%: $(TOPSRC)/examples/ex%.c
|
||||
$(CC) -o $@ $< $(CFLAGS)
|
||||
|
||||
# tiny assembler testing
|
||||
asmtest.ref: asmtest.S
|
||||
$(CC) -Wa,-W -o asmtest.ref.o -c asmtest.S
|
||||
objdump -D asmtest.ref.o > asmtest.ref
|
||||
|
||||
asmtest asmtest2: asmtest.ref
|
||||
@echo ------------ $@ ------------
|
||||
$(TCC) $(MAYBE_RUN_TCC) -c asmtest.S
|
||||
objdump -D asmtest.o > asmtest.out
|
||||
@if diff -u --ignore-matching-lines="file format" asmtest.ref asmtest.out ; then echo "ASM Auto Test OK"; fi
|
||||
|
||||
# test assembler with tcc compiled by itself
|
||||
asmtest2: MAYBE_RUN_TCC = $(RUN_TCC)
|
||||
|
||||
# Check that code generated by libtcc is binary compatible with
|
||||
# that generated by CC
|
||||
abitest-cc$(EXESUF): abitest.c $(LIBTCC)
|
||||
$(CC) -o $@ $^ $(CFLAGS) $(LIBS) -w
|
||||
|
||||
abitest-tcc$(EXESUF): abitest.c libtcc.c
|
||||
$(TCC) -o $@ $^ $(NATIVE_DEFINES) $(LIBS)
|
||||
|
||||
ABITESTS := abitest-cc$(EXESUF)
|
||||
ifneq ($(CONFIG_arm_eabi),yes) # not ARM soft-float
|
||||
ABITESTS += abitest-tcc$(EXESUF)
|
||||
endif
|
||||
|
||||
abitest: $(ABITESTS)
|
||||
@echo ------------ $@ ------------
|
||||
./abitest-cc$(EXESUF) $(TCCFLAGS)
|
||||
ifneq ($(CONFIG_arm_eabi),yes) # not ARM soft-float
|
||||
./abitest-tcc$(EXESUF) $(TCCFLAGS)
|
||||
endif
|
||||
|
||||
vla_test$(EXESUF): vla_test.c
|
||||
$(TCC) -o $@ $^
|
||||
|
||||
vla_test-run: vla_test$(EXESUF)
|
||||
@echo ------------ $@ ------------
|
||||
./vla_test$(EXESUF)
|
||||
|
||||
asm-c-connect$(EXESUF): asm-c-connect-1.c asm-c-connect-2.c
|
||||
$(TCC) -o $@ $^
|
||||
|
||||
asm-c-connect-%.o: asm-c-connect-%.c
|
||||
$(TCC) -c -o $@ $<
|
||||
|
||||
asm-c-connect-sep$(EXESUF): asm-c-connect-1.o asm-c-connect-2.o
|
||||
$(TCC) -o $@ $^
|
||||
|
||||
asm-c-connect-test: asm-c-connect$(EXESUF) asm-c-connect-sep$(EXESUF)
|
||||
@echo ------------ $@ ------------
|
||||
./asm-c-connect$(EXESUF) > asm-c-connect.out1 && cat asm-c-connect.out1
|
||||
./asm-c-connect-sep$(EXESUF) > asm-c-connect.out2 && cat asm-c-connect.out2
|
||||
@diff -u asm-c-connect.out1 asm-c-connect.out2 && echo "ok"
|
||||
|
||||
cross-test :
|
||||
@echo ------------ $@ ------------
|
||||
$(TOP)/i386-tcc$(EXESUF) $(TCCFLAGS-unx) -c $(TOPSRC)/examples/ex3.c && echo "ok"
|
||||
$(TOP)/i386-win32-tcc$(EXESUF) $(TCCFLAGS-win) $(TOPSRC)/examples/ex3.c && echo "ok"
|
||||
$(TOP)/x86_64-tcc$(EXESUF) $(TCCFLAGS-unx) -c $(TOPSRC)/examples/ex3.c && echo "ok"
|
||||
$(TOP)/x86_64-win32-tcc$(EXESUF) $(TCCFLAGS-win) $(TOPSRC)/examples/ex3.c && echo "ok"
|
||||
$(TOP)/arm-tcc$(EXESUF) $(TCCFLAGS-unx) -c $(TOPSRC)/examples/ex3.c && echo "ok"
|
||||
$(TOP)/arm-wince-tcc$(EXESUF) $(TCCFLAGS-win) -c $(TOPSRC)/examples/ex3.c && echo "ok"
|
||||
$(TOP)/arm64-tcc$(EXESUF) $(TCCFLAGS-unx) -c $(TOPSRC)/examples/ex3.c && echo "ok"
|
||||
$(TOP)/c67-tcc$(EXESUF) $(TCCFLAGS-unx) -c $(TOPSRC)/examples/ex3.c && echo "ok"
|
||||
$(TOP)/i386-win32-tcc$(EXESUF) $(TCCFLAGS-win) $(TOPSRC)/win32/examples/hello_win.c && echo "ok"
|
||||
$(TOP)/x86_64-win32-tcc$(EXESUF) $(TCCFLAGS-win) $(TOPSRC)/win32/examples/hello_win.c && echo "ok"
|
||||
$(TOP)/arm-wince-tcc$(EXESUF) $(TCCFLAGS-win) -c $(TOPSRC)/win32/examples/hello_win.c && echo "ok"
|
||||
|
||||
# targets for development
|
||||
%.bin: %.c tcc
|
||||
$(TCC) -g -o $@ $<
|
||||
$(DISAS) $@
|
||||
|
||||
instr: instr.o
|
||||
objdump -d instr.o
|
||||
|
||||
instr.o: instr.S
|
||||
$(CC) -o $@ -c $< -O2 -Wall -g
|
||||
|
||||
cache: tcc_g
|
||||
cachegrind ./tcc_g -o /tmp/linpack -lm bench/linpack.c
|
||||
vg_annotate tcc.c > /tmp/linpack.cache.log
|
||||
|
||||
# clean
|
||||
clean:
|
||||
rm -f *~ *.o *.a *.bin *.i *.ref *.out *.out? *.out?b *.cc *.gcc
|
||||
rm -f *-cc *-gcc *-tcc *.exe hello libtcc_test vla_test tcctest[1234]
|
||||
rm -f asm-c-connect$(EXESUF)
|
||||
rm -f ex? tcc_g weaktest.*.txt *.def
|
||||
@$(MAKE) -C tests2 $@
|
||||
@$(MAKE) -C pp $@
|
||||
|
||||
# silent clean, used before running tests
|
||||
clean-s:
|
||||
@$(MAKE) -s --no-print-directory clean
|
691
05/tcc-0.9.27/tests/abitest.c
Normal file
691
05/tcc-0.9.27/tests/abitest.c
Normal file
|
@ -0,0 +1,691 @@
|
|||
#include <libtcc.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
// MinGW has 80-bit rather than 64-bit long double which isn't compatible with TCC or MSVC
|
||||
#if defined(_WIN32) && defined(__GNUC__)
|
||||
#define LONG_DOUBLE double
|
||||
#define LONG_DOUBLE_LITERAL(x) x
|
||||
#else
|
||||
#define LONG_DOUBLE long double
|
||||
#define LONG_DOUBLE_LITERAL(x) x ## L
|
||||
#endif
|
||||
|
||||
static int g_argc;
|
||||
static char **g_argv;
|
||||
|
||||
static void set_options(TCCState *s, int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
for (i = 1; i < argc; ++i) {
|
||||
char *a = argv[i];
|
||||
if (a[0] == '-') {
|
||||
if (a[1] == 'B')
|
||||
tcc_set_lib_path(s, a+2);
|
||||
else if (a[1] == 'I')
|
||||
tcc_add_include_path(s, a+2);
|
||||
else if (a[1] == 'L')
|
||||
tcc_add_library_path(s, a+2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typedef int (*callback_type) (void*);
|
||||
|
||||
/*
|
||||
* Compile source code and call a callback with a pointer to the symbol "f".
|
||||
*/
|
||||
static int run_callback(const char *src, callback_type callback) {
|
||||
TCCState *s;
|
||||
int result;
|
||||
void *ptr;
|
||||
|
||||
s = tcc_new();
|
||||
if (!s)
|
||||
return -1;
|
||||
|
||||
set_options(s, g_argc, g_argv);
|
||||
|
||||
if (tcc_set_output_type(s, TCC_OUTPUT_MEMORY) == -1)
|
||||
return -1;
|
||||
if (tcc_compile_string(s, src) == -1)
|
||||
return -1;
|
||||
if (tcc_relocate(s, TCC_RELOCATE_AUTO) == -1)
|
||||
return -1;
|
||||
|
||||
ptr = tcc_get_symbol(s, "f");
|
||||
if (!ptr)
|
||||
return -1;
|
||||
result = callback(ptr);
|
||||
|
||||
tcc_delete(s);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#define STR2(x) #x
|
||||
#define STR(x) STR2(x)
|
||||
|
||||
#define RET_PRIMITIVE_TEST(name, type, val) \
|
||||
static int ret_ ## name ## _test_callback(void *ptr) { \
|
||||
type (*callback) (type) = (type(*)(type))ptr; \
|
||||
type x = val; \
|
||||
type y = callback(x); \
|
||||
return (y == x+x) ? 0 : -1; \
|
||||
} \
|
||||
\
|
||||
static int ret_ ## name ## _test(void) { \
|
||||
const char *src = STR(type) " f(" STR(type) " x) {return x+x;}"; \
|
||||
return run_callback(src, ret_ ## name ## _test_callback); \
|
||||
}
|
||||
|
||||
RET_PRIMITIVE_TEST(int, int, 70000)
|
||||
RET_PRIMITIVE_TEST(longlong, long long, 4333369356528LL)
|
||||
RET_PRIMITIVE_TEST(float, float, 63.0)
|
||||
RET_PRIMITIVE_TEST(double, double, 14789798.0)
|
||||
RET_PRIMITIVE_TEST(longdouble, LONG_DOUBLE, LONG_DOUBLE_LITERAL(378943892.0))
|
||||
|
||||
/*
|
||||
* ret_2float_test:
|
||||
*
|
||||
* On x86-64, a struct with 2 floats should be packed into a single
|
||||
* SSE register (VT_DOUBLE is used for this purpose).
|
||||
*/
|
||||
typedef struct ret_2float_test_type_s {float x, y;} ret_2float_test_type;
|
||||
typedef ret_2float_test_type (*ret_2float_test_function_type) (ret_2float_test_type);
|
||||
|
||||
static int ret_2float_test_callback(void *ptr) {
|
||||
ret_2float_test_function_type f = (ret_2float_test_function_type)ptr;
|
||||
ret_2float_test_type a = {10, 35};
|
||||
ret_2float_test_type r;
|
||||
r = f(a);
|
||||
return ((r.x == a.x*5) && (r.y == a.y*3)) ? 0 : -1;
|
||||
}
|
||||
|
||||
static int ret_2float_test(void) {
|
||||
const char *src =
|
||||
"typedef struct ret_2float_test_type_s {float x, y;} ret_2float_test_type;"
|
||||
"ret_2float_test_type f(ret_2float_test_type a) {\n"
|
||||
" ret_2float_test_type r = {a.x*5, a.y*3};\n"
|
||||
" return r;\n"
|
||||
"}\n";
|
||||
|
||||
return run_callback(src, ret_2float_test_callback);
|
||||
}
|
||||
|
||||
/*
|
||||
* ret_2double_test:
|
||||
*
|
||||
* On x86-64, a struct with 2 doubles should be passed in two SSE
|
||||
* registers.
|
||||
*/
|
||||
typedef struct ret_2double_test_type_s {double x, y;} ret_2double_test_type;
|
||||
typedef ret_2double_test_type (*ret_2double_test_function_type) (ret_2double_test_type);
|
||||
|
||||
static int ret_2double_test_callback(void *ptr) {
|
||||
ret_2double_test_function_type f = (ret_2double_test_function_type)ptr;
|
||||
ret_2double_test_type a = {10, 35};
|
||||
ret_2double_test_type r;
|
||||
r = f(a);
|
||||
return ((r.x == a.x*5) && (r.y == a.y*3)) ? 0 : -1;
|
||||
}
|
||||
|
||||
static int ret_2double_test(void) {
|
||||
const char *src =
|
||||
"typedef struct ret_2double_test_type_s {double x, y;} ret_2double_test_type;"
|
||||
"ret_2double_test_type f(ret_2double_test_type a) {\n"
|
||||
" ret_2double_test_type r = {a.x*5, a.y*3};\n"
|
||||
" return r;\n"
|
||||
"}\n";
|
||||
|
||||
return run_callback(src, ret_2double_test_callback);
|
||||
}
|
||||
|
||||
/*
|
||||
* ret_8plus2double_test:
|
||||
*
|
||||
* This catches a corner case in the x86_64 ABI code: the first 7
|
||||
* arguments fit into registers, the 8th doesn't, but the 9th argument
|
||||
* fits into the 8th XMM register.
|
||||
*
|
||||
* Note that the purpose of the 10th argument is to avoid a situation
|
||||
* in which gcc would accidentally put the double at the right
|
||||
* address, thus causing a success message even though TCC actually
|
||||
* generated incorrect code.
|
||||
*/
|
||||
typedef ret_2double_test_type (*ret_8plus2double_test_function_type) (double, double, double, double, double, double, double, ret_2double_test_type, double, double);
|
||||
|
||||
static int ret_8plus2double_test_callback(void *ptr) {
|
||||
ret_8plus2double_test_function_type f = (ret_8plus2double_test_function_type)ptr;
|
||||
ret_2double_test_type a = {10, 35};
|
||||
ret_2double_test_type r;
|
||||
r = f(0, 0, 0, 0, 0, 0, 0, a, 37, 38);
|
||||
return ((r.x == 37) && (r.y == 37)) ? 0 : -1;
|
||||
}
|
||||
|
||||
static int ret_8plus2double_test(void) {
|
||||
const char *src =
|
||||
"typedef struct ret_2double_test_type_s {double x, y;} ret_2double_test_type;"
|
||||
"ret_2double_test_type f(double x1, double x2, double x3, double x4, double x5, double x6, double x7, ret_2double_test_type a, double x8, double x9) {\n"
|
||||
" ret_2double_test_type r = { x8, x8 };\n"
|
||||
" return r;\n"
|
||||
"}\n";
|
||||
|
||||
return run_callback(src, ret_8plus2double_test_callback);
|
||||
}
|
||||
|
||||
/*
|
||||
* ret_mixed_test:
|
||||
*
|
||||
* On x86-64, a struct with a double and a 64-bit integer should be
|
||||
* passed in one SSE register and one integer register.
|
||||
*/
|
||||
typedef struct ret_mixed_test_type_s {double x; long long y;} ret_mixed_test_type;
|
||||
typedef ret_mixed_test_type (*ret_mixed_test_function_type) (ret_mixed_test_type);
|
||||
|
||||
static int ret_mixed_test_callback(void *ptr) {
|
||||
ret_mixed_test_function_type f = (ret_mixed_test_function_type)ptr;
|
||||
ret_mixed_test_type a = {10, 35};
|
||||
ret_mixed_test_type r;
|
||||
r = f(a);
|
||||
return ((r.x == a.x*5) && (r.y == a.y*3)) ? 0 : -1;
|
||||
}
|
||||
|
||||
static int ret_mixed_test(void) {
|
||||
const char *src =
|
||||
"typedef struct ret_mixed_test_type_s {double x; long long y;} ret_mixed_test_type;"
|
||||
"ret_mixed_test_type f(ret_mixed_test_type a) {\n"
|
||||
" ret_mixed_test_type r = {a.x*5, a.y*3};\n"
|
||||
" return r;\n"
|
||||
"}\n";
|
||||
|
||||
return run_callback(src, ret_mixed_test_callback);
|
||||
}
|
||||
|
||||
/*
|
||||
* ret_mixed2_test:
|
||||
*
|
||||
* On x86-64, a struct with two floats and two 32-bit integers should
|
||||
* be passed in one SSE register and one integer register.
|
||||
*/
|
||||
typedef struct ret_mixed2_test_type_s {float x,x2; int y,y2;} ret_mixed2_test_type;
|
||||
typedef ret_mixed2_test_type (*ret_mixed2_test_function_type) (ret_mixed2_test_type);
|
||||
|
||||
static int ret_mixed2_test_callback(void *ptr) {
|
||||
ret_mixed2_test_function_type f = (ret_mixed2_test_function_type)ptr;
|
||||
ret_mixed2_test_type a = {10, 5, 35, 7 };
|
||||
ret_mixed2_test_type r;
|
||||
r = f(a);
|
||||
return ((r.x == a.x*5) && (r.y == a.y*3)) ? 0 : -1;
|
||||
}
|
||||
|
||||
static int ret_mixed2_test(void) {
|
||||
const char *src =
|
||||
"typedef struct ret_mixed2_test_type_s {float x, x2; int y,y2;} ret_mixed2_test_type;"
|
||||
"ret_mixed2_test_type f(ret_mixed2_test_type a) {\n"
|
||||
" ret_mixed2_test_type r = {a.x*5, 0, a.y*3, 0};\n"
|
||||
" return r;\n"
|
||||
"}\n";
|
||||
|
||||
return run_callback(src, ret_mixed2_test_callback);
|
||||
}
|
||||
|
||||
/*
|
||||
* ret_mixed3_test:
|
||||
*
|
||||
* On x86-64, this struct should be passed in two integer registers.
|
||||
*/
|
||||
typedef struct ret_mixed3_test_type_s {float x; int y; float x2; int y2;} ret_mixed3_test_type;
|
||||
typedef ret_mixed3_test_type (*ret_mixed3_test_function_type) (ret_mixed3_test_type);
|
||||
|
||||
static int ret_mixed3_test_callback(void *ptr) {
|
||||
ret_mixed3_test_function_type f = (ret_mixed3_test_function_type)ptr;
|
||||
ret_mixed3_test_type a = {10, 5, 35, 7 };
|
||||
ret_mixed3_test_type r;
|
||||
r = f(a);
|
||||
return ((r.x == a.x*5) && (r.y2 == a.y*3)) ? 0 : -1;
|
||||
}
|
||||
|
||||
static int ret_mixed3_test(void) {
|
||||
const char *src =
|
||||
"typedef struct ret_mixed3_test_type_s {float x; int y; float x2; int y2;} ret_mixed3_test_type;"
|
||||
"ret_mixed3_test_type f(ret_mixed3_test_type a) {\n"
|
||||
" ret_mixed3_test_type r = {a.x*5, 0, 0, a.y*3};\n"
|
||||
" return r;\n"
|
||||
"}\n";
|
||||
|
||||
return run_callback(src, ret_mixed3_test_callback);
|
||||
}
|
||||
|
||||
/*
|
||||
* reg_pack_test: return a small struct which should be packed into
|
||||
* registers (Win32) during return.
|
||||
*/
|
||||
typedef struct reg_pack_test_type_s {int x, y;} reg_pack_test_type;
|
||||
typedef reg_pack_test_type (*reg_pack_test_function_type) (reg_pack_test_type);
|
||||
|
||||
static int reg_pack_test_callback(void *ptr) {
|
||||
reg_pack_test_function_type f = (reg_pack_test_function_type)ptr;
|
||||
reg_pack_test_type a = {10, 35};
|
||||
reg_pack_test_type r;
|
||||
r = f(a);
|
||||
return ((r.x == a.x*5) && (r.y == a.y*3)) ? 0 : -1;
|
||||
}
|
||||
|
||||
static int reg_pack_test(void) {
|
||||
const char *src =
|
||||
"typedef struct reg_pack_test_type_s {int x, y;} reg_pack_test_type;"
|
||||
"reg_pack_test_type f(reg_pack_test_type a) {\n"
|
||||
" reg_pack_test_type r = {a.x*5, a.y*3};\n"
|
||||
" return r;\n"
|
||||
"}\n";
|
||||
|
||||
return run_callback(src, reg_pack_test_callback);
|
||||
}
|
||||
|
||||
/*
|
||||
* reg_pack_longlong_test: return a small struct which should be packed into
|
||||
* registers (x86-64) during return.
|
||||
*/
|
||||
typedef struct reg_pack_longlong_test_type_s {long long x, y;} reg_pack_longlong_test_type;
|
||||
typedef reg_pack_longlong_test_type (*reg_pack_longlong_test_function_type) (reg_pack_longlong_test_type);
|
||||
|
||||
static int reg_pack_longlong_test_callback(void *ptr) {
|
||||
reg_pack_longlong_test_function_type f = (reg_pack_longlong_test_function_type)ptr;
|
||||
reg_pack_longlong_test_type a = {10, 35};
|
||||
reg_pack_longlong_test_type r;
|
||||
r = f(a);
|
||||
return ((r.x == a.x*5) && (r.y == a.y*3)) ? 0 : -1;
|
||||
}
|
||||
|
||||
static int reg_pack_longlong_test(void) {
|
||||
const char *src =
|
||||
"typedef struct reg_pack_longlong_test_type_s {long long x, y;} reg_pack_longlong_test_type;"
|
||||
"reg_pack_longlong_test_type f(reg_pack_longlong_test_type a) {\n"
|
||||
" reg_pack_longlong_test_type r = {a.x*5, a.y*3};\n"
|
||||
" return r;\n"
|
||||
"}\n";
|
||||
|
||||
return run_callback(src, reg_pack_longlong_test_callback);
|
||||
}
|
||||
|
||||
/*
|
||||
* ret_6plus2longlong_test:
|
||||
*
|
||||
* This catches a corner case in the x86_64 ABI code: the first 5
|
||||
* arguments fit into registers, the 6th doesn't, but the 7th argument
|
||||
* fits into the 6th argument integer register, %r9.
|
||||
*
|
||||
* Note that the purpose of the 10th argument is to avoid a situation
|
||||
* in which gcc would accidentally put the longlong at the right
|
||||
* address, thus causing a success message even though TCC actually
|
||||
* generated incorrect code.
|
||||
*/
|
||||
typedef reg_pack_longlong_test_type (*ret_6plus2longlong_test_function_type) (long long, long long, long long, long long, long long, reg_pack_longlong_test_type, long long, long long);
|
||||
|
||||
static int ret_6plus2longlong_test_callback(void *ptr) {
|
||||
ret_6plus2longlong_test_function_type f = (ret_6plus2longlong_test_function_type)ptr;
|
||||
reg_pack_longlong_test_type a = {10, 35};
|
||||
reg_pack_longlong_test_type r;
|
||||
r = f(0, 0, 0, 0, 0, a, 37, 38);
|
||||
return ((r.x == 37) && (r.y == 37)) ? 0 : -1;
|
||||
}
|
||||
|
||||
static int ret_6plus2longlong_test(void) {
|
||||
const char *src =
|
||||
"typedef struct reg_pack_longlong_test_type_s {long long x, y;} reg_pack_longlong_test_type;"
|
||||
"reg_pack_longlong_test_type f(long long x1, long long x2, long long x3, long long x4, long long x5, reg_pack_longlong_test_type a, long long x8, long long x9) {\n"
|
||||
" reg_pack_longlong_test_type r = { x8, x8 };\n"
|
||||
" return r;\n"
|
||||
"}\n";
|
||||
|
||||
return run_callback(src, ret_6plus2longlong_test_callback);
|
||||
}
|
||||
|
||||
/*
|
||||
* sret_test: Create a struct large enough to be returned via sret
|
||||
* (hidden pointer as first function argument)
|
||||
*/
|
||||
typedef struct sret_test_type_s {long long a, b, c;} sret_test_type;
|
||||
typedef sret_test_type (*sret_test_function_type) (sret_test_type);
|
||||
|
||||
static int sret_test_callback(void *ptr) {
|
||||
sret_test_function_type f = (sret_test_function_type)(ptr);
|
||||
sret_test_type x = {5436LL, 658277698LL, 43878957LL};
|
||||
sret_test_type r = f(x);
|
||||
return ((r.a==x.a*35)&&(r.b==x.b*19)&&(r.c==x.c*21)) ? 0 : -1;
|
||||
}
|
||||
|
||||
static int sret_test(void) {
|
||||
const char *src =
|
||||
"typedef struct sret_test_type_s {long long a, b, c;} sret_test_type;\n"
|
||||
"sret_test_type f(sret_test_type x) {\n"
|
||||
" sret_test_type r = {x.a*35, x.b*19, x.c*21};\n"
|
||||
" return r;\n"
|
||||
"}\n";
|
||||
|
||||
return run_callback(src, sret_test_callback);
|
||||
}
|
||||
|
||||
/*
|
||||
* one_member_union_test:
|
||||
*
|
||||
* In the x86-64 ABI a union should always be passed on the stack. However
|
||||
* it appears that a single member union is treated by GCC as its member.
|
||||
*/
|
||||
typedef union one_member_union_test_type_u {int x;} one_member_union_test_type;
|
||||
typedef one_member_union_test_type (*one_member_union_test_function_type) (one_member_union_test_type);
|
||||
|
||||
static int one_member_union_test_callback(void *ptr) {
|
||||
one_member_union_test_function_type f = (one_member_union_test_function_type)ptr;
|
||||
one_member_union_test_type a, b;
|
||||
a.x = 34;
|
||||
b = f(a);
|
||||
return (b.x == a.x*2) ? 0 : -1;
|
||||
}
|
||||
|
||||
static int one_member_union_test(void) {
|
||||
const char *src =
|
||||
"typedef union one_member_union_test_type_u {int x;} one_member_union_test_type;\n"
|
||||
"one_member_union_test_type f(one_member_union_test_type a) {\n"
|
||||
" one_member_union_test_type b;\n"
|
||||
" b.x = a.x * 2;\n"
|
||||
" return b;\n"
|
||||
"}\n";
|
||||
return run_callback(src, one_member_union_test_callback);
|
||||
}
|
||||
|
||||
/*
|
||||
* two_member_union_test:
|
||||
*
|
||||
* In the x86-64 ABI a union should always be passed on the stack.
|
||||
*/
|
||||
typedef union two_member_union_test_type_u {int x; long y;} two_member_union_test_type;
|
||||
typedef two_member_union_test_type (*two_member_union_test_function_type) (two_member_union_test_type);
|
||||
|
||||
static int two_member_union_test_callback(void *ptr) {
|
||||
two_member_union_test_function_type f = (two_member_union_test_function_type)ptr;
|
||||
two_member_union_test_type a, b;
|
||||
a.x = 34;
|
||||
b = f(a);
|
||||
return (b.x == a.x*2) ? 0 : -1;
|
||||
}
|
||||
|
||||
static int two_member_union_test(void) {
|
||||
const char *src =
|
||||
"typedef union two_member_union_test_type_u {int x; long y;} two_member_union_test_type;\n"
|
||||
"two_member_union_test_type f(two_member_union_test_type a) {\n"
|
||||
" two_member_union_test_type b;\n"
|
||||
" b.x = a.x * 2;\n"
|
||||
" return b;\n"
|
||||
"}\n";
|
||||
return run_callback(src, two_member_union_test_callback);
|
||||
}
|
||||
|
||||
/*
|
||||
* Win64 calling convention test.
|
||||
*/
|
||||
|
||||
typedef struct many_struct_test_type_s {long long a, b, c;} many_struct_test_type;
|
||||
typedef many_struct_test_type (*many_struct_test_function_type) (many_struct_test_type,many_struct_test_type,many_struct_test_type,many_struct_test_type,many_struct_test_type,many_struct_test_type);
|
||||
|
||||
static int many_struct_test_callback(void *ptr) {
|
||||
many_struct_test_function_type f = (many_struct_test_function_type)ptr;
|
||||
many_struct_test_type v = {1, 2, 3};
|
||||
many_struct_test_type r = f(v,v,v,v,v,v);
|
||||
return ((r.a == 6) && (r.b == 12) && (r.c == 18))?0:-1;
|
||||
}
|
||||
|
||||
static int many_struct_test(void) {
|
||||
const char *src =
|
||||
"typedef struct many_struct_test_type_s {long long a, b, c;} many_struct_test_type;\n"
|
||||
"many_struct_test_type f(many_struct_test_type x1, many_struct_test_type x2, many_struct_test_type x3, many_struct_test_type x4, many_struct_test_type x5, many_struct_test_type x6) {\n"
|
||||
" many_struct_test_type y;\n"
|
||||
" y.a = x1.a + x2.a + x3.a + x4.a + x5.a + x6.a;\n"
|
||||
" y.b = x1.b + x2.b + x3.b + x4.b + x5.b + x6.b;\n"
|
||||
" y.c = x1.c + x2.c + x3.c + x4.c + x5.c + x6.c;\n"
|
||||
" return y;\n"
|
||||
"}\n";
|
||||
return run_callback(src, many_struct_test_callback);
|
||||
}
|
||||
|
||||
/*
|
||||
* Win64 calling convention test.
|
||||
*/
|
||||
|
||||
typedef struct many_struct_test_2_type_s {int a, b;} many_struct_test_2_type;
|
||||
typedef many_struct_test_2_type (*many_struct_test_2_function_type) (many_struct_test_2_type,many_struct_test_2_type,many_struct_test_2_type,many_struct_test_2_type,many_struct_test_2_type,many_struct_test_2_type);
|
||||
|
||||
static int many_struct_test_2_callback(void *ptr) {
|
||||
many_struct_test_2_function_type f = (many_struct_test_2_function_type)ptr;
|
||||
many_struct_test_2_type v = {1,2};
|
||||
many_struct_test_2_type r = f(v,v,v,v,v,v);
|
||||
return ((r.a == 6) && (r.b == 12))?0:-1;
|
||||
}
|
||||
|
||||
static int many_struct_test_2(void) {
|
||||
const char *src =
|
||||
"typedef struct many_struct_test_2_type_s {int a, b;} many_struct_test_2_type;\n"
|
||||
"many_struct_test_2_type f(many_struct_test_2_type x1, many_struct_test_2_type x2, many_struct_test_2_type x3, many_struct_test_2_type x4, many_struct_test_2_type x5, many_struct_test_2_type x6) {\n"
|
||||
" many_struct_test_2_type y;\n"
|
||||
" y.a = x1.a + x2.a + x3.a + x4.a + x5.a + x6.a;\n"
|
||||
" y.b = x1.b + x2.b + x3.b + x4.b + x5.b + x6.b;\n"
|
||||
" return y;\n"
|
||||
"}\n";
|
||||
return run_callback(src, many_struct_test_2_callback);
|
||||
}
|
||||
|
||||
/*
|
||||
* Win64 calling convention test.
|
||||
*/
|
||||
|
||||
typedef struct many_struct_test_3_type_s {int a, b;} many_struct_test_3_type;
|
||||
typedef many_struct_test_3_type (*many_struct_test_3_function_type) (many_struct_test_3_type,many_struct_test_3_type,many_struct_test_3_type,many_struct_test_3_type,many_struct_test_3_type,many_struct_test_3_type, ...);
|
||||
typedef struct many_struct_test_3_struct_type { many_struct_test_3_function_type f; many_struct_test_3_function_type *f2; } many_struct_test_3_struct_type;
|
||||
|
||||
static void many_struct_test_3_dummy(double d, ...)
|
||||
{
|
||||
volatile double x = d;
|
||||
}
|
||||
|
||||
static int many_struct_test_3_callback(void *ptr) {
|
||||
many_struct_test_3_struct_type s = { ptr, };
|
||||
many_struct_test_3_struct_type *s2 = &s;
|
||||
s2->f2 = &s2->f;
|
||||
many_struct_test_3_dummy(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, &s2);
|
||||
many_struct_test_3_function_type f = *(s2->f2);
|
||||
many_struct_test_3_type v = {1,2};
|
||||
many_struct_test_3_type r = (*((s2->f2=&f)+0))(v,v,v,v,v,v,1.0);
|
||||
return ((r.a == 6) && (r.b == 12))?0:-1;
|
||||
}
|
||||
|
||||
static int many_struct_test_3(void) {
|
||||
const char *src =
|
||||
"typedef struct many_struct_test_3_type_s {int a, b;} many_struct_test_3_type;\n"
|
||||
"many_struct_test_3_type f(many_struct_test_3_type x1, many_struct_test_3_type x2, many_struct_test_3_type x3, many_struct_test_3_type x4, many_struct_test_3_type x5, many_struct_test_3_type x6, ...) {\n"
|
||||
" many_struct_test_3_type y;\n"
|
||||
" y.a = x1.a + x2.a + x3.a + x4.a + x5.a + x6.a;\n"
|
||||
" y.b = x1.b + x2.b + x3.b + x4.b + x5.b + x6.b;\n"
|
||||
" return y;\n"
|
||||
"}\n";
|
||||
return run_callback(src, many_struct_test_3_callback);
|
||||
}
|
||||
|
||||
/*
|
||||
* stdarg_test: Test variable argument list ABI
|
||||
*/
|
||||
|
||||
typedef struct {long long a, b, c;} stdarg_test_struct_type;
|
||||
typedef void (*stdarg_test_function_type) (int,int,int,...);
|
||||
|
||||
static int stdarg_test_callback(void *ptr) {
|
||||
stdarg_test_function_type f = (stdarg_test_function_type)ptr;
|
||||
int x;
|
||||
double y;
|
||||
stdarg_test_struct_type z = {1, 2, 3}, w;
|
||||
f(10, 10, 5,
|
||||
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, &x,
|
||||
1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, &y,
|
||||
z, z, z, z, z, &w);
|
||||
return ((x == 55) && (y == 55) && (w.a == 5) && (w.b == 10) && (w.c == 15)) ? 0 : -1;
|
||||
}
|
||||
|
||||
static int stdarg_test(void) {
|
||||
const char *src =
|
||||
"#include <stdarg.h>\n"
|
||||
"typedef struct {long long a, b, c;} stdarg_test_struct_type;\n"
|
||||
"void f(int n_int, int n_float, int n_struct, ...) {\n"
|
||||
" int i, ti = 0;\n"
|
||||
" double td = 0.0;\n"
|
||||
" stdarg_test_struct_type ts = {0,0,0}, tmp;\n"
|
||||
" va_list ap;\n"
|
||||
" va_start(ap, n_struct);\n"
|
||||
" for (i = 0, ti = 0; i < n_int; ++i)\n"
|
||||
" ti += va_arg(ap, int);\n"
|
||||
" *va_arg(ap, int*) = ti;\n"
|
||||
" for (i = 0, td = 0; i < n_float; ++i)\n"
|
||||
" td += va_arg(ap, double);\n"
|
||||
" *va_arg(ap, double*) = td;\n"
|
||||
" for (i = 0; i < n_struct; ++i) {\n"
|
||||
" tmp = va_arg(ap, stdarg_test_struct_type);\n"
|
||||
" ts.a += tmp.a; ts.b += tmp.b; ts.c += tmp.c;"
|
||||
" }\n"
|
||||
" *va_arg(ap, stdarg_test_struct_type*) = ts;\n"
|
||||
" va_end(ap);"
|
||||
"}\n";
|
||||
return run_callback(src, stdarg_test_callback);
|
||||
}
|
||||
|
||||
typedef struct {long long a, b;} stdarg_many_test_struct_type;
|
||||
typedef void (*stdarg_many_test_function_type) (int, int, int, int, int,
|
||||
stdarg_many_test_struct_type,
|
||||
int, int, ...);
|
||||
|
||||
static int stdarg_many_test_callback(void *ptr)
|
||||
{
|
||||
stdarg_many_test_function_type f = (stdarg_many_test_function_type)ptr;
|
||||
int x;
|
||||
stdarg_many_test_struct_type l = {10, 11};
|
||||
f(1, 2, 3, 4, 5, l, 6, 7, &x, 44);
|
||||
return x == 44 ? 0 : -1;
|
||||
}
|
||||
|
||||
static int stdarg_many_test(void)
|
||||
{
|
||||
const char *src =
|
||||
"#include <stdarg.h>\n"
|
||||
"typedef struct {long long a, b;} stdarg_many_test_struct_type;\n"
|
||||
"void f (int a, int b, int c, int d, int e, stdarg_many_test_struct_type l, int f, int g, ...){\n"
|
||||
" va_list ap;\n"
|
||||
" int *p;\n"
|
||||
" va_start (ap, g);\n"
|
||||
" p = va_arg(ap, int*);\n"
|
||||
" *p = va_arg(ap, int);\n"
|
||||
" va_end (ap);\n"
|
||||
"}\n";
|
||||
return run_callback(src, stdarg_many_test_callback);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test Win32 stdarg handling, since the calling convention will pass a pointer
|
||||
* to the struct and the stdarg pointer must point to that pointer initially.
|
||||
*/
|
||||
|
||||
typedef struct {long long a, b, c;} stdarg_struct_test_struct_type;
|
||||
typedef int (*stdarg_struct_test_function_type) (stdarg_struct_test_struct_type a, ...);
|
||||
|
||||
static int stdarg_struct_test_callback(void *ptr) {
|
||||
stdarg_struct_test_function_type f = (stdarg_struct_test_function_type)ptr;
|
||||
stdarg_struct_test_struct_type v = {10, 35, 99};
|
||||
int x = f(v, 234);
|
||||
return (x == 378) ? 0 : -1;
|
||||
}
|
||||
|
||||
static int stdarg_struct_test(void) {
|
||||
const char *src =
|
||||
"#include <stdarg.h>\n"
|
||||
"typedef struct {long long a, b, c;} stdarg_struct_test_struct_type;\n"
|
||||
"int f(stdarg_struct_test_struct_type a, ...) {\n"
|
||||
" va_list ap;\n"
|
||||
" va_start(ap, a);\n"
|
||||
" int z = va_arg(ap, int);\n"
|
||||
" va_end(ap);\n"
|
||||
" return z + a.a + a.b + a.c;\n"
|
||||
"}\n";
|
||||
return run_callback(src, stdarg_struct_test_callback);
|
||||
}
|
||||
|
||||
/* Test that x86-64 arranges the stack correctly for arguments with alignment >8 bytes */
|
||||
|
||||
typedef LONG_DOUBLE (*arg_align_test_callback_type) (LONG_DOUBLE,int,LONG_DOUBLE,int,LONG_DOUBLE);
|
||||
|
||||
static int arg_align_test_callback(void *ptr) {
|
||||
arg_align_test_callback_type f = (arg_align_test_callback_type)ptr;
|
||||
long double x = f(12, 0, 25, 0, 37);
|
||||
return (x == 74) ? 0 : -1;
|
||||
}
|
||||
|
||||
static int arg_align_test(void) {
|
||||
const char *src =
|
||||
"long double f(long double a, int b, long double c, int d, long double e) {\n"
|
||||
" return a + c + e;\n"
|
||||
"}\n";
|
||||
return run_callback(src, arg_align_test_callback);
|
||||
}
|
||||
|
||||
#define RUN_TEST(t) \
|
||||
if (!testname || (strcmp(#t, testname) == 0)) { \
|
||||
fputs(#t "... ", stdout); \
|
||||
fflush(stdout); \
|
||||
if (t() == 0) { \
|
||||
fputs("success\n", stdout); \
|
||||
} else { \
|
||||
fputs("failure\n", stdout); \
|
||||
retval = EXIT_FAILURE; \
|
||||
} \
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int i;
|
||||
const char *testname = NULL;
|
||||
int retval = EXIT_SUCCESS;
|
||||
|
||||
/* if tcclib.h and libtcc1.a are not installed, where can we find them */
|
||||
for (i = 1; i < argc; ++i) {
|
||||
if (!memcmp(argv[i], "run_test=", 9))
|
||||
testname = argv[i] + 9;
|
||||
}
|
||||
|
||||
g_argv = argv, g_argc = argc;
|
||||
|
||||
RUN_TEST(ret_int_test);
|
||||
RUN_TEST(ret_longlong_test);
|
||||
RUN_TEST(ret_float_test);
|
||||
RUN_TEST(ret_double_test);
|
||||
RUN_TEST(ret_longdouble_test);
|
||||
RUN_TEST(ret_2float_test);
|
||||
RUN_TEST(ret_2double_test);
|
||||
RUN_TEST(ret_8plus2double_test);
|
||||
RUN_TEST(ret_6plus2longlong_test);
|
||||
#if !defined __x86_64__ || defined _WIN32
|
||||
/* currently broken on x86_64 linux */
|
||||
RUN_TEST(ret_mixed_test);
|
||||
RUN_TEST(ret_mixed2_test);
|
||||
#endif
|
||||
RUN_TEST(ret_mixed3_test);
|
||||
RUN_TEST(reg_pack_test);
|
||||
RUN_TEST(reg_pack_longlong_test);
|
||||
RUN_TEST(sret_test);
|
||||
RUN_TEST(one_member_union_test);
|
||||
RUN_TEST(two_member_union_test);
|
||||
RUN_TEST(many_struct_test);
|
||||
RUN_TEST(many_struct_test_2);
|
||||
RUN_TEST(many_struct_test_3);
|
||||
RUN_TEST(stdarg_test);
|
||||
RUN_TEST(stdarg_many_test);
|
||||
RUN_TEST(stdarg_struct_test);
|
||||
RUN_TEST(arg_align_test);
|
||||
return retval;
|
||||
}
|
57
05/tcc-0.9.27/tests/asm-c-connect-1.c
Normal file
57
05/tcc-0.9.27/tests/asm-c-connect-1.c
Normal file
|
@ -0,0 +1,57 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#if defined _WIN32 && !defined __TINYC__
|
||||
# define _ "_"
|
||||
#else
|
||||
# define _
|
||||
#endif
|
||||
|
||||
static int x1_c(void)
|
||||
{
|
||||
printf(" x1");
|
||||
return 1;
|
||||
}
|
||||
|
||||
asm(".text;"_"x1: call "_"x1_c; ret");
|
||||
|
||||
void callx4(void);
|
||||
void callx5_again(void);
|
||||
|
||||
void x6()
|
||||
{
|
||||
printf(" x6-1");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
printf("*");
|
||||
asm("call "_"x1");
|
||||
asm("call "_"x2");
|
||||
asm("call "_"x3");
|
||||
callx4();
|
||||
asm("call "_"x5");
|
||||
callx5_again();
|
||||
x6();
|
||||
printf(" *\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int x2(void)
|
||||
{
|
||||
printf(" x2");
|
||||
return 2;
|
||||
}
|
||||
|
||||
extern int x3(void);
|
||||
|
||||
void x4(void)
|
||||
{
|
||||
printf(" x4");
|
||||
}
|
||||
|
||||
void x5(void);
|
||||
void x5(void)
|
||||
{
|
||||
printf(" x5");
|
||||
}
|
36
05/tcc-0.9.27/tests/asm-c-connect-2.c
Normal file
36
05/tcc-0.9.27/tests/asm-c-connect-2.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#if defined _WIN32 && !defined __TINYC__
|
||||
# define _ "_"
|
||||
#else
|
||||
# define _
|
||||
#endif
|
||||
|
||||
int x3(void)
|
||||
{
|
||||
printf(" x3");
|
||||
return 3;
|
||||
}
|
||||
|
||||
/* That callx4 is defined globally (as if ".globl callx4")
|
||||
is a TCC extension. GCC doesn't behave like this. */
|
||||
void callx4(void);
|
||||
__asm__(_"callx4: call "_"x4; ret;"
|
||||
#ifndef __TINYC__
|
||||
" .global "_"callx4"
|
||||
#endif
|
||||
);
|
||||
|
||||
extern void x5(void);
|
||||
|
||||
void callx5_again(void);
|
||||
void callx5_again(void)
|
||||
{
|
||||
x5();
|
||||
asm("call "_"x6");
|
||||
}
|
||||
|
||||
static void x6()
|
||||
{
|
||||
printf(" x6-2");
|
||||
}
|
978
05/tcc-0.9.27/tests/asmtest.S
Normal file
978
05/tcc-0.9.27/tests/asmtest.S
Normal file
|
@ -0,0 +1,978 @@
|
|||
# gas comment with ``gnu'' style quotes
|
||||
|
||||
/* some directive tests */
|
||||
|
||||
.byte 0xff
|
||||
.byte 1, 2, 3
|
||||
.short 1, 2, 3
|
||||
.word 1, 2, 3
|
||||
.long 1, 2, 3
|
||||
.int 1, 2, 3
|
||||
.align 8
|
||||
.byte 1
|
||||
/* .align 16, 0x90 gas is too clever for us with 0x90 fill */
|
||||
.balign 4, 0x92
|
||||
.align 16, 0x91 /* 0x91 tests the non-clever behaviour */
|
||||
.skip 3
|
||||
.skip 15, 0x90
|
||||
.string "hello\0world"
|
||||
/* Macro expansion should work like with C, the #n shouldn't be parsed
|
||||
as asm line comment */
|
||||
#define __stringify(n) #n
|
||||
#define stringify(n) __stringify(n)
|
||||
.skip 8,0x90
|
||||
.asciz stringify(BLA)
|
||||
.skip 8,0x90
|
||||
|
||||
# 28 "asmtest.S" # a line directive (and a line comment)
|
||||
movl %eax, %ebx # some more asm comment
|
||||
/* some label tests */
|
||||
L1:
|
||||
movl %eax, %ebx
|
||||
mov 0x10000, %eax
|
||||
L2:
|
||||
movl $L2 - L1, %ecx
|
||||
var1:
|
||||
nop ; nop ; nop ; nop
|
||||
|
||||
mov var1, %eax
|
||||
|
||||
/* instruction tests */
|
||||
movl %eax, %ebx
|
||||
mov 0x10000, %eax
|
||||
mov 0x10000, %ax
|
||||
mov 0x10000, %al
|
||||
mov %al, 0x10000
|
||||
|
||||
mov $1, %edx
|
||||
mov $1, %dx
|
||||
mov $1, %cl
|
||||
movb $2, 0x100(%ebx,%edx,2)
|
||||
movw $2, 0x100(%ebx,%edx,2)
|
||||
movl $2, 0x100(%ebx,%edx,2)
|
||||
movl %eax, 0x100(%ebx,%edx,2)
|
||||
movl 0x100(%ebx,%edx,2), %edx
|
||||
movw %ax, 0x100(%ebx,%edx,2)
|
||||
|
||||
movw $0x1122,%si
|
||||
movl $0x112233,%edx
|
||||
movl $0x80000000, %esi
|
||||
movl $-0x7fffffff, %edi
|
||||
#ifdef __x86_64__
|
||||
mov $0x11223344,%rbx
|
||||
movq $0x11223344,%rbx
|
||||
mov $0x1122334455,%rbx
|
||||
movq $0x1122334455,%rbx
|
||||
movl $0x11334455,(%rbx)
|
||||
#endif
|
||||
|
||||
mov %eax, 0x12(,%edx,2)
|
||||
|
||||
#ifdef __i386__
|
||||
mov %cr3, %edx
|
||||
mov %ecx, %cr3
|
||||
movl %cr3, %eax
|
||||
movl %tr3, %eax
|
||||
movl %db3, %ebx
|
||||
movl %dr6, %eax
|
||||
#else
|
||||
mov %cr3, %rdx
|
||||
mov %rcx, %cr3
|
||||
movq %cr3, %rax
|
||||
movq %db3, %rbx
|
||||
movq %dr6, %rax
|
||||
mov %cr8, %rsi
|
||||
mov %rdi, %cr8
|
||||
#endif
|
||||
movl %fs, %ecx
|
||||
movl %ebx, %fs
|
||||
|
||||
#ifdef __x86_64__
|
||||
movq %r8, %r9
|
||||
movq %r10, %r11
|
||||
movq %r12, %r13
|
||||
movq %r14, %r15
|
||||
movq %rax, %r9
|
||||
movq %r15, %rsi
|
||||
inc %r9b
|
||||
dec %r10w
|
||||
not %r11d
|
||||
negq %r12
|
||||
decb %r13b
|
||||
incw %r14w
|
||||
notl %r15d
|
||||
#endif
|
||||
|
||||
movsbl 0x1000, %eax
|
||||
movsbw 0x1000, %ax
|
||||
movswl 0x1000, %eax
|
||||
|
||||
movzbl 0x1000, %eax
|
||||
movzbw 0x1000, %ax
|
||||
movzwl 0x1000, %eax
|
||||
|
||||
movzb 0x1000, %eax
|
||||
movzb 0x1000, %ax
|
||||
|
||||
mov $0x12345678,%eax
|
||||
|
||||
#ifdef __x86_64__
|
||||
movzb 0x1000, %rax
|
||||
movzbq 0x1000, %rbx
|
||||
movsbq 0x1000, %rdx
|
||||
movzwq 0x1000, %rdi
|
||||
movswq 0x1000, %rdx
|
||||
movslq %eax, %rcx
|
||||
mov $0x12345678,%rax
|
||||
mov $0x12345678,%rdx
|
||||
mov $0x12345678,%r10
|
||||
mov $0x123456789abcdef0,%rax
|
||||
mov $0x123456789abcdef0,%rcx
|
||||
mov $0x123456789abcdef0,%r11
|
||||
#endif
|
||||
|
||||
#ifdef __i386__
|
||||
pushl %eax
|
||||
push %eax
|
||||
push %cs
|
||||
#else
|
||||
pushq %rax
|
||||
push %rax
|
||||
#endif
|
||||
pushw %ax
|
||||
push %gs
|
||||
push $1
|
||||
push $100
|
||||
push 0x42(%eax)
|
||||
pop 0x43(%esi)
|
||||
|
||||
#ifdef __i386__
|
||||
popl %eax
|
||||
pop %eax
|
||||
pop %ds
|
||||
#else
|
||||
popq %rax
|
||||
pop %rax
|
||||
#endif
|
||||
popw %ax
|
||||
pop %fs
|
||||
|
||||
xchg %eax, %ecx
|
||||
xchg %edx, %eax
|
||||
xchg %bx, 0x10000
|
||||
xchg 0x10000, %ebx
|
||||
xchg 0x10000, %dl
|
||||
|
||||
in $100, %al
|
||||
in $100, %ax
|
||||
in $100, %eax
|
||||
in %dx, %al
|
||||
in %dx, %ax
|
||||
in %dx, %eax
|
||||
inb %dx
|
||||
inw %dx
|
||||
inl %dx
|
||||
|
||||
out %al, $100
|
||||
out %ax, $100
|
||||
out %eax, $100
|
||||
|
||||
/* NOTE: gas is bugged here, so size must be added */
|
||||
outb %al, %dx
|
||||
outw %ax, %dx
|
||||
outl %eax, %dx
|
||||
|
||||
leal 0x1000(%ebx), %ecx
|
||||
lea 0x1000(%ebx), %ecx
|
||||
|
||||
#ifdef __i386__
|
||||
les 0x2000, %eax
|
||||
lds 0x2000, %ebx
|
||||
lss 0x2000, %edx
|
||||
#endif
|
||||
lfs 0x2000, %ecx
|
||||
lgs 0x2000, %edx
|
||||
|
||||
addl $0x123, %eax
|
||||
add $0x123, %ebx
|
||||
add $-16, %ecx
|
||||
add $-0x123, %esi
|
||||
add $1, %bx
|
||||
add $1, %ebx
|
||||
add $-1, %bx
|
||||
add $-1, %ebx
|
||||
add $127, %bx
|
||||
addl $127, %ebx
|
||||
addl $-128, %ebx
|
||||
addl $-128, %ebx
|
||||
addl $-129, %ebx
|
||||
addl $128, %ebx
|
||||
addl $255, %ebx
|
||||
addl $256, %ebx
|
||||
andb $0xf, %ah
|
||||
andb $-15, %cl
|
||||
xorb $127, %dh
|
||||
cmpb $42, (%eax)
|
||||
addl $0x123, 0x100
|
||||
addl $0x123, 0x100(%ebx)
|
||||
addl $0x123, 0x100(%ebx,%edx,2)
|
||||
addl $0x123, 0x100(%esp)
|
||||
addl $0x123, (3*8)(%esp)
|
||||
addl $0x123, (%ebp)
|
||||
addl $0x123, (%esp)
|
||||
cmpl $0x123, (%esp)
|
||||
|
||||
#ifdef __x86_64__
|
||||
xor %bl,%ah
|
||||
xor %bl,%r8b
|
||||
xor %r9b,%bl
|
||||
xor %sil,%cl
|
||||
add %eax,(%r8d)
|
||||
add %ebx,(%r9)
|
||||
add %edx,(%r10d,%r11d)
|
||||
add %ecx,(%r12,%r13)
|
||||
add %esi,(%r14,%r15,4)
|
||||
add %edi,0x1000(%rbx,%r12,8)
|
||||
add %r11,0x1000(%ebp,%r9d,8)
|
||||
movb $12, %ah
|
||||
movb $13, %bpl
|
||||
movb $14, %dil
|
||||
movb $15, %r12b
|
||||
#endif
|
||||
|
||||
add %eax, (%ebx)
|
||||
add (%ebx), %eax
|
||||
|
||||
or %dx, (%ebx)
|
||||
or (%ebx), %si
|
||||
|
||||
add %cl, (%ebx)
|
||||
add (%ebx), %dl
|
||||
|
||||
inc %edx
|
||||
incl 0x10000
|
||||
incb 0x10000
|
||||
dec %dx
|
||||
|
||||
test $1, %al
|
||||
test $1, %cl
|
||||
|
||||
testl $1, 0x1000
|
||||
testb $1, 0x1000
|
||||
testw $1, 0x1000
|
||||
test %eax, %ebx
|
||||
test %eax, 0x1000
|
||||
test 0x1000, %edx
|
||||
|
||||
not %edx
|
||||
notw 0x10000
|
||||
notl 0x10000
|
||||
notb 0x10000
|
||||
|
||||
neg %edx
|
||||
negw 0x10000
|
||||
negl 0x10000
|
||||
negb 0x10000
|
||||
|
||||
imul %ecx
|
||||
mul %edx
|
||||
mulb %cl
|
||||
|
||||
imul %eax, %ecx
|
||||
imul 0x1000, %cx
|
||||
imul $10, %eax, %ecx
|
||||
imul $10, %ax, %cx
|
||||
imul $10, %eax
|
||||
imul $0x1100000, %eax
|
||||
imul $1, %eax
|
||||
|
||||
idivw 0x1000
|
||||
div %ecx
|
||||
div %bl
|
||||
div %ecx, %eax
|
||||
|
||||
and $15,%bx
|
||||
and $-20,%edx
|
||||
|
||||
shl %edx
|
||||
shl $10, %edx
|
||||
shl %cl, %edx
|
||||
|
||||
shld $1, %eax, %edx
|
||||
shld %cl, %eax, %edx
|
||||
shld %eax, %edx
|
||||
|
||||
shrd $1, %eax, %edx
|
||||
shrd %cl, %eax, %edx
|
||||
shrd %eax, %edx
|
||||
|
||||
L4:
|
||||
call 0x1000
|
||||
call L4
|
||||
#ifdef __i386__
|
||||
call *%eax
|
||||
#else
|
||||
call *%rax
|
||||
#endif
|
||||
call *0x1000
|
||||
call func1
|
||||
|
||||
.global L5,L6
|
||||
|
||||
L5:
|
||||
L6:
|
||||
|
||||
#ifdef __i386__
|
||||
lcall $0x100, $0x1000
|
||||
#else
|
||||
lcall *0x100
|
||||
lcall *(%rax)
|
||||
#endif
|
||||
|
||||
jmp 0x1000
|
||||
jmp *(%edi)
|
||||
#ifdef __i386__
|
||||
jmp *%eax
|
||||
#else
|
||||
jmp *%rax
|
||||
#endif
|
||||
jmp *0x1000
|
||||
|
||||
#ifdef __i386__
|
||||
ljmp $0x100, $0x1000
|
||||
#else
|
||||
ljmp *0x100
|
||||
ljmp *(%rdi)
|
||||
ljmpl *(%esi)
|
||||
ljmpw *(%esi)
|
||||
#endif
|
||||
|
||||
ret
|
||||
ret $10
|
||||
#ifdef __i386__
|
||||
retl
|
||||
retl $10
|
||||
#else
|
||||
retq
|
||||
retq $10
|
||||
#endif
|
||||
|
||||
lret
|
||||
|
||||
lret $10
|
||||
|
||||
enter $1234, $10
|
||||
|
||||
L3:
|
||||
jo 0x1000
|
||||
jnp 0x1001
|
||||
jne 0x1002
|
||||
jg 0x1003
|
||||
|
||||
jo L3
|
||||
jnp L3
|
||||
jne L3
|
||||
jg L3
|
||||
|
||||
loopne L3
|
||||
loopnz L3
|
||||
loope L3
|
||||
loopz L3
|
||||
loop L3
|
||||
jecxz L3
|
||||
|
||||
|
||||
seto %al
|
||||
setc %al
|
||||
setcb %al
|
||||
setnp 0x1000
|
||||
setl 0xaaaa
|
||||
setg %dl
|
||||
|
||||
fadd
|
||||
fadd %st(1), %st
|
||||
fadd %st(0), %st(1)
|
||||
fadd %st(3)
|
||||
|
||||
fmul %st(0),%st(0)
|
||||
fmul %st(0),%st(1)
|
||||
|
||||
faddp %st(5)
|
||||
faddp
|
||||
faddp %st(1), %st
|
||||
|
||||
fadds 0x1000
|
||||
fiadds 0x1002
|
||||
faddl 0x1004
|
||||
fiaddl 0x1006
|
||||
|
||||
fmul
|
||||
fmul %st(1), %st
|
||||
fmul %st(3)
|
||||
|
||||
fmulp %st(5)
|
||||
fmulp
|
||||
fmulp %st(1), %st
|
||||
|
||||
fmuls 0x1000
|
||||
fimuls 0x1002
|
||||
fmull 0x1004
|
||||
fimull 0x1006
|
||||
|
||||
fsub
|
||||
fsub %st(1), %st
|
||||
fsub %st(3)
|
||||
|
||||
fsubp %st(5)
|
||||
fsubp
|
||||
fsubp %st(1), %st
|
||||
|
||||
fsubs 0x1000
|
||||
fisubs 0x1002
|
||||
fsubl 0x1004
|
||||
fisubl 0x1006
|
||||
|
||||
fsubr
|
||||
fsubr %st(1), %st
|
||||
fsubr %st(3)
|
||||
|
||||
fsubrp %st(5)
|
||||
fsubrp
|
||||
fsubrp %st(1), %st
|
||||
|
||||
fsubrs 0x1000
|
||||
fisubrs 0x1002
|
||||
fsubrl 0x1004
|
||||
fisubrl 0x1006
|
||||
|
||||
fdiv
|
||||
fdiv %st(1), %st
|
||||
fdiv %st(3)
|
||||
|
||||
fdivp %st(5)
|
||||
fdivp
|
||||
fdivp %st(1), %st
|
||||
|
||||
fdivs 0x1000
|
||||
fidivs 0x1002
|
||||
fdivl 0x1004
|
||||
fidivl 0x1006
|
||||
|
||||
fcom %st(3)
|
||||
|
||||
fcoms 0x1000
|
||||
ficoms 0x1002
|
||||
fcoml 0x1004
|
||||
ficoml 0x1006
|
||||
|
||||
fcomp %st(5)
|
||||
fcomp
|
||||
fcompp
|
||||
|
||||
fcomps 0x1000
|
||||
ficomps 0x1002
|
||||
fcompl 0x1004
|
||||
ficompl 0x1006
|
||||
|
||||
fld %st(5)
|
||||
fldl 0x1000
|
||||
flds 0x1002
|
||||
fildl 0x1004
|
||||
fst %st(4)
|
||||
fstp %st(6)
|
||||
fstpt 0x1006
|
||||
fbstp 0x1008
|
||||
|
||||
fxch
|
||||
fxch %st(4)
|
||||
|
||||
fucom %st(6)
|
||||
fucomp %st(3)
|
||||
fucompp
|
||||
|
||||
finit
|
||||
fninit
|
||||
fldcw 0x1000
|
||||
fnstcw 0x1002
|
||||
fstcw 0x1002
|
||||
fnstsw 0x1004
|
||||
fnstsw (%eax)
|
||||
fstsw 0x1004
|
||||
fstsw (%eax)
|
||||
fnclex
|
||||
fclex
|
||||
fnstenv 0x1000
|
||||
fstenv 0x1000
|
||||
fldenv 0x1000
|
||||
fnsave 0x1002
|
||||
fsave 0x1000
|
||||
frstor 0x1000
|
||||
ffree %st(7)
|
||||
ffreep %st(6)
|
||||
|
||||
ftst
|
||||
fxam
|
||||
fld1
|
||||
fldl2t
|
||||
fldl2e
|
||||
fldpi
|
||||
fldlg2
|
||||
fldln2
|
||||
fldz
|
||||
|
||||
f2xm1
|
||||
fyl2x
|
||||
fptan
|
||||
fpatan
|
||||
fxtract
|
||||
fprem1
|
||||
fdecstp
|
||||
fincstp
|
||||
fprem
|
||||
fyl2xp1
|
||||
fsqrt
|
||||
fsincos
|
||||
frndint
|
||||
fscale
|
||||
fsin
|
||||
fcos
|
||||
fchs
|
||||
fabs
|
||||
fnop
|
||||
fwait
|
||||
|
||||
bswap %edx
|
||||
bswapl %ecx
|
||||
xadd %ecx, %edx
|
||||
xaddb %dl, 0x1000
|
||||
xaddw %ax, 0x1000
|
||||
xaddl %eax, 0x1000
|
||||
cmpxchg %ecx, %edx
|
||||
cmpxchgb %dl, 0x1000
|
||||
cmpxchgw %ax, 0x1000
|
||||
cmpxchgl %eax, 0x1000
|
||||
invlpg 0x1000
|
||||
cmpxchg8b 0x1002
|
||||
#ifdef __x86_64__
|
||||
cmpxchg16b (%rax)
|
||||
cmpxchg16b (%r10,%r11)
|
||||
#endif
|
||||
|
||||
fcmovb %st(5), %st
|
||||
fcmove %st(5), %st
|
||||
fcmovbe %st(5), %st
|
||||
fcmovu %st(5), %st
|
||||
fcmovnb %st(5), %st
|
||||
fcmovne %st(5), %st
|
||||
fcmovnbe %st(5), %st
|
||||
fcmovnu %st(5), %st
|
||||
fcomi %st(5), %st
|
||||
fucomi %st(5), %st
|
||||
fcomip %st(5), %st
|
||||
fucomip %st(5), %st
|
||||
|
||||
|
||||
|
||||
cmovo 0x1000, %eax
|
||||
cmovs 0x1000, %eax
|
||||
cmovns %edx, %edi
|
||||
cmovne %ax, %si
|
||||
cmovbw %ax, %di
|
||||
cmovnbel %edx, %ecx
|
||||
#ifdef __x86_64__
|
||||
bswapq %rsi
|
||||
bswapq %r10
|
||||
cmovz %rdi,%rbx
|
||||
cmovpeq %rsi, %rdx
|
||||
#endif
|
||||
|
||||
int $3
|
||||
int $0x10
|
||||
|
||||
#ifdef __i386__
|
||||
pusha
|
||||
popa
|
||||
#endif
|
||||
clc # another comment
|
||||
cld # a comment with embedded ' tick
|
||||
cli
|
||||
clts
|
||||
cmc
|
||||
lahf
|
||||
sahf
|
||||
#ifdef __i386__
|
||||
pushfl
|
||||
popfl
|
||||
#else
|
||||
pushfq
|
||||
popfq
|
||||
#endif
|
||||
pushf
|
||||
popf
|
||||
stc
|
||||
std
|
||||
sti
|
||||
#ifdef __i386__
|
||||
aaa
|
||||
aas
|
||||
daa
|
||||
das
|
||||
aad
|
||||
aam
|
||||
into
|
||||
#endif
|
||||
cbw
|
||||
cwd
|
||||
cwde
|
||||
cdq
|
||||
cbtw
|
||||
cwtd
|
||||
cwtl
|
||||
cltd
|
||||
leave
|
||||
int3
|
||||
iret
|
||||
rsm
|
||||
hlt
|
||||
wait
|
||||
nop
|
||||
|
||||
/* XXX: handle prefixes */
|
||||
#if 0
|
||||
aword
|
||||
addr16
|
||||
#endif
|
||||
lock
|
||||
rep
|
||||
repe
|
||||
repz
|
||||
repne
|
||||
repnz
|
||||
nop
|
||||
|
||||
lock ;negl (%eax)
|
||||
wait ;pushf
|
||||
rep ;stosb
|
||||
repe ;lodsb
|
||||
repz ;cmpsb
|
||||
repne;movsb
|
||||
repnz;outsb
|
||||
|
||||
/* handle one-line prefix + ops */
|
||||
lock negl (%eax)
|
||||
wait pushf
|
||||
rep stosb
|
||||
repe lodsb
|
||||
repz cmpsb
|
||||
repne movsb
|
||||
repnz outsb
|
||||
|
||||
invd
|
||||
wbinvd
|
||||
cpuid
|
||||
wrmsr
|
||||
rdtsc
|
||||
rdmsr
|
||||
rdpmc
|
||||
ud2
|
||||
#ifdef __x86_64__
|
||||
syscall
|
||||
sysret
|
||||
sysretq
|
||||
lfence
|
||||
mfence
|
||||
sfence
|
||||
prefetchnta 0x18(%rdx)
|
||||
prefetcht0 (%rcx)
|
||||
prefetcht1 (%rsi)
|
||||
prefetcht2 (%rdi)
|
||||
prefetchw (%rdi)
|
||||
clflush 0x1000(%rax,%rcx)
|
||||
fxsaveq (%rdx)
|
||||
fxsaveq (%r11)
|
||||
fxrstorq (%rcx)
|
||||
fxrstorq (%r10)
|
||||
|
||||
#endif
|
||||
|
||||
lar %ax,%dx
|
||||
lar %eax,%dx
|
||||
lar %ax,%edx
|
||||
lar %eax,%edx
|
||||
#ifdef __x86_64__
|
||||
lar %ax,%rdx
|
||||
lar %eax,%rdx
|
||||
#endif
|
||||
emms
|
||||
movd %edx, %mm3
|
||||
movd 0x1000, %mm2
|
||||
movd %mm4, %ecx
|
||||
movd %mm5, 0x1000
|
||||
|
||||
movq 0x1000, %mm2
|
||||
movq %mm4, 0x1000
|
||||
|
||||
pand 0x1000, %mm3
|
||||
pand %mm4, %mm5
|
||||
|
||||
psllw $1, %mm6
|
||||
psllw 0x1000, %mm7
|
||||
psllw %mm2, %mm7
|
||||
|
||||
xlat
|
||||
cmpsb
|
||||
scmpw
|
||||
insl
|
||||
outsw
|
||||
lodsb
|
||||
slodl
|
||||
movsb
|
||||
movsl
|
||||
smovb
|
||||
scasb
|
||||
sscaw
|
||||
stosw
|
||||
sstol
|
||||
|
||||
bsf 0x1000, %ebx
|
||||
bsr 0x1000, %ebx
|
||||
bt %edx, 0x1000
|
||||
btl $2, 0x1000
|
||||
btc %edx, 0x1000
|
||||
btcl $2, 0x1000
|
||||
btr %edx, 0x1000
|
||||
btrl $2, 0x1000
|
||||
bts %edx, 0x1000
|
||||
btsl $2, 0x1000
|
||||
|
||||
|
||||
|
||||
#ifdef __i386__
|
||||
boundl %edx, 0x10000
|
||||
boundw %bx, 0x1000
|
||||
|
||||
arpl %bx, 0x1000
|
||||
#endif
|
||||
lar 0x1000, %eax
|
||||
lgdt 0x1000
|
||||
lidt 0x1000
|
||||
lldt 0x1000
|
||||
sgdt 0x1000
|
||||
sidt 0x1000
|
||||
sldt 0x1000
|
||||
#ifdef __x86_64__
|
||||
lgdtq 0x1000
|
||||
lidtq 0x1000
|
||||
sgdtq 0x1000
|
||||
sidtq 0x1000
|
||||
|
||||
swapgs
|
||||
|
||||
str %rdx
|
||||
str %r9
|
||||
#endif
|
||||
|
||||
lmsw 0x1000
|
||||
lsl 0x1000, %ecx
|
||||
ltr 0x1000
|
||||
ltr %si
|
||||
smsw 0x1000
|
||||
str 0x1000
|
||||
str %ecx
|
||||
str %dx
|
||||
|
||||
verr 0x1000
|
||||
verw 0x1000
|
||||
|
||||
#ifdef __i386__
|
||||
push %ds
|
||||
pushw %ds
|
||||
pushl %ds
|
||||
pop %ds
|
||||
popw %ds
|
||||
popl %ds
|
||||
#endif
|
||||
fxsave 1(%ebx)
|
||||
fxrstor 1(%ecx)
|
||||
#ifdef __i386__
|
||||
pushl $1
|
||||
#else
|
||||
pushq $1
|
||||
#endif
|
||||
pushw $1
|
||||
push $1
|
||||
|
||||
#ifdef __ASSEMBLER__ // should be defined, for S files
|
||||
inc %eax
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
ft1: ft2: ft3: ft4: ft5: ft6: ft7: ft8: ft9:
|
||||
xor %eax, %eax
|
||||
ret
|
||||
|
||||
.type ft1,STT_FUNC
|
||||
.type ft2,@STT_FUNC
|
||||
.type ft3,%STT_FUNC
|
||||
.type ft4,"STT_FUNC"
|
||||
.type ft5,function
|
||||
.type ft6,@function
|
||||
.type ft7,%function
|
||||
.type ft8,"function"
|
||||
#endif
|
||||
|
||||
pause
|
||||
.rept 6
|
||||
nop
|
||||
.endr
|
||||
.fill 4,1,0x90
|
||||
|
||||
.section .text.one,"ax"
|
||||
nop
|
||||
.previous
|
||||
.pushsection .text.one,"ax"
|
||||
nop
|
||||
.pushsection .text.two,"ax"
|
||||
nop
|
||||
.popsection
|
||||
.popsection
|
||||
|
||||
1: ud2
|
||||
.pushsection __bug_table,"a"
|
||||
.align 8
|
||||
2: .long 1b - 2b
|
||||
.long 0x600000 - 2b
|
||||
.long 1b + 42
|
||||
.long 43 + 1b
|
||||
.long 2b + 144
|
||||
.long 145 + 2b
|
||||
.word 164, 0
|
||||
.org 2b+32
|
||||
#ifdef __x86_64__
|
||||
.quad 1b
|
||||
#else
|
||||
.long 1b
|
||||
#endif
|
||||
.popsection
|
||||
3: mov %eax,%ecx
|
||||
4:
|
||||
.pushsection .text.three, "ax"
|
||||
nop
|
||||
.skip (-((4b-3b) > 0) * 2) , 0x90
|
||||
.popsection
|
||||
|
||||
.globl overrideme
|
||||
.weak overrideme
|
||||
nop
|
||||
.globl notimplemented
|
||||
notimplemented:
|
||||
ret
|
||||
.set overrideme, notimplemented
|
||||
overrideme = notimplemented
|
||||
overrideme:
|
||||
ret
|
||||
|
||||
movd %esi, %mm1
|
||||
movd %edi, %xmm2
|
||||
movd (%ebx), %mm3
|
||||
movd (%ebx), %xmm3
|
||||
movd %mm1, %esi
|
||||
movd %xmm2, %edi
|
||||
movd %mm3, (%edx)
|
||||
movd %xmm3, (%edx)
|
||||
#ifdef __x86_64__
|
||||
movd %rsi, %mm1
|
||||
movd %rdi, %xmm2
|
||||
movd (%rbx), %mm3
|
||||
movd (%rbx), %xmm3
|
||||
movd %mm1, %r12
|
||||
movd %xmm2, %rdi
|
||||
movd %mm3, (%r8)
|
||||
movd %xmm3, (%r13)
|
||||
#endif
|
||||
|
||||
movq (%ebp), %mm1
|
||||
movq %mm2, (%edi)
|
||||
movq (%edi), %xmm3
|
||||
movq %mm4, %mm5
|
||||
#ifdef __x86_64__
|
||||
movq %rcx, %mm1
|
||||
movq %rdx, %xmm2
|
||||
movq %r13, %xmm3
|
||||
/* movq mem64->xmm is encoded as f30f7e by GAS, but as
|
||||
660f6e by tcc (which really is a movd and would need
|
||||
a REX.W prefix to be movq). */
|
||||
movq (%rsi), %xmm3
|
||||
movq %mm1, %rdx
|
||||
movq %xmm3, %rcx
|
||||
movq %xmm4, (%rsi)
|
||||
#endif
|
||||
|
||||
#define TEST_MMX_SSE(insn) \
|
||||
insn %mm1, %mm2; \
|
||||
insn %xmm2, %xmm3; \
|
||||
insn (%ebx), %xmm3;
|
||||
#define TEST_MMX_SSE_I8(insn) \
|
||||
TEST_MMX_SSE(insn) \
|
||||
insn $0x42, %mm4; \
|
||||
insn $0x42, %xmm4;
|
||||
|
||||
TEST_MMX_SSE(packssdw)
|
||||
TEST_MMX_SSE(packsswb)
|
||||
TEST_MMX_SSE(packuswb)
|
||||
TEST_MMX_SSE(paddb)
|
||||
TEST_MMX_SSE(paddw)
|
||||
TEST_MMX_SSE(paddd)
|
||||
TEST_MMX_SSE(paddsb)
|
||||
TEST_MMX_SSE(paddsw)
|
||||
TEST_MMX_SSE(paddusb)
|
||||
TEST_MMX_SSE(paddusw)
|
||||
TEST_MMX_SSE(pand)
|
||||
TEST_MMX_SSE(pandn)
|
||||
TEST_MMX_SSE(pcmpeqb)
|
||||
TEST_MMX_SSE(pcmpeqw)
|
||||
TEST_MMX_SSE(pcmpeqd)
|
||||
TEST_MMX_SSE(pcmpgtb)
|
||||
TEST_MMX_SSE(pcmpgtw)
|
||||
TEST_MMX_SSE(pcmpgtd)
|
||||
TEST_MMX_SSE(pmaddwd)
|
||||
TEST_MMX_SSE(pmulhw)
|
||||
TEST_MMX_SSE(pmullw)
|
||||
TEST_MMX_SSE(por)
|
||||
TEST_MMX_SSE(psllw)
|
||||
TEST_MMX_SSE_I8(psllw)
|
||||
TEST_MMX_SSE(pslld)
|
||||
TEST_MMX_SSE_I8(pslld)
|
||||
TEST_MMX_SSE(psllq)
|
||||
TEST_MMX_SSE_I8(psllq)
|
||||
TEST_MMX_SSE(psraw)
|
||||
TEST_MMX_SSE_I8(psraw)
|
||||
TEST_MMX_SSE(psrad)
|
||||
TEST_MMX_SSE_I8(psrad)
|
||||
TEST_MMX_SSE(psrlw)
|
||||
TEST_MMX_SSE_I8(psrlw)
|
||||
TEST_MMX_SSE(psrld)
|
||||
TEST_MMX_SSE_I8(psrld)
|
||||
TEST_MMX_SSE(psrlq)
|
||||
TEST_MMX_SSE_I8(psrlq)
|
||||
TEST_MMX_SSE(psubb)
|
||||
TEST_MMX_SSE(psubw)
|
||||
TEST_MMX_SSE(psubd)
|
||||
TEST_MMX_SSE(psubsb)
|
||||
TEST_MMX_SSE(psubsw)
|
||||
TEST_MMX_SSE(psubusb)
|
||||
TEST_MMX_SSE(psubusw)
|
||||
TEST_MMX_SSE(punpckhbw)
|
||||
TEST_MMX_SSE(punpckhwd)
|
||||
TEST_MMX_SSE(punpckhdq)
|
||||
TEST_MMX_SSE(punpcklbw)
|
||||
TEST_MMX_SSE(punpcklwd)
|
||||
TEST_MMX_SSE(punpckldq)
|
||||
TEST_MMX_SSE(pxor)
|
||||
|
||||
cvtpi2ps %mm1, %xmm2
|
||||
cvtpi2ps (%ebx), %xmm2
|
||||
TEST_MMX_SSE(pmaxsw)
|
||||
TEST_MMX_SSE(pmaxub)
|
||||
TEST_MMX_SSE(pminsw)
|
||||
TEST_MMX_SSE(pminub)
|
285
05/tcc-0.9.27/tests/boundtest.c
Normal file
285
05/tcc-0.9.27/tests/boundtest.c
Normal file
|
@ -0,0 +1,285 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define NB_ITS 1000000
|
||||
//#define NB_ITS 1
|
||||
#define TAB_SIZE 100
|
||||
|
||||
int tab[TAB_SIZE];
|
||||
int ret_sum;
|
||||
char tab3[256];
|
||||
|
||||
int test1(void)
|
||||
{
|
||||
int i, sum = 0;
|
||||
for(i=0;i<TAB_SIZE;i++) {
|
||||
sum += tab[i];
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/* error */
|
||||
int test2(void)
|
||||
{
|
||||
int i, sum = 0;
|
||||
for(i=0;i<TAB_SIZE + 1;i++) {
|
||||
sum += tab[i];
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/* actually, profiling test */
|
||||
int test3(void)
|
||||
{
|
||||
int sum;
|
||||
int i, it;
|
||||
|
||||
sum = 0;
|
||||
for(it=0;it<NB_ITS;it++) {
|
||||
for(i=0;i<TAB_SIZE;i++) {
|
||||
sum += tab[i];
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/* ok */
|
||||
int test4(void)
|
||||
{
|
||||
int i, sum = 0;
|
||||
int *tab4;
|
||||
|
||||
fprintf(stderr, "%s start\n", __FUNCTION__);
|
||||
|
||||
tab4 = malloc(20 * sizeof(int));
|
||||
for(i=0;i<20;i++) {
|
||||
sum += tab4[i];
|
||||
}
|
||||
free(tab4);
|
||||
|
||||
fprintf(stderr, "%s end\n", __FUNCTION__);
|
||||
return sum;
|
||||
}
|
||||
|
||||
/* error */
|
||||
int test5(void)
|
||||
{
|
||||
int i, sum = 0;
|
||||
int *tab4;
|
||||
|
||||
fprintf(stderr, "%s start\n", __FUNCTION__);
|
||||
|
||||
tab4 = malloc(20 * sizeof(int));
|
||||
for(i=0;i<21;i++) {
|
||||
sum += tab4[i];
|
||||
}
|
||||
free(tab4);
|
||||
|
||||
fprintf(stderr, "%s end\n", __FUNCTION__);
|
||||
return sum;
|
||||
}
|
||||
|
||||
/* error */
|
||||
/* XXX: currently: bug */
|
||||
int test6(void)
|
||||
{
|
||||
int i, sum = 0;
|
||||
int *tab4;
|
||||
|
||||
tab4 = malloc(20 * sizeof(int));
|
||||
free(tab4);
|
||||
for(i=0;i<21;i++) {
|
||||
sum += tab4[i];
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
/* error */
|
||||
int test7(void)
|
||||
{
|
||||
int i, sum = 0;
|
||||
int *p;
|
||||
|
||||
for(i=0;i<TAB_SIZE + 1;i++) {
|
||||
p = &tab[i];
|
||||
if (i == TAB_SIZE)
|
||||
printf("i=%d %x\n", i, p);
|
||||
sum += *p;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/* ok */
|
||||
int test8(void)
|
||||
{
|
||||
int i, sum = 0;
|
||||
int tab[10];
|
||||
|
||||
for(i=0;i<10;i++) {
|
||||
sum += tab[i];
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/* error */
|
||||
int test9(void)
|
||||
{
|
||||
int i, sum = 0;
|
||||
char tab[10];
|
||||
|
||||
for(i=0;i<11;i++) {
|
||||
sum += tab[i];
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/* ok */
|
||||
int test10(void)
|
||||
{
|
||||
char tab[10];
|
||||
char tab1[10];
|
||||
|
||||
memset(tab, 0, 10);
|
||||
memcpy(tab, tab1, 10);
|
||||
memmove(tab, tab1, 10);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* error */
|
||||
int test11(void)
|
||||
{
|
||||
char tab[10];
|
||||
|
||||
memset(tab, 0, 11);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* error */
|
||||
int test12(void)
|
||||
{
|
||||
void *ptr;
|
||||
ptr = malloc(10);
|
||||
free(ptr);
|
||||
free(ptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* error */
|
||||
int test13(void)
|
||||
{
|
||||
char pad1 = 0;
|
||||
char tab[10];
|
||||
char pad2 = 0;
|
||||
memset(tab, 'a', sizeof(tab));
|
||||
return strlen(tab);
|
||||
}
|
||||
|
||||
int test14(void)
|
||||
{
|
||||
char *p = alloca(TAB_SIZE);
|
||||
memset(p, 'a', TAB_SIZE);
|
||||
p[TAB_SIZE-1] = 0;
|
||||
return strlen(p);
|
||||
}
|
||||
|
||||
/* error */
|
||||
int test15(void)
|
||||
{
|
||||
char *p = alloca(TAB_SIZE-1);
|
||||
memset(p, 'a', TAB_SIZE);
|
||||
p[TAB_SIZE-1] = 0;
|
||||
return strlen(p);
|
||||
}
|
||||
|
||||
/* ok */
|
||||
int test16()
|
||||
{
|
||||
char *demo = "This is only a test.";
|
||||
char *p;
|
||||
|
||||
fprintf(stderr, "%s start\n", __FUNCTION__);
|
||||
|
||||
p = alloca(16);
|
||||
strcpy(p,"12345678901234");
|
||||
printf("alloca: p is %s\n", p);
|
||||
|
||||
/* Test alloca embedded in a larger expression */
|
||||
printf("alloca: %s\n", strcpy(alloca(strlen(demo)+1),demo) );
|
||||
|
||||
fprintf(stderr, "%s end\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
/* error */
|
||||
int test17()
|
||||
{
|
||||
char *demo = "This is only a test.";
|
||||
char *p;
|
||||
|
||||
fprintf(stderr, "%s start\n", __FUNCTION__);
|
||||
|
||||
p = alloca(16);
|
||||
strcpy(p,"12345678901234");
|
||||
printf("alloca: p is %s\n", p);
|
||||
|
||||
/* Test alloca embedded in a larger expression */
|
||||
printf("alloca: %s\n", strcpy(alloca(strlen(demo)),demo) );
|
||||
|
||||
fprintf(stderr, "%s end\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
int (*table_test[])(void) = {
|
||||
test1,
|
||||
test2,
|
||||
test3,
|
||||
test4,
|
||||
test5,
|
||||
test6,
|
||||
test7,
|
||||
test8,
|
||||
test9,
|
||||
test10,
|
||||
test11,
|
||||
test12,
|
||||
test13,
|
||||
test14,
|
||||
test15,
|
||||
test16,
|
||||
test17,
|
||||
};
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int index;
|
||||
int (*ftest)(void);
|
||||
int index_max = sizeof(table_test)/sizeof(table_test[0]);
|
||||
|
||||
if (argc < 2) {
|
||||
printf(
|
||||
"test TCC bound checking system\n"
|
||||
"usage: boundtest N\n"
|
||||
" 1 <= N <= %d\n", index_max);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
index = 0;
|
||||
if (argc >= 2)
|
||||
index = atoi(argv[1]) - 1;
|
||||
|
||||
if ((index < 0) || (index >= index_max)) {
|
||||
printf("N is outside of the valid range (%d)\n", index);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
/* well, we also use bounds on this ! */
|
||||
ftest = table_test[index];
|
||||
ftest();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* without bound 0.77 s
|
||||
* with bounds 4.73
|
||||
*/
|
33
05/tcc-0.9.27/tests/gcctestsuite.sh
Executable file
33
05/tcc-0.9.27/tests/gcctestsuite.sh
Executable file
|
@ -0,0 +1,33 @@
|
|||
#!/bin/sh
|
||||
|
||||
TESTSUITE_PATH=$HOME/gcc/gcc-3.2/gcc/testsuite/gcc.c-torture
|
||||
TCC="./tcc -B. -I. -DNO_TRAMPOLINES"
|
||||
rm -f tcc.sum tcc.log
|
||||
nb_failed="0"
|
||||
|
||||
for src in $TESTSUITE_PATH/compile/*.c ; do
|
||||
echo $TCC -o /tmp/test.o -c $src
|
||||
$TCC -o /tmp/test.o -c $src >> tcc.log 2>&1
|
||||
if [ "$?" = "0" ] ; then
|
||||
result="PASS"
|
||||
else
|
||||
result="FAIL"
|
||||
nb_failed=$(( $nb_failed + 1 ))
|
||||
fi
|
||||
echo "$result: $src" >> tcc.sum
|
||||
done
|
||||
|
||||
for src in $TESTSUITE_PATH/execute/*.c ; do
|
||||
echo $TCC $src
|
||||
$TCC $src >> tcc.log 2>&1
|
||||
if [ "$?" = "0" ] ; then
|
||||
result="PASS"
|
||||
else
|
||||
result="FAIL"
|
||||
nb_failed=$(( $nb_failed + 1 ))
|
||||
fi
|
||||
echo "$result: $src" >> tcc.sum
|
||||
done
|
||||
|
||||
echo "$nb_failed test(s) failed." >> tcc.sum
|
||||
echo "$nb_failed test(s) failed."
|
96
05/tcc-0.9.27/tests/libtcc_test.c
Normal file
96
05/tcc-0.9.27/tests/libtcc_test.c
Normal file
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* Simple Test program for libtcc
|
||||
*
|
||||
* libtcc can be useful to use tcc as a "backend" for a code generator.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "libtcc.h"
|
||||
|
||||
/* this function is called by the generated code */
|
||||
int add(int a, int b)
|
||||
{
|
||||
return a + b;
|
||||
}
|
||||
|
||||
/* this strinc is referenced by the generated code */
|
||||
const char hello[] = "Hello World!";
|
||||
|
||||
char my_program[] =
|
||||
"#include <tcclib.h>\n" /* include the "Simple libc header for TCC" */
|
||||
"extern int add(int a, int b);\n"
|
||||
"#ifdef _WIN32\n" /* dynamically linked data needs 'dllimport' */
|
||||
" __attribute__((dllimport))\n"
|
||||
"#endif\n"
|
||||
"extern const char hello[];\n"
|
||||
"int fib(int n)\n"
|
||||
"{\n"
|
||||
" if (n <= 2)\n"
|
||||
" return 1;\n"
|
||||
" else\n"
|
||||
" return fib(n-1) + fib(n-2);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"int foo(int n)\n"
|
||||
"{\n"
|
||||
" printf(\"%s\\n\", hello);\n"
|
||||
" printf(\"fib(%d) = %d\\n\", n, fib(n));\n"
|
||||
" printf(\"add(%d, %d) = %d\\n\", n, 2 * n, add(n, 2 * n));\n"
|
||||
" return 0;\n"
|
||||
"}\n";
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
TCCState *s;
|
||||
int i;
|
||||
int (*func)(int);
|
||||
|
||||
s = tcc_new();
|
||||
if (!s) {
|
||||
fprintf(stderr, "Could not create tcc state\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* if tcclib.h and libtcc1.a are not installed, where can we find them */
|
||||
for (i = 1; i < argc; ++i) {
|
||||
char *a = argv[i];
|
||||
if (a[0] == '-') {
|
||||
if (a[1] == 'B')
|
||||
tcc_set_lib_path(s, a+2);
|
||||
else if (a[1] == 'I')
|
||||
tcc_add_include_path(s, a+2);
|
||||
else if (a[1] == 'L')
|
||||
tcc_add_library_path(s, a+2);
|
||||
}
|
||||
}
|
||||
|
||||
/* MUST BE CALLED before any compilation */
|
||||
tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
|
||||
|
||||
if (tcc_compile_string(s, my_program) == -1)
|
||||
return 1;
|
||||
|
||||
/* as a test, we add symbols that the compiled program can use.
|
||||
You may also open a dll with tcc_add_dll() and use symbols from that */
|
||||
tcc_add_symbol(s, "add", add);
|
||||
tcc_add_symbol(s, "hello", hello);
|
||||
|
||||
/* relocate the code */
|
||||
if (tcc_relocate(s, TCC_RELOCATE_AUTO) < 0)
|
||||
return 1;
|
||||
|
||||
/* get entry symbol */
|
||||
func = tcc_get_symbol(s, "foo");
|
||||
if (!func)
|
||||
return 1;
|
||||
|
||||
/* run the code */
|
||||
func(32);
|
||||
|
||||
/* delete the state */
|
||||
tcc_delete(s);
|
||||
|
||||
return 0;
|
||||
}
|
6
05/tcc-0.9.27/tests/pp/01.c
Normal file
6
05/tcc-0.9.27/tests/pp/01.c
Normal file
|
@ -0,0 +1,6 @@
|
|||
#define hash_hash # ## #
|
||||
#define mkstr(a) # a
|
||||
#define in_between(a) mkstr(a)
|
||||
#define join(c, d) in_between(c hash_hash d)
|
||||
char p[] = join(x, y);
|
||||
// char p[] = "x ## y";
|
1
05/tcc-0.9.27/tests/pp/01.expect
Normal file
1
05/tcc-0.9.27/tests/pp/01.expect
Normal file
|
@ -0,0 +1 @@
|
|||
char p[] = "x ## y";
|
28
05/tcc-0.9.27/tests/pp/02.c
Normal file
28
05/tcc-0.9.27/tests/pp/02.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
#define x 3
|
||||
#define f(a) f(x * (a))
|
||||
#undef x
|
||||
#define x 2
|
||||
#define g f
|
||||
#define z z[0]
|
||||
#define h g(~
|
||||
#define m(a) a(w)
|
||||
#define w 0,1
|
||||
#define t(a) a
|
||||
#define p() int
|
||||
#define q(x) x
|
||||
#define r(x,y) x ## y
|
||||
#define str(x) # x
|
||||
f(y+1) + f(f(z)) % t(t(g)(0) + t)(1);
|
||||
g(x+(3,4)-w) | h 5) & m
|
||||
(f)^m(m);
|
||||
char c[2][6] = { str(hello), str() };
|
||||
/*
|
||||
* f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1);
|
||||
* f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1);
|
||||
* char c[2][6] = { "hello", "" };
|
||||
*/
|
||||
#define L21 f(y+1) + f(f(z)) % t(t(g)(0) + t)(1);
|
||||
#define L22 g(x+(3,4)-w) | h 5) & m\
|
||||
(f)^m(m);
|
||||
L21
|
||||
L22
|
5
05/tcc-0.9.27/tests/pp/02.expect
Normal file
5
05/tcc-0.9.27/tests/pp/02.expect
Normal file
|
@ -0,0 +1,5 @@
|
|||
f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1);
|
||||
f(2 * (2 +(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1);
|
||||
char c[2][6] = { "hello", "" };
|
||||
f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1);
|
||||
f(2 * (2 +(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1);
|
15
05/tcc-0.9.27/tests/pp/03.c
Normal file
15
05/tcc-0.9.27/tests/pp/03.c
Normal file
|
@ -0,0 +1,15 @@
|
|||
#define str(s) # s
|
||||
#define xstr(s) str(s)
|
||||
#define debug(s, t) printf("x" # s "= %d, x" # t "= %s", \
|
||||
x ## s, x ## t)
|
||||
#define INCFILE(n) vers ## n
|
||||
#define glue(a, b) a ## b
|
||||
#define xglue(a, b) glue(a, b)
|
||||
#define HIGHLOW "hello"
|
||||
#define LOW LOW ", world"
|
||||
debug(1, 2);
|
||||
fputs(str(strncmp("abc\0d", "abc", '\4') // this goes away
|
||||
== 0) str(: @\n), s);
|
||||
\#include xstr(INCFILE(2).h)
|
||||
glue(HIGH, LOW);
|
||||
xglue(HIGH, LOW)
|
5
05/tcc-0.9.27/tests/pp/03.expect
Normal file
5
05/tcc-0.9.27/tests/pp/03.expect
Normal file
|
@ -0,0 +1,5 @@
|
|||
printf("x" "1" "= %d, x" "2" "= %s", x1, x2);
|
||||
fputs("strncmp(\"abc\\0d\", \"abc\", '\\4') == 0" ": @\n", s);
|
||||
\#include "vers2.h"
|
||||
"hello";
|
||||
"hello" ", world"
|
4
05/tcc-0.9.27/tests/pp/04.c
Normal file
4
05/tcc-0.9.27/tests/pp/04.c
Normal file
|
@ -0,0 +1,4 @@
|
|||
#define foobar 1
|
||||
#define C(x,y) x##y
|
||||
#define D(x) (C(x,bar))
|
||||
D(foo)
|
1
05/tcc-0.9.27/tests/pp/04.expect
Normal file
1
05/tcc-0.9.27/tests/pp/04.expect
Normal file
|
@ -0,0 +1 @@
|
|||
(1)
|
7
05/tcc-0.9.27/tests/pp/05.c
Normal file
7
05/tcc-0.9.27/tests/pp/05.c
Normal file
|
@ -0,0 +1,7 @@
|
|||
#define t(x,y,z) x ## y ## z
|
||||
#define xxx(s) int s[] = { t(1,2,3), t(,4,5), t(6,,7), t(8,9,), \
|
||||
t(10,,), t(,11,), t(,,12), t(,,) };
|
||||
|
||||
int j[] = { t(1,2,3), t(,4,5), t(6,,7), t(8,9,),
|
||||
t(10,,), t(,11,), t(,,12), t(,,) };
|
||||
xxx(j)
|
3
05/tcc-0.9.27/tests/pp/05.expect
Normal file
3
05/tcc-0.9.27/tests/pp/05.expect
Normal file
|
@ -0,0 +1,3 @@
|
|||
int j[] = { 123, 45, 67, 89,
|
||||
10, 11, 12, };
|
||||
int j[] = { 123, 45, 67, 89, 10, 11, 12, };
|
5
05/tcc-0.9.27/tests/pp/06.c
Normal file
5
05/tcc-0.9.27/tests/pp/06.c
Normal file
|
@ -0,0 +1,5 @@
|
|||
#define X(a,b, \
|
||||
c,d) \
|
||||
foo
|
||||
|
||||
X(1,2,3,4)
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue