diff --git a/README b/README
index d51c76fcbf..347cfa36b5 100644
--- a/README
+++ b/README
@@ -36,4 +36,4 @@ applications, provided you follow the rules stated in the LGPL. You can
also modify Racket; if you distribute a modified version, you must
distribute it under the terms of the LGPL, which in particular means
that you must release the source code for the modified software. See
-doc/release-notes/COPYING.txt for more information.
+doc/release-notes/COPYING_LESSER.txt for more information.
diff --git a/collects/scribblings/guide/performance.scrbl b/collects/scribblings/guide/performance.scrbl
index 7581f3c0f2..10d90a61a9 100644
--- a/collects/scribblings/guide/performance.scrbl
+++ b/collects/scribblings/guide/performance.scrbl
@@ -70,7 +70,7 @@ On some platforms, bytecode is further compiled to native code via a
compiler substantially speeds programs that execute tight loops,
arithmetic on small integers, and arithmetic on inexact real
numbers. Currently, @tech{JIT} compilation is supported for x86,
-x86_64 (a.k.a. AMD64), and 32-bit PowerPC processors. The @tech{JIT}
+x86_64 (a.k.a. AMD64), ARM, and 32-bit PowerPC processors. The @tech{JIT}
compiler can be disabled via the @racket[eval-jit-enabled] parameter
or the @DFlag{no-jit}/@Flag{j} command-line flag for @exec{racket}.
diff --git a/collects/scribblings/main/license.scrbl b/collects/scribblings/main/license.scrbl
index 496aaee264..8e331798b7 100644
--- a/collects/scribblings/main/license.scrbl
+++ b/collects/scribblings/main/license.scrbl
@@ -21,7 +21,7 @@ General Public License (LGPL). This means
]
-See @filepath{doc/release-notes/COPYING.txt} in your Racket installation
+See @filepath{doc/release-notes/COPYING_LESSER.txt} in your Racket installation
for more information.
@copyright{
@@ -88,7 +88,7 @@ Racket software includes or extends the following copyrighted material:
@copyright{
GNU lightning
- Copyright (c) 1994, 1995, 1996, 1999, 2000, 2001, 2002
+ Copyright (c) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2011
Free Software Foundation, Inc.
}
diff --git a/doc/release-notes/COPYING.txt b/doc/release-notes/COPYING.txt
index 4362b49151..4432540474 100644
--- a/doc/release-notes/COPYING.txt
+++ b/doc/release-notes/COPYING.txt
@@ -1,502 +1,676 @@
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 2.1, February 1999
- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
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
- Preamble
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
- 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.
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
- 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, 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
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
- 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 prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
- 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 such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
- 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.
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
- 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.
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
- 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.
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
- 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.
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
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
+modification follow.
- 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".
+ TERMS AND CONDITIONS
- 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.
+ 0. Definitions.
- 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".)
+ "This License" refers to version 3 of the GNU General Public License.
- "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.
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
- 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.
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
- 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.
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
- You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
- 2. You may modify your copy or copies of the 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:
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
- a) The modified work must itself be a software library.
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
- b) You must cause the files modified to carry prominent notices
- stating that you changed the files and the date of any change.
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
- 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.
+ 1. Source Code.
- 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.
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
- (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.)
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
-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.
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run 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.
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
-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.
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
- 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.
+ The Corresponding Source for a work in source code form is that
+same work.
- This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
+ 2. Basic Permissions.
- 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.
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
- 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.
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
- 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.
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
- 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.
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
- 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.
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
- 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.)
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
- 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.
+ 4. Conveying Verbatim Copies.
- 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:
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
- 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.)
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
- 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.
+ 5. Conveying Modified Source Versions.
- 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.
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
- 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.
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
- e) Verify that the user has already received a copy of these
- materials or that you have already sent this user a copy.
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
- 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.
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
- 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:
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
- 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.
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
- 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.
+ 6. Conveying Non-Source Forms.
- 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.
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
- 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.
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
- 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
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
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
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If 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.
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
+ 13. Use with the GNU Affero General Public License.
-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.
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
+ 14. Revised Versions 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.
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU 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.
- 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
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
-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.
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
- NO WARRANTY
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
- 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.
+ 15. Disclaimer of Warranty.
- 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.
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Libraries
+ 16. Limitation of Liability.
- 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).
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
- 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.
+ 17. Interpretation of Sections 15 and 16.
-
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
Copyright (C)
- 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.1 of the License, or (at your option) any later version.
+ 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 3 of the License, or
+ (at your option) any later version.
- This library is distributed in the hope that it will be useful,
+ 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
- Lesser General Public License for more details.
+ 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 Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
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:
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
- Yoyodyne, Inc., hereby disclaims all copyright interest in the
- library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
- , 1 April 1990
- Ty Coon, President of Vice
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
-That's all there is to it!
diff --git a/doc/release-notes/racket/HISTORY.txt b/doc/release-notes/racket/HISTORY.txt
index 2bbf69eec4..65a5314897 100644
--- a/doc/release-notes/racket/HISTORY.txt
+++ b/doc/release-notes/racket/HISTORY.txt
@@ -1,3 +1,6 @@
+Version 5.3.4.1
+Changed JIT to support ARM
+
Version 5.3.3.9
racket/udp: added multicast support: udp-multicast-join-group!,
udp-multicast-leave-group!, udp-multicast-interface,
diff --git a/src/configure b/src/configure
index 953cd24322..0948f4a72d 100755
--- a/src/configure
+++ b/src/configure
@@ -8806,7 +8806,7 @@ fi
############## drop optimization flags ################
if test "${enable_noopt}" = "yes" ; then
- AWKPRG='BEGIN { FS = "(^| )-O(0|1|2|3|4|5|6|7|8|9|())( |$)" } /.*/ { for (i = 1; i < NF; i++) printf "%s ", $i; print $NF }'
+ AWKPRG='BEGIN { FS = "(^| )-O(0|1|2|3|4|5|6|7|8|9)?( |$)" } /.*/ { for (i = 1; i < NF; i++) printf "%s ", $i; print $NF }'
CFLAGS=`echo "$CFLAGS" | awk "$AWKPRG"`
fi
diff --git a/src/foreign/foreign.c b/src/foreign/foreign.c
index 8e75e53f8e..19098ac75c 100644
--- a/src/foreign/foreign.c
+++ b/src/foreign/foreign.c
@@ -1796,6 +1796,11 @@ static void* SCHEME2C(const char *who,
delta += (sizeof(intptr_t)-sizeof(Tsint8));
}
# endif /* SCHEME_BIG_ENDIAN */
+# ifdef FFI_CALLBACK_NEED_INT_CLEAR
+ if (sizeof(Tsint8)c]);
diff --git a/src/foreign/libffi/config.sub b/src/foreign/libffi/config.sub
index 17c91458a8..872199acf7 100644
--- a/src/foreign/libffi/config.sub
+++ b/src/foreign/libffi/config.sub
@@ -1,38 +1,31 @@
#! /bin/sh
# Configuration validation subroutine script.
-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
-# Free Software Foundation, Inc.
+# Copyright 1992-2013 Free Software Foundation, Inc.
-timestamp='2009-11-07'
+timestamp='2013-02-12'
-# This file is (in principle) common to ALL GNU software.
-# The presence of a machine in this file suggests that SOME GNU software
-# can handle that machine. It does not imply ALL GNU software can.
-#
-# 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 of the License, or
+# 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 3 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.
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
-# 02110-1301, USA.
+# along with this program; if not, see .
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
+# the same distribution terms that you use for the rest of that
+# program. This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
-# Please send patches to . Submit a context
-# diff and a properly formatted GNU ChangeLog entry.
+# Please send patches with a ChangeLog entry to config-patches@gnu.org.
#
# Configuration subroutine to validate and canonicalize a configuration type.
# Supply the specified configuration type as an argument.
@@ -75,8 +68,7 @@ Report bugs and patches to ."
version="\
GNU config.sub ($timestamp)
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+Copyright 1992-2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -123,13 +115,18 @@ esac
# Here we must recognize all the valid KERNEL-OS combinations.
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
case $maybe_os in
- nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
- uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+ nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
+ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
+ knetbsd*-gnu* | netbsd*-gnu* | \
kopensolaris*-gnu* | \
storm-chaos* | os2-emx* | rtmk-nova*)
os=-$maybe_os
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
;;
+ android-linux)
+ os=-linux-android
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
+ ;;
*)
basic_machine=`echo $1 | sed 's/-[^-]*$//'`
if [ $basic_machine != $1 ]
@@ -152,12 +149,12 @@ case $os in
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
- -apple | -axis | -knuth | -cray | -microblaze)
+ -apple | -axis | -knuth | -cray | -microblaze*)
os=
basic_machine=$1
;;
- -bluegene*)
- os=-cnk
+ -bluegene*)
+ os=-cnk
;;
-sim | -cisco | -oki | -wec | -winbond)
os=
@@ -173,10 +170,10 @@ case $os in
os=-chorusos
basic_machine=$1
;;
- -chorusrdb)
- os=-chorusrdb
+ -chorusrdb)
+ os=-chorusrdb
basic_machine=$1
- ;;
+ ;;
-hiux*)
os=-hiuxwe2
;;
@@ -221,6 +218,12 @@ case $os in
-isc*)
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
+ -lynx*178)
+ os=-lynxos178
+ ;;
+ -lynx*5)
+ os=-lynxos5
+ ;;
-lynx*)
os=-lynxos
;;
@@ -245,20 +248,27 @@ case $basic_machine in
# Some are omitted here because they have special meanings below.
1750a | 580 \
| a29k \
+ | aarch64 | aarch64_be \
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
| am33_2.0 \
- | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+ | arc \
+ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
+ | avr | avr32 \
+ | be32 | be64 \
| bfin \
| c4x | clipper \
| d10v | d30v | dlx | dsp16xx \
+ | epiphany \
| fido | fr30 | frv \
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | hexagon \
| i370 | i860 | i960 | ia64 \
| ip2k | iq2000 \
+ | le32 | le64 \
| lm32 \
| m32c | m32r | m32rle | m68000 | m68k | m88k \
- | maxq | mb | microblaze | mcore | mep | metag \
+ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \
| mips | mipsbe | mipseb | mipsel | mipsle \
| mips16 \
| mips64 | mips64el \
@@ -276,34 +286,45 @@ case $basic_machine in
| mipsisa64r2 | mipsisa64r2el \
| mipsisa64sb1 | mipsisa64sb1el \
| mipsisa64sr71k | mipsisa64sr71kel \
+ | mipsr5900 | mipsr5900el \
| mipstx39 | mipstx39el \
| mn10200 | mn10300 \
| moxie \
| mt \
| msp430 \
- | nios | nios2 \
+ | nds32 | nds32le | nds32be \
+ | nios | nios2 | nios2eb | nios2el \
| ns16k | ns32k \
- | or32 \
+ | open8 \
+ | or1k | or32 \
| pdp10 | pdp11 | pj | pjl \
- | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+ | powerpc | powerpc64 | powerpc64le | powerpcle \
| pyramid \
- | rx \
+ | rl78 | rx \
| score \
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
| sh64 | sh64le \
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
- | spu | strongarm \
- | tahoe | thumb | tic4x | tic80 | tron \
+ | spu \
+ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
| ubicom32 \
- | v850 | v850e \
+ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
| we32k \
- | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
+ | x86 | xc16x | xstormy16 | xtensa \
| z8k | z80)
basic_machine=$basic_machine-unknown
;;
- m6811 | m68hc11 | m6812 | m68hc12 | picochip)
- # Motorola 68HC11/12.
+ c54x)
+ basic_machine=tic54x-unknown
+ ;;
+ c55x)
+ basic_machine=tic55x-unknown
+ ;;
+ c6x)
+ basic_machine=tic6x-unknown
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip)
basic_machine=$basic_machine-unknown
os=-none
;;
@@ -313,6 +334,21 @@ case $basic_machine in
basic_machine=mt-unknown
;;
+ strongarm | thumb | xscale)
+ basic_machine=arm-unknown
+ ;;
+ xgate)
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ xscaleeb)
+ basic_machine=armeb-unknown
+ ;;
+
+ xscaleel)
+ basic_machine=armel-unknown
+ ;;
+
# We use `pc' rather than `unknown'
# because (1) that's what they normally are, and
# (2) the word "unknown" tends to confuse beginning users.
@@ -327,25 +363,30 @@ case $basic_machine in
# Recognize the basic CPU types with company name.
580-* \
| a29k-* \
+ | aarch64-* | aarch64_be-* \
| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
| avr-* | avr32-* \
+ | be32-* | be64-* \
| bfin-* | bs2000-* \
- | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* \
| clipper-* | craynv-* | cydra-* \
| d10v-* | d30v-* | dlx-* \
| elxsi-* \
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
| h8300-* | h8500-* \
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | hexagon-* \
| i*86-* | i860-* | i960-* | ia64-* \
| ip2k-* | iq2000-* \
+ | le32-* | le64-* \
| lm32-* \
| m32c-* | m32r-* | m32rle-* \
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
- | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \
+ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
+ | microblaze-* | microblazeel-* \
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
| mips16-* \
| mips64-* | mips64el-* \
@@ -363,29 +404,34 @@ case $basic_machine in
| mipsisa64r2-* | mipsisa64r2el-* \
| mipsisa64sb1-* | mipsisa64sb1el-* \
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipsr5900-* | mipsr5900el-* \
| mipstx39-* | mipstx39el-* \
| mmix-* \
| mt-* \
| msp430-* \
- | nios-* | nios2-* \
+ | nds32-* | nds32le-* | nds32be-* \
+ | nios-* | nios2-* | nios2eb-* | nios2el-* \
| none-* | np1-* | ns16k-* | ns32k-* \
+ | open8-* \
| orion-* \
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
- | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
| pyramid-* \
- | romp-* | rs6000-* | rx-* \
+ | rl78-* | romp-* | rs6000-* | rx-* \
| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
| sparclite-* \
- | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
- | tahoe-* | thumb-* \
- | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
+ | tahoe-* \
+ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+ | tile*-* \
| tron-* \
| ubicom32-* \
- | v850-* | v850e-* | vax-* \
+ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
+ | vax-* \
| we32k-* \
- | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
+ | x86-* | x86_64-* | xc16x-* | xps100-* \
| xstormy16-* | xtensa*-* \
| ymp-* \
| z8k-* | z80-*)
@@ -410,7 +456,7 @@ case $basic_machine in
basic_machine=a29k-amd
os=-udi
;;
- abacus)
+ abacus)
basic_machine=abacus-unknown
;;
adobe68k)
@@ -480,11 +526,20 @@ case $basic_machine in
basic_machine=powerpc-ibm
os=-cnk
;;
+ c54x-*)
+ basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ c55x-*)
+ basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ c6x-*)
+ basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
c90)
basic_machine=c90-cray
os=-unicos
;;
- cegcc)
+ cegcc)
basic_machine=arm-unknown
os=-cegcc
;;
@@ -516,7 +571,7 @@ case $basic_machine in
basic_machine=craynv-cray
os=-unicosmp
;;
- cr16)
+ cr16 | cr16-*)
basic_machine=cr16-unknown
os=-elf
;;
@@ -674,7 +729,6 @@ case $basic_machine in
i370-ibm* | ibm*)
basic_machine=i370-ibm
;;
-# I'm not sure what "Sysv32" means. Should this be sysv3.2?
i*86v32)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv32
@@ -732,9 +786,13 @@ case $basic_machine in
basic_machine=ns32k-utek
os=-sysv
;;
- microblaze)
+ microblaze*)
basic_machine=microblaze-xilinx
;;
+ mingw64)
+ basic_machine=x86_64-pc
+ os=-mingw64
+ ;;
mingw32)
basic_machine=i386-pc
os=-mingw32
@@ -771,10 +829,18 @@ case $basic_machine in
ms1-*)
basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
;;
+ msys)
+ basic_machine=i386-pc
+ os=-msys
+ ;;
mvs)
basic_machine=i370-ibm
os=-mvs
;;
+ nacl)
+ basic_machine=le32-unknown
+ os=-nacl
+ ;;
ncr3000)
basic_machine=i486-ncr
os=-sysv4
@@ -839,6 +905,12 @@ case $basic_machine in
np1)
basic_machine=np1-gould
;;
+ neo-tandem)
+ basic_machine=neo-tandem
+ ;;
+ nse-tandem)
+ basic_machine=nse-tandem
+ ;;
nsr-tandem)
basic_machine=nsr-tandem
;;
@@ -921,9 +993,10 @@ case $basic_machine in
;;
power) basic_machine=power-ibm
;;
- ppc) basic_machine=powerpc-unknown
+ ppc | ppcbe) basic_machine=powerpc-unknown
;;
- ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ppc-* | ppcbe-*)
+ basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ppcle | powerpclittle | ppc-le | powerpc-little)
basic_machine=powerpcle-unknown
@@ -948,7 +1021,11 @@ case $basic_machine in
basic_machine=i586-unknown
os=-pw32
;;
- rdos)
+ rdos | rdos64)
+ basic_machine=x86_64-pc
+ os=-rdos
+ ;;
+ rdos32)
basic_machine=i386-pc
os=-rdos
;;
@@ -1017,6 +1094,9 @@ case $basic_machine in
basic_machine=i860-stratus
os=-sysv4
;;
+ strongarm-* | thumb-*)
+ basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
sun2)
basic_machine=m68000-sun
;;
@@ -1073,20 +1153,8 @@ case $basic_machine in
basic_machine=t90-cray
os=-unicos
;;
- tic54x | c54x*)
- basic_machine=tic54x-unknown
- os=-coff
- ;;
- tic55x | c55x*)
- basic_machine=tic55x-unknown
- os=-coff
- ;;
- tic6x | c6x*)
- basic_machine=tic6x-unknown
- os=-coff
- ;;
tile*)
- basic_machine=tile-unknown
+ basic_machine=$basic_machine-unknown
os=-linux-gnu
;;
tx39)
@@ -1156,6 +1224,9 @@ case $basic_machine in
xps | xps100)
basic_machine=xps100-honeywell
;;
+ xscale-* | xscalee[bl]-*)
+ basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
+ ;;
ymp)
basic_machine=ymp-cray
os=-unicos
@@ -1253,9 +1324,12 @@ esac
if [ x"$os" != x"" ]
then
case $os in
- # First match some system type aliases
- # that might get confused with valid system types.
+ # First match some system type aliases
+ # that might get confused with valid system types.
# -solaris* is a basic system type, with this one exception.
+ -auroraux)
+ os=-auroraux
+ ;;
-solaris1 | -solaris1.*)
os=`echo $os | sed -e 's|solaris1|sunos4|'`
;;
@@ -1277,21 +1351,22 @@ case $os in
# -sysv* is not here because it comes later, after sysvr4.
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
| -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
- | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
- | -kopensolaris* \
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
+ | -sym* | -kopensolaris* | -plan9* \
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
| -aos* | -aros* \
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
- | -openbsd* | -solidbsd* \
+ | -bitrig* | -openbsd* | -solidbsd* \
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
| -chorusos* | -chorusrdb* | -cegcc* \
- | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
- | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
+ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
+ | -linux-newlib* | -linux-musl* | -linux-uclibc* \
| -uxpv* | -beos* | -mpeix* | -udk* \
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
@@ -1338,7 +1413,7 @@ case $os in
-opened*)
os=-openedition
;;
- -os400*)
+ -os400*)
os=-os400
;;
-wince*)
@@ -1387,7 +1462,7 @@ case $os in
-sinix*)
os=-sysv4
;;
- -tpf*)
+ -tpf*)
os=-tpf
;;
-triton*)
@@ -1423,15 +1498,14 @@ case $os in
-aros*)
os=-aros
;;
- -kaos*)
- os=-kaos
- ;;
-zvmoe)
os=-zvmoe
;;
-dicos*)
os=-dicos
;;
+ -nacl*)
+ ;;
-none)
;;
*)
@@ -1454,10 +1528,10 @@ else
# system, and we'll never get to this point.
case $basic_machine in
- score-*)
+ score-*)
os=-elf
;;
- spu-*)
+ spu-*)
os=-elf
;;
*-acorn)
@@ -1469,8 +1543,20 @@ case $basic_machine in
arm*-semi)
os=-aout
;;
- c4x-* | tic4x-*)
- os=-coff
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
+ hexagon-*)
+ os=-elf
+ ;;
+ tic54x-*)
+ os=-coff
+ ;;
+ tic55x-*)
+ os=-coff
+ ;;
+ tic6x-*)
+ os=-coff
;;
# This must come before the *-dec entry.
pdp10-*)
@@ -1490,14 +1576,11 @@ case $basic_machine in
;;
m68000-sun)
os=-sunos3
- # This also exists in the configure program, but was not the
- # default.
- # os=-sunos4
;;
m68*-cisco)
os=-aout
;;
- mep-*)
+ mep-*)
os=-elf
;;
mips*-cisco)
@@ -1506,6 +1589,9 @@ case $basic_machine in
mips*-*)
os=-elf
;;
+ or1k-*)
+ os=-elf
+ ;;
or32-*)
os=-coff
;;
@@ -1524,7 +1610,7 @@ case $basic_machine in
*-ibm)
os=-aix
;;
- *-knuth)
+ *-knuth)
os=-mmixware
;;
*-wec)
diff --git a/src/lt/config.sub b/src/lt/config.sub
index c060f44833..872199acf7 100755
--- a/src/lt/config.sub
+++ b/src/lt/config.sub
@@ -1,44 +1,40 @@
#! /bin/sh
# Configuration validation subroutine script.
-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
-# Inc.
+# Copyright 1992-2013 Free Software Foundation, Inc.
-timestamp='2007-04-29'
+timestamp='2013-02-12'
-# This file is (in principle) common to ALL GNU software.
-# The presence of a machine in this file suggests that SOME GNU software
-# can handle that machine. It does not imply ALL GNU software can.
-#
-# 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 of the License, or
+# 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 3 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.
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
-# 02110-1301, USA.
+# along with this program; if not, see .
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
+# the same distribution terms that you use for the rest of that
+# program. This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
-# Please send patches to . Submit a context
-# diff and a properly formatted ChangeLog entry.
+# Please send patches with a ChangeLog entry to config-patches@gnu.org.
#
# Configuration subroutine to validate and canonicalize a configuration type.
# Supply the specified configuration type as an argument.
# If it is invalid, we print an error message on stderr and exit with code 1.
# Otherwise, we print the canonical config type on stdout and succeed.
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
# This file is supposed to be the same for all GNU packages
# and recognize all the CPU types, system types and aliases
# that are meaningful with *any* GNU software.
@@ -72,8 +68,7 @@ Report bugs and patches to ."
version="\
GNU config.sub ($timestamp)
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
-Free Software Foundation, Inc.
+Copyright 1992-2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -120,12 +115,18 @@ esac
# Here we must recognize all the valid KERNEL-OS combinations.
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
case $maybe_os in
- nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
- uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+ nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
+ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
+ knetbsd*-gnu* | netbsd*-gnu* | \
+ kopensolaris*-gnu* | \
storm-chaos* | os2-emx* | rtmk-nova*)
os=-$maybe_os
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
;;
+ android-linux)
+ os=-linux-android
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
+ ;;
*)
basic_machine=`echo $1 | sed 's/-[^-]*$//'`
if [ $basic_machine != $1 ]
@@ -148,10 +149,13 @@ case $os in
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
- -apple | -axis | -knuth | -cray)
+ -apple | -axis | -knuth | -cray | -microblaze*)
os=
basic_machine=$1
;;
+ -bluegene*)
+ os=-cnk
+ ;;
-sim | -cisco | -oki | -wec | -winbond)
os=
basic_machine=$1
@@ -166,10 +170,10 @@ case $os in
os=-chorusos
basic_machine=$1
;;
- -chorusrdb)
- os=-chorusrdb
+ -chorusrdb)
+ os=-chorusrdb
basic_machine=$1
- ;;
+ ;;
-hiux*)
os=-hiuxwe2
;;
@@ -214,6 +218,12 @@ case $os in
-isc*)
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
+ -lynx*178)
+ os=-lynxos178
+ ;;
+ -lynx*5)
+ os=-lynxos5
+ ;;
-lynx*)
os=-lynxos
;;
@@ -238,24 +248,34 @@ case $basic_machine in
# Some are omitted here because they have special meanings below.
1750a | 580 \
| a29k \
+ | aarch64 | aarch64_be \
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
| am33_2.0 \
- | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+ | arc \
+ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
+ | avr | avr32 \
+ | be32 | be64 \
| bfin \
| c4x | clipper \
| d10v | d30v | dlx | dsp16xx \
+ | epiphany \
| fido | fr30 | frv \
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | hexagon \
| i370 | i860 | i960 | ia64 \
| ip2k | iq2000 \
+ | le32 | le64 \
+ | lm32 \
| m32c | m32r | m32rle | m68000 | m68k | m88k \
- | maxq | mb | microblaze | mcore | mep \
+ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \
| mips | mipsbe | mipseb | mipsel | mipsle \
| mips16 \
| mips64 | mips64el \
- | mips64vr | mips64vrel \
+ | mips64octeon | mips64octeonel \
| mips64orion | mips64orionel \
+ | mips64r5900 | mips64r5900el \
+ | mips64vr | mips64vrel \
| mips64vr4100 | mips64vr4100el \
| mips64vr4300 | mips64vr4300el \
| mips64vr5000 | mips64vr5000el \
@@ -266,31 +286,45 @@ case $basic_machine in
| mipsisa64r2 | mipsisa64r2el \
| mipsisa64sb1 | mipsisa64sb1el \
| mipsisa64sr71k | mipsisa64sr71kel \
+ | mipsr5900 | mipsr5900el \
| mipstx39 | mipstx39el \
| mn10200 | mn10300 \
+ | moxie \
| mt \
| msp430 \
- | nios | nios2 \
+ | nds32 | nds32le | nds32be \
+ | nios | nios2 | nios2eb | nios2el \
| ns16k | ns32k \
- | or32 \
+ | open8 \
+ | or1k | or32 \
| pdp10 | pdp11 | pj | pjl \
- | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+ | powerpc | powerpc64 | powerpc64le | powerpcle \
| pyramid \
+ | rl78 | rx \
| score \
- | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
| sh64 | sh64le \
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
- | spu | strongarm \
- | tahoe | thumb | tic4x | tic80 | tron \
- | v850 | v850e \
+ | spu \
+ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
+ | ubicom32 \
+ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
| we32k \
- | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
- | z8k)
+ | x86 | xc16x | xstormy16 | xtensa \
+ | z8k | z80)
basic_machine=$basic_machine-unknown
;;
- m6811 | m68hc11 | m6812 | m68hc12)
- # Motorola 68HC11/12.
+ c54x)
+ basic_machine=tic54x-unknown
+ ;;
+ c55x)
+ basic_machine=tic55x-unknown
+ ;;
+ c6x)
+ basic_machine=tic6x-unknown
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip)
basic_machine=$basic_machine-unknown
os=-none
;;
@@ -300,6 +334,21 @@ case $basic_machine in
basic_machine=mt-unknown
;;
+ strongarm | thumb | xscale)
+ basic_machine=arm-unknown
+ ;;
+ xgate)
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ xscaleeb)
+ basic_machine=armeb-unknown
+ ;;
+
+ xscaleel)
+ basic_machine=armel-unknown
+ ;;
+
# We use `pc' rather than `unknown'
# because (1) that's what they normally are, and
# (2) the word "unknown" tends to confuse beginning users.
@@ -314,29 +363,37 @@ case $basic_machine in
# Recognize the basic CPU types with company name.
580-* \
| a29k-* \
+ | aarch64-* | aarch64_be-* \
| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
| avr-* | avr32-* \
+ | be32-* | be64-* \
| bfin-* | bs2000-* \
- | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* \
| clipper-* | craynv-* | cydra-* \
| d10v-* | d30v-* | dlx-* \
| elxsi-* \
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
| h8300-* | h8500-* \
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | hexagon-* \
| i*86-* | i860-* | i960-* | ia64-* \
| ip2k-* | iq2000-* \
+ | le32-* | le64-* \
+ | lm32-* \
| m32c-* | m32r-* | m32rle-* \
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
- | m88110-* | m88k-* | maxq-* | mcore-* \
+ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
+ | microblaze-* | microblazeel-* \
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
| mips16-* \
| mips64-* | mips64el-* \
- | mips64vr-* | mips64vrel-* \
+ | mips64octeon-* | mips64octeonel-* \
| mips64orion-* | mips64orionel-* \
+ | mips64r5900-* | mips64r5900el-* \
+ | mips64vr-* | mips64vrel-* \
| mips64vr4100-* | mips64vr4100el-* \
| mips64vr4300-* | mips64vr4300el-* \
| mips64vr5000-* | mips64vr5000el-* \
@@ -347,31 +404,41 @@ case $basic_machine in
| mipsisa64r2-* | mipsisa64r2el-* \
| mipsisa64sb1-* | mipsisa64sb1el-* \
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipsr5900-* | mipsr5900el-* \
| mipstx39-* | mipstx39el-* \
| mmix-* \
| mt-* \
| msp430-* \
- | nios-* | nios2-* \
+ | nds32-* | nds32le-* | nds32be-* \
+ | nios-* | nios2-* | nios2eb-* | nios2el-* \
| none-* | np1-* | ns16k-* | ns32k-* \
+ | open8-* \
| orion-* \
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
- | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
| pyramid-* \
- | romp-* | rs6000-* \
- | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+ | rl78-* | romp-* | rs6000-* | rx-* \
+ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
| sparclite-* \
- | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
- | tahoe-* | thumb-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
+ | tahoe-* \
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+ | tile*-* \
| tron-* \
- | v850-* | v850e-* | vax-* \
+ | ubicom32-* \
+ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
+ | vax-* \
| we32k-* \
- | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
- | xstormy16-* | xtensa-* \
+ | x86-* | x86_64-* | xc16x-* | xps100-* \
+ | xstormy16-* | xtensa*-* \
| ymp-* \
- | z8k-*)
+ | z8k-* | z80-*)
+ ;;
+ # Recognize the basic CPU types without company name, with glob match.
+ xtensa*)
+ basic_machine=$basic_machine-unknown
;;
# Recognize the various machine names and aliases which stand
# for a CPU type and a company and sometimes even an OS.
@@ -389,7 +456,7 @@ case $basic_machine in
basic_machine=a29k-amd
os=-udi
;;
- abacus)
+ abacus)
basic_machine=abacus-unknown
;;
adobe68k)
@@ -435,6 +502,10 @@ case $basic_machine in
basic_machine=m68k-apollo
os=-bsd
;;
+ aros)
+ basic_machine=i386-pc
+ os=-aros
+ ;;
aux)
basic_machine=m68k-apple
os=-aux
@@ -443,10 +514,35 @@ case $basic_machine in
basic_machine=ns32k-sequent
os=-dynix
;;
+ blackfin)
+ basic_machine=bfin-unknown
+ os=-linux
+ ;;
+ blackfin-*)
+ basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ bluegene*)
+ basic_machine=powerpc-ibm
+ os=-cnk
+ ;;
+ c54x-*)
+ basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ c55x-*)
+ basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ c6x-*)
+ basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
c90)
basic_machine=c90-cray
os=-unicos
;;
+ cegcc)
+ basic_machine=arm-unknown
+ os=-cegcc
+ ;;
convex-c1)
basic_machine=c1-convex
os=-bsd
@@ -475,8 +571,8 @@ case $basic_machine in
basic_machine=craynv-cray
os=-unicosmp
;;
- cr16c)
- basic_machine=cr16c-unknown
+ cr16 | cr16-*)
+ basic_machine=cr16-unknown
os=-elf
;;
crds | unos)
@@ -514,6 +610,10 @@ case $basic_machine in
basic_machine=m88k-motorola
os=-sysv3
;;
+ dicos)
+ basic_machine=i686-pc
+ os=-dicos
+ ;;
djgpp)
basic_machine=i586-pc
os=-msdosdjgpp
@@ -629,7 +729,6 @@ case $basic_machine in
i370-ibm* | ibm*)
basic_machine=i370-ibm
;;
-# I'm not sure what "Sysv32" means. Should this be sysv3.2?
i*86v32)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv32
@@ -668,6 +767,14 @@ case $basic_machine in
basic_machine=m68k-isi
os=-sysv
;;
+ m68knommu)
+ basic_machine=m68k-unknown
+ os=-linux
+ ;;
+ m68knommu-*)
+ basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
m88k-omron*)
basic_machine=m88k-omron
;;
@@ -679,6 +786,13 @@ case $basic_machine in
basic_machine=ns32k-utek
os=-sysv
;;
+ microblaze*)
+ basic_machine=microblaze-xilinx
+ ;;
+ mingw64)
+ basic_machine=x86_64-pc
+ os=-mingw64
+ ;;
mingw32)
basic_machine=i386-pc
os=-mingw32
@@ -715,10 +829,18 @@ case $basic_machine in
ms1-*)
basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
;;
+ msys)
+ basic_machine=i386-pc
+ os=-msys
+ ;;
mvs)
basic_machine=i370-ibm
os=-mvs
;;
+ nacl)
+ basic_machine=le32-unknown
+ os=-nacl
+ ;;
ncr3000)
basic_machine=i486-ncr
os=-sysv4
@@ -783,6 +905,12 @@ case $basic_machine in
np1)
basic_machine=np1-gould
;;
+ neo-tandem)
+ basic_machine=neo-tandem
+ ;;
+ nse-tandem)
+ basic_machine=nse-tandem
+ ;;
nsr-tandem)
basic_machine=nsr-tandem
;;
@@ -813,6 +941,14 @@ case $basic_machine in
basic_machine=i860-intel
os=-osf
;;
+ parisc)
+ basic_machine=hppa-unknown
+ os=-linux
+ ;;
+ parisc-*)
+ basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
pbd)
basic_machine=sparc-tti
;;
@@ -857,9 +993,10 @@ case $basic_machine in
;;
power) basic_machine=power-ibm
;;
- ppc) basic_machine=powerpc-unknown
+ ppc | ppcbe) basic_machine=powerpc-unknown
;;
- ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ppc-* | ppcbe-*)
+ basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ppcle | powerpclittle | ppc-le | powerpc-little)
basic_machine=powerpcle-unknown
@@ -884,7 +1021,11 @@ case $basic_machine in
basic_machine=i586-unknown
os=-pw32
;;
- rdos)
+ rdos | rdos64)
+ basic_machine=x86_64-pc
+ os=-rdos
+ ;;
+ rdos32)
basic_machine=i386-pc
os=-rdos
;;
@@ -953,6 +1094,9 @@ case $basic_machine in
basic_machine=i860-stratus
os=-sysv4
;;
+ strongarm-* | thumb-*)
+ basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
sun2)
basic_machine=m68000-sun
;;
@@ -1009,17 +1153,9 @@ case $basic_machine in
basic_machine=t90-cray
os=-unicos
;;
- tic54x | c54x*)
- basic_machine=tic54x-unknown
- os=-coff
- ;;
- tic55x | c55x*)
- basic_machine=tic55x-unknown
- os=-coff
- ;;
- tic6x | c6x*)
- basic_machine=tic6x-unknown
- os=-coff
+ tile*)
+ basic_machine=$basic_machine-unknown
+ os=-linux-gnu
;;
tx39)
basic_machine=mipstx39-unknown
@@ -1088,6 +1224,9 @@ case $basic_machine in
xps | xps100)
basic_machine=xps100-honeywell
;;
+ xscale-* | xscalee[bl]-*)
+ basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
+ ;;
ymp)
basic_machine=ymp-cray
os=-unicos
@@ -1096,6 +1235,10 @@ case $basic_machine in
basic_machine=z8k-unknown
os=-sim
;;
+ z80-*-coff)
+ basic_machine=z80-unknown
+ os=-sim
+ ;;
none)
basic_machine=none-none
os=-none
@@ -1134,7 +1277,7 @@ case $basic_machine in
we32k)
basic_machine=we32k-att
;;
- sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
+ sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
basic_machine=sh-unknown
;;
sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
@@ -1181,9 +1324,12 @@ esac
if [ x"$os" != x"" ]
then
case $os in
- # First match some system type aliases
- # that might get confused with valid system types.
+ # First match some system type aliases
+ # that might get confused with valid system types.
# -solaris* is a basic system type, with this one exception.
+ -auroraux)
+ os=-auroraux
+ ;;
-solaris1 | -solaris1.*)
os=`echo $os | sed -e 's|solaris1|sunos4|'`
;;
@@ -1204,21 +1350,23 @@ case $os in
# Each alternative MUST END IN A *, to match a version number.
# -sysv* is not here because it comes later, after sysvr4.
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
- | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
- | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
+ | -sym* | -kopensolaris* | -plan9* \
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
- | -aos* \
+ | -aos* | -aros* \
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
- | -openbsd* | -solidbsd* \
+ | -bitrig* | -openbsd* | -solidbsd* \
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
- | -chorusos* | -chorusrdb* \
- | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
- | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
+ | -chorusos* | -chorusrdb* | -cegcc* \
+ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
+ | -linux-newlib* | -linux-musl* | -linux-uclibc* \
| -uxpv* | -beos* | -mpeix* | -udk* \
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
@@ -1226,7 +1374,7 @@ case $os in
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
- | -skyos* | -haiku* | -rdos* | -toppers* | -drops*)
+ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-qnx*)
@@ -1265,7 +1413,7 @@ case $os in
-opened*)
os=-openedition
;;
- -os400*)
+ -os400*)
os=-os400
;;
-wince*)
@@ -1314,7 +1462,7 @@ case $os in
-sinix*)
os=-sysv4
;;
- -tpf*)
+ -tpf*)
os=-tpf
;;
-triton*)
@@ -1350,12 +1498,14 @@ case $os in
-aros*)
os=-aros
;;
- -kaos*)
- os=-kaos
- ;;
-zvmoe)
os=-zvmoe
;;
+ -dicos*)
+ os=-dicos
+ ;;
+ -nacl*)
+ ;;
-none)
;;
*)
@@ -1378,10 +1528,10 @@ else
# system, and we'll never get to this point.
case $basic_machine in
- score-*)
+ score-*)
os=-elf
;;
- spu-*)
+ spu-*)
os=-elf
;;
*-acorn)
@@ -1393,8 +1543,20 @@ case $basic_machine in
arm*-semi)
os=-aout
;;
- c4x-* | tic4x-*)
- os=-coff
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
+ hexagon-*)
+ os=-elf
+ ;;
+ tic54x-*)
+ os=-coff
+ ;;
+ tic55x-*)
+ os=-coff
+ ;;
+ tic6x-*)
+ os=-coff
;;
# This must come before the *-dec entry.
pdp10-*)
@@ -1414,14 +1576,11 @@ case $basic_machine in
;;
m68000-sun)
os=-sunos3
- # This also exists in the configure program, but was not the
- # default.
- # os=-sunos4
;;
m68*-cisco)
os=-aout
;;
- mep-*)
+ mep-*)
os=-elf
;;
mips*-cisco)
@@ -1430,6 +1589,9 @@ case $basic_machine in
mips*-*)
os=-elf
;;
+ or1k-*)
+ os=-elf
+ ;;
or32-*)
os=-coff
;;
@@ -1448,7 +1610,7 @@ case $basic_machine in
*-ibm)
os=-aix
;;
- *-knuth)
+ *-knuth)
os=-mmixware
;;
*-wec)
@@ -1553,7 +1715,7 @@ case $basic_machine in
-sunos*)
vendor=sun
;;
- -aix*)
+ -cnk*|-aix*)
vendor=ibm
;;
-beos*)
diff --git a/src/racket/configure.ac b/src/racket/configure.ac
index 3dd9c6d35d..ee390687cf 100644
--- a/src/racket/configure.ac
+++ b/src/racket/configure.ac
@@ -1242,7 +1242,7 @@ fi
############## drop optimization flags ################
if test "${enable_noopt}" = "yes" ; then
- AWKPRG='BEGIN { FS = "(^| )-O(0|1|2|3|4|5|6|7|8|9|())( |$)" } /.*/ { for (i = 1; i < NF; i++) printf "%s ", $i; print $NF }'
+ AWKPRG='BEGIN { FS = "(^| )-O(0|1|2|3|4|5|6|7|8|9)?( |$)" } /.*/ { for (i = 1; i < NF; i++) printf "%s ", $i; print $NF }'
CFLAGS=`echo "$CFLAGS" | awk "$AWKPRG"`
fi
diff --git a/src/racket/include/scheme.h b/src/racket/include/scheme.h
index c78800468b..3feb45ee3d 100644
--- a/src/racket/include/scheme.h
+++ b/src/racket/include/scheme.h
@@ -207,7 +207,7 @@ typedef struct FSSpec mzFSSpec;
#endif
#ifndef MZ_DONT_USE_JIT
-# if defined(MZ_USE_JIT_PPC) || defined(MZ_USE_JIT_I386) || defined(MZ_USE_JIT_X86_64)
+# if defined(MZ_USE_JIT_PPC) || defined(MZ_USE_JIT_I386) || defined(MZ_USE_JIT_X86_64) || defined(MZ_USE_JIT_ARM)
# define MZ_USE_JIT
# endif
#endif
diff --git a/src/racket/sconfig.h b/src/racket/sconfig.h
index 4792b83495..0b32ac28f5 100644
--- a/src/racket/sconfig.h
+++ b/src/racket/sconfig.h
@@ -156,39 +156,49 @@
#if defined(linux)
+# ifdef __ANDROID__
+# define SPLS_LINUX "android"
+# else
+# define SPLS_LINUX "linux"
+# endif
+
# if defined(i386)
-# define SCHEME_PLATFORM_LIBRARY_SUBPATH "i386-linux"
+# define SCHEME_PLATFORM_LIBRARY_SUBPATH "i386-" SPLS_LINUX
# define REGISTER_POOR_MACHINE
# define MZ_TRY_EXTFLONUMS
# define ASM_DBLPREC_CONTROL_87
# endif
# if defined(powerpc)
-# define SCHEME_PLATFORM_LIBRARY_SUBPATH "ppc-linux"
+# define SCHEME_PLATFORM_LIBRARY_SUBPATH "ppc-" SPLS_LINUX
# endif
# if defined(__mc68000__)
-# define SCHEME_PLATFORM_LIBRARY_SUBPATH "m68k-linux"
+# define SCHEME_PLATFORM_LIBRARY_SUBPATH "m68k-" SPLS_LINUX
# endif
# if defined(mips)
-# define SCHEME_PLATFORM_LIBRARY_SUBPATH "mips-linux"
+# define SCHEME_PLATFORM_LIBRARY_SUBPATH "mips-" SPLS_LINUX
# endif
# if defined(__alpha__)
-# define SCHEME_PLATFORM_LIBRARY_SUBPATH "alpha-linux"
+# define SCHEME_PLATFORM_LIBRARY_SUBPATH "alpha-" SPLS_LINUX
# endif
# if defined(__hppa__)
-# define SCHEME_PLATFORM_LIBRARY_SUBPATH "hppa-linux"
+# define SCHEME_PLATFORM_LIBRARY_SUBPATH "hppa-" SPLS_LINUX
# endif
# if defined(__sparc__)
-# define SCHEME_PLATFORM_LIBRARY_SUBPATH "sparc-linux"
+# define SCHEME_PLATFORM_LIBRARY_SUBPATH "sparc-" SPLS_LINUX
# define FLUSH_SPARC_REGISTER_WINDOWS
# endif
+# if defined(__arm__) || defined(__thumb__)
+# define SCHEME_PLATFORM_LIBRARY_SUBPATH "arm-" SPLS_LINUX
+# define FFI_CALLBACK_NEED_INT_CLEAR
+# endif
# if defined(__x86_64__)
-# define SCHEME_PLATFORM_LIBRARY_SUBPATH "x86_64-linux"
+# define SCHEME_PLATFORM_LIBRARY_SUBPATH "x86_64-" SPLS_LINUX
# define REGISTER_POOR_MACHINE
# define ASM_DBLPREC_CONTROL_87
# define MZ_TRY_EXTFLONUMS
# endif
# ifndef SCHEME_PLATFORM_LIBRARY_SUBPATH
-# define SCHEME_PLATFORM_LIBRARY_SUBPATH "unknown-linux"
+# define SCHEME_PLATFORM_LIBRARY_SUBPATH "unknown-" SPLS_LINUX
# endif
# include "uconfig.h"
@@ -215,6 +225,10 @@
# define MZ_TCP_LISTEN_IPV6_ONLY_SOCKOPT
+# ifdef __ANDROID__
+# define USE_FCNTL_O_NONBLOCK
+# endif
+
# define FLAGS_ALREADY_SET
#if defined(i386)
@@ -229,6 +243,10 @@
#if defined(powerpc)
# define MZ_USE_JIT_PPC
#endif
+# if defined(__arm__)
+# define MZ_USE_JIT_ARM
+# define MZ_USE_DWARF_LIBUNWIND
+#endif
#endif
@@ -1655,6 +1673,10 @@
/* WIN32S_HACK uses a special hack to implement threads under Win32s
with some compilers. Obsolete. */
+ /* FFI_CALLBACK_NEED_INT_CLEAR indiates thet libffi callback results
+ that are smaller than an `int' should clear `int'-sized space
+ in the result area. */
+
#endif /* FLAGS_ALREADY_SET */
/****** (END CONFIGURATION FLAG DESCRPTIONS AND DEFAULTS) *******/
diff --git a/src/racket/src/Makefile.in b/src/racket/src/Makefile.in
index a857662b09..718ea684d1 100644
--- a/src/racket/src/Makefile.in
+++ b/src/racket/src/Makefile.in
@@ -305,6 +305,11 @@ JIT_HEADERS = $(srcdir)/jit.h $(srcdir)/jitfpu.h $(srcdir)/stypes.h \
$(srcdir)/lightning/ppc/asm.h $(srcdir)/lightning/ppc/asm-common.h \
$(srcdir)/lightning/ppc/funcs.h $(srcdir)/lightning/ppc/funcs-common.h \
$(srcdir)/lightning/ppc/fp.h $(srcdir)/lightning/ppc/fp-common.h \
+ $(srcdir)/lightning/arm/core.h $(srcdir)/lightning/arm/core-common.h \
+ $(srcdir)/lightning/arm/asm.h $(srcdir)/lightning/arm/asm-common.h \
+ $(srcdir)/lightning/arm/funcs.h $(srcdir)/lightning/arm/funcs-common.h \
+ $(srcdir)/lightning/arm/fp.h $(srcdir)/lightning/arm/fp-common.h \
+ $(srcdir)/lightning/arm/fp-vfp.h $(srcdir)/lightning/arm/fp-swf.h \
$(srcdir)/future.h $(srcdir)/jit_ts.c $(srcdir)/jit_ts_protos.h
salloc.@LTO@: $(COMMON_HEADERS) \
diff --git a/src/racket/src/jit.c b/src/racket/src/jit.c
index e2d5ca49f0..548b6d85ff 100644
--- a/src/racket/src/jit.c
+++ b/src/racket/src/jit.c
@@ -933,7 +933,7 @@ static void patch_branch_addr(mz_jit_state *jitter, Branch_Info_Addr *addr, int
} else if (addr[i].kind == BRANCH_ADDR_UCBRANCH) {
mz_patch_ucbranch(addr[i].addr);
} else {
- jit_patch_movi(addr[i].addr, (_jit.x.pc));
+ jit_patch_movi(addr[i].addr, jit_get_ip());
}
}
@@ -972,7 +972,7 @@ void scheme_add_or_patch_branch_true_movi(mz_jit_state *jitter, Branch_Info *for
if (for_branch->true_needs_jump) {
add_branch(for_branch, ref, BRANCH_ADDR_TRUE, BRANCH_ADDR_MOVI);
} else {
- jit_patch_movi(ref, (_jit.x.pc));
+ jit_patch_movi(ref, jit_get_ip());
}
}
@@ -2353,7 +2353,7 @@ int scheme_generate(Scheme_Object *obj, mz_jit_state *jitter, int is_tail, int w
CHECK_RUNSTACK_OVERFLOW();
/* Copy args: */
jit_ldxi_l(JIT_R1, JIT_R1, &((Scheme_Thread *)0x0)->ku.multiple.array);
- refloop = _jit.x.pc;
+ refloop = jit_get_ip();
ref3 = jit_blei_l(jit_forward(), JIT_R2, 0);
jit_subi_l(JIT_R2, JIT_R2, JIT_WORD_SIZE);
jit_ldxr_p(JIT_R0, JIT_R1, JIT_R2);
@@ -2983,6 +2983,8 @@ int scheme_generate(Scheme_Object *obj, mz_jit_state *jitter, int is_tail, int w
__END_TINY_JUMPS__(1);
}
+ CHECK_LIMIT();
+
/* Key and value are (still) on runstack */
if (!wcm_may_replace) {
(void)jit_calli(sjc.wcm_nontail_code);
@@ -3020,8 +3022,8 @@ int scheme_generate(Scheme_Object *obj, mz_jit_state *jitter, int is_tail, int w
mz_rs_sync();
jit_movi_i(JIT_R0, WORDS_TO_BYTES(c));
- jit_movi_i(JIT_R1, &(((Scheme_Prefix *)0x0)->a[i + p + 1]));
- jit_movi_i(JIT_R2, &(((Scheme_Prefix *)0x0)->a[p]));
+ jit_movi_i(JIT_R1, (int)&(((Scheme_Prefix *)0x0)->a[i + p + 1]));
+ jit_movi_i(JIT_R2, (int)&(((Scheme_Prefix *)0x0)->a[p]));
(void)jit_calli(sjc.quote_syntax_code);
CHECK_LIMIT();
@@ -3232,6 +3234,9 @@ typedef struct {
Scheme_Native_Closure *nc;
int argc, argv_delta;
Scheme_Object **argv;
+#ifdef NEED_RETAIN_CODE_POINTERS
+ void *retain_code;
+#endif
} Generate_Closure_Data;
static int do_generate_closure(mz_jit_state *jitter, void *_data)
@@ -3239,10 +3244,13 @@ static int do_generate_closure(mz_jit_state *jitter, void *_data)
Generate_Closure_Data *gdata = (Generate_Closure_Data *)_data;
Scheme_Closure_Data *data = gdata->data;
void *start_code, *tail_code, *code_end, *arity_code;
+#ifdef NEED_RETAIN_CODE_POINTERS
+ void *retain_code = NULL;
+#endif
int i, r, cnt, has_rest, is_method, num_params, to_args, argc, argv_delta;
Scheme_Object **argv;
- start_code = jit_get_ip().ptr;
+ start_code = jit_get_ip();
jitter->nc = gdata->nc;
@@ -3278,23 +3286,30 @@ static int do_generate_closure(mz_jit_state *jitter, void *_data)
shared_arity_code = sjc.shared_arity_check[num_params][has_rest][is_method];
if (!shared_arity_code) {
shared_arity_code = generate_lambda_simple_arity_check(num_params, has_rest, is_method, 1);
+ shared_arity_code = jit_adjust_ip(shared_arity_code);
sjc.shared_arity_check[num_params][has_rest][is_method] = shared_arity_code;
}
- arity_code = jit_get_ip().ptr;
+ arity_code = jit_get_ip();
if (!has_rest)
(void)jit_bnei_i(shared_arity_code, JIT_R1, num_params);
else
(void)jit_blti_i(shared_arity_code, JIT_R1, num_params);
- } else
+ } else {
arity_code = generate_lambda_simple_arity_check(num_params, has_rest, is_method, 0);
+#ifdef NEED_RETAIN_CODE_POINTERS
+ retain_code = MALLOC_N(void*,2);
+ ((void **)retain_code)[1] = arity_code;
+#endif
+ arity_code = jit_adjust_ip(arity_code);
+ }
/* A tail call starts here. Caller must ensure that the stack is big
enough, right number of arguments (at start of runstack), closure
is in R0. If the closure has a rest arg, also ensure argc in R1
and argv in R2. */
- tail_code = jit_get_ip().ptr;
+ tail_code = jit_get_ip();
/* 0 params and has_rest => (lambda args E) where args is not in E,
so accept any number of arguments and just clear them (for space
@@ -3558,7 +3573,7 @@ static int do_generate_closure(mz_jit_state *jitter, void *_data)
jitter->self_data = data;
- jitter->self_restart_code = jit_get_ip().ptr;
+ jitter->self_restart_code = jit_get_ip();
jitter->self_restart_space = jitter->flostack_space;
jitter->self_restart_offset = jitter->flostack_offset;
if (!has_rest)
@@ -3586,7 +3601,7 @@ static int do_generate_closure(mz_jit_state *jitter, void *_data)
jit_ret();
}
- code_end = jit_get_ip().ptr;
+ code_end = jit_get_ip();
if (jitter->retain_start) {
gdata->arity_code = arity_code;
@@ -3597,6 +3612,13 @@ static int do_generate_closure(mz_jit_state *jitter, void *_data)
gdata->max_tail_depth = jitter->max_tail_depth;
gdata->code_end = code_end;
gdata->patch_depth = jitter->patch_depth;
+#ifdef NEED_RETAIN_CODE_POINTERS
+ if (retain_code)
+ ((void **)retain_code)[0] = jit_unadjust_ip(start_code);
+ else
+ retain_code = jit_unadjust_ip(start_code);
+ gdata->retain_code = retain_code;
+#endif
}
return 1;
@@ -3644,10 +3666,14 @@ static void on_demand_generate_lambda(Scheme_Native_Closure *nc, int argc, Schem
tail_code = gdata.tail_code;
if (data->name) {
- scheme_jit_add_symbol((uintptr_t)start_code, (uintptr_t)gdata.code_end - 1, data->name, 1);
+ scheme_jit_add_symbol((uintptr_t)jit_unadjust_ip(start_code),
+ (uintptr_t)jit_unadjust_ip(gdata.code_end) - 1,
+ data->name, 1);
} else {
#ifdef MZ_USE_DWARF_LIBUNWIND
- scheme_jit_add_symbol((uintptr_t)start_code, (uintptr_t)gdata.code_end - 1, scheme_null, 1);
+ scheme_jit_add_symbol((uintptr_t)jit_unadjust_ip(start_code),
+ (uintptr_t)jit_unadjust_ip(gdata.code_end) - 1,
+ scheme_null, 1);
#endif
}
@@ -3682,6 +3708,9 @@ static void on_demand_generate_lambda(Scheme_Native_Closure *nc, int argc, Schem
ndata->u2.name = data->name;
/* Let-depth is in bytes instead of words: */
ndata->max_let_depth = max_depth;
+#ifdef NEED_RETAIN_CODE_POINTERS
+ ndata->retain_code = gdata.retain_code;
+#endif
}
void scheme_on_demand_generate_lambda(Scheme_Native_Closure *nc, int argc, Scheme_Object **argv, int argv_delta)
@@ -3948,17 +3977,20 @@ static int do_generate_case_lambda_dispatch(mz_jit_state *jitter, void *_data)
Generate_Case_Dispatch_Data *data = (Generate_Case_Dispatch_Data *)_data;
void *start_code, *arity_code;
- start_code = jit_get_ip().ptr;
+ start_code = jit_get_ip();
generate_function_prolog(jitter, start_code, data->ndata->max_let_depth);
CHECK_LIMIT();
if (generate_case_lambda_dispatch(jitter, data->c, data->ndata, 1)) {
- arity_code = jit_get_ip().ptr;
+ arity_code = jit_get_ip();
if (generate_case_lambda_dispatch(jitter, data->c, data->ndata, 0)) {
data->ndata->start_code = start_code;
data->ndata->arity_code = arity_code;
-
+#ifdef NEED_RETAIN_CODE_POINTERS
+ data->ndata->retain_code = jit_unadjust_ip(start_code);
+#endif
+
return 1;
}
}
diff --git a/src/racket/src/jit.h b/src/racket/src/jit.h
index e091d00d62..ce5e168066 100644
--- a/src/racket/src/jit.h
+++ b/src/racket/src/jit.h
@@ -67,9 +67,6 @@ END_XFORM_ARITH;
#endif
#ifdef MZ_USE_JIT_PPC
-# ifndef DEFINE_LIGHTNING_FUNCS
-# define SUPPRESS_LIGHTNING_FUNCS
-# endif
# define DEFINE_LIGHTNING_FUNCS_STATIC /* empty */
# define jit_notify_freed_code scheme_jit_notify_freed_code
# define jit_flush_code scheme_jit_flush_code
@@ -77,8 +74,13 @@ END_XFORM_ARITH;
# define _jit_epilog scheme_jit_epilog
#endif
+#ifndef DEFINE_LIGHTNING_FUNCS
+# define SUPPRESS_LIGHTNING_FUNCS
+#endif
+
#include "lightning/lightning.h"
#define _jit (jitter->js)
+#define _jitp (&_jit)
#ifdef MZ_USE_JIT_X86_64
# define JIT_LOG_WORD_SIZE 3
@@ -128,20 +130,25 @@ END_XFORM_ARITH;
#if defined(MZ_USE_JIT_I386) && !defined(MZ_USE_JIT_X86_64)
# define USE_TINY_JUMPS
#endif
+#if defined(MZ_USE_JIT_ARM)
+/* For ARM, long jumps are needed for jumps longer than 2^23: */
+# define NEED_LONG_JUMPS
+# define LONG_JUMPS_DEFAULT(x) 1
+#endif
-#if defined(MZ_PRECISE_GC) && defined(MZ_USE_JIT_I386)
-# define USE_FLONUM_UNBOXING
+#if defined(MZ_PRECISE_GC)
+# if defined(MZ_USE_JIT_I386)
+# define USE_FLONUM_UNBOXING
+# endif
+# if defined(MZ_USE_JIT_ARM) && defined(__ARM_PCS_VFP)
+# define USE_FLONUM_UNBOXING
+# endif
#endif
#ifdef MZ_USE_FUTURES
# define MZ_USE_LWC
#endif
-#define JIT_NOT_RET JIT_R1
-#if JIT_NOT_RET == JIT_RET
-Fix me! See use.
-#endif
-
#ifdef MZ_USE_SINGLE_FLOATS
# define SCHEME_FLOAT_TYPE scheme_float_type
#else
@@ -177,12 +184,12 @@ static void assert_failure(int where) { printf("JIT assert failed %d\n", where);
extern int jit_sizes[NUM_CATEGORIES];
extern int jit_counts[NUM_CATEGORIES];
extern int jit_code_size;
-# define START_JIT_DATA() void *__pos = jit_get_ip().ptr; uintptr_t __total = 0
+# define START_JIT_DATA() void *__pos = jit_get_ip(); uintptr_t __total = 0
# define END_JIT_DATA(where) if (jitter->retain_start) { \
- jit_sizes[where] += __total + ((uintptr_t)jit_get_ip().ptr - (uintptr_t)__pos); \
+ jit_sizes[where] += __total + ((uintptr_t)jit_get_ip() - (uintptr_t)__pos); \
jit_counts[where]++; }
-# define PAUSE_JIT_DATA() __total += ((uintptr_t)jit_get_ip().ptr - (uintptr_t)__pos)
-# define RESUME_JIT_DATA() __pos = jit_get_ip().ptr
+# define PAUSE_JIT_DATA() __total += ((uintptr_t)jit_get_ip() - (uintptr_t)__pos)
+# define RESUME_JIT_DATA() __pos = jit_get_ip()
# define RECORD_CODE_SIZE(s) jit_code_size += s
#else
# define START_JIT_DATA() /* empty */
@@ -555,8 +562,8 @@ void *scheme_jit_get_threadlocal_table();
# define tl_scheme_jit_save_extfp (&scheme_jit_save_extfp)
# define tl_scheme_jit_save_extfp2 (&scheme_jit_save_extfp2)
# endif
-# define tl_scheme_fuel_counter (&scheme_fuel_counter)
-# define tl_scheme_jit_stack_boundary (&scheme_jit_stack_boundary)
+# define tl_scheme_fuel_counter ((void *)&scheme_fuel_counter)
+# define tl_scheme_jit_stack_boundary ((void *)&scheme_jit_stack_boundary)
#endif
/*========================================================================*/
@@ -709,6 +716,8 @@ int check_location;
is one word past alignment. Push 1 to realign (but
mz_push_locals() pushes 3, because we need at least
two locals).
+ - On ARM, the stack should be 8-byte aligned, and
+ jit_prolog() leaves the stack in an aligned state.
*/
/* LOCAL1 is used to save the value current_cont_mark_stack,
@@ -740,7 +749,7 @@ int check_location;
* On some platforms, a lightweight function created with
mz_prolog() and mz_epilog() uses LOCAL2 to save the return
- address. On those platforms, though, LOCAL3 is dufferent from
+ address. On those platforms, though, LOCAL3 is different from
LOCAL2. So, LOCAL3 can always be used for temporary storage in
such functions (assuming that they're called from a function that
pushes locals, and that nothing else is using LOCAL2).
@@ -773,7 +782,8 @@ int check_location;
#define mz_set_local_p(x, l) mz_set_local_p_x(x, l, JIT_FP)
#define mz_get_local_p(x, l) mz_get_local_p_x(x, l, JIT_FP)
-#ifdef MZ_USE_JIT_PPC
+/* --- PPC --- */
+#if defined(MZ_USE_JIT_PPC)
/* JIT_LOCAL1, JIT_LOCAL2, and JIT_LOCAL3 are offsets in the stack frame. */
# define JIT_LOCAL1 56
# define JIT_LOCAL2 60
@@ -821,7 +831,40 @@ void scheme_jit_prolog_again(mz_jit_state *jitter, int n, int ret_addr_reg)
}
# endif
# define _jit_prolog_again scheme_jit_prolog_again
-#else
+#endif
+
+/* --- ARM --- */
+#ifdef MZ_USE_JIT_ARM
+# define JIT_LOCAL1 JIT_FRAME_EXTRA_SPACE_OFFSET
+# define JIT_LOCAL2 (JIT_FRAME_EXTRA_SPACE_OFFSET+4)
+# define JIT_LOCAL3 (JIT_FRAME_EXTRA_SPACE_OFFSET+8)
+# define JIT_LOCAL4 (JIT_FRAME_EXTRA_SPACE_OFFSET+12)
+# define JIT_FRAME_FLOSTACK_OFFSET JIT_FRAME_EXTRA_SPACE_OFFSET
+# define mz_set_local_p_x(x, l, FP) jit_stxi_p(l, FP, x)
+# define mz_get_local_p_x(x, l, FP) jit_ldxi_p(x, FP, l)
+# define mz_patch_branch_at(a, v) jit_patch_at(a, v)
+# define mz_patch_ucbranch_at(a, v) jit_patch_at(a, v)
+# define mz_prolog(x) (mz_set_local_p(JIT_LR, JIT_LOCAL2))
+# define mz_epilog(x) (mz_get_local_p(x, JIT_LOCAL2), jit_jmpr(x))
+# define mz_epilog_without_jmp() /* empty */
+# define jit_shuffle_saved_regs() /* empty */
+# define jit_unshuffle_saved_regs() /* empty */
+# define mz_push_locals() /* empty */
+# define mz_pop_locals() /* empty */
+# ifdef SUPPRESS_LIGHTNING_FUNCS
+void scheme_jit_prolog_again(mz_jit_state *jitter, int n, int ret_addr_reg);
+# else
+void scheme_jit_prolog_again(mz_jit_state *jitter, int n, int ret_addr_reg)
+{
+ jit_movr_p(JIT_LR, ret_addr_reg);
+ arm_prolog(_jitp, n);
+}
+# endif
+# define _jit_prolog_again scheme_jit_prolog_again
+#endif
+
+/* --- x86[_64] --- */
+#if defined(JIT_X86_64) || defined(JIT_X86_PLAIN)
/* From frame pointer, -1 is saved frame pointer, -2 is saved ESI/R12,
and -3 is saved EDI/R13. On entry to a procedure, prolog pushes 4
since the call (which also pushed), so if the stack was 16-bytes
@@ -934,8 +977,8 @@ static jit_insn *fp_tmpr;
# define mz_st_fppop_x(i, r, FP, extfl) (check_fp_depth(i, FP), (void)jit_FPSEL_stxi_xd_fppop(extfl, (JIT_FRAME_FLOSTACK_OFFSET - (i)), FP, r))
# define mz_st_fppop(i, r, extfl) mz_st_fppop_x(i, r, JIT_FP, extfl)
-#define mz_patch_branch(a) mz_patch_branch_at(a, (_jit.x.pc))
-#define mz_patch_ucbranch(a) mz_patch_ucbranch_at(a, (_jit.x.pc))
+#define mz_patch_branch(a) mz_patch_branch_at(a, jit_get_ip())
+#define mz_patch_ucbranch(a) mz_patch_ucbranch_at(a, jit_get_ip())
#ifdef NEED_LONG_JUMPS
# define __START_SHORT_JUMPS__(cond) if (cond) { _jitl.long_jumps = 0; }
@@ -1233,14 +1276,14 @@ static void emit_indentation(mz_jit_state *jitter)
# define JIT_BUFFER_PAD_SIZE 100
#endif
-#define PAST_LIMIT() ((uintptr_t)jit_get_ip().ptr > (uintptr_t)jitter->limit)
+#define PAST_LIMIT() ((uintptr_t)jit_get_raw_ip() > (uintptr_t)jitter->limit)
#define CHECK_LIMIT() if (PAST_LIMIT()) return past_limit(jitter, __FILE__, __LINE__);
#if 1
# define past_limit(j, f, l) 0
#else
static int past_limit(mz_jit_state *jitter, const char *file, int line)
{
- if (((uintptr_t)jit_get_ip().ptr > (uintptr_t)jitter->limit + JIT_BUFFER_PAD_SIZE)
+ if (((uintptr_t)jit_get_raw_ip() > (uintptr_t)jitter->limit + JIT_BUFFER_PAD_SIZE)
|| (jitter->retain_start)) {
printf("way past %s %d\n", file, line); abort();
}
diff --git a/src/racket/src/jitalloc.c b/src/racket/src/jitalloc.c
index e780092eee..a4bb75c43f 100644
--- a/src/racket/src/jitalloc.c
+++ b/src/racket/src/jitalloc.c
@@ -132,7 +132,7 @@ int scheme_inline_alloc(mz_jit_state *jitter, int amt, Scheme_Type ty, int flags
algn = GC_alloc_alignment();
__START_TINY_JUMPS__(1);
- reffail = _jit.x.pc;
+ reffail = jit_get_ip();
mz_tl_ldi_p(JIT_V1, tl_GC_gen0_alloc_page_ptr);
jit_subi_l(JIT_R2, JIT_V1, 1);
jit_andi_l(JIT_R2, JIT_R2, (algn - 1));
@@ -141,21 +141,30 @@ int scheme_inline_alloc(mz_jit_state *jitter, int amt, Scheme_Type ty, int flags
__END_TINY_JUMPS__(1);
/* Failure handling */
- if (keep_r0_r1) {
- if (inline_retry) {
- scheme_generate_alloc_retry(jitter, 1);
- CHECK_LIMIT();
- } else {
- (void)jit_calli(sjc.retry_alloc_code_keep_r0_r1);
- }
- } else if (keep_fpr1) {
- (void)jit_calli(sjc.retry_alloc_code_keep_fpr1);
-#ifdef MZ_LONG_DOUBLE
- } else if (keep_extfpr1) {
- (void)jit_calli(sjc.retry_alloc_code_keep_extfpr1);
-#endif
+ if (inline_retry) {
+ int mode;
+ if (keep_r0_r1)
+ mode = 1;
+ else if (keep_fpr1)
+ mode = 2;
+ else if (keep_extfpr1)
+ mode = 3;
+ else
+ mode = 0;
+ scheme_generate_alloc_retry(jitter, mode);
+ CHECK_LIMIT();
} else {
- (void)jit_calli(sjc.retry_alloc_code);
+ if (keep_r0_r1) {
+ (void)jit_calli(sjc.retry_alloc_code_keep_r0_r1);
+ } else if (keep_fpr1) {
+ (void)jit_calli(sjc.retry_alloc_code_keep_fpr1);
+#ifdef MZ_LONG_DOUBLE
+ } else if (keep_extfpr1) {
+ (void)jit_calli(sjc.retry_alloc_code_keep_extfpr1);
+#endif
+ } else {
+ (void)jit_calli(sjc.retry_alloc_code);
+ }
}
__START_TINY_JUMPS__(1);
(void)jit_jmpi(reffail);
diff --git a/src/racket/src/jitarith.c b/src/racket/src/jitarith.c
index d8d3d38ce7..2bd7486f76 100644
--- a/src/racket/src/jitarith.c
+++ b/src/racket/src/jitarith.c
@@ -364,7 +364,7 @@ static jit_insn *generate_arith_slow_path(mz_jit_state *jitter, Scheme_Object *r
{
GC_CAN_IGNORE jit_insn *ref, *ref4, *refslow;
- refslow = _jit.x.pc;
+ refslow = jit_get_ip();
(void)jit_movi_p(JIT_R2, ((Scheme_Primitive_Proc *)rator)->prim_val);
if (for_branch) {
@@ -417,7 +417,7 @@ static jit_insn *generate_arith_slow_path(mz_jit_state *jitter, Scheme_Object *r
if (arith == ARITH_LSH) {
/* Add tag back to first arg, just in case. See arithmetic-shift branch to refslow. */
- ref = _jit.x.pc;
+ ref = jit_get_ip();
if (reversed || use_v) {
jit_ori_l(JIT_R0, JIT_R0, 0x1);
@@ -700,6 +700,8 @@ static int generate_float_point_arith(mz_jit_state *jitter, Scheme_Object *rator
}
#endif
+ CHECK_LIMIT();
+
if (arith) {
#if defined(MZ_LONG_DOUBLE) && defined(MZ_NEED_SET_EXTFL_MODE)
int need_control_reset = 0;
@@ -766,6 +768,7 @@ static int generate_float_point_arith(mz_jit_state *jitter, Scheme_Object *rator
refc = jit_FPSEL_bger_xd_fppop(extfl, jit_forward(), fpr0, fpr1);
}
}
+ CHECK_LIMIT();
if (unboxed) {
jit_FPSEL_movr_xd_rel(extfl, fpr0, fpr1);
need_post_pop = 1;
@@ -800,8 +803,10 @@ static int generate_float_point_arith(mz_jit_state *jitter, Scheme_Object *rator
/* to check whether it fits in a fixnum, we
need to convert back and check whether it
is the same */
- if (unboxed)
- jit_FPSEL_movr_xd_fppush(extfl, fpr1+1, fpr1); /* for slow path */
+ if (unboxed) {
+ JIT_ASSERT(jitter->unbox_depth == 0);
+ jit_FPSEL_movr_xd_fppush(extfl, JIT_FPR2, fpr1); /* for slow path */
+ }
jit_FPSEL_extr_l_xd_fppush(extfl, fpr0, JIT_R1);
__START_TINY_JUMPS__(1);
refs = jit_FPSEL_bantieqr_xd_fppop(extfl, jit_forward(), fpr0, fpr1);
@@ -814,7 +819,7 @@ static int generate_float_point_arith(mz_jit_state *jitter, Scheme_Object *rator
__END_TINY_JUMPS__(1);
#if !defined(DIRECT_FPR_ACCESS) || defined(MZ_LONG_DOUBLE)
if (unboxed && !USES_DIRECT_FPR_ACCESS)
- jit_FPSEL_roundr_xd_l_fppop(extfl, JIT_R1, fpr1+1); /* slow path won't be needed */
+ jit_FPSEL_roundr_xd_l_fppop(extfl, JIT_R1, JIT_FPR2); /* slow path won't be needed */
#endif
}
jit_fixnum_l(dest, JIT_R1);
@@ -1037,7 +1042,7 @@ static int check_float_type_result(mz_jit_state *jitter, int reg, void *fail_cod
ref = jit_bmci_l(jit_forward(), reg, 0x1);
__END_TINY_JUMPS__(1);
- reffail = _jit.x.pc;
+ reffail = jit_get_ip();
(void)jit_movi_p(JIT_V1, ((Scheme_Primitive_Proc *)rator)->prim_val);
(void)jit_calli(fail_code);
@@ -1645,7 +1650,7 @@ int scheme_generate_arith_for(mz_jit_state *jitter, Scheme_Object *rator, Scheme
if (!unsafe_fx || overflow_refslow) {
GC_CAN_IGNORE jit_insn *refx;
__START_INNER_TINY__(branch_short);
- refx = jit_bnei_l(jit_forward(), JIT_R0, (void *)(((intptr_t)1 << ((8 * JIT_WORD_SIZE) - 2))));
+ refx = jit_bnei_p(jit_forward(), JIT_R0, (void *)(((intptr_t)1 << ((8 * JIT_WORD_SIZE) - 2))));
__END_INNER_TINY__(branch_short);
/* first argument must have been most negative fixnum,
second argument must have been -1: */
@@ -1688,11 +1693,11 @@ int scheme_generate_arith_for(mz_jit_state *jitter, Scheme_Object *rator, Scheme
if (!unsafe_fx || overflow_refslow) {
/* check for a small enough shift */
if (arith == ARITH_RSH) {
- (void)jit_blti_l(refslow, v2, scheme_make_integer(0));
- (void)jit_bgti_l(refslow, v2, scheme_make_integer(MAX_TRY_SHIFT));
+ (void)jit_blti_p(refslow, v2, scheme_make_integer(0));
+ (void)jit_bgti_p(refslow, v2, scheme_make_integer(MAX_TRY_SHIFT));
jit_rshi_l(JIT_V1, v2, 0x1);
} else {
- (void)jit_blti_l(refslow, v2, scheme_make_integer(-MAX_TRY_SHIFT));
+ (void)jit_blti_p(refslow, v2, scheme_make_integer(-MAX_TRY_SHIFT));
jit_notr_l(JIT_V1, v2);
jit_rshi_l(JIT_V1, JIT_V1, 0x1);
jit_addi_l(JIT_V1, JIT_V1, 0x1);
@@ -2228,7 +2233,7 @@ int scheme_generate_nary_arith(mz_jit_state *jitter, Scheme_App_Rec *app,
mz_patch_branch(reffx);
}
- refslow = _jit.x.pc;
+ refslow = jit_get_ip();
/* slow path */
if (alt_args) {
/* get all args on runstack */
@@ -2251,7 +2256,7 @@ int scheme_generate_nary_arith(mz_jit_state *jitter, Scheme_App_Rec *app,
}
refdone = jit_jmpi(jit_forward());
if (!arith) {
- reffalse = _jit.x.pc;
+ reffalse = jit_get_ip();
(void)jit_movi_p(JIT_R0, scheme_false);
refdone3 = jit_jmpi(jit_forward());
} else {
diff --git a/src/racket/src/jitcall.c b/src/racket/src/jitcall.c
index 92255b5184..9a1e8118a8 100644
--- a/src/racket/src/jitcall.c
+++ b/src/racket/src/jitcall.c
@@ -355,7 +355,7 @@ int scheme_generate_tail_call(mz_jit_state *jitter, int num_rands, int direct_na
ref = ref2 = NULL;
}
- refagain = _jit.x.pc;
+ refagain = jit_get_ip();
/* Right kind of function. Extract data and check stack depth: */
if (!direct_to_code) {
@@ -644,7 +644,7 @@ static int generate_retry_call(mz_jit_state *jitter, int num_rands, int multi_ok
jit_ldxi_p(JIT_V1, JIT_R1, &((Scheme_Thread *)0x0)->ku.apply.tail_rands);
jit_lshi_l(JIT_R2, JIT_R2, JIT_LOG_WORD_SIZE);
CHECK_LIMIT();
- refloop = _jit.x.pc;
+ refloop = jit_get_ip();
ref2 = jit_blei_l(jit_forward(), JIT_R2, 0);
jit_subi_l(JIT_R2, JIT_R2, JIT_WORD_SIZE);
jit_ldxr_p(JIT_R0, JIT_V1, JIT_R2);
@@ -667,7 +667,7 @@ static int generate_retry_call(mz_jit_state *jitter, int num_rands, int multi_ok
/* Slow path; restore R0 to SCHEME_TAIL_CALL_WAITING */
mz_patch_branch(ref);
- jit_movi_l(JIT_R0, SCHEME_TAIL_CALL_WAITING);
+ jit_movi_p(JIT_R0, SCHEME_TAIL_CALL_WAITING);
return 1;
}
@@ -741,7 +741,7 @@ int scheme_generate_non_tail_call(mz_jit_state *jitter, int num_rands, int direc
if (num_rands != -1) {
mz_prolog(JIT_R1);
} else {
- reftop = _jit.x.pc;
+ reftop = jit_get_ip();
}
}
@@ -756,7 +756,7 @@ int scheme_generate_non_tail_call(mz_jit_state *jitter, int num_rands, int direc
ref = ref2 = NULL;
}
- refagain = _jit.x.pc;
+ refagain = jit_get_ip();
/* Before inlined native, check max let depth */
if (!nontail_self) {
@@ -801,7 +801,7 @@ int scheme_generate_non_tail_call(mz_jit_state *jitter, int num_rands, int direc
/* keep call & ret paired by jumping to where we really
want to return,then back here: */
refr = jit_jmpi(jit_forward());
- refxr = _jit.x.pc;
+ refxr = jit_get_ip();
jit_base_prolog();
#else
refr = jit_patchable_movi_p(JIT_R1, jit_forward());
@@ -837,7 +837,7 @@ int scheme_generate_non_tail_call(mz_jit_state *jitter, int num_rands, int direc
GC_CAN_IGNORE jit_insn *refrr;
refrr = jit_patchable_movi_p(JIT_R1, jit_forward());
jit_jmpr(JIT_V1);
- jit_patch_movi(refrr, _jit.x.pc);
+ jit_patch_movi(refrr, jit_get_ip());
jit_movi_i(JIT_R1, num_rands); /* argc */
jit_movr_p(JIT_R2, JIT_RUNSTACK); /* argv */
}
@@ -861,7 +861,7 @@ int scheme_generate_non_tail_call(mz_jit_state *jitter, int num_rands, int direc
mz_patch_ucbranch(refr);
(void)jit_short_calli(refxr);
#else
- jit_patch_movi(refr, (_jit.x.pc));
+ jit_patch_movi(refr, jit_get_ip());
#endif
jit_unshuffle_saved_regs(); /* maybe uncopies V registers */
/* If num_rands < 0, then V1 has argc */
@@ -1093,7 +1093,7 @@ static int generate_self_tail_call(Scheme_Object *rator, mz_jit_state *jitter, i
__START_TINY_OR_SHORT_JUMPS__(jmp_tiny, jmp_short);
- refagain = _jit.x.pc;
+ refagain = jit_get_ip();
/* Check for thread swap: */
(void)mz_tl_ldi_i(JIT_R2, tl_scheme_fuel_counter);
@@ -1210,7 +1210,7 @@ static int generate_self_tail_call(Scheme_Object *rator, mz_jit_state *jitter, i
iref = NULL;
jit_movi_l(JIT_R0, aoffset);
mz_rs_sync();
- MZ_FPUSEL_STMT(extfl,
+ MZ_FPUSEL_STMT(extfl,
(void)jit_calli(sjc.box_extflonum_from_stack_code),
(void)jit_calli(sjc.box_flonum_from_stack_code));
if (i != num_rands - 1)
@@ -1313,9 +1313,11 @@ void scheme_jit_register_sub_func(mz_jit_state *jitter, void *code, Scheme_Objec
{
void *code_end;
- code_end = jit_get_ip().ptr;
+ code_end = jit_get_ip();
if (jitter->retain_start)
- scheme_jit_add_symbol((uintptr_t)code, (uintptr_t)code_end - 1, protocol, 0);
+ scheme_jit_add_symbol((uintptr_t)jit_unadjust_ip(code),
+ (uintptr_t)jit_unadjust_ip(code_end) - 1,
+ protocol, 0);
}
void scheme_jit_register_helper_func(mz_jit_state *jitter, void *code)
@@ -1339,7 +1341,7 @@ static int do_generate_shared_call(mz_jit_state *jitter, void *_data)
int ok;
void *code;
- code = jit_get_ip().ptr;
+ code = jit_get_ip();
if (data->direct_prim)
ok = generate_direct_prim_tail_call(jitter, data->num_rands);
@@ -1354,7 +1356,7 @@ static int do_generate_shared_call(mz_jit_state *jitter, void *_data)
int ok;
void *code;
- code = jit_get_ip().ptr;
+ code = jit_get_ip();
if (data->direct_prim)
ok = generate_direct_prim_non_tail_call(jitter, data->num_rands, data->multi_ok, 1);
@@ -1374,6 +1376,7 @@ void *scheme_generate_shared_call(int num_rands, mz_jit_state *old_jitter, int m
int unboxed_args)
{
Generate_Call_Data data;
+ void *ip;
data.num_rands = num_rands;
data.old_jitter = old_jitter;
@@ -1385,7 +1388,8 @@ void *scheme_generate_shared_call(int num_rands, mz_jit_state *old_jitter, int m
data.nontail_self = nontail_self;
data.unboxed_args = unboxed_args;
- return scheme_generate_one(old_jitter, do_generate_shared_call, &data, 0, NULL, NULL);
+ ip = scheme_generate_one(old_jitter, do_generate_shared_call, &data, 0, NULL, NULL);
+ return jit_adjust_ip(ip);
}
void scheme_ensure_retry_available(mz_jit_state *jitter, int multi_ok, int result_ignored)
@@ -1566,7 +1570,7 @@ static int generate_call_path_with_unboxes(mz_jit_state *jitter, int direct_flos
int i, k, offset;
refgo = jit_jmpi(jit_forward());
- refcopy = _jit.x.pc;
+ refcopy = jit_get_ip();
/* Callback code to copy unboxed arguments.
R1 has the return address, R2 holds the old FP */
diff --git a/src/racket/src/jitcommon.c b/src/racket/src/jitcommon.c
index 09174d472e..506d4d9a54 100644
--- a/src/racket/src/jitcommon.c
+++ b/src/racket/src/jitcommon.c
@@ -103,7 +103,7 @@ static Scheme_Object *vector_check_chaperone_of(Scheme_Object *o, Scheme_Object
static int save_struct_temp(mz_jit_state *jitter, int reg)
{
-#ifdef MZ_USE_JIT_PPC
+#if defined(MZ_USE_JIT_PPC) || defined(MZ_USE_JIT_ARM)
jit_movr_p(JIT_V(3), reg);
#endif
#ifdef MZ_USE_JIT_I386
@@ -122,7 +122,7 @@ int scheme_save_struct_temp(mz_jit_state *jitter, int reg) {
static int restore_struct_temp(mz_jit_state *jitter, int reg)
{
-#ifdef MZ_USE_JIT_PPC
+#if defined(MZ_USE_JIT_PPC) || defined(MZ_USE_JIT_ARM)
jit_movr_p(reg, JIT_V(3));
#endif
#ifdef MZ_USE_JIT_I386
@@ -204,7 +204,7 @@ static int common0(mz_jit_state *jitter, void *_data)
/* *** check_arity_code *** */
/* Called as a function: */
- sjc.check_arity_code = (Native_Check_Arity_Proc)jit_get_ip().ptr;
+ sjc.check_arity_code = (Native_Check_Arity_Proc)jit_get_ip();
jit_prolog(NATIVE_ARG_COUNT); /* only need 2 arguments, but return path overlaps with proc conventions */
mz_push_threadlocal_early();
in = jit_arg_p();
@@ -223,7 +223,7 @@ static int common0(mz_jit_state *jitter, void *_data)
/* *** get_arity_code *** */
/* Called as a function: */
- sjc.get_arity_code = (Native_Get_Arity_Proc)jit_get_ip().ptr;
+ sjc.get_arity_code = (Native_Get_Arity_Proc)jit_get_ip();
jit_prolog(NATIVE_ARG_COUNT); /* only need 1 argument, but return path overlaps with proc conventions */
mz_push_threadlocal_early();
in = jit_arg_p();
@@ -243,7 +243,7 @@ static int common0(mz_jit_state *jitter, void *_data)
/* *** bad_result_arity_code *** */
/* Jumped-to from non-tail contexts */
- sjc.bad_result_arity_code = (Native_Get_Arity_Proc)jit_get_ip().ptr;
+ sjc.bad_result_arity_code = (Native_Get_Arity_Proc)jit_get_ip();
mz_tl_ldi_p(JIT_R2, tl_scheme_current_thread);
jit_ldxi_l(JIT_R1, JIT_R2, &((Scheme_Thread *)0x0)->ku.multiple.count);
jit_ldxi_p(JIT_R2, JIT_R2, &((Scheme_Thread *)0x0)->ku.multiple.array);
@@ -258,7 +258,7 @@ static int common0(mz_jit_state *jitter, void *_data)
CHECK_LIMIT();
/* *** unbound_global_code *** */
- sjc.unbound_global_code = jit_get_ip().ptr;
+ sjc.unbound_global_code = jit_get_ip();
JIT_UPDATE_THREAD_RSPTR();
mz_prepare(1);
jit_pusharg_p(JIT_R2);
@@ -267,7 +267,7 @@ static int common0(mz_jit_state *jitter, void *_data)
/* *** quote_syntax_code *** */
/* R0 is WORDS_TO_BYTES(c), R1 is &0->a[i+p+1], R2 is &0->a[p] */
- sjc.quote_syntax_code = jit_get_ip().ptr;
+ sjc.quote_syntax_code = jit_get_ip();
mz_prolog(JIT_V1);
__START_SHORT_JUMPS__(1);
/* Load global array: */
@@ -328,7 +328,7 @@ static int common1(mz_jit_state *jitter, void *_data)
for (i = 0; i < 13; i++) {
void *code;
- code = jit_get_ip().ptr;
+ code = jit_get_ip();
switch (i) {
case 0:
sjc.bad_car_code = code;
@@ -460,7 +460,7 @@ static int common1b(mz_jit_state *jitter, void *_data)
/* Bad argument is in R0, other is in R1 */
for (i = 0; i < 4; i++) {
void *code;
- code = jit_get_ip().ptr;
+ code = jit_get_ip();
switch (i) {
case 0:
sjc.bad_set_mcar_code = code;
@@ -509,7 +509,7 @@ static int common1b(mz_jit_state *jitter, void *_data)
/* *** unbox_code *** */
/* R0 is argument */
- sjc.unbox_code = jit_get_ip().ptr;
+ sjc.unbox_code = jit_get_ip();
mz_prolog(JIT_R1);
JIT_UPDATE_THREAD_RSPTR();
jit_prepare(1);
@@ -522,7 +522,7 @@ static int common1b(mz_jit_state *jitter, void *_data)
/* *** set_box_code *** */
/* R0 is box, R1 is value */
- sjc.set_box_code = jit_get_ip().ptr;
+ sjc.set_box_code = jit_get_ip();
mz_prolog(JIT_R2);
JIT_UPDATE_THREAD_RSPTR();
jit_prepare(2);
@@ -539,7 +539,7 @@ static int common1b(mz_jit_state *jitter, void *_data)
/* call scheme_box_cas to raise the exception,
we use mz_finish_lwe because it will capture the stack,
and the ts_ version because we may be in a future */
- sjc.box_cas_fail_code = jit_get_ip().ptr;
+ sjc.box_cas_fail_code = jit_get_ip();
mz_prolog(JIT_R2);
JIT_UPDATE_THREAD_RSPTR_IF_NEEDED();
jit_movi_l(JIT_R0, 3);
@@ -552,7 +552,7 @@ static int common1b(mz_jit_state *jitter, void *_data)
/* *** bad_vector_length_code *** */
/* R0 is argument */
- sjc.bad_vector_length_code = jit_get_ip().ptr;
+ sjc.bad_vector_length_code = jit_get_ip();
mz_prolog(JIT_R1);
/* Check for chaperone: */
@@ -572,7 +572,7 @@ static int common1b(mz_jit_state *jitter, void *_data)
/* *** bad_flvector_length_code *** */
/* R0 is argument */
- sjc.bad_flvector_length_code = jit_get_ip().ptr;
+ sjc.bad_flvector_length_code = jit_get_ip();
mz_prolog(JIT_R1);
jit_prepare(1);
jit_pusharg_p(JIT_R0);
@@ -583,7 +583,7 @@ static int common1b(mz_jit_state *jitter, void *_data)
#ifdef MZ_LONG_DOUBLE
/* *** bad_extflvector_length_code *** */
/* R0 is argument */
- sjc.bad_extflvector_length_code = jit_get_ip().ptr;
+ sjc.bad_extflvector_length_code = jit_get_ip();
mz_prolog(JIT_R1);
jit_prepare(1);
jit_pusharg_p(JIT_R0);
@@ -594,7 +594,7 @@ static int common1b(mz_jit_state *jitter, void *_data)
/* *** bad_fxvector_length_code *** */
/* R0 is argument */
- sjc.bad_fxvector_length_code = jit_get_ip().ptr;
+ sjc.bad_fxvector_length_code = jit_get_ip();
mz_prolog(JIT_R1);
jit_prepare(1);
jit_pusharg_p(JIT_R0);
@@ -619,7 +619,7 @@ static int common2(mz_jit_state *jitter, void *_data)
void *code;
for (j = 0; j < 2; j++) {
CHECK_LIMIT();
- code = jit_get_ip().ptr;
+ code = jit_get_ip();
if (!i) {
if (!j)
sjc.call_original_unary_arith_code = code;
@@ -693,7 +693,7 @@ static int common2(mz_jit_state *jitter, void *_data)
{
void *code;
- code = jit_get_ip().ptr;
+ code = jit_get_ip();
sjc.call_original_nary_arith_code = code;
mz_prolog(JIT_R2);
@@ -718,7 +718,7 @@ static int common2(mz_jit_state *jitter, void *_data)
/* Used as the code stub for a closure whose
code is not yet compiled. See generate_function_prolog
for the state of registers on entry */
- scheme_on_demand_jit_code = jit_get_ip().ptr;
+ scheme_on_demand_jit_code = jit_get_ip();
jit_prolog(NATIVE_ARG_COUNT);
mz_push_threadlocal_early();
in = jit_arg_p();
@@ -731,7 +731,7 @@ static int common2(mz_jit_state *jitter, void *_data)
mz_push_locals();
mz_push_threadlocal(in);
mz_tl_ldi_p(JIT_RUNSTACK, tl_MZ_RUNSTACK);
- sjc.on_demand_jit_arity_code = jit_get_ip().ptr; /* <<<- arity variant starts here */
+ sjc.on_demand_jit_arity_code = jit_get_ip(); /* <<<- arity variant starts here */
jit_subi_p(JIT_RUNSTACK, JIT_RUNSTACK, WORDS_TO_BYTES(2));
CHECK_RUNSTACK_OVERFLOW();
jit_str_p(JIT_RUNSTACK, JIT_R0);
@@ -794,13 +794,13 @@ static int common2(mz_jit_state *jitter, void *_data)
/* Used for the state of a function that is being JITted
(for a kind of cycle detection) without breaking concurrent
future threads that might try to call the function. */
- sjc.in_progress_on_demand_jit_arity_code = jit_get_ip().ptr;
+ sjc.in_progress_on_demand_jit_arity_code = jit_get_ip();
(void)jit_jmpi(sjc.on_demand_jit_arity_code);
/* *** app_values_tail_slow_code *** */
/* RELIES ON jit_prolog(NATIVE_ARG_COUNT) FROM ABOVE */
/* Rator in V1, arguments are in thread's multiple-values cells. */
- sjc.app_values_tail_slow_code = jit_get_ip().ptr;
+ sjc.app_values_tail_slow_code = jit_get_ip();
JIT_UPDATE_THREAD_RSPTR();
mz_prepare(1);
jit_pusharg_p(JIT_V1);
@@ -815,17 +815,17 @@ static int common2(mz_jit_state *jitter, void *_data)
/* *** finish_tail_call_[fixup_]code *** */
/* RELIES ON jit_prolog(NATIVE_ARG_COUNT) FROM ABOVE */
- sjc.finish_tail_call_code = jit_get_ip().ptr;
+ sjc.finish_tail_call_code = jit_get_ip();
scheme_generate_finish_tail_call(jitter, 0);
CHECK_LIMIT();
scheme_jit_register_helper_func(jitter, sjc.finish_tail_call_code);
- sjc.finish_tail_call_fixup_code = jit_get_ip().ptr;
+ sjc.finish_tail_call_fixup_code = jit_get_ip();
scheme_generate_finish_tail_call(jitter, 2);
CHECK_LIMIT();
scheme_jit_register_helper_func(jitter, sjc.finish_tail_call_fixup_code);
/* *** get_stack_pointer_code *** */
- sjc.get_stack_pointer_code = jit_get_ip().ptr;
+ sjc.get_stack_pointer_code = jit_get_ip();
jit_leaf(0);
jit_movr_p(JIT_R0, JIT_FP);
/* Get frame pointer of caller... */
@@ -834,6 +834,9 @@ static int common2(mz_jit_state *jitter, void *_data)
#endif
#ifdef MZ_USE_JIT_I386
jit_ldr_p(JIT_R0, JIT_R0);
+#endif
+#ifdef MZ_USE_JIT_ARM
+ jit_ldxi_p(JIT_R0, JIT_R0, JIT_NEXT_FP_OFFSET);
#endif
jit_movr_p(JIT_RET, JIT_R0);
jit_ret();
@@ -844,7 +847,7 @@ static int common2(mz_jit_state *jitter, void *_data)
any registers that a function call would normally save
and restore. JIT_AUX, which is used by things like jit_ldi,
is such a register for PPC. */
- sjc.stack_cache_pop_code = jit_get_ip().ptr;
+ sjc.stack_cache_pop_code = jit_get_ip();
jit_movr_p(JIT_R0, JIT_RET);
#ifdef MZ_USE_JIT_PPC
jit_subi_p(JIT_SP, JIT_SP, 48); /* includes space maybe used by callee */
@@ -875,7 +878,7 @@ static int common2(mz_jit_state *jitter, void *_data)
/* *** bad_app_vals_target *** */
/* Non-proc is in R0 */
- sjc.bad_app_vals_target = jit_get_ip().ptr;
+ sjc.bad_app_vals_target = jit_get_ip();
JIT_UPDATE_THREAD_RSPTR();
mz_prepare(1);
jit_pusharg_p(JIT_R0);
@@ -887,9 +890,9 @@ static int common2(mz_jit_state *jitter, void *_data)
/* Rator in V1, arguments are in thread's multiple-values cells. */
for (i = 0; i < 2; i++) {
if (i)
- sjc.app_values_multi_slow_code = jit_get_ip().ptr;
+ sjc.app_values_multi_slow_code = jit_get_ip();
else
- sjc.app_values_slow_code = jit_get_ip().ptr;
+ sjc.app_values_slow_code = jit_get_ip();
mz_prolog(JIT_R1);
JIT_UPDATE_THREAD_RSPTR();
mz_prepare(1);
@@ -910,7 +913,7 @@ static int common2(mz_jit_state *jitter, void *_data)
{
GC_CAN_IGNORE jit_insn *refslow, *ref1, *refloop, *ref2;
- sjc.values_code = jit_get_ip().ptr;
+ sjc.values_code = jit_get_ip();
mz_prolog(JIT_R1);
mz_tl_ldi_p(JIT_R2, tl_scheme_current_thread);
jit_ldxi_p(JIT_R1, JIT_R2, &((Scheme_Thread *)0x0)->values_buffer);
@@ -918,7 +921,7 @@ static int common2(mz_jit_state *jitter, void *_data)
CHECK_LIMIT();
/* Allocate new array: */
- refslow = _jit.x.pc;
+ refslow = jit_get_ip();
JIT_UPDATE_THREAD_RSPTR();
mz_prepare(2);
jit_pusharg_p(JIT_R2);
@@ -942,7 +945,7 @@ static int common2(mz_jit_state *jitter, void *_data)
/* Copy values over: */
jit_movr_p(JIT_R0, JIT_RUNSTACK);
- refloop = _jit.x.pc;
+ refloop = jit_get_ip();
jit_ldr_p(JIT_R2, JIT_R0);
jit_str_p(JIT_R1, JIT_R2);
jit_subi_l(JIT_V1, JIT_V1, 1);
@@ -1055,7 +1058,7 @@ static int common3(mz_jit_state *jitter, void *_data)
int offset, count_offset, log_elem_size;
void *code;
- code = jit_get_ip().ptr;
+ code = jit_get_ip();
switch (ii) {
case -1:
@@ -1173,7 +1176,7 @@ static int common3(mz_jit_state *jitter, void *_data)
CHECK_LIMIT();
/* Slow path: */
- reffail = _jit.x.pc;
+ reffail = jit_get_ip();
if (ii != -1) {
/* in chaperone mode, we already saved original and index on runstack */
if (!i) {
@@ -1470,7 +1473,7 @@ int scheme_generate_struct_op(mz_jit_state *jitter, int kind, int for_branch,
/* Check argument: */
if (kind == 1) {
bref1 = jit_bmsi_ul(jit_forward(), JIT_R1, 0x1);
- refretry = _jit.x.pc;
+ refretry = jit_get_ip();
jit_ldxi_s(JIT_R2, JIT_R1, &((Scheme_Object *)0x0)->type);
__START_INNER_TINY__(1);
ref2 = jit_beqi_i(jit_forward(), JIT_R2, scheme_structure_type);
@@ -1674,7 +1677,7 @@ static int common4(mz_jit_state *jitter, void *_data)
for (i = 0; i < 3; i++) {
void *code;
- code = jit_get_ip().ptr;
+ code = jit_get_ip();
if (!i) {
sjc.flvector_ref_check_index_code[iii] = code;
@@ -1731,7 +1734,7 @@ static int common4(mz_jit_state *jitter, void *_data)
for (iii = 0; iii < 2; iii++) { /* ref, set */
void *code;
- code = jit_get_ip().ptr;
+ code = jit_get_ip();
if (!iii) {
sjc.struct_raw_ref_code = code;
@@ -1767,13 +1770,13 @@ static int common4(mz_jit_state *jitter, void *_data)
/* R0 is (potential) syntax object */
{
GC_CAN_IGNORE jit_insn *ref, *reffail, *refrts;
- sjc.syntax_e_code = jit_get_ip().ptr;
+ sjc.syntax_e_code = jit_get_ip();
__START_TINY_JUMPS__(1);
mz_prolog(JIT_R2);
ref = jit_bmci_ul(jit_forward(), JIT_R0, 0x1);
- reffail = _jit.x.pc;
+ reffail = jit_get_ip();
jit_subi_p(JIT_RUNSTACK, JIT_RUNSTACK, WORDS_TO_BYTES(1));
CHECK_RUNSTACK_OVERFLOW();
jit_str_p(JIT_RUNSTACK, JIT_R0);
@@ -1829,41 +1832,41 @@ static int common4(mz_jit_state *jitter, void *_data)
if ((ii == 1) && (i == 1)) continue; /* no multi variant of pred branch */
if ((ii == 2) && (i == 1)) continue; /* no tail variant of pred branch */
- code = jit_get_ip().ptr;
+ code = jit_get_ip();
if (!i) {
kind = 1;
for_branch = 0;
if (ii == 2)
- sjc.struct_pred_tail_code = jit_get_ip().ptr;
+ sjc.struct_pred_tail_code = jit_get_ip();
else if (ii == 1)
- sjc.struct_pred_multi_code = jit_get_ip().ptr;
+ sjc.struct_pred_multi_code = jit_get_ip();
else
- sjc.struct_pred_code = jit_get_ip().ptr;
+ sjc.struct_pred_code = jit_get_ip();
} else if (i == 1) {
kind = 1;
for_branch = 1;
- sjc.struct_pred_branch_code = jit_get_ip().ptr;
+ sjc.struct_pred_branch_code = jit_get_ip();
/* Save target address for false branch: */
save_struct_temp(jitter, JIT_V1);
} else if (i == 2) {
kind = 2;
for_branch = 0;
if (ii == 2)
- sjc.struct_get_tail_code = jit_get_ip().ptr;
+ sjc.struct_get_tail_code = jit_get_ip();
else if (ii == 1)
- sjc.struct_get_multi_code = jit_get_ip().ptr;
+ sjc.struct_get_multi_code = jit_get_ip();
else
- sjc.struct_get_code = jit_get_ip().ptr;
+ sjc.struct_get_code = jit_get_ip();
} else {
kind = 3;
for_branch = 0;
if (ii == 2)
- sjc.struct_set_tail_code = jit_get_ip().ptr;
+ sjc.struct_set_tail_code = jit_get_ip();
else if (ii == 1)
- sjc.struct_set_multi_code = jit_get_ip().ptr;
+ sjc.struct_set_multi_code = jit_get_ip();
else
- sjc.struct_set_code = jit_get_ip().ptr;
+ sjc.struct_set_code = jit_get_ip();
/* Save value to install: */
save_struct_temp(jitter, JIT_V1);
}
@@ -1876,13 +1879,13 @@ static int common4(mz_jit_state *jitter, void *_data)
CHECK_LIMIT();
/* Slow path: non-struct proc. */
- refslow = _jit.x.pc;
+ refslow = jit_get_ip();
gen_struct_slow(jitter, kind, 0, for_branch, ii == 2, ii == 1, &bref5, &bref6);
CHECK_LIMIT();
if ((kind == 2) || (kind == 3)) {
/* Slow path: argument type is bad for a getter/setter. */
- refslow2 = _jit.x.pc;
+ refslow2 = jit_get_ip();
gen_struct_slow(jitter, kind, 1, 0, 0, 0, NULL, NULL);
CHECK_LIMIT();
} else
@@ -1916,7 +1919,7 @@ static int common4b(mz_jit_state *jitter, void *_data)
void *code;
GC_CAN_IGNORE jit_insn *ref, *ref2, *ref3, *refno, *refslow, *refloop;
- code = jit_get_ip().ptr;
+ code = jit_get_ip();
if (i == 0) {
if (ii == 2)
@@ -1957,7 +1960,7 @@ static int common4b(mz_jit_state *jitter, void *_data)
/* Slow path: non-struct-prop proc, or argument type is
bad for a getter. */
- refslow = _jit.x.pc;
+ refslow = jit_get_ip();
jit_subi_p(JIT_RUNSTACK, JIT_RUNSTACK, WORDS_TO_BYTES(1));
CHECK_RUNSTACK_OVERFLOW();
JIT_UPDATE_THREAD_RSPTR();
@@ -1987,7 +1990,7 @@ static int common4b(mz_jit_state *jitter, void *_data)
mz_epilog(JIT_V1);
CHECK_LIMIT();
if (i == 2) {
- refno = _jit.x.pc;
+ refno = jit_get_ip();
(void)jit_movi_p(JIT_R0, scheme_false);
mz_epilog(JIT_V1);
CHECK_LIMIT();
@@ -2028,7 +2031,7 @@ static int common4b(mz_jit_state *jitter, void *_data)
if (i == 2) {
(void)jit_blei_i(refslow, JIT_V1, 0);
}
- refloop = _jit.x.pc;
+ refloop = jit_get_ip();
(void)jit_blei_i(refno, JIT_V1, 0);
jit_subi_i(JIT_V1, JIT_V1, 1);
mz_set_local_p(JIT_V1, JIT_LOCAL3);
@@ -2097,7 +2100,7 @@ static int common4c(mz_jit_state *jitter, void *_data)
void *code;
int num_args;
- code = jit_get_ip().ptr;
+ code = jit_get_ip();
if (i == 0) {
if (ii == 2)
@@ -2151,14 +2154,14 @@ static int common5(mz_jit_state *jitter, void *_data)
/* *** retry_alloc_code[{_keep_r0_r1,_keep_fpr1}] *** */
for (i = 0; i < END_OF_I; i++) {
if (!i)
- sjc.retry_alloc_code = jit_get_ip().ptr;
+ sjc.retry_alloc_code = jit_get_ip();
else if (i == 1)
- sjc.retry_alloc_code_keep_r0_r1 = jit_get_ip().ptr;
+ sjc.retry_alloc_code_keep_r0_r1 = jit_get_ip();
else if (i == 2)
- sjc.retry_alloc_code_keep_fpr1 = jit_get_ip().ptr;
+ sjc.retry_alloc_code_keep_fpr1 = jit_get_ip();
#ifdef MZ_LONG_DOUBLE
else if (i == 3)
- sjc.retry_alloc_code_keep_extfpr1 = jit_get_ip().ptr;
+ sjc.retry_alloc_code_keep_extfpr1 = jit_get_ip();
#endif
mz_prolog(JIT_V1);
@@ -2176,9 +2179,9 @@ static int common5(mz_jit_state *jitter, void *_data)
GC_CAN_IGNORE jit_insn *ref, *refnext;
if (i == 0)
- sjc.make_list_code = jit_get_ip().ptr;
+ sjc.make_list_code = jit_get_ip();
else
- sjc.make_list_star_code = jit_get_ip().ptr;
+ sjc.make_list_star_code = jit_get_ip();
mz_prolog(JIT_R1);
jit_lshi_l(JIT_R2, JIT_R2, JIT_LOG_WORD_SIZE);
if (i == 0)
@@ -2190,7 +2193,7 @@ static int common5(mz_jit_state *jitter, void *_data)
__START_SHORT_JUMPS__(1);
ref = jit_beqi_l(jit_forward(), JIT_R2, 0);
- refnext = _jit.x.pc;
+ refnext = jit_get_ip();
__END_SHORT_JUMPS__(1);
CHECK_LIMIT();
@@ -2215,7 +2218,7 @@ static int common5(mz_jit_state *jitter, void *_data)
/* *** box_flonum_from_stack_code *** */
/* R0 has offset from frame pointer to double on stack */
{
- sjc.box_flonum_from_stack_code = jit_get_ip().ptr;
+ sjc.box_flonum_from_stack_code = jit_get_ip();
mz_prolog(JIT_R2);
@@ -2232,7 +2235,7 @@ static int common5(mz_jit_state *jitter, void *_data)
/* *** box_flonum_from_reg_code *** */
/* JIT_FPR2 (reg-based) or JIT_FPR0 (stack-based) has value */
{
- sjc.box_flonum_from_reg_code = jit_get_ip().ptr;
+ sjc.box_flonum_from_reg_code = jit_get_ip();
mz_prolog(JIT_R2);
@@ -2252,7 +2255,7 @@ static int common5(mz_jit_state *jitter, void *_data)
/* *** box_extflonum_from_stack_code *** */
/* R0 has offset from frame pointer to long double on stack */
{
- sjc.box_extflonum_from_stack_code = jit_get_ip().ptr;
+ sjc.box_extflonum_from_stack_code = jit_get_ip();
mz_prolog(JIT_R2);
@@ -2269,7 +2272,7 @@ static int common5(mz_jit_state *jitter, void *_data)
/* *** box_extflonum_from_reg_code *** */
/* JIT_FPU_FPR2 (reg-based) or JIT_FPU_FPR0 (stack-based) has value */
{
- sjc.box_extflonum_from_reg_code = jit_get_ip().ptr;
+ sjc.box_extflonum_from_reg_code = jit_get_ip();
mz_prolog(JIT_R2);
@@ -2285,7 +2288,7 @@ static int common5(mz_jit_state *jitter, void *_data)
/* *** fl1_fail_code *** */
/* R0 has argument, V1 has primitive proc */
for (iii = 0; iii < JIT_NUM_FL_KINDS; iii++) {
- sjc.fl1_fail_code[iii] = jit_get_ip().ptr;
+ sjc.fl1_fail_code[iii] = jit_get_ip();
mz_prolog(JIT_R2);
@@ -2316,7 +2319,7 @@ static int common5(mz_jit_state *jitter, void *_data)
void *code;
int a0, a1;
- code = jit_get_ip().ptr;
+ code = jit_get_ip();
switch (i) {
case 0:
sjc.fl2rr_fail_code[ii][iii] = code;
@@ -2388,14 +2391,14 @@ static int common6(mz_jit_state *jitter, void *_data)
{
GC_CAN_IGNORE jit_insn *refloop, *ref, *ref2, *ref3, *ref4, *ref5, *ref7, *ref8;
- sjc.wcm_code = jit_get_ip().ptr;
+ sjc.wcm_code = jit_get_ip();
mz_prolog(JIT_R2);
(void)mz_tl_ldi_p(JIT_R2, tl_scheme_current_cont_mark_stack);
/* R2 has counter for search */
- refloop = _jit.x.pc;
+ refloop = jit_get_ip();
(void)mz_tl_ldi_p(JIT_R1, tl_scheme_current_thread);
jit_ldxi_l(JIT_R0, JIT_R1, &((Scheme_Thread *)0x0)->cont_mark_stack_bottom);
ref = jit_bler_i(jit_forward(), JIT_R2, JIT_R0); /* => double-check meta-continuation */
@@ -2439,14 +2442,14 @@ static int common6(mz_jit_state *jitter, void *_data)
jit_subi_l(JIT_R2, JIT_R2, 2);
ref = jit_bner_i(jit_forward(), JIT_R2, JIT_R0); /* => try to allocate new slot */
jit_ldxi_p(JIT_R1, JIT_R1, &((Scheme_Thread *)0x0)->meta_continuation);
- ref7 = jit_beqi_l(jit_forward(), JIT_R1, NULL); /* => try to allocate new slot */
+ ref7 = jit_beqi_p(jit_forward(), JIT_R1, NULL); /* => try to allocate new slot */
/* we need to check a meta-continuation... take the slow path. */
ref8 = jit_jmpi(jit_forward());
CHECK_LIMIT();
/* Entry point when we know we're not in non-tail position with respect
to any enclosing wcm: */
- sjc.wcm_nontail_code = jit_get_ip().ptr;
+ sjc.wcm_nontail_code = jit_get_ip();
mz_prolog(JIT_R2);
/* Try to allocate new slot: */
@@ -2491,7 +2494,7 @@ static int common6(mz_jit_state *jitter, void *_data)
CHECK_LIMIT();
/* return: */
- ref5 = _jit.x.pc;
+ ref5 = jit_get_ip();
mz_epilog(JIT_R2);
/* slow path: */
@@ -2519,7 +2522,7 @@ static int common6(mz_jit_state *jitter, void *_data)
/* key and value are on runstack and are updated there */
{
GC_CAN_IGNORE jit_insn *ref2;
- sjc.wcm_chaperone = jit_get_ip().ptr;
+ sjc.wcm_chaperone = jit_get_ip();
mz_prolog(JIT_R2);
JIT_UPDATE_THREAD_RSPTR();
@@ -2545,7 +2548,7 @@ static int common7(mz_jit_state *jitter, void *_data)
GC_CAN_IGNORE jit_insn *refloop, *ref1, *ref2, *ref3, *ref4;
GC_CAN_IGNORE jit_insn *ref5, *ref6, *ref7, *ref8;
- code = jit_get_ip().ptr;
+ code = jit_get_ip();
if (!i)
sjc.list_p_code = code;
else
@@ -2562,7 +2565,7 @@ static int common7(mz_jit_state *jitter, void *_data)
/* Note: there's no fuel check in this loop, just like there isn't in
scheme_is_list(). */
- refloop = _jit.x.pc;
+ refloop = jit_get_ip();
jit_ldxi_s(JIT_R2, JIT_R0, &MZ_OPT_HASH_KEY(&((Scheme_Stx *)0x0)->iso));
ref1 = jit_bmsi_ul(jit_forward(), JIT_R2, PAIR_FLAG_MASK);
@@ -2673,7 +2676,7 @@ static int common8(mz_jit_state *jitter, void *_data)
void *code;
GC_CAN_IGNORE jit_insn *refloop, *ref1, *ref2, *ref3, *ref4, *ref5;
- code = jit_get_ip().ptr;
+ code = jit_get_ip();
sjc.list_length_code = code;
mz_prolog(JIT_R2);
@@ -2689,7 +2692,7 @@ static int common8(mz_jit_state *jitter, void *_data)
/* R0 has argument, R1 has counter */
jit_movi_l(JIT_R1, 0);
- refloop = _jit.x.pc;
+ refloop = jit_get_ip();
ref2 = jit_beqi_p(jit_forward(), JIT_R0, scheme_null);
ref3 = jit_bmsi_l(jit_forward(), JIT_R0, 0x1);
@@ -2710,7 +2713,7 @@ static int common8(mz_jit_state *jitter, void *_data)
mz_patch_branch(ref2);
__END_SHORT_JUMPS__(1);
jit_fixnum_l(JIT_R0, JIT_R1);
- ref1 = _jit.x.pc;
+ ref1 = jit_get_ip();
mz_epilog(JIT_R2);
__START_SHORT_JUMPS__(1);
@@ -2747,7 +2750,7 @@ static int common8_5(mz_jit_state *jitter, void *_data)
GC_CAN_IGNORE jit_insn *refslow, *refloop, *refdone, *ref, *refr;
GC_CAN_IGNORE jit_insn *refmaybedone, *refresume;
- code = jit_get_ip().ptr;
+ code = jit_get_ip();
if (i == 0)
sjc.list_tail_code = code;
else
@@ -2763,7 +2766,7 @@ static int common8_5(mz_jit_state *jitter, void *_data)
ref = jit_bmsi_l(jit_forward(), JIT_R1, 0x1);
- refslow = _jit.x.pc;
+ refslow = jit_get_ip();
jit_subi_p(JIT_RUNSTACK, JIT_RUNSTACK, WORDS_TO_BYTES(2));
JIT_UPDATE_THREAD_RSPTR();
@@ -2794,10 +2797,10 @@ static int common8_5(mz_jit_state *jitter, void *_data)
jit_rshi_l(JIT_R1, JIT_R1, 1);
(void)jit_blti_l(refslow, JIT_R1, 0);
- refloop = _jit.x.pc;
+ refloop = jit_get_ip();
if (i == 0) {
refmaybedone = jit_bmci_l(jit_forward(), JIT_R1, 0xFFF);
- refresume = _jit.x.pc;
+ refresume = jit_get_ip();
} else {
refmaybedone = NULL;
refresume = NULL;
@@ -2806,7 +2809,7 @@ static int common8_5(mz_jit_state *jitter, void *_data)
(void)mz_bnei_t(refslow, JIT_R0, scheme_pair_type, JIT_R2);
if (i == 1) {
refmaybedone = jit_bmci_l(jit_forward(), JIT_R1, 0xFFF);
- refresume = _jit.x.pc;
+ refresume = jit_get_ip();
}
jit_subi_l(JIT_R1, JIT_R1, 1);
jit_ldxi_p(JIT_R0, JIT_R0, (intptr_t)&SCHEME_CDR(0x0));
@@ -2848,7 +2851,7 @@ static int common9(mz_jit_state *jitter, void *_data)
void *code;
GC_CAN_IGNORE jit_insn *ref;
- code = jit_get_ip().ptr;
+ code = jit_get_ip();
if (i == 0)
sjc.eqv_code = code;
else
@@ -2902,7 +2905,7 @@ static int common10(mz_jit_state *jitter, void *_data)
{
GC_CAN_IGNORE jit_insn *ref, *refslow, *refr ,*ref_nc, *ref_prim, *refno;
- sjc.proc_arity_includes_code = jit_get_ip().ptr;
+ sjc.proc_arity_includes_code = jit_get_ip();
mz_prolog(JIT_R2);
@@ -2910,7 +2913,7 @@ static int common10(mz_jit_state *jitter, void *_data)
ref = jit_bmsi_l(jit_forward(), JIT_R1, 0x1);
- refslow = _jit.x.pc;
+ refslow = jit_get_ip();
jit_subi_p(JIT_RUNSTACK, JIT_RUNSTACK, WORDS_TO_BYTES(2));
JIT_UPDATE_THREAD_RSPTR();
@@ -2931,7 +2934,7 @@ static int common10(mz_jit_state *jitter, void *_data)
mz_epilog(JIT_R2);
- refno = _jit.x.pc;
+ refno = jit_get_ip();
(void)jit_movi_p(JIT_R0, scheme_false);
mz_epilog(JIT_R2);
@@ -3018,7 +3021,7 @@ static int common11(mz_jit_state *jitter, void *_data)
{
GC_CAN_IGNORE jit_insn *refr;
- sjc.bad_char_to_integer_code = jit_get_ip().ptr;
+ sjc.bad_char_to_integer_code = jit_get_ip();
mz_prolog(JIT_R2);
@@ -3043,7 +3046,7 @@ static int common11(mz_jit_state *jitter, void *_data)
{
GC_CAN_IGNORE jit_insn *refr;
- sjc.slow_integer_to_char_code = jit_get_ip().ptr;
+ sjc.slow_integer_to_char_code = jit_get_ip();
mz_prolog(JIT_R2);
@@ -3097,7 +3100,7 @@ static int more_common0(mz_jit_state *jitter, void *_data)
{
GC_CAN_IGNORE jit_insn *ref, *ref2, *ref3, *refslow, *refrts;
- sjc.struct_proc_extract_code = jit_get_ip().ptr;
+ sjc.struct_proc_extract_code = jit_get_ip();
mz_prolog(JIT_V1);
__START_SHORT_JUMPS__(1);
@@ -3107,7 +3110,7 @@ static int more_common0(mz_jit_state *jitter, void *_data)
CHECK_LIMIT();
/* Slow path: call C implementation */
- refslow = _jit.x.pc;
+ refslow = jit_get_ip();
JIT_UPDATE_THREAD_RSPTR();
jit_movi_i(JIT_V1, 5);
jit_prepare(2);
@@ -3204,7 +3207,7 @@ static int more_common0(mz_jit_state *jitter, void *_data)
{
int in;
- sjc.module_run_start_code = jit_get_ip().ptr;
+ sjc.module_run_start_code = jit_get_ip();
jit_prolog(3);
in = jit_arg_p();
jit_getarg_p(JIT_R0, in); /* menv */
@@ -3235,7 +3238,7 @@ static int more_common0(mz_jit_state *jitter, void *_data)
{
int in;
- sjc.module_exprun_start_code = jit_get_ip().ptr;
+ sjc.module_exprun_start_code = jit_get_ip();
jit_prolog(3);
in = jit_arg_p();
jit_getarg_p(JIT_R0, in); /* menv */
@@ -3266,7 +3269,7 @@ static int more_common0(mz_jit_state *jitter, void *_data)
{
int in;
- sjc.module_start_start_code = jit_get_ip().ptr;
+ sjc.module_start_start_code = jit_get_ip();
jit_prolog(2);
in = jit_arg_p();
jit_getarg_p(JIT_R0, in); /* a */
@@ -3299,7 +3302,7 @@ static int more_common1(mz_jit_state *jitter, void *_data)
{
GC_CAN_IGNORE jit_insn *ref1, *ref2, *ref3, *ref4, *ref5, *ref6, *refloop;
- sjc.apply_to_list_tail_code = jit_get_ip().ptr;
+ sjc.apply_to_list_tail_code = jit_get_ip();
__START_SHORT_JUMPS__(1);
@@ -3311,7 +3314,7 @@ static int more_common1(mz_jit_state *jitter, void *_data)
CHECK_LIMIT();
/* check that it's a list and get the length */
- refloop = _jit.x.pc;
+ refloop = jit_get_ip();
__START_INNER_TINY__(1);
ref2 = jit_beqi_p(jit_forward(), JIT_R0, scheme_null);
__END_INNER_TINY__(1);
@@ -3365,7 +3368,7 @@ static int more_common1(mz_jit_state *jitter, void *_data)
jit_addr_l(JIT_R2, JIT_R2, JIT_R0); /* move R2 and RUNSTACK pointers to end instead of start */
jit_addr_l(JIT_RUNSTACK, JIT_RUNSTACK, JIT_R0);
jit_negr_l(JIT_R0, JIT_R0); /* negate counter */
- refloop = _jit.x.pc;
+ refloop = jit_get_ip();
jit_ldxr_p(JIT_R1, JIT_RUNSTACK, JIT_R0);
jit_stxr_p(JIT_R0, JIT_R2, JIT_R1);
jit_addi_l(JIT_R0, JIT_R0, JIT_WORD_SIZE);
@@ -3383,7 +3386,7 @@ static int more_common1(mz_jit_state *jitter, void *_data)
mz_patch_branch(ref6);
jit_subi_l(JIT_R0, JIT_V1, 1); /* drop last arg */
jit_lshi_ul(JIT_R0, JIT_R0, JIT_LOG_WORD_SIZE);
- refloop = _jit.x.pc;
+ refloop = jit_get_ip();
jit_subi_l(JIT_R0, JIT_R0, JIT_WORD_SIZE);
jit_ldxr_p(JIT_R1, JIT_RUNSTACK, JIT_R0);
jit_stxr_p(JIT_R0, JIT_R2, JIT_R1);
@@ -3400,7 +3403,7 @@ static int more_common1(mz_jit_state *jitter, void *_data)
mz_get_local_p(JIT_R0, JIT_LOCAL2); /* list in R0 */
jit_subi_l(JIT_R1, JIT_V1, 1); /* drop last original arg */
jit_lshi_ul(JIT_R1, JIT_R1, JIT_LOG_WORD_SIZE);
- refloop = _jit.x.pc;
+ refloop = jit_get_ip();
__START_INNER_TINY__(1);
ref6 = jit_beqi_p(jit_forward(), JIT_R0, scheme_null);
__END_INNER_TINY__(1);
@@ -3437,7 +3440,7 @@ static int more_common1(mz_jit_state *jitter, void *_data)
mz_ld_runstack_base_alt(JIT_R2);
jit_lshi_ul(JIT_R0, JIT_V1, JIT_LOG_WORD_SIZE);
jit_subr_p(JIT_R2, JIT_RUNSTACK_BASE_OR_ALT(JIT_R2), JIT_R0);
- refloop = _jit.x.pc;
+ refloop = jit_get_ip();
jit_subi_l(JIT_R0, JIT_R0, JIT_WORD_SIZE);
jit_ldxr_p(JIT_R1, JIT_RUNSTACK, JIT_R0);
jit_stxr_p(JIT_R0, JIT_R2, JIT_R1);
@@ -3468,7 +3471,7 @@ static int more_common1(mz_jit_state *jitter, void *_data)
void *code;
for (multi_ok = 0; multi_ok < 2; multi_ok++) {
- code = jit_get_ip().ptr;
+ code = jit_get_ip();
if (multi_ok)
sjc.apply_to_list_multi_ok_code = code;
else
@@ -3487,7 +3490,7 @@ static int more_common1(mz_jit_state *jitter, void *_data)
/* check that it's a list and get the length */
- refloop = _jit.x.pc;
+ refloop = jit_get_ip();
__START_INNER_TINY__(1);
ref2 = jit_beqi_p(jit_forward(), JIT_R0, scheme_null);
__END_INNER_TINY__(1);
@@ -3523,7 +3526,7 @@ static int more_common1(mz_jit_state *jitter, void *_data)
jit_subi_l(JIT_R0, JIT_V1, 2); /* drop first and last arg */
jit_lshi_ul(JIT_R0, JIT_R0, JIT_LOG_WORD_SIZE);
jit_addi_p(JIT_RUNSTACK, JIT_RUNSTACK, JIT_WORD_SIZE); /* skip first arg */
- refloop = _jit.x.pc;
+ refloop = jit_get_ip();
jit_subi_l(JIT_R0, JIT_R0, JIT_WORD_SIZE);
jit_ldxr_p(JIT_R1, JIT_RUNSTACK, JIT_R0);
jit_stxr_p(JIT_R0, JIT_R2, JIT_R1);
@@ -3546,7 +3549,7 @@ static int more_common1(mz_jit_state *jitter, void *_data)
jit_subi_l(JIT_R1, JIT_V1, 2); /* drop first and last original arg */
jit_lshi_ul(JIT_R1, JIT_R1, JIT_LOG_WORD_SIZE);
- refloop = _jit.x.pc;
+ refloop = jit_get_ip();
__START_INNER_TINY__(1);
ref6 = jit_beqi_p(jit_forward(), JIT_R0, scheme_null);
__END_INNER_TINY__(1);
@@ -3582,7 +3585,7 @@ static int more_common1(mz_jit_state *jitter, void *_data)
wants to pop N arguments. */
jit_lshi_ul(JIT_R0, JIT_V1, JIT_LOG_WORD_SIZE);
jit_subr_p(JIT_R2, JIT_RUNSTACK, JIT_R0);
- refloop = _jit.x.pc;
+ refloop = jit_get_ip();
jit_subi_l(JIT_R0, JIT_R0, JIT_WORD_SIZE);
jit_ldxr_p(JIT_R1, JIT_RUNSTACK, JIT_R0);
jit_stxr_p(JIT_R0, JIT_R2, JIT_R1);
@@ -3610,7 +3613,7 @@ static int more_common1(mz_jit_state *jitter, void *_data)
#ifdef MZ_USE_LWC
/* native_starter_code */
{
- sjc.native_starter_code = (LWC_Native_Starter)jit_get_ip().ptr;
+ sjc.native_starter_code = (LWC_Native_Starter)jit_get_ip();
/* store stack pointer in address given by 5th argument, then jump to
the address given by the 4th argument */
@@ -3626,7 +3629,7 @@ static int more_common1(mz_jit_state *jitter, void *_data)
{
int in;
- sjc.continuation_apply_indirect_code = (Continuation_Apply_Indirect)jit_get_ip().ptr;
+ sjc.continuation_apply_indirect_code = (Continuation_Apply_Indirect)jit_get_ip();
/* install stack pointer into first argument before doing anything */
jit_getprearg__p(JIT_PREARG);
@@ -3667,7 +3670,7 @@ static int more_common1(mz_jit_state *jitter, void *_data)
{
int in;
- sjc.continuation_apply_finish_code = (Continuation_Apply_Finish)jit_get_ip().ptr;
+ sjc.continuation_apply_finish_code = (Continuation_Apply_Finish)jit_get_ip();
jit_prolog(2);
in = jit_arg_p();
diff --git a/src/racket/src/jitinline.c b/src/racket/src/jitinline.c
index 8b380bf24d..7c1cc9f0a1 100644
--- a/src/racket/src/jitinline.c
+++ b/src/racket/src/jitinline.c
@@ -412,7 +412,7 @@ static int generate_inlined_struct_op(int kind, mz_jit_state *jitter,
if (inline_rator && (kind != INLINE_STRUCT_PROC_PRED)) {
__START_SHORT_JUMPS__(1);
ref = jit_bmci_ul(jit_forward(), JIT_R1, 0x1);
- refslow = _jit.x.pc;
+ refslow = jit_get_ip();
if (kind == INLINE_STRUCT_PROC_SET)
scheme_restore_struct_temp(jitter, JIT_V1);
__END_SHORT_JUMPS__(1);
@@ -662,7 +662,7 @@ int scheme_generate_struct_alloc(mz_jit_state *jitter, int num_args,
/* Slow path: non-struct-prop proc, or argument type is
bad for a getter. */
- refslow = _jit.x.pc;
+ refslow = jit_get_ip();
if (inline_slow) {
if (num_args == 1) {
jit_subi_p(JIT_RUNSTACK, JIT_RUNSTACK, WORDS_TO_BYTES(1));
@@ -1224,7 +1224,7 @@ int scheme_generate_inlined_unary(mz_jit_state *jitter, Scheme_App2_Rec *app, in
if (!sjc.skip_checks) {
if (!i) {
ref = jit_bmci_ul(jit_forward(), JIT_R0, 0x1);
- reffail = _jit.x.pc;
+ reffail = jit_get_ip();
__END_TINY_JUMPS__(1);
if (steps == 1) {
if (name[1] == 'a') {
@@ -1289,7 +1289,7 @@ int scheme_generate_inlined_unary(mz_jit_state *jitter, Scheme_App2_Rec *app, in
__START_TINY_JUMPS__(1);
ref = jit_bmci_ul(jit_forward(), JIT_R0, 0x1);
- reffail = _jit.x.pc;
+ reffail = jit_get_ip();
__END_TINY_JUMPS__(1);
if (name[2] == 'a') {
(void)jit_calli(sjc.bad_mcar_code);
@@ -1398,7 +1398,7 @@ int scheme_generate_inlined_unary(mz_jit_state *jitter, Scheme_App2_Rec *app, in
ref = jit_bmci_ul(jit_forward(), JIT_R0, 0x1);
__END_TINY_JUMPS__(1);
- reffail = _jit.x.pc;
+ reffail = jit_get_ip();
if (for_fl) {
MZ_FPUSEL_STMT(extfl,
(void)jit_calli(sjc.bad_extflvector_length_code),
@@ -1477,7 +1477,7 @@ int scheme_generate_inlined_unary(mz_jit_state *jitter, Scheme_App2_Rec *app, in
ref = jit_bmci_ul(jit_forward(), JIT_R0, 0x1);
__END_TINY_JUMPS__(1);
- reffail = _jit.x.pc;
+ reffail = jit_get_ip();
(void)jit_calli(sjc.unbox_code);
jit_movr_p(dest, JIT_R0);
@@ -1580,7 +1580,7 @@ int scheme_generate_inlined_unary(mz_jit_state *jitter, Scheme_App2_Rec *app, in
__START_TINY_JUMPS__(1);
ref = jit_bmci_ul(jit_forward(), JIT_R0, 0x1);
- reffail = _jit.x.pc;
+ reffail = jit_get_ip();
__END_TINY_JUMPS__(1);
if (name[0] == 'i') {
(void)jit_calli(sjc.imag_part_code);
@@ -1842,7 +1842,7 @@ int scheme_generate_inlined_unary(mz_jit_state *jitter, Scheme_App2_Rec *app, in
__START_TINY_JUMPS__(1);
ref = jit_bmci_ul(jit_forward(), JIT_R0, 0x1);
- reffail = _jit.x.pc;
+ reffail = jit_get_ip();
__END_TINY_JUMPS__(1);
(void)jit_calli(sjc.bad_char_to_integer_code);
__START_TINY_JUMPS__(1);
@@ -1869,14 +1869,14 @@ int scheme_generate_inlined_unary(mz_jit_state *jitter, Scheme_App2_Rec *app, in
__START_TINY_JUMPS__(1);
ref = jit_bmsi_ul(jit_forward(), JIT_R0, 0x1);
- refslow = _jit.x.pc;
+ refslow = jit_get_ip();
__END_TINY_JUMPS__(1);
(void)jit_calli(sjc.slow_integer_to_char_code);
__START_TINY_JUMPS__(1);
refdone = jit_jmpi(jit_forward());
mz_patch_branch(ref);
- (void)jit_blti_l(refslow, JIT_R0, scheme_make_integer(0));
- (void)jit_bgti_l(refslow, JIT_R0, scheme_make_integer(255));
+ (void)jit_blti_p(refslow, JIT_R0, scheme_make_integer(0));
+ (void)jit_bgti_p(refslow, JIT_R0, scheme_make_integer(255));
jit_rshi_l(JIT_R0, JIT_R0, 1);
jit_lshi_l(JIT_R2, JIT_R0, JIT_LOG_WORD_SIZE);
@@ -2077,7 +2077,7 @@ static int generate_binary_char(mz_jit_state *jitter, Scheme_App3_Rec *app,
if (!SCHEME_CHARP(r1)) {
GC_CAN_IGNORE jit_insn *pref;
pref = jit_bmci_ul(jit_forward(), JIT_R0, 0x1);
- reffail = _jit.x.pc;
+ reffail = jit_get_ip();
(void)jit_movi_p(JIT_R2, ((Scheme_Primitive_Proc *)rator)->prim_val);
__END_SHORT_JUMPS__(branch_short);
if (direction > 0) {
@@ -2097,7 +2097,7 @@ static int generate_binary_char(mz_jit_state *jitter, Scheme_App3_Rec *app,
if (!reffail) {
GC_CAN_IGNORE jit_insn *pref;
pref = jit_bmci_ul(jit_forward(), JIT_R1, 0x1);
- reffail = _jit.x.pc;
+ reffail = jit_get_ip();
(void)jit_movi_p(JIT_R2, ((Scheme_Primitive_Proc *)rator)->prim_val);
__END_SHORT_JUMPS__(branch_short);
if (direction > 0) {
@@ -2174,7 +2174,7 @@ static int generate_vector_op(mz_jit_state *jitter, int set, int int_ready, int
}
__END_TINY_JUMPS__(1);
- reffail = _jit.x.pc;
+ reffail = jit_get_ip();
if (int_ready) {
jit_fixnum_l(JIT_R1, JIT_R1);
}
@@ -3024,7 +3024,7 @@ int scheme_generate_inlined_binary(mz_jit_state *jitter, Scheme_App3_Rec *app, i
offset = SCHEME_INT_VAL(app->rand2);
if (!unsafe || can_chaperone)
- (void)jit_movi_p(JIT_R1, offset);
+ (void)jit_movi_l(JIT_R1, offset);
if (!which)
offset = base_offset + WORDS_TO_BYTES(offset);
else if (which == 3)
@@ -3208,7 +3208,7 @@ int scheme_generate_inlined_binary(mz_jit_state *jitter, Scheme_App3_Rec *app, i
__START_TINY_JUMPS__(1);
ref = jit_bmci_ul(jit_forward(), JIT_R0, 0x1);
- reffail = _jit.x.pc;
+ reffail = jit_get_ip();
__END_TINY_JUMPS__(1);
if (set_mcar)
(void)jit_calli(sjc.bad_set_mcar_code);
@@ -3268,7 +3268,7 @@ int scheme_generate_inlined_binary(mz_jit_state *jitter, Scheme_App3_Rec *app, i
ref = mz_beqi_t(jit_forward(), JIT_R0, scheme_box_type, JIT_R2);
if (ref3)
mz_patch_branch(ref3);
- reffail = _jit.x.pc;
+ reffail = jit_get_ip();
(void)jit_calli(sjc.set_box_code);
ref2 = jit_jmpi(jit_forward());
mz_patch_branch(ref);
@@ -3395,7 +3395,7 @@ int scheme_generate_inlined_binary(mz_jit_state *jitter, Scheme_App3_Rec *app, i
jit_ldxi_s(JIT_R2, JIT_R0, &((Scheme_Object *)0x0)->type);
ref2 = jit_bgei_i(jit_forward(), JIT_R2, scheme_bignum_type);
/* (slow path) */
- refslow = _jit.x.pc;
+ refslow = jit_get_ip();
(void)jit_calli(sjc.make_rectangular_code);
jit_retval(dest);
CHECK_LIMIT();
@@ -3446,7 +3446,7 @@ int scheme_generate_inlined_binary(mz_jit_state *jitter, Scheme_App3_Rec *app, i
__START_TINY_JUMPS__(1);
ref = jit_bmci_ul(jit_forward(), JIT_R0, 0x1);
- refslow = _jit.x.pc;
+ refslow = jit_get_ip();
(void)jit_calli(sjc.bad_make_flrectangular_code);
mz_patch_branch(ref);
(void)mz_bnei_t(refslow, JIT_R0, scheme_double_type, JIT_R2);
@@ -3604,7 +3604,7 @@ int scheme_generate_inlined_nary(mz_jit_state *jitter, Scheme_App_Rec *app, int
__START_TINY_JUMPS__(1);
/* Fail if this isn't a pointer (0x1 is the integer tag) */
ref = jit_bmci_ul(jit_forward(), JIT_R1, 0x1);
- reffail = _jit.x.pc;
+ reffail = jit_get_ip();
__END_TINY_JUMPS__(1);
(void)jit_calli(sjc.box_cas_fail_code);
@@ -3643,7 +3643,7 @@ int scheme_generate_inlined_nary(mz_jit_state *jitter, Scheme_App_Rec *app, int
#ifdef MZ_USE_FUTURES
if (scheme_is_multithreaded(0)) {
jit_lock_cmpxchgr_l(JIT_R1, JIT_V1); /* implicitly uses JIT_R0 */
- reffalse = (JNEm(jit_forward(), 0,0,0), _jit.x.pc);
+ reffalse = (JNEm(jit_forward(), 0,0,0), jit_get_ip());
} else
#endif
{
@@ -3941,7 +3941,7 @@ int scheme_generate_inlined_nary(mz_jit_state *jitter, Scheme_App_Rec *app, int
} else {
intptr_t offset;
offset = SCHEME_INT_VAL(app->args[2]);
- (void)jit_movi_p(JIT_R1, offset);
+ (void)jit_movi_l(JIT_R1, offset);
if (!which)
offset = base_offset + WORDS_TO_BYTES(offset);
else if (which == 3)
diff --git a/src/racket/src/jitstack.c b/src/racket/src/jitstack.c
index e1f937b9b3..1932e275e4 100644
--- a/src/racket/src/jitstack.c
+++ b/src/racket/src/jitstack.c
@@ -58,6 +58,7 @@ void scheme_register_stack_cache_stack(void)
typedef void *(*Get_Stack_Proc)();
#ifdef MZ_USE_JIT_PPC
+# define NEXT_FRAME_OFFSET 0
# ifdef _CALL_DARWIN
# define RETURN_ADDRESS_OFFSET 2
# else
@@ -65,8 +66,13 @@ typedef void *(*Get_Stack_Proc)();
# endif
#endif
#ifdef MZ_USE_JIT_I386
+# define NEXT_FRAME_OFFSET 0
# define RETURN_ADDRESS_OFFSET 1
#endif
+#ifdef MZ_USE_JIT_ARM
+# define NEXT_FRAME_OFFSET JIT_NEXT_FP_OFFSET
+# define RETURN_ADDRESS_OFFSET (JIT_NEXT_FP_OFFSET+1)
+#endif
#define CACHE_STACK_MIN_TRIGGER 128
@@ -109,7 +115,7 @@ static void check_stack(void)
}
}
- q = *(void **)p;
+ q = ((void **)p)[NEXT_FRAME_OFFSET];
if (STK_COMP((uintptr_t)q, (uintptr_t)p))
break;
p = q;
@@ -330,23 +336,31 @@ Scheme_Object *scheme_native_stack_trace(void)
name = find_symbol((uintptr_t)q);
#ifdef MZ_USE_DWARF_LIBUNWIND
- if (name) manual_unw = 1;
+ if (name && !manual_unw) {
+ manual_unw = 1;
+# ifdef MZ_USE_JIT_ARM
+ use_unw = 0;
+ p = (void *)unw_get_frame_pointer(&c);
+ if (!(STK_COMP((uintptr_t)p, stack_end)
+ && STK_COMP(stack_start, (uintptr_t)p)))
+ break;
+# endif
+ }
#endif
if (SCHEME_FALSEP(name) || SCHEME_VOIDP(name)) {
/* Code uses special calling convention */
-#ifdef MZ_USE_JIT_PPC
+#if defined(MZ_USE_JIT_PPC) || defined(MZ_USE_JIT_ARM)
/* JIT_LOCAL2 has the next return address */
q = ((void **)p)[JIT_LOCAL2 >> JIT_LOG_WORD_SIZE];
#endif
#ifdef MZ_USE_JIT_I386
-
# ifdef MZ_USE_DWARF_LIBUNWIND
if (use_unw) {
q = (void *)unw_get_frame_pointer(&c);
} else
# endif
- q = *(void **)p;
+ q = ((void **)p)[NEXT_FRAME_OFFSET];
/* q is now the frame pointer for the former q,
so we can find the actual q */
@@ -368,7 +382,7 @@ Scheme_Object *scheme_native_stack_trace(void)
} else if (SCHEME_EOFP(name)) {
/* Stub (to mark start of running a module body, for example) */
/* JIT_LOCAL2 has the name to use */
-#ifdef MZ_USE_JIT_PPC
+#if defined(MZ_USE_JIT_PPC) || defined(MZ_USE_JIT_ARM)
name = *(Scheme_Object **)((void **)p)[JIT_LOCAL2 >> JIT_LOG_WORD_SIZE];
#endif
#ifdef MZ_USE_JIT_I386
@@ -450,7 +464,7 @@ Scheme_Object *scheme_native_stack_trace(void)
#endif
if (!use_unw) {
- q = *(void **)p;
+ q = ((void **)p)[NEXT_FRAME_OFFSET];
if (STK_COMP((uintptr_t)q, (uintptr_t)p))
break;
p = q;
diff --git a/src/racket/src/jitstate.c b/src/racket/src/jitstate.c
index 3880e7906f..2ceae22e7f 100644
--- a/src/racket/src/jitstate.c
+++ b/src/racket/src/jitstate.c
@@ -49,7 +49,7 @@ static volatile uintptr_t code_low, code_high;
static void *get_end_pointer(mz_jit_state *jitter)
{
- return jit_get_ip().ptr;
+ return jit_unadjust_ip(jit_get_ip());
}
int scheme_mz_retain_it(mz_jit_state *jitter, void *v)
@@ -204,6 +204,10 @@ void *scheme_generate_one(mz_jit_state *old_jitter,
#endif
}
+#ifdef MZ_USE_JIT_ARM
+ jit_get_cpu();
+#endif
+
while (1) {
memset(jitter, 0, sizeof(_jitter));
#ifdef SET_DEFAULT_LONG_JUMPS
@@ -282,7 +286,7 @@ void *scheme_generate_one(mz_jit_state *old_jitter,
}
#endif
- (void)jit_set_ip(buffer).ptr;
+ (void)jit_set_ip(buffer);
jitter->limit = (char *)buffer + size_pre_retained_double - padding;
if (known_size) {
jitter->retain_double_start = (double *)jitter->limit;
@@ -348,7 +352,7 @@ void *scheme_generate_one(mz_jit_state *old_jitter,
if (PAST_LIMIT() || (jitter->retain_start
&& (jitter->retained > num_retained))) {
scheme_console_printf("JIT buffer overflow: %p [%p,%p] (%d)!!\n",
- jit_get_ip().ptr,
+ jit_get_ip(),
buffer, jitter->limit,
!!jitter->retain_start);
abort();
@@ -366,11 +370,11 @@ void *scheme_generate_one(mz_jit_state *old_jitter,
scheme_signal_error("internal error: ended with unbox_extflonum");
if (known_size) {
/* That was in the permanent area, so return: */
- jit_flush_code(buffer, jit_get_ip().ptr);
+ jit_flush_code(buffer, jit_get_raw_ip());
return buffer;
} else {
/* Allocate permanent area and jit again: */
- known_size = ((uintptr_t)jit_get_ip().ptr) - (uintptr_t)buffer;
+ known_size = ((uintptr_t)jit_get_raw_ip()) - (uintptr_t)buffer;
/* Make sure room for pointers is aligned: */
if (known_size & (JIT_WORD_SIZE - 1)) {
known_size += (JIT_WORD_SIZE - (known_size & (JIT_WORD_SIZE - 1)));
diff --git a/src/racket/src/lightning/arm/asm-common.h b/src/racket/src/lightning/arm/asm-common.h
new file mode 100644
index 0000000000..63da549e28
--- /dev/null
+++ b/src/racket/src/lightning/arm/asm-common.h
@@ -0,0 +1,269 @@
+/******************************** -*- C -*- ****************************
+ *
+ * Dynamic assembler support
+ *
+ ***********************************************************************/
+
+
+/***********************************************************************
+ *
+ * Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
+ * Written by Paolo Bonzini.
+ *
+ * This file is part of GNU lightning.
+ *
+ * GNU lightning 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU lightning 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 GNU lightning; see the file COPYING.LESSER; if not, write to the
+ * Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ ***********************************************************************/
+
+
+#ifndef __lightning_asm_common_h
+#define __lightning_asm_common_h_
+
+#if 1
+# include
+# define jit_assert(x) assert(x)
+#else
+# define jit_assert(x) /* empty */
+#endif
+
+#define __WORDSIZE 32
+
+#define __jit_constructor /* empty */
+#define __jit_inline XFORM_NONGCING MZ_INLINE static
+
+typedef unsigned int _ui;
+
+typedef signed char _sc;
+typedef unsigned char _uc, jit_insn;
+typedef unsigned short _us;
+typedef unsigned int _ui;
+typedef long _sl;
+typedef unsigned long _ul;
+typedef struct jit_local_state jit_local_state;
+
+typedef struct jit_state jit_state;
+
+struct jit_local_state {
+ int long_jumps;
+ int nextarg_get;
+ int nextarg_put;
+ int nextarg_getf;
+ jit_insn *thumb;
+};
+
+struct {
+ _ui version : 4;
+ _ui extend : 1;
+ /* only generate thumb instructions for thumb2 */
+ _ui thumb : 1;
+ _ui vfp : 3;
+ _ui neon : 1;
+ _ui abi : 2;
+} jit_cpu;
+struct {
+ /* prevent using thumb instructions that set flags? */
+ _ui no_set_flags : 1;
+} jit_flags;
+
+typedef struct jit_state {
+ union {
+ jit_insn *pc;
+ _uc *uc_pc;
+ _us *us_pc;
+ _ui *ui_pc;
+ _ul *ul_pc;
+ } x;
+ struct jit_fp *fp;
+ jit_local_state jitl;
+} jit_state_t[1];
+
+#ifndef _ASM_SAFETY
+#define JITFAIL(MSG) 0
+#else
+#if (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) || (defined __GNUC__ && (__GNUC__ == 3 ? __GNUC_MINOR__ >= 2 : __GNUC__ > 3))
+#define JITFAIL(MSG) jit_fail(MSG, __FILE__, __LINE__, __func__)
+#elif defined __GNUC__
+#define JITFAIL(MSG) jit_fail(MSG, __FILE__, __LINE__, __FUNCTION__)
+#else
+#define JITFAIL(MSG) jit_fail(MSG, __FILE__, __LINE__, "(unknown)")
+#endif
+#endif
+
+#if (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) || (defined __GNUC__ && (__GNUC__ == 3 ? __GNUC_MINOR__ >= 2 : __GNUC__ > 3))
+#define JITSORRY(MSG) jit_fail("sorry, unimplemented: " MSG, __FILE__, __LINE__, __func__)
+#elif defined __GNUC__
+#define JITSORRY(MSG) jit_fail("sorry, unimplemented: " MSG, __FILE__, __LINE__, __FUNCTION__)
+#else
+#define JITSORRY(MSG) jit_fail("sorry, unimplemented: " MSG, __FILE__, __LINE__, "(unknown)")
+#endif
+
+#ifdef __GNUC__
+#define JIT_UNUSED __attribute__((__unused__))
+#else
+#define JIT_UNUSED
+#endif
+
+static int jit_fail(const char *, const char*, int, const char *) JIT_UNUSED;
+
+
+/* NextStep 2.0 cc is really gcc 1.93 but it defines __GNUC__ = 2 and
+ does not implement __extension__. But that compiler doesn't define
+ __GNUC_MINOR__. */
+#ifdef __GNUC__
+#if __GNUC__ < 2 || (defined(__NeXT__) && !__GNUC_MINOR__)
+#define __extension__
+#endif
+
+#define _TEMPD(type, var)
+
+#define _TEMP(type, var, val, body) __extension__ ({ \
+ register struct { type var } _jitl; _jitl.var = val; \
+ body; \
+})
+
+#else
+
+/* Between loading a global and calling a subroutine, we choose the lesser
+ * evil. */
+#define _TEMPD(type, var) static type var;
+#define _TEMP(type, var, val, body) ((var = val), body)
+
+#endif
+
+#define _jit_UC(X) ((_uc )(X))
+#define _jit_US(X) ((_us )(X))
+#define _jit_UI(X) ((_ui )(X))
+#define _jit_SI(X) ((int )(X))
+#define _jit_SL(X) ((_sl )(X))
+#define _jit_UL(X) ((_ul )(X))
+# define _PUC(X) ((_uc *)(X))
+# define _PUS(X) ((_us *)(X))
+# define _PUI(X) ((_ui *)(X))
+# define _PSI(X) ((int *)(X))
+# define _PSL(X) ((_sl *)(X))
+# define _PUL(X) ((_ul *)(X))
+
+#define _jit_B(B) _jit_UL(((*_jitp->x.uc_pc++)= _jit_UC((B)& 0xff)))
+#define _jit_W(W) _jit_UL(((*_jitp->x.us_pc++)= _jit_US((W)&0xffff)))
+#define _jit_I(I) _jit_UL(((*_jitp->x.ui_pc++)= _jit_UI((I) )))
+#define _jit_L(L) _jit_UL(((*_jitp->x.ul_pc++)= _jit_UL((L) )))
+#define _jit_I_noinc(I) _jit_UL(((*_jitp->x.ui_pc)= _jit_UI((I) )))
+
+#define _MASK(N) ((unsigned long)((1L<<(N)))-1L)
+#define _siP(N,I) (!((((unsigned long)(I))^(((unsigned long)(I))<<1))&~_MASK(N)))
+#define _uiP(N,I) (!(((unsigned long)(I))&~_MASK(N)))
+#define _suiP(N,I) (_siP(N,I) | _uiP(N,I))
+
+#ifndef _ASM_SAFETY
+#define _ck_s(W,I) (_jit_UL(I) & _MASK(W))
+#define _ck_u(W,I) (_jit_UL(I) & _MASK(W))
+#define _ck_su(W,I) (_jit_UL(I) & _MASK(W))
+#define _ck_d(W,I) (_jit_UL(I) & _MASK(W))
+#else
+#define _ck_s(W,I) (_siP(W,I) ? (_jit_UL(I) & _MASK(W)) : JITFAIL( "signed integer `"#I"' too large for "#W"-bit field"))
+#define _ck_u(W,I) (_uiP(W,I) ? (_jit_UL(I) & _MASK(W)) : JITFAIL("unsigned integer `"#I"' too large for "#W"-bit field"))
+#define _ck_su(W,I) (_suiP(W,I) ? (_jit_UL(I) & _MASK(W)) : JITFAIL( "integer `"#I"' too large for "#W"-bit field"))
+#define _ck_d(W,I) (_siP(W,I) ? (_jit_UL(I) & _MASK(W)) : JITFAIL( "displacement `"#I"' too large for "#W"-bit field"))
+#endif
+
+#define _s0P(I) ((I)==0)
+#define _s8P(I) _siP(8,I)
+#define _s16P(I) _siP(16,I)
+#define _s20P(I) _siP(20,I)
+#define _s24P(I) _siP(24,I)
+#define _s32P(I) _siP(32,I)
+#define _u8P(I) _uiP(8,I)
+#define _u16P(I) _uiP(16,I)
+#define _u32P(I) _uiP(32,I)
+
+#define _su8(I) _ck_su(8,I)
+#define _su16(I) _ck_su(16,I)
+
+#define _s1(I) _ck_s( 1,I)
+#define _s2(I) _ck_s( 2,I)
+#define _s3(I) _ck_s( 3,I)
+#define _s4(I) _ck_s( 4,I)
+#define _s5(I) _ck_s( 5,I)
+#define _s6(I) _ck_s( 6,I)
+#define _s7(I) _ck_s( 7,I)
+#define _s8(I) _ck_s( 8,I)
+#define _s9(I) _ck_s( 9,I)
+#define _s10(I) _ck_s(10,I)
+#define _s11(I) _ck_s(11,I)
+#define _s12(I) _ck_s(12,I)
+#define _s13(I) _ck_s(13,I)
+#define _s14(I) _ck_s(14,I)
+#define _s15(I) _ck_s(15,I)
+#define _s16(I) _ck_s(16,I)
+#define _s17(I) _ck_s(17,I)
+#define _s18(I) _ck_s(18,I)
+#define _s19(I) _ck_s(19,I)
+#define _s20(I) _ck_s(20,I)
+#define _s21(I) _ck_s(21,I)
+#define _s22(I) _ck_s(22,I)
+#define _s23(I) _ck_s(23,I)
+#define _s24(I) _ck_s(24,I)
+#define _s25(I) _ck_s(25,I)
+#define _s26(I) _ck_s(26,I)
+#define _s27(I) _ck_s(27,I)
+#define _s28(I) _ck_s(28,I)
+#define _s29(I) _ck_s(29,I)
+#define _s30(I) _ck_s(30,I)
+#define _s31(I) _ck_s(31,I)
+#if __WORDSIZE == 32
+# define _s32(I) (I)
+#else
+# define _s32(I) _ck_s(32,I)
+#endif
+#define _u1(I) _ck_u( 1,I)
+#define _u2(I) _ck_u( 2,I)
+#define _u3(I) _ck_u( 3,I)
+#define _u4(I) _ck_u( 4,I)
+#define _u5(I) _ck_u( 5,I)
+#define _u6(I) _ck_u( 6,I)
+#define _u7(I) _ck_u( 7,I)
+#define _u8(I) _ck_u( 8,I)
+#define _u9(I) _ck_u( 9,I)
+#define _u10(I) _ck_u(10,I)
+#define _u11(I) _ck_u(11,I)
+#define _u12(I) _ck_u(12,I)
+#define _u13(I) _ck_u(13,I)
+#define _u14(I) _ck_u(14,I)
+#define _u15(I) _ck_u(15,I)
+#define _u16(I) _ck_u(16,I)
+#define _u17(I) _ck_u(17,I)
+#define _u18(I) _ck_u(18,I)
+#define _u19(I) _ck_u(19,I)
+#define _u20(I) _ck_u(20,I)
+#define _u21(I) _ck_u(21,I)
+#define _u22(I) _ck_u(22,I)
+#define _u23(I) _ck_u(23,I)
+#define _u24(I) _ck_u(24,I)
+#define _u25(I) _ck_u(25,I)
+#define _u26(I) _ck_u(26,I)
+#define _u27(I) _ck_u(27,I)
+#define _u28(I) _ck_u(28,I)
+#define _u29(I) _ck_u(29,I)
+#define _u30(I) _ck_u(30,I)
+#define _u31(I) _ck_u(31,I)
+#if __WORDSIZE == 32
+# define _u32(I) (I)
+#else
+# define _u32(I) _ck_u(32,I)
+#endif
+
+#endif /* __lightning_asm_common_h */
diff --git a/src/racket/src/lightning/arm/asm.h b/src/racket/src/lightning/arm/asm.h
new file mode 100644
index 0000000000..276e7cf937
--- /dev/null
+++ b/src/racket/src/lightning/arm/asm.h
@@ -0,0 +1,2220 @@
+/******************************** -*- C -*- ****************************
+ *
+ * Run-time assembler for the arm
+ *
+ ***********************************************************************/
+
+/***********************************************************************
+ *
+ * Copyright 2011 Free Software Foundation
+ *
+ * This file is part of GNU lightning.
+ *
+ * GNU lightning 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU lightning 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 GNU lightning; see the file COPYING.LESSER; if not, write to the
+ * Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * Authors:
+ * Paulo Cesar Pereira de Andrade
+ ***********************************************************************/
+
+#ifndef __lightning_asm_h
+#define __lightning_asm_h
+
+typedef enum {
+ _R0, /* argument / result */
+ _R1, /* argument */
+ _R2, /* argument */
+ _R3, /* argument */
+ _R4, /* variable */
+ _R5, /* variable */
+ _R6, /* variable */
+ _R7, /* variable */
+ _R8, /* variable */
+ _R9, /* variable */
+ _R10, /* sl - stack limit */
+ _R11, /* fp - frame pointer */
+ _R12, /* ip - temporary */
+ _R13, /* sp - stack pointer */
+ _R14, /* lr - link register */
+ _R15, /* pc - program counter */
+} jit_gpr_t;
+
+#define JIT_RET _R0
+#define JIT_PC _R15
+#define JIT_LR _R14
+#define JIT_SP _R13
+#define JIT_FP _R11
+#define JIT_TMP _R3
+#define JIT_TMP2 _R7
+#define JIT_FTMP JIT_TMP2
+
+/* must use blx to call functions or jit instruction set matches runtime? */
+#define jit_exchange_p() 1
+
+/* _VxxxQ macros mean _Q0=_D0, _Q1=_D2, ... */
+typedef enum {
+ _S0, _D0 = _S0, _Q0 = _D0,
+ _S1,
+ _S2, _D1 = _S2,
+ _S3,
+ _S4, _D2 = _S4, _Q1 = _D2,
+ _S5,
+ _S6, _D3 = _S6,
+ _S7,
+ _S8, _D4 = _S8, _Q2 = _D4,
+ _S9,
+ _S10, _D5 = _S10,
+ _S11,
+ _S12, _D6 = _S12, _Q3 = _D6,
+ _S13,
+ _S14, _D7 = _S14,
+ _S15,
+ _S16, _D8 = _S16, _Q4 = _D8,
+ _S17,
+ _S18, _D9 = _S18,
+ _S19,
+ _S20, _D10 = _S20, _Q5 = _D10,
+ _S21,
+ _S22, _D11 = _S22,
+ _S23,
+ _S24, _D12 = _S24, _Q6 = _D12,
+ _S25,
+ _S26, _D13 = _S26,
+ _S27,
+ _S28, _D14 = _S28, _Q7 = _D14,
+ _S29,
+ _S30, _D15 = _S30,
+ _S31,
+ JIT_FPRET, /* for abstraction of returning a float/double result */
+} jit_fpr_t;
+
+/* match vfpv3 result */
+#define NAN_TO_INT_IS_ZERO 1
+
+#define jit_thumb_p() jit_cpu.thumb
+#define jit_armv6_p() (jit_cpu.version >= 6)
+typedef union _jit_thumb_t {
+ int i;
+ short s[2];
+} jit_thumb_t;
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+# define _jit_WW(i, j) do { _jit_W(j); _jit_W(i); } while (0)
+# define code2thumb(t0, t1, c0, c1) do { t1 = c0; t0 = c1; } while (0)
+# define thumb2code(t0, t1, c0, c1) do { c0 = t1; c1 = t0; } while (0)
+#else
+# define _jit_WW(i, j) do { _jit_W(i); _jit_W(j); } while (0)
+# define code2thumb(t0, t1, c0, c1) do { t0 = c0; t1 = c1; } while (0)
+# define thumb2code(t0, t1, c0, c1) do { c0 = t0; c1 = t1; } while (0)
+#endif
+
+#define ARM_CC_EQ 0x00000000 /* Z=1 */
+#define ARM_CC_NE 0x10000000 /* Z=0 */
+#define ARM_CC_HS 0x20000000 /* C=1 */
+# define ARM_CC_CS ARM_CC_HS
+#define ARM_CC_LO 0x30000000 /* C=0 */
+# define ARM_CC_CC ARM_CC_LO
+#define ARM_CC_MI 0x40000000 /* N=1 */
+#define ARM_CC_PL 0x50000000 /* N=0 */
+#define ARM_CC_VS 0x60000000 /* V=1 */
+#define ARM_CC_VC 0x70000000 /* V=0 */
+#define ARM_CC_HI 0x80000000 /* C=1 && Z=0 */
+#define ARM_CC_LS 0x90000000 /* C=0 || Z=1 */
+#define ARM_CC_GE 0xa0000000 /* N=V */
+#define ARM_CC_LT 0xb0000000 /* N!=V */
+#define ARM_CC_GT 0xc0000000 /* Z=0 && N=V */
+#define ARM_CC_LE 0xd0000000 /* Z=1 || N!=V */
+#define ARM_CC_AL 0xe0000000 /* always */
+#define ARM_CC_NV 0xf0000000 /* reserved */
+
+#define ARM_MOV 0x01a00000
+#define THUMB_MOV 0x4600
+#define ARM_MOVWI 0x03000000
+#define THUMB_MOVI 0x2000
+#define THUMB2_MOVI 0xf0400000
+#define THUMB2_MOVWI 0xf2400000
+#define ARM_MOVTI 0x03400000
+#define THUMB2_MOVTI 0xf2c00000
+#define ARM_MVN 0x01e00000
+#define THUMB_MVN 0x43c0
+#define THUMB2_MVN 0xea600000
+#define THUMB2_MVNI 0xf0600000
+#define ARM_MRC 0x0e100010
+#define ARM_MRRC 0x0c500000
+#define ARM_MRS 0x010f0000
+#define ARM_MSRI 0x03200000
+#define ARM_MSR 0x0120f000
+
+#define ARM_I 0x02000000 /* immediate */
+#define ARM_S 0x00100000 /* set flags */
+#define ARM_ADD 0x00800000
+#define THUMB_ADD 0x1800
+#define THUMB_ADDX 0x4400
+#define THUMB2_ADD 0xeb000000
+#define THUMB_ADDI3 0x1c00
+#define THUMB_ADDI8 0x3000
+#define THUMB2_ADDI 0xf1000000
+#define THUMB2_ADDWI 0xf2000000
+#define ARM_ADC 0x00a00000
+#define THUMB_ADC 0x4140
+#define THUMB2_ADC 0xeb400000
+#define THUMB2_ADCI 0xf1400000
+#define ARM_SUB 0x00400000
+#define THUMB_SUB 0x1a00
+#define THUMB2_SUB 0xeba00000
+#define THUMB_SUBI3 0x1e00
+#define THUMB_SUBI8 0x3800
+#define THUMB2_SUBI 0xf1a00000
+#define THUMB2_SUBWI 0xf2a00000
+#define ARM_SBC 0x00c00000
+#define THUMB_SBC 0x4180
+#define THUMB2_SBC 0xeb600000
+#define THUMB2_SBCI 0xf1600000
+#define ARM_RSB 0x00600000
+#define THUMB2_RSB 0xebc00000
+#define THUMB_RSBI 0x4240
+#define THUMB2_RSBI 0xf1c00000
+#define ARM_MUL 0x00000090
+#define THUMB_MUL 0x4340
+#define THUMB2_MUL 0xfb00f000
+#define ARM_SMULL 0x00c00090
+#define THUMB2_SMULL 0xfb800000
+#define ARM_UMULL 0x00800090
+#define THUMB2_UMULL 0xfba00000
+#define THUMB2_SDIV 0xfb90f0f0
+#define THUMB2_UDIV 0xfbb0f0f0
+
+#define ARM_AND 0x00000000
+#define THUMB_AND 0x4000
+#define THUMB2_AND 0xea000000
+#define THUMB2_ANDI 0xf0000000
+#define ARM_BIC 0x01c00000
+#define THUMB2_BIC 0xea200000
+#define THUMB2_BICI 0xf0200000
+#define ARM_ORR 0x01800000
+#define THUMB_ORR 0x4300
+#define THUMB2_ORR 0xea400000
+#define THUMB2_ORRI 0xf0400000
+#define ARM_EOR 0x00200000
+#define THUMB_EOR 0x4040
+#define THUMB2_EOR 0xea800000
+#define THUMB2_EORI 0xf0800000
+#define ARM_REV 0x06bf0f30
+#define THUMB_REV 0xba00
+#define THUMB2_REV 0xfa90f080
+#define ARM_REV16 0x06bf0fb0
+#define THUMB_REV16 0xba40
+#define THUMB2_REV16 0xfa90f090
+#define ARM_SXTB 0x06af0070
+#define THUMB_SXTB 0xb240
+#define THUMB2_SXTB 0xfa4f0080
+#define ARM_UXTB 0x06ef0070
+#define THUMB_UXTB 0xb2c0
+#define THUMB2_UXTB 0xfa5f0080
+#define ARM_SXTH 0x06bf0070
+#define THUMB_SXTH 0xb200
+#define THUMB2_SXTH 0xfa0f0080
+#define ARM_UXTH 0x06ff0070
+#define THUMB_UXTH 0xb280
+#define THUMB2_UXTH 0xfa1f0080
+#define ARM_XTR8 0x00000400 /* ?xt? rotate 8 bits */
+#define ARM_XTR16 0x00000800 /* ?xt? rotate 16 bits */
+#define ARM_XTR24 0x00000c00 /* ?xt? rotate 24 bits */
+
+#define ARM_SHIFT 0x01a00000
+#define ARM_R 0x00000010 /* register shift */
+#define ARM_LSL 0x00000000
+#define THUMB_LSL 0x4080
+#define THUMB2_LSL 0xfa00f000
+#define THUMB_LSLI 0x0000
+#define THUMB2_LSLI 0xea4f0000
+#define ARM_LSR 0x00000020
+#define THUMB_LSR 0x40c0
+#define THUMB2_LSR 0xfa20f000
+#define THUMB_LSRI 0x0800
+#define THUMB2_LSRI 0xea4f0010
+#define ARM_ASR 0x00000040
+#define THUMB_ASR 0x4100
+#define THUMB2_ASR 0xfa40f000
+#define THUMB_ASRI 0x1000
+#define THUMB2_ASRI 0xea4f0020
+#define ARM_ROR 0x00000060
+#define ARM_PKH 0x06800010 /* v6T2,v7 */
+
+#define ARM_CMP 0x01500000
+#define THUMB_CMP 0x4280
+#define THUMB_CMPX 0x4500
+#define THUMB2_CMP 0xebb00000
+#define THUMB_CMPI 0x2800
+#define THUMB2_CMPI 0xf1b00000
+#define ARM_CMN 0x01700000
+#define THUMB_CMN 0x42c0
+#define THUMB2_CMN 0xeb100000
+#define THUMB2_CMNI 0xf1100000
+#define ARM_TST 0x01100000
+#define THUMB_TST 0x4200
+#define THUMB2_TST 0xea100000
+#define THUMB2_TSTI 0xf0100000
+#define ARM_TEQ 0x01300000
+
+/* branch */
+#define ARM_BX 0x012fff10
+#define ARM_BLX 0x012fff30
+#define THUMB_BLX 0x4780
+#define ARM_BLXI 0xfa000000
+#define THUMB2_BLXI 0xf000c000
+#define ARM_B 0x0a000000
+#define THUMB_CC_B 0xd000
+#define THUMB_B 0xe000
+#define THUMB2_CC_B 0xf0008000
+#define THUMB2_B 0xf0009000
+#define ARM_BLI 0x0b000000
+#define THUMB2_BLI 0xf000d000
+
+/* ldr/str */
+#define ARM_P 0x00800000 /* positive offset
+ * actually, the errata manual
+ * calls this to U field and
+ * 1<<24 the P field */
+#define THUMB2_P 0x00000400
+#define THUMB2_U 0x00000200
+#define THUMB2_W 0x00000100
+#define ARM_LDRSB 0x011000d0
+#define THUMB_LDRSB 0x5600
+#define THUMB2_LDRSB 0xf9100000
+#define ARM_LDRSBI 0x015000d0
+#define THUMB2_LDRSBI 0xf9100c00
+#define THUMB2_LDRSBWI 0xf9900000
+#define ARM_LDRB 0x07500000
+#define THUMB_LDRB 0x5c00
+#define THUMB2_LDRB 0xf8100000
+#define ARM_LDRBI 0x05500000
+#define THUMB_LDRBI 0x7800
+#define THUMB2_LDRBI 0xf8100c00
+#define THUMB2_LDRBWI 0xf8900000
+#define ARM_LDRSH 0x011000f0
+#define THUMB_LDRSH 0x5e00
+#define THUMB2_LDRSH 0xf9300000
+#define ARM_LDRSHI 0x015000f0
+#define THUMB2_LDRSHI 0xf9300c00
+#define THUMB2_LDRSHWI 0xf9b00000
+#define ARM_LDRH 0x011000b0
+#define THUMB_LDRH 0x5a00
+#define THUMB2_LDRH 0xf8300000
+#define ARM_LDRHI 0x015000b0
+#define THUMB_LDRHI 0x8800
+#define THUMB2_LDRHI 0xf8300c00
+#define THUMB2_LDRHWI 0xf8b00000
+#define ARM_LDR 0x07100000
+#define THUMB_LDR 0x5800
+#define THUMB2_LDR 0xf8500000
+#define ARM_LDRI 0x05100000
+#define THUMB_LDRI 0x6800
+#define THUMB_LDRISP 0x9800
+#define THUMB2_LDRI 0xf8500c00 /* manual says v6t2/v7; does not work */
+#define THUMB2_LDRWI 0xf8d00000
+#define ARM_LDRD 0x010000d0
+#define ARM_LDRDI 0x014000d0
+#define THUMB2_LDRDI 0xe8500000
+#define ARM_STRB 0x07400000
+#define THUMB_STRB 0x5400
+#define THUMB2_STRB 0xf8000000
+#define ARM_STRBI 0x05400000
+#define THUMB_STRBI 0x7000
+#define THUMB2_STRBI 0xf8000c00
+#define THUMB2_STRBWI 0xf8800000
+#define ARM_STRH 0x010000b0
+#define THUMB_STRH 0x5200
+#define THUMB2_STRH 0xf8200000
+#define ARM_STRHI 0x014000b0
+#define THUMB_STRHI 0x8000
+#define THUMB2_STRHI 0xf8200c00
+#define THUMB2_STRHWI 0xf8a00000
+#define ARM_STR 0x07000000
+#define THUMB_STR 0x5000
+#define THUMB2_STR 0xf8400000
+#define ARM_STRI 0x05000000
+#define THUMB_STRI 0x6000
+#define THUMB_STRISP 0x9000
+#define THUMB2_STRI 0xf8400c00
+#define THUMB2_STRWI 0xf8c00000
+#define ARM_STRD 0x010000f0
+#define ARM_STRDI 0x014000f0
+#define THUMB2_STRDI 0xe8400000 /* manual says v6t2/v7; does not work */
+
+/* ldm/stm */
+#define ARM_M 0x08000000
+#define ARM_M_L 0x00100000 /* load; store if not set */
+#define ARM_M_I 0x00800000 /* inc; dec if not set */
+#define ARM_M_B 0x01000000 /* before; after if not set */
+#define ARM_M_U 0x00200000 /* update Rn */
+#define THUMB2_LDM_W 0x00200000
+#define THUMB2_LDM_P 0x00008000
+#define THUMB2_LDM_M 0x00004000
+#define THUMB_LDMIA 0xc800
+#define THUMB2_LDMIA 0xe8900000
+#define THUMB2_LDMDB 0xe9100000
+#define THUMB_PUSH 0xb400
+#define THUMB2_PUSH 0xe92d0000
+#define THUMB_POP 0xbc00
+#define THUMB2_POP 0xe8bd0000
+
+/* misc */
+#define ARM_CLZ 0x016f0f10
+#define ARM_PLD 0xf750f000
+#define ARM_PLDW 0xf710f000
+#define ARM_PLDI 0xf510f000
+#define ARM_PLDWI 0xf510f000
+#define ARM_PLDLI 0xf55ff000
+#define ARM_PLD_U 0x00800000
+#define ARM_PLII 0xf4d0f000
+#define ARM_PLINI 0xf450f000
+#define ARM_PLI 0xf6d0f000
+#define ARM_PLIN 0xf650f000
+
+#define FPSCR_N 0x80000000/* Negative condition code flag */
+#define FPSCR_Z 0x40000000/* Zero condition code flag */
+#define FPSCR_C 0x20000000/* Carry condition code flag */
+#define FPSCR_V 0x10000000/* Overflow condition code flag */
+#define FPSCR_QC 0x08000000/* Cumulative saturation flag */
+#define FPSCR_AHP 0x04000000/* Alternative half-precision (unset is IEEE format) */
+#define FPSCR_DN 0x02000000/* Default NaN mode */
+#define FPSCR_FZ 0x01000000/* Flush to zero (unset is fully IEEE-754 compliant) */
+#define FPSCR_RMASK 0x00c00000
+# define FPSCR_RN 0x00000000 /* Round to Nearest */
+# define FPSCR_RP 0x00400000 /* Round towards Plus Infinity */
+# define FPSCR_RM 0x00800000 /* Round towards Minus Infinity */
+# define FPSCR_RZ 0x00c00000 /* Round towards Zero */
+#define FPSCR_STRIDE 0x00300000
+#define FPSCR_RES1 0x00080000/* Reserved, UNK/SBZP */
+#define FPSCR_LEN 0x00070000
+#define FPSCR_IDE 0x00008000/* Input Denormal exception trap enable */
+#define FPSCR_IXE 0x00001000/* Inexact exception trap enable */
+#define FPSCR_UFE 0x00000800/* Underflow exception trap enable */
+#define FPSCR_OFE 0x00000400/* Overflow exception trap enable */
+#define FPSCR_DZE 0x00000200/* Division by zero exception trap enable */
+#define FPSCR_IOE 0x00000100/* Invalid Operation exception trap enable */
+#define FPSCR_IDC 0x00000080/* Input Denormal cumulative exception flag */
+#define FPSCR_RES0 0x00000060/* Reserved, UNK/SBZP */
+#define FPSCR_IXC 0x00000010/* Inexact cumulative exception flag */
+#define FPSCR_UFC 0x00000008/* Underflow cumulative exception flag */
+#define FPSCR_OFC 0x00000004/* Overflow cumulative exception flag */
+#define FPSCR_DZC 0x00000002/* Division by zero cumulative exception flag */
+#define FPSCR_IOC 0x00000001/* Invalid Operation cumulative exception flag */
+
+/***********************************************************************
+ * VFPv2 and VFPv3 (encoding T2/A2) instructions
+ ***********************************************************************/
+#define ARM_V_E 0x00000080 /* ARM_VCMP exception if NaN arg(s) */
+#define ARM_V_Z 0x00010000 /* ARM_VCMP with zero */
+#define ARM_V_F64 0x00000100 /* Undefined in single precision only variant */
+#define ARM_VADD_F 0x0e300a00
+#define ARM_VSUB_F 0x0e300a40
+#define ARM_VMUL_F 0x0e200a00
+#define ARM_VDIV_F 0x0e800a00
+#define ARM_VABS_F 0x0eb00ac0
+#define ARM_VNEG_F 0x0eb10a40
+#define ARM_VSQRT_F 0x0eb10ac0
+#define ARM_VMOV_F 0x0eb00a40
+#define ARM_VMOV_A_S 0x0e100a10 /* vmov rn, sn */
+#define ARM_VMOV_S_A 0x0e000a10 /* vmov sn, rn */
+#define ARM_VMOV_AA_D 0x0c500b10 /* vmov rn,rn, dn */
+#define ARM_VMOV_D_AA 0x0c400b10 /* vmov dn, rn,rn */
+#define ARM_VCMP 0x0eb40a40
+#define ARM_VMRS 0x0ef10a10
+#define ARM_VMSR 0x0ee10a10
+#define ARM_VCVT_2I 0x00040000 /* to integer */
+#define ARM_VCVT_2S 0x00010000 /* to signed */
+#define ARM_VCVT_RS 0x00000080 /* round to zero or signed */
+#define ARM_VCVT 0x0eb80a40
+#define ARM_VCVT_S32_F32 ARM_VCVT|ARM_VCVT_2I|ARM_VCVT_2S|ARM_VCVT_RS
+#define ARM_VCVT_U32_F32 ARM_VCVT|ARM_VCVT_2I|ARM_VCVT_RS
+#define ARM_VCVT_S32_F64 ARM_VCVT|ARM_VCVT_2I|ARM_VCVT_2S|ARM_VCVT_RS|ARM_V_F64
+#define ARM_VCVT_U32_F64 ARM_VCVT|ARM_VCVT_2I|ARM_VCVT_RS|ARM_V_F64
+#define ARM_VCVT_F32_S32 ARM_VCVT|ARM_VCVT_RS
+#define ARM_VCVT_F32_U32 ARM_VCVT
+#define ARM_VCVT_F64_S32 ARM_VCVT|ARM_VCVT_RS|ARM_V_F64
+#define ARM_VCVT_F64_U32 ARM_VCVT|ARM_V_F64
+#define ARM_VCVT_F 0x0eb70ac0
+#define ARM_VCVT_F32_F64 ARM_VCVT_F
+#define ARM_VCVT_F64_F32 ARM_VCVT_F|ARM_V_F64
+
+/* does not set bit 7, meaning to use rounding mode of FPSCR */
+#define ARM_VCVTR_S32_F32 ARM_VCVT|ARM_VCVT_2I|ARM_VCVT_2S
+#define ARM_VCVTR_U32_F32 ARM_VCVT|ARM_VCVT_2I
+#define ARM_VCVTR_S32_F64 ARM_VCVT|ARM_VCVT_2I|ARM_VCVT_2S|ARM_V_F64
+#define ARM_VCVTR_U32_F64 ARM_VCVT|ARM_VCVT_2I|ARM_V_F64
+
+/***********************************************************************
+ * NEON instructions (encoding T1/A1) (condition must always be ARM_CC_NV)
+ ***********************************************************************/
+#define ARM_V_D 0x00400000
+#define ARM_V_N 0x00000080
+#define ARM_V_Q 0x00000040
+#define ARM_V_M 0x00000020
+#define ARM_V_U 0x01000000
+#define ARM_V_I16 0x00100000
+#define ARM_V_I32 0x00200000
+#define ARM_V_I64 0x00300000
+#define ARM_V_S16 0x00040000
+#define ARM_V_S32 0x00080000
+
+#define ARM_VADD_I 0x02000800
+#define ARM_VQADD_I 0x02000010 /* sets flag on overflow/carry */
+#define ARM_VADDL_I 0x02800000 /* q=d+d */
+#define ARM_VADDW_I 0x02800100 /* q=q+d */
+#define ARM_VSUB_I 0x03000800
+#define ARM_VQSUB_I 0x02000210 /* sets flag on overflow/carry */
+#define ARM_VSUBL_I 0x02800200
+#define ARM_VSUBW_I 0x02800300
+#define ARM_VMUL_I 0x02000910
+#define ARM_VMULL_I 0x02800c00
+
+#define ARM_VABS_I 0x03b10300
+#define ARM_VQABS_I 0x03b00700 /* sets flag on overflow */
+#define ARM_VNEG_I 0x03b10380
+#define ARM_VQNEG_I 0x03b00780 /* sets flag on overflow */
+
+#define ARM_VAND 0x02000110
+#define ARM_VBIC 0x02100110
+#define ARM_VORR 0x02200110
+#define ARM_VORN 0x02300110
+#define ARM_VEOR 0x03000110
+#define ARM_VMOVL_S8 0x00080000
+#define ARM_VMOVL_S16 0x00100000
+#define ARM_VMOVL_S32 0x00200000
+#define ARM_VMOVL_I 0x02800a10
+
+#define ARM_VMVSI 0x0eb00a00
+#define ARM_VMOVI 0x02800010
+#define ARM_VMVNI 0x02800030
+
+#define ARM_VLDR 0x0d100a00
+#define ARM_VSTR 0x0d000a00
+#define ARM_VM 0x0c000a00
+
+/***********************************************************************
+ * Advanced SIMD (encoding T2/A2) instructions
+ ***********************************************************************/
+#define ARM_VMOV_ADV_U 0x00800000 /* zero extend, sign extend if unset */
+#define ARM_VMOV_ADV_8 0x00400000
+#define ARM_VMOV_ADV_16 0x00000020
+#define ARM_VMOV_A_D 0x0e100b10
+#define ARM_VMOV_D_A 0x0e000b10
+
+static int
+encode_vfp_double(int mov, int inv, unsigned lo, unsigned hi)
+{
+ int code, mode, imm, mask;
+
+ if (hi != lo) {
+ if (mov && !inv) {
+ /* (I64)
+ * aaaaaaaabbbbbbbbccccccccddddddddeeeeeeeeffffffffgggggggghhhhhhhh
+ */
+ for (mode = 0, mask = 0xff; mode < 4; mask <<= 8, mode++) {
+ imm = lo & mask;
+ if (imm != mask && imm != 0)
+ goto fail;
+ imm = hi & mask;
+ if (imm != mask && imm != 0)
+ goto fail;
+ }
+ mode = 0xe20;
+ imm = (((hi & 0x80000000) >> 24) | ((hi & 0x00800000) >> 17) |
+ ((hi & 0x00008000) >> 10) | ((hi & 0x00000080) >> 3) |
+ ((lo & 0x80000000) >> 28) | ((lo & 0x00800000) >> 21) |
+ ((lo & 0x00008000) >> 14) | ((lo & 0x00000080) >> 7));
+ goto success;
+ }
+ goto fail;
+ }
+ /* (I32)
+ * 00000000 00000000 00000000 abcdefgh
+ * 00000000 00000000 abcdefgh 00000000
+ * 00000000 abcdefgh 00000000 00000000
+ * abcdefgh 00000000 00000000 00000000 */
+ for (mode = 0, mask = 0xff; mode < 4; mask <<= 8, mode++) {
+ if ((lo & mask) == lo) {
+ imm = lo >> (mode << 3);
+ mode <<= 9;
+ goto success;
+ }
+ }
+ /* (I16)
+ * 00000000 abcdefgh 00000000 abcdefgh
+ * abcdefgh 00000000 abcdefgh 00000000 */
+ for (mode = 0, mask = 0xff; mode < 2; mask <<= 8, mode++) {
+ if ((lo & mask) && ((lo & (mask << 16)) >> 16) == (lo & mask)) {
+ imm = lo >> (mode << 3);
+ mode = 0x800 | (mode << 9);
+ goto success;
+ }
+ }
+ if (mov) {
+ /* (I32)
+ * 00000000 00000000 abcdefgh 11111111
+ * 00000000 abcdefgh 11111111 11111111 */
+ for (mode = 0, mask = 0xff; mode < 2;
+ mask = (mask << 8) | 0xff, mode++) {
+ if ((lo & mask) == mask &&
+ !((lo & ~mask) >> 8) &&
+ (imm = lo >> (8 + (mode << 8)))) {
+ mode = 0xc00 | (mode << 8);
+ goto success;
+ }
+ }
+ if (!inv) {
+ /* (F32)
+ * aBbbbbbc defgh000 00000000 00000000
+ * from the ARM Architecture Reference Manual:
+ * In this entry, B = NOT(b). The bit pattern represents the
+ * floating-point number (-1)^s* 2^exp * mantissa, where
+ * S = UInt(a),
+ * exp = UInt(NOT(b):c:d)-3 and
+ * mantissa = (16+UInt(e:f:g:h))/16. */
+ if ((lo & 0x7ffff) == 0 &&
+ (((lo & 0x7e000000) == 0x3e000000) ||
+ ((lo & 0x7e000000) == 0x40000000))) {
+ mode = 0xf00;
+ imm = ((lo >> 24) & 0x80) | ((lo >> 19) & 0x7f);
+ goto success;
+ }
+ }
+ }
+
+fail:
+ /* need another approach (load from memory, move from arm register, etc) */
+ return (-1);
+
+success:
+ code = inv ? ARM_VMVNI : ARM_VMOVI;
+ switch ((mode & 0xf00) >> 8) {
+ case 0x0: case 0x2: case 0x4: case 0x6:
+ case 0x8: case 0xa:
+ if (inv) mode |= 0x20;
+ if (!mov) mode |= 0x100;
+ break;
+ case 0x1: case 0x3: case 0x5: case 0x7:
+ /* should actually not reach here */
+ jit_assert(!inv);
+ case 0x9: case 0xb:
+ jit_assert(!mov);
+ break;
+ case 0xc: case 0xd:
+ /* should actually not reach here */
+ jit_assert(inv);
+ case 0xe:
+ jit_assert(mode & 0x20);
+ jit_assert(mov && !inv);
+ break;
+ default:
+ jit_assert(!(mode & 0x20));
+ break;
+ }
+ imm = ((imm & 0x80) << 17) | ((imm & 0x70) << 12) | (imm & 0x0f);
+ code |= mode | imm;
+ if (jit_thumb_p()) {
+ if (code & 0x1000000)
+ code |= 0xff000000;
+ else
+ code |= 0xef000000;
+ }
+ else
+ code |= ARM_CC_NV;
+ return (code);
+}
+
+#define arm_vodi(oi,r0) _arm_vodi(_jitp,oi,r0)
+__jit_inline void
+_arm_vodi(jit_state_t _jitp, int oi, int r0)
+{
+ jit_thumb_t thumb;
+ jit_assert(!(oi & 0x0000f000));
+ jit_assert(!(r0 & 1)); r0 >>= 1;
+ thumb.i = oi|(_u4(r0)<<12);
+ if (jit_thumb_p())
+ _jit_WW(thumb.s[0], thumb.s[1]);
+ else
+ _jit_I(thumb.i);
+}
+
+#define arm_voqi(oi,r0) _arm_voqi(_jitp,oi,r0)
+__jit_inline void
+_arm_voqi(jit_state_t _jitp, int oi, int r0)
+{
+ jit_thumb_t thumb;
+ jit_assert(!(oi & 0x0000f000));
+ jit_assert(!(r0 & 3)); r0 >>= 1;
+ thumb.i = oi|(_u4(r0)<<12);
+ if (jit_thumb_p())
+ _jit_WW(thumb.s[0], thumb.s[1]);
+ else
+ _jit_I(thumb.i);
+}
+
+#define arm_vo_ss(o,r0,r1) _arm_cc_vo_ss(_jitp,ARM_CC_NV,o,r0,r1)
+#define arm_cc_vo_ss(cc,o,r0,r1) _arm_cc_vo_ss(_jitp,cc,o,r0,r1)
+__jit_inline void
+_arm_cc_vo_ss(jit_state_t _jitp, int cc, int o, int r0, int r1)
+{
+ jit_thumb_t thumb;
+ jit_assert(!(cc & 0x0fffffff));
+ jit_assert(!(o & 0xf000f00f));
+ if (r0 & 1) o |= ARM_V_D; r0 >>= 1;
+ if (r1 & 1) o |= ARM_V_M; r1 >>= 1;
+ thumb.i = cc|o|(_u4(r0)<<12)|_u4(r1);
+ if (jit_thumb_p())
+ _jit_WW(thumb.s[0], thumb.s[1]);
+ else
+ _jit_I(thumb.i);
+}
+
+#define arm_vo_dd(o,r0,r1) _arm_cc_vo_dd(_jitp,ARM_CC_NV,o,r0,r1)
+#define arm_cc_vo_dd(cc,o,r0,r1) _arm_cc_vo_dd(_jitp,cc,o,r0,r1)
+__jit_inline void
+_arm_cc_vo_dd(jit_state_t _jitp, int cc, int o, int r0, int r1)
+{
+ jit_thumb_t thumb;
+ jit_assert(!(cc & 0x0fffffff));
+ jit_assert(!(o & 0xf000f00f));
+ jit_assert(!(r0 & 1) && !(r1 & 1));
+ r0 >>= 1; r1 >>= 1;
+ thumb.i = cc|o|(_u4(r0)<<12)|_u4(r1);
+ if (jit_thumb_p())
+ _jit_WW(thumb.s[0], thumb.s[1]);
+ else
+ _jit_I(thumb.i);
+}
+
+#define arm_vo_qd(o,r0,r1) _arm_cc_vo_qd(_jitp,ARM_CC_NV,o,r0,r1)
+#define arm_cc_vo_qd(cc,o,r0,r1) _arm_cc_vo_qd(_jitp,cc,o,r0,r1)
+__jit_inline void
+_arm_cc_vo_qd(jit_state_t _jitp, int cc, int o, int r0, int r1)
+{
+ jit_thumb_t thumb;
+ jit_assert(!(cc & 0x0fffffff));
+ jit_assert(!(o & 0xf000f00f));
+ jit_assert(!(r0 & 3) && !(r1 & 1));
+ r0 >>= 1; r1 >>= 1;
+ thumb.i = cc|o|(_u4(r0)<<12)|_u4(r1);
+ if (jit_thumb_p())
+ _jit_WW(thumb.s[0], thumb.s[1]);
+ else
+ _jit_I(thumb.i);
+}
+
+#define arm_vo_qq(o,r0,r1) _arm_cc_vo_qq(_jitp,ARM_CC_NV,o,r0,r1)
+#define arm_cc_vo_qq(cc,o,r0,r1) _arm_cc_vo_qq(_jitp,cc,o,r0,r1)
+__jit_inline void
+_arm_cc_vo_qq(jit_state_t _jitp, int cc, int o, int r0, int r1)
+{
+ jit_thumb_t thumb;
+ jit_assert(!(cc & 0x0fffffff));
+ jit_assert(!(o & 0xf000f00f));
+ jit_assert(!(r0 & 3) && !(r1 & 3));
+ r0 >>= 1; r1 >>= 1;
+ thumb.i = cc|o|(_u4(r0)<<12)|_u4(r1);
+ if (jit_thumb_p())
+ _jit_WW(thumb.s[0], thumb.s[1]);
+ else
+ _jit_I(thumb.i);
+}
+
+#define arm_vorr_(o,r0,r1) _arm_cc_vorr_(_jitp,ARM_CC_NV,o,r0,r1)
+#define arm_cc_vorr_(cc,o,r0,r1) _arm_cc_vorr_(_jitp,cc,o,r0,r1)
+__jit_inline void
+_arm_cc_vorr_(jit_state_t _jitp, int cc, int o, int r0, int r1)
+{
+ jit_thumb_t thumb;
+ jit_assert(!(cc & 0x0fffffff));
+ jit_assert(!(o & 0xf000f00f));
+ thumb.i = cc|o|(_u4(r1)<<16)|(_u4(r0)<<12);
+ if (jit_thumb_p())
+ _jit_WW(thumb.s[0], thumb.s[1]);
+ else
+ _jit_I(thumb.i);
+}
+
+#define arm_vors_(o,r0,r1) _arm_cc_vors_(_jitp,ARM_CC_NV,o,r0,r1)
+#define arm_cc_vors_(cc,o,r0,r1) _arm_cc_vors_(_jitp,cc,o,r0,r1)
+__jit_inline void
+_arm_cc_vors_(jit_state_t _jitp, int cc, int o, int r0, int r1)
+{
+ jit_thumb_t thumb;
+ jit_assert(!(cc & 0x0fffffff));
+ jit_assert(!(o & 0xf000f00f));
+ if (r1 & 1) o |= ARM_V_N; r1 >>= 1;
+ thumb.i = cc|o|(_u4(r1)<<16)|(_u4(r0)<<12);
+ if (jit_thumb_p())
+ _jit_WW(thumb.s[0], thumb.s[1]);
+ else
+ _jit_I(thumb.i);
+}
+
+#define arm_vorv_(o,r0,r1) _arm_cc_vorv_(_jitp,ARM_CC_NV,o,r0,r1)
+#define arm_cc_vorv_(cc,o,r0,r1) _arm_cc_vorv_(_jitp,cc,o,r0,r1)
+__jit_inline void
+_arm_cc_vorv_(jit_state_t _jitp, int cc, int o, int r0, int r1)
+{
+ jit_thumb_t thumb;
+ jit_assert(!(cc & 0x0fffffff));
+ jit_assert(!(o & 0xf000f00f));
+ if (r1 & 1) cc |= ARM_V_M; r1 >>= 1;
+ thumb.i = cc|o|(_u4(r1)<<16)|(_u4(r0)<<12);
+ if (jit_thumb_p())
+ _jit_WW(thumb.s[0], thumb.s[1]);
+ else
+ _jit_I(thumb.i);
+}
+
+#define arm_vori_(o,r0,r1) _arm_cc_vori_(_jitp,ARM_CC_NV,o,r0,r1)
+#define arm_cc_vori_(cc,o,r0,r1) _arm_cc_vori_(_jitp,cc,o,r0,r1)
+__jit_inline void
+_arm_cc_vori_(jit_state_t _jitp, int cc, int o, int r0, int r1)
+{
+ jit_thumb_t thumb;
+ jit_assert(!(cc & 0x0fffffff));
+ jit_assert(!(o & 0xf000f00f));
+ /* use same bit pattern, to set opc1... */
+ if (r1 & 1) o |= ARM_V_I32; r1 >>= 1;
+ thumb.i = cc|o|(_u4(r1)<<16)|(_u4(r0)<<12);
+ if (jit_thumb_p())
+ _jit_WW(thumb.s[0], thumb.s[1]);
+ else
+ _jit_I(thumb.i);
+}
+
+#define arm_vorrd(o,r0,r1,r2) _arm_cc_vorrd(_jitp,ARM_CC_NV,o,r0,r1,r2)
+#define arm_cc_vorrd(cc,o,r0,r1,r2) _arm_cc_vorrd(_jitp,cc,o,r0,r1,r2)
+__jit_inline void
+_arm_cc_vorrd(jit_state_t _jitp, int cc, int o, int r0, int r1, int r2)
+{
+ jit_thumb_t thumb;
+ jit_assert(!(cc & 0x0fffffff));
+ jit_assert(!(o & 0xf00ff00f));
+ jit_assert(!(r2 & 1));
+ r2 >>= 1;
+ thumb.i = cc|o|(_u4(r1)<<16)|(_u4(r0)<<12)|_u4(r2);
+ if (jit_thumb_p())
+ _jit_WW(thumb.s[0], thumb.s[1]);
+ else
+ _jit_I(thumb.i);
+}
+
+#define arm_vosss(o,r0,r1,r2) _arm_cc_vosss(_jitp,ARM_CC_NV,o,r0,r1,r2)
+#define arm_cc_vosss(cc,o,r0,r1,r2) _arm_cc_vosss(_jitp,cc,o,r0,r1,r2)
+__jit_inline void
+_arm_cc_vosss(jit_state_t _jitp, int cc, int o, int r0, int r1, int r2)
+{
+ jit_thumb_t thumb;
+ jit_assert(!(cc & 0x0fffffff));
+ jit_assert(!(o & 0xf00ff00f));
+ if (r0 & 1) o |= ARM_V_D; r0 >>= 1;
+ if (r1 & 1) o |= ARM_V_N; r1 >>= 1;
+ if (r2 & 1) o |= ARM_V_M; r2 >>= 1;
+ thumb.i = cc|o|(_u4(r1)<<16)|(_u4(r0)<<12)|_u4(r2);
+ if (jit_thumb_p())
+ _jit_WW(thumb.s[0], thumb.s[1]);
+ else
+ _jit_I(thumb.i);
+}
+
+#define arm_voddd(o,r0,r1,r2) _arm_cc_voddd(_jitp,ARM_CC_NV,o,r0,r1,r2)
+#define arm_cc_voddd(cc,o,r0,r1,r2) _arm_cc_voddd(_jitp,cc,o,r0,r1,r2)
+__jit_inline void
+_arm_cc_voddd(jit_state_t _jitp, int cc, int o, int r0, int r1, int r2)
+{
+ jit_thumb_t thumb;
+ jit_assert(!(cc & 0x0fffffff));
+ jit_assert(!(o & 0xf00ff00f));
+ jit_assert(!(r0 & 1) && !(r1 & 1) && !(r2 & 1));
+ r0 >>= 1; r1 >>= 1; r2 >>= 1;
+ thumb.i = cc|o|(_u4(r1)<<16)|(_u4(r0)<<12)|_u4(r2);
+ if (jit_thumb_p())
+ _jit_WW(thumb.s[0], thumb.s[1]);
+ else
+ _jit_I(thumb.i);
+}
+
+#define arm_voqdd(o,r0,r1,r2) _arm_cc_voqdd(_jitp,ARM_CC_NV,o,r0,r1,r2)
+#define arm_cc_voqdd(cc,o,r0,r1,r2) _arm_cc_voqdd(_jitp,cc,o,r0,r1,r2)
+__jit_inline void
+_arm_cc_voqdd(jit_state_t _jitp, int cc, int o, int r0, int r1, int r2)
+{
+ jit_thumb_t thumb;
+ jit_assert(!(cc & 0x0fffffff));
+ jit_assert(!(o & 0xf00ff00f));
+ jit_assert(!(r0 & 3) && !(r1 & 1) && !(r2 & 1));
+ r0 >>= 1; r1 >>= 1; r2 >>= 1;
+ thumb.i = cc|o|(_u4(r1)<<16)|(_u4(r0)<<12)|_u4(r2);
+ if (jit_thumb_p())
+ _jit_WW(thumb.s[0], thumb.s[1]);
+ else
+ _jit_I(thumb.i);
+}
+
+#define arm_voqqd(o,r0,r1,r2) _arm_cc_voqqd(_jitp,ARM_CC_NV,o,r0,r1,r2)
+#define arm_cc_voqqd(cc,o,r0,r1,r2) _arm_cc_voqqd(_jitp,cc,o,r0,r1,r2)
+__jit_inline void
+_arm_cc_voqqd(jit_state_t _jitp, int cc, int o, int r0, int r1, int r2)
+{
+ jit_thumb_t thumb;
+ jit_assert(!(cc & 0x0fffffff));
+ jit_assert(!(o & 0xf00ff00f));
+ jit_assert(!(r0 & 3) && !(r1 & 3) && !(r2 & 1));
+ r0 >>= 1; r1 >>= 1; r2 >>= 1;
+ thumb.i = cc|o|(_u4(r1)<<16)|(_u4(r0)<<12)|_u4(r2);
+ if (jit_thumb_p())
+ _jit_WW(thumb.s[0], thumb.s[1]);
+ else
+ _jit_I(thumb.i);
+}
+
+#define arm_voqqq(o,r0,r1,r2) _arm_cc_voqqq(_jitp,ARM_CC_NV,o,r0,r1,r2)
+#define arm_cc_voqqq(cc,o,r0,r1,r2) _arm_cc_voqqq(_jitp,cc,o,r0,r1,r2)
+__jit_inline void
+_arm_cc_voqqq(jit_state_t _jitp, int cc, int o, int r0, int r1, int r2)
+{
+ jit_thumb_t thumb;
+ jit_assert(!(cc & 0x0fffffff));
+ jit_assert(!(o & 0xf00ff00f));
+ jit_assert(!(r0 & 3) && !(r1 & 3) && !(r2 & 3));
+ r0 >>= 1; r1 >>= 1; r2 >>= 1;
+ thumb.i = cc|o|(_u4(r1)<<16)|(_u4(r0)<<12)|_u4(r2);
+ if (jit_thumb_p())
+ _jit_WW(thumb.s[0], thumb.s[1]);
+ else
+ _jit_I(thumb.i);
+}
+
+#define arm_cc_vldst(cc,o,r0,r1,i0) _arm_cc_vldst(_jitp,cc,o,r0,r1,i0)
+__jit_inline void
+_arm_cc_vldst(jit_state_t _jitp, int cc, int o, int r0, int r1, int i0)
+{
+ jit_thumb_t thumb;
+ /* i0 << 2 is byte offset */
+ jit_assert(!(cc & 0x0fffffff));
+ jit_assert(!(o & 0xf00ff0ff));
+ if (r0 & 1) {
+ jit_assert(!(o & ARM_V_F64));
+ o |= ARM_V_D;
+ }
+ r0 >>= 1;
+ thumb.i = cc|o|(_u4(r1)<<16)|(_u4(r0)<<12)|_u8(i0);
+ if (jit_thumb_p())
+ _jit_WW(thumb.s[0], thumb.s[1]);
+ else
+ _jit_I(thumb.i);
+}
+
+#define arm_cc_vorsl(cc,o,r0,r1,i0) _arm_cc_vorsl(_jitp,cc,o,r0,r1,i0)
+__jit_inline void
+_arm_cc_vorsl(jit_state_t _jitp, int cc, int o, int r0, int r1, int i0)
+{
+ jit_thumb_t thumb;
+ jit_assert(!(cc & 0x0fffffff));
+ jit_assert(!(o & 0xf00ff0ff));
+ /* save i0 double precision registers */
+ if (o & ARM_V_F64) i0 <<= 1;
+ jit_assert(i0 && !(i0 & 1) && r1 + i0 <= 32);
+ /* if (r1 & 1) cc & ARM_V_F64 must be false */
+ if (r1 & 1) o |= ARM_V_D; r1 >>= 1;
+ thumb.i = cc|o|(_u4(r0)<<16)|(_u4(r1)<<12)|_u8(i0);
+ if (jit_thumb_p())
+ _jit_WW(thumb.s[0], thumb.s[1]);
+ else
+ _jit_I(thumb.i);
+}
+
+/***********************************************************************
+ * VFPv2 and VFPv3 (encoding T2/A2) instructions
+ ***********************************************************************/
+#define _CC_VADD_F32(cc,r0,r1,r2) arm_cc_vosss(cc,ARM_VADD_F,r0,r1,r2)
+#define _VADD_F32(r0,r1,r2) _CC_VADD_F32(ARM_CC_AL,r0,r1,r2)
+#define _CC_VADD_F64(cc,r0,r1,r2) arm_cc_voddd(cc,ARM_VADD_F|ARM_V_F64,r0,r1,r2)
+#define _VADD_F64(r0,r1,r2) _CC_VADD_F64(ARM_CC_AL,r0,r1,r2)
+#define _CC_VSUB_F32(cc,r0,r1,r2) arm_cc_vosss(cc,ARM_VSUB_F,r0,r1,r2)
+#define _VSUB_F32(r0,r1,r2) _CC_VSUB_F32(ARM_CC_AL,r0,r1,r2)
+#define _CC_VSUB_F64(cc,r0,r1,r2) arm_cc_voddd(cc,ARM_VSUB_F|ARM_V_F64,r0,r1,r2)
+#define _VSUB_F64(r0,r1,r2) _CC_VSUB_F64(ARM_CC_AL,r0,r1,r2)
+#define _CC_VMUL_F32(cc,r0,r1,r2) arm_cc_vosss(cc,ARM_VMUL_F,r0,r1,r2)
+#define _VMUL_F32(r0,r1,r2) _CC_VMUL_F32(ARM_CC_AL,r0,r1,r2)
+#define _CC_VMUL_F64(cc,r0,r1,r2) arm_cc_voddd(cc,ARM_VMUL_F|ARM_V_F64,r0,r1,r2)
+#define _VMUL_F64(r0,r1,r2) _CC_VMUL_F64(ARM_CC_AL,r0,r1,r2)
+#define _CC_VDIV_F32(cc,r0,r1,r2) arm_cc_vosss(cc,ARM_VDIV_F,r0,r1,r2)
+#define _VDIV_F32(r0,r1,r2) _CC_VDIV_F32(ARM_CC_AL,r0,r1,r2)
+#define _CC_VDIV_F64(cc,r0,r1,r2) arm_cc_voddd(cc,ARM_VDIV_F|ARM_V_F64,r0,r1,r2)
+#define _VDIV_F64(r0,r1,r2) _CC_VDIV_F64(ARM_CC_AL,r0,r1,r2)
+#define _CC_VABS_F32(cc,r0,r1) arm_cc_vo_ss(cc,ARM_VABS_F,r0,r1)
+#define _VABS_F32(r0,r1) _CC_VABS_F32(ARM_CC_AL,r0,r1)
+#define _CC_VABS_F64(cc,r0,r1) arm_cc_vo_dd(cc,ARM_VABS_F|ARM_V_F64,r0,r1)
+#define _VABS_F64(r0,r1) _CC_VABS_F64(ARM_CC_AL,r0,r1)
+#define _CC_VNEG_F32(cc,r0,r1) arm_cc_vo_ss(cc,ARM_VNEG_F,r0,r1)
+#define _VNEG_F32(r0,r1) _CC_VNEG_F32(ARM_CC_AL,r0,r1)
+#define _CC_VNEG_F64(cc,r0,r1) arm_cc_vo_dd(cc,ARM_VNEG_F|ARM_V_F64,r0,r1)
+#define _VNEG_F64(r0,r1) _CC_VNEG_F64(ARM_CC_AL,r0,r1)
+#define _CC_VSQRT_F32(cc,r0,r1) arm_cc_vo_ss(cc,ARM_VSQRT_F,r0,r1)
+#define _VSQRT_F32(r0,r1) _CC_VSQRT_F32(ARM_CC_AL,r0,r1)
+#define _CC_VSQRT_F64(cc,r0,r1) arm_cc_vo_dd(cc,ARM_VSQRT_F|ARM_V_F64,r0,r1)
+#define _VSQRT_F64(r0,r1) _CC_VSQRT_F64(ARM_CC_AL,r0,r1)
+#define _CC_VMOV_F32(cc,r0,r1) arm_cc_vo_ss(cc,ARM_VMOV_F,r0,r1)
+#define _VMOV_F32(r0,r1) _CC_VMOV_F32(ARM_CC_AL,r0,r1)
+#define _CC_VMOV_F64(cc,r0,r1) arm_cc_vo_dd(cc,ARM_VMOV_F|ARM_V_F64,r0,r1)
+#define _VMOV_F64(r0,r1) _CC_VMOV_F64(ARM_CC_AL,r0,r1)
+#define _CC_VMOV_AA_D(cc,r0,r1,r2) arm_cc_vorrd(cc,ARM_VMOV_AA_D,r0,r1,r2)
+#define _VMOV_AA_D(r0,r1,r2) _CC_VMOV_AA_D(ARM_CC_AL,r0,r1,r2)
+#define _CC_VMOV_D_AA(cc,r0,r1,r2) arm_cc_vorrd(cc,ARM_VMOV_D_AA,r1,r2,r0)
+#define _VMOV_D_AA(r0,r1,r2) _CC_VMOV_D_AA(ARM_CC_AL,r0,r1,r2)
+#define _CC_VMOV_A_S(cc,r0,r1) arm_cc_vors_(cc,ARM_VMOV_A_S,r0,r1)
+#define _VMOV_A_S(r0,r1) _CC_VMOV_A_S(ARM_CC_AL,r0,r1)
+#define _CC_VMOV_S_A(cc,r0,r1) arm_cc_vors_(cc,ARM_VMOV_S_A,r1,r0)
+#define _VMOV_S_A(r0,r1) _CC_VMOV_S_A(ARM_CC_AL,r0,r1)
+#define _CC_VCMP_F32(cc,r0,r1) arm_cc_vo_ss(cc,ARM_VCMP,r0,r1)
+#define _VCMP_F32(r0,r1) _CC_VCMP_F32(ARM_CC_AL,r0,r1)
+#define _CC_VCMP_F64(cc,r0,r1) arm_cc_vo_dd(cc,ARM_VCMP|ARM_V_F64,r0,r1)
+#define _VCMP_F64(r0,r1) _CC_VCMP_F64(ARM_CC_AL,r0,r1)
+#define _CC_VCMPE_F32(cc,r0,r1) arm_cc_vo_ss(cc,ARM_VCMP|ARM_V_E,r0,r1)
+#define _VCMPE_F32(r0,r1) _CC_VCMPE_F32(ARM_CC_AL,r0,r1)
+#define _CC_VCMPE_F64(cc,r0,r1) arm_cc_vo_dd(cc,ARM_VCMP|ARM_V_E|ARM_V_F64,r0,r1)
+#define _VCMPE_F64(r0,r1) _CC_VCMPE_F64(ARM_CC_AL,r0,r1)
+#define _CC_VCMPZ_F32(cc,r0) arm_cc_vo_ss(cc,ARM_VCMP|ARM_V_Z,r0,0)
+#define _VCMPZ_F32(r0) _CC_VCMPZ_F32(ARM_CC_AL,r0)
+#define _CC_VCMPZ_F64(cc,r0) arm_cc_vo_dd(cc,ARM_VCMP|ARM_V_Z|ARM_V_F64,r0,0)
+#define _VCMPZ_F64(r0) _CC_VCMPZ_F64(ARM_CC_AL,r0)
+#define _CC_VCMPEZ_F32(cc,r0) arm_cc_vo_ss(cc,ARM_VCMP|ARM_V_Z|ARM_V_E,r0,0)
+#define _VCMPEZ_F32(r0) _CC_VCMPEZ_F32(ARM_CC_AL,r0)
+#define _CC_VCMPEZ_F64(cc,r0) arm_cc_vo_dd(cc,ARM_VCMP|ARM_V_Z|ARM_V_E|ARM_V_F64,r0,0)
+#define _VCMPEZ_F64(r0) _CC_VCMPEZ_F64(ARM_CC_AL,r0)
+#define _CC_VMRS(cc,r0) arm_cc_vorr_(cc,ARM_VMRS,r0,0)
+#define _VMRS(r0) _CC_VMRS(ARM_CC_AL,r0)
+#define _CC_VMSR(cc,r0) arm_cc_vorr_(cc,ARM_VMSR,r0,0)
+#define _VMSR(r0) _CC_VMSR(ARM_CC_AL,r0)
+#define _CC_VCVT_S32_F32(cc,r0,r1) arm_cc_vo_ss(cc,ARM_VCVT_S32_F32,r0,r1)
+#define _VCVT_S32_F32(r0,r1) _CC_VCVT_S32_F32(ARM_CC_AL,r0,r1)
+#define _CC_VCVT_U32_F32(cc,r0,r1) arm_cc_vo_ss(cc,ARM_VCVT_U32_F32,r0,r1)
+#define _VCVT_U32_F32(r0,r1) _CC_VCVT_U32_F32(ARM_CC_AL,r0,r1)
+#define _CC_VCVT_S32_F64(cc,r0,r1) arm_cc_vo_ss(cc,ARM_VCVT_S32_F64,r0,r1)
+#define _VCVT_S32_F64(r0,r1) _CC_VCVT_S32_F64(ARM_CC_AL,r0,r1)
+#define _CC_VCVT_U32_F64(cc,r0,r1) arm_cc_vo_ss(cc,ARM_VCVT_U32_F64,r0,r1)
+#define _VCVT_U32_F64(r0,r1) _CC_VCVT_U32_F64(ARM_CC_AL,r0,r1)
+#define _CC_VCVT_F32_S32(cc,r0,r1) arm_cc_vo_ss(cc,ARM_VCVT_F32_S32,r0,r1)
+#define _VCVT_F32_S32(r0,r1) _CC_VCVT_F32_S32(ARM_CC_AL,r0,r1)
+#define _CC_VCVT_F32_U32(cc,r0,r1) arm_cc_vo_ss(cc,ARM_VCVT_F32_U32,r0,r1)
+#define _VCVT_F32_U32(r0,r1) _CC_VCVT_F32_U32(ARM_CC_AL,r0,r1)
+#define _CC_VCVT_F64_S32(cc,r0,r1) arm_cc_vo_ss(cc,ARM_VCVT_F64_S32,r0,r1)
+#define _VCVT_F64_S32(r0,r1) _CC_VCVT_F64_S32(ARM_CC_AL,r0,r1)
+#define _CC_VCVT_F64_U32(cc,r0,r1) arm_cc_vo_ss(cc,ARM_VCVT_F64_U32,r0,r1)
+#define _VCVT_F64_U32(r0,r1) _CC_VCVT_F64_U32(ARM_CC_AL,r0,r1)
+#define _CC_VCVT_F32_F64(cc,r0,r1) arm_cc_vo_ss(cc,ARM_VCVT_F32_F64,r0,r1)
+#define _VCVT_F32_F64(r0,r1) _CC_VCVT_F32_F64(ARM_CC_AL,r0,r1)
+#define _CC_VCVT_F64_F32(cc,r0,r1) arm_cc_vo_ss(cc,ARM_VCVT_F64_F32,r0,r1)
+#define _VCVT_F64_F32(r0,r1) _CC_VCVT_F64_F32(ARM_CC_AL,r0,r1)
+/* use rounding mode in fpscr (intended for floor, ceil, etc) */
+#define _CC_VCVTR_S32_F32(cc,r0,r1) arm_cc_vo_ss(cc,ARM_VCVTR_S32_F32,r0,r1)
+#define _VCVTR_S32_F32(r0,r1) _CC_VCVTR_S32_F32(ARM_CC_AL,r0,r1)
+#define _CC_VCVTR_U32_F32(cc,r0,r1) arm_cc_vo_ss(cc,ARM_VCVTR_U32_F32,r0,r1)
+#define _VCVTR_U32_F32(r0,r1) _CC_VCVTR_U32_F32(ARM_CC_AL,r0,r1)
+#define _CC_VCVTR_S32_F64(cc,r0,r1) arm_cc_vo_ss(cc,ARM_VCVTR_S32_F64,r0,r1)
+#define _VCVTR_S32_F64(r0,r1) _CC_VCVTR_S32_F64(ARM_CC_AL,r0,r1)
+#define _CC_VCVTR_U32_F64(cc,r0,r1) arm_cc_vo_ss(cc,ARM_VCVTR_U32_F64,r0,r1)
+#define _VCVTR_U32_F64(r0,r1) _CC_VCVTR_U32_F64(ARM_CC_AL,r0,r1)
+/***********************************************************************
+ * NEON instructions (encoding T1/A1) (condition must always be ARM_CC_NV)
+ ***********************************************************************/
+#define _CC_VLDMIA_F32(cc,r0,r1,i0) arm_cc_vorsl(cc,ARM_VM|ARM_M_L|ARM_M_I,r0,r1,i0)
+#define _VLDMIA_F32(r0,r1,i0) _CC_VLDMIA_F32(ARM_CC_AL,r0,r1,i0)
+#define _CC_VLDMIA_F64(cc,r0,r1,i0) arm_cc_vorsl(cc,ARM_VM|ARM_M_L|ARM_M_I|ARM_V_F64,r0,r1,i0)
+#define _VLDMIA_F64(r0,r1,i0) _CC_VLDMIA_F64(ARM_CC_AL,r0,r1,i0)
+#define _CC_VSTMIA_F32(cc,r0,r1,i0) arm_cc_vorsl(cc,ARM_VM|ARM_M_I,r0,r1,i0)
+#define _VSTMIA_F32(r0,r1,i0) _CC_VSTMIA_F32(ARM_CC_AL,r0,r1,i0)
+#define _CC_VSTMIA_F64(cc,r0,r1,i0) arm_cc_vorsl(cc,ARM_VM|ARM_M_I|ARM_V_F64,r0,r1,i0)
+#define _VSTMIA_F64(r0,r1,i0) _CC_VSTMIA_F64(ARM_CC_AL,r0,r1,i0)
+#define _CC_VLDMIA_U_F32(cc,r0,r1,i0) arm_cc_vorsl(cc,ARM_VM|ARM_M_L|ARM_M_I|ARM_M_U,r0,r1,i0)
+#define _VLDMIA_U_F32(r0,r1,i0) _CC_VLDMIA_U_F32(ARM_CC_AL,r0,r1,i0)
+#define _CC_VLDMIA_U_F64(cc,r0,r1,i0) arm_cc_vorsl(cc,ARM_VM|ARM_M_L|ARM_M_I|ARM_M_U|ARM_V_F64,r0,r1,i0)
+#define _VLDMIA_U_F64(r0,r1,i0) _CC_VLDMIA_U_F64(ARM_CC_AL,r0,r1,i0)
+#define _CC_VSTMIA_U_F32(cc,r0,r1,i0) arm_cc_vorsl(cc,ARM_VM|ARM_M_I|ARM_M_U,r0,r1,i0)
+#define _VSTMIA_U_F32(r0,r1,i0) _CC_VSTMIA_U_F32(ARM_CC_AL,r0,r1,i0)
+#define _CC_VSTMIA_U_F64(cc,r0,r1,i0) arm_cc_vorsl(cc,ARM_VM|ARM_M_I|ARM_M_U|ARM_V_F64,r0,r1,i0)
+#define _VSTMIA_U_F64(r0,r1,i0) _CC_VSTMIA_U_F64(ARM_CC_AL,r0,r1,i0)
+#define _CC_VLDMDB_U_F32(cc,r0,r1,i0) arm_cc_vorsl(cc,ARM_VM|ARM_M_L|ARM_M_B|ARM_M_U,r0,r1,i0)
+#define _VLDMDB_U_F32(r0,r1,i0) _CC_VLDMDB_U_F32(ARM_CC_AL,r0,r1,i0)
+#define _CC_VLDMDB_U_F64(cc,r0,r1,i0) arm_cc_vorsl(cc,ARM_VM|ARM_M_L|ARM_M_B|ARM_M_U|ARM_V_F64,r0,r1,i0)
+#define _VLDMDB_U_F64(r0,r1,i0) _CC_VLDMDB_U_F64(ARM_CC_AL,r0,r1,i0)
+#define _CC_VSTMDB_U_F32(cc,r0,r1,i0) arm_cc_vorsl(cc,ARM_VM|ARM_M_B|ARM_M_U,r0,r1,i0)
+#define _VSTMDB_U_F32(r0,r1,i0) _CC_VSTMDB_U_F32(ARM_CC_AL,r0,r1,i0)
+#define _CC_VSTMDB_U_F64(cc,r0,r1,i0) arm_cc_vorsl(cc,ARM_VM|ARM_M_B|ARM_M_U|ARM_V_F64,r0,r1,i0)
+#define _VSTMDB_U_F64(r0,r1,i0) _CC_VSTMDB_U_F64(ARM_CC_AL,r0,r1,i0)
+#define _CC_VPUSH_F32(cc,r0,i0) _CC_VSTMDB_U_F32(cc,JIT_SP,r0,i0)
+#define _VPUSH_F32(r0,i0) _CC_VPUSH_F32(ARM_CC_AL,r0,i0)
+#define _CC_VPUSH_F64(cc,r0,i0) _CC_VSTMDB_U_F64(cc,JIT_SP,r0,i0)
+#define _VPUSH_F64(r0,i0) _CC_VPUSH_F64(ARM_CC_AL,r0,i0)
+#define _CC_VPOP_F32(cc,r0,i0) _CC_VLDMIA_U_F32(cc,JIT_SP,r0,i0)
+#define _VPOP_F32(r0,i0) _CC_VPOP_F32(ARM_CC_AL,r0,i0)
+#define _CC_VPOP_F64(cc,r0,i0) _CC_VLDMIA_U_F64(cc,JIT_SP,r0,i0)
+#define _VPOP_F64(r0,i0) _CC_VPOP_F64(ARM_CC_AL,r0,i0)
+/***********************************************************************
+ * Advanced SIMD (encoding T2/A2) instructions
+ ***********************************************************************/
+#define _CC_VMOV_A_S8(cc,r0,r1) arm_cc_vorv_(cc,ARM_VMOV_A_D|ARM_VMOV_ADV_8,r0,r1)
+#define _VMOV_A_S8(r0,r1) _CC_VMOV_A_S8(ARM_CC_AL,r0,r1)
+#define _CC_VMOV_A_U8(cc,r0,r1) arm_cc_vorv_(cc,ARM_VMOV_A_D|ARM_VMOV_ADV_8|ARM_VMOV_ADV_U,r0,r1)
+#define _VMOV_A_U8(r0,r1) _CC_VMOV_A_U8(ARM_CC_AL,r0,r1)
+#define _CC_VMOV_A_S16(cc,r0,r1) arm_cc_vorv_(cc,ARM_VMOV_A_D|ARM_VMOV_ADV_16,r0,r1)
+#define _VMOV_A_S16(r0,r1) _CC_VMOV_A_S16(ARM_CC_AL,r0,r1)
+#define _CC_VMOV_A_U16(cc,r0,r1) arm_cc_vorv_(cc,ARM_VMOV_A_D|ARM_VMOV_ADV_16|ARM_VMOV_ADV_U,r0,r1)
+#define _VMOV_A_U16(r0,r1) _CC_VMOV_A_U16(ARM_CC_AL,r0,r1)
+#define _CC_VMOV_A_S32(cc,r0,r1) arm_cc_vori_(cc,ARM_VMOV_A_D,r0,r1)
+#define _VMOV_A_S32(r0,r1) _CC_VMOV_A_S32(ARM_CC_AL,r0,r1)
+#define _CC_VMOV_A_U32(cc,r0,r1) arm_cc_vori_(cc,ARM_VMOV_A_D|ARM_VMOV_ADV_U,r0,r1)
+#define _VMOV_A_U32(r0,r1) _CC_VMOV_A_U32(ARM_CC_AL,r0,r1)
+#define _CC_VMOV_V_I8(cc,r0,r1) arm_cc_vorv_(cc,ARM_VMOV_D_A|ARM_VMOV_ADV_8,r1,r0)
+#define _VMOV_V_I8(r0,r1) _CC_VMOV_V_I8(ARM_CC_AL,r0,r1)
+#define _CC_VMOV_V_I16(cc,r0,r1) arm_cc_vorv_(cc,ARM_VMOV_D_A|ARM_VMOV_ADV_16,r1,r0)
+#define _VMOV_V_I16(r0,r1) _CC_VMOV_V_I16(ARM_CC_AL,r0,r1)
+#define _CC_VMOV_V_I32(cc,r0,r1) arm_cc_vori_(cc,ARM_VMOV_D_A,r1,r0)
+#define _VMOV_V_I32(r0,r1) _CC_VMOV_V_I32(ARM_CC_AL,r0,r1)
+#define _VADD_I8(r0,r1,r2) arm_voddd(ARM_VADD_I,r0,r1,r2)
+#define _VADDQ_I8(r0,r1,r2) arm_voqqq(ARM_VADD_I|ARM_V_Q,r0,r1,r2)
+#define _VADD_I16(r0,r1,r2) arm_voddd(ARM_VADD_I|ARM_V_I16,r0,r1,r2)
+#define _VADDQ_I16(r0,r1,r2) arm_voqqq(ARM_VADD_I|ARM_V_I16|ARM_V_Q,r0,r1,r2)
+#define _VADD_I32(r0,r1,r2) arm_voddd(ARM_VADD_I|ARM_V_I32,r0,r1,r2)
+#define _VADDQ_I32(r0,r1,r2) arm_voqqq(ARM_VADD_I|ARM_V_I32|ARM_V_Q,r0,r1,r2)
+#define _VADD_I64(r0,r1,r2) arm_voddd(ARM_VADD_I|ARM_V_I64,r0,r1,r2)
+#define _VADDQ_I64(r0,r1,r2) arm_voqqq(ARM_VADD_I|ARM_V_I64|ARM_V_Q,r0,r1,r2)
+#define _VQADD_S8(r0,r1,r2) arm_voddd(ARM_VQADD_I,r0,r1,r2)
+#define _VQADDQ_S8(r0,r1,r2) arm_voqqq(ARM_VQADD_I|ARM_V_Q,r0,r1,r2)
+#define _VQADD_U8(r0,r1,r2) arm_voddd(ARM_VQADD_I|ARM_V_U,r0,r1,r2)
+#define _VQADDQ_U8(r0,r1,r2) arm_voqqq(ARM_VQADD_I|ARM_V_U|ARM_V_Q,r0,r1,r2)
+#define _VQADD_S16(r0,r1,r2) arm_voddd(ARM_VQADD_I|ARM_V_I16,r0,r1,r2)
+#define _VQADDQ_S16(r0,r1,r2) arm_voqqq(ARM_VQADD_I|ARM_V_I16|ARM_V_Q,r0,r1,r2)
+#define _VQADD_U16(r0,r1,r2) arm_voddd(ARM_VQADD_I|ARM_V_I16|ARM_V_U,r0,r1,r2)
+#define _VQADDQ_U16(r0,r1,r2) arm_voqqq(ARM_VQADD_I|ARM_V_I16|ARM_V_U|ARM_V_Q,r0,r1,r2)
+#define _VQADD_S32(r0,r1,r2) arm_voddd(ARM_VQADD_I|ARM_V_I32,r0,r1,r2)
+#define _VQADDQ_S32(r0,r1,r2) arm_voqqq(ARM_VQADD_I|ARM_V_I32|ARM_V_Q,r0,r1,r2)
+#define _VQADD_U32(r0,r1,r2) arm_voddd(ARM_VQADD_I|ARM_V_I32|ARM_V_U,r0,r1,r2)
+#define _VQADDQ_U32(r0,r1,r2) arm_voqqq(ARM_VQADD_I|ARM_V_I32|ARM_V_U|ARM_V_Q,r0,r1,r2)
+#define _VQADD_S64(r0,r1,r2) arm_voddd(ARM_VQADD_I|ARM_V_I64,r0,r1,r2)
+#define _VQADDQ_S64(r0,r1,r2) arm_voqqq(ARM_VQADD_I|ARM_V_I64|ARM_V_Q,r0,r1,r2)
+#define _VQADD_U64(r0,r1,r2) arm_voddd(ARM_VQADD_I|ARM_V_I64|ARM_V_U,r0,r1,r2)
+#define _VQADDQ_U64(r0,r1,r2) arm_voqqq(ARM_VQADD_I|ARM_V_I64|ARM_V_U|ARM_V_Q,r0,r1,r2)
+#define _VADDL_S8(r0,r1,r2) arm_voqdd(ARM_VADDL_I,r0,r1,r2)
+#define _VADDL_U8(r0,r1,r2) arm_voqdd(ARM_VADDL_I|ARM_V_U,r0,r1,r2)
+#define _VADDL_S16(r0,r1,r2) arm_voqdd(ARM_VADDL_I|ARM_V_I16,r0,r1,r2)
+#define _VADDL_U16(r0,r1,r2) arm_voqdd(ARM_VADDL_I|ARM_V_I16|ARM_V_U,r0,r1,r2)
+#define _VADDL_S32(r0,r1,r2) arm_voqdd(ARM_VADDL_I|ARM_V_I32,r0,r1,r2)
+#define _VADDL_U32(r0,r1,r2) arm_voqdd(ARM_VADDL_I|ARM_V_I32|ARM_V_U,r0,r1,r2)
+#define _VADDW_S8(r0,r1,r2) arm_voqqd(ARM_VADDW_I,r0,r1,r2)
+#define _VADDW_U8(r0,r1,r2) arm_voqqd(ARM_VADDW_I|ARM_V_U,r0,r1,r2)
+#define _VADDW_S16(r0,r1,r2) arm_voqqd(ARM_VADDW_I|ARM_V_I16,r0,r1,r2)
+#define _VADDW_U16(r0,r1,r2) arm_voqqd(ARM_VADDW_I|ARM_V_I16|ARM_V_U,r0,r1,r2)
+#define _VADDW_S32(r0,r1,r2) arm_voqqd(ARM_VADDW_I|ARM_V_I32,r0,r1,r2)
+#define _VADDW_U32(r0,r1,r2) arm_voqqd(ARM_VADDW_I|ARM_V_I32|ARM_V_U,r0,r1,r2)
+#define _VSUB_I8(r0,r1,r2) arm_voddd(ARM_VSUB_I,r0,r1,r2)
+#define _VSUBQ_I8(r0,r1,r2) arm_voqqq(ARM_VSUB_I|ARM_V_Q,r0,r1,r2)
+#define _VSUB_I16(r0,r1,r2) arm_voddd(ARM_VSUB_I|ARM_V_I16,r0,r1,r2)
+#define _VSUBQ_I16(r0,r1,r2) arm_voqqq(ARM_VSUB_I|ARM_V_I16|ARM_V_Q,r0,r1,r2)
+#define _VSUB_I32(r0,r1,r2) arm_voddd(ARM_VSUB_I|ARM_V_I32,r0,r1,r2)
+#define _VSUBQ_I32(r0,r1,r2) arm_voqqq(ARM_VSUB_I|ARM_V_I32|ARM_V_Q,r0,r1,r2)
+#define _VSUB_I64(r0,r1,r2) arm_voddd(ARM_VSUB_I|ARM_V_I64,r0,r1,r2)
+#define _VSUBQ_I64(r0,r1,r2) arm_voqqq(ARM_VSUB_I|ARM_V_I64|ARM_V_Q,r0,r1,r2)
+#define _VQSUB_S8(r0,r1,r2) arm_voddd(ARM_VQSUB_I,r0,r1,r2)
+#define _VQSUBQ_S8(r0,r1,r2) arm_voqqq(ARM_VQSUB_I|ARM_V_Q,r0,r1,r2)
+#define _VQSUB_U8(r0,r1,r2) arm_voddd(ARM_VQSUB_I|ARM_V_U,r0,r1,r2)
+#define _VQSUBQ_U8(r0,r1,r2) arm_voqqq(ARM_VQSUB_I|ARM_V_U|ARM_V_Q,r0,r1,r2)
+#define _VQSUB_S16(r0,r1,r2) arm_voddd(ARM_VQSUB_I|ARM_V_I16,r0,r1,r2)
+#define _VQSUBQ_S16(r0,r1,r2) arm_voqqq(ARM_VQSUB_I|ARM_V_I16|ARM_V_Q,r0,r1,r2)
+#define _VQSUB_U16(r0,r1,r2) arm_voddd(ARM_VQSUB_I|ARM_V_I16|ARM_V_U,r0,r1,r2)
+#define _VQSUBQ_U16(r0,r1,r2) arm_voqqq(ARM_VQSUB_I|ARM_V_I16|ARM_V_U|ARM_V_Q,r0,r1,r2)
+#define _VQSUB_S32(r0,r1,r2) arm_voddd(ARM_VQSUB_I|ARM_V_I32,r0,r1,r2)
+#define _VQSUBQ_S32(r0,r1,r2) arm_voqqq(ARM_VQSUB_I|ARM_V_I32|ARM_V_Q,r0,r1,r2)
+#define _VQSUB_U32(r0,r1,r2) arm_voddd(ARM_VQSUB_I|ARM_V_I32|ARM_V_U,r0,r1,r2)
+#define _VQSUBQ_U32(r0,r1,r2) arm_voqqq(ARM_VQSUB_I|ARM_V_I32|ARM_V_U|ARM_V_Q,r0,r1,r2)
+#define _VQSUB_S64(r0,r1,r2) arm_voddd(ARM_VQSUB_I|ARM_V_I64,r0,r1,r2)
+#define _VQSUBQ_S64(r0,r1,r2) arm_voqqq(ARM_VQSUB_I|ARM_V_I64|ARM_V_Q,r0,r1,r2)
+#define _VQSUB_U64(r0,r1,r2) arm_voddd(ARM_VQSUB_I|ARM_V_I64|ARM_V_U,r0,r1,r2)
+#define _VQSUBQ_U64(r0,r1,r2) arm_voqqq(ARM_VQSUB_I|ARM_V_I64|ARM_V_U|ARM_V_Q,r0,r1,r2)
+#define _VSUBL_S8(r0,r1,r2) arm_voqdd(ARM_VSUBL_I,r0,r1,r2)
+#define _VSUBL_U8(r0,r1,r2) arm_voqdd(ARM_VSUBL_I|ARM_V_U,r0,r1,r2)
+#define _VSUBL_S16(r0,r1,r2) arm_voqdd(ARM_VSUBL_I|ARM_V_I16,r0,r1,r2)
+#define _VSUBL_U16(r0,r1,r2) arm_voqdd(ARM_VSUBL_I|ARM_V_I16|ARM_V_U,r0,r1,r2)
+#define _VSUBL_S32(r0,r1,r2) arm_voqdd(ARM_VSUBL_I|ARM_V_I32,r0,r1,r2)
+#define _VSUBL_U32(r0,r1,r2) arm_voqdd(ARM_VSUBL_I|ARM_V_I32|ARM_V_U,r0,r1,r2)
+#define _VSUBW_S8(r0,r1,r2) arm_voqqd(ARM_VSUBW_I,r0,r1,r2)
+#define _VSUBW_U8(r0,r1,r2) arm_voqqd(ARM_VSUBW_I|ARM_V_U,r0,r1,r2)
+#define _VSUBW_S16(r0,r1,r2) arm_voqqd(ARM_VSUBW_I|ARM_V_I16,r0,r1,r2)
+#define _VSUBW_U16(r0,r1,r2) arm_voqqd(ARM_VSUBW_I|ARM_V_I16|ARM_V_U,r0,r1,r2)
+#define _VSUBW_S32(r0,r1,r2) arm_voqqd(ARM_VSUBW_I|ARM_V_I32,r0,r1,r2)
+#define _VSUBW_U32(r0,r1,r2) arm_voqqd(ARM_VSUBW_I|ARM_V_I32|ARM_V_U,r0,r1,r2)
+#define _VMUL_I8(r0,r1,r2) arm_voddd(ARM_VMUL_I,r0,r1,r2)
+#define _VMULQ_I8(r0,r1,r2) arm_voqqq(ARM_VMUL_I|ARM_V_Q,r0,r1,r2)
+#define _VMUL_I16(r0,r1,r2) arm_voddd(ARM_VMUL_I|ARM_V_I16,r0,r1,r2)
+#define _VMULQ_I16(r0,r1,r2) arm_voqqq(ARM_VMUL_I|ARM_V_Q|ARM_V_I16,r0,r1,r2)
+#define _VMUL_I32(r0,r1,r2) arm_voddd(ARM_VMUL_I|ARM_V_I32,r0,r1,r2)
+#define _VMULQ_I32(r0,r1,r2) arm_voqqq(ARM_VMUL_I|ARM_V_Q|ARM_V_I32,r0,r1,r2)
+#define _VMULL_S8(r0,r1,r2) arm_voqdd(ARM_VMULL_I,r0,r1,r2)
+#define _VMULL_U8(r0,r1,r2) arm_voqdd(ARM_VMULL_I|ARM_V_U,r0,r1,r2)
+#define _VMULL_S16(r0,r1,r2) arm_voqdd(ARM_VMULL_I|ARM_V_I16,r0,r1,r2)
+#define _VMULL_U16(r0,r1,r2) arm_voqdd(ARM_VMULL_I|ARM_V_U|ARM_V_I16,r0,r1,r2)
+#define _VMULL_S32(r0,r1,r2) arm_voqdd(ARM_VMULL_I|ARM_V_I32,r0,r1,r2)
+#define _VMULL_U32(r0,r1,r2) arm_voqdd(ARM_VMULL_I|ARM_V_U|ARM_V_I32,r0,r1,r2)
+#define _VABS_S8(r0,r1) arm_vo_dd(ARM_VABS_I,r0,r1)
+#define _VABSQ_S8(r0,r1) arm_vo_qq(ARM_VABS_I|ARM_V_Q,r0,r1)
+#define _VABS_S16(r0,r1) arm_vo_dd(ARM_VABS_I|ARM_V_S16,r0,r1)
+#define _VABSQ_S16(r0,r1) arm_vo_qq(ARM_VABS_I|ARM_V_S16|ARM_V_Q,r0,r1)
+#define _VABS_S32(r0,r1) arm_vo_dd(ARM_VABS_I|ARM_V_S32,r0,r1)
+#define _VABSQ_S32(r0,r1) arm_vo_qq(ARM_VABS_I|ARM_V_S32|ARM_V_Q,r0,r1)
+#define _VQABS_S8(r0,r1) arm_vo_dd(ARM_VQABS_I,r0,r1)
+#define _VQABSQ_S8(r0,r1) arm_vo_qq(ARM_VQABS_I|ARM_V_Q,r0,r1)
+#define _VQABS_S16(r0,r1) arm_vo_dd(ARM_VQABS_I|ARM_V_S16,r0,r1)
+#define _VQABSQ_S16(r0,r1) arm_vo_qq(ARM_VQABS_I|ARM_V_S16|ARM_V_Q,r0,r1)
+#define _VQABS_S32(r0,r1) arm_vo_dd(ARM_VQABS_I|ARM_V_S32,r0,r1)
+#define _VQABSQ_S32(r0,r1) arm_vo_qq(ARM_VQABS_I|ARM_V_S32|ARM_V_Q,r0,r1)
+#define _VNEG_S8(r0,r1) arm_vo_dd(ARM_VNEG_I,r0,r1)
+#define _VNEGQ_S8(r0,r1) arm_vo_qq(ARM_VNEG_I|ARM_V_Q,r0,r1)
+#define _VNEG_S16(r0,r1) arm_vo_dd(ARM_VNEG_I|ARM_V_S16,r0,r1)
+#define _VNEGQ_S16(r0,r1) arm_vo_qq(ARM_VNEG_I|ARM_V_S16|ARM_V_Q,r0,r1)
+#define _VNEG_S32(r0,r1) arm_vo_dd(ARM_VNEG_I|ARM_V_S32,r0,r1)
+#define _VNEGQ_S32(r0,r1) arm_vo_qq(ARM_VNEG_I|ARM_V_S32|ARM_V_Q,r0,r1)
+#define _VQNEG_S8(r0,r1) arm_vo_dd(ARM_VQNEG_I,r0,r1)
+#define _VQNEGQ_S8(r0,r1) arm_vo_qq(ARM_VQNEG_I|ARM_V_Q,r0,r1)
+#define _VQNEG_S16(r0,r1) arm_vo_dd(ARM_VQNEG_I|ARM_V_S16,r0,r1)
+#define _VQNEGQ_S16(r0,r1) arm_vo_qq(ARM_VQNEG_I|ARM_V_S16|ARM_V_Q,r0,r1)
+#define _VQNEG_S32(r0,r1) arm_vo_dd(ARM_VQNEG_I|ARM_V_S32,r0,r1)
+#define _VQNEGQ_S32(r0,r1) arm_vo_qq(ARM_VQNEG_I|ARM_V_S32|ARM_V_Q,r0,r1)
+#define _VAND(r0,r1,r2) arm_voddd(ARM_VAND,r0,r1,r2)
+#define _VANDQ(r0,r1,r2) arm_voqqq(ARM_VAND|ARM_V_Q,r0,r1,r2)
+#define _VBIC(r0,r1,r2) arm_voddd(ARM_VBIC,r0,r1,r2)
+#define _VBICQ(r0,r1,r2) arm_voqqq(ARM_VBIC|ARM_V_Q,r0,r1,r2)
+#define _VORR(r0,r1,r2) arm_voddd(ARM_VORR,r0,r1,r2)
+#define _VORRQ(r0,r1,r2) arm_voqqq(ARM_VORR|ARM_V_Q,r0,r1,r2)
+#define _VORN(r0,r1,r2) arm_voddd(ARM_VORN,r0,r1,r2)
+#define _VORNQ(r0,r1,r2) arm_voqqq(ARM_VORN|ARM_V_Q,r0,r1,r2)
+#define _VEOR(r0,r1,r2) arm_voddd(ARM_VEOR,r0,r1,r2)
+#define _VEORQ(r0,r1,r2) arm_voqqq(ARM_VEOR|ARM_V_Q,r0,r1,r2)
+#define _VMOV(r0,r1) _VORR(r0,r1,r1)
+#define _VMOVQ(r0,r1) _VORRQ(r0,r1,r1)
+#define _VMOVL_S8(r0,r1) arm_vo_qd(ARM_VMOVL_I|ARM_VMOVL_S8,r0,r1)
+#define _VMOVL_U8(r0,r1) arm_vo_qd(ARM_VMOVL_I|ARM_V_U|ARM_VMOVL_S8,r0,r1)
+#define _VMOVL_S16(r0,r1) arm_vo_qd(ARM_VMOVL_I|ARM_VMOVL_S16,r0,r1)
+#define _VMOVL_U16(r0,r1) arm_vo_qd(ARM_VMOVL_I|ARM_V_U|ARM_VMOVL_S16,r0,r1)
+#define _VMOVL_S32(r0,r1) arm_vo_qd(ARM_VMOVL_I|ARM_VMOVL_S32,r0,r1)
+#define _VMOVL_U32(r0,r1) arm_vo_qd(ARM_VMOVL_I|ARM_V_U|ARM_VMOVL_S32,r0,r1)
+/* "oi" should be the result of encode_vfp_double */
+#define _VIMM(oi,r0) arm_vodi(oi,r0)
+#define _VIMMQ(oi,r0) arm_voqi(oi|ARM_V_Q,r0)
+/* index is multipled by four */
+#define _CC_VLDRN_F32(cc,r0,r1,i0) arm_cc_vldst(cc,ARM_VLDR,r0,r1,i0)
+#define _VLDRN_F32(r0,r1,i0) _CC_VLDRN_F32(ARM_CC_AL,r0,r1,i0)
+#define _CC_VLDR_F32(cc,r0,r1,i0) arm_cc_vldst(cc,ARM_VLDR|ARM_P,r0,r1,i0)
+#define _VLDR_F32(r0,r1,i0) _CC_VLDR_F32(ARM_CC_AL,r0,r1,i0)
+#define _CC_VLDRN_F64(cc,r0,r1,i0) arm_cc_vldst(cc,ARM_VLDR|ARM_V_F64,r0,r1,i0)
+#define _VLDRN_F64(r0,r1,i0) _CC_VLDRN_F64(ARM_CC_AL,r0,r1,i0)
+#define _CC_VLDR_F64(cc,r0,r1,i0) arm_cc_vldst(cc,ARM_VLDR|ARM_V_F64|ARM_P,r0,r1,i0)
+#define _VLDR_F64(r0,r1,i0) _CC_VLDR_F64(ARM_CC_AL,r0,r1,i0)
+#define _CC_VSTRN_F32(cc,r0,r1,i0) arm_cc_vldst(cc,ARM_VSTR,r0,r1,i0)
+#define _VSTRN_F32(r0,r1,i0) _CC_VSTRN_F32(ARM_CC_AL,r0,r1,i0)
+#define _CC_VSTR_F32(cc,r0,r1,i0) arm_cc_vldst(cc,ARM_VSTR|ARM_P,r0,r1,i0)
+#define _VSTR_F32(r0,r1,i0) _CC_VSTR_F32(ARM_CC_AL,r0,r1,i0)
+#define _CC_VSTRN_F64(cc,r0,r1,i0) arm_cc_vldst(cc,ARM_VSTR|ARM_V_F64,r0,r1,i0)
+#define _VSTRN_F64(r0,r1,i0) _CC_VSTRN_F64(ARM_CC_AL,r0,r1,i0)
+#define _CC_VSTR_F64(cc,r0,r1,i0) arm_cc_vldst(cc,ARM_VSTR|ARM_V_F64|ARM_P,r0,r1,i0)
+#define _VSTR_F64(r0,r1,i0) _CC_VSTR_F64(ARM_CC_AL,r0,r1,i0)
+
+/* from binutils */
+#define rotate_left(v, n) (v << n | v >> (32 - n))
+static int
+encode_arm_immediate(unsigned int v)
+{
+ unsigned int a, i;
+
+ for (i = 0; i < 32; i += 2)
+ if ((a = rotate_left(v, i)) <= 0xff)
+ return (a | (i << 7));
+
+ return (-1);
+}
+
+#define corrr(cc,o,rn,rd,rm) _corrr(_jitp,cc,o,rn,rd,rm)
+__jit_inline void
+_corrr(jit_state_t _jitp, int cc, int o, int rn, int rd, int rm)
+{
+ jit_assert(!(cc & 0x0fffffff));
+ jit_assert(!(o & 0xf00fff0f));
+ _jit_I(cc|o|(_u4(rn)<<16)|(_u4(rd)<<12)|_u4(rm));
+}
+
+#define corri(cc,o,rn,rd,im) _corri(_jitp,cc,o,rn,rd,im)
+__jit_inline void
+_corri(jit_state_t _jitp, int cc, int o, int rn, int rd, int im)
+{
+ jit_assert(!(cc & 0x0fffffff));
+ jit_assert(!(o & 0xf00fffff));
+ jit_assert(!(im & 0xfffff000));
+ _jit_I(cc|o|(_u4(rn)<<16)|(_u4(rd)<<12)|_u12(im));
+}
+
+#define coriw(cc,o,rd,im) _coriw(_jitp,cc,o,rd,im)
+__jit_inline void
+_coriw(jit_state_t _jitp, int cc, int o, int rd, int im)
+{
+ jit_assert(!(cc & 0x0fffffff));
+ jit_assert(!(o & 0xf00fffff));
+ jit_assert(!(im & 0xffff0000));
+ _jit_I(cc|o|((im&0xf000)<<4)|(_u4(rd)<<12)|(im&0xfff));
+}
+
+#define corri8(cc,o,rn,rt,im) _corri8(_jitp,cc,o,rn,rt,im)
+__jit_inline void
+_corri8(jit_state_t _jitp, int cc, int o, int rn, int rt, int im)
+{
+ jit_assert(!(cc & 0x0fffffff));
+ jit_assert(!(o & 0xf00fff0f));
+ jit_assert(!(im & 0xffffff00));
+ _jit_I(cc|o|(_u4(rn)<<16)|(_u4(rt)<<12)|((im&0xf0)<<4)|(im&0x0f));
+}
+
+#define corrrr(cc,o,rh,rl,rm,rn) _corrrr(_jitp,cc,o,rh,rl,rm,rn)
+__jit_inline void
+_corrrr(jit_state_t _jitp, int cc, int o, int rh, int rl, int rm, int rn)
+{
+ jit_assert(!(cc & 0x0fffffff));
+ jit_assert(!(o & 0xf00fff0f));
+ _jit_I(cc|o|(_u4(rh)<<16)|(_u4(rl)<<12)|(_u4(rm)<<8)|_u4(rn));
+}
+
+#define corrrs(cc,o,rn,rd,rm,im) _corrrs(_jitp,cc,o,rn,rd,rm,im)
+__jit_inline void
+_corrrs(jit_state_t _jitp, int cc, int o, int rn, int rd, int rm, int im)
+{
+ jit_assert(!(cc & 0x0fffffff));
+ jit_assert(!(o & 0xf000ff8f));
+ _jit_I(cc|o|(_u4(rd)<<12)|(_u4(rn)<<16)|(im<<7)|_u4(rm));
+}
+
+#define cshift(cc,o,rd,rm,rn,im) _cshift(_jitp,cc,o,rd,rm,rn,im)
+__jit_inline void
+_cshift(jit_state_t _jitp, int cc, int o, int rd, int rm, int rn, int im)
+{
+ jit_assert(!(cc & 0x0fffffff));
+ jit_assert(!(o & 0xffe0ff8f));
+ jit_assert(((_u4(rm)<<8)&(im<<7)) == 0);
+ _jit_I(cc|ARM_SHIFT|o|(_u4(rd)<<12)|(_u4(rm)<<8)|(im<<7)|_u4(rn));
+}
+
+#define cb(cc,o,im) _cb(_jitp,cc,o,im)
+__jit_inline void
+_cb(jit_state_t _jitp, int cc, int o, int im)
+{
+ jit_assert(!(cc & 0x0fffffff));
+ jit_assert(!(o & 0xf0ffffff));
+ _jit_I(cc|o|_u24(im));
+}
+
+#define cbx(cc,o,rm) _cbx(_jitp,cc,o,rm)
+__jit_inline void
+_cbx(jit_state_t _jitp, int cc, int o, int rm)
+{
+ jit_assert(!(cc & 0x0fffffff));
+ jit_assert(!(o & 0xf000000f));
+ _jit_I(cc|o|_u4(rm));
+}
+
+#define corl(cc,o,r0,i0) _corl(_jitp,cc,o,r0,i0)
+__jit_inline void
+_corl(jit_state_t _jitp, int cc, int o, int r0, int i0)
+{
+ jit_assert(!(cc & 0x0fffffff));
+ jit_assert(!(o & 0xf00fffff));
+ _jit_I(cc|o|(_u4(r0)<<16)|_u16(i0));
+}
+
+#define c6orr(cc,o,rd,rm) _c6orr(_jitp,cc,o,rd,rm)
+__jit_inline void
+_c6orr(jit_state_t _jitp, int cc, int o, int rd, int rm)
+{
+ jit_assert(!(cc & 0x0fffffff));
+ jit_assert(!(o & 0xf000f00f));
+ _jit_I(cc|o|(_u4(rd)<<12)|_u4(rm));
+}
+
+#define arm_cc_pkh(cc,o,rn,rd,rm,im) _arm_cc_pkh(_jitp,cc,o,rn,rd,rm,im)
+__jit_inline void
+_arm_cc_pkh(jit_state_t _jitp, int cc, int o, int rn, int rd, int rm, int im)
+{
+ jit_assert(!(cc & 0x0fffffff));
+ jit_assert(!(o & 0xf00ff00f));
+ _jit_I(cc|o|(_u4(rn)<<16)|(_u4(rd)<<12)|(_u5(im)<<7)|_u4(rm));
+}
+
+
+#define _CC_MOV(cc,rd,rm) corrr(cc,ARM_MOV,0,rd,rm)
+#define _MOV(rd,rm) _CC_MOV(ARM_CC_AL,rd,rm)
+#define T1_MOV(rd,rm) _jit_W(THUMB_MOV|((_u4(rd)&8)<<4)|(_u4(rm)<<3)|(rd&7))
+#define T2_MOV(rd,rm) T2_ORR(rd,_R15,rm)
+#define _CC_MOVI(cc,rd,im) corri(cc,ARM_MOV|ARM_I,0,rd,im)
+#define _MOVI(rd,im) _CC_MOVI(ARM_CC_AL,rd,im)
+#define _CC_MOVWI(cc,rd,im) coriw(cc,ARM_MOVWI,rd,im)
+#define _MOVWI(rd,im) _CC_MOVWI(ARM_CC_AL,rd,im)
+#define T1_MOVI(rd,im) _jit_W(THUMB_MOVI|(_u3(rd)<<8)|_u8(im))
+#define T2_MOVI(rd,im) torri(THUMB2_MOVI,_R15,rd,im)
+#define T2_MOVWI(rd,im) toriw(THUMB2_MOVWI,rd,im)
+#define _CC_MOVTI(cc,rd,im) coriw(cc,ARM_MOVTI,rd,im)
+#define _MOVTI(rd,im) _CC_MOVTI(ARM_CC_AL,rd,im)
+#define T2_MOVTI(rd,im) toriw(THUMB2_MOVTI,rd,im)
+#define _CC_MVN(cc,rd,rm) corrr(cc,ARM_MVN,0,rd,rm)
+#define _MVN(rd,rm) _CC_MVN(ARM_CC_AL,rd,rm)
+#define T1_MVN(rd,rm) _jit_W(THUMB_MVN|(_u3(rm)<<3)|_u3(rd))
+#define T2_MVN(rd,rm) torrr(THUMB2_MVN,rd,_R15,rm)
+#define _CC_MVNI(cc,rd,im) corri(cc,ARM_MVN|ARM_I,0,rd,im)
+#define _MVNI(rd,im) _CC_MVNI(ARM_CC_AL,rd,im)
+#define T2_MVNI(rd,im) torri(THUMB2_MVNI,_R15,rd,im)
+#define _CC_NOT(cc,rd,rm) _CC_MVN(cc,rd,rm)
+#define _NOT(rd,rm) _CC_NOT(ARM_CC_AL,rd,rm)
+#define T1_NOT(rd,rm) T1_MVN(rd,rm)
+#define T2_NOT(rd,rm) T2_MVN(rd,rm)
+#define _NOP() _MOV(_R0, _R0)
+#define T1_NOP() _jit_W(0xbf00)
+
+#define _CC_ADD(cc,rd,rn,rm) corrr(cc,ARM_ADD,rn,rd,rm)
+#define _ADD(rd,rn,rm) _CC_ADD(ARM_CC_AL,rd,rn,rm)
+#define T1_ADD(rd,rn,rm) _jit_W(THUMB_ADD|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rd))
+#define T1_ADDX(rdn,rm) _jit_W(THUMB_ADDX|((_u4(rdn)&8)<<4)|(_u4(rm)<<3)|(rdn&7))
+#define T2_ADD(rd,rn,rm) torrr(THUMB2_ADD,rn,rd,rm)
+#define _CC_ADDI(cc,rd,rn,im) corri(cc,ARM_ADD|ARM_I,rn,rd,im)
+#define _ADDI(rd,rn,im) _CC_ADDI(ARM_CC_AL,rd,rn,im)
+#define T1_ADDI3(rd,rn,im) _jit_W(THUMB_ADDI3|(_u3(im)<<6)|(_u3(rn)<<3)|_u3(rd))
+#define T1_ADDI8(rdn,im) _jit_W(THUMB_ADDI8|(_u3(rdn)<<8)|_u8(im))
+#define T2_ADDI(rd,rn,im) torri(THUMB2_ADDI,rn,rd,im)
+#define T2_ADDWI(rd,rn,im) torri(THUMB2_ADDWI,rn,rd,im)
+#define _CC_ADDS(cc,rd,rn,rm) corrr(cc,ARM_ADD|ARM_S,rn,rd,rm)
+#define _ADDS(rd,rn,rm) _CC_ADDS(ARM_CC_AL,rd,rn,rm)
+#define T2_ADDS(rd,rn,rm) torrr(THUMB2_ADD|ARM_S,rn,rd,rm)
+#define _ADDSI(rd,rn,im) corri(ARM_CC_AL,ARM_ADD|ARM_S|ARM_I,rn,rd,im)
+#define T2_ADDSI(rd,rn,im) torri(THUMB2_ADDI|ARM_S,rn,rd,im)
+#define _CC_ADC(cc,rd,rn,rm) corrr(cc,ARM_ADC,rn,rd,rm)
+#define _ADC(rd,rn,rm) _CC_ADC(ARM_CC_AL,rd,rn,rm)
+#define T1_ADC(rdn,rm) _jit_W(THUMB_ADC|(_u3(rm)<<3)|_u3(rdn))
+#define T2_ADC(rd,rn,rm) torrr(THUMB2_ADC,rn,rd,rm)
+#define _CC_ADCI(cc,rd,rn,im) corri(cc,ARM_ADC|ARM_I,rn,rd,im)
+#define _ADCI(rd,rn,im) _CC_ADCI(ARM_CC_AL,rd,rn,im)
+#define T2_ADCI(rd,rn,im) torri(THUMB2_ADCI,rn,rd,im)
+#define _CC_ADCS(cc,rd,rn,rm) corrr(cc,ARM_ADC|ARM_S,rn,rd,rm)
+#define _ADCS(rd,rn,rm) _CC_ADCS(ARM_CC_AL,rd,rn,rm)
+#define T2_ADCS(rd,rn,rm) torrr(THUMB2_ADC|ARM_S,rn,rd,rm)
+#define _CC_ADCSI(cc,rd,rn,im) corri(cc,ARM_ADC|ARM_S|ARM_I,rn,rd,im)
+#define _ADCSI(rd,rn,im) _CC_ADCSI(ARM_CC_AL,rd,rn,im)
+#define T2_ADCSI(rd,rn,im) torri(THUMB2_ADCI|ARM_S,rn,rd,im)
+#define _CC_SUB(cc,rd,rn,rm) corrr(cc,ARM_SUB,rn,rd,rm)
+#define _SUB(rd,rn,rm) _CC_SUB(ARM_CC_AL,rd,rn,rm)
+#define T1_SUB(rd,rn,rm) _jit_W(THUMB_SUB|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rd))
+#define T2_SUB(rd,rn,rm) torrr(THUMB2_SUB,rn,rd,rm)
+#define _CC_SUBI(cc,rd,rn,im) corri(cc,ARM_SUB|ARM_I,rn,rd,im)
+#define _SUBI(rd,rn,im) _CC_SUBI(ARM_CC_AL,rd,rn,im)
+#define T1_SUBI3(rd,rn,im) _jit_W(THUMB_SUBI3|(_u3(im)<<6)|(_u3(rn)<<3)|_u3(rd))
+#define T1_SUBI8(rdn,im) _jit_W(THUMB_SUBI8|(_u3(rdn)<<8)|_u8(im))
+#define T2_SUBI(rd,rn,im) torri(THUMB2_SUBI,rn,rd,im)
+#define T2_SUBWI(rd,rn,im) torri(THUMB2_SUBWI,rn,rd,im)
+#define _CC_SUBS(cc,rd,rn,rm) corrr(cc,ARM_SUB|ARM_S,rn,rd,rm)
+#define _SUBS(rd,rn,rm) _CC_SUBS(ARM_CC_AL,rd,rn,rm)
+#define T2_SUBS(rd,rn,rm) torrr(THUMB2_SUB|ARM_S,rn,rd,rm)
+#define _CC_SUBSI(cc,rd,rn,im) corri(cc,ARM_SUB|ARM_S|ARM_I,rn,rd,im)
+#define _SUBSI(rd,rn,im) _CC_SUBSI(ARM_CC_AL,rd,rn,im)
+#define T2_SUBSI(rd,rn,im) torri(THUMB2_SUBI|ARM_S,rn,rd,im)
+#define _CC_SBC(cc,rd,rn,rm) corrr(cc,ARM_SBC,rn,rd,rm)
+#define _SBC(rd,rn,rm) _CC_SBC(ARM_CC_AL,rd,rn,rm)
+#define T1_SBC(rdn,rm) _jit_W(THUMB_SBC|(_u3(rm)<<3)|_u3(rdn))
+#define T2_SBC(rd,rn,rm) torrr(THUMB2_SBC,rn,rd,rm)
+#define _CC_SBCI(cc,rd,rn,im) corri(cc,ARM_SBC|ARM_I,rn,rd,im)
+#define _SBCI(rd,rn,im) _CC_SBCI(ARM_CC_AL,rd,rn,im)
+#define T2_SBCI(rd,rn,im) torri(THUMB2_SBCI,rn,rd,im)
+#define _CC_SBCS(cc,rd,rn,rm) corrr(cc,ARM_SBC|ARM_S,rn,rd,rm)
+#define _SBCS(rd,rn,rm) _CC_SBCS(ARM_CC_AL,rd,rn,rm)
+#define T2_SBCS(rd,rn,rm) torrr(THUMB2_SBC|ARM_S,rn,rd,rm)
+#define _CC_SBCSI(cc,rd,rn,im) corri(cc,ARM_SBC|ARM_S|ARM_I,rn,rd,im)
+#define _SBCSI(rd,rn,im) _CC_SBCSI(ARM_CC_AL,rd,rn,im)
+#define T2_SBCSI(rd,rn,im) torri(THUMB2_SBCI|ARM_S,rn,rd,im)
+#define _CC_RSB(cc,rd,rn,rm) corrr(cc,ARM_RSB,rn,rd,rm)
+#define _RSB(rd,rn,rm) _CC_RSB(ARM_CC_AL,rd,rn,rm)
+#define T2_RSB(rd,rn,rm) torrr(THUMB2_RSB,rn,rd,rm)
+#define _CC_RSBI(cc,rd,rn,im) corri(cc,ARM_RSB|ARM_I,rn,rd,im)
+#define _RSBI(rd,rn,im) _CC_RSBI(ARM_CC_AL,rd,rn,im)
+#define T1_RSBI(rd,rn) _jit_W(THUMB_RSBI|(_u3(rn)<<3)|_u3(rd))
+#define T2_RSBI(rd,rn,im) torri(THUMB2_RSBI,rn,rd,im)
+
+#define _CC_MUL(cc,rl,rn,rm) corrrr(cc,ARM_MUL,rl,0,rm,rn)
+#define _MUL(rl,rn,rm) _CC_MUL(ARM_CC_AL,rl,rn,rm)
+#define T1_MUL(rdm,rn) _jit_W(THUMB_MUL|(_u3(rn)<<3)|_u3(rdm))
+#define T2_MUL(rd,rn,rm) torrr(THUMB2_MUL,rn,rd,rm)
+#define _CC_SMULL(cc,rl,rh,rn,rm) corrrr(cc,ARM_SMULL,rh,rl,rm,rn)
+#define _SMULL(rl,rh,rn,rm) _CC_SMULL(ARM_CC_AL,rl,rh,rn,rm)
+#define T2_SMULL(rl,rh,rn,rm) torrrr(THUMB2_SMULL,rn,rl,rh,rm)
+#define _CC_UMULL(cc,rl,rh,rn,rm) corrrr(cc,ARM_UMULL,rh,rl,rm,rn)
+#define _UMULL(rl,rh,rn,rm) _CC_UMULL(ARM_CC_AL,rl,rh,rn,rm)
+#define T2_UMULL(rl,rh,rn,rm) torrrr(THUMB2_UMULL,rn,rl,rh,rm)
+#define T2_SDIV(rd,rn,rm) torrr(THUMB2_SDIV,rn,rd,rm)
+#define T2_UDIV(rd,rn,rm) torrr(THUMB2_UDIV,rn,rd,rm)
+
+#define _CC_MULS(cc,rd,rn,rm) corrrr(cc,ARM_MUL|ARM_S,rd,0,rm,rn)
+#define _MULS(rd,rn,rm) _CC_MULS(ARM_CC_AL,rd,rn,rm)
+#define T2_MULS(rd,rn,rm) torrr(THUMB2_ADD|ARM_S,rn,rd,rm)
+
+#define _CC_AND(cc,rd,rn,rm) corrr(cc,ARM_AND,rn,rd,rm)
+#define _AND(rd,rn,rm) _CC_AND(ARM_CC_AL,rd,rn,rm)
+#define T1_AND(rdn,rm) _jit_W(THUMB_AND|(_u3(rm)<<3)|_u3(rdn))
+#define T2_AND(rd,rn,rm) torrr(THUMB2_AND,rn,rd,rm)
+#define _CC_ANDI(cc,rd,rn,im) corri(cc,ARM_AND|ARM_I,rn,rd,im)
+#define _ANDI(rd,rn,im) _CC_ANDI(ARM_CC_AL,rd,rn,im)
+#define T2_ANDI(rd,rn,im) torri(THUMB2_ANDI,rn,rd,im)
+#define _CC_ANDS(cc,rd,rn,rm) corrr(cc,ARM_AND|ARM_S,rn,rd,rm)
+#define _ANDS(rd,rn,rm) _CC_ANDS(ARM_CC_AL,rd,rn,rm)
+#define T2_ANDS(rd,rn,rm) torrr(THUMB2_AND|ARM_S,rn,rd,rm)
+#define _CC_ANDSI(cc,rd,rn,im) corri(cc,ARM_AND|ARM_S|ARM_I,rn,rd,im)
+#define _ANDSI(rd,rn,im) _CC_ANDSI(ARM_CC_AL,rd,rn,im)
+#define T2_ANDSI(rd,rn,im) torri(ARM_CC_AL,THUMB2_ANDI|ARM_S,rn,rd,im)
+#define _CC_BIC(cc,rd,rn,rm) corrr(cc,ARM_BIC,rn,rd,rm)
+#define _BIC(rd,rn,rm) _CC_BIC(ARM_CC_AL,rd,rn,rm)
+#define T2_BIC(rd,rn,rm) torrr(THUMB2_BIC,rn,rd,rm)
+#define _CC_BICI(cc,rd,rn,im) corri(cc,ARM_BIC|ARM_I,rn,rd,im)
+#define _BICI(rd,rn,im) _CC_BICI(ARM_CC_AL,rd,rn,im)
+#define T2_BICI(rd,rn,im) torri(THUMB2_BICI,rn,rd,im)
+#define _CC_BICS(cc,rd,rn,rm) corrr(cc,ARM_BIC|ARM_S,rn,rd,rm)
+#define _BICS(rd,rn,rm) _CC_BICS(ARM_CC_AL,rd,rn,rm)
+#define T2_BICS(rd,rn,rm) torrr(THUMB2_BIC|ARM_S,rn,rd,rm)
+#define _CC_BICSI(cc,rd,rn,im) corri(cc,ARM_BIC|ARM_S|ARM_I,rn,rd,im)
+#define _BICSI(rd,rn,im) _CC_BICSI(ARM_CC_AL,rd,rn,im)
+#define T2_BICSI(rd,rn,im) torri(ARM_CC_AL,THUMB2_BICI|ARM_S,rn,rd,im)
+#define _CC_ORR(cc,rd,rn,rm) corrr(cc,ARM_ORR,rn,rd,rm)
+#define _ORR(rd,rn,rm) _CC_ORR(ARM_CC_AL,rd,rn,rm)
+#define T1_ORR(rdn,rm) _jit_W(THUMB_ORR|(_u3(rm)<<3)|_u3(rdn))
+#define T2_ORR(rd,rn,rm) torrr(THUMB2_ORR,rn,rd,rm)
+#define _CC_ORR_SI(cc,rd,rn,rm,sh,im) \
+ corrrs(cc,ARM_ORR|sh,rn,rd,rm,im)
+#define _ORR_SI(rd,rn,rm,sh,im) _CC_ORR_SI(ARM_CC_AL,rd,rn,rm,sh,im)
+#define _CC_ORRI(cc,rd,rn,im) corri(cc,ARM_ORR|ARM_I,rn,rd,im)
+#define _ORRI(rd,rn,im) _CC_ORRI(ARM_CC_AL,rd,rn,im)
+#define T2_ORRI(rd,rn,im) torri(THUMB2_ORRI,rn,rd,im)
+#define _CC_EOR(cc,rd,rn,rm) corrr(cc,ARM_EOR,rn,rd,rm)
+#define _EOR(rd,rn,rm) _CC_EOR(ARM_CC_AL,rd,rn,rm)
+#define T1_EOR(rdn,rm) _jit_W(THUMB_EOR|(_u3(rm)<<3)|_u3(rdn))
+#define T2_EOR(rd,rn,rm) torrr(THUMB2_EOR,rn,rd,rm)
+#define _CC_EOR_SI(cc,rd,rn,rm,sh,im) \
+ corrrs(cc,ARM_EOR|sh,rn,rd,rm,im)
+#define _EOR_SI(rd,rn,rm,sh,im) _CC_EOR_SI(ARM_CC_AL,rd,rn,rm,sh,im)
+#define _CC_EORI(cc,rd,rn,im) corri(cc,ARM_EOR|ARM_I,rn,rd,im)
+#define _EORI(rd,rn,im) _CC_EORI(ARM_CC_AL,rd,rn,im)
+#define T2_EORI(rd,rn,im) torri(THUMB2_EORI,rn,rd,im)
+
+#define _CC_REV(cc,rd,rm) c6orr(cc,ARM_REV,rd,rm)
+#define _REV(rd,rm) _CC_REV(ARM_CC_AL,rd,rm)
+#define T1_REV(rd,rm) _jit_W(THUMB_REV|(_u3(rm)<<3)|_u3(rd))
+#define T2_REV(rd,rm) torrr(THUMB2_REV,rm,rd,rm)
+#define _CC_REV16(cc,rd,rm) c6orr(cc,ARM_REV16,rd,rm)
+#define _REV16(rd,rm) _CC_REV16(ARM_CC_AL,rd,rm)
+#define T1_REV16(rd,rm) _jit_W(THUMB_REV16|(_u3(rm)<<3)|_u3(rd))
+#define T2_REV16(rd,rm) torrr(THUMB2_REV16,rm,rd,rm)
+#define _CC_SXTB(cc,rd,rm) c6orr(cc,ARM_SXTB,rd,rm)
+#define _SXTB(rd,rm) _CC_SXTB(ARM_CC_AL,rd,rm)
+#define T1_SXTB(rd,rm) _jit_W(THUMB_SXTB|(_u3(rm)<<3)|_u3(rd))
+#define T2_SXTB(rd,rm) torrr(THUMB2_SXTB,_R15,rd,rm)
+#define _CC_UXTB(cc,rd,rm) c6orr(cc,ARM_UXTB,rd,rm)
+#define _UXTB(rd,rm) _CC_UXTB(ARM_CC_AL,rd,rm)
+#define T1_UXTB(rd,rm) _jit_W(THUMB_UXTB|(_u3(rm)<<3)|_u3(rd))
+#define T2_UXTB(rd,rm) torrr(THUMB2_UXTB,_R15,rd,rm)
+#define _CC_SXTH(cc,rd,rm) c6orr(cc,ARM_SXTH,rd,rm)
+#define _SXTH(rd,rm) _CC_SXTH(ARM_CC_AL,rd,rm)
+#define T1_SXTH(rd,rm) _jit_W(THUMB_SXTH|(_u3(rm)<<3)|_u3(rd))
+#define T2_SXTH(rd,rm) torrr(THUMB2_SXTH,_R15,rd,rm)
+#define _CC_UXTH(cc,rd,rm) c6orr(cc,ARM_UXTH,rd,rm)
+#define _UXTH(rd,rm) _CC_UXTH(ARM_CC_AL,rd,rm)
+#define T1_UXTH(rd,rm) _jit_W(THUMB_UXTH|(_u3(rm)<<3)|_u3(rd))
+#define T2_UXTH(rd,rm) torrr(THUMB2_UXTH,_R15,rd,rm)
+
+#define _CC_SHIFT(cc,o,rd,rm,rn,im) cshift(cc,o,rd,rm,rn,im)
+#define _CC_LSL(cc,rd,rn,rm) _CC_SHIFT(cc,ARM_LSL|ARM_R,rd,rm,rn,0)
+#define _LSL(rd,rn,rm) _CC_LSL(ARM_CC_AL,rd,rn,rm)
+#define T1_LSL(rdn,rm) _jit_W(THUMB_LSL|(_u3(rm)<<3)|_u3(rdn))
+#define T2_LSL(rd,rn,rm) torrr(THUMB2_LSL,rn,rd,rm)
+#define _CC_LSLI(cc,rd,rn,im) _CC_SHIFT(cc,ARM_LSL,rd,0,rn,im)
+#define _LSLI(rd,rn,im) _CC_LSLI(ARM_CC_AL,rd,rn,im)
+#define T1_LSLI(rd,rm,im) _jit_W(THUMB_LSLI|(_u5(im)<<6)|(_u3(rm)<<3)|_u3(rd))
+#define T2_LSLI(rd,rm,im) tshift(THUMB2_LSLI,rd,rm,im)
+#define _CC_LSR(cc,rd,rn,rm) _CC_SHIFT(cc,ARM_LSR|ARM_R,rd,rm,rn,0)
+#define _LSR(rd,rn,rm) _CC_LSR(ARM_CC_AL,rd,rn,rm)
+#define T1_LSR(rdn,rm) _jit_W(THUMB_LSR|(_u3(rm)<<3)|_u3(rdn))
+#define T2_LSR(rd,rn,rm) torrr(THUMB2_LSR,rn,rd,rm)
+#define _CC_LSRI(cc,rd,rn,im) _CC_SHIFT(cc,ARM_LSR,rd,0,rn,im)
+#define _LSRI(rd,rn,im) _CC_LSRI(ARM_CC_AL,rd,rn,im)
+#define T1_LSRI(rd,rm,im) _jit_W(THUMB_LSRI|(_u5(im)<<6)|(_u3(rm)<<3)|_u3(rd))
+#define T2_LSRI(rd,rm,im) tshift(THUMB2_LSRI,rd,rm,im)
+#define _CC_ASR(cc,rd,rn,rm) _CC_SHIFT(cc,ARM_ASR|ARM_R,rd,rm,rn,0)
+#define _ASR(rd,rn,rm) _CC_ASR(ARM_CC_AL,rd,rn,rm)
+#define T1_ASR(rdn,rm) _jit_W(THUMB_ASR|(_u3(rm)<<3)|_u3(rdn))
+#define T2_ASR(rd,rn,rm) torrr(THUMB2_ASR,rn,rd,rm)
+#define _CC_ASRI(cc,rd,rn,im) _CC_SHIFT(cc,ARM_ASR,rd,0,rn,im)
+#define _ASRI(rd,rn,im) _CC_ASRI(ARM_CC_AL,rd,rn,im)
+#define T1_ASRI(rd,rm,im) _jit_W(THUMB_ASRI|(_u5(im)<<6)|(_u3(rm)<<3)|_u3(rd))
+#define T2_ASRI(rd,rm,im) tshift(THUMB2_ASRI,rd,rm,im)
+
+#define _CC_CMP(cc,rn,rm) corrr(cc,ARM_CMP,rn,0,rm)
+#define _CC_CMPSH(cc,rn,rm,t,s) corrrs(cc,ARM_CMP|t,rn,0,rm,s)
+#define _CMP(rn,rm) _CC_CMP(ARM_CC_AL,rn,rm)
+#define T1_CMP(rn,rm) _jit_W(THUMB_CMP|(_u3(rm)<<3)|_u3(rn))
+#define T1_CMPX(rn,rm) _jit_W(THUMB_CMPX|((_u4(rn)&8)<<4)|(_u4(rm)<<3)|(rn&7))
+#define T2_CMP(rn,rm) torrr(THUMB2_CMP,rn,_R15,rm)
+#define _CC_CMPI(cc,rn,im) corri(cc,ARM_CMP|ARM_I,rn,0,im)
+#define _CMPI(rn,im) _CC_CMPI(ARM_CC_AL,rn,im)
+#define T1_CMPI(rn,im) _jit_W(THUMB_CMPI|(_u3(rn)<<8)|_u8(im))
+#define T2_CMPI(rn,im) torri(THUMB2_CMPI,rn,_R15,im)
+#define _CC_CMN(cc,rn,rm) corrr(cc,ARM_CMN,rn,0,rm)
+#define _CMN(rn,rm) _CC_CMN(ARM_CC_AL,rn,rm)
+#define T1_CMN(rn,rm) _jit_W(THUMB_CMN|(_u3(rm)<<3)|_u3(rm))
+#define T2_CMN(rn,rm) torrr(THUMB2_CMN,rn,_R15,rm)
+#define _CC_CMNI(cc,rn,im) corri(cc,ARM_CMN|ARM_I,rn,_R15,im)
+#define _CMNI(rn,im) _CC_CMNI(ARM_CC_AL,rn,im)
+#define T2_CMNI(rn,im) torri(THUMB2_CMNI,rn,_R15,im)
+#define _CC_TST(cc,rn,rm) corrr(cc,ARM_TST,rn,r0,rm)
+#define _TST(rn,rm) _CC_TST(ARM_CC_AL,rn,rm)
+#define T1_TST(rn,rm) _jit_W(THUMB_TST|(_u3(rm)<<3)|_u3(rn))
+#define T2_TST(rn,rm) torrr(THUMB2_TST,rn,_R15,rm)
+#define _CC_TSTI(cc,rn,im) corri(cc,ARM_TST|ARM_I,rn,0,im)
+#define _TSTI(rn,im) _CC_TSTI(ARM_CC_AL,rn,im)
+#define T2_TSTI(rn,im) torri(THUMB2_TSTI,rn,_R15,im)
+#define _CC_TEQ(cc,rn,rm) corrr(cc,ARM_TEQ,rn,0,rm)
+#define _TEQ(rn,rm) _CC_TEQ(ARM_CC_AL,rn,rm)
+#define _CC_TEQI(cc,rm,im) corri(cc,ARM_TEQ|ARM_I,rn,0,im)
+#define _TEQI(rn,im) _CC_TEQI(ARM_CC_AL,rn,im)
+
+#define _CC_BX(cc,rm) cbx(cc,ARM_BX,rm)
+#define _BX(rm) _CC_BX(ARM_CC_AL,rm)
+#define T1_BX(rm) _jit_W(0x4700|(_u4(rm)<<3))
+#define _CC_BLX(cc,rm) cbx(cc,ARM_BLX,rm)
+#define _BLX(rm) _CC_BLX(ARM_CC_AL,rm)
+#define T1_BLX(rm) _jit_W(THUMB_BLX|(_u4(rm)<<3))
+#define _BLXI(im) blxi(im)
+#define T2_BLXI(im) tb(THUMB2_BLXI,im)
+#define _CC_B(cc,im) cb(cc,ARM_B,im)
+#define _B(im) _CC_B(ARM_CC_AL,im)
+#define T1_CC_B(cc,im) tc8(cc,im)
+#define T1_B(im) t11(im)
+#define T2_CC_B(cc,im) tcb(cc,im)
+#define T2_B(im) tb(THUMB2_B,im)
+#define _CC_BLI(cc,im) cb(cc,ARM_BLI,im)
+#define _BLI(im) _CC_BLI(ARM_CC_AL,im)
+#define T2_BLI(im) tb(THUMB2_BLI,im)
+
+#define _CC_LDRSB(cc,rt,rn,rm) corrr(cc,ARM_LDRSB|ARM_P,rn,rt,rm)
+#define _LDRSB(rt,rn,rm) _CC_LDRSB(ARM_CC_AL,rt,rn,rm)
+#define T1_LDRSB(rt,rn,rm) _jit_W(THUMB_LDRSB|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt))
+#define T2_LDRSB(rt,rn,rm) torxr(THUMB2_LDRSB,rn,rt,rm)
+#define _CC_LDRSBN(cc,rt,rn,rm) corrr(cc,ARM_LDRSB,rn,rt,rm)
+#define _LDRSBN(rt,rn,rm) _CC_LDRSBN(ARM_CC_AL,rt,rn,rm)
+#define _CC_LDRSBI(cc,rt,rn,im) corri8(cc,ARM_LDRSBI|ARM_P,rn,rt,im)
+#define _LDRSBI(rt,rn,im) _CC_LDRSBI(ARM_CC_AL,rt,rn,im)
+#define T2_LDRSBI(rt,rn,im) torri8(THUMB2_LDRSBI|THUMB2_U,rn,rt,im)
+#define T2_LDRSBWI(rt,rn,im) torri12(THUMB2_LDRSBWI,rn,rt,im)
+#define _CC_LDRSBIN(cc,rt,rn,im) corri8(cc,ARM_LDRSBI,rn,rt,im)
+#define _LDRSBIN(rt,rn,im) _CC_LDRSBIN(ARM_CC_AL,rt,rn,im)
+#define T2_LDRSBIN(rt,rn,im) torri8(THUMB2_LDRSBI,rn,rt,im)
+#define _CC_LDRB(cc,rt,rn,rm) corrr(cc,ARM_LDRB|ARM_P,rn,rt,rm)
+#define _LDRB(rt,rn,rm) _CC_LDRB(ARM_CC_AL,rt,rn,rm)
+#define T1_LDRB(rt,rn,rm) _jit_W(THUMB_LDRB|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt))
+#define T2_LDRB(rt,rn,rm) torxr(THUMB2_LDRB,rn,rt,rm)
+#define _CC_LDRBN(cc,rt,rn,rm) corrr(cc,ARM_LDRB,rn,rt,rm)
+#define _LDRBN(rt,rn,rm) _CC_LDRBN(ARM_CC_AL,rt,rn,rm)
+#define _CC_LDRBI(cc,rt,rn,im) corri(cc,ARM_LDRBI|ARM_P,rn,rt,im)
+#define _LDRBI(rt,rn,im) _CC_LDRBI(ARM_CC_AL,rt,rn,im)
+#define T1_LDRBI(rt,rn,im) _jit_W(THUMB_LDRBI|(_u5(im)<<6)|(_u3(rn)<<3)|_u3(rt))
+#define T2_LDRBI(rt,rn,im) torri8(THUMB2_LDRBI|THUMB2_U,rn,rt,im)
+#define T2_LDRBWI(rt,rn,im) torri12(THUMB2_LDRBWI,rn,rt,im)
+#define _CC_LDRBIN(cc,rt,rn,im) corri(cc,ARM_LDRBI,rn,rt,im)
+#define _LDRBIN(rt,rn,im) _CC_LDRBIN(ARM_CC_AL,rt,rn,im)
+#define T2_LDRBIN(rt,rn,im) torri8(THUMB2_LDRBI,rn,rt,im)
+#define _CC_LDRSH(cc,rt,rn,rm) corrr(cc,ARM_LDRSH|ARM_P,rn,rt,rm)
+#define _LDRSH(rt,rn,rm) _CC_LDRSH(ARM_CC_AL,rt,rn,rm)
+#define T1_LDRSH(rt,rn,rm) _jit_W(THUMB_LDRSH|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt))
+#define T2_LDRSH(rt,rn,rm) torxr(THUMB2_LDRSH,rn,rt,rm)
+#define _CC_LDRSHN(cc,rt,rn,rm) corrr(cc,ARM_LDRSH,rn,rt,rm)
+#define _LDRSHN(rt,rn,rm) _CC_LDRSHN(ARM_CC_AL,rt,rn,rm)
+#define _CC_LDRSHI(cc,rt,rn,im) corri8(cc,ARM_LDRSHI|ARM_P,rn,rt,im)
+#define _LDRSHI(rt,rn,im) _CC_LDRSHI(ARM_CC_AL,rt,rn,im)
+#define T2_LDRSHI(rt,rn,im) torri8(THUMB2_LDRSHI|THUMB2_U,rn,rt,im)
+#define T2_LDRSHWI(rt,rn,im) torri12(THUMB2_LDRSHWI,rn,rt,im)
+#define _CC_LDRSHIN(cc,rt,rn,im) corri8(cc,ARM_LDRSHI,rn,rt,im)
+#define _LDRSHIN(rt,rn,im) _CC_LDRSHIN(ARM_CC_AL,rt,rn,im)
+#define T2_LDRSHIN(rt,rn,im) torri8(THUMB2_LDRSHI,rn,rt,im)
+#define _CC_LDRH(cc,rt,rn,rm) corrr(cc,ARM_LDRH|ARM_P,rn,rt,rm)
+#define _LDRH(rt,rn,rm) _CC_LDRH(ARM_CC_AL,rt,rn,rm)
+#define T1_LDRH(rt,rn,rm) _jit_W(THUMB_LDRH|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt))
+#define T2_LDRH(rt,rn,rm) torxr(THUMB2_LDRH,rn,rt,rm)
+#define _CC_LDRHN(cc,rt,rn,rm) corrr(cc,ARM_LDRH,rn,rt,rm)
+#define _LDRHN(rt,rn,rm) CC_LDRHN(ARM_CC_AL,rt,rn,rm)
+#define _CC_LDRHI(cc,rt,rn,im) corri8(cc,ARM_LDRHI|ARM_P,rn,rt,im)
+#define _LDRHI(rt,rn,im) _CC_LDRHI(ARM_CC_AL,rt,rn,im)
+#define T1_LDRHI(rt,rn,im) _jit_W(THUMB_LDRHI|(_u5(im)<<6)|(_u3(rn)<<3)|_u3(rt))
+#define T2_LDRHI(rt,rn,im) torri8(THUMB2_LDRHI|THUMB2_U,rn,rt,im)
+#define T2_LDRHWI(rt,rn,im) torri12(THUMB2_LDRHWI,rn,rt,im)
+#define _CC_LDRHIN(cc,rt,rn,im) corri8(cc,ARM_LDRHI,rn,rt,im)
+#define _LDRHIN(rt,rn,im) _CC_LDRHIN(ARM_CC_AL,rt,rn,im)
+#define T2_LDRHIN(rt,rn,im) torri8(THUMB2_LDRHI,rn,rt,im)
+#define _CC_LDR(cc,rt,rn,rm) corrr(cc,ARM_LDR|ARM_P,rn,rt,rm)
+#define _LDR(rt,rn,rm) _CC_LDR(ARM_CC_AL,rt,rn,rm)
+#define T1_LDR(rt,rn,rm) _jit_W(THUMB_LDR|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt))
+#define T2_LDR(rt,rn,rm) torxr(THUMB2_LDR,rn,rt,rm)
+#define _CC_LDRN(cc,rt,rn,rm) corrr(cc,ARM_LDR,rn,rt,rm)
+#define _LDRN(rt,rn,rm) _CC_LDRN(ARM_CC_AL,rt,rn,rm)
+#define _CC_LDRI(cc,rt,rn,im) corri(cc,ARM_LDRI|ARM_P,rn,rt,im)
+#define _LDRI(rt,rn,im) _CC_LDRI(ARM_CC_AL,rt,rn,im)
+#define T1_LDRI(rt,rn,im) _jit_W(THUMB_LDRI|(_u5(im)<<6)|(_u3(rn)<<3)|_u3(rt))
+#define T1_LDRISP(rt,im) _jit_W(THUMB_LDRISP|(_u3(rt)<<8)|_u8(im))
+#define T2_LDRI(rt,rn,im) torri8(THUMB2_LDRI|THUMB2_U,rn,rt,im)
+#define T2_LDRWI(rt,rn,im) torri12(THUMB2_LDRWI,rn,rt,im)
+#define _CC_LDRIN(cc,rt,rn,im) corri(cc,ARM_LDRI,rn,rt,im)
+#define _LDRIN(rt,rn,im) _CC_LDRIN(ARM_CC_AL,rt,rn,im)
+#define T2_LDRIN(rt,rn,im) torri8(THUMB2_LDRI,rn,rt,im)
+#define _CC_LDRD(cc,rt,rn,rm) corrr(cc,ARM_LDRD|ARM_P,rn,rt,rm)
+#define _LDRD(rt,rn,rm) _CC_LDRD(ARM_CC_AL,rt,rn,rm)
+#define _CC_LDRDN(cc,rt,rn,rm) corrr(cc,ARM_LDRD,rn,rt,rm)
+#define _LDRDN(rd,rn,rm) _CC_LDRDN(ARM_CC_AL,rn,rt,rm)
+#define _CC_LDRDI(cc,rt,rn,im) corri8(cc,ARM_LDRDI|ARM_P,rn,rt,im)
+#define _LDRDI(rt,rn,im) _CC_LDRDI(ARM_CC_AL,rn,rt,im)
+#define T2_LDRDI(rt,rt2,rn,im) torrri8(THUMB2_LDRDI|ARM_P,rn,rt,rt2,im)
+#define _CC_LDRDIN(cc,rt,rn,im) corri8(cc,ARM_LDRDI,rn,rt,im)
+#define _LDRDIN(rt,rn,im) _CC_LDRDIN(ARM_CC_AL,rt,rn,im)
+#define T2_LDRDIN(rt,rt2,rn,im) torrri8(THUMB2_LDRDI,rn,rt,rt2,im)
+#define _CC_STRB(cc,rt,rn,rm) corrr(cc,ARM_STRB|ARM_P,rn,rt,rm)
+#define _STRB(rt,rn,rm) _CC_STRB(ARM_CC_AL,rt,rn,rm)
+#define T1_STRB(rt,rn,rm) _jit_W(THUMB_STRB|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt))
+#define T2_STRB(rt,rn,rm) torxr(THUMB2_STRB,rn,rt,rm)
+#define _CC_STRBN(cc,rt,rn,rm) corrr(cc,ARM_STRB,rn,rt,rm)
+#define _STRBN(rt,rn,rm) _CC_STRBN(ARM_CC_AL,rt,rn,rm)
+#define _CC_STRBI(cc,rt,rn,im) corri(cc,ARM_STRBI|ARM_P,rn,rt,im)
+#define _STRBI(rt,rn,im) _CC_STRBI(ARM_CC_AL,rt,rn,im)
+#define T1_STRBI(rt,rn,im) _jit_W(THUMB_STRBI|(_u5(im)<<6)|(_u3(rn)<<3)|_u3(rt))
+#define T2_STRBI(rt,rn,im) torri8(THUMB2_STRBI|THUMB2_U,rn,rt,im)
+#define T2_STRBWI(rt,rn,im) torri12(THUMB2_STRBWI,rn,rt,im)
+#define _CC_STRBIN(cc,rt,rn,im) corri(cc,ARM_STRBI,rn,rt,im)
+#define _STRBIN(rt,rn,im) _CC_STRBIN(ARM_CC_AL,rt,rn,im)
+#define T2_STRBIN(rt,rn,im) torri8(THUMB2_STRBI,rn,rt,im)
+#define _CC_STRH(cc,rt,rn,rm) corrr(cc,ARM_STRH|ARM_P,rn,rt,rm)
+#define _STRH(rt,rn,rm) _CC_STRH(ARM_CC_AL,rt,rn,rm)
+#define T1_STRH(rt,rn,rm) _jit_W(THUMB_STRH|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt))
+#define T2_STRH(rt,rn,rm) torxr(THUMB2_STRH,rn,rt,rm)
+#define _CC_STRHN(cc,rt,rn,rm) corrr(cc,ARM_STRH,rn,rt,rm)
+#define _STRHN(rt,rn,rm) _CC_STRHN(ARM_CC_AL,rt,rn,rm)
+#define _CC_STRHI(cc,rt,rn,im) corri8(cc,ARM_STRHI|ARM_P,rn,rt,im)
+#define _STRHI(rt,rn,im) _CC_STRHI(ARM_CC_AL,rt,rn,im)
+#define T1_STRHI(rt,rn,im) _jit_W(THUMB_STRHI|(_u5(im)<<6)|(_u3(rn)<<3)|_u3(rt))
+#define T2_STRHI(rt,rn,im) torri8(THUMB2_STRHI|THUMB2_U,rn,rt,im)
+#define T2_STRHWI(rt,rn,im) torri12(THUMB2_STRHWI,rn,rt,im)
+#define _CC_STRHIN(cc,rt,rn,im) corri8(cc,ARM_STRHI,rn,rt,im)
+#define _STRHIN(rt,rn,im) _CC_STRHIN(ARM_CC_AL,rt,rn,im)
+#define T2_STRHIN(rt,rn,im) torri8(THUMB2_STRHI,rn,rt,im)
+#define _CC_STR(cc,rt,rn,rm) corrr(cc,ARM_STR|ARM_P,rn,rt,rm)
+#define _STR(rt,rn,rm) _CC_STR(ARM_CC_AL,rt,rn,rm)
+#define T1_STR(rt,rn,rm) _jit_W(THUMB_STR|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt))
+#define T2_STR(rt,rn,rm) torxr(THUMB2_STR,rn,rt,rm)
+#define _CC_STRN(cc,rt,rn,rm) corrr(cc,ARM_STR,rn,rt,rm)
+#define _STRN(rt,rn,rm) _CC_STRN(ARM_CC_AL,rt,rn,rm)
+#define _CC_STRI(cc,rt,rn,im) corri(cc,ARM_STRI|ARM_P,rn,rt,im)
+#define _STRI(rt,rn,im) _CC_STRI(ARM_CC_AL,rt,rn,im)
+#define T1_STRI(rt,rn,im) _jit_W(THUMB_STRI|(_u5(im)<<6)|(_u3(rn)<<3)|_u3(rt))
+#define T1_STRISP(rt,im) _jit_W(THUMB_STRISP|(_u3(rt)<<8)|(_u8(im)))
+#define T2_STRI(rt,rn,im) torri8(THUMB2_STRI|THUMB2_U,rn,rt,im)
+#define T2_STRWI(rt,rn,im) torri12(THUMB2_STRWI,rn,rt,im)
+#define _CC_STRIN(cc,rt,rn,im) corri(cc,ARM_STRI,rn,rt,im)
+#define _STRIN(rt,rn,im) _CC_STRIN(ARM_CC_AL,rt,rn,im)
+#define T2_STRIN(rt,rn,im) torri8(THUMB2_STRI,rn,rt,im)
+#define _CC_STRD(cc,rt,rn,rm) corrr(cc,ARM_STRD|ARM_P,rt,rn,rm)
+#define _STRD(rt,rn,rm) _CC_STRD(ARM_CC_AL,rt,rn,rm)
+#define _CC_STRDN(cc,rt,rn,rm) corrr(cc,ARM_STRD,rn,rt,rm)
+#define _STRDN(rt,rn,rm) _CC_STRDN(ARM_CC_AL,rt,rn,rm)
+#define _CC_STRDI(cc,rt,rn,im) corri8(cc,ARM_STRDI|ARM_P,rn,rt,im)
+#define _STRDI(rt,rn,im) _CC_STRDI(ARM_CC_AL,rt,rn,im)
+#define T2_STRDI(rt,rt2,rn,im) torrri8(THUMB2_STRDI|ARM_P,rn,rt,rt2,im)
+#define _CC_STRDIN(cc,rt,rn,im) corri8(cc,ARM_STRDI,rn,rt,im)
+#define _STRDIN(rt,rn,im) _CC_STRDIN(ARM_CC_AL,rt,rn,im)
+#define T2_STRDIN(rt,rt2,rn,im) torrri8(THUMB2_STRDI,rn,rt,rt2,im)
+
+#define _CC_LDMIA(cc,rn,im) corl(cc,ARM_M|ARM_M_L|ARM_M_I,rn,im)
+#define _LDMIA(rn,im) _CC_LDMIA(ARM_CC_AL,rn,im)
+#define _CC_LDM(cc,rn,im) _CC_LDMIA(cc,rn,im)
+#define _LDM(rn,im) _LDMIA(rn,im)
+#define T1_LDMIA(rn,im) _jit_W(THUMB_LDMIA|(_u3(rn)<<8)|im)
+#define T2_LDMIA(rn,im) torl(THUMB2_LDMIA,rn,im)
+#define _CC_LDMIA_U(cc,rn,im) corl(cc,ARM_M|ARM_M_L|ARM_M_I|ARM_M_U,rn,im)
+#define _LDMIA_U(rn,im) _CC_LDMIA_U(ARM_CC_AL,rn,im)
+#define _LDM_U(r0,i0) _LDMIA_U(r0,i0)
+#define _CC_LDMIB(cc,rn,im) corl(cc,ARM_M|ARM_M_L|ARM_M_I|ARM_M_B,rn,im)
+#define _LDMIB(rn,im) _CC_LDMIB(ARM_CC_AL,rn,im)
+#define _CC_LDMIB_U(cc,rn,im) corl(cc,ARM_M|ARM_M_L|ARM_M_I|ARM_M_B|ARM_M_U,rn,im)
+#define _LDMIB_U(rn,im) _CC_LDMIB_U(ARM_CC_AL,rn,im)
+#define _CC_LDMDA(cc,rn,im) corl(cc,ARM_M|ARM_M_L,rn,im)
+#define _LDMDA(rn,im) _CC_LDMDA(ARM_CC_AL,rn,im)
+#define _CC_LDMDA_U(cc,rn,im) corl(cc,ARM_M|ARM_M_L|ARM_M_U,rn,im)
+#define _LDMDA_U(rn,im) _CC_LDMDA_U(ARM_CC_AL,rn,im)
+#define _CC_LDMDB(cc,rn,im) corl(cc,ARM_M|ARM_M_L|ARM_M_B,rn,im)
+#define _LDMDB(rn,im) _CC_LDMDB(ARM_CC_AL,rn,im)
+# define T2_LDMDB(rn,im) torl(THUMB2_LDMDB,rn,im)
+
+#define _CC_LDMDB_U(cc,rn,im) corl(cc,ARM_M|ARM_M_L|ARM_M_B|ARM_M_U,rn,im)
+#define _LDMDB_U(rn,im) _CC_LDMDB_U(ARM_CC_AL,rn,im)
+#define _CC_STMIA(cc,rn,im) corl(cc,ARM_M|ARM_M_I,rn,im)
+#define _STMIA(rn,im) _CC_STMIA(ARM_CC_AL,rn,im)
+#define _CC_STM(cc,rn,im) _CC_STMIA(cc,rn,im)
+#define _STM(rn,im) _STMIA(rn,im)
+#define _CC_STMIA_U(cc,rn,im) corl(cc,ARM_M|ARM_M_I|ARM_M_U,rn,im)
+#define _STMIA_U(rn,im) _CC_STMIA_U(ARM_CC_AL,rn,im)
+#define _CC_STM_U(cc,rn,im) _CC_STMIA_U(cc,rn,im)
+#define _STM_U(rn,im) _STMIA_U(rn,im)
+#define _CC_STMIB(cc,rn,im) corl(cc,ARM_M|ARM_M_I|ARM_M_B,rn,im)
+#define _STMIB(rn,im) _CC_STMIB(ARM_CC_AL,rn,im)
+#define _CC_STMIB_U(cc,rn,im) corl(cc,ARM_M|ARM_M_I|ARM_M_B|ARM_M_U,rn,im)
+#define _STMIB_U(rn,im) _CC_STMIB_U(ARM_CC_AL,rn,im)
+#define _CC_STMDA(cc,rn,im) corl(cc,ARM_M,rn,im)
+#define _STMDA(rn,im) _CC_STMDA(ARM_CC_AL,rn,im)
+#define _CC_STMDA_U(cc,rn,im) corl(cc,ARM_M|ARM_M_U,rn,im)
+#define _STMDA_U(rn,im) _CC_STMDA_U(ARM_CC_AL,rn,im)
+#define _CC_STMDB(cc,rn,im) corl(cc,ARM_M|ARM_M_B,rn,im)
+#define _STMDB(rn,im) _CC_STMDB(ARM_CC_AL,rn,im)
+#define _CC_STMDB_U(cc,rn,im) corl(cc,ARM_M|ARM_M_B|ARM_M_U,rn,im)
+#define _STMDB_U(rn,im) _CC_STMDB_U(ARM_CC_AL,rn,im)
+#define _CC_PUSH(cc,im) _CC_STMDB_U(cc,JIT_SP,im)
+#define _PUSH(im) _STMDB_U(JIT_SP,im)
+#define T1_PUSH(im) _jit_W(THUMB_PUSH|((im&0x4000)>>6)|(im&0xff))
+#define T2_PUSH(im) tpp(THUMB2_PUSH,im)
+#define _CC_POP(cc,im) _LDMIA_U(cc,JIT_SP,im)
+#define _POP(im) _LDMIA_U(JIT_SP,im)
+#define T1_POP(im) _jit_W(THUMB_POP|((im&0x8000)>>7)|(im&0xff))
+#define T2_POP(im) tpp(THUMB2_POP,im)
+
+#define _CC_PKHBTI(cc,rd,rn,rm,im) arm_cc_pkh(cc,ARM_PKH,rn,rd,rm,im)
+#define _CC_PKHTBI(cc,rd,rn,rm,im) arm_cc_pkh(cc,ARM_PKH|ARM_ASR,rn,rd,rm,im)
+#define _PKHBTI(rd,rn,rm,im) _CC_PKHBTI(ARM_CC_AL,rd,rn,rm,im)
+#define _PKHTBI(rd,rn,rm,im) _CC_PKHTBI(ARM_CC_AL,rd,rn,rm,im)
+#define _PKHBT(rd,rn,rm) _CC_PKHBTI(ARM_CC_AL,rd,rn,rm,0)
+#define _PKHTB(rd,rn,rm) _CC_PKHTBI(ARM_CC_AL,rd,rn,rm,0)
+
+static int
+encode_thumb_immediate(unsigned int v)
+{
+ int i;
+ unsigned int m;
+ unsigned int n;
+ /* 00000000 00000000 00000000 abcdefgh */
+ if ((v & 0xff) == v)
+ return (v);
+ /* 00000000 abcdefgh 00000000 abcdefgh */
+ if ((v & 0xff00ff) == v && ((v & 0xff0000) >> 16) == (v & 0xff))
+ return ((v & 0xff) | (1 << 12));
+ /* abcdefgh 00000000 abcdefgh 00000000 */
+ if (((v & 0xffff0000) >> 16) == (v & 0xffff) && (v & 0xff) == 0)
+ return ((v & 0x000000ff) | (2 << 12));
+ /* abcdefgh abcdefgh abcdefgh abcdefgh */
+ if ( (v & 0xff) == ((v & 0xff00) >> 8) &&
+ ((v & 0xff00) >> 8) == ((v & 0xff0000) >> 16) &&
+ ((v & 0xff0000) << 8) == (v & 0xff000000))
+ return ((v & 0xff) | (3 << 12));
+ /* 1bcdefgh << 24 ... 1bcdefgh << 1 */
+ for (i = 8, m = 0xff000000, n = 0x80000000;
+ i < 23; i++, m >>= 1, n >>= 1) {
+ if ((v & m) == v && (v & n)) {
+ v >>= 32 - i;
+ if (!(i & 1))
+ v &= 0x7f;
+ i >>= 1;
+ return (((i & 7) << 12) | ((i & 8) << 23) | v);
+ }
+ }
+ return (-1);
+}
+
+static int
+encode_thumb_word_immediate(unsigned int v)
+{
+ if ((v & 0xfffff000) == 0)
+ return (((v & 0x800) << 15) | ((v & 0x700) << 4) | (v & 0xff));
+ return (-1);
+}
+
+static int
+encode_thumb_jump(int v)
+{
+ int s, i1, i2, j1, j2;
+ if (v >= (int)-0x800000 && v <= 0x7fffff) {
+ s = !!(v & 0x800000);
+ i1 = !!(v & 0x400000);
+ i2 = !!(v & 0x200000);
+ j1 = s ? i1 : !i1;
+ j2 = s ? i2 : !i2;
+ return ((s<<26)|((v&0x1ff800)<<5)|(j1<<13)|(j2<<11)|(v&0x7ff));
+ }
+ return (-1);
+}
+
+static int
+encode_thumb_cc_jump(int v)
+{
+ int s, j1, j2;
+ if (v >= (int)-0x80000 && v <= 0x7ffff) {
+ s = !!(v & 0x80000);
+ j1 = !!(v & 0x20000);
+ j2 = !!(v & 0x40000);
+ return ((s<<26)|((v&0x1f800)<<5)|(j1<<13)|(j2<<11)|(v&0x7ff));
+ }
+ return (-1);
+}
+
+#if !NAN_TO_INT_IS_ZERO
+static int
+encode_thumb_shift(int v, int type)
+{
+ switch (type) {
+ case ARM_ASR:
+ case ARM_LSL:
+ case ARM_LSR: type >>= 1; break;
+ default: jit_assert(!"handled shift");
+ }
+ jit_assert(v >= 0 && v <= 31);
+ return (((v & 0x1c) << 10) | ((v & 3) << 6) | type);
+}
+#endif
+
+#define thumb2_orri(o,rn,rd,im) _torri(_jitp,o,rn,rd,im)
+#define torri(o,rn,rt,im) _torri(_jitp,o,rn,rt,im)
+__jit_inline void
+_torri(jit_state_t _jitp, int o, int rn, int rd, int im)
+{
+ jit_thumb_t thumb;
+ jit_assert(!(o & 0x0c0f7fff));
+ jit_assert(!(im & 0xfbff8f00));
+ thumb.i = o|(_u4(rn)<<16)|(_u4(rd)<<8)|im;
+ _jit_WW(thumb.s[0], thumb.s[1]);
+}
+
+#define torri8(o,rn,rt,im) _torri8(_jitp,o,rn,rt,im)
+__jit_inline void
+_torri8(jit_state_t _jitp, int o, int rn, int rt, int im)
+{
+ jit_thumb_t thumb;
+ jit_assert(!(o & 0x000ff0ff));
+ jit_assert(!(im & 0xffffff00));
+ thumb.i = o|(_u4(rn)<<16)|(_u4(rt)<<12)|im;
+ _jit_WW(thumb.s[0], thumb.s[1]);
+}
+
+#define torri12(o,rn,rt,im) _torri12(_jitp,o,rn,rt,im)
+__jit_inline void
+_torri12(jit_state_t _jitp, int o, int rn, int rt, int im)
+{
+ jit_thumb_t thumb;
+ jit_assert(!(o & 0x000fffff));
+ jit_assert(!(im & 0xfffff000));
+ thumb.i = o|(_u4(rn)<<16)|(_u4(rt)<<12)|im;
+ _jit_WW(thumb.s[0], thumb.s[1]);
+}
+
+#define toriw(o,rd,im) _toriw(_jitp,o,rd,im)
+__jit_inline void
+_toriw(jit_state_t _jitp, int o, int rd, int im)
+{
+ jit_thumb_t thumb;
+ jit_assert(!(o & 0x40f7fff));
+ jit_assert(!(im & 0xffff0000));
+ thumb.i = o|((im&0xf000)<<4)|((im&0x800)<<15)|((im&0x700)<<4)|(_u4(rd)<<8)|(im&0xff);
+ _jit_WW(thumb.s[0], thumb.s[1]);
+}
+
+#define torrr(o,rn,rd,rm) _torrr(_jitp,o,rn,rd,rm)
+__jit_inline void
+_torrr(jit_state_t _jitp, int o, int rn, int rd, int rm)
+{
+ jit_thumb_t thumb;
+ jit_assert(!(o & 0xf0f0f));
+ thumb.i = o|(_u4(rn)<<16)|(_u4(rd)<<8)|_u4(rm);
+ _jit_WW(thumb.s[0], thumb.s[1]);
+}
+
+#define torrrs(o,rn,rd,rm,im) _torrrs(_jitp,o,rn,rd,rm,im)
+__jit_inline void
+_torrrs(jit_state_t _jitp, int o, int rn, int rd, int rm, int im)
+{
+ jit_thumb_t thumb;
+ jit_assert(!(o & 0x000f0f0f));
+ jit_assert(!(im & 0xffff8f0f));
+ thumb.i = o|(_u4(rn)<<16)|(_u4(rd)<<8)|im|_u4(rm);
+ _jit_WW(thumb.s[0], thumb.s[1]);
+}
+
+#define torxr(o,rn,rt,rm) _torxr(_jitp,o,rn,rt,rm)
+__jit_inline void
+_torxr(jit_state_t _jitp, int o, int rn, int rt, int rm)
+{
+ jit_thumb_t thumb;
+ jit_assert(!(o & 0xf0f0f));
+ thumb.i = o|(_u4(rn)<<16)|(_u4(rt)<<12)|_u4(rm);
+ _jit_WW(thumb.s[0], thumb.s[1]);
+}
+
+#define torrrr(o,rn,rl,rh,rm) _torrrr(_jitp,o,rn,rl,rh,rm)
+__jit_inline void
+_torrrr(jit_state_t _jitp, int o, int rn, int rl, int rh, int rm)
+{
+ jit_thumb_t thumb;
+ jit_assert(!(o & 0x000fff0f));
+ thumb.i = o|(_u4(rn)<<16)|(_u4(rl)<<12)|(_u4(rh)<<8)|_u4(rm);
+ _jit_WW(thumb.s[0], thumb.s[1]);
+}
+
+#define torrri8(o,rn,rt,rt2,im) _torrri8(_jitp,o,rn,rt,rt2,im)
+__jit_inline void
+_torrri8(jit_state_t _jitp, int o, int rn, int rt, int rt2, int im)
+{
+ jit_thumb_t thumb;
+ jit_assert(!(o & 0x000fffff));
+ jit_assert(!(im & 0xffffff00));
+ thumb.i = o|(_u4(rn)<<16)|(_u4(rt)<<12)|(_u4(rt2)<<8)|im;
+ _jit_WW(thumb.s[0], thumb.s[1]);
+}
+
+#define tc8(cc,im) _tc8(_jitp,cc,im)
+__jit_inline void
+_tc8(jit_state_t _jitp, int cc, int im)
+{
+ jit_assert(!(cc & 0x0fffffff));
+ jit_assert(cc != ARM_CC_AL && cc != ARM_CC_NV);
+ jit_assert(_s8P(im));
+ _jit_W(THUMB_CC_B|(cc>>20)|(im&0xff));
+}
+
+#define t11(im) _t11(_jitp,im)
+__jit_inline void
+_t11(jit_state_t _jitp, int im)
+{
+ jit_assert(!(im & 0xfffff800));
+ _jit_W(THUMB_B|im);
+}
+
+#define tcb(cc,im) _tcb(_jitp,cc,im)
+__jit_inline void
+_tcb(jit_state_t _jitp, int cc, int im)
+{
+ jit_thumb_t thumb;
+ jit_assert(!(cc & 0xfffffff));
+ jit_assert(cc != ARM_CC_AL && cc != ARM_CC_NV);
+ cc = ((unsigned)cc) >> 6;
+ jit_assert(!(im & (THUMB2_CC_B|cc)));
+ thumb.i = THUMB2_CC_B|cc|im;
+ _jit_WW(thumb.s[0], thumb.s[1]);
+}
+
+#define blxi(im) _blxi(_jitp,im)
+__jit_inline void
+_blxi(jit_state_t _jitp, int im)
+{
+ jit_assert(!(im & 0xfe000000));
+ _jit_I(ARM_BLXI|im);
+}
+
+#define tb(o,im) _tb(_jitp,o,im)
+__jit_inline void
+_tb(jit_state_t _jitp, int o, int im)
+{
+ jit_thumb_t thumb;
+ jit_assert(!(o & 0x07ff2fff));
+ jit_assert(!(o & im));
+ thumb.i = o|im;
+ _jit_WW(thumb.s[0], thumb.s[1]);
+}
+
+#define tshift(o,rd,rm,im) _tshift(_jitp,o,rd,rm,im)
+__jit_inline void
+_tshift(jit_state_t _jitp, int o, int rd, int rm, int im)
+{
+ jit_thumb_t thumb;
+ jit_assert(!(o & 0x7fcf));
+ jit_assert(im >= 0 && im < 32);
+ thumb.i = o|((im&0x1c)<<10)|(_u4(rd)<<8)|((im&3)<<6)|_u4(rm);
+ _jit_WW(thumb.s[0], thumb.s[1]);
+}
+
+#define thumb2_orrr(o,rn,rd,rm) _thumb2_orrr(_jitp,o,rn,rd,rm)
+__jit_inline void
+_thumb2_orrr(jit_state_t _jitp, int o, int rn, int rd, int rm)
+{
+ jit_thumb_t thumb;
+ jit_assert(!(o & 0x000f0f0f));
+ thumb.i = o | (_u4(rn)<<16) | (_u4(rd)<<8) | _u4(rm);
+ _jit_WW(thumb.s[0], thumb.s[1]);
+}
+
+#define thumb2_bfx(o,rn,rd,lsb,width) _thumb2_bfx(_jitp,o,rn,rd,lsb,width)
+__jit_inline void
+_thumb2_bfx(jit_state_t _jitp, int o, int rn, int rd, int lsb, int width)
+{
+ int msb;
+ jit_thumb_t thumb;
+ jit_assert(!(o & 0x7fdf));
+ jit_assert(lsb >= 0 && lsb < 32 && width >= 0 && width <= 32);
+ msb = lsb + width;
+ if (msb > 31)
+ msb = 31;
+ thumb.i = o | (_u4(rn) << 16) | (_u4(rd) << 8) |
+ ((msb & 7) << 10) | ((msb & 3) << 5) | msb;
+ _jit_WW(thumb.s[0], thumb.s[1]);
+}
+
+#define thumb2_cbxz(o,rn,im) _thumb2_cbxz(_jitp,o,rn,im)
+__jit_inline void
+_thumb2_cbxz(jit_state_t _jitp, int o, int rn, int im)
+{
+ jit_assert(!(o & 0x2ff));
+ /* branch forward only */
+ jit_assert(im >= 0 && im < 128 && !(im & 1));
+ im >>= 1;
+ _jit_W(o|((im&0x80)<<5)|((im&0x1f)<<3)|_u3(rn));
+}
+
+#define thumb2_dbg(h,l,im) _thumb2_dbg(_jitp,h,l,im)
+__jit_inline void
+_thumb2_dbg(jit_state_t _jitp, int h, int l, int im)
+{
+ jit_assert(!(h & ~0xffff));
+ jit_assert(!(l & 0xffff000f));
+ _jit_WW(h, l | _u4(im));
+}
+
+#define tpp(o,im) _tpp(_jitp,o,im)
+__jit_inline void
+_tpp(jit_state_t _jitp, int o, int im)
+{
+ jit_thumb_t thumb;
+ jit_assert(!(o & 0x0000ffff));
+ jit_assert(!(im & 0xffff2000));
+ if (o == THUMB2_PUSH)
+ jit_assert(!(im & 0x8000));
+ jit_assert(__builtin_popcount(im & 0x1fff) > 1);
+ thumb.i = o|im;
+ _jit_WW(thumb.s[0], thumb.s[1]);
+}
+
+#define THUMB2_IT 0
+#define THUMB2_ITT 1
+#define THUMB2_ITE 2
+#define THUMB2_ITTT 3
+#define THUMB2_ITET 4
+#define THUMB2_ITTE 5
+#define THUMB2_ITEE 6
+#define THUMB2_ITTTT 7
+#define THUMB2_ITETT 8
+#define THUMB2_ITTET 9
+#define THUMB2_ITEET 10
+#define THUMB2_ITTTE 11
+#define THUMB2_ITETE 12
+#define THUMB2_ITTEE 13
+#define THUMB2_ITEEE 14
+#define tcit(tc,it) _tcit(_jitp,tc,it)
+__jit_inline void
+_tcit(jit_state_t _jitp, unsigned int tc, int it)
+{
+ int c;
+ int m;
+ c = (tc >> 28) & 1;
+ jit_assert(!(tc & 0xfffffff) && tc != ARM_CC_NV);
+ switch (it) {
+ case THUMB2_IT: m = 1<<3; break;
+ case THUMB2_ITT: m = (c<<3)| (1<<2); break;
+ case THUMB2_ITE: m = (!c<<3)| (1<<2); break;
+ case THUMB2_ITTT: m = (c<<3)| (c<<2)| (1<<1); break;
+ case THUMB2_ITET: m = (!c<<3)| (c<<2)| (1<<1); break;
+ case THUMB2_ITTE: m = (c<<3)|(!c<<2)| (1<<1); break;
+ case THUMB2_ITEE: m = (!c<<3)|(!c<<2)| (1<<1); break;
+ case THUMB2_ITTTT: m = (c<<3)| (c<<2)| (c<<1)|1; break;
+ case THUMB2_ITETT: m = (!c<<3)| (c<<2)| (c<<1)|1; break;
+ case THUMB2_ITTET: m = (c<<3)|(!c<<2)| (c<<1)|1; break;
+ case THUMB2_ITEET: m = (!c<<3)|(!c<<2)| (c<<1)|1; break;
+ case THUMB2_ITTTE: m = (c<<3)| (c<<2)|(!c<<1)|1; break;
+ case THUMB2_ITETE: m = (!c<<3)| (c<<2)|(!c<<1)|1; break;
+ case THUMB2_ITTEE: m = (c<<3)|(!c<<2)|(!c<<1)|1; break;
+ case THUMB2_ITEEE: m = (!c<<3)|(!c<<2)|(!c<<1)|1; break;
+ default: jit_assert(!"valid it code!"); m = 0;
+ }
+ jit_assert(m && (tc != ARM_CC_AL || !(m & (m - 1))));
+ _jit_W(0xbf00 | (tc >> 24) | m);
+}
+#define _IT(cc) tcit(cc,THUMB2_IT)
+#define _ITT(cc) tcit(cc,THUMB2_ITT)
+#define _ITE(cc) tcit(cc,THUMB2_ITE)
+#define _ITTT(cc) tcit(cc,THUMB2_ITTT)
+#define _ITTE(cc) tcit(cc,THUMB2_ITTE)
+#define _ITET(cc) tcit(cc,THUMB2_ITET)
+#define _ITEE(cc) tcit(cc,THUMB2_ITEE)
+#define _ITTTT(cc) tcit(cc,THUMB2_ITTTT)
+#define _ITETT(cc) tcit(cc,THUMB2_ITETT)
+#define _ITTET(cc) tcit(cc,THUMB2_ITTET)
+#define _ITEET(cc) tcit(cc,THUMB2_ITEET)
+#define _ITTTE(cc) tcit(cc,THUMB2_ITTTE)
+#define _ITETE(cc) tcit(cc,THUMB2_ITETE)
+#define _ITTEE(cc) tcit(cc,THUMB2_ITTEE)
+#define _ITEEE(cc) tcit(cc,THUMB2_ITEEE)
+
+#define torl(o,rn,im) _torl(_jitp,o,rn,im)
+__jit_inline void
+_torl(jit_state_t _jitp, int o, int rn, int im)
+{
+ jit_thumb_t thumb;
+ jit_assert(!(o & 0xf1fff));
+ jit_assert(rn != _R15 || !im || ((o & 0xc000) == 0xc000));
+ jit_assert(!(o & THUMB2_LDM_W) || !(im & (1 << rn)));
+ thumb.i = o | (_u4(rn)<<16) | _u13(im);
+ _jit_WW(thumb.s[0], thumb.s[1]);
+}
+
+#define thumb2_mrrc(o,t2,t,cc,o1,m) _thumb2_mrrc(_jitp,o,t2,t,cc,o1,m)
+__jit_inline void
+_thumb2_mrrc(jit_state_t _jitp, int o, int t2, int t, int cc, int o1, int m)
+{
+ jit_thumb_t thumb;
+ jit_assert(!(o & 0x03afffff));
+ thumb.i = o|(_u4(t2)<<16)|(_u4(t)<<12)|(_u4(cc)<<8)|(_u4(o1)<<4)|_u4(m);
+ _jit_WW(thumb.s[0], thumb.s[1]);
+}
+
+#define thumb2_pkh(o,rn,rd,rm,im) _thumb2_pkh(_jitp,o,rn,rd,rm,im)
+__jit_inline void
+_thumb2_pkh(jit_state_t _jitp, int o, int rn, int rd, int rm, int im)
+{
+ jit_thumb_t thumb;
+ jit_assert(!(o & 0x7ffcf));
+ thumb.i = o|(_u4(rn)<<16)|((_u5(im)&0x1c)<<10)|
+ (_u4(rd)<<12)|((im&3)<<6)|_u4(rm);
+ _jit_WW(thumb.s[0], thumb.s[1]);
+}
+
+/* v6T2, v7 */
+#define THUMB2_BFX 0xf3600000
+#define T2_BFC(rd,lsb,width) thumb2_bfx(THUMB2_BFX,_R15,rd,lsb,width)
+#define T2_BFI(rd,rn,lsb,width) thumb2_bfx(THUMB2_BFX,rn,rd,lsb,width)
+/* not permitted in IT block */
+#define THUMB2_CBZ 0xb100
+#define T2_CBZ(rn,im) thumb2_cbxz(THUMB2_CBZ,rn,im)
+#define THUMB2_CBNZ 0xb900
+#define T2_CBNZ(rn,im) thumb2_cbxz(THUMB2_CBNZ,rn,im)
+/* CDP/CDP2 here - same encoding as arm, but can start at "&3 == 2 offset" */
+#define THUMB2_CLZ 0xfab0f080
+#define T2_CLZ(rd,rm) thumb2_orrr(THUMB2_CLZ,rd,rm,rm)
+
+#endif /* __lightning_asm_h */
diff --git a/src/racket/src/lightning/arm/core-common.h b/src/racket/src/lightning/arm/core-common.h
new file mode 100644
index 0000000000..cfa89aba63
--- /dev/null
+++ b/src/racket/src/lightning/arm/core-common.h
@@ -0,0 +1,695 @@
+/******************************** -*- C -*- ****************************
+ *
+ * Platform-independent layer support
+ *
+ ***********************************************************************/
+
+
+/***********************************************************************
+ *
+ * Copyright 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ * Written by Paolo Bonzini.
+ *
+ * This file is part of GNU lightning.
+ *
+ * GNU lightning 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU lightning 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 GNU lightning; see the file COPYING.LESSER; if not, write to the
+ * Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ ***********************************************************************/
+
+#ifndef __lightning_core_common_h
+#define __lightning_core_common_h_
+
+#define JIT_NOREG (-1)
+
+#define jit_get_raw_ip() _jitp->x.pc
+#define jit_get_ip() jit_adjust_ip(_jitp->x.pc)
+#define jit_set_ip(ptr) (_jitp->x.pc = (ptr), jit_get_ip ())
+#define jit_get_label() jit_get_ip()
+#define jit_forward() jit_get_ip()
+
+#define jit_adjust_ip(x) ((jit_insn *)(((char *)(x)) + jit_cpu.thumb))
+#define jit_unadjust_ip(x) ((jit_insn *)(((char *)(x)) - jit_cpu.thumb))
+
+#define jit_field(struc, f) ( ((long) (&((struc *) 8)->f) ) - 8)
+#define jit_ptr_field(struc_p, f) ( ((long) (&((struc_p) 8)->f) ) - 8)
+
+/* realignment via N-byte no-ops */
+
+#ifndef jit_align
+#define jit_align(n)
+#endif
+
+/* jit_code: union of many possible function pointer types. Returned
+ * by jit_get_ip().
+ */
+typedef union jit_code {
+ char *ptr;
+ void (*vptr)(void);
+ char (*cptr)(void);
+ unsigned char (*ucptr)(void);
+ short (*sptr)(void);
+ unsigned short (*usptr)(void);
+ int (*iptr)(void);
+ unsigned int (*uiptr)(void);
+ long (*lptr)(void);
+ unsigned long (*ulptr)(void);
+ void * (*pptr)(void);
+ float (*fptr)(void);
+ double (*dptr)(void);
+} jit_code;
+
+#ifndef jit_fill_delay_after
+#define jit_fill_delay_after(branch) (branch)
+#endif
+
+#define jit_delay(insn, branch) ((insn), jit_fill_delay_after(branch))
+
+
+/* ALU synonyms */
+#if !defined(jit_addci_ui)
+# if !defined(jit_addci_i)
+ /* need add/sub that sets carry for all operands */
+# if _ASM_SAFETY
+# warning Assuming jit_{add,sub}{r,i}_{i,ui} always sets carry
+# endif
+# define jit_addci_ui(d, rs, is) jit_addi_ui((d), (rs), (is))
+# define jit_addcr_ui(d, s1, s2) jit_addr_ui((d), (s1), (s2))
+# define jit_subci_ui(d, rs, is) jit_subi_ui((d), (rs), (is))
+# define jit_subcr_ui(d, s1, s2) jit_subr_ui((d), (s1), (s2))
+# elif defined(jit_addci_i)
+ /* allow logically reversed definitions */
+# define jit_addci_ui(d, rs, is) jit_addci_i((d), (rs), (is))
+# define jit_addcr_ui(d, s1, s2) jit_addcr_i((d), (s1), (s2))
+# define jit_subci_ui(d, rs, is) jit_subci_i((d), (rs), (is))
+# define jit_subcr_ui(d, s1, s2) jit_subcr_i((d), (s1), (s2))
+# endif
+#endif
+#if !defined(jit_addci_i) && defined(jit_addci_ui)
+ /* provide compatibility logically wrong definitions */
+# define jit_addci_i(d, rs, is) jit_addci_ui((d), (rs), (is))
+# define jit_addcr_i(d, s1, s2) jit_addcr_ui((d), (s1), (s2))
+# define jit_subci_i(d, rs, is) jit_subci_ui((d), (rs), (is))
+# define jit_subcr_i(d, s1, s2) jit_subcr_ui((d), (s1), (s2))
+#endif
+#if !defined(jit_addxi_ui) && defined(jit_addxi_i)
+ /* allow logically reversed definitions */
+# define jit_addxi_ui(d, rs, is) jit_addxi_i((d), (rs), (is))
+# define jit_addxr_ui(d, s1, s2) jit_addxr_i((d), (s1), (s2))
+# define jit_subxi_ui(d, rs, is) jit_subxi_i((d), (rs), (is))
+# define jit_subxr_ui(d, s1, s2) jit_subxr_i((d), (s1), (s2))
+#endif
+#if !defined(jit_addxi_i) && defined(jit_addxi_ui)
+ /* provide compatibility logically wrong definitions */
+# define jit_addxi_i(d, rs, is) jit_addxi_ui((d), (rs), (is))
+# define jit_addxr_i(d, s1, s2) jit_addxr_ui((d), (s1), (s2))
+# define jit_subxi_i(d, rs, is) jit_subxi_ui((d), (rs), (is))
+# define jit_subxr_i(d, s1, s2) jit_subxr_ui((d), (s1), (s2))
+#endif
+
+#define jit_addi_ui(d, rs, is) jit_addi_i((d), (rs), (is))
+#define jit_addr_ui(d, s1, s2) jit_addr_i((d), (s1), (s2))
+#define jit_andi_ui(d, rs, is) jit_andi_i((d), (rs), (is))
+#define jit_andr_ui(d, s1, s2) jit_andr_i((d), (s1), (s2))
+#define jit_lshi_ui(d, rs, is) jit_lshi_i((d), (rs), (is))
+#define jit_lshr_ui(d, s1, s2) jit_lshr_i((d), (s1), (s2))
+#ifndef jit_movi_ui
+# define jit_movi_ui(d, rs) jit_movi_i((d), (rs))
+#endif
+#define jit_movr_ui(d, rs) jit_movr_i((d), (rs))
+#define jit_ori_ui(d, rs, is) jit_ori_i((d), (rs), (is))
+#define jit_orr_ui(d, s1, s2) jit_orr_i((d), (s1), (s2))
+#define jit_rsbi_ui(d, rs, is) jit_rsbi_i((d), (rs), (is))
+#define jit_rsbr_ui(d, s1, s2) jit_rsbr_i((d), (s1), (s2))
+#define jit_subi_ui(d, rs, is) jit_subi_i((d), (rs), (is))
+#define jit_subr_ui(d, s1, s2) jit_subr_i((d), (s1), (s2))
+#define jit_xori_ui(d, rs, is) jit_xori_i((d), (rs), (is))
+#define jit_xorr_ui(d, s1, s2) jit_xorr_i((d), (s1), (s2))
+
+#if __WORDSIZE == 32
+ /* common definitions when sizeof(long) == sizeof(int) */
+# if !defined(jit_addci_ul) && defined(jit_addci_ui)
+# define jit_addci_ul(d, rs, is) jit_addci_ui((d), (rs), (is))
+# define jit_addcr_ul(d, s1, s2) jit_addcr_ui((d), (s1), (s2))
+# define jit_subci_ul(d, rs, is) jit_subci_ui((d), (rs), (is))
+# define jit_subcr_ul(d, s1, s2) jit_subcr_ui((d), (s1), (s2))
+# endif
+# if !defined(jit_addxi_ul) && defined(jit_addxi_ui)
+# define jit_addxi_ul(d, rs, is) jit_addxi_ui((d), (rs), (is))
+# define jit_addxr_ul(d, s1, s2) jit_addxr_ui((d), (s1), (s2))
+# define jit_subxi_ul(d, rs, is) jit_subxi_ui((d), (rs), (is))
+# define jit_subxr_ul(d, s1, s2) jit_subxr_ui((d), (s1), (s2))
+# endif
+#endif
+#if !defined(jit_addci_ul)
+# if !defined(jit_addci_l)
+ /* need add/sub that sets carry for all operands */
+# if _ASM_SAFETY
+# warning Assuming jit_{add,sub}{r,i}_{l,ul} always sets carry
+# endif
+# define jit_addci_ul(d, rs, is) jit_addi_ul((d), (rs), (is))
+# define jit_addcr_ul(d, s1, s2) jit_addr_ul((d), (s1), (s2))
+# define jit_subci_ul(d, rs, is) jit_subi_ul((d), (rs), (is))
+# define jit_subcr_ul(d, s1, s2) jit_subr_ul((d), (s1), (s2))
+# elif defined(jit_addci_l)
+ /* allow logically reversed definitions */
+# define jit_addci_ul(d, rs, is) jit_addci_l((d), (rs), (is))
+# define jit_addcr_ul(d, s1, s2) jit_addcr_l((d), (s1), (s2))
+# define jit_subci_ul(d, rs, is) jit_subci_l((d), (rs), (is))
+# define jit_subcr_ul(d, s1, s2) jit_subcr_l((d), (s1), (s2))
+# endif
+#endif
+#if !defined(jit_addci_l) && defined(jit_addci_ul)
+ /* provide compatibility logically wrong definitions */
+# define jit_addci_l(d, rs, is) jit_addci_ul((d), (rs), (is))
+# define jit_addcr_l(d, s1, s2) jit_addcr_ul((d), (s1), (s2))
+# define jit_subci_l(d, rs, is) jit_subci_ul((d), (rs), (is))
+# define jit_subcr_l(d, s1, s2) jit_subcr_ul((d), (s1), (s2))
+#endif
+#if !defined(jit_addxi_ul) && defined(jit_addxi_l)
+ /* allow logically reversed definitions */
+# define jit_addxi_ul(d, rs, is) jit_addxi_l((d), (rs), (is))
+# define jit_addxr_ul(d, s1, s2) jit_addxr_l((d), (s1), (s2))
+# define jit_subxi_ul(d, rs, is) jit_subxi_l((d), (rs), (is))
+# define jit_subxr_ul(d, s1, s2) jit_subxr_l((d), (s1), (s2))
+#endif
+#if !defined(jit_addxi_l) && defined(jit_addxi_ul)
+ /* provide compatibility logically wrong definitions */
+# define jit_addxi_l(d, rs, is) jit_addxi_ul((d), (rs), (is))
+# define jit_addxr_l(d, s1, s2) jit_addxr_ul((d), (s1), (s2))
+# define jit_subxi_l(d, rs, is) jit_subxi_ul((d), (rs), (is))
+# define jit_subxr_l(d, s1, s2) jit_subxr_ul((d), (s1), (s2))
+#endif
+#define jit_addi_ul(d, rs, is) jit_addi_l((d), (rs), (is))
+#define jit_addr_ul(d, s1, s2) jit_addr_l((d), (s1), (s2))
+#define jit_andi_ul(d, rs, is) jit_andi_l((d), (rs), (is))
+#define jit_andr_ul(d, s1, s2) jit_andr_l((d), (s1), (s2))
+#define jit_lshi_ul(d, rs, is) jit_lshi_l((d), (rs), (is))
+#define jit_lshr_ul(d, s1, s2) jit_lshr_l((d), (s1), (s2))
+#ifndef jit_movi_ul
+# define jit_movi_ul(d, rs) jit_movi_l((d), (rs))
+#endif
+#ifndef jit_movr_ul
+# define jit_movr_ul(d, rs) jit_movr_l((d), (rs))
+#endif
+#define jit_ori_ul(d, rs, is) jit_ori_l((d), (rs), (is))
+#define jit_orr_ul(d, s1, s2) jit_orr_l((d), (s1), (s2))
+#define jit_rsbi_ul(d, rs, is) jit_rsbi_l((d), (rs), (is))
+#define jit_rsbr_ul(d, s1, s2) jit_rsbr_l((d), (s1), (s2))
+#define jit_subi_ul(d, rs, is) jit_subi_l((d), (rs), (is))
+#define jit_subr_ul(d, s1, s2) jit_subr_l((d), (s1), (s2))
+#define jit_xori_ul(d, rs, is) jit_xori_l((d), (rs), (is))
+#define jit_xorr_ul(d, s1, s2) jit_xorr_l((d), (s1), (s2))
+#define jit_addr_p(d, s1, s2) jit_addr_ul((d), (s1), (s2))
+#define jit_addi_p(d, rs, is) jit_addi_ul((d), (rs), (long) (is))
+#ifndef jit_movr_p
+# define jit_movr_p(d, rs) jit_movr_ul((d), (rs))
+#endif
+#define jit_subr_p(d, s1, s2) jit_subr_ul((d), (s1), (s2))
+#define jit_subi_p(d, rs, is) jit_subi_ul((d), (rs), (long) (is))
+#define jit_rsbi_p(d, rs, is) jit_rsbi_ul((d), (rs), (long) (is))
+
+#ifndef jit_movi_p
+#define jit_movi_p(d, is) (jit_movi_ul((d), (long) (is)), jit_get_ip())
+#endif
+
+#define jit_patch(pv) jit_patch_at ((pv), jit_get_ip())
+
+/* NEG is not mandatory -- pick an appropriate implementation */
+#ifndef jit_negr_i
+# ifdef JIT_RZERO
+# define jit_negr_i(d, rs) jit_subr_i((d), JIT_RZERO, (rs))
+# if __WORDSIZE == 64
+# define jit_negr_l(d, rs) jit_subr_l((d), JIT_RZERO, (rs))
+# endif
+# else /* !JIT_RZERO */
+# ifndef jit_rsbi_i
+# define jit_negr_i(d, rs) (jit_xori_i((d), (rs), -1), jit_addi_l((d), (d), 1))
+# define jit_negr_l(d, rs) (jit_xori_l((d), (rs), -1), jit_addi_l((d), (d), 1))
+# else /* jit_rsbi_i */
+# define jit_negr_i(d, rs) jit_rsbi_i((d), (rs), 0)
+# define jit_negr_l(d, rs) jit_rsbi_l((d), (rs), 0)
+# endif /* jit_rsbi_i */
+# endif /* !JIT_RZERO */
+#endif /* !jit_negr_i */
+
+/* Common 'shortcut' implementations */
+#ifndef jit_subi_i
+# define jit_subi_i(d, rs, is) jit_addi_i((d), (rs), -(is))
+#endif
+#ifndef jit_subi_l
+# define jit_subi_l(d, rs, is) jit_subi_i((d), (rs), (is))
+#endif
+#define jit_rsbr_f(d, s1, s2) jit_subr_f((d), (s2), (s1))
+#define jit_rsbr_d(d, s1, s2) jit_subr_d((d), (s2), (s1))
+#ifndef jit_rsbr_i
+# define jit_rsbr_i(d, s1, s2) jit_subr_i((d), (s2), (s1))
+#endif
+#define jit_rsbr_l(d, s1, s2) jit_subr_l((d), (s2), (s1))
+#define jit_rsbr_p(d, s1, s2) jit_subr_p((d), (s2), (s1))
+
+/* Unary */
+#ifndef jit_notr_i
+# define jit_notr_i(d, rs) jit_xori_i((d), (rs), ~0)
+#endif
+#ifndef jit_notr_l
+# define jit_notr_l(d, rs) jit_xori_l((d), (rs), ~0L)
+#endif
+#ifndef jit_notr_c
+# define jit_notr_c(d, rs) jit_notr_i((d), (rs))
+# define jit_notr_uc(d, rs) jit_notr_i((d), (rs))
+# define jit_notr_s(d, rs) jit_notr_i((d), (rs))
+# define jit_notr_us(d, rs) jit_notr_i((d), (rs))
+#endif
+#ifndef jit_notr_ui
+# define jit_notr_ui(d, rs) jit_notr_i((d), (rs))
+#endif
+#ifndef jit_notr_ul
+# define jit_notr_ul(d, rs) jit_notr_l((d), (rs))
+#endif
+
+#ifndef jit_extr_c_ui
+# define jit_extr_c_ui(d, rs) jit_andi_ui((d), (rs), 0xFF)
+#endif
+#ifndef jit_extr_s_ui
+# define jit_extr_s_ui(d, rs) jit_andi_ui((d), (rs), 0xFFFF)
+#endif
+#ifndef jit_extr_c_i
+# define jit_extr_c_i(d, rs) (jit_lshi_i((d), (rs), 24), jit_rshi_i((d), (d), 24))
+#endif
+#ifndef jit_extr_s_i
+# define jit_extr_s_i(d, rs) (jit_lshi_i((d), (rs), 16), jit_rshi_i((d), (d), 16))
+#endif
+
+#if __WORDSIZE == 64
+# ifndef jit_extr_c_l
+# define jit_extr_c_l(d, rs) (jit_lshi_l((d), (rs), 56), jit_rshi_l((d), (d), 56))
+# endif
+# ifndef jit_extr_s_l
+# define jit_extr_s_l(d, rs) (jit_lshi_l((d), (rs), 48), jit_rshi_l((d), (d), 48))
+# endif
+# ifndef jit_extr_i_l
+# define jit_extr_i_l(d, rs) (jit_lshi_l((d), (rs), 32), jit_rshi_l((d), (d), 32))
+# endif
+# ifndef jit_extr_c_ul
+# define jit_extr_c_ul(d, rs) jit_andi_l((d), (rs), 0xFF)
+# endif
+# ifndef jit_extr_s_ul
+# define jit_extr_s_ul(d, rs) jit_andi_l((d), (rs), 0xFFFF)
+# endif
+# ifndef jit_extr_i_ul
+# define jit_extr_i_ul(d, rs) jit_andi_l((d), (rs), 0xFFFFFFFFUL)
+# endif
+#endif /* __WORDSIZE == 64 */
+
+#define jit_extr_c_s(d, rs) jit_extr_c_i((d), (rs))
+#define jit_extr_c_us(d, rs) jit_extr_c_ui((d), (rs))
+#define jit_extr_uc_s(d, rs) jit_extr_uc_i((d), (rs))
+#define jit_extr_uc_us(d, rs) jit_extr_uc_ui((d), (rs))
+#define jit_extr_uc_i(d, rs) jit_extr_c_ui((d), (rs))
+#define jit_extr_uc_ui(d, rs) jit_extr_c_ui((d), (rs))
+#define jit_extr_us_i(d, rs) jit_extr_s_ui((d), (rs))
+#define jit_extr_us_ui(d, rs) jit_extr_s_ui((d), (rs))
+#define jit_extr_uc_l(d, rs) jit_extr_c_ul((d), (rs))
+#define jit_extr_uc_ul(d, rs) jit_extr_c_ul((d), (rs))
+#define jit_extr_us_l(d, rs) jit_extr_s_ul((d), (rs))
+#define jit_extr_us_ul(d, rs) jit_extr_s_ul((d), (rs))
+#define jit_extr_ui_l(d, rs) jit_extr_i_ul((d), (rs))
+#define jit_extr_ui_ul(d, rs) jit_extr_i_ul((d), (rs))
+
+
+/* NTOH/HTON is not mandatory for big endian architectures */
+#ifndef jit_ntoh_ui /* big endian */
+#define jit_ntoh_ui(d, rs) ((d) == (rs) ? (void)0 : jit_movr_i((d), (rs)))
+#define jit_ntoh_us(d, rs) ((d) == (rs) ? (void)0 : jit_movr_i((d), (rs)))
+#endif /* big endian */
+
+/* hton is a synonym for ntoh */
+#define jit_hton_ui(d, rs) jit_ntoh_ui((d), (rs))
+#define jit_hton_us(d, rs) jit_ntoh_us((d), (rs))
+
+/* Stack synonyms */
+#define jit_pushr_ui(rs) jit_pushr_i(rs)
+#define jit_popr_ui(rs) jit_popr_i(rs)
+#define jit_pushr_ul(rs) jit_pushr_l(rs)
+#define jit_popr_ul(rs) jit_popr_l(rs)
+#define jit_pushr_p(rs) jit_pushr_ul(rs)
+#define jit_popr_p(rs) jit_popr_ul(rs)
+
+#define jit_prepare(nint) jit_prepare_i((nint))
+#define jit_pusharg_c(rs) jit_pusharg_i(rs)
+#define jit_pusharg_s(rs) jit_pusharg_i(rs)
+#define jit_pusharg_uc(rs) jit_pusharg_i(rs)
+#define jit_pusharg_us(rs) jit_pusharg_i(rs)
+#define jit_pusharg_ui(rs) jit_pusharg_i(rs)
+#define jit_pusharg_ul(rs) jit_pusharg_l(rs)
+#define jit_pusharg_p(rs) jit_pusharg_ul(rs)
+
+#define jit_normal_pushonlyarg_p(r0) jit_normal_pushonlyarg_i(r0)
+
+/* Memory synonyms */
+
+#ifdef JIT_RZERO
+#ifndef jit_ldi_c
+#define jit_ldi_c(rd, is) jit_ldxi_c((rd), JIT_RZERO, (is))
+#define jit_sti_c(id, rs) jit_stxi_c((id), JIT_RZERO, (rs))
+#define jit_ldi_s(rd, is) jit_ldxi_s((rd), JIT_RZERO, (is))
+#define jit_sti_s(id, rs) jit_stxi_s((id), JIT_RZERO, (rs))
+#define jit_ldi_i(rd, is) jit_ldxi_i((rd), JIT_RZERO, (is))
+#define jit_sti_i(id, rs) jit_stxi_i((id), JIT_RZERO, (rs))
+#define jit_ldi_l(rd, is) jit_ldxi_l((rd), JIT_RZERO, (is))
+#define jit_sti_l(id, rs) jit_stxi_l((id), JIT_RZERO, (rs))
+#define jit_ldi_uc(rd, is) jit_ldxi_uc((rd), JIT_RZERO, (is))
+#define jit_ldi_us(rd, is) jit_ldxi_us((rd), JIT_RZERO, (is))
+#define jit_ldi_ui(rd, is) jit_ldxi_ui((rd), JIT_RZERO, (is))
+# if __WORDSIZE == 64
+# define jit_ldi_ul(rd, is) jit_ldxi_ul((rd), JIT_RZERO, (is))
+# endif
+#endif
+
+#ifndef jit_ldr_c
+#define jit_ldr_c(rd, rs) jit_ldxr_c((rd), JIT_RZERO, (rs))
+#define jit_str_c(rd, rs) jit_stxr_c(JIT_RZERO, (rd), (rs))
+#define jit_ldr_s(rd, rs) jit_ldxr_s((rd), JIT_RZERO, (rs))
+#define jit_str_s(rd, rs) jit_stxr_s(JIT_RZERO, (rd), (rs))
+#define jit_ldr_i(rd, rs) jit_ldxr_i((rd), JIT_RZERO, (rs))
+#define jit_str_i(rd, rs) jit_stxr_i(JIT_RZERO, (rd), (rs))
+#define jit_ldr_l(rd, rs) jit_ldxr_l((rd), JIT_RZERO, (rs))
+#define jit_str_l(rd, rs) jit_stxr_l(JIT_RZERO, (rd), (rs))
+#define jit_ldr_uc(rd, rs) jit_ldxr_uc((rd), JIT_RZERO, (rs))
+#define jit_ldr_us(rd, rs) jit_ldxr_us((rd), JIT_RZERO, (rs))
+#define jit_ldr_ui(rd, rs) jit_ldxr_ui((rd), JIT_RZERO, (rs))
+# if __WORDSIZE == 64
+# define jit_ldr_ul(rd, rs) jit_ldxr_ul((rd), JIT_RZERO, (rs))
+# endif
+#endif
+#endif
+
+#define jit_str_uc(rd, rs) jit_str_c((rd), (rs))
+#define jit_sti_uc(id, rs) jit_sti_c((id), (rs))
+#define jit_stxr_uc(d1, d2, rs) jit_stxr_c((d1), (d2), (rs))
+#define jit_stxi_uc(id, rd, is) jit_stxi_c((id), (rd), (is))
+
+#define jit_str_us(rd, rs) jit_str_s((rd), (rs))
+#define jit_sti_us(id, rs) jit_sti_s((id), (rs))
+#define jit_stxr_us(d1, d2, rs) jit_stxr_s((d1), (d2), (rs))
+#define jit_stxi_us(id, rd, is) jit_stxi_s((id), (rd), (is))
+
+#define jit_str_ui(rd, rs) jit_str_i((rd), (rs))
+#define jit_sti_ui(id, rs) jit_sti_i((id), (rs))
+#define jit_stxr_ui(d1, d2, rs) jit_stxr_i((d1), (d2), (rs))
+#define jit_stxi_ui(id, rd, is) jit_stxi_i((id), (rd), (is))
+
+#define jit_str_ul(rd, rs) jit_str_l((rd), (rs))
+#define jit_sti_ul(id, rs) jit_sti_l((id), (rs))
+#define jit_stxr_ul(d1, d2, rs) jit_stxr_l((d1), (d2), (rs))
+#define jit_stxi_ul(id, rd, is) jit_stxi_l((id), (rd), (is))
+
+#define jit_str_p(rd, rs) jit_str_l((rd), (rs))
+#define jit_sti_p(id, rs) jit_sti_l((id), (rs))
+#define jit_stxr_p(d1, d2, rs) jit_stxr_l((d1), (d2), (rs))
+#define jit_stxi_p(id, rd, is) jit_stxi_l((id), (rd), (is))
+
+#define jit_ldr_p(rd, rs) jit_ldr_l((rd), (rs))
+#define jit_ldi_p(rd, is) jit_ldi_l((rd), (is))
+#define jit_ldxr_p(rd, s1, s2) jit_ldxr_l((rd), (s1), (s2))
+#ifndef jit_ldxi_p
+# define jit_ldxi_p(rd, rs, is) jit_ldxi_l((rd), (rs), (is))
+#endif
+
+#define jit_ldr_ul(d, rs) jit_ldr_l((d), (rs))
+#define jit_ldi_ul(d, is) jit_ldi_l((d), (is))
+#define jit_ldxr_ul(d, s1, s2) jit_ldxr_l((d), (s1), (s2))
+#ifndef jit_ldxi_ul
+# define jit_ldxi_ul(d, rs, is) jit_ldxi_l((d), (rs), (is))
+#endif
+
+
+/* Boolean & branch synonyms */
+#define jit_eqr_ui(d, s1, s2) jit_eqr_i((d), (s1), (s2))
+#define jit_eqi_ui(d, rs, is) jit_eqi_i((d), (rs), (is))
+#define jit_ner_ui(d, s1, s2) jit_ner_i((d), (s1), (s2))
+#define jit_nei_ui(d, rs, is) jit_nei_i((d), (rs), (is))
+
+#define jit_eqr_ul(d, s1, s2) jit_eqr_l((d), (s1), (s2))
+#define jit_eqi_ul(d, rs, is) jit_eqi_l((d), (rs), (is))
+#define jit_ner_ul(d, s1, s2) jit_ner_l((d), (s1), (s2))
+#define jit_nei_ul(d, rs, is) jit_nei_l((d), (rs), (is))
+
+#define jit_beqr_ui(label, s1, s2) jit_beqr_i((label), (s1), (s2))
+#define jit_beqi_ui(label, rs, is) jit_beqi_i((label), (rs), (is))
+#define jit_bner_ui(label, s1, s2) jit_bner_i((label), (s1), (s2))
+#define jit_bnei_ui(label, rs, is) jit_bnei_i((label), (rs), (is))
+#define jit_bmcr_ui(label, s1, s2) jit_bmcr_i((label), (s1), (s2))
+#define jit_bmci_ui(label, rs, is) jit_bmci_i((label), (rs), (is))
+#define jit_bmsr_ui(label, s1, s2) jit_bmsr_i((label), (s1), (s2))
+#define jit_bmsi_ui(label, rs, is) jit_bmsi_i((label), (rs), (is))
+
+#define jit_beqr_ul(label, s1, s2) jit_beqr_l((label), (s1), (s2))
+#define jit_beqi_ul(label, rs, is) jit_beqi_l((label), (rs), (is))
+#define jit_bner_ul(label, s1, s2) jit_bner_l((label), (s1), (s2))
+#define jit_bnei_ul(label, rs, is) jit_bnei_l((label), (rs), (is))
+#define jit_bmcr_ul(label, s1, s2) jit_bmcr_l((label), (s1), (s2))
+#define jit_bmci_ul(label, rs, is) jit_bmci_l((label), (rs), (is))
+#define jit_bmsr_ul(label, s1, s2) jit_bmsr_l((label), (s1), (s2))
+#define jit_bmsi_ul(label, rs, is) jit_bmsi_l((label), (rs), (is))
+
+#define jit_ltr_p(d, s1, s2) jit_ltr_ul((d), (s1), (s2))
+#define jit_lti_p(d, rs, is) jit_lti_ul((d), (rs), (long)(is))
+#define jit_ler_p(d, s1, s2) jit_ler_ul((d), (s1), (s2))
+#define jit_lei_p(d, rs, is) jit_lei_ul((d), (rs), (long)(is))
+#define jit_gtr_p(d, s1, s2) jit_gtr_ul((d), (s1), (s2))
+#define jit_gti_p(d, rs, is) jit_gti_ul((d), (rs), (long)(is))
+#define jit_ger_p(d, s1, s2) jit_ger_ul((d), (s1), (s2))
+#define jit_gei_p(d, rs, is) jit_gei_ul((d), (rs), (long)(is))
+#define jit_eqr_p(d, s1, s2) jit_eqr_ul((d), (s1), (s2))
+#define jit_eqi_p(d, rs, is) jit_eqi_ul((d), (rs), (long)(is))
+#define jit_ner_p(d, s1, s2) jit_ner_ul((d), (s1), (s2))
+#define jit_nei_p(d, rs, is) jit_nei_ul((d), (rs), (long)(is))
+
+#define jit_bltr_p(label, s1, s2) jit_bltr_ul((label), (s1), (s2))
+#define jit_blti_p(label, rs, is) jit_blti_ul((label), (rs), (long)(is))
+#define jit_bler_p(label, s1, s2) jit_bler_ul((label), (s1), (s2))
+#define jit_blei_p(label, rs, is) jit_blei_ul((label), (rs), (long)(is))
+#define jit_bgtr_p(label, s1, s2) jit_bgtr_ul((label), (s1), (s2))
+#define jit_bgti_p(label, rs, is) jit_bgti_ul((label), (rs), (long)(is))
+#define jit_bger_p(label, s1, s2) jit_bger_ul((label), (s1), (s2))
+#define jit_bgei_p(label, rs, is) jit_bgei_ul((label), (rs), (long)(is))
+#define jit_beqr_p(label, s1, s2) jit_beqr_ul((label), (s1), (s2))
+#define jit_beqi_p(label, rs, is) jit_beqi_ul((label), (rs), (long)(is))
+#define jit_bner_p(label, s1, s2) jit_bner_ul((label), (s1), (s2))
+#define jit_bnei_p(label, rs, is) jit_bnei_ul((label), (rs), (long)(is))
+
+#define jit_retval_ui(rd) jit_retval_i((rd))
+#define jit_retval_uc(rd) jit_retval_i((rd))
+#define jit_retval_us(rd) jit_retval_i((rd))
+#define jit_retval_ul(rd) jit_retval_l((rd))
+#define jit_retval_p(rd) jit_retval_ul((rd))
+#define jit_retval_c(rd) jit_retval_i((rd))
+#define jit_retval_s(rd) jit_retval_i((rd))
+
+/* This was a bug, but we keep it. */
+#define jit_retval(rd) jit_retval_i ((rd))
+
+#ifndef jit_finish
+#define jit_finish(sub) jit_calli(sub)
+#endif
+
+#ifndef jit_finishr
+#define jit_finishr(reg) jit_callr(reg)
+#endif
+
+#ifndef jit_prolog
+#define jit_prolog(numargs)
+#endif
+
+#ifndef jit_leaf
+#define jit_leaf(numargs) jit_prolog(numargs)
+#endif
+
+#ifndef jit_getarg_c
+#ifndef JIT_AP
+#define jit_getarg_c(reg, ofs) jit_extr_c_l ((reg), (ofs))
+#define jit_getarg_i(reg, ofs) jit_extr_i_l ((reg), (ofs))
+#define jit_getarg_l(reg, ofs) jit_movr_l ((reg), (ofs))
+#define jit_getarg_p(reg, ofs) jit_movr_p ((reg), (ofs))
+#define jit_getarg_s(reg, ofs) jit_extr_s_l ((reg), (ofs))
+#define jit_getarg_uc(reg, ofs) jit_extr_uc_ul((reg), (ofs))
+#define jit_getarg_ui(reg, ofs) jit_extr_ui_ul((reg), (ofs))
+#define jit_getarg_ul(reg, ofs) jit_movr_ul ((reg), (ofs))
+#define jit_getarg_us(reg, ofs) jit_extr_us_ul((reg), (ofs))
+#else
+#define jit_getarg_c(reg, ofs) jit_ldxi_c((reg), JIT_AP, (ofs));
+#define jit_getarg_uc(reg, ofs) jit_ldxi_uc((reg), JIT_AP, (ofs));
+#define jit_getarg_s(reg, ofs) jit_ldxi_s((reg), JIT_AP, (ofs));
+#define jit_getarg_us(reg, ofs) jit_ldxi_us((reg), JIT_AP, (ofs));
+#define jit_getarg_i(reg, ofs) jit_ldxi_i((reg), JIT_AP, (ofs));
+#define jit_getarg_ui(reg, ofs) jit_ldxi_ui((reg), JIT_AP, (ofs));
+#define jit_getarg_l(reg, ofs) jit_ldxi_l((reg), JIT_AP, (ofs));
+#define jit_getarg_ul(reg, ofs) jit_ldxi_ul((reg), JIT_AP, (ofs));
+#define jit_getarg_p(reg, ofs) jit_ldxi_p((reg), JIT_AP, (ofs));
+#endif
+#endif
+
+
+/* Common definitions when sizeof(long) = sizeof(int) */
+#if __WORDSIZE == 32
+/* ALU */
+# define jit_addi_l(d, rs, is) jit_addi_i((d), (rs), (is))
+# define jit_addr_l(d, s1, s2) jit_addr_i((d), (s1), (s2))
+# define jit_andi_l(d, rs, is) jit_andi_i((d), (rs), (is))
+# define jit_andr_l(d, s1, s2) jit_andr_i((d), (s1), (s2))
+# define jit_divi_l(d, rs, is) jit_divi_i((d), (rs), (is))
+# define jit_divr_l(d, s1, s2) jit_divr_i((d), (s1), (s2))
+# define jit_hmuli_l(d, rs, is) jit_hmuli_i((d), (rs), (is))
+# define jit_hmulr_l(d, s1, s2) jit_hmulr_i((d), (s1), (s2))
+# define jit_lshi_l(d, rs, is) jit_lshi_i((d), (rs), (is))
+# define jit_lshr_l(d, s1, s2) jit_lshr_i((d), (s1), (s2))
+# define jit_modi_l(d, rs, is) jit_modi_i((d), (rs), (is))
+# define jit_modr_l(d, s1, s2) jit_modr_i((d), (s1), (s2))
+# define jit_muli_l(d, rs, is) jit_muli_i((d), (rs), (is))
+# define jit_mulr_l(d, s1, s2) jit_mulr_i((d), (s1), (s2))
+# ifndef jit_negr_l
+# define jit_negr_l(d, s1) jit_negr_i((d), (s1))
+# endif
+# define jit_ori_l(d, rs, is) jit_ori_i((d), (rs), (is))
+# define jit_orr_l(d, s1, s2) jit_orr_i((d), (s1), (s2))
+# define jit_rshi_l(d, rs, is) jit_rshi_i((d), (rs), (is))
+# define jit_rshr_l(d, s1, s2) jit_rshr_i((d), (s1), (s2))
+# define jit_subr_l(d, s1, s2) jit_subr_i((d), (s1), (s2))
+# define jit_xori_l(d, rs, is) jit_xori_i((d), (rs), (is))
+# define jit_xorr_l(d, s1, s2) jit_xorr_i((d), (s1), (s2))
+# define jit_rsbi_l(d, rs, is) jit_rsbi_i((d), (rs), (is))
+# define jit_divi_ul(d, rs, is) jit_divi_ui((d), (rs), (is))
+# define jit_divr_ul(d, s1, s2) jit_divr_ui((d), (s1), (s2))
+# define jit_hmuli_ul(d, rs, is) jit_hmuli_ui((d), (rs), (is))
+# define jit_hmulr_ul(d, s1, s2) jit_hmulr_ui((d), (s1), (s2))
+# define jit_modi_ul(d, rs, is) jit_modi_ui((d), (rs), (is))
+# define jit_modr_ul(d, s1, s2) jit_modr_ui((d), (s1), (s2))
+# define jit_muli_ul(d, rs, is) jit_muli_ui((d), (rs), (is))
+# define jit_mulr_ul(d, s1, s2) jit_mulr_ui((d), (s1), (s2))
+# define jit_rshi_ul(d, rs, is) jit_rshi_ui((d), (rs), (is))
+# define jit_rshr_ul(d, s1, s2) jit_rshr_ui((d), (s1), (s2))
+
+# define jit_bomulr_l(d, s1, s2) jit_bomulr_i((d), (s1), (s2))
+
+/* Sign/Zero extension */
+# define jit_extr_c_l(d, rs) jit_extr_c_i(d, rs)
+# define jit_extr_c_ul(d, rs) jit_extr_c_ui(d, rs)
+# define jit_extr_s_l(d, rs) jit_extr_s_i(d, rs)
+# define jit_extr_s_ul(d, rs) jit_extr_s_ui(d, rs)
+# define jit_extr_i_l(d, rs) jit_movr_i(d, rs)
+# define jit_extr_i_ul(d, rs) jit_movr_i(d, rs)
+
+/* Unary */
+# define jit_movi_l(d, rs) jit_movi_i((d), (rs))
+# define jit_movr_l(d, rs) jit_movr_i((d), (rs))
+
+/* Stack */
+# define jit_pushr_l(rs) jit_pushr_i(rs)
+# define jit_popr_l(rs) jit_popr_i(rs)
+# define jit_pusharg_l(rs) jit_pusharg_i(rs)
+
+/* Memory */
+# ifndef JIT_RZERO
+# define jit_ldr_l(d, rs) jit_ldr_i((d), (rs))
+# define jit_ldi_l(d, is) jit_ldi_i((d), (is))
+# define jit_str_l(d, rs) jit_str_i((d), (rs))
+# define jit_sti_l(d, is) jit_sti_i((d), (is))
+# define jit_ldr_ui(d, rs) jit_ldr_i((d), (rs))
+# define jit_ldi_ui(d, is) jit_ldi_i((d), (is))
+# endif
+
+# define jit_ldxr_l(d, s1, s2) jit_ldxr_i((d), (s1), (s2))
+# define jit_ldxi_l(d, rs, is) jit_ldxi_i((d), (rs), (is))
+# define jit_stxr_l(d, s1, s2) jit_stxr_i((d), (s1), (s2))
+# define jit_stxi_l(d, rs, is) jit_stxi_i((d), (rs), (is))
+# if !defined (jit_ldxr_ui)
+# define jit_ldxr_ui(d, s1, s2) jit_ldxr_i((d), (s1), (s2))
+# endif
+# if !defined (jit_ldxi_ui)
+# define jit_ldxi_ui(d, rs, is) jit_ldxi_i((d), (rs), (is))
+# endif
+
+
+/* Boolean */
+# define jit_ltr_l(d, s1, s2) jit_ltr_i((d), (s1), (s2))
+# define jit_lti_l(d, rs, is) jit_lti_i((d), (rs), (is))
+# define jit_ler_l(d, s1, s2) jit_ler_i((d), (s1), (s2))
+# define jit_lei_l(d, rs, is) jit_lei_i((d), (rs), (is))
+# define jit_gtr_l(d, s1, s2) jit_gtr_i((d), (s1), (s2))
+# define jit_gti_l(d, rs, is) jit_gti_i((d), (rs), (is))
+# define jit_ger_l(d, s1, s2) jit_ger_i((d), (s1), (s2))
+# define jit_gei_l(d, rs, is) jit_gei_i((d), (rs), (is))
+# define jit_eqr_l(d, s1, s2) jit_eqr_i((d), (s1), (s2))
+# define jit_eqi_l(d, rs, is) jit_eqi_i((d), (rs), (is))
+# define jit_ner_l(d, s1, s2) jit_ner_i((d), (s1), (s2))
+# define jit_nei_l(d, rs, is) jit_nei_i((d), (rs), (is))
+# define jit_ltr_ul(d, s1, s2) jit_ltr_ui((d), (s1), (s2))
+# define jit_lti_ul(d, rs, is) jit_lti_ui((d), (rs), (is))
+# define jit_ler_ul(d, s1, s2) jit_ler_ui((d), (s1), (s2))
+# define jit_lei_ul(d, rs, is) jit_lei_ui((d), (rs), (is))
+# define jit_gtr_ul(d, s1, s2) jit_gtr_ui((d), (s1), (s2))
+# define jit_gti_ul(d, rs, is) jit_gti_ui((d), (rs), (is))
+# define jit_ger_ul(d, s1, s2) jit_ger_ui((d), (s1), (s2))
+# define jit_gei_ul(d, rs, is) jit_gei_ui((d), (rs), (is))
+
+/* Branches */
+# define jit_bltr_l(label, s1, s2) jit_bltr_i((label), (s1), (s2))
+# define jit_blti_l(label, rs, is) jit_blti_i((label), (rs), (is))
+# define jit_bler_l(label, s1, s2) jit_bler_i((label), (s1), (s2))
+# define jit_blei_l(label, rs, is) jit_blei_i((label), (rs), (is))
+# define jit_bgtr_l(label, s1, s2) jit_bgtr_i((label), (s1), (s2))
+# define jit_bgti_l(label, rs, is) jit_bgti_i((label), (rs), (is))
+# define jit_bger_l(label, s1, s2) jit_bger_i((label), (s1), (s2))
+# define jit_bgei_l(label, rs, is) jit_bgei_i((label), (rs), (is))
+# define jit_beqr_l(label, s1, s2) jit_beqr_i((label), (s1), (s2))
+# define jit_beqi_l(label, rs, is) jit_beqi_i((label), (rs), (is))
+# define jit_bner_l(label, s1, s2) jit_bner_i((label), (s1), (s2))
+# define jit_bnei_l(label, rs, is) jit_bnei_i((label), (rs), (is))
+# define jit_bmcr_l(label, s1, s2) jit_bmcr_i((label), (s1), (s2))
+# define jit_bmci_l(label, rs, is) jit_bmci_i((label), (rs), (is))
+# define jit_bmsr_l(label, s1, s2) jit_bmsr_i((label), (s1), (s2))
+# define jit_bmsi_l(label, rs, is) jit_bmsi_i((label), (rs), (is))
+# define jit_boaddr_l(label, s1, s2) jit_boaddr_i((label), (s1), (s2))
+# define jit_boaddi_l(label, rs, is) jit_boaddi_i((label), (rs), (is))
+# define jit_bosubr_l(label, s1, s2) jit_bosubr_i((label), (s1), (s2))
+# define jit_bosubi_l(label, rs, is) jit_bosubi_i((label), (rs), (is))
+# define jit_bltr_ul(label, s1, s2) jit_bltr_ui((label), (s1), (s2))
+# define jit_blti_ul(label, rs, is) jit_blti_ui((label), (rs), (is))
+# define jit_bler_ul(label, s1, s2) jit_bler_ui((label), (s1), (s2))
+# define jit_blei_ul(label, rs, is) jit_blei_ui((label), (rs), (is))
+# define jit_bgtr_ul(label, s1, s2) jit_bgtr_ui((label), (s1), (s2))
+# define jit_bgti_ul(label, rs, is) jit_bgti_ui((label), (rs), (is))
+# define jit_bger_ul(label, s1, s2) jit_bger_ui((label), (s1), (s2))
+# define jit_bgei_ul(label, rs, is) jit_bgei_ui((label), (rs), (is))
+# define jit_boaddr_ul(label, s1, s2) jit_boaddr_ui((label), (s1), (s2))
+# define jit_boaddi_ul(label, rs, is) jit_boaddi_ui((label), (rs), (is))
+# define jit_bosubr_ul(label, s1, s2) jit_bosubr_ui((label), (s1), (s2))
+# define jit_bosubi_ul(label, rs, is) jit_bosubi_ui((label), (rs), (is))
+
+# define jit_retval_l(rd) jit_retval_i((rd))
+#endif /* __WORDSIZE == 32 */
+
+/* RSB is not mandatory */
+#ifndef jit_rsbi_i
+# define jit_rsbi_i(d, rs, is) (jit_subi_i((d), (rs), (is)), jit_negr_i((d), (d)))
+
+# ifndef jit_rsbi_l
+# define jit_rsbi_l(d, rs, is) (jit_subi_l((d), (rs), (is)), jit_negr_l((d), (d)))
+# endif
+#endif
+
+#endif /* __lightning_core_common_h_ */
diff --git a/src/racket/src/lightning/arm/core.h b/src/racket/src/lightning/arm/core.h
new file mode 100644
index 0000000000..588f2755d8
--- /dev/null
+++ b/src/racket/src/lightning/arm/core.h
@@ -0,0 +1,2588 @@
+/******************************** -*- C -*- ****************************
+ *
+ * Platform-independent layer (arm version)
+ *
+ ***********************************************************************/
+
+/***********************************************************************
+ *
+ * Copyright 2011 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU lightning.
+ *
+ * GNU lightning 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU lightning 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 GNU lightning; see the file COPYING.LESSER; if not, write to the
+ * Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ *
+ * Authors:
+ * Paulo Cesar Pereira de Andrade
+ ***********************************************************************/
+
+#ifndef __lightning_core_arm_h
+#define __lightning_core_arm_h
+
+#define _jitl _jitp->jitl
+
+#define JIT_R_NUM 4
+#define JIT_R(i) i
+
+#define JIT_V_NUM 4
+static const jit_gpr_t
+jit_v_order[JIT_V_NUM] = {
+ _R4, _R5, _R6, _R7
+};
+#define JIT_V(i) jit_v_order[i]
+
+#define JIT_R0 _R0
+#define JIT_R1 _R1
+#define JIT_R2 _R2
+#define JIT_V0 _R4
+#define JIT_V1 _R5
+#define JIT_V2 _R6
+
+#define jit_no_set_flags() jit_flags.no_set_flags
+#define jit_armv5_p() (jit_cpu.version >= 5)
+#define jit_armv5e_p() (jit_cpu.version >= 5 && jit_cpu.extend)
+#define jit_armv7r_p() 0
+#define jit_swf_p() (jit_cpu.vfp == 0)
+#define jit_hardfp_p() jit_cpu.abi
+
+extern int __aeabi_idivmod(int, int);
+extern unsigned __aeabi_uidivmod(unsigned, unsigned);
+
+#define jit_nop(n) arm_nop(_jitp, n)
+__jit_inline void
+arm_nop(jit_state_t _jitp, int n)
+{
+ jit_assert(n >= 0);
+ if (jit_thumb_p()) {
+ for (; n > 0; n -= 2)
+ T1_NOP();
+ }
+ else {
+ for (; n > 0; n -= 4)
+ _NOP();
+ }
+}
+
+#define jit_movr_i(r0, r1) arm_movr_i(_jitp, r0, r1)
+__jit_inline void
+arm_movr_i(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1)
+{
+ if (r0 != r1) {
+ if (jit_thumb_p())
+ T1_MOV(r0, r1);
+ else
+ _MOV(r0, r1);
+ }
+}
+
+#define jit_movi_i(r0, i0) arm_movi_i(_jitp, r0, i0)
+__jit_inline void
+arm_movi_i(jit_state_t _jitp, jit_gpr_t r0, int i0)
+{
+ int i;
+ if (jit_thumb_p()) {
+ if (!jit_no_set_flags() && r0 < 8 && !(i0 & 0xffffff80))
+ T1_MOVI(r0, i0);
+ else if ((i = encode_thumb_immediate(i0)) != -1)
+ T2_MOVI(r0, i);
+ else if ((i = encode_thumb_immediate(~i0)) != -1)
+ T2_MVNI(r0, i);
+ else {
+ T2_MOVWI(r0, _jit_US(i0));
+ if (i0 & 0xffff0000)
+ T2_MOVTI(r0, _jit_US((unsigned)i0 >> 16));
+ }
+ }
+ else {
+ if (jit_armv6_p() && !(i0 & 0xffff0000))
+ _MOVWI(r0, i0);
+ else if ((i = encode_arm_immediate(i0)) != -1)
+ _MOVI(r0, i);
+ else if ((i = encode_arm_immediate(~i0)) != -1)
+ _MVNI(r0, i);
+ else if (jit_armv6_p()) {
+ _MOVWI(r0, _jit_US(i0));
+ if ((i0 & 0xffff0000))
+ _MOVTI(r0, _jit_US((unsigned)i0 >> 16));
+ }
+ else {
+ int p0, p1, p2, p3, q0, q1, q2, q3;
+ p0 = i0 & 0x000000ff; p1 = i0 & 0x0000ff00;
+ p2 = i0 & 0x00ff0000; p3 = i0 & 0xff000000;
+ i0 = ~i0;
+ q0 = i0 & 0x000000ff; q1 = i0 & 0x0000ff00;
+ q2 = i0 & 0x00ff0000; q3 = i0 & 0xff000000;
+ if (!!p0 + !!p1 + !!p2 + !!p3 <= !!q0 + !!q1 + !!q2 + !!q3) {
+ /* prefer no inversion on tie */
+ if (p3) {
+ _MOVI(r0, encode_arm_immediate(p3));
+ if (p2) _ORRI(r0, r0, encode_arm_immediate(p2));
+ if (p1) _ORRI(r0, r0, encode_arm_immediate(p1));
+ if (p0) _ORRI(r0, r0, p0);
+ }
+ else if (p2) {
+ _MOVI(r0, encode_arm_immediate(p2));
+ if (p1) _ORRI(r0, r0, encode_arm_immediate(p1));
+ if (p0) _ORRI(r0, r0, p0);
+ }
+ else {
+ _MOVI(r0, encode_arm_immediate(p1));
+ _ORRI(r0, r0, p0);
+ }
+ }
+ else {
+ if (q3) {
+ _MVNI(r0, encode_arm_immediate(q3));
+ if (q2) _EORI(r0, r0, encode_arm_immediate(q2));
+ if (q1) _EORI(r0, r0, encode_arm_immediate(q1));
+ if (q0) _EORI(r0, r0, q0);
+ }
+ else if (q2) {
+ _MVNI(r0, encode_arm_immediate(q2));
+ if (q1) _EORI(r0, r0, encode_arm_immediate(q1));
+ if (q0) _EORI(r0, r0, q0);
+ }
+ else {
+ _MVNI(r0, encode_arm_immediate(q1));
+ _EORI(r0, r0, q0);
+ }
+ }
+ }
+ }
+}
+
+#define jit_movi_p(r0, i0) arm_movi_p(_jitp, r0, i0)
+__jit_inline jit_insn *
+arm_movi_p(jit_state_t _jitp, jit_gpr_t r0, void *i0)
+{
+ jit_insn *l;
+ int im, q0, q1, q2, q3;
+ im = (int)i0;
+ if (jit_thumb_p()) {
+ l = _jitp->x.pc+1;
+ T2_MOVWI(r0, _jit_US((int)i0));
+ T2_MOVTI(r0, _jit_US((int)i0 >> 16));
+ }
+ else {
+ l = _jitp->x.pc;
+ if (jit_armv6_p()) {
+ _MOVWI(r0, _jit_US((unsigned)i0));
+ _MOVTI(r0, _jit_US((unsigned)i0 >> 16));
+ }
+ else {
+ q0 = im & 0x000000ff; q1 = im & 0x0000ff00;
+ q2 = im & 0x00ff0000; q3 = im & 0xff000000;
+ _MOVI(r0, encode_arm_immediate(q3));
+ _ORRI(r0, r0, encode_arm_immediate(q2));
+ _ORRI(r0, r0, encode_arm_immediate(q1));
+ _ORRI(r0, r0, q0);
+ }
+ }
+ return (l);
+}
+
+#define jit_patchable_movi_p(i0, i1) jit_movi_p(i0, i1)
+
+#define jit_patch_movi(i0, i1) arm_patch_movi(i0, i1)
+__jit_inline void
+arm_patch_movi(jit_insn *i0, void *i1)
+{
+ union {
+ short *s;
+ int *i;
+ void *v;
+ } u;
+ jit_thumb_t thumb;
+ unsigned int im;
+ int q0, q1, q2, q3;
+ im = (unsigned int)i1;
+ if (jit_thumb_p()) {
+ jit_assert((long)i0 & 0x1);
+ u.v = i0 - 1;
+ q0 = (im & 0xf000) << 4;
+ q1 = (im & 0x0800) << 15;
+ q2 = (im & 0x0700) << 4;
+ q3 = im & 0x00ff;
+ code2thumb(thumb.s[0], thumb.s[1], u.s[0], u.s[1]);
+ jit_assert( (thumb.i & 0xfbf00000) == THUMB2_MOVWI);
+ thumb.i = (thumb.i & 0xfbf00f00) | q0 | q1 | q2 | q3;
+ thumb2code(thumb.s[0], thumb.s[1], u.s[0], u.s[1]);
+ im >>= 16;
+ q0 = (im & 0xf000) << 4;
+ q1 = (im & 0x0800) << 15;
+ q2 = (im & 0x0700) << 4;
+ q3 = im & 0x00ff;
+ code2thumb(thumb.s[0], thumb.s[1], u.s[2], u.s[3]);
+ jit_assert( (thumb.i & 0xfbf00000) == THUMB2_MOVTI);
+ thumb.i = (thumb.i & 0xfbf00f00) | q0 | q1 | q2 | q3;
+ thumb2code(thumb.s[0], thumb.s[1], u.s[2], u.s[3]);
+ }
+ else {
+ u.v = i0;
+ if (jit_armv6_p()) {
+ q0 = im & 0xfff;
+ q1 = (im & 0xf000) << 4;
+ q2 = (im & 0xfff0000) >> 16;
+ q3 = (im & 0xf0000000) >> 12;
+ jit_assert( (u.i[0] & 0x0ff00000) == (ARM_MOVWI));
+ jit_assert( (u.i[1] & 0x0ff00000) == (ARM_MOVTI));
+ u.i[0] = (u.i[0] & 0xfff0f000) | q1 | q0;
+ u.i[1] = (u.i[1] & 0xfff0f000) | q3 | q2;
+ }
+ else {
+ q0 = im & 0x000000ff; q1 = im & 0x0000ff00;
+ q2 = im & 0x00ff0000; q3 = im & 0xff000000;
+ jit_assert( (u.i[0] & 0x0ff00000) == (ARM_MOV|ARM_I));
+ u.i[0] = (u.i[0] & 0xfffff000) | encode_arm_immediate(q3);
+ jit_assert( (u.i[1] & 0x0ff00000) == (ARM_ORR|ARM_I));
+ u.i[1] = (u.i[1] & 0xfffff000) | encode_arm_immediate(q2);
+ jit_assert( (u.i[2] & 0x0ff00000) == (ARM_ORR|ARM_I));
+ u.i[2] = (u.i[2] & 0xfffff000) | encode_arm_immediate(q1);
+ jit_assert( (u.i[3] & 0x0ff00000) == (ARM_ORR|ARM_I));
+ u.i[3] = (u.i[3] & 0xfffff000) | encode_arm_immediate(q0);
+ }
+ }
+}
+
+#define jit_patch_calli(i0, i1) arm_patch_at(_jitp, i0, i1)
+#define jit_patch_at(jump, label) arm_patch_at(_jitp, jump, label)
+__jit_inline void
+arm_patch_at(jit_state_t _jitp, jit_insn *jump, jit_insn *label)
+{
+ long d;
+ union {
+ short *s;
+ int *i;
+ void *v;
+ } u;
+ jit_thumb_t thumb;
+ u.v = jump;
+ if (jit_thumb_p()) {
+ jit_assert((long)u.v & 0x1);
+ jit_assert((long)label & 0x1);
+ u.v = ((char *)u.v - 1);
+#if 0
+ /* this actually matches other patterns, so cannot patch
+ * automatically short jumps */
+ if ((u.s[0] & THUMB_CC_B) == THUMB_CC_B) {
+ jit_assert(_s8P(d));
+ u.s[0] = (u.s[0] & 0xff00) | (d & 0xff);
+ }
+ else if ((u.s[0] & THUMB_B) == THUMB_B) {
+ jit_assert(_s11P(d));
+ u.s[0] = (u.s[0] & 0xf800) | (d & 0x7ff);
+ }
+ else
+#endif
+ {
+ code2thumb(thumb.s[0], thumb.s[1], u.s[0], u.s[1]);
+ if ((thumb.i & THUMB2_B) == THUMB2_B) {
+ d = (((long)label - (long)jump) >> 1) - 2;
+ jit_assert(_s24P(d));
+ thumb.i = THUMB2_B | encode_thumb_jump(d);
+ thumb2code(thumb.s[0], thumb.s[1], u.s[0], u.s[1]);
+ }
+ else if ((thumb.i & THUMB2_B) == THUMB2_CC_B) {
+ d = (((long)label - (long)jump) >> 1) - 2;
+ jit_assert(_s20P(d));
+ thumb.i = THUMB2_CC_B | (thumb.i & 0x3c00000) |
+ encode_thumb_cc_jump(d);
+ thumb2code(thumb.s[0], thumb.s[1], u.s[0], u.s[1]);
+ }
+ else if ((thumb.i & 0xfbf08000) == THUMB2_MOVWI)
+ jit_patch_movi(jump, label);
+ else
+ jit_assert(!"handled branch opcode");
+ }
+ }
+ else {
+ /* 0x0e000000 because 0x01000000 is (branch&) link modifier */
+ if ((u.i[0] & 0x0e000000) == ARM_B) {
+ d = (((long)label - (long)jump) >> 2) - 2;
+ jit_assert(_s24P(d));
+ u.i[0] = (u.i[0] & 0xff000000) | (d & 0x00ffffff);
+ }
+ else if (( jit_armv6_p() && (u.i[0] & 0x0ff00000) == ARM_MOVWI) ||
+ (!jit_armv6_p() && (u.i[0] & 0x0ff00000) == (ARM_MOV|ARM_I)))
+ jit_patch_movi(jump, label);
+ else
+ jit_assert(!"handled branch opcode");
+ }
+}
+
+#define jit_notr_i(r0, r1) arm_notr_i(_jitp, r0, r1)
+__jit_inline void
+arm_notr_i(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1)
+{
+ if (jit_thumb_p()) {
+ if (!jit_no_set_flags() && (r0|r1) < 8)
+ T1_NOT(r0, r1);
+ else
+ T2_NOT(r0, r1);
+ }
+ else
+ _NOT(r0, r1);
+}
+
+#define jit_negr_i(r0, r1) arm_negr_i(_jitp, r0, r1)
+__jit_inline void
+arm_negr_i(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1)
+{
+ if (jit_thumb_p()) {
+ if (!jit_no_set_flags() && (r0|r1) < 8)
+ T1_RSBI(r0, r1);
+ else
+ T2_RSBI(r0, r1, 0);
+ }
+ else
+ _RSBI(r0, r1, 0);
+}
+
+#define jit_addr_i(r0, r1, r2) arm_addr_i(_jitp, r0, r1, r2)
+__jit_inline void
+arm_addr_i(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, jit_gpr_t r2)
+{
+ if (jit_thumb_p()) {
+ if (!jit_no_set_flags() && (r0|r1|r2) < 8)
+ T1_ADD(r0, r1, r2);
+ else if (r0 == r1 || r0 == r2)
+ T1_ADDX(r0, r0 == r1 ? r2 : r1);
+ else
+ T2_ADD(r0, r1, r2);
+ }
+ else
+ _ADD(r0, r1, r2);
+}
+
+#define jit_addi_i(r0, r1, i0) arm_addi_i(_jitp, r0, r1, i0)
+__jit_inline void
+arm_addi_i(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, int i0)
+{
+ int i;
+ jit_gpr_t reg;
+ if (jit_thumb_p()) {
+ if (!jit_no_set_flags() && (r0|r1) < 8 && !(i0 & ~7))
+ T1_ADDI3(r0, r1, i0);
+ else if (!jit_no_set_flags() && (r0|r1) < 8 && !(-i0 & ~7))
+ T1_SUBI3(r0, r1, -i0);
+ else if (!jit_no_set_flags() && r0 < 8 && r0 == r1 && !(i0 & ~0xff))
+ T1_ADDI8(r0, i0);
+ else if (!jit_no_set_flags() && r0 < 8 && r0 == r1 && !(-i0 & ~0xff))
+ T1_SUBI8(r0, -i0);
+ else if ((i = encode_thumb_immediate(i0)) != -1)
+ T2_ADDI(r0, r1, i);
+ else if ((i = encode_thumb_immediate(-i0)) != -1)
+ T2_SUBI(r0, r1, i);
+ else if ((i = encode_thumb_word_immediate(i0)) != -1)
+ T2_ADDWI(r0, r1, i);
+ else if ((i = encode_thumb_word_immediate(-i0)) != -1)
+ T2_SUBWI(r0, r1, i);
+ else {
+ reg = r0 != r1 ? r0 : JIT_TMP;
+ jit_movi_i(reg, i0);
+ T2_ADD(r0, r1, reg);
+ }
+ }
+ else {
+ if ((i = encode_arm_immediate(i0)) != -1)
+ _ADDI(r0, r1, i);
+ else if ((i = encode_arm_immediate(-i0)) != -1)
+ _SUBI(r0, r1, i);
+ else {
+ reg = r0 != r1 ? r0 : JIT_TMP;
+ jit_movi_i(reg, i0);
+ _ADD(r0, r1, reg);
+ }
+ }
+}
+
+#define jit_addcr_ui(r0, r1, r2) arm_addcr_ui(_jitp, r0, r1, r2)
+__jit_inline void
+arm_addcr_ui(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, jit_gpr_t r2)
+{
+ if (jit_thumb_p()) {
+ /* thumb auto set carry if not inside IT block */
+ if ((r0|r1|r2) < 8)
+ T1_ADD(r0, r1, r2);
+ else
+ T2_ADDS(r0, r1, r2);
+ }
+ else
+ _ADDS(r0, r1, r2);
+}
+
+#define jit_addci_ui(r0, r1, i0) arm_addci_ui(_jitp, r0, r1, i0)
+__jit_inline void
+arm_addci_ui(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, int i0)
+{
+ int i;
+ jit_gpr_t reg;
+ if (jit_thumb_p()) {
+ if ((r0|r1) < 8 && !(i0 & ~7))
+ T1_ADDI3(r0, r1, i0);
+ else if ((r0|r1) < 8 && !(-i0 & ~7))
+ T1_SUBI3(r0, r1, -i0);
+ else if (r0 < 8 && r0 == r1 && !(i0 & ~0xff))
+ T1_ADDI8(r0, i0);
+ else if (r0 < 8 && r0 == r1 && !(-i0 & ~0xff))
+ T1_SUBI8(r0, -i0);
+ else if ((i = encode_thumb_immediate(i0)) != -1)
+ T2_ADDSI(r0, r1, i);
+ else if ((i = encode_thumb_immediate(-i0)) != -1)
+ T2_SUBSI(r0, r1, i);
+ else {
+ reg = r0 != r1 ? r0 : JIT_TMP;
+ jit_movi_i(reg, i0);
+ T2_ADDS(r0, r1, reg);
+ }
+ }
+ else {
+ if ((i = encode_arm_immediate(i0)) != -1)
+ _ADDSI(r0, r1, i);
+ else if ((i = encode_arm_immediate(-i0)) != -1)
+ _SUBSI(r0, r1, i);
+ else {
+ reg = r0 != r1 ? r0 : JIT_TMP;
+ jit_movi_i(reg, i0);
+ _ADDS(r0, r1, reg);
+ }
+ }
+}
+
+#define jit_addxr_ui(r0, r1, r2) arm_addxr_ui(_jitp, r0, r1, r2)
+__jit_inline void
+arm_addxr_ui(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, jit_gpr_t r2)
+{
+ /* keep setting carry because don't know last ADC */
+ if (jit_thumb_p()) {
+ /* thumb auto set carry if not inside IT block */
+ if ((r0|r1|r2) < 8 && (r0 == r1 || r0 == r2))
+ T1_ADC(r0, r0 == r1 ? r2 : r1);
+ else
+ T2_ADCS(r0, r1, r2);
+ }
+ else
+ _ADCS(r0, r1, r2);
+}
+
+#define jit_addxi_ui(r0, r1, i0) arm_addxi_ui(_jitp, r0, r1, i0)
+__jit_inline void
+arm_addxi_ui(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, int i0)
+{
+ int i;
+ jit_gpr_t reg;
+ if (jit_thumb_p()) {
+ if ((i = encode_thumb_immediate(i0)) != -1)
+ T2_ADCSI(r0, r1, i);
+ else if ((i = encode_thumb_immediate(-i0)) != -1)
+ T2_SBCSI(r0, r1, i);
+ else {
+ int no_set_flags = jit_no_set_flags();
+ reg = r0 != r1 ? r0 : JIT_TMP;
+ jit_no_set_flags() = 1;
+ jit_movi_i(reg, i0);
+ jit_no_set_flags() = no_set_flags;
+ T2_ADCS(r0, r1, reg);
+ }
+ }
+ else {
+ if ((i = encode_arm_immediate(i0)) != -1)
+ _ADCSI(r0, r1, i);
+ else if ((i = encode_arm_immediate(-i0)) != -1)
+ _SBCSI(r0, r1, i);
+ else {
+ reg = r0 != r1 ? r0 : JIT_TMP;
+ jit_movi_i(reg, i0);
+ _ADCS(r0, r1, reg);
+ }
+ }
+}
+
+#define jit_subr_i(r0, r1, r2) arm_subr_i(_jitp, r0, r1, r2)
+__jit_inline void
+arm_subr_i(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, jit_gpr_t r2)
+{
+ if (jit_thumb_p()) {
+ if (!jit_no_set_flags() && (r0|r1|r2) < 8)
+ T1_SUB(r0, r1, r2);
+ else
+ T2_SUB(r0, r1, r2);
+ }
+ else
+ _SUB(r0, r1, r2);
+}
+
+#define jit_subi_i(r0, r1, i0) arm_subi_i(_jitp, r0, r1, i0)
+__jit_inline void
+arm_subi_i(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, int i0)
+{
+ int i;
+ jit_gpr_t reg;
+ if (jit_thumb_p()) {
+ if (!jit_no_set_flags() && (r0|r1) < 8 && !(i0 & ~7))
+ T1_SUBI3(r0, r1, i0);
+ else if (!jit_no_set_flags() && (r0|r1) < 8 && !(-i0 & ~7))
+ T1_ADDI3(r0, r1, -i0);
+ else if (!jit_no_set_flags() && r0 < 8 && r0 == r1 && !(i0 & ~0xff))
+ T1_SUBI8(r0, i0);
+ else if (!jit_no_set_flags() && r0 < 8 && r0 == r1 && !(-i0 & ~0xff))
+ T1_ADDI8(r0, -i0);
+ else if ((i = encode_thumb_immediate(i0)) != -1)
+ T2_SUBI(r0, r1, i);
+ else if ((i = encode_thumb_immediate(-i0)) != -1)
+ T2_ADDI(r0, r1, i);
+ else if ((i = encode_thumb_word_immediate(i0)) != -1)
+ T2_SUBWI(r0, r1, i);
+ else if ((i = encode_thumb_word_immediate(-i0)) != -1)
+ T2_ADDWI(r0, r1, i);
+ else {
+ reg = r0 != r1 ? r0 : JIT_TMP;
+ jit_movi_i(reg, i0);
+ T2_SUB(r0, r1, reg);
+ }
+ }
+ else {
+ if ((i = encode_arm_immediate(i0)) != -1)
+ _SUBI(r0, r1, i);
+ else if ((i = encode_arm_immediate(-i0)) != -1)
+ _ADDI(r0, r1, i);
+ else {
+ reg = r0 != r1 ? r0 : JIT_TMP;
+ jit_movi_i(reg, i0);
+ _SUB(r0, r1, reg);
+ }
+ }
+}
+
+#define jit_subcr_ui(r0, r1, r2) arm_subcr_ui(_jitp, r0, r1, r2)
+__jit_inline void
+arm_subcr_ui(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, jit_gpr_t r2)
+{
+ if (jit_thumb_p()) {
+ /* thumb auto set carry if not inside IT block */
+ if ((r0|r1|r2) < 8)
+ T1_SUB(r0, r1, r2);
+ else
+ T2_SUBS(r0, r1, r2);
+ }
+ else
+ _SUBS(r0, r1, r2);
+}
+
+#define jit_subci_ui(r0, r1, i0) arm_subci_ui(_jitp, r0, r1, i0)
+__jit_inline void
+arm_subci_ui(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, int i0)
+{
+ int i;
+ jit_gpr_t reg;
+ if (jit_thumb_p()) {
+ if ((r0|r1) < 8 && !(i0 & ~7))
+ T1_SUBI3(r0, r1, i0);
+ else if ((r0|r1) < 8 && !(-i0 & ~7))
+ T1_ADDI3(r0, r1, -i0);
+ else if (r0 < 8 && r0 == r1 && !(i0 & ~0xff))
+ T1_SUBI8(r0, i0);
+ else if (r0 < 8 && r0 == r1 && !(-i0 & ~0xff))
+ T1_ADDI8(r0, -i0);
+ else if ((i = encode_thumb_immediate(i0)) != -1)
+ T2_SUBSI(r0, r1, i);
+ else if ((i = encode_thumb_immediate(-i0)) != -1)
+ T2_ADDSI(r0, r1, i);
+ else {
+ reg = r0 != r1 ? r0 : JIT_TMP;
+ jit_movi_i(reg, i0);
+ T2_SUBS(r0, r1, reg);
+ }
+ }
+ else {
+ if ((i = encode_arm_immediate(i0)) != -1)
+ _SUBSI(r0, r1, i);
+ else if ((i = encode_arm_immediate(-i0)) != -1)
+ _ADDSI(r0, r1, i);
+ else {
+ reg = r0 != r1 ? r0 : JIT_TMP;
+ jit_movi_i(reg, i0);
+ _SUBS(r0, r1, reg);
+ }
+ }
+}
+
+#define jit_subxr_ui(r0, r1, r2) arm_subxr_ui(_jitp, r0, r1, r2)
+__jit_inline void
+arm_subxr_ui(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, jit_gpr_t r2)
+{
+ /* keep setting carry because don't know last ADC */
+ if (jit_thumb_p()) {
+ /* thumb auto set carry if not inside IT block */
+ if ((r0|r1|r2) < 8 && r0 == r1)
+ T1_SBC(r0, r2);
+ else
+ T2_SBCS(r0, r1, r2);
+ }
+ else
+ _SBCS(r0, r1, r2);
+}
+
+#define jit_subxi_ui(r0, r1, i0) arm_subxi_ui(_jitp, r0, r1, i0)
+__jit_inline void
+arm_subxi_ui(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, int i0)
+{
+ int i;
+ jit_gpr_t reg;
+ if (jit_thumb_p()) {
+ if ((i = encode_thumb_immediate(i0)) != -1)
+ T2_SBCSI(r0, r1, i);
+ else if ((i = encode_thumb_immediate(-i0)) != -1)
+ T2_ADCSI(r0, r1, i);
+ else {
+ int no_set_flags = jit_no_set_flags();
+ reg = r0 != r1 ? r0 : JIT_TMP;
+ jit_no_set_flags() = 1;
+ jit_movi_i(reg, i0);
+ jit_no_set_flags() = no_set_flags;
+ T2_SBCS(r0, r1, reg);
+ }
+ }
+ else {
+ if ((i = encode_arm_immediate(i0)) != -1)
+ _SBCSI(r0, r1, i);
+ else if ((i = encode_arm_immediate(-i0)) != -1)
+ _ADCSI(r0, r1, i);
+ else {
+ reg = r0 != r1 ? r0 : JIT_TMP;
+ jit_movi_i(reg, i0);
+ _SBCS(r0, r1, reg);
+ }
+ }
+}
+
+#define jit_rsbr_i(r0, r1, r2) arm_rsbr_i(_jitp, r0, r1, r2)
+__jit_inline void
+arm_rsbr_i(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, jit_gpr_t r2)
+{
+ if (jit_thumb_p())
+ T2_RSB(r0, r1, r2);
+ else
+ _RSB(r0, r1, r2);
+}
+
+#define jit_rsbi_i(r0, r1, i0) arm_rsbi_i(_jitp, r0, r1, i0)
+__jit_inline void
+arm_rsbi_i(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, int i0)
+{
+ int i;
+ jit_gpr_t reg;
+ if (jit_thumb_p()) {
+ if (i0 == 0)
+ arm_negr_i(_jitp, r0, r1);
+ else if ((i = encode_thumb_immediate(i0)) != -1)
+ T2_RSBI(r0, r1, i);
+ else {
+ reg = r0 != r1 ? r0 : JIT_TMP;
+ jit_movi_i(reg, i0);
+ T2_RSB(r0, r1, reg);
+ }
+ }
+ else {
+ if ((i = encode_arm_immediate(i0)) != -1)
+ _RSBI(r0, r1, i);
+ else {
+ reg = r0 != r1 ? r0 : JIT_TMP;
+ jit_movi_i(reg, i0);
+ _RSB(r0, r1, reg);
+ }
+ }
+}
+
+#define jit_mulr_i(r0, r1, r2) arm_mulr_i(_jitp, r0, r1, r2)
+#define jit_mulr_ui(r0, r1, r2) arm_mulr_i(_jitp, r0, r1, r2)
+__jit_inline void
+arm_mulr_i(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, jit_gpr_t r2)
+{
+ if (jit_thumb_p()) {
+ if (!jit_no_set_flags() && r0 == r2 && (r0|r1) < 8)
+ T1_MUL(r0, r1);
+ else if (!jit_no_set_flags() && r0 == r1 && (r0|r2) < 8)
+ T1_MUL(r0, r2);
+ else
+ T2_MUL(r0, r1, r2);
+ }
+ else {
+ if (r0 == r1 && !jit_armv6_p()) {
+ if (r0 != r2)
+ _MUL(r0, r2, r1);
+ else {
+ _MOV(JIT_TMP, r1);
+ _MUL(r0, JIT_TMP, r2);
+ }
+ }
+ else
+ _MUL(r0, r1, r2);
+ }
+}
+
+#define jit_muli_i(r0, r1, i0) arm_muli_i(_jitp, r0, r1, i0)
+#define jit_muli_ui(r0, r1, i0) arm_muli_i(_jitp, r0, r1, i0)
+__jit_inline void
+arm_muli_i(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, int i0)
+{
+ jit_gpr_t reg;
+ reg = r0 != r1 ? r0 : JIT_TMP;
+ jit_movi_i(reg, i0);
+ arm_mulr_i(_jitp, r0, r1, reg);
+}
+
+#define jit_hmulr_i(r0, r1, r2) arm_hmulr_i(_jitp, r0, r1, r2)
+__jit_inline void
+arm_hmulr_i(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, jit_gpr_t r2)
+{
+ if (jit_thumb_p())
+ T2_SMULL(JIT_TMP, r0, r1, r2);
+ else {
+ if (r0 == r1 && !jit_armv6_p()) {
+ jit_assert(r2 != JIT_TMP);
+ _SMULL(JIT_TMP, r0, r2, r1);
+ }
+ else
+ _SMULL(JIT_TMP, r0, r1, r2);
+ }
+}
+
+#define jit_hmuli_i(r0, r1, i0) arm_hmuli_i(_jitp, r0, r1, i0)
+__jit_inline void
+arm_hmuli_i(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, int i0)
+{
+ jit_gpr_t reg;
+ if (jit_thumb_p()) {
+ jit_assert(r0 != JIT_TMP);
+ jit_movi_i(JIT_TMP, i0);
+ T2_SMULL(JIT_TMP, r0, r1, JIT_TMP);
+ }
+ else {
+ if (r0 != r1 || jit_armv6_p()) {
+ jit_movi_i(JIT_TMP, i0);
+ _SMULL(JIT_TMP, r0, r1, JIT_TMP);
+ }
+ else {
+ if (r0 != _R0) reg = _R0;
+ else if (r0 != _R1) reg = _R1;
+ else if (r0 != _R2) reg = _R2;
+ else reg = _R3;
+ _PUSH(1<= 0 && i0 <= 31);
+ if (i0 == 0)
+ jit_movr_i(r0, r1);
+ else if (jit_thumb_p()) {
+ if (!jit_no_set_flags() && (r0|r1) < 8)
+ T1_LSLI(r0, r1, i0);
+ else
+ T2_LSLI(r0, r1, i0);
+ }
+ else
+ _LSLI(r0, r1, i0);
+}
+
+#define jit_rshr_i(r0, r1, r2) arm_rshr_i(_jitp, r0, r1, r2)
+__jit_inline void
+arm_rshr_i(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, jit_gpr_t r2)
+{
+ if (jit_thumb_p()) {
+ if (!jit_no_set_flags() && (r0|r1|r2) < 8 && r0 == r1)
+ T1_ASR(r0, r2);
+ else
+ T2_ASR(r0, r1, r2);
+ }
+ else
+ _ASR(r0, r1, r2);
+}
+
+#define jit_rshi_i(r0, r1, i0) arm_rshi_i(_jitp, r0, r1, i0)
+__jit_inline void
+arm_rshi_i(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, int i0)
+{
+ jit_assert(i0 >= 0 && i0 <= 31);
+ if (i0 == 0)
+ jit_movr_i(r0, r1);
+ else if (jit_thumb_p()) {
+ if (!jit_no_set_flags() && (r0|r1) < 8)
+ T1_ASRI(r0, r1, i0);
+ else
+ T2_ASRI(r0, r1, i0);
+ }
+ else
+ _ASRI(r0, r1, i0);
+}
+
+#define jit_rshr_ui(r0, r1, r2) arm_rshr_ui(_jitp, r0, r1, r2)
+__jit_inline void
+arm_rshr_ui(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, jit_gpr_t r2)
+{
+ if (jit_thumb_p()) {
+ if (!jit_no_set_flags() && (r0|r1|r2) < 8 && r0 == r1)
+ T1_LSR(r0, r2);
+ else
+ T2_LSR(r0, r1, r2);
+ }
+ else
+ _LSR(r0, r1, r2);
+}
+
+#define jit_rshi_ui(r0, r1, i0) arm_rshi_ui(_jitp, r0, r1, i0)
+__jit_inline void
+arm_rshi_ui(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, int i0)
+{
+ jit_assert(i0 >= 0 && i0 <= 31);
+ if (i0 == 0)
+ jit_movr_i(r0, r1);
+ else if (jit_thumb_p()) {
+ if (!jit_no_set_flags() && (r0|r1) < 8)
+ T1_LSRI(r0, r1, i0);
+ else
+ T2_LSRI(r0, r1, i0);
+ }
+ else
+ _LSRI(r0, r1, i0);
+}
+
+__jit_inline void
+arm_ccr(jit_state_t _jitp, int ct, int cf,
+ jit_gpr_t r0, jit_gpr_t r1, jit_gpr_t r2)
+{
+ if (jit_thumb_p()) {
+ jit_assert((ct ^ cf) >> 28 == 1);
+ if ((r1|r2) < 8)
+ T1_CMP(r1, r2);
+ else if ((r1&r2) & 8)
+ T1_CMPX(r1, r2);
+ else
+ T2_CMP(r1, r2);
+ _ITE(ct);
+ if (r0 < 8) {
+ T1_MOVI(r0, 1);
+ T1_MOVI(r0, 0);
+ }
+ else {
+ T2_MOVI(r0, 1);
+ T2_MOVI(r0, 0);
+ }
+ }
+ else {
+ _CMP(r1, r2);
+ _CC_MOVI(ct, r0, 1);
+ _CC_MOVI(cf, r0, 0);
+ }
+}
+__jit_inline void
+arm_cci(jit_state_t _jitp, int ct, int cf,
+ jit_gpr_t r0, jit_gpr_t r1, int i0)
+{
+ int i;
+ jit_gpr_t reg;
+ if (jit_thumb_p()) {
+ if (r1 < 7 && !(i0 & 0xffffff00))
+ T1_CMPI(r1, i0);
+ else if ((i = encode_thumb_immediate(i0)) != -1)
+ T2_CMPI(r1, i);
+ else if ((i = encode_thumb_immediate(-i0)) != -1)
+ T2_CMNI(r1, i);
+ else {
+ reg = r0 != r1 ? r0 : JIT_TMP;
+ jit_movi_i(reg, i0);
+ arm_ccr(_jitp, ct, cf, r0, r1, reg);
+ return;
+ }
+ _ITE(ct);
+ if (r0 < 8) {
+ T1_MOVI(r0, 1);
+ T1_MOVI(r0, 0);
+ }
+ else {
+ T2_MOVI(r0, 1);
+ T2_MOVI(r0, 0);
+ }
+ }
+ else {
+ if ((i = encode_arm_immediate(i0)) != -1)
+ _CMPI(r1, i);
+ else if ((i = encode_arm_immediate(-i0)) != -1)
+ _CMNI(r1, i);
+ else {
+ reg = r0 != r1 ? r0 : JIT_TMP;
+ jit_movi_i(reg, i0);
+ _CMP(r1, reg);
+ }
+ _CC_MOVI(ct, r0, 1);
+ _CC_MOVI(cf, r0, 0);
+ }
+}
+#define jit_ltr_i(r0, r1, r2) arm_ccr(_jitp,ARM_CC_LT,ARM_CC_GE,r0,r1,r2)
+#define jit_lti_i(r0, r1, i0) arm_cci(_jitp,ARM_CC_LT,ARM_CC_GE,r0,r1,i0)
+#define jit_ltr_ui(r0, r1, r2) arm_ccr(_jitp,ARM_CC_LO,ARM_CC_HS,r0,r1,r2)
+#define jit_lti_ui(r0, r1, i0) arm_cci(_jitp,ARM_CC_LO,ARM_CC_HS,r0,r1,i0)
+#define jit_ler_i(r0, r1, r2) arm_ccr(_jitp,ARM_CC_LE,ARM_CC_GT,r0,r1,r2)
+#define jit_lei_i(r0, r1, i0) arm_cci(_jitp,ARM_CC_LE,ARM_CC_GT,r0,r1,i0)
+#define jit_ler_ui(r0, r1, r2) arm_ccr(_jitp,ARM_CC_LS,ARM_CC_HI,r0,r1,r2)
+#define jit_lei_ui(r0, r1, i0) arm_cci(_jitp,ARM_CC_LS,ARM_CC_HI,r0,r1,i0)
+#define jit_eqr_i(r0, r1, r2) arm_ccr(_jitp,ARM_CC_EQ,ARM_CC_NE,r0,r1,r2)
+#define jit_eqi_i(r0, r1, i0) arm_cci(_jitp,ARM_CC_EQ,ARM_CC_NE,r0,r1,i0)
+#define jit_ger_i(r0, r1, r2) arm_ccr(_jitp,ARM_CC_GE,ARM_CC_LT,r0,r1,r2)
+#define jit_gei_i(r0, r1, i0) arm_cci(_jitp,ARM_CC_GE,ARM_CC_LT,r0,r1,i0)
+#define jit_ger_ui(r0, r1, r2) arm_ccr(_jitp,ARM_CC_HS,ARM_CC_LO,r0,r1,r2)
+#define jit_gei_ui(r0, r1, i0) arm_cci(_jitp,ARM_CC_HS,ARM_CC_LO,r0,r1,i0)
+#define jit_gtr_i(r0, r1, r2) arm_ccr(_jitp,ARM_CC_GT,ARM_CC_LE,r0,r1,r2)
+#define jit_gti_i(r0, r1, i0) arm_cci(_jitp,ARM_CC_GT,ARM_CC_LE,r0,r1,i0)
+#define jit_gtr_ui(r0, r1, r2) arm_ccr(_jitp,ARM_CC_HI,ARM_CC_LS,r0,r1,r2)
+#define jit_gti_ui(r0, r1, i0) arm_cci(_jitp,ARM_CC_HI,ARM_CC_LS,r0,r1,i0)
+
+#define jit_ner_i(r0, r1, r2) arm_ner_i(_jitp, r0, r1, r2)
+__jit_inline void
+arm_ner_i(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, jit_gpr_t r2)
+{
+ if (jit_thumb_p())
+ arm_ccr(_jitp, ARM_CC_NE, ARM_CC_EQ, r0, r1, r2);
+ else {
+ _SUBS(r0, r1, r2);
+ _CC_MOVI(ARM_CC_NE, r0, 1);
+ }
+}
+
+#define jit_nei_i(r0, r1, i0) arm_nei_i(_jitp, r0, r1, i0)
+__jit_inline void
+arm_nei_i(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, int i0)
+{
+ int i;
+ jit_gpr_t reg;
+ if (jit_thumb_p())
+ arm_cci(_jitp, ARM_CC_NE, ARM_CC_EQ, r0, r1, i0);
+ else {
+ if ((i = encode_arm_immediate(i0)) != -1)
+ _SUBSI(r0, r1, i);
+ else if ((i = encode_arm_immediate(-i0)) != -1)
+ _ADDSI(r0, r1, i);
+ else {
+ reg = r0 != r1 ? r0 : JIT_TMP;
+ jit_movi_i(reg, i0);
+ _SUBS(r0, r1, reg);
+ }
+ _CC_MOVI(ARM_CC_NE, r0, 1);
+ }
+}
+
+#define jit_jmpr(r0) arm_jmpr(_jitp, r0)
+__jit_inline void
+arm_jmpr(jit_state_t _jitp, jit_gpr_t r0)
+{
+ if (jit_thumb_p())
+ T1_BX(r0);
+ else
+ _BX(r0);
+}
+
+__jit_inline jit_insn *
+arm_branch(jit_state_t _jitp, int cc, jit_insn *i0)
+{
+ jit_insn *l;
+ long d;
+
+ l = _jitp->x.pc;
+ d = (((long)i0 - (long)l) >> 2) - 2;
+
+ if (!_jitl.long_jumps && _s24P(d)) {
+ _CC_B(cc, d & 0x00ffffff);
+ } else {
+ int im = (int)i0;
+ if (jit_armv6_p()) {
+ _CC_MOVWI(cc, JIT_TMP, _jit_US(im));
+ _CC_MOVTI(cc, JIT_TMP, _jit_US((unsigned)im >> 16));
+ } else {
+ int q0, q1, q2, q3;
+
+ q0 = im & 0x000000ff; q1 = im & 0x0000ff00;
+ q2 = im & 0x00ff0000; q3 = im & 0xff000000;
+ _CC_MOVI(cc, JIT_TMP, encode_arm_immediate(q3));
+ _CC_ORRI(cc, JIT_TMP, JIT_TMP, encode_arm_immediate(q2));
+ _CC_ORRI(cc, JIT_TMP, JIT_TMP, encode_arm_immediate(q1));
+ _CC_ORRI(cc, JIT_TMP, JIT_TMP, q0);
+ }
+ _CC_MOV(cc, _R15, JIT_TMP);
+ }
+
+ return l;
+}
+
+__jit_inline int invert_cc(int cc)
+{
+ return cc ^ ARM_CC_NE;
+}
+
+__jit_inline jit_insn *
+thumb_branch(jit_state_t _jitp, int cc, jit_insn *i0)
+{
+ jit_insn *l;
+ long d;
+
+ jit_assert((long)i0 & 0x1);
+
+ /* use only thumb2 conditional as does not know if will be patched */
+ l = _jitp->x.pc+1;
+ d = (((long)i0 - (long)l) >> 1) - 2;
+ if (!_jitl.long_jumps && _s20P(d)) {
+ if (cc == ARM_CC_AL)
+ T2_B(encode_thumb_jump(d));
+ else
+ T2_CC_B(cc, encode_thumb_cc_jump(d));
+ } else {
+ jit_assert(_jitl.long_jumps);
+ jit_movi_p(JIT_TMP, i0);
+ if (cc != ARM_CC_AL) {
+ cc = invert_cc(cc);
+ T2_CC_B(cc, 1);
+ }
+ T1_MOV(_R15, JIT_TMP);
+ }
+
+ return l;
+}
+
+#define jit_jmpi(i0) arm_jmpi(_jitp, i0)
+__jit_inline jit_insn *
+arm_jmpi(jit_state_t _jitp, void *i0)
+{
+ jit_insn *l;
+ if (jit_thumb_p()) {
+ l = thumb_branch(_jitp, ARM_CC_AL, i0);
+ }
+ else {
+ l = arm_branch(_jitp, ARM_CC_AL, i0);
+ }
+ return (l);
+}
+
+__jit_inline jit_insn *
+arm_bccr(jit_state_t _jitp, int cc, jit_insn *i0, jit_gpr_t r0, jit_gpr_t r1)
+{
+ jit_insn *l;
+
+ if (jit_thumb_p()) {
+ if ((r0|r1) < 8)
+ T1_CMP(r0, r1);
+ else if ((r0&r1) & 8)
+ T1_CMPX(r0, r1);
+ else
+ T2_CMP(r0, r1);
+ l = thumb_branch(_jitp, cc, i0);
+ }
+ else {
+ _CMP(r0, r1);
+ l = arm_branch(_jitp, cc, i0);
+ }
+ return (l);
+}
+__jit_inline jit_insn *
+arm_bcci(jit_state_t _jitp, int cc, jit_insn *i0, jit_gpr_t r0, int i1)
+{
+ jit_insn *l;
+ int i;
+ if (jit_thumb_p()) {
+ if (r0 < 7 && !(i1 & 0xffffff00))
+ T1_CMPI(r0, i1);
+ else if ((i = encode_thumb_immediate(i1)) != -1)
+ T2_CMPI(r0, i);
+ else if ((i = encode_thumb_immediate(-i1)) != -1)
+ T2_CMNI(r0, i);
+ else {
+ jit_movi_i(JIT_TMP, i1);
+ T2_CMP(r0, JIT_TMP);
+ }
+ l = thumb_branch(_jitp, cc, i0);
+ }
+ else {
+ if ((i = encode_arm_immediate(i1)) != -1)
+ _CMPI(r0, i);
+ else if ((i = encode_arm_immediate(-i1)) != -1)
+ _CMNI(r0, i);
+ else {
+ jit_movi_i(JIT_TMP, i1);
+ _CMP(r0, JIT_TMP);
+ }
+ l = arm_branch(_jitp, cc, i0);
+ }
+ return (l);
+}
+#define jit_bltr_i(i0, r0, r1) arm_bccr(_jitp, ARM_CC_LT, i0, r0, r1)
+#define jit_blti_i(i0, r0, i1) arm_bcci(_jitp, ARM_CC_LT, i0, r0, i1)
+#define jit_bltr_ui(i0, r0, r1) arm_bccr(_jitp, ARM_CC_LO, i0, r0, r1)
+#define jit_blti_ui(i0, r0, i1) arm_bcci(_jitp, ARM_CC_LO, i0, r0, i1)
+#define jit_bler_i(i0, r0, r1) arm_bccr(_jitp, ARM_CC_LE, i0, r0, r1)
+#define jit_blei_i(i0, r0, i1) arm_bcci(_jitp, ARM_CC_LE, i0, r0, i1)
+#define jit_bler_ui(i0, r0, r1) arm_bccr(_jitp, ARM_CC_LS, i0, r0, r1)
+#define jit_blei_ui(i0, r0, i1) arm_bcci(_jitp, ARM_CC_LS, i0, r0, i1)
+#define jit_beqr_i(i0, r0, r1) arm_bccr(_jitp, ARM_CC_EQ, i0, r0, r1)
+#define jit_beqi_i(i0, r0, i1) arm_bcci(_jitp, ARM_CC_EQ, i0, r0, i1)
+#define jit_bger_i(i0, r0, r1) arm_bccr(_jitp, ARM_CC_GE, i0, r0, r1)
+#define jit_bgei_i(i0, r0, i1) arm_bcci(_jitp, ARM_CC_GE, i0, r0, i1)
+#define jit_bger_ui(i0, r0, r1) arm_bccr(_jitp, ARM_CC_HS, i0, r0, r1)
+#define jit_bgei_ui(i0, r0, i1) arm_bcci(_jitp, ARM_CC_HS, i0, r0, i1)
+#define jit_bgtr_i(i0, r0, r1) arm_bccr(_jitp, ARM_CC_GT, i0, r0, r1)
+#define jit_bgti_i(i0, r0, i1) arm_bcci(_jitp, ARM_CC_GT, i0, r0, i1)
+#define jit_bgtr_ui(i0, r0, r1) arm_bccr(_jitp, ARM_CC_HI, i0, r0, r1)
+#define jit_bgti_ui(i0, r0, i1) arm_bcci(_jitp, ARM_CC_HI, i0, r0, i1)
+#define jit_bner_i(i0, r0, r1) arm_bccr(_jitp, ARM_CC_NE, i0, r0, r1)
+#define jit_bnei_i(i0, r0, i1) arm_bcci(_jitp, ARM_CC_NE, i0, r0, i1)
+
+__jit_inline jit_insn *
+arm_baddr(jit_state_t _jitp, int cc, jit_insn *i0, jit_gpr_t r0, jit_gpr_t r1)
+{
+ jit_insn *l;
+
+ if (jit_thumb_p()) {
+ if ((r0|r1) < 8)
+ T1_ADD(r0, r0, r1);
+ else
+ T2_ADDS(r0, r0, r1);
+ l = thumb_branch(_jitp, cc, i0);
+ }
+ else {
+ _ADDS(r0, r0, r1);
+ l = arm_branch(_jitp, cc, i0);
+ }
+ return (l);
+}
+__jit_inline jit_insn *
+arm_baddi(jit_state_t _jitp, int cc, jit_insn *i0, jit_gpr_t r0, int i1)
+{
+ jit_insn *l;
+ int i;
+ if (jit_thumb_p()) {
+ if (r0 < 8 && !(i1 & ~7))
+ T1_ADDI3(r0, r0, i1);
+ else if (r0 < 8 && !(-i1 & ~7))
+ T1_SUBI3(r0, r0, -i1);
+ else if (r0 < 8 && !(i1 & ~0xff))
+ T1_ADDI8(r0, i1);
+ else if (r0 < 8 && !(-i1 & ~0xff))
+ T1_SUBI8(r0, -i1);
+ else if ((i = encode_thumb_immediate(i1)) != -1)
+ T2_ADDSI(r0, r0, i);
+ else if ((i = encode_thumb_immediate(-i1)) != -1)
+ T2_SUBSI(r0, r0, i);
+ else {
+ jit_movi_i(JIT_TMP, i1);
+ T2_ADDS(r0, r0, JIT_TMP);
+ }
+ l = thumb_branch(_jitp, cc, i0);
+ }
+ else {
+ if ((i = encode_arm_immediate(i1)) != -1)
+ _ADDSI(r0, r0, i);
+ else if ((i = encode_arm_immediate(-i1)) != -1)
+ _SUBSI(r0, r0, i);
+ else {
+ jit_movi_i(JIT_TMP, i1);
+ _ADDS(r0, r0, JIT_TMP);
+ }
+ l = arm_branch(_jitp, cc, i0);
+ }
+ return (l);
+}
+#define jit_boaddr_i(i0, r0, r1) arm_baddr(_jitp, ARM_CC_VS, i0, r0, r1)
+#define jit_boaddi_i(i0, r0, i1) arm_baddi(_jitp, ARM_CC_VS, i0, r0, i1)
+#define jit_boaddr_ui(i0, r0, r1) arm_baddr(_jitp, ARM_CC_HS, i0, r0, r1)
+#define jit_boaddi_ui(i0, r0, i1) arm_baddi(_jitp, ARM_CC_HS, i0, r0, i1)
+
+__jit_inline jit_insn *
+arm_bsubr(jit_state_t _jitp, int cc, jit_insn *i0, jit_gpr_t r0, jit_gpr_t r1)
+{
+ jit_insn *l;
+ if (jit_thumb_p()) {
+ if ((r0|r1) < 8)
+ T1_SUB(r0, r0, r1);
+ else
+ T2_SUBS(r0, r0, r1);
+ l = thumb_branch(_jitp, cc, i0);
+ }
+ else {
+ _SUBS(r0, r0, r1);
+ l = arm_branch(_jitp, cc, i0);
+ }
+ return (l);
+}
+
+__jit_inline jit_insn *
+arm_bsubi(jit_state_t _jitp, int cc, jit_insn *i0, jit_gpr_t r0, int i1)
+{
+ jit_insn *l;
+ int i;
+ if (jit_thumb_p()) {
+ if (r0 < 8 && !(i1 & ~7))
+ T1_SUBI3(r0, r0, i1);
+ else if (r0 < 8 && !(-i1 & ~7))
+ T1_ADDI3(r0, r0, -i1);
+ else if (r0 < 8 && !(i1 & ~0xff))
+ T1_SUBI8(r0, i1);
+ else if (r0 < 8 && !(-i1 & ~0xff))
+ T1_ADDI8(r0, -i1);
+ else if ((i = encode_thumb_immediate(i1)) != -1)
+ T2_SUBSI(r0, r0, i);
+ else if ((i = encode_thumb_immediate(-i1)) != -1)
+ T2_ADDSI(r0, r0, i);
+ else {
+ jit_movi_i(JIT_TMP, i1);
+ T2_SUBS(r0, r0, JIT_TMP);
+ }
+ l = thumb_branch(_jitp, cc, i0);
+ }
+ else {
+ if ((i = encode_arm_immediate(i1)) != -1)
+ _SUBSI(r0, r0, i);
+ else if ((i = encode_arm_immediate(-i1)) != -1)
+ _ADDSI(r0, r0, i);
+ else {
+ jit_movi_i(JIT_TMP, i1);
+ _SUBS(r0, r0, JIT_TMP);
+ }
+ l = arm_branch(_jitp, cc, i0);
+ }
+ return (l);
+}
+#define jit_bosubr_i(i0, r0, r1) arm_bsubr(_jitp, ARM_CC_VS, i0, r0, r1)
+#define jit_bosubi_i(i0, r0, i1) arm_bsubi(_jitp, ARM_CC_VS, i0, r0, i1)
+#define jit_bosubr_ui(i0, r0, r1) arm_bsubr(_jitp, ARM_CC_LO, i0, r0, r1)
+#define jit_bosubi_ui(i0, r0, i1) arm_bsubi(_jitp, ARM_CC_LO, i0, r0, i1)
+
+#define jit_bomulr_i(a, r0, r1) arm_bomulr_i(_jitp, a, r0, r0, r1)
+#define jit_bomulr_ui(a, r0, r1) arm_bomulr_i(_jitp, a, r0, r0, r1)
+__jit_inline jit_insn *
+arm_bomulr_i(jit_state_t _jitp, jit_insn *i0, jit_gpr_t r0, jit_gpr_t r1, jit_gpr_t r2)
+{
+ jit_insn *l;
+
+ if (jit_thumb_p()) {
+ T2_SMULL(r0, JIT_TMP, r1, r2);
+ T1_ASRI(JIT_TMP2, r0, 31);
+ T1_CMP(JIT_TMP, JIT_TMP2);
+ l = thumb_branch(_jitp, ARM_CC_NE, i0);
+ } else {
+ if (r0 == r1 && !jit_armv6_p()) {
+ jit_assert(r2 != JIT_TMP);
+ _SMULL(r0, JIT_TMP, r2, r1);
+ }
+ else
+ _SMULL(r0, JIT_TMP, r1, r2);
+ _CC_CMPSH(ARM_CC_AL, JIT_TMP, r0, ARM_ASR, 31);
+ l = arm_branch(_jitp, ARM_CC_NE, i0);
+ }
+
+ return l;
+}
+
+__jit_inline jit_insn *
+arm_bmxr(jit_state_t _jitp, int cc, jit_insn *i0, jit_gpr_t r0, jit_gpr_t r1)
+{
+ jit_insn *l;
+ if (jit_thumb_p()) {
+ if ((r0|r1) < 8)
+ T1_TST(r0, r1);
+ else
+ T2_TST(r0, r1);
+ l = thumb_branch(_jitp, cc, i0);
+ }
+ else {
+ if (jit_armv5_p())
+ _TST(r0, r1);
+ else
+ _ANDS(JIT_TMP, r0, r1);
+ l = arm_branch(_jitp, cc, i0);
+ }
+ return (l);
+}
+__jit_inline jit_insn *
+arm_bmxi(jit_state_t _jitp, int cc, jit_insn *i0, jit_gpr_t r0, int i1)
+{
+ jit_insn *l;
+ int i;
+ if (jit_thumb_p()) {
+ if ((i = encode_thumb_immediate(i1)) != -1)
+ T2_TSTI(r0, i);
+ else {
+ jit_movi_i(JIT_TMP, i1);
+ T2_TST(r0, JIT_TMP);
+ }
+ l = thumb_branch(_jitp, cc, i0);
+ }
+ else {
+ if (jit_armv5_p()) {
+ if ((i = encode_arm_immediate(i1)) != -1)
+ _TSTI(r0, i);
+ else {
+ jit_movi_i(JIT_TMP, i1);
+ _TST(r0, JIT_TMP);
+ }
+ }
+ else {
+ if ((i = encode_arm_immediate(i1)) != -1)
+ _ANDSI(JIT_TMP, r0, i);
+ else if ((i = encode_arm_immediate(~i1)) != -1)
+ _BICSI(JIT_TMP, r0, i);
+ else {
+ jit_movi_i(JIT_TMP, i1);
+ _ANDS(JIT_TMP, r0, JIT_TMP);
+ }
+ }
+ l = arm_branch(_jitp, cc, i0);
+ }
+ return (l);
+}
+#define jit_bmsr_i(i0, r0, r1) arm_bmxr(_jitp, ARM_CC_NE, i0, r0, r1)
+#define jit_bmsi_i(i0, r0, i1) arm_bmxi(_jitp, ARM_CC_NE, i0, r0, i1)
+#define jit_bmcr_i(i0, r0, r1) arm_bmxr(_jitp, ARM_CC_EQ, i0, r0, r1)
+#define jit_bmci_i(i0, r0, i1) arm_bmxi(_jitp, ARM_CC_EQ, i0, r0, i1)
+
+#define jit_ldr_c(r0, r1) arm_ldr_c(_jitp, r0, r1)
+__jit_inline void
+arm_ldr_c(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1)
+{
+ if (jit_thumb_p())
+ T2_LDRSBI(r0, r1, 0);
+ else
+ _LDRSBI(r0, r1, 0);
+}
+
+#define jit_ldi_c(r0, i0) arm_ldi_c(_jitp, r0, i0)
+__jit_inline void
+arm_ldi_c(jit_state_t _jitp, jit_gpr_t r0, void *i0)
+{
+ jit_movi_i(JIT_TMP, (int)i0);
+ if (jit_thumb_p())
+ T2_LDRSBI(r0, JIT_TMP, 0);
+ else
+ _LDRSBI(r0, JIT_TMP, 0);
+}
+
+#define jit_ldxr_c(r0, r1, r2) arm_ldxr_c(_jitp, r0, r1, r2)
+__jit_inline void
+arm_ldxr_c(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, jit_gpr_t r2)
+{
+ if (jit_thumb_p()) {
+ if ((r0|r1|r2) < 8)
+ T1_LDRSB(r0, r1, r2);
+ else
+ T2_LDRSB(r0, r1, r2);
+ }
+ else
+ _LDRSB(r0, r1, r2);
+}
+
+#define jit_ldxi_c(r0, r1, i0) arm_ldxi_c(_jitp, r0, r1, i0)
+__jit_inline void
+arm_ldxi_c(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, int i0)
+{
+ jit_gpr_t reg;
+ if (jit_thumb_p()) {
+ if (i0 >= 0 && i0 <= 255)
+ T2_LDRSBI(r0, r1, i0);
+ else if (i0 < 0 && i0 >= -255)
+ T2_LDRSBIN(r0, r1, -i0);
+ else if (i0 >= 0 && i0 <= 4095)
+ T2_LDRSBWI(r0, r1, i0);
+ else {
+ reg = r0 != r1 ? r0 : JIT_TMP;
+ jit_movi_i(reg, i0);
+ if ((r0|r1|reg) < 8)
+ T1_LDRSB(r0, r1, reg);
+ else
+ T2_LDRSB(r0, r1, reg);
+ }
+ }
+ else {
+ if (i0 >= 0 && i0 <= 255)
+ _LDRSBI(r0, r1, i0);
+ else if (i0 < 0 && i0 >= -255)
+ _LDRSBIN(r0, r1, -i0);
+ else {
+ reg = r0 != r1 ? r0 : JIT_TMP;
+ jit_movi_i(reg, i0);
+ _LDRSB(r0, r1, reg);
+ }
+ }
+}
+
+#define jit_ldr_uc(r0, r1) arm_ldr_uc(_jitp, r0, r1)
+__jit_inline void
+arm_ldr_uc(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1)
+{
+ if (jit_thumb_p())
+ T2_LDRBI(r0, r1, 0);
+ else
+ _LDRBI(r0, r1, 0);
+}
+
+#define jit_ldi_uc(r0, i0) arm_ldi_uc(_jitp, r0, i0)
+__jit_inline void
+arm_ldi_uc(jit_state_t _jitp, jit_gpr_t r0, void *i0)
+{
+ jit_movi_i(JIT_TMP, (int)i0);
+ if (jit_thumb_p())
+ T2_LDRBI(r0, JIT_TMP, 0);
+ else
+ _LDRBI(r0, JIT_TMP, 0);
+}
+
+#define jit_ldxr_uc(r0, r1, r2) arm_ldxr_uc(_jitp, r0, r1, r2)
+__jit_inline void
+arm_ldxr_uc(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, jit_gpr_t r2)
+{
+ if (jit_thumb_p()) {
+ if ((r0|r1|r2) < 8)
+ T1_LDRB(r0, r1, r2);
+ else
+ T2_LDRB(r0, r1, r2);
+ }
+ else
+ _LDRB(r0, r1, r2);
+}
+
+#define jit_ldxi_uc(r0, r1, i0) arm_ldxi_uc(_jitp, r0, r1, i0)
+__jit_inline void
+arm_ldxi_uc(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, int i0)
+{
+ jit_gpr_t reg;
+ if (jit_thumb_p()) {
+ if ((r0|r1) < 8 && i0 >= 0 && i0 < 0x20)
+ T1_LDRBI(r0, r1, i0);
+ else if (i0 >= 0 && i0 <= 255)
+ T2_LDRBI(r0, r1, i0);
+ else if (i0 < 0 && i0 >= -255)
+ T2_LDRBIN(r0, r1, -i0);
+ else if (i0 >= 0 && i0 <= 4095)
+ T2_LDRBWI(r0, r1, i0);
+ else {
+ reg = r0 != r1 ? r0 : JIT_TMP;
+ jit_movi_i(reg, i0);
+ if ((r0|r1|reg) < 8)
+ T1_LDRB(r0, r1, reg);
+ else
+ T2_LDRB(r0, r1, reg);
+ }
+ }
+ else {
+ if (i0 >= 0 && i0 <= 4095)
+ _LDRBI(r0, r1, i0);
+ else if (i0 < 0 && i0 >= -4095)
+ _LDRBIN(r0, r1, -i0);
+ else {
+ reg = r0 != r1 ? r0 : JIT_TMP;
+ jit_movi_i(reg, i0);
+ _LDRB(r0, r1, reg);
+ }
+ }
+}
+
+#define jit_ldr_s(r0, r1) arm_ldr_s(_jitp, r0, r1)
+__jit_inline void
+arm_ldr_s(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1)
+{
+ if (jit_thumb_p())
+ T2_LDRSHI(r0, r1, 0);
+ else
+ _LDRSHI(r0, r1, 0);
+}
+
+#define jit_ldi_s(r0, i0) arm_ldi_s(_jitp, r0, i0)
+__jit_inline void
+arm_ldi_s(jit_state_t _jitp, jit_gpr_t r0, void *i0)
+{
+ jit_movi_i(JIT_TMP, (int)i0);
+ if (jit_thumb_p())
+ T2_LDRSHI(r0, JIT_TMP, 0);
+ else
+ _LDRSHI(r0, JIT_TMP, 0);
+}
+
+#define jit_ldxr_s(r0, r1, r2) arm_ldxr_s(_jitp, r0, r1, r2)
+__jit_inline void
+arm_ldxr_s(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, jit_gpr_t r2)
+{
+ if (jit_thumb_p()) {
+ if ((r0|r1|r2) < 8)
+ T1_LDRSH(r0, r1, r2);
+ else
+ T2_LDRSH(r0, r1, r2);
+ }
+ else
+ _LDRSH(r0, r1, r2);
+}
+
+#define jit_ldxi_s(r0, r1, i0) arm_ldxi_s(_jitp, r0, r1, (int)i0)
+__jit_inline void
+arm_ldxi_s(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, int i0)
+{
+ jit_gpr_t reg;
+ if (jit_thumb_p()) {
+ if (i0 >= 0 && i0 <= 255)
+ T2_LDRSHI(r0, r1, i0);
+ else if (i0 < 0 && i0 >= -255)
+ T2_LDRSHIN(r0, r1, -i0);
+ else if (i0 >= 0 && i0 <= 4095)
+ T2_LDRSHWI(r0, r1, i0);
+ else {
+ reg = r0 != r1 ? r0 : JIT_TMP;
+ jit_movi_i(reg, i0);
+ if ((r0|r1|reg) < 8)
+ T1_LDRSH(r0, r1, reg);
+ else
+ T2_LDRSH(r0, r1, reg);
+ }
+ }
+ else {
+ if (i0 >= 0 && i0 <= 255)
+ _LDRSHI(r0, r1, i0);
+ else if (i0 < 0 && i0 >= -255)
+ _LDRSHIN(r0, r1, -i0);
+ else {
+ reg = r0 != r1 ? r0 : JIT_TMP;
+ jit_movi_i(reg, i0);
+ _LDRSH(r0, r1, reg);
+ }
+ }
+
+}
+#define jit_ldr_us(r0, r1) arm_ldr_us(_jitp, r0, r1)
+__jit_inline void
+arm_ldr_us(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1)
+{
+ if (jit_thumb_p())
+ T2_LDRHI(r0, r1, 0);
+ else
+ _LDRHI(r0, r1, 0);
+}
+
+#define jit_ldi_us(r0, i0) arm_ldi_us(_jitp, r0, i0)
+__jit_inline void
+arm_ldi_us(jit_state_t _jitp, jit_gpr_t r0, void *i0)
+{
+ jit_movi_i(JIT_TMP, (int)i0);
+ if (jit_thumb_p())
+ T2_LDRHI(r0, JIT_TMP, 0);
+ else
+ _LDRHI(r0, JIT_TMP, 0);
+}
+
+#define jit_ldxr_us(r0, r1, r2) arm_ldxr_us(_jitp, r0, r1, r2)
+__jit_inline void
+arm_ldxr_us(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, jit_gpr_t r2)
+{
+ if (jit_thumb_p()) {
+ if ((r0|r1|r2) < 8)
+ T1_LDRH(r0, r1, r2);
+ else
+ T2_LDRH(r0, r1, r2);
+ }
+ else
+ _LDRH(r0, r1, r2);
+}
+
+#define jit_ldxi_us(r0, r1, i0) arm_ldxi_us(_jitp, r0, r1, i0)
+__jit_inline void
+arm_ldxi_us(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, int i0)
+{
+ jit_gpr_t reg;
+ if (jit_thumb_p()) {
+ if ((r0|r1) < 8 && i0 >= 0 && !(i0 & 1) && (i0 >> 1) < 0x20)
+ T1_LDRHI(r0, r1, i0 >> 1);
+ else if (i0 >= 0 && i0 <= 255)
+ T2_LDRHI(r0, r1, i0);
+ else if (i0 < 0 && i0 >= -255)
+ T2_LDRHIN(r0, r1, -i0);
+ else if (i0 >= 0 && i0 <= 4095)
+ T2_LDRHWI(r0, r1, i0);
+ else {
+ reg = r0 != r1 ? r0 : JIT_TMP;
+ jit_movi_i(reg, i0);
+ if ((r0|r1|reg) < 8)
+ T1_LDRH(r0, r1, reg);
+ else
+ T2_LDRH(r0, r1, reg);
+ }
+ }
+ else {
+ if (i0 >= 0 && i0 <= 255)
+ _LDRHI(r0, r1, i0);
+ else if (i0 < 0 && i0 >= -255)
+ _LDRHIN(r0, r1, -i0);
+ else {
+ reg = r0 != r1 ? r0 : JIT_TMP;
+ jit_movi_i(reg, i0);
+ _LDRH(r0, r1, reg);
+ }
+ }
+}
+
+#define jit_ldr_i(r0, r1) arm_ldr_i(_jitp, r0, r1)
+__jit_inline void
+arm_ldr_i(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1)
+{
+ if (jit_thumb_p())
+ T2_LDRI(r0, r1, 0);
+ else
+ _LDRI(r0, r1, 0);
+}
+
+#define jit_ldi_i(r0, i0) arm_ldi_i(_jitp, r0, i0)
+__jit_inline void
+arm_ldi_i(jit_state_t _jitp, jit_gpr_t r0, void *i0)
+{
+ jit_movi_i(JIT_TMP, (int)i0);
+ if (jit_thumb_p())
+ T2_LDRI(r0, JIT_TMP, 0);
+ else
+ _LDRI(r0, JIT_TMP, 0);
+}
+
+#define jit_ldxr_i(r0, r1, r2) arm_ldxr_i(_jitp, r0, r1, r2)
+__jit_inline void
+arm_ldxr_i(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, jit_gpr_t r2)
+{
+ if (jit_thumb_p()) {
+ if ((r0|r1|r2) < 8)
+ T1_LDR(r0, r1, r2);
+ else
+ T2_LDR(r0, r1, r2);
+ }
+ else
+ _LDR(r0, r1, r2);
+}
+
+#define jit_ldxi_i(r0, r1, i0) arm_ldxi_i(_jitp, r0, r1, (int)i0)
+__jit_inline void
+arm_ldxi_i(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, int i0)
+{
+ jit_gpr_t reg;
+ if (jit_thumb_p()) {
+ if ((r0|r1) < 8 && i0 >= 0 && !(i0 & 3) && (i0 >> 2) < 0x20)
+ T1_LDRI(r0, r1, i0 >> 2);
+ else if (r1 == _R13 && r0 < 8 &&
+ i0 >= 0 && !(i0 & 3) && (i0 >> 2) <= 255)
+ T1_LDRISP(r0, i0 >> 2);
+ else if (i0 >= 0 && i0 <= 255)
+ T2_LDRI(r0, r1, i0);
+ else if (i0 < 0 && i0 >= -255)
+ T2_LDRIN(r0, r1, -i0);
+ else if (i0 >= 0 && i0 <= 4095)
+ T2_LDRWI(r0, r1, i0);
+ else {
+ reg = r0 != r1 ? r0 : JIT_TMP;
+ jit_movi_i(reg, i0);
+ if ((r0|r1|reg) < 8)
+ T1_LDR(r0, r1, reg);
+ else
+ T2_LDR(r0, r1, reg);
+ }
+ }
+ else {
+ if (i0 >= 0 && i0 <= 4095)
+ _LDRI(r0, r1, i0);
+ else if (i0 < 0 && i0 >= -4095)
+ _LDRIN(r0, r1, -i0);
+ else {
+ reg = r0 != r1 ? r0 : JIT_TMP;
+ jit_movi_i(reg, i0);
+ _LDR(r0, r1, reg);
+ }
+ }
+}
+
+#define jit_str_c(r0, r1) arm_str_c(_jitp, r0, r1)
+__jit_inline void
+arm_str_c(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1)
+{
+ if (jit_thumb_p())
+ T2_STRBI(r1, r0, 0);
+ else
+ _STRBI(r1, r0, 0);
+}
+
+#define jit_sti_c(r0, i0) arm_sti_c(_jitp, r0, i0)
+__jit_inline void
+arm_sti_c(jit_state_t _jitp, void *i0, jit_gpr_t r0)
+{
+ jit_movi_i(JIT_TMP, (int)i0);
+ if (jit_thumb_p())
+ T2_STRBI(r0, JIT_TMP, 0);
+ else
+ _STRBI(r0, JIT_TMP, 0);
+}
+
+#define jit_stxr_c(r0, r1, r2) arm_stxr_c(_jitp, r0, r1, r2)
+__jit_inline void
+arm_stxr_c(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, jit_gpr_t r2)
+{
+ if (jit_thumb_p()) {
+ if ((r0|r1|r2) < 8)
+ T1_STRB(r2, r1, r0);
+ else
+ T2_STRB(r2, r1, r0);
+ }
+ else
+ _STRB(r2, r1, r0);
+}
+
+#define jit_stxi_c(r0, r1, i0) arm_stxi_c(_jitp, r0, r1, i0)
+__jit_inline void
+arm_stxi_c(jit_state_t _jitp, int i0, jit_gpr_t r0, jit_gpr_t r1)
+{
+ if (jit_thumb_p()) {
+ if ((r0|r1) < 8 && i0 >= 0 && i0 < 0x20)
+ T1_STRBI(r1, r0, i0);
+ else if (i0 >= 0 && i0 <= 255)
+ T2_STRBI(r1, r0, i0);
+ else if (i0 < 0 && i0 >= -255)
+ T2_STRBIN(r1, r0, -i0);
+ else if (i0 >= 0 && i0 <= 4095)
+ T2_STRBWI(r1, r0, i0);
+ else {
+ jit_movi_i(JIT_TMP, (int)i0);
+ if ((r0|r1|JIT_TMP) < 8)
+ T1_STRB(r1, r0, JIT_TMP);
+ else
+ T2_STRB(r1, r0, JIT_TMP);
+ }
+ }
+ else {
+ if (i0 >= 0 && i0 <= 4095)
+ _STRBI(r1, r0, i0);
+ else if (i0 < 0 && i0 >= -4095)
+ _STRBIN(r1, r0, -i0);
+ else {
+ jit_movi_i(JIT_TMP, i0);
+ _STRB(r1, r0, JIT_TMP);
+ }
+ }
+}
+
+#define jit_str_s(r0, r1) arm_str_s(_jitp, r0, r1)
+__jit_inline void
+arm_str_s(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1)
+{
+ if (jit_thumb_p())
+ T2_STRHI(r1, r0, 0);
+ else
+ _STRHI(r1, r0, 0);
+}
+
+#define jit_sti_s(r0, i0) arm_sti_s(_jitp, r0, i0)
+__jit_inline void
+arm_sti_s(jit_state_t _jitp, void *i0, jit_gpr_t r0)
+{
+ jit_movi_i(JIT_TMP, (int)i0);
+ if (jit_thumb_p())
+ T2_STRHI(r0, JIT_TMP, 0);
+ else
+ _STRHI(r0, JIT_TMP, 0);
+}
+
+#define jit_stxr_s(r0, r1, r2) arm_stxr_s(_jitp, r0, r1, r2)
+__jit_inline void
+arm_stxr_s(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, jit_gpr_t r2)
+{
+ if (jit_thumb_p()) {
+ if ((r0|r1|r2) < 8)
+ T1_STRH(r2, r1, r0);
+ else
+ T2_STRH(r2, r1, r0);
+ }
+ else
+ _STRH(r2, r1, r0);
+}
+
+#define jit_stxi_s(r0, r1, i0) arm_stxi_s(_jitp, (int)r0, r1, i0)
+__jit_inline void
+arm_stxi_s(jit_state_t _jitp, int i0, jit_gpr_t r0, jit_gpr_t r1)
+{
+ if (jit_thumb_p()) {
+ if ((r0|r1) < 8 && i0 >= 0 && !(i0 & 1) && (i0 >> 1) < 0x20)
+ T1_STRHI(r1, r0, i0 >> 1);
+ else if (i0 >= 0 && i0 <= 255)
+ T2_STRHI(r1, r0, i0);
+ else if (i0 < 0 && i0 >= -255)
+ T2_STRHIN(r1, r0, -i0);
+ else if (i0 >= 0 && i0 <= 4095)
+ T2_STRHWI(r1, r0, i0);
+ else {
+ jit_movi_i(JIT_TMP, (int)i0);
+ if ((r0|r1|JIT_TMP) < 8)
+ T1_STRH(r1, r0, JIT_TMP);
+ else
+ T2_STRH(r1, r0, JIT_TMP);
+ }
+ }
+ else {
+ if (i0 >= 0 && i0 <= 255)
+ _STRHI(r1, r0, i0);
+ else if (i0 < 0 && i0 >= -255)
+ _STRHIN(r1, r0, -i0);
+ else {
+ jit_movi_i(JIT_TMP, i0);
+ _STRH(r1, r0, JIT_TMP);
+ }
+ }
+}
+
+#define jit_str_i(r0, r1) arm_str_i(_jitp, r0, r1)
+__jit_inline void
+arm_str_i(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1)
+{
+ if (jit_thumb_p())
+ T2_STRI(r1, r0, 0);
+ else
+ _STRI(r1, r0, 0);
+}
+
+#define jit_sti_i(r0, i0) arm_sti_i(_jitp, r0, i0)
+__jit_inline void
+arm_sti_i(jit_state_t _jitp, void *i0, jit_gpr_t r0)
+{
+ jit_movi_i(JIT_TMP, (int)i0);
+ if (jit_thumb_p())
+ T2_STRI(r0, JIT_TMP, 0);
+ else
+ _STRI(r0, JIT_TMP, 0);
+}
+
+#define jit_stxr_i(r0, r1, r2) arm_stxr_i(_jitp, r0, r1, r2)
+__jit_inline void
+arm_stxr_i(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, jit_gpr_t r2)
+{
+ if (jit_thumb_p()) {
+ if ((r0|r1|r2) < 8)
+ T1_STR(r2, r1, r0);
+ else
+ T2_STR(r2, r1, r0);
+ }
+ else
+ _STR(r2, r1, r0);
+}
+
+#define jit_stxi_i(r0, r1, i0) arm_stxi_i(_jitp, (int)r0, r1, i0)
+__jit_inline void
+arm_stxi_i(jit_state_t _jitp, int i0, jit_gpr_t r0, jit_gpr_t r1)
+{
+ if (jit_thumb_p()) {
+ if ((r0|r1) < 8 && i0 >= 0 && !(i0 & 3) && (i0 >> 2) < 0x20)
+ T1_STRI(r1, r0, i0 >> 2);
+ else if (r0 == _R13 && r1 < 8 &&
+ i0 >= 0 && !(i0 & 3) && (i0 >> 2) <= 255)
+ T1_STRISP(r1, i0 >> 2);
+ else if (i0 >= 0 && i0 <= 255)
+ T2_STRI(r1, r0, i0);
+ else if (i0 < 0 && i0 >= -255)
+ T2_STRIN(r1, r0, -i0);
+ else if (i0 >= 0 && i0 <= 4095)
+ T2_STRWI(r1, r0, i0);
+ else {
+ jit_movi_i(JIT_TMP, (int)i0);
+ if ((r0|r1|JIT_TMP) < 8)
+ T1_STR(r1, r0, JIT_TMP);
+ else
+ T2_STR(r1, r0, JIT_TMP);
+ }
+ }
+ else {
+ if (i0 >= 0 && i0 <= 4095)
+ _STRI(r1, r0, i0);
+ else if (i0 < 0 && i0 >= -4095)
+ _STRIN(r1, r0, -i0);
+ else {
+ jit_movi_i(JIT_TMP, i0);
+ _STR(r1, r0, JIT_TMP);
+ }
+ }
+}
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+/* inline glibc htons (without register clobber) */
+#define jit_ntoh_us(r0, r1) arm_ntoh_us(_jitp, r0, r1)
+__jit_inline void
+arm_ntoh_us(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1)
+{
+ if (jit_thumb_p()) {
+ if ((r0|r1) < 8)
+ T1_REV16(r0, r1);
+ else
+ T2_REV16(r0, r1);
+ }
+ else {
+ if (jit_armv6_p())
+ _REV16(r0, r1);
+ else {
+ _LSLI(JIT_TMP, r1, 24);
+ _LSRI(r0, r1, 8);
+ _ORR_SI(r0, r0, JIT_TMP, ARM_LSR, 16);
+ }
+ }
+}
+
+/* inline glibc htonl (without register clobber) */
+#define jit_ntoh_ui(r0, r1) arm_ntoh_ui(_jitp, r0, r1)
+__jit_inline void
+arm_ntoh_ui(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1)
+{
+ if (jit_thumb_p()) {
+ if ((r0|r1) < 8)
+ T1_REV(r0, r1);
+ else
+ T2_REV(r0, r1);
+ }
+ else {
+ if (jit_armv6_p())
+ _REV(r0, r1);
+ else {
+ _EOR_SI(JIT_TMP, r1, r1, ARM_ROR, 16);
+ _LSRI(JIT_TMP, JIT_TMP, 8);
+ _BICI(JIT_TMP, JIT_TMP, encode_arm_immediate(0xff00));
+ _EOR_SI(r0, JIT_TMP, r1, ARM_ROR, 8);
+ }
+ }
+}
+#endif
+
+#define jit_extr_c_i(r0, r1) arm_extr_c_i(_jitp, r0, r1)
+__jit_inline void
+arm_extr_c_i(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1)
+{
+ if (jit_thumb_p()) {
+ if ((r0|r1) < 8)
+ T1_SXTB(r0, r1);
+ else
+ T2_SXTB(r0, r1);
+ }
+ else {
+ if (jit_armv6_p())
+ _SXTB(r0, r1);
+ else {
+ _LSLI(r0, r1, 24);
+ _ASRI(r0, r0, 24);
+ }
+ }
+}
+
+#define jit_extr_c_ui(r0, r1) arm_extr_c_ui(_jitp, r0, r1)
+__jit_inline void
+arm_extr_c_ui(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1)
+{
+ if (jit_thumb_p()) {
+ if ((r0|r1) < 8)
+ T1_UXTB(r0, r1);
+ else
+ T2_UXTB(r0, r1);
+ }
+ else {
+ if (jit_armv6_p())
+ _UXTB(r0, r1);
+ else
+ _ANDI(r0, r1, 0xff);
+ }
+}
+
+#define jit_extr_s_i(r0, r1) arm_extr_s_i(_jitp, r0, r1)
+__jit_inline void
+arm_extr_s_i(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1)
+{
+ if (jit_thumb_p()) {
+ if ((r0|r1) < 8)
+ T1_SXTH(r0, r1);
+ else
+ T2_SXTH(r0, r1);
+ }
+ else {
+ if (jit_armv6_p())
+ _SXTH(r0, r1);
+ else {
+ _LSLI(r0, r1, 16);
+ _ASRI(r0, r0, 16);
+ }
+ }
+}
+
+#define jit_extr_s_ui(r0, r1) arm_extr_s_ui(_jitp, r0, r1)
+__jit_inline void
+arm_extr_s_ui(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1)
+{
+ if (jit_thumb_p()) {
+ if ((r0|r1) < 8)
+ T1_UXTH(r0, r1);
+ else
+ T2_UXTH(r0, r1);
+ }
+ else {
+ if (jit_armv6_p())
+ _UXTH(r0, r1);
+ else {
+ /* _ANDI(r0, r1, 0xffff) needs more instructions */
+ _LSLI(r0, r1, 16);
+ _LSRI(r0, r0, 16);
+ }
+ }
+}
+
+#define JIT_NEXT_FP_OFFSET 8
+#define JIT_FRAME_EXTRA_SPACE 16
+#define JIT_FRAME_EXTRA_SPACE_OFFSET (-JIT_FRAME_EXTRA_SPACE)
+#define JIT_ARG_STACK_OFFSET 0
+
+#define jit_prolog(n) arm_prolog(_jitp, n)
+__jit_inline void
+arm_prolog(jit_state_t _jitp, int i0)
+{
+ if (jit_thumb_p()) {
+ T2_PUSH(/* arguments (should keep state and only save "i0" registers) */
+ (1<<_R0)|(1<<_R1)|(1<<_R2)|(1<<_R3)|
+ (1<<_R4)|(1<<_R5)|(1<<_R6)|(1<<_R7)|
+ /* previous fp and return address */
+ (1<x.pc;
+ jit_movi_p(JIT_TMP, i0);
+ if (jit_thumb_p()) {
+ l++;
+ T1_BLX(JIT_TMP);
+ } else
+ _BLX(JIT_TMP);
+ return (l);
+}
+
+#define jit_prepare_i(i0) arm_prepare_i(_jitp, i0)
+__jit_inline void
+arm_prepare_i(jit_state_t _jitp, int i0)
+{
+ jit_assert(i0 >= 0 && !_jitl.nextarg_put);
+}
+
+#define jit_arg_c() arm_arg_i(_jitp)
+#define jit_arg_uc() arm_arg_i(_jitp)
+#define jit_arg_s() arm_arg_i(_jitp)
+#define jit_arg_us() arm_arg_i(_jitp)
+#define jit_arg_i() arm_arg_i(_jitp)
+#define jit_arg_ui() arm_arg_i(_jitp)
+#define jit_arg_l() arm_arg_i(_jitp)
+#define jit_arg_ul() arm_arg_i(_jitp)
+#define jit_arg_p() arm_arg_i(_jitp)
+__jit_inline int
+arm_arg_i(jit_state_t _jitp)
+{
+ int ofs = _jitl.nextarg_get++;
+ return (ofs);
+}
+
+#define jit_getarg_c(r0, i0) arm_getarg_c(_jitp, r0, i0)
+__jit_inline void
+arm_getarg_c(jit_state_t _jitp, jit_gpr_t r0, int i0)
+{
+ if (i0 < 4)
+ i0 <<= 2;
+#if __BYTE_ORDER == __BIG_ENDIAN
+ i0 += sizeof(int) - sizeof(char);
+#endif
+ jit_ldxi_c(r0, JIT_FP, i0);
+}
+
+#define jit_getarg_uc(r0, i0) arm_getarg_uc(_jitp, r0, i0)
+__jit_inline void
+arm_getarg_uc(jit_state_t _jitp, jit_gpr_t r0, int i0)
+{
+ if (i0 < 4)
+ i0 <<= 2;
+#if __BYTE_ORDER == __BIG_ENDIAN
+ i0 += sizeof(int) - sizeof(char);
+#endif
+ jit_ldxi_uc(r0, JIT_FP, i0);
+}
+
+#define jit_getarg_s(r0, i0) arm_getarg_s(_jitp, r0, i0)
+__jit_inline void
+arm_getarg_s(jit_state_t _jitp, jit_gpr_t r0, int i0)
+{
+ if (i0 < 4)
+ i0 <<= 2;
+#if __BYTE_ORDER == __BIG_ENDIAN
+ i0 += sizeof(int) - sizeof(short);
+#endif
+ jit_ldxi_s(r0, JIT_FP, i0);
+}
+
+#define jit_getarg_us(r0, i0) arm_getarg_us(_jitp, r0, i0)
+__jit_inline void
+arm_getarg_us(jit_state_t _jitp, jit_gpr_t r0, int i0)
+{
+ if (i0 < 4)
+ i0 <<= 2;
+#if __BYTE_ORDER == __BIG_ENDIAN
+ i0 += sizeof(int) - sizeof(short);
+#endif
+ jit_ldxi_us(r0, JIT_FP, i0);
+}
+
+#define jit_getarg_i(r0, i0) arm_getarg_i(_jitp, r0, i0)
+#define jit_getarg_ui(r0, i0) arm_getarg_i(_jitp, r0, i0)
+#define jit_getarg_l(r0, i0) arm_getarg_i(_jitp, r0, i0)
+#define jit_getarg_ul(r0, i0) arm_getarg_i(_jitp, r0, i0)
+#define jit_getarg_p(r0, i0) arm_getarg_i(_jitp, r0, i0)
+__jit_inline void
+arm_getarg_i(jit_state_t _jitp, jit_gpr_t r0, int i0)
+{
+ /* arguments are saved in prolog */
+ if (i0 < 4)
+ i0 <<= 2;
+ jit_ldxi_i(r0, JIT_FP, i0);
+}
+
+#define jit_pusharg_i(r0) arm_pusharg_i(_jitp, r0)
+__jit_inline void
+arm_pusharg_i(jit_state_t _jitp, jit_gpr_t r0)
+{
+ int ofs = _jitl.nextarg_put++;
+ jit_stxi_i((ofs <<2) + JIT_ARG_STACK_OFFSET, JIT_FP, r0);
+}
+
+#define jit_normal_pushonlyarg_i(r0) arm_normal_pushonlyarg_i(_jitp, r0)
+__jit_inline void
+arm_normal_pushonlyarg_i(jit_state_t _jitp, jit_gpr_t r0)
+{
+ jit_movr_i(JIT_R0, r0);
+}
+
+static void
+arm_patch_arguments(jit_state_t _jitp)
+{
+ int ofs = _jitl.nextarg_put;
+ int reg = 0;
+ _jitl.nextarg_put = 0;
+ while (ofs) {
+ --ofs;
+ jit_ldxi_i(JIT_R(reg), JIT_FP, (ofs <<2) + JIT_ARG_STACK_OFFSET);
+ reg++;
+ }
+}
+
+#define jit_finishr(rs) arm_finishr(_jitp, rs)
+__jit_inline void
+arm_finishr(jit_state_t _jitp, jit_gpr_t r0)
+{
+ if (r0 < 4) {
+ jit_movr_i(JIT_TMP, r0);
+ r0 = JIT_TMP;
+ }
+ arm_patch_arguments(_jitp);
+ jit_callr(r0);
+}
+
+#define jit_finish(i0) arm_finishi(_jitp, i0)
+__jit_inline jit_insn *
+arm_finishi(jit_state_t _jitp, void *i0)
+{
+ arm_patch_arguments(_jitp);
+ return (jit_calli(i0));
+}
+
+#define jit_normal_finish(i0) arm_normal_finishi(_jitp, i0)
+__jit_inline jit_insn *
+arm_normal_finishi(jit_state_t _jitp, void *i0)
+{
+ return (jit_calli(i0));
+}
+
+#define jit_retval_i(r0) jit_movr_i(r0, JIT_RET)
+#define jit_ret() arm_ret(_jitp)
+__jit_inline void
+arm_ret(jit_state_t _jitp)
+{
+ /* do not restore arguments */
+ jit_addi_i(JIT_SP, JIT_FP, 16);
+ if (jit_thumb_p())
+ T2_POP(/* callee save */
+ (1<<_R4)|(1<<_R5)|(1<<_R6)|(1<<_R7)|
+ /* previous fp and return address */
+ (1<x.pc & 2))
+ T1_NOP();
+}
+
+# define jit_pushr_i(r0) arm_pushr_i(_jitp, r0)
+__jit_inline void
+arm_pushr_i(jit_state_t _jitp, jit_gpr_t r0)
+{
+ _PUSH(1<
+
+#define swf_off(rn) (-JIT_FRAME_EXTRA_SPACE_OFFSET + ((rn) << 2))
+
+extern float __addsf3(float, float);
+extern double __adddf3(double, double);
+extern float __aeabi_fsub(float, float);
+extern double __aeabi_dsub(double, double);
+extern float __aeabi_fmul(float, float);
+extern double __aeabi_dmul(double, double);
+extern float __aeabi_fdiv(float, float);
+extern double __aeabi_ddiv(double, double);
+extern float __aeabi_i2f(int);
+extern double __aeabi_i2d(int);
+extern float __aeabi_d2f(double);
+extern double __aeabi_f2d(float);
+extern int __aeabi_f2iz(double);
+extern int __aeabi_d2iz(float);
+extern int __aeabi_fcmplt(float, float);
+extern int __aeabi_dcmplt(double, double);
+extern int __aeabi_fcmple(float, float);
+extern int __aeabi_dcmple(double, double);
+extern int __aeabi_fcmpeq(float, float);
+extern int __aeabi_dcmpeq(double, double);
+extern int __aeabi_fcmpge(float, float);
+extern int __aeabi_dcmpge(double, double);
+extern int __aeabi_fcmpgt(float, float);
+extern int __aeabi_dcmpgt(double, double);
+extern int __aeabi_fcmpun(float, float);
+extern int __aeabi_dcmpun(double, double);
+
+#define swf_call(function, label) \
+ do { \
+ int d; \
+ if (!jit_exchange_p()) { \
+ if (jit_thumb_p()) \
+ d = (((int)function - (int)_jitp->x.pc) >> 1) - 2; \
+ else \
+ d = (((int)function - (int)_jitp->x.pc) >> 2) - 2; \
+ if (_s24P(d)) { \
+ if (jit_thumb_p()) \
+ T2_BLI(encode_thumb_jump(d)); \
+ else \
+ _BLI(d & 0x00ffffff); \
+ } \
+ else \
+ goto label; \
+ } \
+ else { \
+ label: \
+ jit_movi_i(JIT_FTMP, (int)function); \
+ if (jit_thumb_p()) \
+ T1_BLX(JIT_FTMP); \
+ else \
+ _BLX(JIT_FTMP); \
+ } \
+ } while (0)
+#define swf_ldrin(rt, rn, im) \
+ do { \
+ if (jit_thumb_p()) T2_LDRIN(rt, rn, im); \
+ else _LDRIN(rt, rn, im); \
+ } while (0)
+#define swf_strin(rt, rn, im) \
+ do { \
+ if (jit_thumb_p()) T2_STRIN(rt, rn, im); \
+ else _STRIN(rt, rn, im); \
+ } while (0)
+#define swf_push(mask) \
+ do { \
+ if (jit_thumb_p()) T1_PUSH(mask); \
+ else _PUSH(mask); \
+ } while (0)
+#define swf_pop(mask) \
+ do { \
+ if (jit_thumb_p()) T1_POP(mask); \
+ else _POP(mask); \
+ } while (0)
+#define swf_bici(rt, rn, im) \
+ do { \
+ if (jit_thumb_p()) \
+ T2_BICI(rt, rn, encode_thumb_immediate(im)); \
+ else \
+ _BICI(rt, rn, encode_arm_immediate(im)); \
+ } while (0)
+
+__jit_inline void
+swf_movr_f(jit_state_t _jitp, jit_fpr_t r0, jit_fpr_t r1)
+{
+ if (r0 != r1) {
+ if (r0 == JIT_FPRET)
+ /* jit_ret() must follow! */
+ swf_ldrin(_R0, JIT_FP, swf_off(r1) + 8);
+ else {
+ swf_ldrin(JIT_FTMP, JIT_FP, swf_off(r1) + 8);
+ swf_strin(JIT_FTMP, JIT_FP, swf_off(r0) + 8);
+ }
+ }
+}
+
+__jit_inline void
+swf_movr_d(jit_state_t _jitp, jit_fpr_t r0, jit_fpr_t r1)
+{
+ if (r0 != r1) {
+ if (!jit_thumb_p() && jit_armv5e_p()) {
+ if (r0 == JIT_FPRET)
+ /* jit_ret() must follow! */
+ _LDRDIN(_R0, JIT_FP, swf_off(r1) + 8);
+ else {
+ _LDRDIN(JIT_TMP, JIT_FP, swf_off(r1) + 8);
+ _STRDIN(JIT_TMP, JIT_FP, swf_off(r0) + 8);
+ }
+ }
+ else {
+ if (r0 == JIT_FPRET) {
+ /* jit_ret() must follow! */
+ swf_ldrin(_R0, JIT_FP, swf_off(r1) + 8);
+ swf_ldrin(_R1, JIT_FP, swf_off(r1) + 4);
+ }
+ else {
+ swf_ldrin(JIT_TMP, JIT_FP, swf_off(r1) + 8);
+ swf_ldrin(JIT_FTMP, JIT_FP, swf_off(r1) + 4);
+ swf_strin(JIT_TMP, JIT_FP, swf_off(r0) + 8);
+ swf_strin(JIT_FTMP, JIT_FP, swf_off(r0) + 4);
+ }
+ }
+ }
+}
+
+__jit_inline void
+swf_movi_f(jit_state_t _jitp, jit_fpr_t r0, float i0)
+{
+ union {
+ int i;
+ float f;
+ } u;
+ u.f = i0;
+ if (r0 == JIT_FPRET)
+ /* jit_ret() must follow! */
+ jit_movi_i(_R0, u.i);
+ else {
+ jit_movi_i(JIT_FTMP, u.i);
+ swf_strin(JIT_FTMP, JIT_FP, swf_off(r0) + 8);
+ }
+}
+
+__jit_inline void
+swf_movi_d(jit_state_t _jitp, jit_fpr_t r0, double i0)
+{
+ union {
+ int i[2];
+ double d;
+ } u;
+ u.d = i0;
+ if (r0 == JIT_FPRET) {
+ /* jit_ret() must follow! */
+ jit_movi_i(_R0, u.i[0]);
+ jit_movi_i(_R1, u.i[1]);
+ }
+ else {
+ jit_movi_i(JIT_FTMP, u.i[0]);
+ swf_strin(JIT_FTMP, JIT_FP, swf_off(r0) + 8);
+ jit_movi_i(JIT_FTMP, u.i[1]);
+ swf_strin(JIT_FTMP, JIT_FP, swf_off(r0) + 4);
+ }
+}
+
+__jit_inline void
+swf_extr_i_f(jit_state_t _jitp, jit_fpr_t r0, jit_gpr_t r1)
+{
+ swf_push(0xf);
+ if (r1 != _R0)
+ jit_movr_i(_R0, r1);
+ swf_call(__aeabi_i2f, i2f);
+ swf_strin(_R0, JIT_FP, swf_off(r0) + 8);
+ swf_pop(0xf);
+}
+
+__jit_inline void
+swf_extr_i_d(jit_state_t _jitp, jit_fpr_t r0, jit_gpr_t r1)
+{
+ swf_push(0xf);
+ if (r1 != _R0)
+ jit_movr_i(_R0, r1);
+ swf_call(__aeabi_i2d, i2d);
+ if (!jit_thumb_p() && jit_armv5e_p())
+ _STRDIN(_R0, JIT_FP, swf_off(r0) + 8);
+ else {
+ swf_strin(_R0, JIT_FP, swf_off(r0) + 8);
+ swf_strin(_R1, JIT_FP, swf_off(r0) + 4);
+ }
+ swf_pop(0xf);
+}
+
+__jit_inline void
+swf_extr_d_f(jit_state_t _jitp, jit_fpr_t r0, jit_fpr_t r1)
+{
+ swf_push(0xf);
+ if (!jit_thumb_p() && jit_armv5e_p())
+ _LDRDIN(_R0, JIT_FP, swf_off(r1) + 8);
+ else {
+ swf_ldrin(_R0, JIT_FP, swf_off(r1) + 8);
+ swf_ldrin(_R1, JIT_FP, swf_off(r1) + 4);
+ }
+ swf_call(__aeabi_d2f, d2f);
+ swf_strin(_R0, JIT_FP, swf_off(r0) + 8);
+ swf_pop(0xf);
+}
+
+__jit_inline void
+swf_extr_f_d(jit_state_t _jitp, jit_fpr_t r0, jit_fpr_t r1)
+{
+ swf_push(0xf);
+ swf_ldrin(_R0, JIT_FP, swf_off(r1) + 8);
+ swf_call(__aeabi_f2d, f2d);
+ if (!jit_thumb_p() && jit_armv5e_p())
+ _STRDIN(_R0, JIT_FP, swf_off(r0) + 8);
+ else {
+ swf_strin(_R0, JIT_FP, swf_off(r0) + 8);
+ swf_strin(_R1, JIT_FP, swf_off(r0) + 4);
+ }
+ swf_pop(0xf);
+}
+
+__jit_inline void
+swf_if(jit_state_t _jitp, float (*i0)(float), jit_gpr_t r0, jit_fpr_t r1)
+{
+ int l;
+#if !NAN_TO_INT_IS_ZERO
+ jit_insn *is_nan;
+ jit_insn *fast_not_nan;
+ jit_insn *slow_not_nan;
+#endif
+ l = 0xf;
+ if ((int)r0 < 4)
+ /* bogus extra push to align at 8 bytes */
+ l = (l & ~(1 << r0)) | 0x10;
+ swf_push(l);
+ swf_ldrin(_R0, JIT_FP, swf_off(r1) + 8);
+#if !NAN_TO_INT_IS_ZERO
+ /* >> based on fragment of __aeabi_fcmpun */
+ jit_lshi_i(JIT_FTMP, _R0, 1);
+ if (jit_thumb_p())
+ torrrs(THUMB2_MVN|ARM_S, _R0, JIT_TMP, JIT_FTMP,
+ encode_thumb_shift(24, ARM_ASR));
+ else
+ corrrs(ARM_CC_AL,ARM_MVN|ARM_S|ARM_ASR, _R0, JIT_TMP, JIT_FTMP, 24);
+ fast_not_nan = _jitp->x.pc;
+ if (jit_thumb_p()) {
+ T2_CC_B(ARM_CC_NE, 0);
+ tshift(THUMB2_LSLI|ARM_S, _R0, JIT_TMP, 9);
+ }
+ else {
+ _CC_B(ARM_CC_NE, 0);
+ cshift(ARM_CC_AL, ARM_S|ARM_LSL, _R0, JIT_TMP, _R0, 9);
+ }
+ slow_not_nan = _jitp->x.pc;
+ if (jit_thumb_p())
+ T2_CC_B(ARM_CC_EQ, 0);
+ else
+ _CC_B(ARM_CC_EQ, 0);
+ jit_movi_i(r0, 0x80000000);
+ is_nan = _jitp->x.pc;
+ if (jit_thumb_p())
+ T2_B(0);
+ else
+ _B(ARM_CC_AL, 0);
+ jit_patch(fast_not_nan);
+ jit_patch(slow_not_nan);
+ /* << based on fragment of __aeabi_fcmpun */
+#endif
+ if (i0)
+ swf_call(i0, fallback);
+ swf_call(__aeabi_f2iz, f2iz);
+ jit_movr_i(r0, _R0);
+#if !NAN_TO_INT_IS_ZERO
+ jit_patch(is_nan);
+#endif
+ swf_pop(l);
+}
+
+__jit_inline void
+swf_id(jit_state_t _jitp, double (*i0)(double), jit_gpr_t r0, jit_fpr_t r1)
+{
+ int l;
+#if !NAN_TO_INT_IS_ZERO
+ jit_insn *is_nan;
+ jit_insn *fast_not_nan;
+ jit_insn *slow_not_nan;
+#endif
+ l = 0xf;
+ if ((int)r0 < 4)
+ /* bogus extra push to align at 8 bytes */
+ l = (l & ~(1 << r0)) | 0x10;
+ swf_push(l);
+ if (!jit_thumb_p() && jit_armv5e_p())
+ _LDRDIN(_R0, JIT_FP, swf_off(r1) + 8);
+ else {
+ swf_ldrin(_R0, JIT_FP, swf_off(r1) + 8);
+ swf_ldrin(_R1, JIT_FP, swf_off(r1) + 4);
+ }
+#if !NAN_TO_INT_IS_ZERO
+ /* >> based on fragment of __aeabi_dcmpun */
+ jit_lshi_i(JIT_TMP, _R1, 1);
+ if (jit_thumb_p())
+ torrrs(THUMB2_MVN|ARM_S, _R0, JIT_TMP, JIT_TMP,
+ encode_thumb_shift(21, ARM_ASR));
+ else
+ corrrs(ARM_CC_AL,ARM_MVN|ARM_S|ARM_ASR, _R0, JIT_TMP, JIT_TMP, 21);
+ fast_not_nan = _jitp->x.pc;
+ if (jit_thumb_p()) {
+ T2_CC_B(ARM_CC_NE, 0);
+ torrrs(THUMB2_ORR|ARM_S, _R0, JIT_TMP, _R1,
+ encode_thumb_shift(12, ARM_LSL));
+ }
+ else {
+ _CC_B(ARM_CC_NE, 0);
+ corrrs(ARM_CC_AL,ARM_ORR|ARM_S|ARM_LSL, _R0, JIT_TMP, _R1, 12);
+ }
+ slow_not_nan = _jitp->x.pc;
+ if (jit_thumb_p())
+ T2_CC_B(ARM_CC_EQ, 0);
+ else
+ _CC_B(ARM_CC_EQ, 0);
+ jit_movi_i(r0, 0x80000000);
+ is_nan = _jitp->x.pc;
+ if (jit_thumb_p())
+ T2_B(0);
+ else
+ _B(0);
+ jit_patch(fast_not_nan);
+ jit_patch(slow_not_nan);
+ /* << based on fragment of __aeabi_dcmpun */
+#endif
+ if (i0)
+ swf_call(i0, fallback);
+ swf_call(__aeabi_d2iz, d2iz);
+ jit_movr_i(r0, _R0);
+#if !NAN_TO_INT_IS_ZERO
+ jit_patch(is_nan);
+#endif
+ swf_pop(l);
+}
+
+#define swf_rintr_f_i(_jitp, r0, r1) swf_if(_jitp, rintf, r0, r1)
+#define swf_rintr_d_i(_jitp, r0, r1) swf_id(_jitp, rint, r0, r1)
+#define swf_roundr_f_i(_jitp, r0, r1) swf_if(_jitp, roundf, r0, r1)
+#define swf_roundr_d_i(_jitp, r0, r1) swf_id(_jitp, round, r0, r1)
+#define swf_truncr_f_i(_jitp, r0, r1) swf_if(_jitp, (void *)0, r0, r1)
+#define swf_truncr_d_i(_jitp, r0, r1) swf_id(_jitp, (void *)0, r0, r1)
+#define swf_ceilr_f_i(_jitp, r0, r1) swf_if(_jitp, ceilf, r0, r1)
+#define swf_ceilr_d_i(_jitp, r0, r1) swf_id(_jitp, ceil, r0, r1)
+#define swf_floorr_f_i(_jitp, r0, r1) swf_if(_jitp, floorf, r0, r1)
+#define swf_floorr_d_i(_jitp, r0, r1) swf_id(_jitp, floor, r0, r1)
+
+__jit_inline void
+swf_absr_f(jit_state_t _jitp, jit_fpr_t r0, jit_fpr_t r1)
+{
+ swf_ldrin(JIT_FTMP, JIT_FP, swf_off(r1) + 8);
+ swf_bici(JIT_FTMP, JIT_FTMP, 0x80000000);
+ swf_strin(JIT_FTMP, JIT_FP, swf_off(r0) + 8);
+}
+
+__jit_inline void
+swf_absr_d(jit_state_t _jitp, jit_fpr_t r0, jit_fpr_t r1)
+{
+ swf_ldrin(JIT_FTMP, JIT_FP, swf_off(r1) + 4);
+ swf_bici(JIT_FTMP, JIT_FTMP, 0x80000000);
+ swf_strin(JIT_FTMP, JIT_FP, swf_off(r0) + 4);
+ if (r0 != r1) {
+ swf_ldrin(JIT_FTMP, JIT_FP, swf_off(r1) + 8);
+ swf_strin(JIT_FTMP, JIT_FP, swf_off(r0) + 8);
+ }
+}
+
+__jit_inline void
+swf_negr_f(jit_state_t _jitp, jit_fpr_t r0, jit_fpr_t r1)
+{
+ swf_ldrin(JIT_FTMP, JIT_FP, swf_off(r1) + 8);
+ jit_xori_i(JIT_FTMP, JIT_FTMP, 0x80000000);
+ swf_strin(JIT_FTMP, JIT_FP, swf_off(r0) + 8);
+}
+
+__jit_inline void
+swf_negr_d(jit_state_t _jitp, jit_fpr_t r0, jit_fpr_t r1)
+{
+ swf_ldrin(JIT_FTMP, JIT_FP, swf_off(r1) + 4);
+ jit_xori_i(JIT_FTMP, JIT_FTMP, 0x80000000);
+ swf_strin(JIT_FTMP, JIT_FP, swf_off(r0) + 4);
+ if (r0 != r1) {
+ swf_ldrin(JIT_FTMP, JIT_FP, swf_off(r1) + 8);
+ swf_strin(JIT_FTMP, JIT_FP, swf_off(r0) + 8);
+ }
+}
+
+__jit_inline void
+swf_ff(jit_state_t _jitp, float (*i0)(float), jit_fpr_t r0, jit_fpr_t r1)
+{
+ swf_push(0xf);
+ swf_ldrin(_R0, JIT_FP, swf_off(r1) + 8);
+ swf_call(i0, fallback);
+ swf_strin(_R0, JIT_FP, swf_off(r0) + 8);
+ swf_pop(0xf);
+}
+
+__jit_inline void
+swf_dd(jit_state_t _jitp, double (*i0)(double), jit_fpr_t r0, jit_fpr_t r1)
+{
+ swf_push(0xf);
+ if (!jit_thumb_p() && jit_armv5e_p())
+ _LDRDIN(_R0, JIT_FP, swf_off(r1) + 8);
+ else {
+ swf_ldrin(_R0, JIT_FP, swf_off(r1) + 8);
+ swf_ldrin(_R1, JIT_FP, swf_off(r1) + 4);
+ }
+ swf_call(i0, fallback);
+ if (!jit_thumb_p() && jit_armv5e_p())
+ _STRDIN(_R0, JIT_FP, swf_off(r0) + 8);
+ else {
+ swf_strin(_R0, JIT_FP, swf_off(r0) + 8);
+ swf_strin(_R1, JIT_FP, swf_off(r0) + 4);
+ }
+ swf_pop(0xf);
+}
+
+#define swf_sqrtr_f(_jitp, r0, r1) swf_ff(_jitp, sqrtf, r0, r1)
+#define swf_sqrtr_d(_jitp, r0, r1) swf_dd(_jitp, sqrt, r0, r1)
+
+__jit_inline void
+swf_fff(jit_state_t _jitp, float (*i0)(float, float),
+ jit_fpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ swf_push(0xf);
+ swf_ldrin(_R0, JIT_FP, swf_off(r1) + 8);
+ swf_ldrin(_R1, JIT_FP, swf_off(r2) + 8);
+ swf_call(i0, fallback);
+ swf_strin(_R0, JIT_FP, swf_off(r0) + 8);
+ swf_pop(0xf);
+}
+
+__jit_inline void
+swf_ddd(jit_state_t _jitp, double (*i0)(double, double),
+ jit_fpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ swf_push(0xf);
+ if (!jit_thumb_p() && jit_armv5e_p()) {
+ _LDRDIN(_R0, JIT_FP, swf_off(r1) + 8);
+ _LDRDIN(_R2, JIT_FP, swf_off(r2) + 8);
+ }
+ else {
+ swf_ldrin(_R0, JIT_FP, swf_off(r1) + 8);
+ swf_ldrin(_R1, JIT_FP, swf_off(r1) + 4);
+ swf_ldrin(_R2, JIT_FP, swf_off(r2) + 8);
+ swf_ldrin(_R3, JIT_FP, swf_off(r2) + 4);
+ }
+ swf_call(i0, fallback);
+ if (!jit_thumb_p() && jit_armv5e_p())
+ _STRDIN(_R0, JIT_FP, swf_off(r0) + 8);
+ else {
+ swf_strin(_R0, JIT_FP, swf_off(r0) + 8);
+ swf_strin(_R1, JIT_FP, swf_off(r0) + 4);
+ }
+ swf_pop(0xf);
+}
+
+#define swf_addr_f(_jitp, r0, r1, r2) swf_fff(_jitp, __addsf3, r0, r1, r2)
+#define swf_addr_d(_jitp, r0, r1, r2) swf_ddd(_jitp, __adddf3, r0, r1, r2)
+#define swf_subr_f(_jitp, r0, r1, r2) swf_fff(_jitp, __aeabi_fsub, r0, r1, r2)
+#define swf_subr_d(_jitp, r0, r1, r2) swf_ddd(_jitp, __aeabi_dsub, r0, r1, r2)
+#define swf_mulr_f(_jitp, r0, r1, r2) swf_fff(_jitp, __aeabi_fmul, r0, r1, r2)
+#define swf_mulr_d(_jitp, r0, r1, r2) swf_ddd(_jitp, __aeabi_dmul, r0, r1, r2)
+#define swf_divr_f(_jitp, r0, r1, r2) swf_fff(_jitp, __aeabi_fdiv, r0, r1, r2)
+#define swf_divr_d(_jitp, r0, r1, r2) swf_ddd(_jitp, __aeabi_ddiv, r0, r1, r2)
+
+__jit_inline void
+swf_iff(jit_state_t _jitp, int (*i0)(float, float),
+ jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ int l;
+ l = 0xf;
+ if ((int)r0 < 4)
+ /* bogus extra push to align at 8 bytes */
+ l = (l & ~(1 << r0)) | 0x10;
+ swf_push(l);
+ swf_ldrin(_R0, JIT_FP, swf_off(r1) + 8);
+ swf_ldrin(_R1, JIT_FP, swf_off(r2) + 8);
+ swf_call(i0, fallback);
+ jit_movr_i(r0, _R0);
+ swf_pop(l);
+}
+
+__jit_inline void
+swf_idd(jit_state_t _jitp, int (*i0)(double, double),
+ jit_fpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ int l;
+ l = 0xf;
+ if ((int)r0 < 4)
+ /* bogus extra push to align at 8 bytes */
+ l = (l & ~(1 << r0)) | 0x10;
+ swf_push(l);
+ if (!jit_thumb_p() && jit_armv5e_p()) {
+ _LDRDIN(_R0, JIT_FP, swf_off(r1) + 8);
+ _LDRDIN(_R2, JIT_FP, swf_off(r2) + 8);
+ }
+ else {
+ swf_ldrin(_R0, JIT_FP, swf_off(r1) + 8);
+ swf_ldrin(_R1, JIT_FP, swf_off(r1) + 4);
+ swf_ldrin(_R2, JIT_FP, swf_off(r2) + 8);
+ swf_ldrin(_R3, JIT_FP, swf_off(r2) + 4);
+ }
+ swf_call(i0, fallback);
+ jit_movr_i(r0, _R0);
+ swf_pop(l);
+}
+
+#define swf_ltr_f(_jitp, r0, r1, r2) swf_iff(_jitp, __aeabi_fcmplt,r0,r1,r2)
+#define swf_ltr_d(_jitp, r0, r1, r2) swf_idd(_jitp, __aeabi_dcmplt,r0,r1,r2)
+#define swf_ler_f(_jitp, r0, r1, r2) swf_iff(_jitp, __aeabi_fcmple,r0,r1,r2)
+#define swf_ler_d(_jitp, r0, r1, r2) swf_idd(_jitp, __aeabi_dcmple,r0,r1,r2)
+#define swf_eqr_f(_jitp, r0, r1, r2) swf_iff(_jitp, __aeabi_fcmpeq,r0,r1,r2)
+#define swf_eqr_d(_jitp, r0, r1, r2) swf_idd(_jitp, __aeabi_dcmpeq,r0,r1,r2)
+#define swf_ger_f(_jitp, r0, r1, r2) swf_iff(_jitp, __aeabi_fcmpge,r0,r1,r2)
+#define swf_ger_d(_jitp, r0, r1, r2) swf_idd(_jitp, __aeabi_dcmpge,r0,r1,r2)
+#define swf_gtr_f(_jitp, r0, r1, r2) swf_iff(_jitp, __aeabi_fcmpgt,r0,r1,r2)
+#define swf_gtr_d(_jitp, r0, r1, r2) swf_idd(_jitp, __aeabi_dcmpgt,r0,r1,r2)
+
+__jit_inline void
+swf_ner_f(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ swf_iff(_jitp, __aeabi_fcmpeq, r0, r1, r2);
+ jit_xori_i(r0, r0, 1);
+}
+
+__jit_inline void
+swf_ner_d(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ swf_idd(_jitp, __aeabi_dcmpeq, r0, r1, r2);
+ jit_xori_i(r0, r0, 1);
+}
+
+__jit_inline void
+swf_iunff(jit_state_t _jitp, int (*i0)(float, float),
+ jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ int l;
+ jit_insn *i;
+ l = 0xf;
+ if ((int)r0 < 4)
+ /* bogus extra push to align at 8 bytes */
+ l = (l & ~(1 << r0)) | 0x10;
+ swf_push(l);
+ swf_ldrin(_R0, JIT_FP, swf_off(r1) + 8);
+ swf_ldrin(_R1, JIT_FP, swf_off(r2) + 8);
+ swf_call(__aeabi_fcmpun, fcmpun);
+ if (jit_thumb_p()) {
+ T1_CMPI(_R0, 0);
+ _IT(ARM_CC_NE);
+ if (r0 < 8)
+ T1_MOVI(r0, 1);
+ else
+ T2_MOVI(r0, 1);
+ i = _jitp->x.pc;
+ T2_CC_B(ARM_CC_NE, 0);
+ }
+ else {
+ _CMPI(_R0, 0);
+ _CC_MOVI(ARM_CC_NE, r0, 1);
+ i = _jitp->x.pc;
+ _CC_B(ARM_CC_NE, 0);
+ }
+ swf_ldrin(_R0, JIT_FP, swf_off(r1) + 8);
+ swf_ldrin(_R1, JIT_FP, swf_off(r2) + 8);
+ swf_call(i0, fallback);
+ jit_movr_i(r0, _R0);
+ jit_patch(i);
+ swf_pop(l);
+}
+
+__jit_inline void
+swf_iundd(jit_state_t _jitp, int (*i0)(double, double),
+ jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ int l;
+ jit_insn *i;
+ l = 0xf;
+ if ((int)r0 < 4)
+ /* bogus extra push to align at 8 bytes */
+ l = (l & ~(1 << r0)) | 0x10;
+ swf_push(l);
+ if (!jit_thumb_p() && jit_armv5e_p()) {
+ _LDRDIN(_R0, JIT_FP, swf_off(r1) + 8);
+ _LDRDIN(_R2, JIT_FP, swf_off(r2) + 8);
+ }
+ else {
+ swf_ldrin(_R0, JIT_FP, swf_off(r1) + 8);
+ swf_ldrin(_R1, JIT_FP, swf_off(r1) + 4);
+ swf_ldrin(_R2, JIT_FP, swf_off(r2) + 8);
+ swf_ldrin(_R3, JIT_FP, swf_off(r2) + 4);
+ }
+ swf_call(__aeabi_dcmpun, dcmpun);
+ if (jit_thumb_p()) {
+ T1_CMPI(_R0, 0);
+ _IT(ARM_CC_NE);
+ if (r0 < 8)
+ T1_MOVI(r0, 1);
+ else
+ T2_MOVI(r0, 1);
+ i = _jitp->x.pc;
+ T2_CC_B(ARM_CC_NE, 0);
+ }
+ else {
+ _CMPI(_R0, 0);
+ _CC_MOVI(ARM_CC_NE, r0, 1);
+ i = _jitp->x.pc;
+ _CC_B(ARM_CC_NE, 0);
+ }
+ if (!jit_thumb_p() && jit_armv5e_p()) {
+ _LDRDIN(_R0, JIT_FP, swf_off(r1) + 8);
+ _LDRDIN(_R2, JIT_FP, swf_off(r2) + 8);
+ }
+ else {
+ swf_ldrin(_R0, JIT_FP, swf_off(r1) + 8);
+ swf_ldrin(_R1, JIT_FP, swf_off(r1) + 4);
+ swf_ldrin(_R2, JIT_FP, swf_off(r2) + 8);
+ swf_ldrin(_R3, JIT_FP, swf_off(r2) + 4);
+ }
+ swf_call(i0, fallback);
+ jit_movr_i(r0, _R0);
+ jit_patch(i);
+ swf_pop(l);
+}
+
+#define swf_unltr_f(_jitp, r0, r1, r2) swf_iunff(_jitp,__aeabi_fcmplt,r0,r1,r2)
+#define swf_unltr_d(_jitp, r0, r1, r2) swf_iundd(_jitp,__aeabi_dcmplt,r0,r1,r2)
+#define swf_unler_f(_jitp, r0, r1, r2) swf_iunff(_jitp,__aeabi_fcmple,r0,r1,r2)
+#define swf_unler_d(_jitp, r0, r1, r2) swf_iundd(_jitp,__aeabi_dcmple,r0,r1,r2)
+#define swf_uneqr_f(_jitp, r0, r1, r2) swf_iunff(_jitp,__aeabi_fcmpeq,r0,r1,r2)
+#define swf_uneqr_d(_jitp, r0, r1, r2) swf_iundd(_jitp,__aeabi_dcmpeq,r0,r1,r2)
+#define swf_unger_f(_jitp, r0, r1, r2) swf_iunff(_jitp,__aeabi_fcmpge,r0,r1,r2)
+#define swf_unger_d(_jitp, r0, r1, r2) swf_iundd(_jitp,__aeabi_dcmpge,r0,r1,r2)
+#define swf_ungtr_f(_jitp, r0, r1, r2) swf_iunff(_jitp,__aeabi_fcmpgt,r0,r1,r2)
+#define swf_ungtr_d(_jitp, r0, r1, r2) swf_iundd(_jitp,__aeabi_dcmpgt,r0,r1,r2)
+
+__jit_inline void
+swf_ltgtr_f(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ swf_iunff(_jitp, __aeabi_fcmpeq, r0, r1, r2);
+ jit_xori_i(r0, r0, 1);
+}
+
+__jit_inline void
+swf_ltgtr_d(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ swf_iundd(_jitp, __aeabi_dcmpeq, r0, r1, r2);
+ jit_xori_i(r0, r0, 1);
+}
+
+__jit_inline void
+swf_ordr_f(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ swf_iff(_jitp, __aeabi_fcmpun, r0, r1, r2);
+ jit_xori_i(r0, r0, 1);
+}
+
+__jit_inline void
+swf_ordr_d(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ swf_idd(_jitp, __aeabi_dcmpun, r0, r1, r2);
+ jit_xori_i(r0, r0, 1);
+}
+
+#define swf_unordr_f(_jitp, r0, r1, r2) swf_iunff(_jitp,__aeabi_fcmpun,r0,r1,r2)
+#define swf_unordr_d(_jitp, r0, r1, r2) swf_iundd(_jitp,__aeabi_dcmpun,r0,r1,r2)
+
+__jit_inline jit_insn *
+swf_bff(jit_state_t _jitp, int (*i0)(float, float), int cc,
+ void *i1, jit_fpr_t r1, jit_fpr_t r2)
+{
+ jit_insn *l;
+
+ assert(r1 != JIT_FPRET && r2 != JIT_FPRET);
+ swf_push(0xf);
+ swf_ldrin(_R0, JIT_FP, swf_off(r1) + 8);
+ swf_ldrin(_R1, JIT_FP, swf_off(r2) + 8);
+ swf_call(i0, fallback);
+ if (jit_thumb_p()) {
+ T1_CMPI(_R0, 0);
+ swf_pop(0xf);
+ l = thumb_branch(_jitp, cc, i1);
+ }
+ else {
+ _CMPI(_R0, 0);
+ swf_pop(0xf);
+ l = arm_branch(_jitp, cc, i1);
+ }
+ return (l);
+}
+
+__jit_inline jit_insn *
+swf_bdd(jit_state_t _jitp, int (*i0)(double, double), int cc,
+ void *i1, jit_fpr_t r1, jit_fpr_t r2)
+{
+ jit_insn *l;
+ assert(r1 != JIT_FPRET && r2 != JIT_FPRET);
+ swf_push(0xf);
+ if (!jit_thumb_p() && jit_armv5e_p()) {
+ _LDRDIN(_R0, JIT_FP, swf_off(r1) + 8);
+ _LDRDIN(_R2, JIT_FP, swf_off(r2) + 8);
+ }
+ else {
+ swf_ldrin(_R0, JIT_FP, swf_off(r1) + 8);
+ swf_ldrin(_R1, JIT_FP, swf_off(r1) + 4);
+ swf_ldrin(_R2, JIT_FP, swf_off(r2) + 8);
+ swf_ldrin(_R3, JIT_FP, swf_off(r2) + 4);
+ }
+ swf_call(i0, fallback);
+ if (jit_thumb_p()) {
+ T1_CMPI(_R0, 0);
+ swf_pop(0xf);
+ l = thumb_branch(_jitp, cc, i1);
+ }
+ else {
+ _CMPI(_R0, 0);
+ swf_pop(0xf);
+ l = arm_branch(_jitp, cc, i1);
+ }
+ return (l);
+}
+
+#define swf_bltr_f(_jitp,i0,r0,r1) swf_bff(_jitp,__aeabi_fcmplt,ARM_CC_NE,i0,r0,r1)
+#define swf_bltr_d(_jitp,i0,r0,r1) swf_bdd(_jitp,__aeabi_dcmplt,ARM_CC_NE,i0,r0,r1)
+#define swf_bler_f(_jitp,i0,r0,r1) swf_bff(_jitp,__aeabi_fcmple,ARM_CC_NE,i0,r0,r1)
+#define swf_bler_d(_jitp,i0,r0,r1) swf_bdd(_jitp,__aeabi_dcmple,ARM_CC_NE,i0,r0,r1)
+#define swf_beqr_f(_jitp,i0,r0,r1) swf_bff(_jitp,__aeabi_fcmpeq,ARM_CC_NE,i0,r0,r1)
+#define swf_beqr_d(_jitp,i0,r0,r1) swf_bdd(_jitp,__aeabi_dcmpeq,ARM_CC_NE,i0,r0,r1)
+#define swf_bger_f(_jitp,i0,r0,r1) swf_bff(_jitp,__aeabi_fcmpge,ARM_CC_NE,i0,r0,r1)
+#define swf_bger_d(_jitp,i0,r0,r1) swf_bdd(_jitp,__aeabi_dcmpge,ARM_CC_NE,i0,r0,r1)
+#define swf_bgtr_f(_jitp,i0,r0,r1) swf_bff(_jitp,__aeabi_fcmpgt,ARM_CC_NE,i0,r0,r1)
+#define swf_bgtr_d(_jitp,i0,r0,r1) swf_bdd(_jitp,__aeabi_dcmpgt,ARM_CC_NE,i0,r0,r1)
+#define swf_bner_f(_jitp,i0,r0,r1) swf_bff(_jitp,__aeabi_fcmpeq,ARM_CC_EQ,i0,r0,r1)
+#define swf_bner_d(_jitp,i0,r0,r1) swf_bdd(_jitp,__aeabi_dcmpeq,ARM_CC_EQ,i0,r0,r1)
+#define swf_bunltr_f(_jitp,i0,r0,r1) swf_bff(_jitp,__aeabi_fcmpge,ARM_CC_EQ,i0,r0,r1)
+#define swf_bunltr_d(_jitp,i0,r0,r1) swf_bdd(_jitp,__aeabi_dcmpge,ARM_CC_EQ,i0,r0,r1)
+#define swf_bunler_f(_jitp,i0,r0,r1) swf_bff(_jitp,__aeabi_fcmpgt,ARM_CC_EQ,i0,r0,r1)
+#define swf_bunler_d(_jitp,i0,r0,r1) swf_bdd(_jitp,__aeabi_dcmpgt,ARM_CC_EQ,i0,r0,r1)
+
+__jit_inline jit_insn *
+swf_bunff(jit_state_t _jitp, int eq, void *i1, jit_fpr_t r1, jit_fpr_t r2)
+{
+ jit_insn *l;
+ jit_insn *j0;
+ jit_insn *j1;
+ assert(r1 != JIT_FPRET && r2 != JIT_FPRET);
+ swf_push(0xf);
+ swf_ldrin(_R0, JIT_FP, swf_off(r1) + 8);
+ swf_ldrin(_R1, JIT_FP, swf_off(r2) + 8);
+ swf_call(__aeabi_fcmpun, fcmpun);
+ /* if unordered */
+ if (jit_thumb_p()) {
+ T1_CMPI(_R0, 0);
+ j0 = _jitp->x.pc;
+ T2_CC_B(ARM_CC_NE, 0);
+ }
+ else {
+ _CMPI(_R0, 0);
+ j0 = _jitp->x.pc;
+ _CC_B(ARM_CC_NE, 0);
+ }
+ swf_ldrin(_R0, JIT_FP, swf_off(r1) + 8);
+ swf_ldrin(_R1, JIT_FP, swf_off(r2) + 8);
+ swf_call(__aeabi_fcmpeq, fcmpeq);
+ if (jit_thumb_p()) {
+ T1_CMPI(_R0, 0);
+ j1 = _jitp->x.pc;
+ if (eq) {
+ T2_CC_B(ARM_CC_EQ, 0);
+ jit_patch(j0);
+ }
+ else
+ T2_CC_B(ARM_CC_NE, 0);
+ swf_pop(0xf);
+ l = thumb_branch(_jitp, ARM_CC_AL, i1);
+ }
+ else {
+ _CMPI(_R0, 0);
+ j1 = _jitp->x.pc;
+ if (eq) {
+ _CC_B(ARM_CC_EQ, 0);
+ jit_patch(j0);
+ }
+ else
+ _CC_B(ARM_CC_NE, 0);
+ swf_pop(0xf);
+ l = arm_branch(_jitp, ARM_CC_AL, i1);
+ }
+ if (!eq)
+ jit_patch(j0);
+ jit_patch(j1);
+ swf_pop(0xf);
+ return (l);
+}
+
+__jit_inline jit_insn *
+swf_bundd(jit_state_t _jitp, int eq, void *i1, jit_fpr_t r1, jit_fpr_t r2)
+{
+ jit_insn *l;
+ jit_insn *j0;
+ jit_insn *j1;
+ assert(r1 != JIT_FPRET && r2 != JIT_FPRET);
+ swf_push(0xf);
+ if (!jit_thumb_p() && jit_armv5e_p()) {
+ _LDRDIN(_R0, JIT_FP, swf_off(r1) + 8);
+ _LDRDIN(_R2, JIT_FP, swf_off(r2) + 8);
+ }
+ else {
+ swf_ldrin(_R0, JIT_FP, swf_off(r1) + 8);
+ swf_ldrin(_R1, JIT_FP, swf_off(r1) + 4);
+ swf_ldrin(_R2, JIT_FP, swf_off(r2) + 8);
+ swf_ldrin(_R3, JIT_FP, swf_off(r2) + 4);
+ }
+ swf_call(__aeabi_dcmpun, dcmpun);
+ /* if unordered */
+ if (jit_thumb_p()) {
+ T1_CMPI(_R0, 0);
+ j0 = _jitp->x.pc;
+ T2_CC_B(ARM_CC_NE, 0);
+ }
+ else {
+ _CMPI(_R0, 0);
+ j0 = _jitp->x.pc;
+ _CC_B(ARM_CC_NE, 0);
+ }
+ if (!jit_thumb_p() && jit_armv5e_p()) {
+ _LDRDIN(_R0, JIT_FP, swf_off(r1) + 8);
+ _LDRDIN(_R2, JIT_FP, swf_off(r2) + 8);
+ }
+ else {
+ swf_ldrin(_R0, JIT_FP, swf_off(r1) + 8);
+ swf_ldrin(_R1, JIT_FP, swf_off(r1) + 4);
+ swf_ldrin(_R2, JIT_FP, swf_off(r2) + 8);
+ swf_ldrin(_R3, JIT_FP, swf_off(r2) + 4);
+ }
+ swf_call(__aeabi_dcmpeq, dcmpeq);
+ if (jit_thumb_p()) {
+ T1_CMPI(_R0, 0);
+ j1 = _jitp->x.pc;
+ if (eq) {
+ T2_CC_B(ARM_CC_EQ, 0);
+ jit_patch(j0);
+ }
+ else
+ T2_CC_B(ARM_CC_NE, 0);
+ swf_pop(0xf);
+ l = thumb_branch(_jitp, ARM_CC_AL, i1);
+ }
+ else {
+ _CMPI(_R0, 0);
+ j1 = _jitp->x.pc;
+ if (eq) {
+ _CC_B(ARM_CC_EQ, 0);
+ jit_patch(j0);
+ }
+ else
+ _CC_B(ARM_CC_NE, 0);
+ swf_pop(0xf);
+ l = arm_branch(_jitp, ARM_CC_AL, i1);
+ }
+ if (!eq)
+ jit_patch(j0);
+ jit_patch(j1);
+ swf_pop(0xf);
+ return (l);
+}
+
+#define swf_buneqr_f(_jitp,i0,r0,r1) swf_bunff(_jitp,1,i0,r0,r1)
+#define swf_buneqr_d(_jitp,i0,r0,r1) swf_bundd(_jitp,1,i0,r0,r1)
+#define swf_bunger_f(_jitp,i0,r0,r1) swf_bff(_jitp,__aeabi_fcmplt,ARM_CC_EQ,i0,r0,r1)
+#define swf_bunger_d(_jitp,i0,r0,r1) swf_bdd(_jitp,__aeabi_dcmplt,ARM_CC_EQ,i0,r0,r1)
+#define swf_bungtr_f(_jitp,i0,r0,r1) swf_bff(_jitp,__aeabi_fcmple,ARM_CC_EQ,i0,r0,r1)
+#define swf_bungtr_d(_jitp,i0,r0,r1) swf_bdd(_jitp,__aeabi_dcmple,ARM_CC_EQ,i0,r0,r1)
+#define swf_bltgtr_f(_jitp,i0,r0,r1) swf_bunff(_jitp,0,i0,r0,r1)
+#define swf_bltgtr_d(_jitp,i0,r0,r1) swf_bundd(_jitp,0,i0,r0,r1)
+#define swf_bordr_f(_jitp,i0,r0,r1) swf_bff(_jitp,__aeabi_fcmpun,ARM_CC_EQ,i0,r0,r1)
+#define swf_bordr_d(_jitp,i0,r0,r1) swf_bdd(_jitp,__aeabi_dcmpun,ARM_CC_EQ,i0,r0,r1)
+#define swf_bunordr_f(_jitp,i0,r0,r1) swf_bff(_jitp,__aeabi_fcmpun,ARM_CC_NE,i0,r0,r1)
+#define swf_bunordr_d(_jitp,i0,r0,r1) swf_bdd(_jitp,__aeabi_dcmpun,ARM_CC_NE,i0,r0,r1)
+
+__jit_inline void
+swf_ldr_f(jit_state_t _jitp, jit_fpr_t r0, jit_gpr_t r1)
+{
+ jit_ldr_i(JIT_FTMP, r1);
+ swf_strin(JIT_FTMP, JIT_FP, swf_off(r0) + 8);
+}
+
+__jit_inline void
+swf_ldr_d(jit_state_t _jitp, jit_fpr_t r0, jit_gpr_t r1)
+{
+ if (!jit_thumb_p() && jit_armv5e_p()) {
+ _LDRDI(JIT_TMP, r1, 0);
+ _STRDIN(JIT_TMP, JIT_FP, swf_off(r0) + 8);
+ }
+ else {
+ jit_ldxi_i(JIT_TMP, r1, 0);
+ jit_ldxi_i(JIT_FTMP, r1, 4);
+ swf_strin(JIT_TMP, JIT_FP, swf_off(r0) + 8);
+ swf_strin(JIT_FTMP, JIT_FP, swf_off(r0) + 4);
+ }
+}
+
+__jit_inline void
+swf_ldi_f(jit_state_t _jitp, jit_fpr_t r0, void *i0)
+{
+ jit_ldi_i(JIT_FTMP, i0);
+ swf_strin(JIT_FTMP, JIT_FP, swf_off(r0) + 8);
+}
+
+__jit_inline void
+swf_ldi_d(jit_state_t _jitp, jit_fpr_t r0, void *i0)
+{
+ jit_movi_i(JIT_TMP, (int)i0);
+ if (!jit_thumb_p() && jit_armv5e_p()) {
+ _LDRDI(JIT_TMP, JIT_TMP, 0);
+ _STRDIN(JIT_TMP, JIT_FP, swf_off(r0) + 8);
+ }
+ else {
+ jit_ldxi_i(JIT_FTMP, JIT_TMP, 4);
+ jit_ldxi_i(JIT_TMP, JIT_TMP, 0);
+ swf_strin(JIT_TMP, JIT_FP, swf_off(r0) + 8);
+ swf_strin(JIT_FTMP, JIT_FP, swf_off(r0) + 4);
+ }
+}
+
+__jit_inline void
+swf_ldxr_f(jit_state_t _jitp, jit_fpr_t r0, jit_gpr_t r1, jit_gpr_t r2)
+{
+ jit_ldxr_i(JIT_TMP, r1, r2);
+ swf_strin(JIT_TMP, JIT_FP, swf_off(r0) + 8);
+}
+
+__jit_inline void
+swf_ldxr_d(jit_state_t _jitp, jit_fpr_t r0, jit_gpr_t r1, jit_gpr_t r2)
+{
+ if (!jit_thumb_p() && jit_armv5e_p()) {
+ _LDRD(JIT_TMP, r1, r2);
+ _STRDIN(JIT_TMP, JIT_FP, swf_off(r0) + 8);
+ }
+ else {
+ jit_addr_i(JIT_TMP, r1, r2);
+ jit_ldxi_i(JIT_FTMP, JIT_TMP, 4);
+ jit_ldxi_i(JIT_TMP, JIT_TMP, 0);
+ swf_strin(JIT_TMP, JIT_FP, swf_off(r0) + 8);
+ swf_strin(JIT_FTMP, JIT_FP, swf_off(r0) + 4);
+ }
+}
+
+__jit_inline void
+swf_ldxi_f(jit_state_t _jitp, jit_fpr_t r0, jit_gpr_t r1, int i0)
+{
+ jit_ldxi_i(JIT_FTMP, r1, i0);
+ swf_strin(JIT_FTMP, JIT_FP, swf_off(r0) + 8);
+}
+
+__jit_inline void
+swf_ldxi_d(jit_state_t _jitp, jit_fpr_t r0, jit_gpr_t r1, int i0)
+{
+ if (!jit_thumb_p() && jit_armv5e_p()) {
+ if (i0 >= 0 && i0 <= 255)
+ _LDRDI(JIT_TMP, r1, i0);
+ else if (i0 < 0 && i0 >= -255)
+ _LDRDIN(JIT_TMP, r1, -i0);
+ else {
+ jit_addi_i(JIT_FTMP, r1, i0);
+ _LDRDI(JIT_TMP, JIT_FTMP, 0);
+ }
+ _STRDIN(JIT_TMP, JIT_FP, swf_off(r0) + 8);
+ }
+ else {
+ if (((jit_thumb_p() && i0 >= -255) ||
+ (!jit_thumb_p() && i0 >= -4095)) && i0 + 4 <= 4095) {
+ if (i0 >= 0)
+ jit_ldxi_i(JIT_TMP, r1, i0);
+ else if (i0 < 0)
+ swf_ldrin(JIT_TMP, r1, -i0);
+ i0 += 4;
+ if (i0 >= 0)
+ jit_ldxi_i(JIT_FTMP, r1, i0);
+ else if (i0 < 0)
+ swf_ldrin(JIT_FTMP, r1, -i0);
+ }
+ else {
+ jit_addi_i(JIT_FTMP, r1, i0);
+ jit_ldxi_i(JIT_TMP, JIT_FTMP, 0);
+ jit_ldxi_i(JIT_FTMP, JIT_FTMP, 4);
+ }
+ swf_strin(JIT_TMP, JIT_FP, swf_off(r0) + 8);
+ swf_strin(JIT_FTMP, JIT_FP, swf_off(r0) + 4);
+ }
+}
+
+__jit_inline void
+swf_str_f(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1)
+{
+ swf_ldrin(JIT_FTMP, JIT_FP, swf_off(r1) + 8);
+ jit_stxi_i(0, r0, JIT_FTMP);
+}
+
+__jit_inline void
+swf_str_d(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1)
+{
+ if (!jit_thumb_p() && jit_armv5e_p()) {
+ _LDRDIN(JIT_TMP, JIT_FP, swf_off(r1) + 8);
+ _STRDI(JIT_TMP, r0, 0);
+ }
+ else {
+ swf_ldrin(JIT_TMP, JIT_FP, swf_off(r1) + 8);
+ swf_ldrin(JIT_FTMP, JIT_FP, swf_off(r1) + 4);
+ jit_stxi_i(0, r0, JIT_TMP);
+ jit_stxi_i(4, r0, JIT_FTMP);
+ }
+}
+
+__jit_inline void
+swf_sti_f(jit_state_t _jitp, void *i0, jit_fpr_t r0)
+{
+ jit_movi_i(JIT_TMP, (int)i0);
+ swf_ldrin(JIT_FTMP, JIT_FP, swf_off(r0) + 8);
+ jit_stxi_i(0, JIT_TMP, JIT_FTMP);
+}
+
+__jit_inline void
+swf_sti_d(jit_state_t _jitp, void *i0, jit_fpr_t r0)
+{
+ jit_movi_i(JIT_TMP, (int)i0);
+ swf_ldrin(JIT_FTMP, JIT_FP, swf_off(r0) + 8);
+ jit_stxi_i(0, JIT_TMP, JIT_FTMP);
+ swf_ldrin(JIT_FTMP, JIT_FP, swf_off(r0) + 4);
+ jit_stxi_i(4, JIT_TMP, JIT_FTMP);
+}
+
+__jit_inline void
+swf_stxr_f(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, jit_fpr_t r2)
+{
+ swf_ldrin(JIT_TMP, JIT_FP, swf_off(r2) + 8);
+ jit_stxr_i(r1, r0, JIT_TMP);
+}
+
+__jit_inline void
+swf_stxr_d(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, jit_fpr_t r2)
+{
+ if (!jit_thumb_p() && jit_armv5e_p()) {
+ _LDRDIN(JIT_TMP, JIT_FP, swf_off(r2) + 8);
+ _STRD(JIT_TMP, r0, r1);
+ }
+ else {
+ jit_addr_i(JIT_TMP, r0, r1);
+ swf_ldrin(JIT_FTMP, JIT_FP, swf_off(r2) + 8);
+ jit_stxi_i(0, JIT_TMP, JIT_FTMP);
+ swf_ldrin(JIT_FTMP, JIT_FP, swf_off(r2) + 4);
+ jit_stxi_i(4, JIT_TMP, JIT_FTMP);
+ }
+}
+
+__jit_inline void
+swf_stxi_f(jit_state_t _jitp, int i0, jit_gpr_t r0, jit_fpr_t r1)
+{
+ swf_ldrin(JIT_FTMP, JIT_FP, swf_off(r1) + 8);
+ jit_stxi_i(i0, r0, JIT_FTMP);
+}
+
+__jit_inline void
+swf_stxi_d(jit_state_t _jitp, int i0, jit_gpr_t r0, jit_fpr_t r1)
+{
+ if (!jit_thumb_p() && jit_armv5e_p()) {
+ if (i0 >= 0 && i0 <= 255) {
+ _LDRDIN(JIT_TMP, JIT_FP, swf_off(r1) + 8);
+ _STRDI(JIT_TMP, r0, i0);
+ }
+ else if (i0 < 0 && i0 >= -255) {
+ _LDRDIN(JIT_TMP, JIT_FP, swf_off(r1) + 8);
+ _STRDIN(JIT_TMP, r0, -i0);
+ }
+ else {
+ jit_addi_i(JIT_FTMP, r0, i0);
+ swf_ldrin(JIT_TMP, JIT_FP, swf_off(r1) + 8);
+ jit_stxi_i(0, JIT_TMP, JIT_FTMP);
+ swf_ldrin(JIT_TMP, JIT_FP, swf_off(r1) + 4);
+ jit_stxi_i(4, JIT_TMP, JIT_FTMP);
+ }
+ }
+ else {
+ jit_addi_i(JIT_FTMP, r0, i0);
+ swf_ldrin(JIT_TMP, JIT_FP, swf_off(r1) + 8);
+ jit_stxi_i(0, JIT_FTMP, JIT_TMP);
+ swf_ldrin(JIT_TMP, JIT_FP, swf_off(r1) + 4);
+ jit_stxi_i(4, JIT_FTMP, JIT_TMP);
+ }
+}
+
+__jit_inline void
+swf_getarg_f(jit_state_t _jitp, jit_fpr_t r0, int i0)
+{
+ assert(0);
+}
+
+__jit_inline void
+swf_getarg_d(jit_state_t _jitp, jit_fpr_t r0, int i0)
+{
+ assert(0);
+}
+
+__jit_inline void
+swf_pusharg_f(jit_state_t _jitp, jit_fpr_t r0)
+{
+ assert(0);
+}
+
+__jit_inline void
+swf_pusharg_d(jit_state_t _jitp, jit_fpr_t r0)
+{
+ assert(0);
+}
+
+#define swf_retval_f(_jitp, r0) swf_strin(_R0, JIT_FP, swf_off(r0) + 8)
+__jit_inline void
+swf_retval_d(jit_state_t _jitp, jit_fpr_t r0)
+{
+ if (!jit_thumb_p() && jit_armv5e_p())
+ _STRDIN(_R0, JIT_FP, swf_off(r0) + 8);
+ else {
+ swf_strin(_R0, JIT_FP, swf_off(r0) + 8);
+ swf_strin(_R1, JIT_FP, swf_off(r0) + 4);
+ }
+}
+
+#endif /* __lightning_fp_swf_h */
diff --git a/src/racket/src/lightning/arm/fp-vfp.h b/src/racket/src/lightning/arm/fp-vfp.h
new file mode 100644
index 0000000000..d114395fd5
--- /dev/null
+++ b/src/racket/src/lightning/arm/fp-vfp.h
@@ -0,0 +1,1022 @@
+/******************************** -*- C -*- ****************************
+ *
+ * Support macros for arm VFP floating-point math
+ *
+ ***********************************************************************/
+
+
+/***********************************************************************
+ *
+ * Copyright 2011 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU lightning.
+ *
+ * GNU lightning 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU lightning 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 GNU lightning; see the file COPYING.LESSER; if not, write to the
+ * Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * Authors:
+ * Paulo Cesar Pereira de Andrade
+ ***********************************************************************/
+
+
+#ifndef __lightning_fp_vfp_h
+#define __lightning_fp_vfp_h
+
+__jit_inline void
+vfp_movr_f(jit_state_t _jitp, jit_fpr_t r0, jit_fpr_t r1)
+{
+ if (r0 != r1) {
+ if (r0 == JIT_FPRET) {
+ /* jit_ret() must follow! */
+ if (!jit_hardfp_p())
+ _VMOV_A_S(_R0, r1);
+ else
+ _VMOV_F32(_D0, r1);
+ }
+ else
+ _VMOV_F32(r0, r1);
+ }
+}
+
+__jit_inline void
+vfp_movr_d(jit_state_t _jitp, jit_fpr_t r0, jit_fpr_t r1)
+{
+ if (r0 != r1) {
+ if (r0 == JIT_FPRET) {
+ /* jit_ret() must follow! */
+ if (!jit_hardfp_p())
+ _VMOV_AA_D(_R0, _R1, r1);
+ else
+ _VMOV_F64(_D0, r1);
+ }
+ else
+ _VMOV_F64(r0, r1);
+ }
+}
+
+__jit_inline void
+vfp_movi_f(jit_state_t _jitp, jit_fpr_t r0, float i0)
+{
+ union {
+ int i;
+ float f;
+ } u;
+ int code;
+ u.f = i0;
+ if (!jit_hardfp_p() && r0 == JIT_FPRET)
+ /* jit_ret() must follow! */
+ jit_movi_i(_R0, u.i);
+ else {
+ if (r0 == JIT_FPRET)
+ r0 = _D0;
+ if ((code = encode_vfp_double(1, 0, u.i, u.i)) != -1 ||
+ (code = encode_vfp_double(1, 1, ~u.i, ~u.i)) != -1)
+ _VIMM(code, r0);
+ else {
+ jit_movi_i(JIT_FTMP, u.i);
+ _VMOV_S_A(r0, JIT_FTMP);
+ }
+ }
+}
+
+__jit_inline void
+vfp_movi_d(jit_state_t _jitp, jit_fpr_t r0, double i0)
+{
+ union {
+ int i[2];
+ double d;
+ } u;
+ int code;
+ u.d = i0;
+ if (!jit_hardfp_p() && r0 == JIT_FPRET) {
+ /* jit_ret() must follow! */
+ jit_movi_i(_R0, u.i[0]);
+ jit_movi_i(_R1, u.i[1]);
+ }
+ else {
+ if (r0 == JIT_FPRET)
+ r0 = _D0;
+ if ((code = encode_vfp_double(1, 0, u.i[0], u.i[1])) != -1 ||
+ (code = encode_vfp_double(1, 1, ~u.i[0], ~u.i[1])) != -1)
+ _VIMM(code, r0);
+ else {
+ jit_movi_i(JIT_TMP, u.i[0]);
+ jit_movi_i(JIT_FTMP, u.i[1]);
+ _VMOV_D_AA(r0, JIT_TMP, JIT_FTMP);
+ }
+ }
+}
+
+__jit_inline void
+vfp_extr_i_f(jit_state_t _jitp, jit_fpr_t r0, jit_gpr_t r1)
+{
+ _VMOV_V_I32(r0, r1);
+ _VCVT_F32_S32(r0, r0);
+}
+
+__jit_inline void
+vfp_extr_i_d(jit_state_t _jitp, jit_fpr_t r0, jit_gpr_t r1)
+{
+ _VMOV_V_I32(r0, r1);
+ _VCVT_F64_S32(r0, r0);
+}
+
+#define vfp_extr_d_f(_jitp, r0, r1) _VCVT_F64_F32(r0, r1)
+#define vfp_extr_f_d(_jitp, r0, r1) _VCVT_F32_F64(r0, r1)
+
+#define vfp_get_tmp(r, n) jit_fpr_t tmp = _D7
+#define vfp_unget_tmp(n) /* empty */
+
+__jit_inline void
+vfp_rintr_f_i(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1)
+{
+ vfp_get_tmp(r1, 32);
+ _VCVT_S32_F32(tmp, r1);
+ _VMOV_A_S32(r0, tmp);
+ vfp_unget_tmp(32);
+}
+
+__jit_inline void
+vfp_rintr_d_i(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1)
+{
+ vfp_get_tmp(r1, 64);
+ _VCVT_S32_F64(tmp, r1);
+ _VMOV_A_S32(r0, tmp);
+ vfp_unget_tmp(64);
+}
+
+__jit_inline void
+vfp_roundr_f_i(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1)
+{
+ vfp_get_tmp(r1, 32);
+ _VMOV_A_S(JIT_FTMP, r1);
+ if (jit_thumb_p()) {
+ T2_TSTI(JIT_FTMP, encode_thumb_immediate(0x80000000));
+ _ITE(ARM_CC_NE);
+ /* add -0.5 if negative */
+ T2_MOVI(JIT_FTMP, encode_thumb_immediate(0xbf000000));
+ /* add 0.5 if positive */
+ T2_MOVI(JIT_FTMP, encode_thumb_immediate(0x3f000000));
+ }
+ else {
+ if (jit_armv6_p())
+ _TSTI(JIT_FTMP, encode_arm_immediate(0x80000000));
+ else
+ _ANDSI(JIT_FTMP, JIT_FTMP, encode_arm_immediate(0x80000000));
+ /* add -0.5 if negative */
+ _CC_MOVI(ARM_CC_NE, JIT_FTMP, encode_arm_immediate(0xbf000000));
+ /* add 0.5 if positive */
+ _CC_MOVI(ARM_CC_EQ, JIT_FTMP, encode_arm_immediate(0x3f000000));
+ }
+ _VMOV_S_A(tmp, JIT_FTMP);
+ _VADD_F32(tmp, r1, tmp);
+ /* truncate to zero */
+ _VCVT_S32_F32(tmp, tmp);
+ _VMOV_A_S32(r0, tmp);
+ vfp_unget_tmp(32);
+}
+
+__jit_inline void
+vfp_roundr_d_i(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1)
+{
+ vfp_get_tmp(r1, 64);
+ _VMOV_AA_D(JIT_TMP, JIT_FTMP, r1);
+ if (jit_thumb_p()) {
+ T2_TSTI(JIT_FTMP, encode_thumb_immediate(0x80000000));
+ T2_MOVI(JIT_FTMP, encode_thumb_immediate(0x0fe00000));
+ _ITE(ARM_CC_NE);
+ /* add -0.5 if negative */
+ T2_ORRI(JIT_FTMP, JIT_FTMP, encode_thumb_immediate(0xb0000000));
+ /* add 0.5 if positive */
+ T2_ORRI(JIT_FTMP, JIT_FTMP, encode_thumb_immediate(0x30000000));
+ }
+ else {
+ if (jit_armv6_p())
+ _TSTI(JIT_FTMP, encode_arm_immediate(0x80000000));
+ else
+ _ANDSI(JIT_FTMP, JIT_FTMP, encode_arm_immediate(0x80000000));
+ _MOVI(JIT_FTMP, encode_arm_immediate(0x0fe00000));
+ /* add -0.5 if negative */
+ _CC_ORRI(ARM_CC_NE, JIT_FTMP, JIT_FTMP,
+ encode_arm_immediate(0xb0000000));
+ /* add 0.5 if positive */
+ _CC_ORRI(ARM_CC_EQ, JIT_FTMP, JIT_FTMP,
+ encode_arm_immediate(0x30000000));
+ }
+ jit_movi_i(JIT_TMP, 0);
+ _VMOV_D_AA(tmp, JIT_TMP, JIT_FTMP);
+ _VADD_F64(tmp, r1, tmp);
+ /* truncate to zero */
+ _VCVT_S32_F64(tmp, tmp);
+ _VMOV_A_S32(r0, tmp);
+ vfp_unget_tmp(64);
+}
+
+#define vfp_truncr_f_i(_jitp, r0, r1) vfp_rintr_f_i(_jitp, r0, r1)
+#define vfp_truncr_d_i(_jitp, r0, r1) vfp_rintr_d_i(_jitp, r0, r1)
+
+__jit_inline void
+vfp_ceilr_f_i(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1)
+{
+ vfp_get_tmp(r1, 32);
+ _VMRS(JIT_TMP);
+ if (jit_thumb_p()) {
+ T2_BICI(JIT_FTMP, JIT_TMP, encode_thumb_immediate(FPSCR_RMASK));
+ T2_ORRI(JIT_FTMP, JIT_FTMP, encode_thumb_immediate(FPSCR_RP));
+ }
+ else {
+ _BICI(JIT_FTMP, JIT_TMP, encode_arm_immediate(FPSCR_RMASK));
+ _ORRI(JIT_FTMP, JIT_FTMP, encode_arm_immediate(FPSCR_RP));
+ }
+ _VMSR(JIT_FTMP);
+ _VCVTR_S32_F32(tmp, r1);
+ _VMOV_A_S32(r0, tmp);
+ _VMSR(JIT_TMP);
+ vfp_unget_tmp(32);
+}
+
+__jit_inline void
+vfp_ceilr_d_i(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1)
+{
+ vfp_get_tmp(r1, 64);
+ _VMRS(JIT_TMP);
+ if (jit_thumb_p()) {
+ T2_BICI(JIT_FTMP, JIT_TMP, encode_thumb_immediate(FPSCR_RMASK));
+ T2_ORRI(JIT_FTMP, JIT_FTMP, encode_thumb_immediate(FPSCR_RP));
+ }
+ else {
+ _BICI(JIT_FTMP, JIT_TMP, encode_arm_immediate(FPSCR_RMASK));
+ _ORRI(JIT_FTMP, JIT_FTMP, encode_arm_immediate(FPSCR_RP));
+ }
+ _VMSR(JIT_FTMP);
+ _VCVTR_S32_F64(tmp, r1);
+ _VMOV_A_S32(r0, tmp);
+ _VMSR(JIT_TMP);
+ vfp_unget_tmp(64);
+}
+
+__jit_inline void
+vfp_floorr_f_i(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1)
+{
+ vfp_get_tmp(r1, 32);
+ _VMRS(JIT_TMP);
+ if (jit_thumb_p()) {
+ T2_BICI(JIT_FTMP, JIT_TMP, encode_thumb_immediate(FPSCR_RMASK));
+ T2_ORRI(JIT_FTMP, JIT_FTMP, encode_thumb_immediate(FPSCR_RM));
+ }
+ else {
+ _BICI(JIT_FTMP, JIT_TMP, encode_arm_immediate(FPSCR_RMASK));
+ _ORRI(JIT_FTMP, JIT_FTMP, encode_arm_immediate(FPSCR_RM));
+ }
+ _VMSR(JIT_FTMP);
+ _VCVTR_S32_F32(tmp, r1);
+ _VMOV_A_S32(r0, tmp);
+ _VMSR(JIT_TMP);
+ vfp_unget_tmp(32);
+}
+
+__jit_inline void
+vfp_floorr_d_i(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1)
+{
+ vfp_get_tmp(r1, 64);
+ _VMRS(JIT_TMP);
+ if (jit_thumb_p()) {
+ T2_BICI(JIT_FTMP, JIT_TMP, encode_thumb_immediate(FPSCR_RMASK));
+ T2_ORRI(JIT_FTMP, JIT_FTMP, encode_thumb_immediate(FPSCR_RM));
+ }
+ else {
+ _BICI(JIT_FTMP, JIT_TMP, encode_arm_immediate(FPSCR_RMASK));
+ _ORRI(JIT_FTMP, JIT_FTMP, encode_arm_immediate(FPSCR_RM));
+ }
+ _VMSR(JIT_FTMP);
+ _VCVTR_S32_F64(tmp, r1);
+ _VMOV_A_S32(r0, tmp);
+ _VMSR(JIT_TMP);
+ vfp_unget_tmp(64);
+}
+
+#define vfp_absr_f(_jitp, r0, r1) _VABS_F32(r0, r1)
+#define vfp_absr_d(_jitp, r0, r1) _VABS_F64(r0, r1)
+#define vfp_negr_f(_jitp, r0, r1) _VNEG_F32(r0, r1)
+#define vfp_negr_d(_jitp, r0, r1) _VNEG_F64(r0, r1)
+#define vfp_sqrtr_f(_jitp, r0, r1) _VSQRT_F32(r0, r1)
+#define vfp_sqrtr_d(_jitp, r0, r1) _VSQRT_F64(r0, r1)
+#define vfp_addr_f(_jitp, r0, r1, r2) _VADD_F32(r0, r1, r2)
+#define vfp_addr_d(_jitp, r0, r1, r2) _VADD_F64(r0, r1, r2)
+#define vfp_subr_f(_jitp, r0, r1, r2) _VSUB_F32(r0, r1, r2)
+#define vfp_subr_d(_jitp, r0, r1, r2) _VSUB_F64(r0, r1, r2)
+#define vfp_mulr_f(_jitp, r0, r1, r2) _VMUL_F32(r0, r1, r2)
+#define vfp_mulr_d(_jitp, r0, r1, r2) _VMUL_F64(r0, r1, r2)
+#define vfp_divr_f(_jitp, r0, r1, r2) _VDIV_F32(r0, r1, r2)
+#define vfp_divr_d(_jitp, r0, r1, r2) _VDIV_F64(r0, r1, r2)
+
+__jit_inline void
+_vcmp01_x(jit_state_t _jitp, int c0, int c1, jit_gpr_t r0)
+{
+ _VMRS(_R15);
+ if (jit_thumb_p()) {
+ if ((c0 ^ c1) >> 28 == 1) {
+ _ITE(c0);
+ if (r0 < 8) {
+ T1_MOVI(r0, 0);
+ T1_MOVI(r0, 1);
+ }
+ else {
+ T2_MOVI(r0, 0);
+ T2_MOVI(r0, 1);
+ }
+ }
+ else {
+ if (r0 < 8) {
+ _IT(c0);
+ T1_MOVI(r0, 0);
+ _IT(c1);
+ T1_MOVI(r0, 1);
+ }
+ else {
+ _IT(c0);
+ T2_MOVI(r0, 0);
+ _IT(c1);
+ T2_MOVI(r0, 1);
+ }
+ }
+ }
+ else {
+ _CC_MOVI(c0, r0, 0);
+ _CC_MOVI(c1, r0, 1);
+ }
+}
+
+__jit_inline void
+_vcmp01_f(jit_state_t _jitp, int c0, int c1,
+ jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ _VCMP_F32(r1, r2);
+ _vcmp01_x(_jitp, c0, c1, r0);
+}
+
+__jit_inline void
+_vcmp01_d(jit_state_t _jitp, int c0, int c1,
+ jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ _VCMP_F64(r1, r2);
+ _vcmp01_x(_jitp, c0, c1, r0);
+}
+
+#define vfp_ltr_f(_jitp,r0,r1,r2) _vcmp01_f(_jitp,ARM_CC_PL,ARM_CC_MI,r0,r1,r2)
+#define vfp_ltr_d(_jitp,r0,r1,r2) _vcmp01_d(_jitp,ARM_CC_PL,ARM_CC_MI,r0,r1,r2)
+#define vfp_ler_f(_jitp,r0,r1,r2) _vcmp01_f(_jitp,ARM_CC_HS,ARM_CC_LS,r0,r1,r2)
+#define vfp_ler_d(_jitp,r0,r1,r2) _vcmp01_d(_jitp,ARM_CC_HS,ARM_CC_LS,r0,r1,r2)
+#define vfp_eqr_f(_jitp,r0,r1,r2) _vcmp01_f(_jitp,ARM_CC_NE,ARM_CC_EQ,r0,r1,r2)
+#define vfp_eqr_d(_jitp,r0,r1,r2) _vcmp01_d(_jitp,ARM_CC_NE,ARM_CC_EQ,r0,r1,r2)
+#define vfp_ger_f(_jitp,r0,r1,r2) _vcmp01_f(_jitp,ARM_CC_LT,ARM_CC_GE,r0,r1,r2)
+#define vfp_ger_d(_jitp,r0,r1,r2) _vcmp01_d(_jitp,ARM_CC_LT,ARM_CC_GE,r0,r1,r2)
+#define vfp_gtr_f(_jitp,r0,r1,r2) _vcmp01_f(_jitp,ARM_CC_LE,ARM_CC_GT,r0,r1,r2)
+#define vfp_gtr_d(_jitp,r0,r1,r2) _vcmp01_d(_jitp,ARM_CC_LE,ARM_CC_GT,r0,r1,r2)
+#define vfp_ner_f(_jitp,r0,r1,r2) _vcmp01_f(_jitp,ARM_CC_EQ,ARM_CC_NE,r0,r1,r2)
+#define vfp_ner_d(_jitp,r0,r1,r2) _vcmp01_d(_jitp,ARM_CC_EQ,ARM_CC_NE,r0,r1,r2)
+
+__jit_inline void
+_vcmp10_x(jit_state_t _jitp, int cc, jit_gpr_t r0)
+{
+ if (jit_thumb_p()) {
+ if (r0 < 8) {
+ T1_MOVI(r0, 1);
+ _VMRS(_R15);
+ _IT(cc);
+ T1_MOVI(r0, 0);
+ }
+ else {
+ T2_MOVI(r0, 1);
+ _VMRS(_R15);
+ _IT(cc);
+ T2_MOVI(r0, 0);
+ }
+ }
+ else {
+ _VMRS(_R15);
+ _MOVI(r0, 1);
+ _CC_MOVI(cc, r0, 0);
+ }
+}
+
+__jit_inline void
+_vcmp_10_f(jit_state_t _jitp, int cc, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ _VCMP_F32(r1, r2);
+ _vcmp10_x(_jitp, cc, r0);
+}
+
+__jit_inline void
+_vcmp_10_d(jit_state_t _jitp, int cc, jit_gpr_t r0, jit_gpr_t r1, jit_gpr_t r2)
+{
+ _VCMP_F64(r1, r2);
+ _vcmp10_x(_jitp, cc, r0);
+}
+
+#define vfp_unltr_f(_jitp,r0,r1,r2) _vcmp_10_f(_jitp,ARM_CC_GE,r0,r1,r2)
+#define vfp_unltr_d(_jitp,r0,r1,r2) _vcmp_10_d(_jitp,ARM_CC_GE,r0,r1,r2)
+#define vfp_unler_f(_jitp,r0,r1,r2) _vcmp_10_f(_jitp,ARM_CC_GT,r0,r1,r2)
+#define vfp_unler_d(_jitp,r0,r1,r2) _vcmp_10_d(_jitp,ARM_CC_GT,r0,r1,r2)
+
+__jit_inline void
+vfp_uneqr_x(jit_state_t _jitp, jit_gpr_t r0)
+{
+ _VMRS(_R15);
+ if (jit_thumb_p()) {
+ _ITE(ARM_CC_NE);
+ if (r0 < 8) {
+ T1_MOVI(r0, 0);
+ T1_MOVI(r0, 1);
+ _IT(ARM_CC_VS);
+ T1_MOVI(r0, 1);
+ }
+ else {
+ T2_MOVI(r0, 0);
+ T2_MOVI(r0, 1);
+ _IT(ARM_CC_VS);
+ T2_MOVI(r0, 1);
+ }
+ }
+ else {
+ _CC_MOVI(ARM_CC_NE, r0, 0);
+ _CC_MOVI(ARM_CC_EQ, r0, 1);
+ _CC_MOVI(ARM_CC_VS, r0, 1);
+ }
+}
+
+__jit_inline void
+vfp_uneqr_f(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ _VCMP_F32(r1, r2);
+ vfp_uneqr_x(_jitp, r0);
+}
+
+__jit_inline void
+vfp_uneqr_d(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ _VCMP_F64(r1, r2);
+ vfp_uneqr_x(_jitp, r0);
+}
+
+__jit_inline void
+_vcmp_01_x(jit_state_t _jitp, int cc, jit_gpr_t r0)
+{
+ if (jit_thumb_p()) {
+ if (r0 < 8) {
+ T1_MOVI(r0, 0);
+ _VMRS(_R15);
+ _IT(cc);
+ T1_MOVI(r0, 1);
+ }
+ else {
+ T2_MOVI(r0, 0);
+ _VMRS(_R15);
+ _IT(cc);
+ T2_MOVI(r0, 1);
+ }
+ }
+ else {
+ _VMRS(_R15);
+ _MOVI(r0, 0);
+ _CC_MOVI(cc, r0, 1);
+ }
+}
+
+__jit_inline void
+_vcmp_01_f(jit_state_t _jitp, int cc, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ _VCMP_F32(r1, r2);
+ _vcmp_01_x(_jitp, cc, r0);
+}
+
+__jit_inline void
+_vcmp_01_d(jit_state_t _jitp, int cc, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ _VCMP_F64(r1, r2);
+ _vcmp_01_x(_jitp, cc, r0);
+}
+
+#define vfp_unger_f(_jitp,r0,r1,r2) _vcmp_01_f(_jitp,ARM_CC_CS,r0,r1,r2)
+#define vfp_unger_d(_jitp,r0,r1,r2) _vcmp_01_d(_jitp,ARM_CC_CS,r0,r1,r2)
+#define vfp_ungtr_f(_jitp,r0,r1,r2) _vcmp_01_f(_jitp,ARM_CC_HI,r0,r1,r2)
+#define vfp_ungtr_d(_jitp,r0,r1,r2) _vcmp_01_d(_jitp,ARM_CC_HI,r0,r1,r2)
+
+__jit_inline void
+_vfp_ltgtr_x(jit_state_t _jitp, jit_gpr_t r0)
+{
+ _VMRS(_R15);
+ if (jit_thumb_p()) {
+ _ITE(ARM_CC_NE);
+ if (r0 < 8) {
+ T1_MOVI(r0, 1);
+ T1_MOVI(r0, 0);
+ _IT(ARM_CC_VS);
+ T1_MOVI(r0, 0);
+ }
+ else {
+ T2_MOVI(r0, 1);
+ T2_MOVI(r0, 0);
+ _IT(ARM_CC_VS);
+ T2_MOVI(r0, 0);
+ }
+ }
+ else {
+ _CC_MOVI(ARM_CC_NE, r0, 1);
+ _CC_MOVI(ARM_CC_EQ, r0, 0);
+ _CC_MOVI(ARM_CC_VS, r0, 0);
+ }
+}
+
+__jit_inline void
+vfp_ltgtr_f(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ _VCMP_F32(r1, r2);
+ _vfp_ltgtr_x(_jitp, r0);
+}
+
+__jit_inline void
+vfp_ltgtr_d(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ _VCMP_F64(r1, r2);
+ _vfp_ltgtr_x(_jitp, r0);
+}
+
+__jit_inline void
+vfp_ordr_f(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ _VCMP_F32(r1, r2);
+ _vcmp10_x(_jitp, ARM_CC_VS, r0);
+}
+
+__jit_inline void
+vfp_ordr_d(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ _VCMP_F64(r1, r2);
+ _vcmp10_x(_jitp, ARM_CC_VS, r0);
+}
+
+__jit_inline void
+vfp_unordr_f(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ _VCMP_F32(r1, r2);
+ _vcmp_01_x(_jitp, ARM_CC_VS, r0);
+}
+
+__jit_inline void
+vfp_unordr_d(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ _VCMP_F64(r1, r2);
+ _vcmp_01_x(_jitp, ARM_CC_VS, r0);
+}
+
+__jit_inline jit_insn *
+_vbcmp_x(jit_state_t _jitp, int cc, jit_insn *i0)
+{
+ jit_insn *l;
+ _VMRS(_R15);
+ if (jit_thumb_p()) {
+ l = thumb_branch(_jitp, cc, i0);
+ }
+ else {
+ l = arm_branch(_jitp, cc, i0);
+ }
+ return (l);
+}
+
+__jit_inline jit_insn *
+_vbcmp_f(jit_state_t _jitp, int cc, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
+{
+ _VCMP_F32(r0, r1);
+ return (_vbcmp_x(_jitp, cc, i0));
+}
+
+__jit_inline jit_insn *
+_vbcmp_d(jit_state_t _jitp, int cc, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
+{
+ _VCMP_F64(r0, r1);
+ return (_vbcmp_x(_jitp, cc, i0));
+}
+
+#define vfp_bltr_f(_jitp,i0,r0,r1) _vbcmp_f(_jitp,ARM_CC_MI,i0,r0,r1)
+#define vfp_bltr_d(_jitp,i0,r0,r1) _vbcmp_d(_jitp,ARM_CC_MI,i0,r0,r1)
+#define vfp_bler_f(_jitp,i0,r0,r1) _vbcmp_f(_jitp,ARM_CC_LS,i0,r0,r1)
+#define vfp_bler_d(_jitp,i0,r0,r1) _vbcmp_d(_jitp,ARM_CC_LS,i0,r0,r1)
+#define vfp_beqr_f(_jitp,i0,r0,r1) _vbcmp_f(_jitp,ARM_CC_EQ,i0,r0,r1)
+#define vfp_beqr_d(_jitp,i0,r0,r1) _vbcmp_d(_jitp,ARM_CC_EQ,i0,r0,r1)
+#define vfp_bger_f(_jitp,i0,r0,r1) _vbcmp_f(_jitp,ARM_CC_GE,i0,r0,r1)
+#define vfp_bger_d(_jitp,i0,r0,r1) _vbcmp_d(_jitp,ARM_CC_GE,i0,r0,r1)
+#define vfp_bgtr_f(_jitp,i0,r0,r1) _vbcmp_f(_jitp,ARM_CC_GT,i0,r0,r1)
+#define vfp_bgtr_d(_jitp,i0,r0,r1) _vbcmp_d(_jitp,ARM_CC_GT,i0,r0,r1)
+#define vfp_bner_f(_jitp,i0,r0,r1) _vbcmp_f(_jitp,ARM_CC_NE,i0,r0,r1)
+#define vfp_bner_d(_jitp,i0,r0,r1) _vbcmp_d(_jitp,ARM_CC_NE,i0,r0,r1)
+
+__jit_inline jit_insn *
+_vbncmp_x(jit_state_t _jitp, int cc, jit_insn *i0)
+{
+ jit_insn *i;
+ jit_insn *l;
+ _VMRS(_R15);
+ i = jit_get_ip();
+ if (jit_thumb_p()) {
+ T2_CC_B(cc, 0);
+ l = thumb_branch(_jitp, ARM_CC_AL, i0);
+ }
+ else {
+ _CC_B(cc, 0);
+ l = arm_branch(_jitp, ARM_CC_AL, i0);
+ }
+ jit_patch(i);
+ return (l);
+}
+
+__jit_inline jit_insn *
+_vbncmp_f(jit_state_t _jitp, int cc, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
+{
+ _VCMP_F32(r0, r1);
+ return (_vbncmp_x(_jitp, cc, i0));
+}
+
+__jit_inline jit_insn *
+_vbncmp_d(jit_state_t _jitp, int cc, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
+{
+ _VCMP_F64(r0, r1);
+ return (_vbncmp_x(_jitp, cc, i0));
+}
+
+#define vfp_bunltr_f(_jitp,i0,r0,r1) _vbncmp_f(_jitp,ARM_CC_GE,i0,r0,r1)
+#define vfp_bunltr_d(_jitp,i0,r0,r1) _vbncmp_d(_jitp,ARM_CC_GE,i0,r0,r1)
+#define vfp_bunler_f(_jitp,i0,r0,r1) _vbncmp_f(_jitp,ARM_CC_GT,i0,r0,r1)
+#define vfp_bunler_d(_jitp,i0,r0,r1) _vbncmp_d(_jitp,ARM_CC_GT,i0,r0,r1)
+
+__jit_inline jit_insn *
+vfp_buneqr_x(jit_state_t _jitp, jit_insn *i0)
+{
+ jit_insn *i;
+ jit_insn *j;
+ jit_insn *l;
+ _VMRS(_R15);
+ i = jit_get_ip();
+ if (jit_thumb_p()) {
+ T2_CC_B(ARM_CC_VS, 0);
+ j = jit_get_ip();
+ T2_CC_B(ARM_CC_NE, 0);
+ jit_patch(i);
+ l = thumb_branch(_jitp, ARM_CC_AL, i0);
+ }
+ else {
+ _CC_B(ARM_CC_VS, 0);
+ j = jit_get_ip();
+ _CC_B(ARM_CC_NE, 0);
+ jit_patch(i);
+ l = arm_branch(_jitp, ARM_CC_AL, i0);
+ }
+ jit_patch(j);
+ return (l);
+}
+
+__jit_inline jit_insn *
+vfp_buneqr_f(jit_state_t _jitp, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
+{
+ _VCMP_F32(r0, r1);
+ return (vfp_buneqr_x(_jitp, i0));
+}
+
+__jit_inline jit_insn *
+vfp_buneqr_d(jit_state_t _jitp, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
+{
+ _VCMP_F64(r0, r1);
+ return (vfp_buneqr_x(_jitp, i0));
+}
+
+__jit_inline jit_insn *
+vfp_bunger_x(jit_state_t _jitp, jit_insn *i0)
+{
+ jit_insn *i;
+ jit_insn *l;
+ _VMRS(_R15);
+ i = jit_get_ip();
+ if (jit_thumb_p()) {
+ T2_CC_B(ARM_CC_MI, 0);
+ l = thumb_branch(_jitp, ARM_CC_HS, i0);
+ }
+ else {
+ _CC_B(ARM_CC_MI, 0);
+ l = arm_branch(_jitp, ARM_CC_HS, i0);
+ }
+ jit_patch(i);
+ return (l);
+}
+
+__jit_inline jit_insn *
+vfp_bunger_f(jit_state_t _jitp, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
+{
+ _VCMP_F32(r0, r1);
+ return (vfp_bunger_x(_jitp, i0));
+}
+
+__jit_inline jit_insn *
+vfp_bunger_d(jit_state_t _jitp, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
+{
+ _VCMP_F64(r0, r1);
+ return (vfp_bunger_x(_jitp, i0));
+}
+
+#define vfp_bungtr_f(_jitp,i0,r0,r1) _vbcmp_f(_jitp,ARM_CC_HI,i0,r0,r1)
+#define vfp_bungtr_d(_jitp,i0,r0,r1) _vbcmp_d(_jitp,ARM_CC_HI,i0,r0,r1)
+
+__jit_inline jit_insn *
+vfp_bltgtr_x(jit_state_t _jitp, jit_insn *i0)
+{
+ jit_insn *i;
+ jit_insn *j;
+ jit_insn *l;
+ _VMRS(_R15);
+ i = jit_get_ip();
+ if (jit_thumb_p()) {
+ T2_CC_B(ARM_CC_VS, 0);
+ j = jit_get_ip();
+ T2_CC_B(ARM_CC_EQ, 0);
+ l = thumb_branch(_jitp, ARM_CC_AL, i0);
+ }
+ else {
+ _CC_B(ARM_CC_VS, 0);
+ j = jit_get_ip();
+ _CC_B(ARM_CC_EQ, 0);
+ l = arm_branch(_jitp, ARM_CC_AL, i0);
+ }
+ jit_patch(i);
+ jit_patch(j);
+ return (l);
+}
+
+__jit_inline jit_insn *
+vfp_bltgtr_f(jit_state_t _jitp, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
+{
+ _VCMP_F32(r0, r1);
+ return (vfp_bltgtr_x(_jitp, i0));
+}
+
+__jit_inline jit_insn *
+vfp_bltgtr_d(jit_state_t _jitp, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
+{
+ _VCMP_F64(r0, r1);
+ return (vfp_bltgtr_x(_jitp, i0));
+}
+
+#define vfp_bordr_f(_jitp,i0,r0,r1) _vbcmp_f(_jitp,ARM_CC_VC,i0,r0,r1)
+#define vfp_bordr_d(_jitp,i0,r0,r1) _vbcmp_d(_jitp,ARM_CC_VC,i0,r0,r1)
+#define vfp_bunordr_f(_jitp,i0,r0,r1) _vbcmp_f(_jitp,ARM_CC_VS,i0,r0,r1)
+#define vfp_bunordr_d(_jitp,i0,r0,r1) _vbcmp_d(_jitp,ARM_CC_VS,i0,r0,r1)
+#define vfp_ldr_f(_jitp, r0, r1) _VLDR_F32(r0, r1, 0)
+#define vfp_ldr_d(_jitp, r0, r1) _VLDR_F64(r0, r1, 0)
+
+__jit_inline void
+vfp_ldi_f(jit_state_t _jitp, jit_fpr_t r0, void *i0)
+{
+ jit_movi_i(JIT_FTMP, (int)i0);
+ _VLDR_F32(r0, JIT_FTMP, 0);
+}
+
+__jit_inline void
+vfp_ldi_d(jit_state_t _jitp, jit_fpr_t r0, void *i0)
+{
+ jit_movi_i(JIT_FTMP, (int)i0);
+ _VLDR_F64(r0, JIT_FTMP, 0);
+}
+
+__jit_inline void
+vfp_ldxr_f(jit_state_t _jitp, jit_fpr_t r0, jit_gpr_t r1, jit_gpr_t r2)
+{
+ jit_addr_i(JIT_FTMP, r1, r2);
+ _VLDR_F32(r0, JIT_FTMP, 0);
+}
+
+__jit_inline void
+vfp_ldxr_d(jit_state_t _jitp, jit_fpr_t r0, jit_gpr_t r1, jit_gpr_t r2)
+{
+ jit_addr_i(JIT_FTMP, r1, r2);
+ _VLDR_F64(r0, JIT_FTMP, 0);
+}
+
+__jit_inline void
+vfp_ldxi_f(jit_state_t _jitp, jit_fpr_t r0, jit_gpr_t r1, int i0)
+{
+ if (i0 >= 0) {
+ assert(!(i0 & 3));
+ i0 >>= 2;
+ if (i0 < 256)
+ _VLDR_F32(r0, r1, i0);
+ else {
+ jit_addi_i(JIT_FTMP, r1, i0);
+ _VLDR_F32(r0, JIT_FTMP, 0);
+ }
+ }
+ else {
+ i0 = -i0;
+ assert(!(i0 & 3));
+ i0 >>= 2;
+ if (i0 < 256)
+ _VLDRN_F32(r0, r1, i0);
+ else {
+ jit_subi_i(JIT_FTMP, r1, i0);
+ _VLDR_F32(r0, JIT_FTMP, 0);
+ }
+ }
+}
+
+__jit_inline void
+vfp_ldxi_d(jit_state_t _jitp, jit_fpr_t r0, jit_gpr_t r1, int i0)
+{
+ if (i0 >= 0) {
+ assert(!(i0 & 3));
+ i0 >>= 2;
+ if (i0 < 256)
+ _VLDR_F64(r0, r1, i0);
+ else {
+ jit_addi_i(JIT_FTMP, r1, i0);
+ _VLDR_F64(r0, JIT_FTMP, 0);
+ }
+ }
+ else {
+ i0 = -i0;
+ assert(!(i0 & 3));
+ i0 >>= 2;
+ if (i0 < 256)
+ _VLDRN_F64(r0, r1, i0);
+ else {
+ jit_subi_i(JIT_FTMP, r1, i0);
+ _VLDR_F64(r0, JIT_FTMP, 0);
+ }
+ }
+}
+
+#define vfp_str_f(_jitp, r0, r1) _VSTR_F32(r1, r0, 0)
+#define vfp_str_d(_jitp, r0, r1) _VSTR_F64(r1, r0, 0)
+
+__jit_inline void
+vfp_sti_f(jit_state_t _jitp, void *i0, jit_fpr_t r0)
+{
+ jit_movi_i(JIT_FTMP, (int)i0);
+ _VSTR_F32(r0, JIT_FTMP, 0);
+}
+
+__jit_inline void
+vfp_sti_d(jit_state_t _jitp, void *i0, jit_fpr_t r0)
+{
+ jit_movi_i(JIT_FTMP, (int)i0);
+ _VSTR_F64(r0, JIT_FTMP, 0);
+}
+
+__jit_inline void
+vfp_stxr_f(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, jit_fpr_t r2)
+{
+ jit_addr_i(JIT_FTMP, r0, r1);
+ _VSTR_F32(r2, JIT_FTMP, 0);
+}
+
+__jit_inline void
+vfp_stxr_d(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, jit_fpr_t r2)
+{
+ jit_addr_i(JIT_FTMP, r0, r1);
+ _VSTR_F64(r2, JIT_FTMP, 0);
+}
+
+__jit_inline void
+vfp_stxi_f(jit_state_t _jitp, int i0, jit_gpr_t r0, jit_fpr_t r1)
+{
+ if (i0 >= 0) {
+ assert(!(i0 & 3));
+ i0 >>= 2;
+ if (i0 < 256)
+ _VSTR_F32(r1, r0, i0);
+ else {
+ jit_addi_i(JIT_FTMP, r0, i0);
+ _VSTR_F32(r1, JIT_FTMP, 0);
+ }
+ }
+ else {
+ i0 = -i0;
+ assert(!(i0 & 3));
+ i0 >>= 2;
+ if (i0 < 256)
+ _VSTRN_F32(r1, r0, i0);
+ else {
+ jit_subi_i(JIT_FTMP, r0, i0);
+ _VSTR_F32(r1, JIT_FTMP, 0);
+ }
+ }
+}
+
+__jit_inline void
+vfp_stxi_d(jit_state_t _jitp, int i0, jit_gpr_t r0, jit_fpr_t r1)
+{
+ if (i0 >= 0) {
+ assert(!(i0 & 3));
+ i0 >>= 2;
+ if (i0 < 256)
+ _VSTR_F64(r1, r0, i0);
+ else {
+ jit_addi_i(JIT_FTMP, r0, i0);
+ _VSTR_F64(r1, JIT_FTMP, 0);
+ }
+ }
+ else {
+ i0 = -i0;
+ assert(!(i0 & 3));
+ i0 >>= 2;
+ if (i0 < 256)
+ _VSTRN_F64(r1, r0, i0);
+ else {
+ jit_subi_i(JIT_FTMP, r0, i0);
+ _VSTR_F64(r1, JIT_FTMP, 0);
+ }
+ }
+}
+
+__jit_inline void
+vfp_getarg_f(jit_state_t _jitp, jit_fpr_t r0, int i0)
+{
+ if (jit_hardfp_p()) {
+ if (i0 < 16) {
+ if (r0 != (jit_fpr_t)i0)
+ _VMOV_F32(r0, (jit_fpr_t)i0);
+ return;
+ }
+ }
+ else if (i0 < 4) {
+ /* registers are already saved on stack and argument registers
+ * may have been clobbered */
+#if 0
+ _VMOV_S_A(r0, i0);
+#else
+ vfp_ldxi_f(_jitp, r0, JIT_FP, i0 << 2);
+#endif
+ return;
+ }
+ vfp_ldxi_f(_jitp, r0, JIT_FP, i0);
+}
+
+__jit_inline void
+vfp_getarg_d(jit_state_t _jitp, jit_fpr_t r0, int i0)
+{
+ if (jit_hardfp_p()) {
+ if (i0 < 16) {
+ if (r0 != (jit_fpr_t)i0)
+ _VMOV_F64(r0, (jit_fpr_t)i0);
+ return;
+ }
+ }
+ else if (i0 < 4) {
+ /* registers are already saved on stack and argument registers
+ * may have been clobbered */
+#if 0
+ _VMOV_D_AA(r0, i0, i0 + 1);
+#else
+ vfp_ldxi_d(_jitp, r0, JIT_FP, i0 << 2);
+#endif
+ return;
+ }
+ vfp_ldxi_d(_jitp, r0, JIT_FP, i0);
+}
+
+__jit_inline void
+vfp_pusharg_f(jit_state_t _jitp, jit_fpr_t r0)
+{
+ assert(0);
+}
+
+__jit_inline void
+vfp_pusharg_d(jit_state_t _jitp, jit_fpr_t r0)
+{
+ assert(0);
+}
+
+__jit_inline void
+vfp_retval_f(jit_state_t _jitp, jit_fpr_t r0)
+{
+ assert(0);
+}
+
+__jit_inline void
+vfp_retval_d(jit_state_t _jitp, jit_fpr_t r0)
+{
+ assert(0);
+}
+
+#undef vfp_unget_tmp
+#undef vfp_get_tmp
+
+#endif /* __lightning_fp_vfp_h */
diff --git a/src/racket/src/lightning/arm/fp.h b/src/racket/src/lightning/arm/fp.h
new file mode 100644
index 0000000000..12f823a25e
--- /dev/null
+++ b/src/racket/src/lightning/arm/fp.h
@@ -0,0 +1,1074 @@
+/******************************** -*- C -*- ****************************
+ *
+ * Floating-point support (arm)
+ *
+ ***********************************************************************/
+
+/***********************************************************************
+ *
+ * Copyright 2011 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU lightning.
+ *
+ * GNU lightning 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU lightning 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 GNU lightning; see the file COPYING.LESSER; if not, write to the
+ * Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * Authors:
+ * Paulo Cesar Pereira de Andrade
+ ***********************************************************************/
+
+#ifndef __lightning_fp_arm_h
+#define __lightning_fp_arm_h
+
+#define JIT_FPR_NUM 6
+
+#define JIT_FPR(n) (_D0+((n)<<1))
+
+#include "fp-swf.h"
+#include "fp-vfp.h"
+
+#define jit_movr_f(r0, r1) arm_movr_f(_jitp, r0, r1)
+__jit_inline void
+arm_movr_f(jit_state_t _jitp, jit_fpr_t r0, jit_fpr_t r1)
+{
+ if (jit_swf_p()) swf_movr_f(_jitp, r0, r1);
+ else vfp_movr_f(_jitp, r0, r1);
+}
+
+#define jit_movr_d(r0, r1) arm_movr_d(_jitp, r0, r1)
+__jit_inline void
+arm_movr_d(jit_state_t _jitp, jit_fpr_t r0, jit_fpr_t r1)
+{
+ if (jit_swf_p()) swf_movr_d(_jitp, r0, r1);
+ else vfp_movr_d(_jitp, r0, r1);
+}
+
+#define jit_movi_f(r0, i0) arm_movi_f(_jitp, r0, i0)
+__jit_inline void
+arm_movi_f(jit_state_t _jitp, jit_fpr_t r0, float i0)
+{
+ if (jit_swf_p()) swf_movi_f(_jitp, r0, i0);
+ else vfp_movi_f(_jitp, r0, i0);
+}
+
+#define jit_movi_d(r0, i0) arm_movi_d(_jitp, r0, i0)
+__jit_inline void
+arm_movi_d(jit_state_t _jitp, jit_fpr_t r0, double i0)
+{
+ if (jit_swf_p()) swf_movi_d(_jitp, r0, i0);
+ else vfp_movi_d(_jitp, r0, i0);
+}
+
+#define jit_extr_i_f(r0, r1) arm_extr_i_f(_jitp, r0, r1)
+__jit_inline void
+arm_extr_i_f(jit_state_t _jitp, jit_fpr_t r0, jit_gpr_t r1)
+{
+ assert(r0 != JIT_FPRET);
+ if (jit_swf_p()) swf_extr_i_f(_jitp, r0, r1);
+ else vfp_extr_i_f(_jitp, r0, r1);
+}
+
+#define jit_extr_i_d(r0, r1) arm_extr_i_d(_jitp, r0, r1)
+__jit_inline void
+arm_extr_i_d(jit_state_t _jitp, jit_fpr_t r0, jit_gpr_t r1)
+{
+ assert(r0 != JIT_FPRET);
+ if (jit_swf_p()) swf_extr_i_d(_jitp, r0, r1);
+ else vfp_extr_i_d(_jitp, r0, r1);
+}
+
+#define jit_extr_d_f(r0, r1) arm_extr_d_f(_jitp, r0, r1)
+__jit_inline void
+arm_extr_d_f(jit_state_t _jitp, jit_fpr_t r0, jit_fpr_t r1)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET);
+ if (jit_swf_p()) swf_extr_d_f(_jitp, r0, r1);
+ else vfp_extr_d_f(_jitp, r0, r1);
+}
+
+#define jit_extr_f_d(r0, r1) arm_extr_f_d(_jitp, r0, r1)
+__jit_inline void
+arm_extr_f_d(jit_state_t _jitp, jit_fpr_t r0, jit_fpr_t r1)
+{
+ if (jit_swf_p()) swf_extr_f_d(_jitp, r0, r1);
+ else vfp_extr_f_d(_jitp, r0, r1);
+}
+
+#define jit_rintr_f_i(r0, r1) arm_rintr_f_i(_jitp, r0, r1)
+__jit_inline void
+arm_rintr_f_i(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1)
+{
+ assert(r1 != JIT_FPRET);
+ if (jit_swf_p()) swf_rintr_f_i(_jitp, r0, r1);
+ else vfp_rintr_f_i(_jitp, r0, r1);
+}
+
+#define jit_rintr_d_i(r0, r1) arm_rintr_d_i(_jitp, r0, r1)
+__jit_inline void
+arm_rintr_d_i(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1)
+{
+ assert(r1 != JIT_FPRET);
+ if (jit_swf_p()) swf_rintr_d_i(_jitp, r0, r1);
+ else vfp_rintr_d_i(_jitp, r0, r1);
+}
+
+#define jit_roundr_f_i(r0, r1) arm_roundr_f_i(_jitp, r0, r1)
+__jit_inline void
+arm_roundr_f_i(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1)
+{
+ assert(r1 != JIT_FPRET);
+ if (jit_swf_p()) swf_roundr_f_i(_jitp, r0, r1);
+ else vfp_roundr_f_i(_jitp, r0, r1);
+}
+
+#define jit_roundr_d_i(r0, r1) arm_roundr_d_i(_jitp, r0, r1)
+__jit_inline void
+arm_roundr_d_i(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1)
+{
+ assert(r1 != JIT_FPRET);
+ if (jit_swf_p()) swf_roundr_d_i(_jitp, r0, r1);
+ else vfp_roundr_d_i(_jitp, r0, r1);
+}
+
+#define jit_truncr_f_i(r0, r1) arm_truncr_f_i(_jitp, r0, r1)
+__jit_inline void
+arm_truncr_f_i(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1)
+{
+ assert(r1 != JIT_FPRET);
+ if (jit_swf_p()) swf_truncr_f_i(_jitp, r0, r1);
+ else vfp_truncr_f_i(_jitp, r0, r1);
+}
+
+#define jit_truncr_d_i(r0, r1) arm_truncr_d_i(_jitp, r0, r1)
+__jit_inline void
+arm_truncr_d_i(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1)
+{
+ assert(r1 != JIT_FPRET);
+ if (jit_swf_p()) swf_truncr_d_i(_jitp, r0, r1);
+ else vfp_truncr_d_i(_jitp, r0, r1);
+}
+
+#define jit_ceilr_f_i(r0, r1) arm_ceilr_f_i(_jitp, r0, r1)
+__jit_inline void
+arm_ceilr_f_i(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1)
+{
+ assert(r1 != JIT_FPRET);
+ if (jit_swf_p()) swf_ceilr_f_i(_jitp, r0, r1);
+ else vfp_ceilr_f_i(_jitp, r0, r1);
+}
+
+#define jit_ceilr_d_i(r0, r1) arm_ceilr_d_i(_jitp, r0, r1)
+__jit_inline void
+arm_ceilr_d_i(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1)
+{
+ assert(r1 != JIT_FPRET);
+ if (jit_swf_p()) swf_ceilr_d_i(_jitp, r0, r1);
+ else vfp_ceilr_d_i(_jitp, r0, r1);
+}
+
+#define jit_floorr_f_i(r0, r1) arm_floorr_f_i(_jitp, r0, r1)
+__jit_inline void
+arm_floorr_f_i(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1)
+{
+ assert(r1 != JIT_FPRET);
+ if (jit_swf_p()) swf_floorr_f_i(_jitp, r0, r1);
+ else vfp_floorr_f_i(_jitp, r0, r1);
+}
+
+#define jit_floorr_d_i(r0, r1) arm_floorr_d_i(_jitp, r0, r1)
+__jit_inline void
+arm_floorr_d_i(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1)
+{
+ assert(r1 != JIT_FPRET);
+ if (jit_swf_p()) swf_floorr_d_i(_jitp, r0, r1);
+ else vfp_floorr_d_i(_jitp, r0, r1);
+}
+
+#define jit_absr_f(r0, r1) arm_absr_f(_jitp, r0, r1)
+__jit_inline void
+arm_absr_f(jit_state_t _jitp, jit_fpr_t r0, jit_fpr_t r1)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET);
+ if (jit_swf_p()) swf_absr_f(_jitp, r0, r1);
+ else vfp_absr_f(_jitp, r0, r1);
+}
+
+#define jit_absr_d(r0, r1) arm_absr_d(_jitp, r0, r1)
+__jit_inline void
+arm_absr_d(jit_state_t _jitp, jit_fpr_t r0, jit_fpr_t r1)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET);
+ if (jit_swf_p()) swf_absr_d(_jitp, r0, r1);
+ else vfp_absr_d(_jitp, r0, r1);
+}
+#define jit_abs_d(r0, r1) jit_absr_d(r0, r1)
+
+#define jit_negr_f(r0, r1) arm_negr_f(_jitp, r0, r1)
+__jit_inline void
+arm_negr_f(jit_state_t _jitp, jit_fpr_t r0, jit_fpr_t r1)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET);
+ if (jit_swf_p()) swf_negr_f(_jitp, r0, r1);
+ else vfp_negr_f(_jitp, r0, r1);
+}
+
+#define jit_negr_d(r0, r1) arm_negr_d(_jitp, r0, r1)
+__jit_inline void
+arm_negr_d(jit_state_t _jitp, jit_fpr_t r0, jit_fpr_t r1)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET);
+ if (jit_swf_p()) swf_negr_d(_jitp, r0, r1);
+ else vfp_negr_d(_jitp, r0, r1);
+}
+
+#define jit_sqrtr_f(r0, r1) arm_sqrtr_f(_jitp, r0, r1)
+__jit_inline void
+arm_sqrtr_f(jit_state_t _jitp, jit_fpr_t r0, jit_fpr_t r1)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET);
+ if (jit_swf_p()) swf_sqrtr_f(_jitp, r0, r1);
+ else vfp_sqrtr_f(_jitp, r0, r1);
+}
+
+#define jit_sqrtr_d(r0, r1) arm_sqrtr_d(_jitp, r0, r1)
+__jit_inline void
+arm_sqrtr_d(jit_state_t _jitp, jit_fpr_t r0, jit_fpr_t r1)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET);
+ if (jit_swf_p()) swf_sqrtr_d(_jitp, r0, r1);
+ else vfp_sqrtr_d(_jitp, r0, r1);
+}
+#define jit_sqrt_d(r0, r1) jit_sqrtr_d(r0, r1)
+
+#define jit_addr_f(r0, r1, r2) arm_addr_f(_jitp, r0, r1, r2)
+__jit_inline void
+arm_addr_f(jit_state_t _jitp, jit_fpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET && r2 != JIT_FPRET);
+ if (jit_swf_p()) swf_addr_f(_jitp, r0, r1, r2);
+ else vfp_addr_f(_jitp, r0, r1, r2);
+}
+
+#define jit_addr_d(r0, r1, r2) arm_addr_d(_jitp, r0, r1, r2)
+__jit_inline void
+arm_addr_d(jit_state_t _jitp, jit_fpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET && r2 != JIT_FPRET);
+ if (jit_swf_p()) swf_addr_d(_jitp, r0, r1, r2);
+ else vfp_addr_d(_jitp, r0, r1, r2);
+}
+
+#define jit_subr_f(r0, r1, r2) arm_subr_f(_jitp, r0, r1, r2)
+__jit_inline void
+arm_subr_f(jit_state_t _jitp, jit_fpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET && r2 != JIT_FPRET);
+ if (jit_swf_p()) swf_subr_f(_jitp, r0, r1, r2);
+ else vfp_subr_f(_jitp, r0, r1, r2);
+}
+
+#define jit_subr_d(r0, r1, r2) arm_subr_d(_jitp, r0, r1, r2)
+#define jit_subrr_d(r0, r1, r2) arm_subr_d(_jitp, r0, r2, r1)
+__jit_inline void
+arm_subr_d(jit_state_t _jitp, jit_fpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET && r2 != JIT_FPRET);
+ if (jit_swf_p()) swf_subr_d(_jitp, r0, r1, r2);
+ else vfp_subr_d(_jitp, r0, r1, r2);
+}
+
+#define jit_mulr_f(r0, r1, r2) arm_mulr_f(_jitp, r0, r1, r2)
+__jit_inline void
+arm_mulr_f(jit_state_t _jitp, jit_fpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET && r2 != JIT_FPRET);
+ if (jit_swf_p()) swf_mulr_f(_jitp, r0, r1, r2);
+ else vfp_mulr_f(_jitp, r0, r1, r2);
+}
+
+#define jit_mulr_d(r0, r1, r2) arm_mulr_d(_jitp, r0, r1, r2)
+__jit_inline void
+arm_mulr_d(jit_state_t _jitp, jit_fpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET && r2 != JIT_FPRET);
+ if (jit_swf_p()) swf_mulr_d(_jitp, r0, r1, r2);
+ else vfp_mulr_d(_jitp, r0, r1, r2);
+}
+
+#define jit_divr_f(r0, r1, r2) arm_divr_f(_jitp, r0, r1, r2)
+__jit_inline void
+arm_divr_f(jit_state_t _jitp, jit_fpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET && r2 != JIT_FPRET);
+ if (jit_swf_p()) swf_divr_f(_jitp, r0, r1, r2);
+ else vfp_divr_f(_jitp, r0, r1, r2);
+}
+
+#define jit_divr_d(r0, r1, r2) arm_divr_d(_jitp, r0, r1, r2)
+#define jit_divrr_d(r0, r1, r2) arm_divr_d(_jitp, r0, r2, r1)
+__jit_inline void
+arm_divr_d(jit_state_t _jitp, jit_fpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET && r2 != JIT_FPRET);
+ if (jit_swf_p()) swf_divr_d(_jitp, r0, r1, r2);
+ else vfp_divr_d(_jitp, r0, r1, r2);
+}
+
+#define jit_ltr_f(r0, r1, r2) arm_ltr_f(_jitp, r0, r1, r2)
+__jit_inline void
+arm_ltr_f(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ assert(r1 != JIT_FPRET && r2 != JIT_FPRET);
+ if (jit_swf_p()) swf_ltr_f(_jitp, r0, r1, r2);
+ else vfp_ltr_f(_jitp, r0, r1, r2);
+}
+
+#define jit_ltr_d(r0, r1, r2) arm_ltr_d(_jitp, r0, r1, r2)
+__jit_inline void
+arm_ltr_d(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ assert(r1 != JIT_FPRET && r2 != JIT_FPRET);
+ if (jit_swf_p()) swf_ltr_d(_jitp, r0, r1, r2);
+ else vfp_ltr_d(_jitp, r0, r1, r2);
+}
+
+#define jit_ler_f(r0, r1, r2) arm_ler_f(_jitp, r0, r1, r2)
+__jit_inline void
+arm_ler_f(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ assert(r1 != JIT_FPRET && r2 != JIT_FPRET);
+ if (jit_swf_p()) swf_ler_f(_jitp, r0, r1, r2);
+ else vfp_ler_f(_jitp, r0, r1, r2);
+}
+
+#define jit_ler_d(r0, r1, r2) arm_ler_d(_jitp, r0, r1, r2)
+__jit_inline void
+arm_ler_d(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ assert(r1 != JIT_FPRET && r2 != JIT_FPRET);
+ if (jit_swf_p()) swf_ler_d(_jitp, r0, r1, r2);
+ else vfp_ler_d(_jitp, r0, r1, r2);
+}
+
+#define jit_eqr_f(r0, r1, r2) arm_eqr_f(_jitp, r0, r1, r2)
+__jit_inline void
+arm_eqr_f(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ assert(r1 != JIT_FPRET && r2 != JIT_FPRET);
+ if (jit_swf_p()) swf_eqr_f(_jitp, r0, r1, r2);
+ else vfp_eqr_f(_jitp, r0, r1, r2);
+}
+
+#define jit_eqr_d(r0, r1, r2) arm_eqr_d(_jitp, r0, r1, r2)
+__jit_inline void
+arm_eqr_d(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ assert(r1 != JIT_FPRET && r2 != JIT_FPRET);
+ if (jit_swf_p()) swf_eqr_d(_jitp, r0, r1, r2);
+ else vfp_eqr_d(_jitp, r0, r1, r2);
+}
+
+#define jit_ger_f(r0, r1, r2) arm_ger_f(_jitp, r0, r1, r2)
+__jit_inline void
+arm_ger_f(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ assert(r1 != JIT_FPRET && r2 != JIT_FPRET);
+ if (jit_swf_p()) swf_ger_f(_jitp, r0, r1, r2);
+ else vfp_ger_f(_jitp, r0, r1, r2);
+}
+
+#define jit_ger_d(r0, r1, r2) arm_ger_d(_jitp, r0, r1, r2)
+__jit_inline void
+arm_ger_d(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ assert(r1 != JIT_FPRET && r2 != JIT_FPRET);
+ if (jit_swf_p()) swf_ger_d(_jitp, r0, r1, r2);
+ else vfp_ger_d(_jitp, r0, r1, r2);
+}
+
+#define jit_gtr_f(r0, r1, r2) arm_gtr_f(_jitp, r0, r1, r2)
+__jit_inline void
+arm_gtr_f(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ assert(r1 != JIT_FPRET && r2 != JIT_FPRET);
+ if (jit_swf_p()) swf_gtr_f(_jitp, r0, r1, r2);
+ else vfp_gtr_f(_jitp, r0, r1, r2);
+}
+
+#define jit_gtr_d(r0, r1, r2) arm_gtr_d(_jitp, r0, r1, r2)
+__jit_inline void
+arm_gtr_d(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ assert(r1 != JIT_FPRET && r2 != JIT_FPRET);
+ if (jit_swf_p()) swf_gtr_d(_jitp, r0, r1, r2);
+ else vfp_gtr_d(_jitp, r0, r1, r2);
+}
+
+#define jit_ner_f(r0, r1, r2) arm_ner_f(_jitp, r0, r1, r2)
+__jit_inline void
+arm_ner_f(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ assert(r1 != JIT_FPRET && r2 != JIT_FPRET);
+ if (jit_swf_p()) swf_ner_f(_jitp, r0, r1, r2);
+ else vfp_ner_f(_jitp, r0, r1, r2);
+}
+
+#define jit_ner_d(r0, r1, r2) arm_ner_d(_jitp, r0, r1, r2)
+__jit_inline void
+arm_ner_d(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ assert(r1 != JIT_FPRET && r2 != JIT_FPRET);
+ if (jit_swf_p()) swf_ner_d(_jitp, r0, r1, r2);
+ else vfp_ner_d(_jitp, r0, r1, r2);
+}
+
+#define jit_unltr_f(r0, r1, r2) arm_unltr_f(_jitp, r0, r1, r2)
+__jit_inline void
+arm_unltr_f(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ assert(r1 != JIT_FPRET && r2 != JIT_FPRET);
+ if (jit_swf_p()) swf_unltr_f(_jitp, r0, r1, r2);
+ else vfp_unltr_f(_jitp, r0, r1, r2);
+}
+
+#define jit_unltr_d(r0, r1, r2) arm_unltr_d(_jitp, r0, r1, r2)
+__jit_inline void
+arm_unltr_d(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ assert(r1 != JIT_FPRET && r2 != JIT_FPRET);
+ if (jit_swf_p()) swf_unltr_d(_jitp, r0, r1, r2);
+ else vfp_unltr_d(_jitp, r0, r1, r2);
+}
+
+#define jit_unler_f(r0, r1, r2) arm_unler_f(_jitp, r0, r1, r2)
+__jit_inline void
+arm_unler_f(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ assert(r1 != JIT_FPRET && r2 != JIT_FPRET);
+ if (jit_swf_p()) swf_unler_f(_jitp, r0, r1, r2);
+ else vfp_unler_f(_jitp, r0, r1, r2);
+}
+
+#define jit_unler_d(r0, r1, r2) arm_unler_d(_jitp, r0, r1, r2)
+__jit_inline void
+arm_unler_d(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ assert(r1 != JIT_FPRET && r2 != JIT_FPRET);
+ if (jit_swf_p()) swf_unler_d(_jitp, r0, r1, r2);
+ else vfp_unler_d(_jitp, r0, r1, r2);
+}
+
+#define jit_uneqr_f(r0, r1, r2) arm_uneqr_f(_jitp, r0, r1, r2)
+__jit_inline void
+arm_uneqr_f(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ assert(r1 != JIT_FPRET && r2 != JIT_FPRET);
+ if (jit_swf_p()) swf_uneqr_f(_jitp, r0, r1, r2);
+ else vfp_uneqr_f(_jitp, r0, r1, r2);
+}
+
+#define jit_uneqr_d(r0, r1, r2) arm_uneqr_d(_jitp, r0, r1, r2)
+__jit_inline void
+arm_uneqr_d(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ assert(r1 != JIT_FPRET && r2 != JIT_FPRET);
+ if (jit_swf_p()) swf_uneqr_d(_jitp, r0, r1, r2);
+ else vfp_uneqr_d(_jitp, r0, r1, r2);
+}
+
+#define jit_unger_f(r0, r1, r2) arm_unger_f(_jitp, r0, r1, r2)
+__jit_inline void
+arm_unger_f(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ assert(r1 != JIT_FPRET && r2 != JIT_FPRET);
+ if (jit_swf_p()) swf_unger_f(_jitp, r0, r1, r2);
+ else vfp_unger_f(_jitp, r0, r1, r2);
+}
+
+#define jit_unger_d(r0, r1, r2) arm_unger_d(_jitp, r0, r1, r2)
+__jit_inline void
+arm_unger_d(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ assert(r1 != JIT_FPRET && r2 != JIT_FPRET);
+ if (jit_swf_p()) swf_unger_d(_jitp, r0, r1, r2);
+ else vfp_unger_d(_jitp, r0, r1, r2);
+}
+
+#define jit_ungtr_f(r0, r1, r2) arm_ungtr_f(_jitp, r0, r1, r2)
+__jit_inline void
+arm_ungtr_f(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ assert(r1 != JIT_FPRET && r2 != JIT_FPRET);
+ if (jit_swf_p()) swf_ungtr_f(_jitp, r0, r1, r2);
+ else vfp_ungtr_f(_jitp, r0, r1, r2);
+}
+
+#define jit_ungtr_d(r0, r1, r2) arm_ungtr_d(_jitp, r0, r1, r2)
+__jit_inline void
+arm_ungtr_d(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ assert(r1 != JIT_FPRET && r2 != JIT_FPRET);
+ if (jit_swf_p()) swf_ungtr_d(_jitp, r0, r1, r2);
+ else vfp_ungtr_d(_jitp, r0, r1, r2);
+}
+
+#define jit_ltgtr_f(r0, r1, r2) arm_ltgtr_f(_jitp, r0, r1, r2)
+__jit_inline void
+arm_ltgtr_f(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ assert(r1 != JIT_FPRET && r2 != JIT_FPRET);
+ if (jit_swf_p()) swf_ltgtr_f(_jitp, r0, r1, r2);
+ else vfp_ltgtr_f(_jitp, r0, r1, r2);
+}
+
+#define jit_ltgtr_d(r0, r1, r2) arm_ltgtr_d(_jitp, r0, r1, r2)
+__jit_inline void
+arm_ltgtr_d(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ assert(r1 != JIT_FPRET && r2 != JIT_FPRET);
+ if (jit_swf_p()) swf_ltgtr_d(_jitp, r0, r1, r2);
+ else vfp_ltgtr_d(_jitp, r0, r1, r2);
+}
+
+#define jit_ordr_f(r0, r1, r2) arm_ordr_f(_jitp, r0, r1, r2)
+__jit_inline void
+arm_ordr_f(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ assert(r1 != JIT_FPRET && r2 != JIT_FPRET);
+ if (jit_swf_p()) swf_ordr_f(_jitp, r0, r1, r2);
+ else vfp_ordr_f(_jitp, r0, r1, r2);
+}
+
+#define jit_ordr_d(r0, r1, r2) arm_ordr_d(_jitp, r0, r1, r2)
+__jit_inline void
+arm_ordr_d(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ assert(r1 != JIT_FPRET && r2 != JIT_FPRET);
+ if (jit_swf_p()) swf_ordr_d(_jitp, r0, r1, r2);
+ else vfp_ordr_d(_jitp, r0, r1, r2);
+}
+
+#define jit_unordr_f(r0, r1, r2) arm_unordr_f(_jitp, r0, r1, r2)
+__jit_inline void
+arm_unordr_f(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ assert(r1 != JIT_FPRET && r2 != JIT_FPRET);
+ if (jit_swf_p()) swf_unordr_f(_jitp, r0, r1, r2);
+ else vfp_unordr_f(_jitp, r0, r1, r2);
+}
+
+#define jit_unordr_d(r0, r1, r2) arm_unordr_d(_jitp, r0, r1, r2)
+__jit_inline void
+arm_unordr_d(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
+{
+ assert(r1 != JIT_FPRET && r2 != JIT_FPRET);
+ if (jit_swf_p()) swf_unordr_d(_jitp, r0, r1, r2);
+ else vfp_unordr_d(_jitp, r0, r1, r2);
+}
+
+#define jit_bltr_f(i0, r0, r1) arm_bltr_f(_jitp, i0, r0, r1)
+__jit_inline jit_insn *
+arm_bltr_f(jit_state_t _jitp, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET);
+ if (jit_swf_p()) return (swf_bltr_f(_jitp, i0, r0, r1));
+ return (vfp_bltr_f(_jitp, i0, r0, r1));
+}
+
+#define jit_bltr_d(i0, r0, r1) arm_bltr_d(_jitp, i0, r0, r1)
+__jit_inline jit_insn *
+arm_bltr_d(jit_state_t _jitp, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET);
+ if (jit_swf_p()) return (swf_bltr_d(_jitp, i0, r0, r1));
+ return (vfp_bltr_d(_jitp, i0, r0, r1));
+}
+
+#define jit_bler_f(i0, r0, r1) arm_bler_f(_jitp, i0, r0, r1)
+__jit_inline jit_insn *
+arm_bler_f(jit_state_t _jitp, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET);
+ if (jit_swf_p()) return (swf_bler_f(_jitp, i0, r0, r1));
+ return (vfp_bler_f(_jitp, i0, r0, r1));
+}
+
+#define jit_bler_d(i0, r0, r1) arm_bler_d(_jitp, i0, r0, r1)
+__jit_inline jit_insn *
+arm_bler_d(jit_state_t _jitp, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET);
+ if (jit_swf_p()) return (swf_bler_d(_jitp, i0, r0, r1));
+ return (vfp_bler_d(_jitp, i0, r0, r1));
+}
+
+#define jit_beqr_f(i0, r0, r1) arm_beqr_f(_jitp, i0, r0, r1)
+__jit_inline jit_insn *
+arm_beqr_f(jit_state_t _jitp, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET);
+ if (jit_swf_p()) return (swf_beqr_f(_jitp, i0, r0, r1));
+ return (vfp_beqr_f(_jitp, i0, r0, r1));
+}
+
+#define jit_beqr_d(i0, r0, r1) arm_beqr_d(_jitp, i0, r0, r1)
+__jit_inline jit_insn *
+arm_beqr_d(jit_state_t _jitp, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET);
+ if (jit_swf_p()) return (swf_beqr_d(_jitp, i0, r0, r1));
+ return (vfp_beqr_d(_jitp, i0, r0, r1));
+}
+
+#define jit_bger_f(i0, r0, r1) arm_bger_f(_jitp, i0, r0, r1)
+__jit_inline jit_insn *
+arm_bger_f(jit_state_t _jitp, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET);
+ if (jit_swf_p()) return (swf_bger_f(_jitp, i0, r0, r1));
+ return (vfp_bger_f(_jitp, i0, r0, r1));
+}
+
+#define jit_bger_d(i0, r0, r1) arm_bger_d(_jitp, i0, r0, r1)
+__jit_inline jit_insn *
+arm_bger_d(jit_state_t _jitp, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET);
+ if (jit_swf_p()) return (swf_bger_d(_jitp, i0, r0, r1));
+ return (vfp_bger_d(_jitp, i0, r0, r1));
+}
+
+#define jit_bgtr_f(i0, r0, r1) arm_bgtr_f(_jitp, i0, r0, r1)
+__jit_inline jit_insn *
+arm_bgtr_f(jit_state_t _jitp, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET);
+ if (jit_swf_p()) return (swf_bgtr_f(_jitp, i0, r0, r1));
+ return (vfp_bgtr_f(_jitp, i0, r0, r1));
+}
+
+#define jit_bgtr_d(i0, r0, r1) arm_bgtr_d(_jitp, i0, r0, r1)
+__jit_inline jit_insn *
+arm_bgtr_d(jit_state_t _jitp, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET);
+ if (jit_swf_p()) return (swf_bgtr_d(_jitp, i0, r0, r1));
+ return (vfp_bgtr_d(_jitp, i0, r0, r1));
+}
+
+#define jit_bner_f(i0, r0, r1) arm_bner_f(_jitp, i0, r0, r1)
+__jit_inline jit_insn *
+arm_bner_f(jit_state_t _jitp, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET);
+ if (jit_swf_p()) return (swf_bner_f(_jitp, i0, r0, r1));
+ return (vfp_bner_f(_jitp, i0, r0, r1));
+}
+
+#define jit_bner_d(i0, r0, r1) arm_bner_d(_jitp, i0, r0, r1)
+__jit_inline jit_insn *
+arm_bner_d(jit_state_t _jitp, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET);
+ if (jit_swf_p()) return (swf_bner_d(_jitp, i0, r0, r1));
+ return (vfp_bner_d(_jitp, i0, r0, r1));
+}
+
+#define jit_bunltr_f(i0, r0, r1) arm_bunltr_f(_jitp, i0, r0, r1)
+__jit_inline jit_insn *
+arm_bunltr_f(jit_state_t _jitp, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET);
+ if (jit_swf_p()) return (swf_bunltr_f(_jitp, i0, r0, r1));
+ return (vfp_bunltr_f(_jitp, i0, r0, r1));
+}
+
+#define jit_bunltr_d(i0, r0, r1) arm_bunltr_d(_jitp, i0, r0, r1)
+__jit_inline jit_insn *
+arm_bunltr_d(jit_state_t _jitp, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET);
+ if (jit_swf_p()) return (swf_bunltr_d(_jitp, i0, r0, r1));
+ return (vfp_bunltr_d(_jitp, i0, r0, r1));
+}
+
+#define jit_bunler_f(i0, r0, r1) arm_bunler_f(_jitp, i0, r0, r1)
+__jit_inline jit_insn *
+arm_bunler_f(jit_state_t _jitp, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET);
+ if (jit_swf_p()) return (swf_bunler_f(_jitp, i0, r0, r1));
+ return (vfp_bunler_f(_jitp, i0, r0, r1));
+}
+
+#define jit_bunler_d(i0, r0, r1) arm_bunler_d(_jitp, i0, r0, r1)
+__jit_inline jit_insn *
+arm_bunler_d(jit_state_t _jitp, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET);
+ if (jit_swf_p()) return (swf_bunler_d(_jitp, i0, r0, r1));
+ return (vfp_bunler_d(_jitp, i0, r0, r1));
+}
+
+#define jit_buneqr_f(i0, r0, r1) arm_buneqr_f(_jitp, i0, r0, r1)
+__jit_inline jit_insn *
+arm_buneqr_f(jit_state_t _jitp, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET);
+ if (jit_swf_p()) return (swf_buneqr_f(_jitp, i0, r0, r1));
+ return (vfp_buneqr_f(_jitp, i0, r0, r1));
+}
+
+#define jit_buneqr_d(i0, r0, r1) arm_buneqr_d(_jitp, i0, r0, r1)
+__jit_inline jit_insn *
+arm_buneqr_d(jit_state_t _jitp, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET);
+ if (jit_swf_p()) return (swf_buneqr_d(_jitp, i0, r0, r1));
+ return (vfp_buneqr_d(_jitp, i0, r0, r1));
+}
+
+#define jit_bunger_f(i0, r0, r1) arm_bunger_f(_jitp, i0, r0, r1)
+__jit_inline jit_insn *
+arm_bunger_f(jit_state_t _jitp, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET);
+ if (jit_swf_p()) return (swf_bunger_f(_jitp, i0, r0, r1));
+ return (vfp_bunger_f(_jitp, i0, r0, r1));
+}
+
+#define jit_bunger_d(i0, r0, r1) arm_bunger_d(_jitp, i0, r0, r1)
+__jit_inline jit_insn *
+arm_bunger_d(jit_state_t _jitp, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET);
+ if (jit_swf_p()) return (swf_bunger_d(_jitp, i0, r0, r1));
+ return (vfp_bunger_d(_jitp, i0, r0, r1));
+}
+
+#define jit_bungtr_f(i0, r0, r1) arm_bungtr_f(_jitp, i0, r0, r1)
+__jit_inline jit_insn *
+arm_bungtr_f(jit_state_t _jitp, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET);
+ if (jit_swf_p()) return (swf_bungtr_f(_jitp, i0, r0, r1));
+ return (vfp_bungtr_f(_jitp, i0, r0, r1));
+}
+
+#define jit_bungtr_d(i0, r0, r1) arm_bungtr_d(_jitp, i0, r0, r1)
+__jit_inline jit_insn *
+arm_bungtr_d(jit_state_t _jitp, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET);
+ if (jit_swf_p()) return (swf_bungtr_d(_jitp, i0, r0, r1));
+ return (vfp_bungtr_d(_jitp, i0, r0, r1));
+}
+
+#define jit_bltgtr_f(i0, r0, r1) arm_bltgtr_f(_jitp, i0, r0, r1)
+__jit_inline jit_insn *
+arm_bltgtr_f(jit_state_t _jitp, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET);
+ if (jit_swf_p()) return (swf_bltgtr_f(_jitp, i0, r0, r1));
+ return (vfp_bltgtr_f(_jitp, i0, r0, r1));
+}
+
+#define jit_bltgtr_d(i0, r0, r1) arm_bltgtr_d(_jitp, i0, r0, r1)
+__jit_inline jit_insn *
+arm_bltgtr_d(jit_state_t _jitp, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET);
+ if (jit_swf_p()) return (swf_bltgtr_d(_jitp, i0, r0, r1));
+ return (vfp_bltgtr_d(_jitp, i0, r0, r1));
+}
+
+#define jit_bordr_f(i0, r0, r1) arm_bordr_f(_jitp, i0, r0, r1)
+__jit_inline jit_insn *
+arm_bordr_f(jit_state_t _jitp, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET);
+ if (jit_swf_p()) return (swf_bordr_f(_jitp, i0, r0, r1));
+ return (vfp_bordr_f(_jitp, i0, r0, r1));
+}
+
+#define jit_bordr_d(i0, r0, r1) arm_bordr_d(_jitp, i0, r0, r1)
+__jit_inline jit_insn *
+arm_bordr_d(jit_state_t _jitp, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET);
+ if (jit_swf_p()) return (swf_bordr_d(_jitp, i0, r0, r1));
+ return (vfp_bordr_d(_jitp, i0, r0, r1));
+}
+
+#define jit_bunordr_f(i0, r0, r1) arm_bunordr_f(_jitp, i0, r0, r1)
+__jit_inline jit_insn *
+arm_bunordr_f(jit_state_t _jitp, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET);
+ if (jit_swf_p()) return (swf_bunordr_f(_jitp, i0, r0, r1));
+ return (vfp_bunordr_f(_jitp, i0, r0, r1));
+}
+
+#define jit_bunordr_d(i0, r0, r1) arm_bunordr_d(_jitp, i0, r0, r1)
+__jit_inline jit_insn *
+arm_bunordr_d(jit_state_t _jitp, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
+{
+ assert(r0 != JIT_FPRET && r1 != JIT_FPRET);
+ if (jit_swf_p()) return (swf_bunordr_d(_jitp, i0, r0, r1));
+ return (vfp_bunordr_d(_jitp, i0, r0, r1));
+}
+
+#define jit_ldr_f(r0, r1) arm_ldr_f(_jitp, r0, r1)
+__jit_inline void
+arm_ldr_f(jit_state_t _jitp, jit_fpr_t r0, jit_gpr_t r1)
+{
+ assert(r0 != JIT_FPRET);
+ if (jit_swf_p()) swf_ldr_f(_jitp, r0, r1);
+ else vfp_ldr_f(_jitp, r0, r1);
+}
+
+#define jit_ldr_d(r0, r1) arm_ldr_d(_jitp, r0, r1)
+__jit_inline void
+arm_ldr_d(jit_state_t _jitp, jit_fpr_t r0, jit_gpr_t r1)
+{
+ assert(r0 != JIT_FPRET);
+ if (jit_swf_p()) swf_ldr_d(_jitp, r0, r1);
+ else vfp_ldr_d(_jitp, r0, r1);
+}
+
+#define jit_ldi_f(r0, i0) arm_ldi_f(_jitp, r0, i0)
+__jit_inline void
+arm_ldi_f(jit_state_t _jitp, jit_fpr_t r0, void *i0)
+{
+ assert(r0 != JIT_FPRET);
+ if (jit_swf_p()) swf_ldi_f(_jitp, r0, i0);
+ else vfp_ldi_f(_jitp, r0, i0);
+}
+
+#define jit_ldi_d(r0, i0) arm_ldi_d(_jitp, r0, i0)
+__jit_inline void
+arm_ldi_d(jit_state_t _jitp, jit_fpr_t r0, void *i0)
+{
+ assert(r0 != JIT_FPRET);
+ if (jit_swf_p()) swf_ldi_d(_jitp, r0, i0);
+ else vfp_ldi_d(_jitp, r0, i0);
+}
+
+#define jit_ldxr_f(r0, r1, r2) arm_ldxr_f(_jitp, r0, r1, r2)
+__jit_inline void
+arm_ldxr_f(jit_state_t _jitp, jit_fpr_t r0, jit_gpr_t r1, jit_gpr_t r2)
+{
+ assert(r0 != JIT_FPRET);
+ if (jit_swf_p()) swf_ldxr_f(_jitp, r0, r1, r2);
+ else vfp_ldxr_f(_jitp, r0, r1, r2);
+}
+
+#define jit_ldxr_d(r0, r1, r2) arm_ldxr_d(_jitp, r0, r1, r2)
+__jit_inline void
+arm_ldxr_d(jit_state_t _jitp, jit_fpr_t r0, jit_gpr_t r1, jit_gpr_t r2)
+{
+ assert(r0 != JIT_FPRET);
+ if (jit_swf_p()) swf_ldxr_d(_jitp, r0, r1, r2);
+ else vfp_ldxr_d(_jitp, r0, r1, r2);
+}
+
+#define jit_ldxi_f(r0, r1, i0) arm_ldxi_f(_jitp, r0, r1, i0)
+__jit_inline void
+arm_ldxi_f(jit_state_t _jitp, jit_fpr_t r0, jit_gpr_t r1, int i0)
+{
+ assert(r0 != JIT_FPRET);
+ if (jit_swf_p()) swf_ldxi_f(_jitp, r0, r1, i0);
+ else vfp_ldxi_f(_jitp, r0, r1, i0);
+}
+
+#define jit_ldxi_d(r0, r1, i0) arm_ldxi_d(_jitp, r0, r1, (int)i0)
+__jit_inline void
+arm_ldxi_d(jit_state_t _jitp, jit_fpr_t r0, jit_gpr_t r1, int i0)
+{
+ assert(r0 != JIT_FPRET);
+ if (jit_swf_p()) swf_ldxi_d(_jitp, r0, r1, i0);
+ else vfp_ldxi_d(_jitp, r0, r1, i0);
+}
+
+#define jit_str_f(r0, r1) arm_str_f(_jitp, r0, r1)
+__jit_inline void
+arm_str_f(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1)
+{
+ assert(r1 != JIT_FPRET);
+ if (jit_swf_p()) swf_str_f(_jitp, r0, r1);
+ else vfp_str_f(_jitp, r0, r1);
+}
+
+#define jit_str_d(r0, r1) arm_str_d(_jitp, r0, r1)
+__jit_inline void
+arm_str_d(jit_state_t _jitp, jit_gpr_t r0, jit_fpr_t r1)
+{
+ assert(r1 != JIT_FPRET);
+ if (jit_swf_p()) swf_str_d(_jitp, r0, r1);
+ else vfp_str_d(_jitp, r0, r1);
+}
+
+#define jit_sti_f(i0, r0) arm_sti_f(_jitp, i0, r0)
+__jit_inline void
+arm_sti_f(jit_state_t _jitp, void *i0, jit_fpr_t r0)
+{
+ assert(r0 != JIT_FPRET);
+ if (jit_swf_p()) swf_sti_f(_jitp, i0, r0);
+ else vfp_sti_f(_jitp, i0, r0);
+}
+
+#define jit_sti_d(i0, r0) arm_sti_d(_jitp, i0, r0)
+__jit_inline void
+arm_sti_d(jit_state_t _jitp, void *i0, jit_fpr_t r0)
+{
+ assert(r0 != JIT_FPRET);
+ if (jit_swf_p()) swf_sti_d(_jitp, i0, r0);
+ else vfp_sti_d(_jitp, i0, r0);
+}
+
+#define jit_stxr_f(r0, r1, r2) arm_stxr_f(_jitp, r0, r1, r2)
+__jit_inline void
+arm_stxr_f(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, jit_fpr_t r2)
+{
+ assert(r2 != JIT_FPRET);
+ if (jit_swf_p()) swf_stxr_f(_jitp, r0, r1, r2);
+ else vfp_stxr_f(_jitp, r0, r1, r2);
+}
+
+#define jit_stxr_d(r0, r1, r2) arm_stxr_d(_jitp, r0, r1, r2)
+__jit_inline void
+arm_stxr_d(jit_state_t _jitp, jit_gpr_t r0, jit_gpr_t r1, jit_fpr_t r2)
+{
+ assert(r2 != JIT_FPRET);
+ if (jit_swf_p()) swf_stxr_d(_jitp, r0, r1, r2);
+ else vfp_stxr_d(_jitp, r0, r1, r2);
+}
+
+#define jit_stxi_f(i0, r0, r1) arm_stxi_f(_jitp, i0, r0, r1)
+__jit_inline void
+arm_stxi_f(jit_state_t _jitp, int i0, jit_gpr_t r0, jit_fpr_t r1)
+{
+ assert(r1 != JIT_FPRET);
+ if (jit_swf_p()) swf_stxi_f(_jitp, i0, r0, r1);
+ else vfp_stxi_f(_jitp, i0, r0, r1);
+}
+
+#define jit_stxi_d(i0, r0, r1) arm_stxi_d(_jitp, (int)i0, r0, r1)
+__jit_inline void
+arm_stxi_d(jit_state_t _jitp, int i0, jit_gpr_t r0, jit_fpr_t r1)
+{
+ assert(r1 != JIT_FPRET);
+ if (jit_swf_p()) swf_stxi_d(_jitp, i0, r0, r1);
+ else vfp_stxi_d(_jitp, i0, r0, r1);
+}
+
+#define jit_prolog_f(i0) do {} while (0)
+#define jit_prolog_d(i0) do {} while (0)
+
+#define jit_prepare_f(i0) arm_prepare_f(_jitp, i0)
+__jit_inline void
+arm_prepare_f(jit_state_t _jitp, int i0)
+{
+ assert(0);
+}
+
+#define jit_prepare_d(i0) arm_prepare_d(_jitp, i0)
+__jit_inline int
+arm_prepare_d(jit_state_t _jitp, int i0)
+{
+ assert(0);
+ return 0;
+}
+
+#define jit_arg_f() arm_arg_f(_jitp)
+__jit_inline void
+arm_arg_f(jit_state_t _jitp)
+{
+ assert(0);
+}
+
+#define jit_arg_d() arm_arg_d(_jitp)
+__jit_inline int
+arm_arg_d(jit_state_t _jitp)
+{
+ assert(0);
+ return 0;
+}
+
+#define jit_getarg_f(r0, i0) arm_getarg_f(_jitp, r0, i0)
+__jit_inline void
+arm_getarg_f(jit_state_t _jitp, jit_fpr_t r0, int i0)
+{
+ assert(r0 != JIT_FPRET);
+ if (jit_swf_p()) swf_getarg_f(_jitp, r0, i0);
+ else vfp_getarg_f(_jitp, r0, i0);
+}
+
+#define jit_getarg_d(r0, i0) arm_getarg_d(_jitp, r0, i0)
+__jit_inline void
+arm_getarg_d(jit_state_t _jitp, jit_fpr_t r0, int i0)
+{
+ assert(r0 != JIT_FPRET);
+ if (jit_swf_p()) swf_getarg_d(_jitp, r0, i0);
+ else vfp_getarg_d(_jitp, r0, i0);
+}
+
+#define jit_pusharg_f(r0) arm_pusharg_f(_jitp, r0)
+__jit_inline void
+arm_pusharg_f(jit_state_t _jitp, jit_fpr_t r0)
+{
+ assert(r0 != JIT_FPRET);
+ if (jit_swf_p()) swf_pusharg_f(_jitp, r0);
+ else vfp_pusharg_f(_jitp, r0);
+}
+
+#define jit_pusharg_d(r0) arm_pusharg_d(_jitp, r0)
+__jit_inline void
+arm_pusharg_d(jit_state_t _jitp, jit_fpr_t r0)
+{
+ assert(r0 != JIT_FPRET);
+ if (jit_swf_p()) swf_pusharg_d(_jitp, r0);
+ else vfp_pusharg_d(_jitp, r0);
+}
+
+#define jit_retval_f(r0) arm_retval_f(_jitp, r0)
+__jit_inline void
+arm_retval_f(jit_state_t _jitp, jit_fpr_t r0)
+{
+ if (r0 != JIT_FPRET) {
+ if (jit_swf_p()) swf_retval_f(_jitp, r0);
+ else vfp_retval_f(_jitp, r0);
+ }
+ /* else assume chaining call to jit_retval_f as done in tests/funcfp.c */
+}
+
+#define jit_retval_d(r0) arm_retval_d(_jitp, r0)
+__jit_inline void
+arm_retval_d(jit_state_t _jitp, jit_fpr_t r0)
+{
+ if (r0 != JIT_FPRET) {
+ if (jit_swf_p()) swf_retval_d(_jitp, r0);
+ else vfp_retval_d(_jitp, r0);
+ }
+ /* else assume chaining call to jit_retval_d as done in tests/funcfp.c */
+}
+
+#define jit_bantigtr_d(dest, r0, r1) jit_bunler_d(dest, r0, r1)
+#define jit_bantiger_d(dest, r0, r1) jit_bunltr_d(dest, r0, r1)
+#define jit_bantiltr_d(dest, r0, r1) jit_bunger_d(dest, r0, r1)
+#define jit_bantiler_d(dest, r0, r1) jit_bungtr_d(dest, r0, r1)
+#define jit_bantieqr_d(dest, r0, r1) jit_bner_d(dest, r0, r1)
+
+#endif /* __lightning_fp_arm_h */
diff --git a/src/racket/src/lightning/arm/funcs-common.h b/src/racket/src/lightning/arm/funcs-common.h
new file mode 100644
index 0000000000..12cb6affe9
--- /dev/null
+++ b/src/racket/src/lightning/arm/funcs-common.h
@@ -0,0 +1,47 @@
+/******************************** -*- C -*- ****************************
+ *
+ * Platform-independent layer inline functions (common part)
+ *
+ ***********************************************************************/
+
+
+/***********************************************************************
+ *
+ * Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
+ * Written by Paolo Bonzini.
+ *
+ * This file is part of GNU lightning.
+ *
+ * GNU lightning 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU lightning 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 GNU lightning; see the file COPYING.LESSER; if not, write to the
+ * Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ ***********************************************************************/
+
+#ifndef __lightning_funcs_common_h
+#define __lightning_funcs_common_h
+
+#include
+#include
+
+int
+jit_fail(const char *msg, const char *file, int line, const char *function)
+{
+ fprintf(stderr, "%s: In function `%s':\n", file, function);
+ fprintf(stderr, "%s:%d: %s\n", file, line, msg);
+ abort();
+}
+
+
+#endif /* __lightning_funcs_common_h */
diff --git a/src/racket/src/lightning/arm/funcs.h b/src/racket/src/lightning/arm/funcs.h
new file mode 100644
index 0000000000..b2b154e684
--- /dev/null
+++ b/src/racket/src/lightning/arm/funcs.h
@@ -0,0 +1,136 @@
+/******************************** -*- C -*- ****************************
+ *
+ * Run-time assembler for the arm
+ *
+ ***********************************************************************/
+
+/***********************************************************************
+ *
+ * Copyright 2011 Free Software Foundation
+ *
+ * This file is part of GNU lightning.
+ *
+ * GNU lightning 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU lightning 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 GNU lightning; see the file COPYING.LESSER; if not, write to the
+ * Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * Authors:
+ * Paulo Cesar Pereira de Andrade
+ ***********************************************************************/
+
+#ifndef __lightning_funcs_h
+#define __lightning_funcs_h
+
+#if defined(__linux__)
+# include
+# include
+#endif
+
+#include
+#include
+
+#define jit_notify_freed_code() /* empty */
+
+extern void __clear_cache(void*, void*);
+
+__jit_inline void
+jit_flush_code(void *start, void *end)
+{
+ /* Flush via __clear_cache() --- which seems to work only for ranges
+ that fall within a page, so call it once for each page in the
+ range `start' to `end'. */
+ while (start < end) {
+ void *e;
+ e = (void *)(((uintptr_t)start + 4096) & ~4095);
+ if (e < end) {
+ __clear_cache(start, e);
+ start = e;
+ } else {
+ __clear_cache(start, end);
+ break;
+ }
+ }
+}
+
+#define jit_get_cpu jit_get_cpu
+__jit_constructor __jit_inline void
+jit_get_cpu(void)
+{
+ static int initialized;
+
+ if (initialized)
+ return;
+
+ initialized = 1;
+
+#if defined(__linux__)
+ {
+ FILE *fp;
+ char *ptr;
+ char buf[128];
+
+ if ((fp = fopen("/proc/cpuinfo", "r")) == NULL)
+ return;
+
+ while (fgets(buf, sizeof(buf), fp)) {
+ if (strncmp(buf, "CPU architecture:", 17) == 0) {
+ jit_cpu.version = strtol(buf + 17, &ptr, 10);
+ while (*ptr) {
+ if (*ptr == 'T' || *ptr == 't') {
+ ++ptr;
+ jit_cpu.thumb = 1;
+ }
+ else if (*ptr == 'E' || *ptr == 'e') {
+ jit_cpu.extend = 1;
+ ++ptr;
+ }
+ else
+ ++ptr;
+ }
+ }
+ else if (strncmp(buf, "Features\t:", 10) == 0) {
+ if ((ptr = strstr(buf + 10, "vfpv")))
+ jit_cpu.vfp = strtol(ptr + 4, NULL, 0);
+ if ((ptr = strstr(buf + 10, "neon")))
+ jit_cpu.neon = 1;
+ if ((ptr = strstr(buf + 10, "thumb")))
+ jit_cpu.thumb = 1;
+ }
+ }
+ fclose(fp);
+ }
+#endif
+#if defined(__ARM_PCS_VFP)
+ if (!jit_cpu.vfp)
+ jit_cpu.vfp = 3;
+ if (!jit_cpu.version)
+ jit_cpu.version = 7;
+ jit_cpu.abi = 1;
+#endif
+#ifdef __VFP_FP__
+ if (!jit_cpu.vfp)
+ jit_cpu.vfp = 1;
+#endif
+ /* armv6t2 todo (software float and thumb2) */
+ if (!jit_cpu.vfp && jit_cpu.thumb)
+ jit_cpu.thumb = 0;
+
+ /* Note that software float works only when the ABI does not use
+ VFP for floating-point arguments. VFP, in contrast, works
+ whether or not a VFP ABI is in use (since we avoid passing
+ floating-point arguments or receiving floating-point results in
+ that mode). */
+}
+
+#endif /* __lightning_funcs_h */
diff --git a/src/racket/src/lightning/i386/core-common.h b/src/racket/src/lightning/i386/core-common.h
index 39870bedea..61742585dc 100644
--- a/src/racket/src/lightning/i386/core-common.h
+++ b/src/racket/src/lightning/i386/core-common.h
@@ -72,11 +72,15 @@ static jit_state _jit;
#define _jitl _jit.jitl
-#define jit_get_ip() (_jit.x.code)
+#define jit_get_ip() (_jit.x.pc)
+#define jit_get_raw_ip() jit_get_ip()
#define jit_set_ip(ptr) (_jit.x.pc = (ptr), jit_get_ip ())
#define jit_get_label() (_jit.x.pc)
#define jit_forward() (_jit.x.pc)
+#define jit_adjust_ip(x) x
+#define jit_unadjust_ip(x) x
+
#define jit_field(struc, f) ( ((intptr_t) (&((struc *) 8)->f) ) - 8)
#define jit_ptr_field(struc_p, f) ( ((intptr_t) (&((struc_p) 8)->f) ) - 8)
diff --git a/src/racket/src/lightning/lightning.h b/src/racket/src/lightning/lightning.h
index 0257c27d11..050fea149f 100644
--- a/src/racket/src/lightning/lightning.h
+++ b/src/racket/src/lightning/lightning.h
@@ -64,6 +64,19 @@ extern "C" {
#endif
+#ifdef MZ_USE_JIT_ARM
+
+#include "arm/asm-common.h"
+#include "arm/asm.h"
+#include "arm/funcs.h"
+#include "arm/funcs-common.h"
+#include "arm/core.h"
+#include "arm/core-common.h"
+#include "arm/fp.h"
+#include "arm/fp-common.h"
+
+#endif
+
#ifndef JIT_R0
#error GNU lightning does not support the current target
#endif
diff --git a/src/racket/src/lightning/ppc/core-common.h b/src/racket/src/lightning/ppc/core-common.h
index 5fc4261914..ff64be69d7 100644
--- a/src/racket/src/lightning/ppc/core-common.h
+++ b/src/racket/src/lightning/ppc/core-common.h
@@ -83,11 +83,15 @@ static jit_state _jit;
#define _jitl _jit.jitl
-#define jit_get_ip() (_jit.x.code)
+#define jit_get_ip() (_jit.x.pc)
+#define jit_get_raw_ip() jit_get_ip()
#define jit_set_ip(ptr) (_jit.x.pc = (ptr), jit_get_ip ())
#define jit_get_label() (_jit.x.pc)
#define jit_forward() (_jit.x.pc)
+#define jit_adjust_ip(x) x
+#define jit_unadjust_ip(x) x
+
#define jit_field(struc, f) ( ((long) (&((struc *) 8)->f) ) - 8)
#define jit_ptr_field(struc_p, f) ( ((long) (&((struc_p) 8)->f) ) - 8)
diff --git a/src/racket/src/place.c b/src/racket/src/place.c
index 27cdb555a7..fe0a4acbd0 100644
--- a/src/racket/src/place.c
+++ b/src/racket/src/place.c
@@ -319,8 +319,6 @@ Scheme_Object *scheme_place(int argc, Scheme_Object *args[]) {
place_data->parent_gc = parent_gc;
{
- Scheme_Object *so;
-
in_arg = args[2];
out_arg = args[3];
err_arg = args[4];
diff --git a/src/racket/src/schpriv.h b/src/racket/src/schpriv.h
index 0c9527af1a..71b8131f49 100644
--- a/src/racket/src/schpriv.h
+++ b/src/racket/src/schpriv.h
@@ -2572,6 +2572,11 @@ typedef struct Scheme_Native_Closure_Data {
#ifdef MZ_PRECISE_GC
void **retained; /* inside code */
#endif
+#if defined(MZ_USE_JIT_ARM) && !defined(MZ_PRECISE_GC)
+# define NEED_RETAIN_CODE_POINTERS
+ /* Thumb code is off by one, need real start for GC */
+ void *retain_code;
+#endif
} Scheme_Native_Closure_Data;
#define SCHEME_NATIVE_CLOSURE_DATA_FLAGS(obj) MZ_OPT_HASH_KEY(&(obj)->iso)
@@ -3840,7 +3845,7 @@ intptr_t scheme_port_closed_p (Scheme_Object *port);
#define CURRENT_OUTPUT_PORT(config) scheme_get_param(config, MZCONFIG_OUTPUT_PORT)
#define CHECK_PORT_CLOSED(who, kind, port, closed) if (closed) scheme_raise_exn(MZEXN_FAIL, "%s: " kind " port is closed", who);
-#ifdef USE_FCNTL_O_NONBLOCK
+#if defined(USE_FCNTL_O_NONBLOCK)
# define MZ_NONBLOCKING O_NONBLOCK
#else
# define MZ_NONBLOCKING FNDELAY
diff --git a/src/racket/src/unwind/libunwind.c b/src/racket/src/unwind/libunwind.c
index 4aff5bc043..38376e5579 100644
--- a/src/racket/src/unwind/libunwind.c
+++ b/src/racket/src/unwind/libunwind.c
@@ -30,6 +30,16 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include
#include "libunwind_i.h"
+#ifdef CONFIG_DEBUG_FRAME
+# include
+# include
+# include
+# include
+# include "os-linux.h"
+#endif
+
+#define UNW_PI_FLAG_DEBUG_FRAME 32
+
/*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
/* region-based memory management */
/*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
@@ -260,7 +270,7 @@ do { \
OPND1_TYPE (operands_signature),
&operand1, arg)) < 0)
return ret;
- if (NUM_OPERANDS (operands_signature > 1))
+ if (NUM_OPERANDS (operands_signature) > 1)
if ((ret = read_operand (as, a, addr,
OPND2_TYPE (operands_signature),
&operand2, arg)) < 0)
@@ -657,12 +667,15 @@ do { \
/*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
static inline int
-is_cie_id (unw_word_t val)
+is_cie_id (unw_word_t val, int is_debug_frame)
{
- /* DWARF spec says CIE_id is 0xffffffff (for 32-bit ELF) or
- 0xffffffffffffffff (for 64-bit ELF). However, the GNU toolchain
+ /* The CIE ID is normally 0xffffffff (for 32-bit ELF) or
+ 0xffffffffffffffff (for 64-bit ELF). However, .eh_frame
uses 0. */
- return (val == 0 || val == - (unw_word_t) 1);
+ if (is_debug_frame)
+ return (val == - (uint32_t) 1 || val == - (uint64_t) 1);
+ else
+ return (val == 0);
}
/* Note: we don't need to keep track of more than the first four
@@ -672,7 +685,8 @@ is_cie_id (unw_word_t val)
repeated. */
static inline int
parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr,
- const unw_proc_info_t *pi, struct dwarf_cie_info *dci, void *arg)
+ const unw_proc_info_t *pi, struct dwarf_cie_info *dci,
+ unw_word_t base, void *arg)
{
uint8_t version, ch, augstr[5], fde_encoding, handler_encoding;
unw_word_t len, cie_end_addr, aug_size;
@@ -705,13 +719,14 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr,
{
/* the CIE is in the 32-bit DWARF format */
uint32_t cie_id;
+ /* DWARF says CIE id should be 0xffffffff, but in .eh_frame, it's 0 */
+ const uint32_t expected_id = (base) ? 0xffffffff : 0;
len = u32val;
cie_end_addr = addr + len;
if ((ret = dwarf_readu32 (as, a, &addr, &cie_id, arg)) < 0)
return ret;
- /* DWARF says CIE id should be 0xffffffff, but in .eh_frame, it's 0 */
- if (cie_id != 0)
+ if (cie_id != expected_id)
{
Debug (1, "Unexpected CIE id %x\n", cie_id);
return -UNW_EINVAL;
@@ -721,6 +736,9 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr,
{
/* the CIE is in the 64-bit DWARF format */
uint64_t cie_id;
+ /* DWARF says CIE id should be 0xffffffffffffffff, but in
+ .eh_frame, it's 0 */
+ const uint64_t expected_id = (base) ? 0xffffffffffffffffull : 0;
if ((ret = dwarf_readu64 (as, a, &addr, &u64val, arg)) < 0)
return ret;
@@ -728,9 +746,7 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr,
cie_end_addr = addr + len;
if ((ret = dwarf_readu64 (as, a, &addr, &cie_id, arg)) < 0)
return ret;
- /* DWARF says CIE id should be 0xffffffffffffffff, but in
- .eh_frame, it's 0 */
- if (cie_id != 0)
+ if (cie_id != expected_id)
{
Debug (1, "Unexpected CIE id %llx\n", (long long) cie_id);
return -UNW_EINVAL;
@@ -777,14 +793,16 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr,
arg)) < 0)
return ret;
+ i = 0;
if (augstr[0] == 'z')
{
dci->sized_augmentation = 1;
if ((ret = dwarf_read_uleb128 (as, a, &addr, &aug_size, arg)) < 0)
return ret;
+ i++;
}
- for (i = 1; i < sizeof (augstr) && augstr[i]; ++i)
+ for (; i < sizeof (augstr) && augstr[i]; ++i)
switch (augstr[i])
{
case 'L':
@@ -810,22 +828,24 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr,
break;
case 'S':
+ /* This is a signal frame. */
+ dci->signal_frame = 1;
+
/* Temporarily set it to one so dwarf_parse_fde() knows that
it should fetch the actual ABI/TAG pair from the FDE. */
dci->have_abi_marker = 1;
break;
default:
+ Debug (1, "Unexpected augmentation string `%s'\n", augstr);
if (dci->sized_augmentation)
/* If we have the size of the augmentation body, we can skip
over the parts that we don't understand, so we're OK. */
- return 0;
+ goto done;
else
- {
- Debug (1, "Unexpected augmentation string `%s'\n", augstr);
- return -UNW_EINVAL;
- }
+ return -UNW_EINVAL;
}
+ done:
dci->fde_encoding = fde_encoding;
dci->cie_instr_start = addr;
Debug (15, "CIE parsed OK, augmentation = \"%s\", handler=0x%lx\n",
@@ -833,12 +853,15 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr,
return 0;
}
-/* Extract proc-info from the FDE starting at address ADDR. */
+/* Extract proc-info from the FDE starting at adress ADDR.
+
+ Pass BASE as zero for eh_frame behaviour, or a pointer to
+ debug_frame base for debug_frame behaviour. */
HIDDEN int
dwarf_extract_proc_info_from_fde (unw_addr_space_t as, unw_accessors_t *a,
unw_word_t *addrp, unw_proc_info_t *pi,
- int need_unwind_info,
+ int need_unwind_info, unw_word_t base,
void *arg)
{
unw_word_t fde_end_addr, cie_addr, cie_offset_addr, aug_end_addr = 0;
@@ -857,7 +880,7 @@ dwarf_extract_proc_info_from_fde (unw_addr_space_t as, unw_accessors_t *a,
if (u32val != 0xffffffff)
{
- uint32_t cie_offset;
+ int32_t cie_offset;
/* In some configurations, an FDE with a 0 length indicates the
end of the FDE-table. */
@@ -869,22 +892,25 @@ dwarf_extract_proc_info_from_fde (unw_addr_space_t as, unw_accessors_t *a,
*addrp = fde_end_addr = addr + u32val;
cie_offset_addr = addr;
- if ((ret = dwarf_readu32 (as, a, &addr, &cie_offset, arg)) < 0)
+ if ((ret = dwarf_reads32 (as, a, &addr, &cie_offset, arg)) < 0)
return ret;
- if (is_cie_id (cie_offset))
+ if (is_cie_id (cie_offset, base != 0))
/* ignore CIEs (happens during linear searches) */
return 0;
- /* DWARF says that the CIE_pointer in the FDE is a
- .debug_frame-relative offset, but the GCC-generated .eh_frame
- sections instead store a "pcrelative" offset, which is just
- as fine as it's self-contained. */
- cie_addr = cie_offset_addr - cie_offset;
+ if (base != 0)
+ cie_addr = base + cie_offset;
+ else
+ /* DWARF says that the CIE_pointer in the FDE is a
+ .debug_frame-relative offset, but the GCC-generated .eh_frame
+ sections instead store a "pcrelative" offset, which is just
+ as fine as it's self-contained. */
+ cie_addr = cie_offset_addr - cie_offset;
}
else
{
- uint64_t cie_offset;
+ int64_t cie_offset;
/* the FDE is in the 64-bit DWARF format */
@@ -894,21 +920,26 @@ dwarf_extract_proc_info_from_fde (unw_addr_space_t as, unw_accessors_t *a,
*addrp = fde_end_addr = addr + u64val;
cie_offset_addr = addr;
- if ((ret = dwarf_readu64 (as, a, &addr, &cie_offset, arg)) < 0)
+ if ((ret = dwarf_reads64 (as, a, &addr, &cie_offset, arg)) < 0)
return ret;
- if (is_cie_id (cie_offset))
+ if (is_cie_id (cie_offset, base != 0))
/* ignore CIEs (happens during linear searches) */
return 0;
- /* DWARF says that the CIE_pointer in the FDE is a
- .debug_frame-relative offset, but the GCC-generated .eh_frame
- sections instead store a "pcrelative" offset, which is just
- as fine as it's self-contained. */
- cie_addr = (unw_word_t) ((uint64_t) cie_offset_addr - cie_offset);
+ if (base != 0)
+ cie_addr = base + cie_offset;
+ else
+ /* DWARF says that the CIE_pointer in the FDE is a
+ .debug_frame-relative offset, but the GCC-generated .eh_frame
+ sections instead store a "pcrelative" offset, which is just
+ as fine as it's self-contained. */
+ cie_addr = (unw_word_t) ((uint64_t) cie_offset_addr - cie_offset);
}
- if ((ret = parse_cie (as, a, cie_addr, pi, &dci, arg)) < 0)
+ Debug (15, "looking for CIE at address %lx\n", (long) cie_addr);
+
+ if ((ret = parse_cie (as, a, cie_addr, pi, &dci, base, arg)) < 0)
return ret;
/* IP-range has same encoding as FDE pointers, except that it's
@@ -942,9 +973,9 @@ dwarf_extract_proc_info_from_fde (unw_addr_space_t as, unw_accessors_t *a,
{
pi->format = UNW_INFO_FORMAT_TABLE;
pi->unwind_info_size = sizeof (dci);
- pi->unwind_info = malloc_in_rgn (as, sizeof(struct dwarf_cie_info));
+ pi->unwind_info = malloc_in_rgn(as, sizeof(struct dwarf_cie_info));
if (!pi->unwind_info)
- return UNW_ENOMEM;
+ return -UNW_ENOMEM;
if (dci.have_abi_marker)
{
@@ -1016,10 +1047,15 @@ run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr,
as = c->as;
arg = c->as_arg;
+ if (c->pi.flags & UNW_PI_FLAG_DEBUG_FRAME)
+ {
+ /* .debug_frame CFI is stored in local address space. */
+ arg = NULL;
+ }
a = unw_get_accessors (as);
curr_ip = c->pi.start_ip;
- while (curr_ip < ip && *addr < end_addr)
+ while (curr_ip <= ip && *addr < end_addr)
{
if ((ret = dwarf_readu8 (as, a, addr, &op, arg)) < 0)
return ret;
@@ -1324,6 +1360,22 @@ fetch_proc_info (struct dwarf_cursor *c, unw_word_t ip, int need_unwind_info)
{
int ret;
+ /* The 'ip' can point either to the previous or next instruction
+ depending on what type of frame we have: normal call or a place
+ to resume execution (e.g. after signal frame).
+
+ For a normal call frame we need to back up so we point within the
+ call itself; this is important because a) the call might be the
+ very last instruction of the function and the edge of the FDE,
+ and b) so that run_cfi_program() runs locations up to the call
+ but not more.
+
+ For execution resume, we need to do the exact opposite and look
+ up using the current 'ip' value. That is where execution will
+ continue, and it's important we get this right, as 'ip' could be
+ right at the function entry and hence FDE edge, or at instruction
+ that manipulates CFA (push/pop). */
+ if (c->use_prev_instr)
--ip;
if (c->pi_valid && !need_unwind_info)
@@ -1335,6 +1387,15 @@ fetch_proc_info (struct dwarf_cursor *c, unw_word_t ip, int need_unwind_info)
return ret;
c->pi_valid = 1;
+
+ /* Update use_prev_instr for the next frame. */
+ if (need_unwind_info)
+ {
+ assert(c->pi.unwind_info);
+ struct dwarf_cie_info *dci = c->pi.unwind_info;
+ c->use_prev_instr = ! dci->signal_frame;
+ }
+
return ret;
}
@@ -1465,7 +1526,7 @@ hash (unw_word_t ip)
static inline long
cache_match (dwarf_reg_state_t *rs, unw_word_t ip)
{
- if (ip == rs->ip)
+ if (rs->valid && (ip == rs->ip))
return 1;
return 0;
}
@@ -1552,7 +1613,9 @@ rs_new (struct dwarf_rs_cache *cache, struct dwarf_cursor * c)
rs->hint = 0;
rs->ip = c->ip;
+ rs->valid = 1;
rs->ret_addr_column = c->ret_addr_column;
+ rs->signal_frame = 0;
return rs;
}
@@ -1687,16 +1750,21 @@ apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs)
case DWARF_WHERE_EXPR:
addr = rs->reg[i].val;
- if ((ret = eval_location_expr (c, as, a, addr, c->loc + i, arg)) , 0)
+ if ((ret = eval_location_expr (c, as, a, addr, c->loc + i, arg)) < 0)
return ret;
break;
}
}
c->cfa = cfa;
- ret = dwarf_get (c, c->loc[c->ret_addr_column], &ip);
- if (ret < 0)
- return ret;
- c->ip = ip;
+ /* DWARF spec says undefined return address location means end of stack. */
+ if (DWARF_IS_NULL_LOC (c->loc[c->ret_addr_column]))
+ c->ip = 0;
+ else {
+ ret = dwarf_get (c, c->loc[c->ret_addr_column], &ip);
+ if (ret < 0)
+ return ret;
+ c->ip = ip;
+ }
/* XXX: check for ip to be code_aligned */
if (c->ip == prev_ip && c->cfa == prev_cfa)
@@ -1749,6 +1817,7 @@ dwarf_find_save_locs (struct dwarf_cursor *c)
if (rs)
{
c->ret_addr_column = rs->ret_addr_column;
+ c->use_prev_instr = ! rs->signal_frame;
goto apply;
}
@@ -1856,7 +1925,7 @@ linear_search (unw_addr_space_t as, unw_word_t ip,
while (i++ < fde_count && addr < eh_frame_end)
{
fde_addr = addr;
- if ((ret = dwarf_extract_proc_info_from_fde (as, a, &addr, pi, 0, arg))
+ if ((ret = dwarf_extract_proc_info_from_fde (as, a, &addr, pi, 0, 0, arg))
< 0)
return ret;
@@ -1866,7 +1935,7 @@ linear_search (unw_addr_space_t as, unw_word_t ip,
return 1;
addr = fde_addr;
if ((ret = dwarf_extract_proc_info_from_fde (as, a, &addr, pi,
- need_unwind_info, arg))
+ need_unwind_info, 0, arg))
< 0)
return ret;
return 1;
@@ -1875,6 +1944,401 @@ linear_search (unw_addr_space_t as, unw_word_t ip,
return -UNW_ENOINFO;
}
+#ifdef CONFIG_DEBUG_FRAME
+/* Load .debug_frame section from FILE. Allocates and returns space
+ in *BUF, and sets *BUFSIZE to its size. IS_LOCAL is 1 if using the
+ local process, in which case we can search the system debug file
+ directory; 0 for other address spaces, in which case we do not; or
+ -1 for recursive calls following .gnu_debuglink. Returns 0 on
+ success, 1 on error. Succeeds even if the file contains no
+ .debug_frame. */
+/* XXX: Could use mmap; but elf_map_image keeps tons mapped in. */
+
+static int
+load_debug_frame (const char *file, char **buf, size_t *bufsize, int is_local)
+{
+ FILE *f;
+ Elf_W (Ehdr) ehdr;
+ Elf_W (Half) shstrndx;
+ Elf_W (Shdr) *sec_hdrs = NULL;
+ char *stringtab = NULL;
+ unsigned int i;
+ size_t linksize = 0;
+ char *linkbuf = NULL;
+
+ *buf = NULL;
+ *bufsize = 0;
+
+ f = fopen (file, "r");
+
+ if (!f)
+ return 1;
+
+ if (fread (&ehdr, sizeof (Elf_W (Ehdr)), 1, f) != 1)
+ goto file_error;
+
+ shstrndx = ehdr.e_shstrndx;
+
+ Debug (4, "opened file '%s'. Section header at offset %d\n",
+ file, (int) ehdr.e_shoff);
+
+ fseek (f, ehdr.e_shoff, SEEK_SET);
+ sec_hdrs = calloc (ehdr.e_shnum, sizeof (Elf_W (Shdr)));
+ if (fread (sec_hdrs, sizeof (Elf_W (Shdr)), ehdr.e_shnum, f) != ehdr.e_shnum)
+ goto file_error;
+
+ Debug (4, "loading string table of size %zd\n",
+ sec_hdrs[shstrndx].sh_size);
+ stringtab = malloc (sec_hdrs[shstrndx].sh_size);
+ fseek (f, sec_hdrs[shstrndx].sh_offset, SEEK_SET);
+ if (fread (stringtab, 1, sec_hdrs[shstrndx].sh_size, f) != sec_hdrs[shstrndx].sh_size)
+ goto file_error;
+
+ for (i = 1; i < ehdr.e_shnum && *buf == NULL; i++)
+ {
+ char *secname = &stringtab[sec_hdrs[i].sh_name];
+
+ if (strcmp (secname, ".debug_frame") == 0)
+ {
+ *bufsize = sec_hdrs[i].sh_size;
+ *buf = malloc (*bufsize);
+
+ fseek (f, sec_hdrs[i].sh_offset, SEEK_SET);
+ if (fread (*buf, 1, *bufsize, f) != *bufsize)
+ goto file_error;
+
+ Debug (4, "read %zd bytes of .debug_frame from offset %zd\n",
+ *bufsize, sec_hdrs[i].sh_offset);
+ }
+ else if (strcmp (secname, ".gnu_debuglink") == 0)
+ {
+ linksize = sec_hdrs[i].sh_size;
+ linkbuf = malloc (linksize);
+
+ fseek (f, sec_hdrs[i].sh_offset, SEEK_SET);
+ if (fread (linkbuf, 1, linksize, f) != linksize)
+ goto file_error;
+
+ Debug (4, "read %zd bytes of .gnu_debuglink from offset %zd\n",
+ linksize, sec_hdrs[i].sh_offset);
+ }
+ }
+
+ free (stringtab);
+ free (sec_hdrs);
+
+ fclose (f);
+
+ /* Ignore separate debug files which contain a .gnu_debuglink section. */
+ if (linkbuf && is_local == -1)
+ {
+ free (linkbuf);
+ return 1;
+ }
+
+ free (linkbuf);
+
+ return 0;
+
+/* An error reading image file. Release resources and return error code */
+file_error:
+ free(stringtab);
+ free(sec_hdrs);
+ free(linkbuf);
+ fclose(f);
+
+ return 1;
+}
+
+/* Locate the binary which originated the contents of address ADDR. Return
+ the name of the binary in *name (space is allocated by the caller)
+ Returns 0 if a binary is successfully found, or 1 if an error occurs. */
+
+static int
+find_binary_for_address (unw_word_t ip, char *name, size_t name_size)
+{
+#if defined(__linux) && (!UNW_REMOTE_ONLY)
+ struct map_iterator mi;
+ int found = 0;
+ int pid = getpid ();
+ unsigned long segbase, mapoff, hi;
+
+ maps_init (&mi, pid);
+ while (maps_next (&mi, &segbase, &hi, &mapoff))
+ if (ip >= segbase && ip < hi)
+ {
+ size_t len = strlen (mi.path);
+
+ if (len + 1 <= name_size)
+ {
+ memcpy (name, mi.path, len + 1);
+ found = 1;
+ }
+ break;
+ }
+ maps_close (&mi);
+ return !found;
+#endif
+
+ return 1;
+}
+
+/* Locate and/or try to load a debug_frame section for address ADDR. Return
+ pointer to debug frame descriptor, or zero if not found. */
+
+static struct unw_debug_frame_list *
+locate_debug_info (unw_addr_space_t as, unw_word_t addr, const char *dlname,
+ unw_word_t start, unw_word_t end)
+{
+#ifndef PATH_MAX
+# define PATH_MAX 1024
+#endif
+ struct unw_debug_frame_list *w, *fdesc = 0;
+ char path[PATH_MAX];
+ char *name = path;
+ int err;
+ char *buf;
+ size_t bufsize;
+
+ /* First, see if we loaded this frame already. */
+
+ for (w = as->debug_frames; w; w = w->next)
+ {
+ Debug (4, "checking %p: %lx-%lx\n", w, (long)w->start, (long)w->end);
+ if (addr >= w->start && addr < w->end)
+ return w;
+ }
+
+ /* If the object name we receive is blank, there's still a chance of locating
+ the file by parsing /proc/self/maps. */
+
+ if (strcmp (dlname, "") == 0)
+ {
+ err = find_binary_for_address (addr, name, sizeof(path));
+ if (err)
+ {
+ Debug (15, "tried to locate binary for 0x%" PRIx64 ", but no luck\n",
+ (uint64_t) addr);
+ return 0;
+ }
+ }
+ else
+ name = (char*) dlname;
+
+ err = load_debug_frame (name, &buf, &bufsize, 1);
+
+ if (!err)
+ {
+ fdesc = malloc (sizeof (struct unw_debug_frame_list));
+
+ fdesc->start = start;
+ fdesc->end = end;
+ fdesc->debug_frame = buf;
+ fdesc->debug_frame_size = bufsize;
+ fdesc->index = NULL;
+ fdesc->next = as->debug_frames;
+
+ as->debug_frames = fdesc;
+ }
+
+ return fdesc;
+}
+
+struct debug_frame_tab
+ {
+ struct table_entry *tab;
+ uint32_t length;
+ uint32_t size;
+ };
+
+static void
+debug_frame_tab_append (struct debug_frame_tab *tab,
+ unw_word_t fde_offset, unw_word_t start_ip)
+{
+ unsigned int length = tab->length;
+
+ if (length == tab->size)
+ {
+ tab->size *= 2;
+ tab->tab = realloc (tab->tab, sizeof (struct table_entry) * tab->size);
+ }
+
+ tab->tab[length].fde_offset = fde_offset;
+ tab->tab[length].start_ip_offset = start_ip;
+
+ tab->length = length + 1;
+}
+
+static void
+debug_frame_tab_shrink (struct debug_frame_tab *tab)
+{
+ if (tab->size > tab->length)
+ {
+ tab->tab = realloc (tab->tab, sizeof (struct table_entry) * tab->length);
+ tab->size = tab->length;
+ }
+}
+
+static int
+debug_frame_tab_compare (const void *a, const void *b)
+{
+ const struct table_entry *fa = a, *fb = b;
+
+ if (fa->start_ip_offset > fb->start_ip_offset)
+ return 1;
+ else if (fa->start_ip_offset < fb->start_ip_offset)
+ return -1;
+ else
+ return 0;
+}
+
+PROTECTED int
+dwarf_find_debug_frame (unw_addr_space_t unw_local_addr_space,
+ int found, unw_dyn_info_t *di_debug, unw_word_t ip,
+ unw_word_t segbase, const char* obj_name,
+ unw_word_t start, unw_word_t end)
+{
+ unw_dyn_info_t *di;
+ struct unw_debug_frame_list *fdesc = 0;
+ unw_accessors_t *a;
+ unw_word_t addr;
+
+ Debug (15, "Trying to find .debug_frame for %s\n", obj_name);
+ di = di_debug;
+
+ fdesc = locate_debug_info (unw_local_addr_space, ip, obj_name, start, end);
+
+ if (!fdesc)
+ {
+ Debug (15, "couldn't load .debug_frame\n");
+ return found;
+ }
+ else
+ {
+ char *buf;
+ size_t bufsize;
+ unw_word_t item_start, item_end = 0;
+ uint32_t u32val = 0;
+ uint64_t cie_id = 0;
+ struct debug_frame_tab tab;
+
+ Debug (15, "loaded .debug_frame\n");
+
+ buf = fdesc->debug_frame;
+ bufsize = fdesc->debug_frame_size;
+
+ if (bufsize == 0)
+ {
+ Debug (15, "zero-length .debug_frame\n");
+ return found;
+ }
+
+ /* Now create a binary-search table, if it does not already exist. */
+ if (!fdesc->index)
+ {
+ addr = (unw_word_t) (uintptr_t) buf;
+
+ a = unw_get_accessors (unw_local_addr_space);
+
+ /* Find all FDE entries in debug_frame, and make into a sorted
+ index. */
+
+ tab.length = 0;
+ tab.size = 16;
+ tab.tab = calloc (tab.size, sizeof (struct table_entry));
+
+ while (addr < (unw_word_t) (uintptr_t) (buf + bufsize))
+ {
+ uint64_t id_for_cie;
+ item_start = addr;
+
+ dwarf_readu32 (unw_local_addr_space, a, &addr, &u32val, NULL);
+
+ if (u32val == 0)
+ break;
+ else if (u32val != 0xffffffff)
+ {
+ uint32_t cie_id32 = 0;
+ item_end = addr + u32val;
+ dwarf_readu32 (unw_local_addr_space, a, &addr, &cie_id32,
+ NULL);
+ cie_id = cie_id32;
+ id_for_cie = 0xffffffff;
+ }
+ else
+ {
+ uint64_t u64val = 0;
+ /* Extended length. */
+ dwarf_readu64 (unw_local_addr_space, a, &addr, &u64val, NULL);
+ item_end = addr + u64val;
+
+ dwarf_readu64 (unw_local_addr_space, a, &addr, &cie_id, NULL);
+ id_for_cie = 0xffffffffffffffffull;
+ }
+
+ /*Debug (1, "CIE/FDE id = %.8x\n", (int) cie_id);*/
+
+ if (cie_id == id_for_cie)
+ ;
+ /*Debug (1, "Found CIE at %.8x.\n", item_start);*/
+ else
+ {
+ unw_word_t fde_addr = item_start;
+ unw_proc_info_t this_pi;
+ int err;
+
+ /*Debug (1, "Found FDE at %.8x\n", item_start);*/
+
+ err = dwarf_extract_proc_info_from_fde (unw_local_addr_space,
+ a, &fde_addr,
+ &this_pi, 0,
+ (uintptr_t) buf,
+ NULL);
+
+ if (err == 0)
+ {
+ Debug (15, "start_ip = %lx, end_ip = %lx\n",
+ (long) this_pi.start_ip, (long) this_pi.end_ip);
+ debug_frame_tab_append (&tab,
+ item_start - (unw_word_t) (uintptr_t) buf,
+ this_pi.start_ip);
+ }
+ /*else
+ Debug (1, "FDE parse failed\n");*/
+ }
+
+ addr = item_end;
+ }
+
+ debug_frame_tab_shrink (&tab);
+ qsort (tab.tab, tab.length, sizeof (struct table_entry),
+ debug_frame_tab_compare);
+ /* for (i = 0; i < tab.length; i++)
+ {
+ fprintf (stderr, "ip %x, fde offset %x\n",
+ (int) tab.tab[i].start_ip_offset,
+ (int) tab.tab[i].fde_offset);
+ }*/
+ fdesc->index = tab.tab;
+ fdesc->index_size = tab.length;
+ }
+
+ di->format = UNW_INFO_FORMAT_TABLE;
+ di->start_ip = fdesc->start;
+ di->end_ip = fdesc->end;
+ di->u.rti.name_ptr = (unw_word_t) (uintptr_t) obj_name;
+ di->u.rti.table_data = (unw_word_t *) fdesc;
+ di->u.rti.table_len = sizeof (*fdesc) / sizeof (unw_word_t);
+ di->u.rti.segbase = segbase;
+
+ found = 1;
+ Debug (15, "found debug_frame table\n");
+ }
+ return found;
+}
+
+#endif /* CONFIG_DEBUG_FRAME */
+
/* Info is a pointer to a unw_dyn_info_t structure and, on entry,
member u.rti.segbase contains the instruction-pointer we're looking
for. */
@@ -1918,8 +2382,9 @@ callback (struct dl_phdr_info *info, size_t size, void *ptr)
Debug(18, "check %lx versus %lx-%lx\n", ip, vaddr, vaddr + phdr->p_memsz);
- if (ip >= vaddr && ip < vaddr + phdr->p_memsz)
+ if (ip >= vaddr && ip < vaddr + phdr->p_memsz) {
p_text = phdr;
+ }
if (vaddr + phdr->p_filesz > max_load_addr)
max_load_addr = vaddr + phdr->p_filesz;
@@ -1929,8 +2394,37 @@ callback (struct dl_phdr_info *info, size_t size, void *ptr)
else if (phdr->p_type == PT_DYNAMIC)
p_dynamic = phdr;
}
- if (!p_text || !p_eh_hdr)
+ if (!p_text || !p_eh_hdr) {
+#ifdef CONFIG_DEBUG_FRAME
+ /* Find the start/end of the described region by parsing the phdr_info
+ structure. */
+ unw_word_t start, end;
+ start = (unw_word_t) -1;
+ end = 0;
+
+ for (n = 0; n < info->dlpi_phnum; n++)
+ {
+ if (info->dlpi_phdr[n].p_type == PT_LOAD)
+ {
+ unw_word_t seg_start = info->dlpi_addr + info->dlpi_phdr[n].p_vaddr;
+ unw_word_t seg_end = seg_start + info->dlpi_phdr[n].p_memsz;
+
+ if (seg_start < start)
+ start = seg_start;
+
+ if (seg_end > end)
+ end = seg_end;
+ }
+ }
+
+ return dwarf_find_debug_frame (cb_data->as,
+ 0, &cb_data->di, ip,
+ info->dlpi_addr, info->dlpi_name, start,
+ end);
+#else
return 0;
+#endif /* CONFIG_DEBUG_FRAME */
+ }
if (likely (p_eh_hdr->p_vaddr >= p_text->p_vaddr
&& p_eh_hdr->p_vaddr < p_text->p_vaddr + p_text->p_memsz))
@@ -2058,6 +2552,7 @@ dwarf_find_proc_info (unw_addr_space_t as, unw_word_t ip,
cb_data.ip = ip;
cb_data.pi = pi;
cb_data.need_unwind_info = need_unwind_info;
+ cb_data.single_fde = 0;
#ifndef UW_NO_SYNC
sigprocmask (SIG_SETMASK, &unwi_full_mask, &saved_mask);
@@ -2112,19 +2607,42 @@ dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
unw_dyn_info_t *di, unw_proc_info_t *pi,
int need_unwind_info, void *arg)
{
- const struct table_entry *e = NULL;
+ const struct table_entry *e = NULL, *table;
unw_word_t segbase = 0, fde_addr;
unw_accessors_t *a;
int ret;
+ size_t table_len;
+ unw_word_t debug_frame_base;
- assert (di->format == UNW_INFO_FORMAT_REMOTE_TABLE
- && (ip >= di->start_ip && ip < di->end_ip));
+ assert (ip >= di->start_ip && ip < di->end_ip);
a = unw_get_accessors (as);
+ if (di->format == UNW_INFO_FORMAT_REMOTE_TABLE)
+ {
+ table = (const struct table_entry *) (uintptr_t) di->u.rti.table_data;
+ table_len = di->u.rti.table_len * sizeof (unw_word_t);
+ debug_frame_base = 0;
+ }
+ else
+ {
+#ifdef CONFIG_DEBUG_FRAME
+ struct unw_debug_frame_list *fdesc = (void *) di->u.rti.table_data;
+
+ /* UNW_INFO_FORMAT_TABLE (i.e. .debug_frame) is read from local address
+ space. Both the index and the unwind tables live in local memory, but
+ the address space to check for properties like the address size and
+ endianness is the target one. */
+ table = fdesc->index;
+ table_len = fdesc->index_size * sizeof (struct table_entry);
+ debug_frame_base = (uintptr_t) fdesc->debug_frame;
+#else
+ assert(0);
+#endif
+ }
+
segbase = di->u.rti.segbase;
- e = lookup ((struct table_entry *) di->u.rti.table_data,
- di->u.rti.table_len * sizeof (unw_word_t), ip - segbase);
+ e = lookup (table, table_len, ip - segbase);
if (!e)
{
@@ -2134,11 +2652,24 @@ dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
}
Debug (15, "ip=0x%lx, start_ip=0x%lx\n",
(long) ip, (long) (e->start_ip_offset + segbase));
- fde_addr = e->fde_offset + segbase;
+ if (debug_frame_base)
+ fde_addr = e->fde_offset + debug_frame_base;
+ else
+ fde_addr = e->fde_offset + segbase;
if ((ret = dwarf_extract_proc_info_from_fde (as, a, &fde_addr, pi,
- need_unwind_info, arg)) < 0)
+ need_unwind_info,
+ debug_frame_base, arg)) < 0)
return ret;
+ /* .debug_frame uses an absolute encoding that does not know about any
+ shared library relocation. */
+ if (di->format == UNW_INFO_FORMAT_TABLE)
+ {
+ pi->start_ip += segbase;
+ pi->end_ip += segbase;
+ pi->flags = UNW_PI_FLAG_DEBUG_FRAME;
+ }
+
if (ip < pi->start_ip || ip >= pi->end_ip)
return -UNW_ENOINFO;
@@ -2203,7 +2734,7 @@ int dl_iterate_phdr (DL_Iter_Callback callback, void *p)
/***********************************************************************/
-#ifdef PLAIN_X86
+#if defined(PLAIN_X86)
static uint8_t dwarf_to_unw_regnum_map[19] =
{
UNW_X86_EAX, UNW_X86_ECX, UNW_X86_EDX, UNW_X86_EBX,
@@ -2212,7 +2743,7 @@ static uint8_t dwarf_to_unw_regnum_map[19] =
UNW_X86_ST0, UNW_X86_ST1, UNW_X86_ST2, UNW_X86_ST3,
UNW_X86_ST4, UNW_X86_ST5, UNW_X86_ST6, UNW_X86_ST7
};
-#else
+#elif defined(UNW_X86_64)
static uint8_t dwarf_to_unw_regnum_map[17] =
{
UNW_X86_64_RAX,
@@ -2238,27 +2769,114 @@ static uint8_t dwarf_to_unw_regnum_map[17] =
int
unw_get_reg (unw_cursor_t *cursor, int regnum, unw_word_t *valp)
{
- void *p;
+ struct cursor *c = (struct cursor *)cursor;
+ dwarf_loc_t loc = DWARF_NULL_LOC;
+
+#ifdef UNW_ARM
+ switch (regnum)
+ {
+ case UNW_ARM_R0:
+ case UNW_ARM_R1:
+ case UNW_ARM_R2:
+ case UNW_ARM_R3:
+ case UNW_ARM_R4:
+ case UNW_ARM_R5:
+ case UNW_ARM_R6:
+ case UNW_ARM_R7:
+ case UNW_ARM_R8:
+ case UNW_ARM_R9:
+ case UNW_ARM_R10:
+ case UNW_ARM_R11:
+ case UNW_ARM_R12:
+ case UNW_ARM_R14:
+ case UNW_ARM_R15:
+ loc = c->dwarf.loc[regnum - UNW_ARM_R0];
+ break;
- p = tdep_uc_addr(((struct cursor *)cursor)->dwarf.as_arg, regnum);
- if (p) {
- *valp = *(unw_word_t *)p;
- return 1;
- } else {
- *valp = -1;
- return 0;
- }
+ case UNW_ARM_R13:
+ *valp = c->dwarf.cfa;
+ return 0;
+
+ /* FIXME: Initialise coprocessor & shadow registers? */
+
+ default:
+ Debug (1, "bad register number %u\n", reg);
+ return -UNW_EBADREG;
+ }
+#endif
+
+#ifdef UNW_X86_64
+ unsigned int mask;
+ int arg_num;
+
+ switch (regnum)
+ {
+
+ case UNW_X86_64_RIP:
+ if (write)
+ c->dwarf.ip = *valp; /* also update the RIP cache */
+ loc = c->dwarf.loc[REG_RIP];
+ break;
+
+ case UNW_X86_64_CFA:
+ case UNW_X86_64_RSP:
+ if (write)
+ return -UNW_EREADONLYREG;
+ *valp = c->dwarf.cfa;
+ return 0;
+
+ case UNW_X86_64_RAX:
+ case UNW_X86_64_RDX:
+ arg_num = regnum - UNW_X86_64_RAX;
+ mask = (1 << arg_num);
+ if (write)
+ {
+ c->dwarf.eh_args[arg_num] = *valp;
+ c->dwarf.eh_valid_mask |= mask;
+ return 0;
+ }
+ else if ((c->dwarf.eh_valid_mask & mask) != 0)
+ {
+ *valp = c->dwarf.eh_args[arg_num];
+ return 0;
+ }
+ else
+ loc = c->dwarf.loc[(regnum == UNW_X86_64_RAX) ? REG_RAX : REG_RDX];
+ break;
+
+ case UNW_X86_64_RCX: loc = c->dwarf.loc[REG_RCX]; break;
+ case UNW_X86_64_RBX: loc = c->dwarf.loc[REG_RBX]; break;
+
+ case UNW_X86_64_RBP: loc = c->dwarf.loc[REG_RBP]; break;
+ case UNW_X86_64_RSI: loc = c->dwarf.loc[REG_RSI]; break;
+ case UNW_X86_64_RDI: loc = c->dwarf.loc[REG_RDI]; break;
+ case UNW_X86_64_R8: loc = c->dwarf.loc[REG_R8]; break;
+ case UNW_X86_64_R9: loc = c->dwarf.loc[REG_R9]; break;
+ case UNW_X86_64_R10: loc = c->dwarf.loc[REG_R10]; break;
+ case UNW_X86_64_R11: loc = c->dwarf.loc[REG_R11]; break;
+ case UNW_X86_64_R12: loc = c->dwarf.loc[REG_R12]; break;
+ case UNW_X86_64_R13: loc = c->dwarf.loc[REG_R13]; break;
+ case UNW_X86_64_R14: loc = c->dwarf.loc[REG_R14]; break;
+ case UNW_X86_64_R15: loc = c->dwarf.loc[REG_R15]; break;
+
+ default:
+ Debug (1, "bad register number %u\n", regnum);
+ return -UNW_EBADREG;
+ }
+#endif
+
+ return dwarf_get (&c->dwarf, loc, valp);
}
void *
-tdep_uc_addr (ucontext_t *uc, int reg)
+tdep_uc_addr (unw_context_t *uc, int reg)
{
void *addr;
switch (reg)
{
#ifdef LINUX
-# ifdef PLAIN_X86
+# if defined(PLAIN_X86)
case UNW_X86_GS: addr = &uc->uc_mcontext.gregs[REG_GS]; break;
case UNW_X86_FS: addr = &uc->uc_mcontext.gregs[REG_FS]; break;
case UNW_X86_ES: addr = &uc->uc_mcontext.gregs[REG_ES]; break;
@@ -2276,7 +2894,7 @@ tdep_uc_addr (ucontext_t *uc, int reg)
case UNW_X86_CS: addr = &uc->uc_mcontext.gregs[REG_CS]; break;
case UNW_X86_EFLAGS: addr = &uc->uc_mcontext.gregs[REG_EFL]; break;
case UNW_X86_SS: addr = &uc->uc_mcontext.gregs[REG_SS]; break;
-# else
+# elif defined(UNW_X86_64)
case UNW_X86_64_R8: addr = &uc->uc_mcontext.gregs[REG_R8]; break;
case UNW_X86_64_R9: addr = &uc->uc_mcontext.gregs[REG_R9]; break;
case UNW_X86_64_R10: addr = &uc->uc_mcontext.gregs[REG_R10]; break;
@@ -2294,6 +2912,24 @@ tdep_uc_addr (ucontext_t *uc, int reg)
case UNW_X86_64_RCX: addr = &uc->uc_mcontext.gregs[REG_RCX]; break;
case UNW_X86_64_RSP: addr = &uc->uc_mcontext.gregs[REG_RSP]; break;
case UNW_X86_64_RIP: addr = &uc->uc_mcontext.gregs[REG_RIP]; break;
+# elif defined(UNW_ARM)
+ case UNW_ARM_R0:
+ case UNW_ARM_R1:
+ case UNW_ARM_R2:
+ case UNW_ARM_R3:
+ case UNW_ARM_R4:
+ case UNW_ARM_R5:
+ case UNW_ARM_R6:
+ case UNW_ARM_R7:
+ case UNW_ARM_R8:
+ case UNW_ARM_R9:
+ case UNW_ARM_R10:
+ case UNW_ARM_R11:
+ case UNW_ARM_R12:
+ case UNW_ARM_R13:
+ case UNW_ARM_R14:
+ case UNW_ARM_R15:
+ addr = &(uc->regs[reg]); break;
# endif
#endif
#ifdef OS_X
@@ -2323,7 +2959,11 @@ tdep_uc_addr (ucontext_t *uc, int reg)
int dwarf_to_unw_regnum(reg)
{
+#ifdef UNW_ARM
+ return (((reg) < 16) ? (reg) : 0);
+#else
return (((reg) <= DWARF_REGNUM_MAP_LENGTH) ? dwarf_to_unw_regnum_map[reg] : 0);
+#endif
}
#ifdef PLAIN_X86
@@ -2340,7 +2980,9 @@ int dwarf_to_unw_regnum(reg)
#define EFLAGS 9
#define TRAPNO 10
#define ST0 11
-#else
+#endif
+
+#ifdef UNW_X86_64
/* DWARF column numbers for x86_64: */
#define RAX 0
#define RDX 1
@@ -2402,7 +3044,9 @@ common_init (struct cursor *c)
return 0;
}
-#else
+#endif
+
+#ifdef UNW_X86_64
static inline int
common_init (struct cursor *c)
{
@@ -2448,7 +3092,61 @@ common_init (struct cursor *c)
}
#endif
-int unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
+#ifdef UNW_ARM
+static inline int
+common_init (struct cursor *c)
+{
+ int i, ret;
+
+ c->dwarf.loc[UNW_ARM_R0] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R0);
+ c->dwarf.loc[UNW_ARM_R1] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R1);
+ c->dwarf.loc[UNW_ARM_R2] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R2);
+ c->dwarf.loc[UNW_ARM_R3] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R3);
+ c->dwarf.loc[UNW_ARM_R4] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R4);
+ c->dwarf.loc[UNW_ARM_R5] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R5);
+ c->dwarf.loc[UNW_ARM_R6] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R6);
+ c->dwarf.loc[UNW_ARM_R7] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R7);
+ c->dwarf.loc[UNW_ARM_R8] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R8);
+ c->dwarf.loc[UNW_ARM_R9] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R9);
+ c->dwarf.loc[UNW_ARM_R10] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R10);
+ c->dwarf.loc[UNW_ARM_R11] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R11);
+ c->dwarf.loc[UNW_ARM_R12] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R12);
+ c->dwarf.loc[UNW_ARM_R13] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R13);
+ c->dwarf.loc[UNW_ARM_R14] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R14);
+ c->dwarf.loc[UNW_ARM_R15] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R15);
+ for (i = UNW_ARM_R15 + 1; i < DWARF_NUM_PRESERVED_REGS; ++i)
+ c->dwarf.loc[i] = DWARF_NULL_LOC;
+
+ ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_ARM_R15], &c->dwarf.ip);
+ if (ret < 0)
+ return ret;
+
+ /* FIXME: correct for ARM? */
+ ret = dwarf_get (&c->dwarf, DWARF_REG_LOC (&c->dwarf, UNW_ARM_R13),
+ &c->dwarf.cfa);
+ if (ret < 0)
+ return ret;
+
+ c->sigcontext_format = ARM_SCF_NONE;
+ c->sigcontext_addr = 0;
+
+ /* FIXME: Initialisation for other registers. */
+
+ c->dwarf.args_size = 0;
+ c->dwarf.ret_addr_column = 0;
+ c->dwarf.pi_valid = 0;
+ c->dwarf.hint = 0;
+ c->dwarf.prev_rs = 0;
+
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_DEBUG_FRAME
+struct unw_debug_frame_list *shared_debug_frames;
+#endif
+
+int unw_init_local (unw_cursor_t *cursor, unw_context_t *uc)
{
struct cursor *c = (struct cursor *) cursor;
unw_addr_space_t as;
@@ -2458,6 +3156,10 @@ int unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
as = (unw_addr_space_t)malloc(sizeof(struct unw_addr_space));
memset(as, 0, sizeof(struct unw_addr_space));
+#ifdef CONFIG_DEBUG_FRAME
+ as->debug_frames = shared_debug_frames;
+#endif
+
c->dwarf.as = as;
c->dwarf.as_arg = uc;
return common_init (c);
@@ -2466,6 +3168,11 @@ int unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
void unw_destroy_local(unw_cursor_t *cursor)
{
struct cursor *c = (struct cursor *) cursor;
+
+#ifdef CONFIG_DEBUG_FRAME
+ shared_debug_frames = c->dwarf.as->debug_frames;
+#endif
+
free_all_allocated(c->dwarf.as);
free(c->dwarf.as);
}
@@ -2515,7 +3222,12 @@ unw_word_t unw_get_ip(unw_cursor_t *c)
unw_word_t unw_get_frame_pointer(unw_cursor_t *c)
{
- return *(unw_word_t *)safe_pointer(((struct cursor *)c)->dwarf.loc[6 /* = BP */].val);
+#ifdef UNW_ARM
+# define JIT_FRAME_POINTER_ID 11
+#else
+# define JIT_FRAME_POINTER_ID 6 /* = BP */
+#endif
+ return *(unw_word_t *)safe_pointer(((struct cursor *)c)->dwarf.loc[JIT_FRAME_POINTER_ID].val);
}
void unw_manual_step(unw_cursor_t *_c,
@@ -2537,7 +3249,7 @@ void unw_manual_step(unw_cursor_t *_c,
c->dwarf.ip = *(unw_word_t *)safe_pointer((unw_word_t)ip_addr);
c->dwarf.cfa = *(unw_word_t *)safe_pointer((unw_word_t)sp_addr);
- c->dwarf.ret_addr_column = RIP;
+ c->dwarf.ret_addr_column = UNW_TDEP_IP;
c->dwarf.pi_valid = 0;
c->dwarf.hint = 0;
c->dwarf.prev_rs = 0;
diff --git a/src/racket/src/unwind/libunwind.h b/src/racket/src/unwind/libunwind.h
index 7fe222166c..4b24f3a414 100644
--- a/src/racket/src/unwind/libunwind.h
+++ b/src/racket/src/unwind/libunwind.h
@@ -32,11 +32,23 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#if defined(i386)
# define PLAIN_X86
#endif
+#if defined(__x86_64__)
+# define UNW_X86_64
+#endif
+#if defined(__arm__)
+# define UNW_ARM
+#endif
-#ifdef PLAIN_X86
+#if defined(PLAIN_X86)
# define UNW_IP UNW_X86_EIP
-#else
+#elif defined(UNW_X86_64)
# define UNW_IP UNW_X86_64_RIP
+#elif defined(UNW_ARM)
+# define UNW_IP UNW_ARM_RIP
+#endif
+
+#ifdef UNW_ARM
+# define CONFIG_DEBUG_FRAME
#endif
#if defined(__cplusplus) || defined(c_plusplus)
@@ -44,10 +56,12 @@ extern "C" {
#endif
#include
-#define _XOPEN_SOURCE /* needed for Mac OS X */
-#define __USE_GNU
-#include
-#undef __USE_GNU
+#ifndef UNW_ARM
+# define _XOPEN_SOURCE /* needed for Mac OS X */
+# define __USE_GNU
+# include
+# undef __USE_GNU
+#endif
/* XXXXXXXXXXXXXXXXXXXX x86 Target XXXXXXXXXXXXXXXXXXXX */
@@ -157,13 +171,17 @@ typedef enum
}
x86_regnum_t;
+/* On x86, we can directly use ucontext_t as the unwind context. */
+typedef ucontext_t unw_tdep_context_t;
+#define unw_tdep_getcontext(uc) (getcontext (uc), 0)
+
#endif
/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
/* XXXXXXXXXXXXXXXXXXXX x86_64 Target XXXXXXXXXXXXXXXXXXXX */
-#ifndef PLAIN_X86
+#ifdef UNW_X86_64
#define UNW_TARGET x86_64
#define UNW_TARGET_X86_64 1
@@ -216,6 +234,94 @@ typedef enum
}
x86_64_regnum_t;
+/* On x86, we can directly use ucontext_t as the unwind context. */
+typedef ucontext_t unw_tdep_context_t;
+#define unw_tdep_getcontext(uc) (getcontext (uc), 0)
+
+#endif
+
+ /* XXXXXXXXXXXXXXXXXXXX ARM Target XXXXXXXXXXXXXXXXXXXX */
+
+#ifdef UNW_ARM
+
+#define UNW_TARGET ARM
+#define UNW_TARGET_ARM 1
+
+#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
+
+/* This needs to be big enough to accommodate "struct cursor", while
+ leaving some slack for future expansion. Changing this value will
+ require recompiling all users of this library. Stack allocation is
+ relatively cheap and unwind-state copying is relatively rare, so we
+ want to err on making it rather too big than too small. */
+#define UNW_TDEP_CURSOR_LEN 127
+
+typedef uint32_t unw_word_t;
+typedef int32_t unw_sword_t;
+
+typedef double unw_tdep_fpreg_t;
+
+typedef enum
+ {
+ UNW_ARM_R0,
+ UNW_ARM_R1,
+ UNW_ARM_R2,
+ UNW_ARM_R3,
+ UNW_ARM_R4,
+ UNW_ARM_R5,
+ UNW_ARM_R6,
+ UNW_ARM_R7,
+ UNW_ARM_R8,
+ UNW_ARM_R9,
+ UNW_ARM_R10,
+ UNW_ARM_R11,
+ UNW_ARM_R12,
+ UNW_ARM_R13,
+ UNW_ARM_RSP = UNW_ARM_R13,
+ UNW_ARM_R14,
+ UNW_ARM_R15,
+ UNW_ARM_RIP = UNW_ARM_R15,
+
+ UNW_TDEP_LAST_REG = UNW_ARM_R15,
+
+ UNW_TDEP_IP = UNW_ARM_RIP,
+ UNW_TDEP_SP = UNW_ARM_RSP,
+ UNW_TDEP_EH = UNW_ARM_R0
+
+ }
+arm_regnum_t;
+
+typedef struct {
+ unsigned long regs[16];
+} unw_tdep_context_t;
+
+/* There is no getcontext() on ARM. Use a stub version which only saves GP
+ registers. FIXME: Not ideal, may not be sufficient for all libunwind
+ use cases. Stores pc+8, which is only approximately correct, really. */
+#ifndef __thumb__
+#define unw_tdep_getcontext(uc) (({ \
+ unw_tdep_context_t *unw_ctx = (uc); \
+ register unsigned long *unw_base asm ("r0") = unw_ctx; \
+ __asm__ __volatile__ ( \
+ "stmia %[base], {r0-r15}" \
+ : : [base] "r" (unw_base) : "memory"); \
+ }), 0)
+#else /* __thumb__ */
+#define unw_tdep_getcontext(uc) (({ \
+ unw_tdep_context_t *unw_ctx = (uc); \
+ register unsigned long *unw_base asm ("r0") = unw_ctx; \
+ __asm__ __volatile__ ( \
+ ".align 2\nbx pc\nnop\n.code 32\n" \
+ "stmia %[base], {r0-r15}\n" \
+ "orr %[base], pc, #1\nbx %[base]" \
+ : [base] "+r" (unw_base) : : "memory", "cc"); \
+ }), 0)
+#endif
+
+#ifndef PT_GNU_EH_FRAME
+# define PT_GNU_EH_FRAME -1
+#endif
+
#endif
/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
@@ -228,15 +334,6 @@ typedef struct unw_tdep_save_loc
}
unw_tdep_save_loc_t;
-/* On x86, we can directly use ucontext_t as the unwind context. */
-typedef ucontext_t unw_tdep_context_t;
-
-/* XXX this is not ideal: an application should not be prevented from
- using the "getcontext" name just because it's using libunwind. We
- can't just use __getcontext() either, because that isn't exported
- by glibc... */
-#define unw_tdep_getcontext(uc) (getcontext (uc), 0)
-
typedef struct unw_dyn_remote_table_info
{
diff --git a/src/racket/src/unwind/libunwind_i.h b/src/racket/src/unwind/libunwind_i.h
index ac4525abbe..71c7b62451 100644
--- a/src/racket/src/unwind/libunwind_i.h
+++ b/src/racket/src/unwind/libunwind_i.h
@@ -530,6 +530,7 @@ typedef struct dwarf_reg_state
unsigned short lru_chain; /* used for least-recently-used chain */
unsigned short coll_chain; /* used for hash collisions */
unsigned short hint; /* hint for next rs to try (or -1) */
+ char valid, signal_frame;
}
dwarf_reg_state_t;
@@ -549,6 +550,7 @@ typedef struct dwarf_cie_info
uint8_t lsda_encoding;
unsigned int sized_augmentation : 1;
unsigned int have_abi_marker : 1;
+ unsigned int signal_frame : 1;
}
dwarf_cie_info_t;
@@ -581,6 +583,8 @@ typedef struct dwarf_cursor
short hint; /* faster lookup of the rs cache */
short prev_rs;
+
+ int use_prev_instr;
}
dwarf_cursor_t;
@@ -637,6 +641,7 @@ HIDDEN int dwarf_extract_proc_info_from_fde (unw_addr_space_t as,
unw_word_t *fde_addr,
unw_proc_info_t *pi,
int need_unwind_info,
+ unw_word_t base,
void *arg);
HIDDEN int dwarf_find_save_locs (struct dwarf_cursor *c);
HIDDEN int dwarf_read_encoded_pointer (unw_addr_space_t as,
@@ -649,6 +654,23 @@ HIDDEN int dwarf_step (struct dwarf_cursor *c);
/*XXXXXXXXXXXXXXXXXXXXXXXXX End dwarf.h XXXXXXXXXXXXXXXXXXXXXXXXXX*/
+#ifdef CONFIG_DEBUG_FRAME
+struct unw_debug_frame_list
+ {
+ /* The start (inclusive) and end (exclusive) of the described region. */
+ unw_word_t start;
+ unw_word_t end;
+ /* The debug frame itself. */
+ char *debug_frame;
+ size_t debug_frame_size;
+ /* Index (for binary search). */
+ struct table_entry *index;
+ size_t index_size;
+ /* Pointer to next descriptor. */
+ struct unw_debug_frame_list *next;
+ };
+#endif
+
struct unw_addr_space
{
void *mem_pool;
@@ -660,6 +682,9 @@ struct unw_addr_space
uint32_t cache_generation;
#endif
struct dwarf_rs_cache global_cache;
+#ifdef CONFIG_DEBUG_FRAME
+ struct unw_debug_frame_list *debug_frames;
+#endif
};
struct cursor
@@ -672,7 +697,8 @@ struct cursor
{
X86_SCF_NONE, /* no signal frame encountered */
X86_SCF_LINUX_SIGFRAME, /* classic x86 sigcontext */
- X86_SCF_LINUX_RT_SIGFRAME /* POSIX ucontext_t */
+ X86_SCF_LINUX_RT_SIGFRAME, /* POSIX ucontext_t */
+ ARM_SCF_NONE
}
sigcontext_format;
unw_word_t sigcontext_addr;
@@ -756,7 +782,7 @@ extern void tdep_init (void);
extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
unw_dyn_info_t *di, unw_proc_info_t *pi,
int need_unwind_info, void *arg);
-extern void *tdep_uc_addr (ucontext_t *uc, int reg);
+extern void *tdep_uc_addr (unw_context_t *uc, int reg);
extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
unsigned long *segbase, unsigned long *mapoff);
extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
diff --git a/src/racket/src/unwind/os-linux.h b/src/racket/src/unwind/os-linux.h
new file mode 100644
index 0000000000..ad9d675e6c
--- /dev/null
+++ b/src/racket/src/unwind/os-linux.h
@@ -0,0 +1,297 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2003-2004 Hewlett-Packard Co
+ Copyright (C) 2007 David Mosberger-Tang
+ Contributed by David Mosberger-Tang
+
+This file is part of libunwind.
+
+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. */
+
+#ifndef os_linux_h
+#define os_linux_h
+
+struct map_iterator
+ {
+ off_t offset;
+ int fd;
+ size_t buf_size;
+ char *buf;
+ char *buf_end;
+ char *path;
+ };
+
+static inline char *
+ltoa (char *buf, long val)
+{
+ char *cp = buf, tmp;
+ ssize_t i, len;
+
+ do
+ {
+ *cp++ = '0' + (val % 10);
+ val /= 10;
+ }
+ while (val);
+
+ /* reverse the order of the digits: */
+ len = cp - buf;
+ --cp;
+ for (i = 0; i < len / 2; ++i)
+ {
+ tmp = buf[i];
+ buf[i] = cp[-i];
+ cp[-i] = tmp;
+ }
+ return buf + len;
+}
+
+static inline int
+maps_init (struct map_iterator *mi, pid_t pid)
+{
+ char path[sizeof ("/proc/0123456789/maps")], *cp;
+
+ memcpy (path, "/proc/", 6);
+ cp = ltoa (path + 6, pid);
+ assert (cp + 6 < path + sizeof (path));
+ memcpy (cp, "/maps", 6);
+
+ mi->fd = open (path, O_RDONLY);
+ if (mi->fd >= 0)
+ {
+ /* Try to allocate a page-sized buffer. */
+ mi->buf_size = getpagesize ();
+ cp = mmap (NULL, mi->buf_size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (cp == MAP_FAILED)
+ {
+ close(mi->fd);
+ mi->fd = -1;
+ return -1;
+ }
+ else
+ {
+ mi->offset = 0;
+ mi->buf = mi->buf_end = cp + mi->buf_size;
+ return 0;
+ }
+ }
+ return -1;
+}
+
+static inline char *
+skip_whitespace (char *cp)
+{
+ if (!cp)
+ return NULL;
+
+ while (*cp == ' ' || *cp == '\t')
+ ++cp;
+ return cp;
+}
+
+static inline char *
+scan_hex (char *cp, unsigned long *valp)
+{
+ unsigned long num_digits = 0, digit, val = 0;
+
+ cp = skip_whitespace (cp);
+ if (!cp)
+ return NULL;
+
+ while (1)
+ {
+ digit = *cp;
+ if ((digit - '0') <= 9)
+ digit -= '0';
+ else if ((digit - 'a') < 6)
+ digit -= 'a' - 10;
+ else if ((digit - 'A') < 6)
+ digit -= 'A' - 10;
+ else
+ break;
+ val = (val << 4) | digit;
+ ++num_digits;
+ ++cp;
+ }
+ if (!num_digits)
+ return NULL;
+ *valp = val;
+ return cp;
+}
+
+static inline char *
+scan_dec (char *cp, unsigned long *valp)
+{
+ unsigned long num_digits = 0, digit, val = 0;
+
+ if (!(cp = skip_whitespace (cp)))
+ return NULL;
+
+ while (1)
+ {
+ digit = *cp;
+ if ((digit - '0') <= 9)
+ {
+ digit -= '0';
+ ++cp;
+ }
+ else
+ break;
+ val = (10 * val) + digit;
+ ++num_digits;
+ }
+ if (!num_digits)
+ return NULL;
+ *valp = val;
+ return cp;
+}
+
+static inline char *
+scan_char (char *cp, char *valp)
+{
+ if (!cp)
+ return NULL;
+
+ *valp = *cp;
+
+ /* don't step over NUL terminator */
+ if (*cp)
+ ++cp;
+ return cp;
+}
+
+/* Scan a string delimited by white-space. Fails on empty string or
+ if string is doesn't fit in the specified buffer. */
+static inline char *
+scan_string (char *cp, char *valp, size_t buf_size)
+{
+ size_t i = 0;
+
+ if (!(cp = skip_whitespace (cp)))
+ return NULL;
+
+ while (*cp != ' ' && *cp != '\t' && *cp != '\0')
+ {
+ if ((valp != NULL) && (i < buf_size - 1))
+ valp[i++] = *cp;
+ ++cp;
+ }
+ if (i == 0 || i >= buf_size)
+ return NULL;
+ valp[i] = '\0';
+ return cp;
+}
+
+static inline int
+maps_next (struct map_iterator *mi,
+ unsigned long *low, unsigned long *high, unsigned long *offset)
+{
+ char perm[16], dash = 0, colon = 0, *cp;
+ unsigned long major, minor, inum;
+ ssize_t i, nread;
+
+ if (mi->fd < 0)
+ return 0;
+
+ while (1)
+ {
+ ssize_t bytes_left = mi->buf_end - mi->buf;
+ char *eol = NULL;
+
+ for (i = 0; i < bytes_left; ++i)
+ {
+ if (mi->buf[i] == '\n')
+ {
+ eol = mi->buf + i;
+ break;
+ }
+ else if (mi->buf[i] == '\0')
+ break;
+ }
+ if (!eol)
+ {
+ /* copy down the remaining bytes, if any */
+ if (bytes_left > 0)
+ memmove (mi->buf_end - mi->buf_size, mi->buf, bytes_left);
+
+ mi->buf = mi->buf_end - mi->buf_size;
+ nread = read (mi->fd, mi->buf + bytes_left,
+ mi->buf_size - bytes_left);
+ if (nread <= 0)
+ return 0;
+ else if ((size_t) (nread + bytes_left) < mi->buf_size)
+ {
+ /* Move contents to the end of the buffer so we
+ maintain the invariant that all bytes between
+ mi->buf and mi->buf_end are valid. */
+ memmove (mi->buf_end - nread - bytes_left, mi->buf,
+ nread + bytes_left);
+ mi->buf = mi->buf_end - nread - bytes_left;
+ }
+
+ eol = mi->buf + bytes_left + nread - 1;
+
+ for (i = bytes_left; i < bytes_left + nread; ++i)
+ if (mi->buf[i] == '\n')
+ {
+ eol = mi->buf + i;
+ break;
+ }
+ }
+ cp = mi->buf;
+ mi->buf = eol + 1;
+ *eol = '\0';
+
+ /* scan: "LOW-HIGH PERM OFFSET MAJOR:MINOR INUM PATH" */
+ cp = scan_hex (cp, low);
+ cp = scan_char (cp, &dash);
+ cp = scan_hex (cp, high);
+ cp = scan_string (cp, perm, sizeof (perm));
+ cp = scan_hex (cp, offset);
+ cp = scan_hex (cp, &major);
+ cp = scan_char (cp, &colon);
+ cp = scan_hex (cp, &minor);
+ cp = scan_dec (cp, &inum);
+ cp = mi->path = skip_whitespace (cp);
+ if (!cp)
+ continue;
+ cp = scan_string (cp, NULL, 0);
+ if (dash != '-' || colon != ':')
+ continue; /* skip line with unknown or bad format */
+ return 1;
+ }
+ return 0;
+}
+
+static inline void
+maps_close (struct map_iterator *mi)
+{
+ if (mi->fd < 0)
+ return;
+ close (mi->fd);
+ mi->fd = -1;
+ if (mi->buf)
+ {
+ munmap (mi->buf_end - mi->buf_size, mi->buf_size);
+ mi->buf = mi->buf_end = NULL;
+ }
+}
+
+#endif /* os_linux_h */