From d5ede87ae8b353f47f1de29e3c543cd5d6885338 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Tue, 2 Apr 2013 14:32:52 -0600 Subject: [PATCH] JIT for ARM Includes switch from LGPL 2.1 to LGPL 3, since the ARM port of GNU lightining is licensed under LGPL 3. --- README | 2 +- collects/scribblings/guide/performance.scrbl | 2 +- collects/scribblings/main/license.scrbl | 4 +- doc/release-notes/COPYING.txt | 1022 ++++--- doc/release-notes/racket/HISTORY.txt | 3 + src/configure | 2 +- src/foreign/foreign.c | 130 + src/foreign/foreign.rktc | 10 + src/foreign/libffi/config.sub | 276 +- src/lt/config.sub | 362 ++- src/racket/configure.ac | 2 +- src/racket/include/scheme.h | 2 +- src/racket/sconfig.h | 40 +- src/racket/src/Makefile.in | 5 + src/racket/src/jit.c | 64 +- src/racket/src/jit.h | 89 +- src/racket/src/jitalloc.c | 39 +- src/racket/src/jitarith.c | 29 +- src/racket/src/jitcall.c | 36 +- src/racket/src/jitcommon.c | 225 +- src/racket/src/jitinline.c | 44 +- src/racket/src/jitstack.c | 28 +- src/racket/src/jitstate.c | 14 +- src/racket/src/lightning/arm/asm-common.h | 269 ++ src/racket/src/lightning/arm/asm.h | 2220 +++++++++++++++ src/racket/src/lightning/arm/core-common.h | 695 +++++ src/racket/src/lightning/arm/core.h | 2588 ++++++++++++++++++ src/racket/src/lightning/arm/fp-common.h | 188 ++ src/racket/src/lightning/arm/fp-swf.h | 1171 ++++++++ src/racket/src/lightning/arm/fp-vfp.h | 1022 +++++++ src/racket/src/lightning/arm/fp.h | 1074 ++++++++ src/racket/src/lightning/arm/funcs-common.h | 47 + src/racket/src/lightning/arm/funcs.h | 136 + src/racket/src/lightning/i386/core-common.h | 6 +- src/racket/src/lightning/lightning.h | 13 + src/racket/src/lightning/ppc/core-common.h | 6 +- src/racket/src/place.c | 2 - src/racket/src/schpriv.h | 7 +- src/racket/src/unwind/libunwind.c | 862 +++++- src/racket/src/unwind/libunwind.h | 129 +- src/racket/src/unwind/libunwind_i.h | 30 +- src/racket/src/unwind/os-linux.h | 297 ++ 42 files changed, 12232 insertions(+), 960 deletions(-) create mode 100644 src/racket/src/lightning/arm/asm-common.h create mode 100644 src/racket/src/lightning/arm/asm.h create mode 100644 src/racket/src/lightning/arm/core-common.h create mode 100644 src/racket/src/lightning/arm/core.h create mode 100644 src/racket/src/lightning/arm/fp-common.h create mode 100644 src/racket/src/lightning/arm/fp-swf.h create mode 100644 src/racket/src/lightning/arm/fp-vfp.h create mode 100644 src/racket/src/lightning/arm/fp.h create mode 100644 src/racket/src/lightning/arm/funcs-common.h create mode 100644 src/racket/src/lightning/arm/funcs.h create mode 100644 src/racket/src/unwind/os-linux.h 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 */