From 3b4c0619133a7a6e829d2d2db267f5b0f4e8c93d Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Sun, 10 Oct 2004 21:18:38 +0000 Subject: [PATCH] initial import (automatically generated log message) git-archimport-id: bonzini@gnu.org--2004b/lightning--stable--1.2--base-0 --- AUTHORS | 2 + COPYING | 340 +++++ COPYING.DOC | 355 +++++ COPYING.LESSER | 503 +++++++ ChangeLog | 75 + INSTALL | 229 +++ Makefile.am | 19 + NEWS | 124 ++ README | 3 + config/help2man | 559 ++++++++ config/texi2dvi | 660 +++++++++ configure.ac | 94 ++ doc/Makefile.am | 18 + doc/body.texi | 306 +++++ doc/lightning.texi | 105 ++ doc/porting.texi | 1415 +++++++++++++++++++ doc/toc.texi | 77 ++ doc/using.texi | 1086 +++++++++++++++ doc/version.texi | 4 + lightning-inst.h | 65 + lightning.h.in | 88 ++ lightning.m4 | 57 + lightning/Makefile.am | 16 + lightning/asm-common.h | 197 +++ lightning/core-common.h | 568 ++++++++ lightning/fp-common.h | 260 ++++ lightning/funcs-common.h | 48 + lightning/i386/asm.h | 1060 ++++++++++++++ lightning/i386/core.h | 408 ++++++ lightning/i386/fp.h | 252 ++++ lightning/i386/funcs.h | 39 + lightning/ppc/asm.h | 597 ++++++++ lightning/ppc/core.h | 276 ++++ lightning/ppc/fp.h | 104 ++ lightning/ppc/funcs.h | 161 +++ lightning/sparc/asm.h | 303 ++++ lightning/sparc/core.h | 249 ++++ lightning/sparc/fp.h | 163 +++ lightning/sparc/funcs.h | 65 + lightningize.in | 226 +++ opcode/Makefile.am | 7 + opcode/ansidecl.h | 13 + opcode/bfd.h | 185 +++ opcode/dis-asm.h | 175 +++ opcode/dis-buf.c | 70 + opcode/disass.c | 78 ++ opcode/i386-dis.c | 2031 +++++++++++++++++++++++++++ opcode/i386.h | 898 ++++++++++++ opcode/ppc-dis.c | 238 ++++ opcode/ppc-opc.c | 2830 ++++++++++++++++++++++++++++++++++++++ opcode/ppc.h | 248 ++++ opcode/sparc-dis.c | 868 ++++++++++++ opcode/sparc-opc.c | 1757 +++++++++++++++++++++++ opcode/sparc.h | 220 +++ opcode/sysdep.h | 10 + tests/Makefile.am | 16 + tests/add.c | 61 + tests/add.ok | 1 + tests/fib.c | 77 ++ tests/fib.ok | 1 + tests/fibdelay.c | 77 ++ tests/fibdelay.ok | 1 + tests/fibit.c | 75 + tests/fibit.ok | 1 + tests/funcfp.c | 173 +++ tests/funcfp.ok | 1 + tests/incr.c | 59 + tests/incr.ok | 1 + tests/printf.c | 68 + tests/printf.ok | 1 + tests/printf2.c | 2409 ++++++++++++++++++++++++++++++++ tests/printf2.ok | 2376 ++++++++++++++++++++++++++++++++ tests/rpn.c | 445 ++++++ tests/rpn.ok | 6 + tests/rpnfp.c | 134 ++ tests/rpnfp.ok | 6 + tests/run-test | 9 + tests/testfp.c | 186 +++ tests/testfp.ok | 5 + 79 files changed, 26993 insertions(+) create mode 100644 AUTHORS create mode 100644 COPYING create mode 100644 COPYING.DOC create mode 100644 COPYING.LESSER create mode 100644 ChangeLog create mode 100644 INSTALL create mode 100644 Makefile.am create mode 100644 NEWS create mode 100644 README create mode 100755 config/help2man create mode 100755 config/texi2dvi create mode 100644 configure.ac create mode 100644 doc/Makefile.am create mode 100644 doc/body.texi create mode 100644 doc/lightning.texi create mode 100644 doc/porting.texi create mode 100644 doc/toc.texi create mode 100644 doc/using.texi create mode 100644 doc/version.texi create mode 100644 lightning-inst.h create mode 100644 lightning.h.in create mode 100644 lightning.m4 create mode 100644 lightning/Makefile.am create mode 100644 lightning/asm-common.h create mode 100644 lightning/core-common.h create mode 100644 lightning/fp-common.h create mode 100644 lightning/funcs-common.h create mode 100644 lightning/i386/asm.h create mode 100644 lightning/i386/core.h create mode 100644 lightning/i386/fp.h create mode 100644 lightning/i386/funcs.h create mode 100644 lightning/ppc/asm.h create mode 100644 lightning/ppc/core.h create mode 100644 lightning/ppc/fp.h create mode 100644 lightning/ppc/funcs.h create mode 100644 lightning/sparc/asm.h create mode 100644 lightning/sparc/core.h create mode 100644 lightning/sparc/fp.h create mode 100644 lightning/sparc/funcs.h create mode 100644 lightningize.in create mode 100644 opcode/Makefile.am create mode 100644 opcode/ansidecl.h create mode 100644 opcode/bfd.h create mode 100644 opcode/dis-asm.h create mode 100644 opcode/dis-buf.c create mode 100644 opcode/disass.c create mode 100644 opcode/i386-dis.c create mode 100644 opcode/i386.h create mode 100644 opcode/ppc-dis.c create mode 100644 opcode/ppc-opc.c create mode 100644 opcode/ppc.h create mode 100644 opcode/sparc-dis.c create mode 100644 opcode/sparc-opc.c create mode 100644 opcode/sparc.h create mode 100644 opcode/sysdep.h create mode 100644 tests/Makefile.am create mode 100644 tests/add.c create mode 100644 tests/add.ok create mode 100644 tests/fib.c create mode 100644 tests/fib.ok create mode 100644 tests/fibdelay.c create mode 100644 tests/fibdelay.ok create mode 100644 tests/fibit.c create mode 100644 tests/fibit.ok create mode 100644 tests/funcfp.c create mode 100644 tests/funcfp.ok create mode 100644 tests/incr.c create mode 100644 tests/incr.ok create mode 100644 tests/printf.c create mode 100644 tests/printf.ok create mode 100644 tests/printf2.c create mode 100644 tests/printf2.ok create mode 100644 tests/rpn.c create mode 100644 tests/rpn.ok create mode 100644 tests/rpnfp.c create mode 100644 tests/rpnfp.ok create mode 100755 tests/run-test create mode 100644 tests/testfp.c create mode 100644 tests/testfp.ok diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 000000000..d19bf6b35 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,2 @@ +Paolo Bonzini +i386 and PPC assemblers by Ian Piumarta \ No newline at end of file diff --git a/COPYING b/COPYING new file mode 100644 index 000000000..d60c31a97 --- /dev/null +++ b/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/COPYING.DOC b/COPYING.DOC new file mode 100644 index 000000000..b42936beb --- /dev/null +++ b/COPYING.DOC @@ -0,0 +1,355 @@ + GNU Free Documentation License + Version 1.1, March 2000 + + Copyright (C) 2000 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + +0. PREAMBLE + +The purpose of this License is to make a manual, textbook, or other +written document "free" in the sense of freedom: to assure everyone +the effective freedom to copy and redistribute it, with or without +modifying it, either commercially or noncommercially. Secondarily, +this License preserves for the author and publisher a way to get +credit for their work, while not being considered responsible for +modifications made by others. + +This License is a kind of "copyleft", which means that derivative +works of the document must themselves be free in the same sense. It +complements the GNU General Public License, which is a copyleft +license designed for free software. + +We have designed this License in order to use it for manuals for free +software, because free software needs free documentation: a free +program should come with manuals providing the same freedoms that the +software does. But this License is not limited to software manuals; +it can be used for any textual work, regardless of subject matter or +whether it is published as a printed book. We recommend this License +principally for works whose purpose is instruction or reference. + + +1. APPLICABILITY AND DEFINITIONS + +This License applies to any manual or other work that contains a +notice placed by the copyright holder saying it can be distributed +under the terms of this License. The "Document", below, refers to any +such manual or work. Any member of the public is a licensee, and is +addressed as "you". + +A "Modified Version" of the Document means any work containing the +Document or a portion of it, either copied verbatim, or with +modifications and/or translated into another language. + +A "Secondary Section" is a named appendix or a front-matter section of +the Document that deals exclusively with the relationship of the +publishers or authors of the Document to the Document's overall subject +(or to related matters) and contains nothing that could fall directly +within that overall subject. (For example, if the Document is in part a +textbook of mathematics, a Secondary Section may not explain any +mathematics.) The relationship could be a matter of historical +connection with the subject or with related matters, or of legal, +commercial, philosophical, ethical or political position regarding +them. + +The "Invariant Sections" are certain Secondary Sections whose titles +are designated, as being those of Invariant Sections, in the notice +that says that the Document is released under this License. + +The "Cover Texts" are certain short passages of text that are listed, +as Front-Cover Texts or Back-Cover Texts, in the notice that says that +the Document is released under this License. + +A "Transparent" copy of the Document means a machine-readable copy, +represented in a format whose specification is available to the +general public, whose contents can be viewed and edited directly and +straightforwardly with generic text editors or (for images composed of +pixels) generic paint programs or (for drawings) some widely available +drawing editor, and that is suitable for input to text formatters or +for automatic translation to a variety of formats suitable for input +to text formatters. A copy made in an otherwise Transparent file +format whose markup has been designed to thwart or discourage +subsequent modification by readers is not Transparent. A copy that is +not "Transparent" is called "Opaque". + +Examples of suitable formats for Transparent copies include plain +ASCII without markup, Texinfo input format, LaTeX input format, SGML +or XML using a publicly available DTD, and standard-conforming simple +HTML designed for human modification. Opaque formats include +PostScript, PDF, proprietary formats that can be read and edited only +by proprietary word processors, SGML or XML for which the DTD and/or +processing tools are not generally available, and the +machine-generated HTML produced by some word processors for output +purposes only. + +The "Title Page" means, for a printed book, the title page itself, +plus such following pages as are needed to hold, legibly, the material +this License requires to appear in the title page. For works in +formats which do not have any title page as such, "Title Page" means +the text near the most prominent appearance of the work's title, +preceding the beginning of the body of the text. + + +2. VERBATIM COPYING + +You may copy and distribute the Document in any medium, either +commercially or noncommercially, provided that this License, the +copyright notices, and the license notice saying this License applies +to the Document are reproduced in all copies, and that you add no other +conditions whatsoever to those of this License. You may not use +technical measures to obstruct or control the reading or further +copying of the copies you make or distribute. However, you may accept +compensation in exchange for copies. If you distribute a large enough +number of copies you must also follow the conditions in section 3. + +You may also lend copies, under the same conditions stated above, and +you may publicly display copies. + + +3. COPYING IN QUANTITY + +If you publish printed copies of the Document numbering more than 100, +and the Document's license notice requires Cover Texts, you must enclose +the copies in covers that carry, clearly and legibly, all these Cover +Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on +the back cover. Both covers must also clearly and legibly identify +you as the publisher of these copies. The front cover must present +the full title with all words of the title equally prominent and +visible. You may add other material on the covers in addition. +Copying with changes limited to the covers, as long as they preserve +the title of the Document and satisfy these conditions, can be treated +as verbatim copying in other respects. + +If the required texts for either cover are too voluminous to fit +legibly, you should put the first ones listed (as many as fit +reasonably) on the actual cover, and continue the rest onto adjacent +pages. + +If you publish or distribute Opaque copies of the Document numbering +more than 100, you must either include a machine-readable Transparent +copy along with each Opaque copy, or state in or with each Opaque copy +a publicly-accessible computer-network location containing a complete +Transparent copy of the Document, free of added material, which the +general network-using public has access to download anonymously at no +charge using public-standard network protocols. If you use the latter +option, you must take reasonably prudent steps, when you begin +distribution of Opaque copies in quantity, to ensure that this +Transparent copy will remain thus accessible at the stated location +until at least one year after the last time you distribute an Opaque +copy (directly or through your agents or retailers) of that edition to +the public. + +It is requested, but not required, that you contact the authors of the +Document well before redistributing any large number of copies, to give +them a chance to provide you with an updated version of the Document. + + +4. MODIFICATIONS + +You may copy and distribute a Modified Version of the Document under +the conditions of sections 2 and 3 above, provided that you release +the Modified Version under precisely this License, with the Modified +Version filling the role of the Document, thus licensing distribution +and modification of the Modified Version to whoever possesses a copy +of it. In addition, you must do these things in the Modified Version: + +A. Use in the Title Page (and on the covers, if any) a title distinct + from that of the Document, and from those of previous versions + (which should, if there were any, be listed in the History section + of the Document). You may use the same title as a previous version + if the original publisher of that version gives permission. +B. List on the Title Page, as authors, one or more persons or entities + responsible for authorship of the modifications in the Modified + Version, together with at least five of the principal authors of the + Document (all of its principal authors, if it has less than five). +C. State on the Title page the name of the publisher of the + Modified Version, as the publisher. +D. Preserve all the copyright notices of the Document. +E. Add an appropriate copyright notice for your modifications + adjacent to the other copyright notices. +F. Include, immediately after the copyright notices, a license notice + giving the public permission to use the Modified Version under the + terms of this License, in the form shown in the Addendum below. +G. Preserve in that license notice the full lists of Invariant Sections + and required Cover Texts given in the Document's license notice. +H. Include an unaltered copy of this License. +I. Preserve the section entitled "History", and its title, and add to + it an item stating at least the title, year, new authors, and + publisher of the Modified Version as given on the Title Page. If + there is no section entitled "History" in the Document, create one + stating the title, year, authors, and publisher of the Document as + given on its Title Page, then add an item describing the Modified + Version as stated in the previous sentence. +J. Preserve the network location, if any, given in the Document for + public access to a Transparent copy of the Document, and likewise + the network locations given in the Document for previous versions + it was based on. These may be placed in the "History" section. + You may omit a network location for a work that was published at + least four years before the Document itself, or if the original + publisher of the version it refers to gives permission. +K. In any section entitled "Acknowledgements" or "Dedications", + preserve the section's title, and preserve in the section all the + substance and tone of each of the contributor acknowledgements + and/or dedications given therein. +L. Preserve all the Invariant Sections of the Document, + unaltered in their text and in their titles. Section numbers + or the equivalent are not considered part of the section titles. +M. Delete any section entitled "Endorsements". Such a section + may not be included in the Modified Version. +N. Do not retitle any existing section as "Endorsements" + or to conflict in title with any Invariant Section. + +If the Modified Version includes new front-matter sections or +appendices that qualify as Secondary Sections and contain no material +copied from the Document, you may at your option designate some or all +of these sections as invariant. To do this, add their titles to the +list of Invariant Sections in the Modified Version's license notice. +These titles must be distinct from any other section titles. + +You may add a section entitled "Endorsements", provided it contains +nothing but endorsements of your Modified Version by various +parties--for example, statements of peer review or that the text has +been approved by an organization as the authoritative definition of a +standard. + +You may add a passage of up to five words as a Front-Cover Text, and a +passage of up to 25 words as a Back-Cover Text, to the end of the list +of Cover Texts in the Modified Version. Only one passage of +Front-Cover Text and one of Back-Cover Text may be added by (or +through arrangements made by) any one entity. If the Document already +includes a cover text for the same cover, previously added by you or +by arrangement made by the same entity you are acting on behalf of, +you may not add another; but you may replace the old one, on explicit +permission from the previous publisher that added the old one. + +The author(s) and publisher(s) of the Document do not by this License +give permission to use their names for publicity for or to assert or +imply endorsement of any Modified Version. + + +5. COMBINING DOCUMENTS + +You may combine the Document with other documents released under this +License, under the terms defined in section 4 above for modified +versions, provided that you include in the combination all of the +Invariant Sections of all of the original documents, unmodified, and +list them all as Invariant Sections of your combined work in its +license notice. + +The combined work need only contain one copy of this License, and +multiple identical Invariant Sections may be replaced with a single +copy. If there are multiple Invariant Sections with the same name but +different contents, make the title of each such section unique by +adding at the end of it, in parentheses, the name of the original +author or publisher of that section if known, or else a unique number. +Make the same adjustment to the section titles in the list of +Invariant Sections in the license notice of the combined work. + +In the combination, you must combine any sections entitled "History" +in the various original documents, forming one section entitled +"History"; likewise combine any sections entitled "Acknowledgements", +and any sections entitled "Dedications". You must delete all sections +entitled "Endorsements." + + +6. COLLECTIONS OF DOCUMENTS + +You may make a collection consisting of the Document and other documents +released under this License, and replace the individual copies of this +License in the various documents with a single copy that is included in +the collection, provided that you follow the rules of this License for +verbatim copying of each of the documents in all other respects. + +You may extract a single document from such a collection, and distribute +it individually under this License, provided you insert a copy of this +License into the extracted document, and follow this License in all +other respects regarding verbatim copying of that document. + + +7. AGGREGATION WITH INDEPENDENT WORKS + +A compilation of the Document or its derivatives with other separate +and independent documents or works, in or on a volume of a storage or +distribution medium, does not as a whole count as a Modified Version +of the Document, provided no compilation copyright is claimed for the +compilation. Such a compilation is called an "aggregate", and this +License does not apply to the other self-contained works thus compiled +with the Document, on account of their being thus compiled, if they +are not themselves derivative works of the Document. + +If the Cover Text requirement of section 3 is applicable to these +copies of the Document, then if the Document is less than one quarter +of the entire aggregate, the Document's Cover Texts may be placed on +covers that surround only the Document within the aggregate. +Otherwise they must appear on covers around the whole aggregate. + + +8. TRANSLATION + +Translation is considered a kind of modification, so you may +distribute translations of the Document under the terms of section 4. +Replacing Invariant Sections with translations requires special +permission from their copyright holders, but you may include +translations of some or all Invariant Sections in addition to the +original versions of these Invariant Sections. You may include a +translation of this License provided that you also include the +original English version of this License. In case of a disagreement +between the translation and the original English version of this +License, the original English version will prevail. + + +9. TERMINATION + +You may not copy, modify, sublicense, or distribute the Document except +as expressly provided for under this License. Any other attempt to +copy, modify, sublicense or distribute the Document 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. + + +10. FUTURE REVISIONS OF THIS LICENSE + +The Free Software Foundation may publish new, revised versions +of the GNU Free Documentation 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. See +http://www.gnu.org/copyleft/. + +Each version of the License is given a distinguishing version number. +If the Document specifies that a particular numbered version of this +License "or any later version" applies to it, you have the option of +following the terms and conditions either of that specified version or +of any later version that has been published (not as a draft) by the +Free Software Foundation. If the Document does not specify a version +number of this License, you may choose any version ever published (not +as a draft) by the Free Software Foundation. + + +ADDENDUM: How to use this License for your documents + +To use this License in a document you have written, include a copy of +the License in the document and put the following copyright and +license notices just after the title page: + + Copyright (c) YEAR YOUR NAME. + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.1 + or any later version published by the Free Software Foundation; + with the Invariant Sections being LIST THEIR TITLES, with the + Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. + A copy of the license is included in the section entitled "GNU + Free Documentation License". + +If you have no Invariant Sections, write "with no Invariant Sections" +instead of saying which ones are invariant. If you have no +Front-Cover Texts, write "no Front-Cover Texts" instead of +"Front-Cover Texts being LIST"; likewise for Back-Cover Texts. + +If your document contains nontrivial examples of program code, we +recommend releasing these examples in parallel under your choice of +free software license, such as the GNU General Public License, +to permit their use in free software. diff --git a/COPYING.LESSER b/COPYING.LESSER new file mode 100644 index 000000000..18662c20c --- /dev/null +++ b/COPYING.LESSER @@ -0,0 +1,503 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + 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 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 000000000..5fbd089d6 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,75 @@ +2004-03-02 Paolo Bonzini + + * lightning/i386/core.h: generate correct code when + doing lt/le/ge/etc. on ESI and EDI. Use MOVZX/MOVSX + where possible. + * lightning/i386/asm.h: Add macros for MOVZX/MOVSX. + Move macros for x87 here, and add many of them. + * lightning/i386/fp.h: Use new macros for x87. + +2004-02-06 Paolo Bonzini + + * lightning/i386/core.h: avoid generating MOV reg, reg. + * lightning/sparc/core.h: fix several bugs. + * lightning/ppc/core.h: fix several bugs. + * tests/rpn.c: rewritten. + +2004-01-08 Paolo Bonzini + + * tests/rpnfp.c: new example, suggested by Basile + Starynkevitch. + * tests/rpnfp.ok: new example. + +2003-12-12 Paolo Bonzini + + * tests/add.c: new test, suggested by Steve Dekorte. + * tests/add.c: new test. + +2003-11-14 Paolo Bonzini + John Redford + + * lightning/asm-common.h: change the 'pc' field of _jit to + be a union of various data types, because ISO C99 doesn't + permit using ++ on a = cast. Change the incremented casts of + _jit.pc to be _jit.x.uc_pc, _jit.x.us_pc, etc. + * all files: change all non-cast instances of _jit.pc to be + _jit.x.pc. + * lightning/i386/core.h: remove casts from jit_might. + +2003-05-25 Paolo Bonzini + + * lightning/i386/core.h: use JITSORRY in jit_replace + * lightning/asm-common.h: define JITSORRY + +2003-05-14 Paolo Bonzini + + * lightning/i386/core.h: fix missing comma in several + load/store macros. + * lightning/core-common.h: fix long/unsigned long/pointer + jit_pushr/jit_popr. + * lightning/ppc/funcs.h: correctly align stack pointer + +No changelogs for the assemblers (lightning directory) until 1.0 + +2003-03-27 Paolo Bonzini + + * tests/printf2.c: new test + +2001-05-03 Paolo Bonzini + + * tests/printf.c: made the message platform independent + +2001-01-19 Paolo Bonzini + + * configure.in: support cross-assembling + + * disass/bfd.h, disass/dis-asm.h, disass/dis-buf.c, + disass/i386-dis.c, disass/i386.h, disass/ppc-dis.c, + disass/ppc.h, disass/ppc-opc.c, disass/sparc-dis.c, + disass/sparc.h, disass/sparc-opc.c: new files, from GDB + + * disass/disass.c, disass/Makefile.am: new files + + * tests/fib.c, tests/fibit.c, tests/incr.c, tests/printf.c, + tests/rpn.c, tests/testfp.c, tests/Makefile.am: support + disassembling diff --git a/INSTALL b/INSTALL new file mode 100644 index 000000000..54caf7c19 --- /dev/null +++ b/INSTALL @@ -0,0 +1,229 @@ +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software +Foundation, Inc. + + This file is free documentation; the Free Software Foundation gives +unlimited permission to copy, distribute and modify it. + +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. (Caching is +disabled by default to prevent problems with accidental use of stale +cache files.) + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You only need +`configure.ac' if you want to change it or regenerate `configure' using +a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. Run `./configure --help' +for details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not support the `VPATH' +variable, you have to compile the package for one architecture at a +time in the source code directory. After you have installed the +package for one architecture, use `make distclean' before reconfiguring +for another architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' cannot figure out +automatically, but needs to determine by the type of machine the package +will run on. Usually, assuming the package is built to be run on the +_same_ architectures, `configure' can figure that out, but if it prints +a message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the `--target=TYPE' option to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + + Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +will cause the specified gcc to be used as the C compiler (unless it is +overridden in the site shell script). + +`configure' Invocation +====================== + + `configure' recognizes the following options to control how it +operates. + +`--help' +`-h' + Print a summary of the options to `configure', and exit. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 000000000..5077ec19d --- /dev/null +++ b/Makefile.am @@ -0,0 +1,19 @@ +# Automake requirements: +AUTOMAKE_OPTIONS = 1.7 gnu + +SUBDIRS = . doc lightning opcode tests +EXTRA_DIST = config/texi2dvi config/help2man + +dist_noinst_HEADERS = lightning-inst.h +nodist_noinst_HEADERS = lightning.h + +uninstall-local: + -rm -f $(DESTDIR)$(includedir)/lightning.h + +install-data-local: + $(mkinstalldirs) $(DESTDIR)$(includedir) + $(INSTALL_DATA) $(srcdir)/lightning-inst.h $(DESTDIR)$(includedir)/lightning.h + +aclocaldir = $(datadir)/aclocal +dist_aclocal_DATA = lightning.m4 +bin_SCRIPTS = lightningize diff --git a/NEWS b/NEWS new file mode 100644 index 000000000..bae18f34f --- /dev/null +++ b/NEWS @@ -0,0 +1,124 @@ +NEWS FROM VERSION 1.1.2 TO 1.2 + +o Floating-point interface rewritten, uses a common register + file architecture rather than a stack. + +o Many bug fixes. + +o More (and more complete) examples provided. + +--- + +NEWS FROM VERSION 1.1.1 TO 1.1.2 + +o This release fixes the bugs in PowerPC cache flushing and in + SPARC testing. + +--- + +NEWS FROM VERSION 1.1 TO 1.1.1 + +o Merge changes from Debian + +This version was released to have a distributable version of lightning +after the recent crack of the GNU FTP machines. It does not fix +outstanding bugs; I apologize for the inconvenience. + +--- + +NEWS FROM VERSION 1.0 TO 1.1 + +o Several bug fixes + +o improved infrastructure for embedding GNU lightning (lightningize + script) + +--- + +NEWS FROM VERSION 0.99 TO 1.0 + +o SPARC backend tested on GNU Smalltalk + + +--- + +NEWS FROM VERSION 0.98 TO 0.99 + +o Added floating point function support (thanks to Laurent Michel); + unfortunately this broke even more the PPC and SPARC floating point + stuff :-( + +--- + +NEWS FROM VERSION 0.97 to 0.98 + +o PPC backend tested on GNU Smalltalk + +o switched to autoconf 2.50 + +o new (much faster) PPC cache flushing code by John McIntosh + +--- + +NEWS FROM VERSION 0.96 to 0.97 + +o support for cross-assembling and for disassembling the code that the tests + generate + +o PPC microtests pass (tested directly by me), SPARC was said to work + +--- + +NEWS FROM VERSION 0.95 to 0.96 + +o fixed implementation of delay slots to be coherent with the manual + +--- + +NEWS FROM VERSION 0.94 to 0.95 + +o adc/sbc replaced with addc/addx/subc/subx to allow for more optimization + (inspired by the PPC instruction set). + +o A few fixes and much less warnings from the compiler + +o Automake-ized everything + +o i386 backend generates smaller code for bms/bmc/or/xor by using byte + or word versions if possible + +o Moved backends to separate directories + +--- + +NEWS FROM VERSION 0.93 to 0.94 + +o Manual builds as DVI file. + +--- + +NEWS FROM VERSION 0.92 to 0.93 + +o Floating-point front-end (began supporting PPC & SPARC). + +--- + +NEWS FROM VERSION 0.91 to 0.92 + +o Floating-point front-end (only x86 supported). + +--- + +NEWS FROM VERSION 0.9 to 0.91 + +o Carrying supported in addition/subtraction. + +o insn type changed to jit_insn. + +o Misc bug fixes. + +o Reentrancy supported. + +o SPARC run-time assembler rewritten. + +o The run-time assembler can be disabled for debugging purposes. diff --git a/README b/README new file mode 100644 index 000000000..ae36ea578 --- /dev/null +++ b/README @@ -0,0 +1,3 @@ +GNU lightning is a library to aid in making portable programs +that compile assembly code at run time. For more information, +look at the info documentation. diff --git a/config/help2man b/config/help2man new file mode 100755 index 000000000..5d4377b6f --- /dev/null +++ b/config/help2man @@ -0,0 +1,559 @@ +#!/usr/bin/env perl + +# Generate a short man page from --help and --version output. +# Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Free Software +# Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Written by Brendan O'Dea +# Available from ftp://ftp.gnu.org/gnu/help2man/ + +use 5.005; +use strict; +use Getopt::Long; +use Text::Tabs qw(expand); +use POSIX qw(strftime setlocale LC_TIME); + +my $this_program = 'help2man'; +my $this_version = '1.28'; +my $version_info = < +EOT + +my $help_info = <. +EOT + +my $section = 1; +my $manual = ''; +my $source = ''; +my $help_option = '--help'; +my $version_option = '--version'; +my ($opt_name, @opt_include, $opt_output, $opt_info, $opt_no_info); + +my %opt_def = ( + 'n|name=s' => \$opt_name, + 's|section=s' => \$section, + 'm|manual=s' => \$manual, + 'S|source=s' => \$source, + 'i|include=s' => sub { push @opt_include, [ pop, 1 ] }, + 'I|opt-include=s' => sub { push @opt_include, [ pop, 0 ] }, + 'o|output=s' => \$opt_output, + 'p|info-page=s' => \$opt_info, + 'N|no-info' => \$opt_no_info, + 'h|help-option=s' => \$help_option, + 'v|version-option=s' => \$version_option, +); + +# Parse options. +Getopt::Long::config('bundling'); +GetOptions (%opt_def, + help => sub { print $help_info; exit }, + version => sub { print $version_info; exit }, +) or die $help_info; + +die $help_info unless @ARGV == 1; + +my %include = (); +my %append = (); +my @include = (); # retain order given in include file + +# Process include file (if given). Format is: +# +# [section name] +# verbatim text +# +# or +# +# /pattern/ +# verbatim text +# + +while (@opt_include) +{ + my ($inc, $required) = @{shift @opt_include}; + + next unless -f $inc or $required; + die "$this_program: can't open `$inc' ($!)\n" + unless open INC, $inc; + + my $key; + my $hash = \%include; + + while () + { + # [section] + if (/^\[([^]]+)\]/) + { + $key = uc $1; + $key =~ s/^\s+//; + $key =~ s/\s+$//; + $hash = \%include; + push @include, $key unless $include{$key}; + next; + } + + # /pattern/ + if (m!^/(.*)/([ims]*)!) + { + my $pat = $2 ? "(?$2)$1" : $1; + + # Check pattern. + eval { $key = qr($pat) }; + if ($@) + { + $@ =~ s/ at .*? line \d.*//; + die "$inc:$.:$@"; + } + + $hash = \%append; + next; + } + + # Check for options before the first section--anything else is + # silently ignored, allowing the first for comments and + # revision info. + unless ($key) + { + # handle options + if (/^-/) + { + local @ARGV = split; + GetOptions %opt_def; + } + + next; + } + + $hash->{$key} ||= ''; + $hash->{$key} .= $_; + } + + close INC; + + die "$this_program: no valid information found in `$inc'\n" + unless $key; +} + +# Compress trailing blank lines. +for my $hash (\(%include, %append)) +{ + for (keys %$hash) { $hash->{$_} =~ s/\n+$/\n/ } +} + +# Turn off localisation of executable's ouput. +@ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3; + +# Turn off localisation of date (for strftime). +setlocale LC_TIME, 'C'; + +# Grab help and version info from executable. +my ($help_text, $version_text) = map { + join '', map { s/ +$//; expand $_ } `$ARGV[0] $_ 2>/dev/null` + or die "$this_program: can't get `$_' info from $ARGV[0]\n" +} $help_option, $version_option; + +my $date = strftime "%B %Y", localtime; +(my $program = $ARGV[0]) =~ s!.*/!!; +my $package = $program; +my $version; + +if ($opt_output) +{ + unlink $opt_output + or die "$this_program: can't unlink $opt_output ($!)\n" + if -e $opt_output; + + open STDOUT, ">$opt_output" + or die "$this_program: can't create $opt_output ($!)\n"; +} + +# The first line of the --version information is assumed to be in one +# of the following formats: +# +# +# +# {GNU,Free} +# ({GNU,Free} ) +# - {GNU,Free} +# +# and seperated from any copyright/author details by a blank line. + +($_, $version_text) = split /\n+/, $version_text, 2; + +if (/^(\S+) +\(((?:GNU|Free) +[^)]+)\) +(.*)/ or + /^(\S+) +- *((?:GNU|Free) +\S+) +(.*)/) +{ + $program = $1; + $package = $2; + $version = $3; +} +elsif (/^((?:GNU|Free) +)?(\S+) +(.*)/) +{ + $program = $2; + $package = $1 ? "$1$2" : $2; + $version = $3; +} +else +{ + $version = $_; +} + +$program =~ s!.*/!!; + +# No info for `info' itself. +$opt_no_info = 1 if $program eq 'info'; + +# --name overrides --include contents. +$include{NAME} = "$program \\- $opt_name\n" if $opt_name; + +# Default (useless) NAME paragraph. +$include{NAME} ||= "$program \\- manual page for $program $version\n"; + +# Man pages traditionally have the page title in caps. +my $PROGRAM = uc $program; + +# Set default page head/footers +$source ||= "$program $version"; +unless ($manual) +{ + for ($section) + { + if (/^(1[Mm]|8)/) { $manual = 'System Administration Utilities' } + elsif (/^6/) { $manual = 'Games' } + else { $manual = 'User Commands' } + } +} + +# Extract usage clause(s) [if any] for SYNOPSIS. +if ($help_text =~ s/^Usage:( +(\S+))(.*)((?:\n(?: {6}\1| *or: +\S).*)*)//m) +{ + my @syn = $2 . $3; + + if ($_ = $4) + { + s/^\n//; + for (split /\n/) { s/^ *(or: +)?//; push @syn, $_ } + } + + my $synopsis = ''; + for (@syn) + { + $synopsis .= ".br\n" if $synopsis; + s!^\S*/!!; + s/^(\S+) *//; + $synopsis .= ".B $1\n"; + s/\s+$//; + s/(([][]|\.\.+)+)/\\fR$1\\fI/g; + s/^/\\fI/ unless s/^\\fR//; + $_ .= '\fR'; + s/(\\fI)( *)/$2$1/g; + s/\\fI\\fR//g; + s/^\\fR//; + s/\\fI$//; + s/^\./\\&./; + + $synopsis .= "$_\n"; + } + + $include{SYNOPSIS} ||= $synopsis; +} + +# Process text, initial section is DESCRIPTION. +my $sect = 'DESCRIPTION'; +$_ = "$help_text\n\n$version_text"; + +# Normalise paragraph breaks. +s/^\n+//; +s/\n*$/\n/; +s/\n\n+/\n\n/g; + +# Temporarily exchange leading dots, apostrophes and backslashes for +# tokens. +s/^\./\x80/mg; +s/^'/\x81/mg; +s/\\/\x82/g; + +# Start a new paragraph (if required) for these. +s/([^\n])\n(Report +bugs|Email +bug +reports +to|Written +by)/$1\n\n$2/g; + +sub convert_option; + +while (length) +{ + # Convert some standard paragraph names. + if (s/^(Options|Examples): *\n//) + { + $sect = uc $1; + next; + } + + # Copyright section + if (/^Copyright +[(\xa9]/) + { + $sect = 'COPYRIGHT'; + $include{$sect} ||= ''; + $include{$sect} .= ".PP\n" if $include{$sect}; + + my $copy; + ($copy, $_) = split /\n\n/, $_, 2; + + for ($copy) + { + # Add back newline + s/\n*$/\n/; + + # Convert iso9959-1 copyright symbol or (c) to nroff + # character. + s/^Copyright +(?:\xa9|\([Cc]\))/Copyright \\(co/mg; + + # Insert line breaks before additional copyright messages + # and the disclaimer. + s/(.)\n(Copyright |This +is +free +software)/$1\n.br\n$2/g; + + # Join hyphenated lines. + s/([A-Za-z])-\n */$1/g; + } + + $include{$sect} .= $copy; + $_ ||= ''; + next; + } + + # Catch bug report text. + if (/^(Report +bugs|Email +bug +reports +to) /) + { + $sect = 'REPORTING BUGS'; + } + + # Author section. + elsif (/^Written +by/) + { + $sect = 'AUTHOR'; + } + + # Examples, indicated by an indented leading $, % or > are + # rendered in a constant width font. + if (/^( +)([\$\%>] )\S/) + { + my $indent = $1; + my $prefix = $2; + my $break = '.IP'; + $include{$sect} ||= ''; + while (s/^$indent\Q$prefix\E(\S.*)\n*//) + { + $include{$sect} .= "$break\n\\f(CW$prefix$1\\fR\n"; + $break = '.br'; + } + + next; + } + + my $matched = ''; + $include{$sect} ||= ''; + + # Sub-sections have a trailing colon and the second line indented. + if (s/^(\S.*:) *\n / /) + { + $matched .= $& if %append; + $include{$sect} .= qq(.SS "$1"\n); + } + + my $indent = 0; + my $content = ''; + + # Option with description. + if (s/^( {1,10}([+-]\S.*?))(?:( +(?!-))|\n( {20,}))(\S.*)\n//) + { + $matched .= $& if %append; + $indent = length ($4 || "$1$3"); + $content = ".TP\n\x83$2\n\x83$5\n"; + unless ($4) + { + # Indent may be different on second line. + $indent = length $& if /^ {20,}/; + } + } + + # Option without description. + elsif (s/^ {1,10}([+-]\S.*)\n//) + { + $matched .= $& if %append; + $content = ".HP\n\x83$1\n"; + $indent = 80; # not continued + } + + # Indented paragraph with tag. + elsif (s/^( +(\S.*?) +)(\S.*)\n//) + { + $matched .= $& if %append; + $indent = length $1; + $content = ".TP\n\x83$2\n\x83$3\n"; + } + + # Indented paragraph. + elsif (s/^( +)(\S.*)\n//) + { + $matched .= $& if %append; + $indent = length $1; + $content = ".IP\n\x83$2\n"; + } + + # Left justified paragraph. + else + { + s/(.*)\n//; + $matched .= $& if %append; + $content = ".PP\n" if $include{$sect}; + $content .= "$1\n"; + } + + # Append continuations. + while (s/^ {$indent}(\S.*)\n//) + { + $matched .= $& if %append; + $content .= "\x83$1\n" + } + + # Move to next paragraph. + s/^\n+//; + + for ($content) + { + # Leading dot and apostrophe protection. + s/\x83\./\x80/g; + s/\x83'/\x81/g; + s/\x83//g; + + # Convert options. + s/(^| )(-[][\w=-]+)/$1 . convert_option $2/mge; + } + + # Check if matched paragraph contains /pat/. + if (%append) + { + for my $pat (keys %append) + { + if ($matched =~ $pat) + { + $content .= ".PP\n" unless $append{$pat} =~ /^\./; + $content .= $append{$pat}; + } + } + } + + $include{$sect} .= $content; +} + +# Refer to the real documentation. +unless ($opt_no_info) +{ + my $info_page = $opt_info || $program; + + $sect = 'SEE ALSO'; + $include{$sect} ||= ''; + $include{$sect} .= ".PP\n" if $include{$sect}; + $include{$sect} .= <. +# +# Please send bug reports, etc. to bug-texinfo@gnu.org. +# If possible, please send a copy of the output of the script called with +# the `--debug' option when making a bug report. + +# This string is expanded by rcs automatically when this file is checked out. +rcs_revision='$Revision: 1.14 $' +rcs_version=`set - $rcs_revision; echo $2` +program=`echo $0 | sed -e 's!.*/!!'` +version="texi2dvi (GNU Texinfo 4.5) $rcs_version + +Copyright (C) 2003 Free Software Foundation, Inc. +There is NO warranty. You may redistribute this software +under the terms of the GNU General Public License. +For more information about these matters, see the files named COPYING." + +usage="Usage: $program [OPTION]... FILE... + +Run each Texinfo or LaTeX FILE through TeX in turn until all +cross-references are resolved, building all indices. The directory +containing each FILE is searched for included files. The suffix of FILE +is used to determine its language (LaTeX or Texinfo). + +Makeinfo is used to perform Texinfo macro expansion before running TeX +when needed. + +Operation modes: + -b, --batch no interaction + -c, --clean remove all auxiliary files + -D, --debug turn on shell debugging (set -x) + -h, --help display this help and exit successfully + -o, --output=OFILE leave output in OFILE (implies --clean); + Only one input FILE may be specified in this case + -q, --quiet no output unless errors (implies --batch) + -s, --silent same as --quiet + -v, --version display version information and exit successfully + -V, --verbose report on what is done + +TeX tuning: + -@ use @input instead of \input; for preloaded Texinfo + -e, -E, --expand force macro expansion using makeinfo + -I DIR search DIR for Texinfo files + -l, --language=LANG specify the LANG of FILE (LaTeX or Texinfo) + -p, --pdf use pdftex or pdflatex for processing + -t, --texinfo=CMD insert CMD after @setfilename in copy of input file + multiple values accumulate + +The values of the BIBTEX, LATEX (or PDFLATEX), MAKEINDEX, MAKEINFO, +TEX (or PDFTEX), and TEXINDEX environment variables are used to run +those commands, if they are set. + +Email bug reports to , +general questions and discussion to . +Texinfo home page: http://www.gnu.org/software/texinfo/" + +# Initialize variables for option overriding and otherwise. +# Don't use `unset' since old bourne shells don't have this command. +# Instead, assign them an empty value. +batch=false # eval for batch mode +clean= +debug= +escape='\' +expand= # t for expansion via makeinfo +miincludes= # makeinfo include path +oformat=dvi +oname= # --output +quiet= # by default let the tools' message be displayed +set_language= +textra= +tmpdir=${TMPDIR:-/tmp}/t2d$$ # avoid collisions on 8.3 filesystems. +txincludes= # TEXINPUTS extensions, with trailing colon +txiprereq=19990129 # minimum texinfo.tex version to have macro expansion +verbose=false # echo for verbose mode + +orig_pwd=`pwd` + +# Systems which define $COMSPEC or $ComSpec use semicolons to separate +# directories in TEXINPUTS. +if test -n "$COMSPEC$ComSpec"; then + path_sep=";" +else + path_sep=":" +fi + +# Pacify verbose cds. +CDPATH=${ZSH_VERSION+.}$path_sep + +# In case someone crazy insists on using grep -E. +: ${EGREP=egrep} + +# Save this so we can construct a new TEXINPUTS path for each file. +TEXINPUTS_orig="$TEXINPUTS" +# Unfortunately makeindex does not read TEXINPUTS. +INDEXSTYLE_orig="$INDEXSTYLE" +export TEXINPUTS INDEXSTYLE + +# Push a token among the arguments that will be used to notice when we +# ended options/arguments parsing. +# Use "set dummy ...; shift" rather than 'set - ..." because on +# Solaris set - turns off set -x (but keeps set -e). +# Use ${1+"$@"} rather than "$@" because Digital Unix and Ultrix 4.3 +# still expand "$@" to a single argument (the empty string) rather +# than nothing at all. +arg_sep="$$--$$" +set dummy ${1+"$@"} "$arg_sep"; shift + +# +# Parse command line arguments. +while test x"$1" != x"$arg_sep"; do + + # Handle --option=value by splitting apart and putting back on argv. + case "$1" in + --*=*) + opt=`echo "$1" | sed -e 's/=.*//'` + val=`echo "$1" | sed -e 's/[^=]*=//'` + shift + set dummy "$opt" "$val" ${1+"$@"}; shift + ;; + esac + + # This recognizes --quark as --quiet. So what. + case "$1" in + -@ ) escape=@;; + # Silently and without documentation accept -b and --b[atch] as synonyms. + -b | --b*) batch=eval;; + -q | -s | --q* | --s*) quiet=t; batch=eval;; + -c | --c*) clean=t;; + -D | --d*) debug=t;; + -e | -E | --e*) expand=t;; + -h | --h*) echo "$usage"; exit 0;; + -I | --I*) + shift + miincludes="$miincludes -I $1" + txincludes="$txincludes$1$path_sep" + ;; + -l | --l*) shift; set_language=$1;; + -o | --o*) + shift + clean=t + case "$1" in + /* | ?:/*) oname=$1;; + *) oname="$orig_pwd/$1";; + esac;; + -p | --p*) oformat=pdf;; + -t | --t*) shift; textra="$textra\\ +$1";; + -v | --vers*) echo "$version"; exit 0;; + -V | --verb*) verbose=echo;; + --) # What remains are not options. + shift + while test x"$1" != x"$arg_sep"; do + set dummy ${1+"$@"} "$1"; shift + shift + done + break;; + -*) + echo "$0: Unknown or ambiguous option \`$1'." >&2 + echo "$0: Try \`--help' for more information." >&2 + exit 1;; + *) set dummy ${1+"$@"} "$1"; shift;; + esac + shift +done +# Pop the token +shift + +# Interpret remaining command line args as filenames. +case $# in + 0) + echo "$0: Missing file arguments." >&2 + echo "$0: Try \`--help' for more information." >&2 + exit 2 + ;; + 1) ;; + *) + if test -n "$oname"; then + echo "$0: Can't use option \`--output' with more than one argument." >&2 + exit 2 + fi + ;; +esac + +# Prepare the temporary directory. Remove it at exit, unless debugging. +if test -z "$debug"; then + trap "cd / && rm -rf $tmpdir" 0 1 2 15 +fi + +# Create the temporary directory with strict rights +(umask 077 && mkdir $tmpdir) || exit 1 + +# Prepare the tools we might need. This may be extra work in some +# cases, but improves the readibility of the script. +utildir=$tmpdir/utils +mkdir $utildir || exit 1 + +# A sed script that preprocesses Texinfo sources in order to keep the +# iftex sections only. We want to remove non TeX sections, and +# comment (with `@c texi2dvi') TeX sections so that makeinfo does not +# try to parse them. Nevertheless, while commenting TeX sections, +# don't comment @macro/@end macro so that makeinfo does propagate +# them. Unfortunately makeinfo --iftex --no-ifhtml --no-ifinfo +# doesn't work well enough (yet) to use that, so work around with sed. +comment_iftex_sed=$utildir/comment.sed +cat <$comment_iftex_sed +/^@tex/,/^@end tex/{ + s/^/@c texi2dvi/ +} +/^@iftex/,/^@end iftex/{ + s/^/@c texi2dvi/ + /^@c texi2dvi@macro/,/^@c texi2dvi@end macro/{ + s/^@c texi2dvi// + } +} +/^@html/,/^@end html/{ + s/^/@c (texi2dvi)/ +} +/^@ifhtml/,/^@end ifhtml/{ + s/^/@c (texi2dvi)/ +} +/^@ifnottex/,/^@end ifnottex/{ + s/^/@c (texi2dvi)/ +} +/^@ifinfo/,/^@end ifinfo/{ + /^@node/p + /^@menu/,/^@end menu/p + t + s/^/@c (texi2dvi)/ +} +s/^@ifnotinfo/@c texi2dvi@ifnotinfo/ +s/^@end ifnotinfo/@c texi2dvi@end ifnotinfo/ +EOF +# Uncommenting is simple: Remove any leading `@c texi2dvi'. +uncomment_iftex_sed=$utildir/uncomment.sed +cat <$uncomment_iftex_sed +s/^@c texi2dvi// +EOF + +# A shell script that computes the list of xref files. +# Takes the filename (without extension) of which we look for xref +# files as argument. The index files must be reported last. +get_xref_files=$utildir/get_xref.sh +cat <<\EOF >$get_xref_files +#! /bin/sh + +# Get list of xref files (indexes, tables and lists). +# Find all files having root filename with a two-letter extension, +# saves the ones that are really Texinfo-related files. .?o? catches +# many files: .toc, .log, LaTeX tables and lists, FiXme's .lox, maybe more. +for this_file in "$1".?o? "$1".aux "$1".?? "$1".idx; do + # If file is empty, skip it. + test -s "$this_file" || continue + # If the file is not suitable to be an index or xref file, don't + # process it. The file can't be if its first character is not a + # backslash or single quote. + first_character=`sed -n '1s/^\(.\).*$/\1/p;q' $this_file` + if test "x$first_character" = "x\\" \ + || test "x$first_character" = "x'"; then + xref_files="$xref_files ./$this_file" + fi +done +echo "$xref_files" +EOF +chmod 500 $get_xref_files + +# File descriptor usage: +# 0 standard input +# 1 standard output (--verbose messages) +# 2 standard error +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 5 tools output (turned off by --quiet) + +# Tools' output. If quiet, discard, else redirect to the message flow. +if test "$quiet" = t; then + exec 5>/dev/null +else + exec 5>&1 +fi + +# Enable tracing +test "$debug" = t && set -x + +# +# TeXify files. + +for command_line_filename in ${1+"$@"}; do + $verbose "Processing $command_line_filename ..." + + # If the COMMAND_LINE_FILENAME is not absolute (e.g., --debug.tex), + # prepend `./' in order to avoid that the tools take it as an option. + echo "$command_line_filename" | $EGREP '^(/|[A-z]:/)' >/dev/null \ + || command_line_filename="./$command_line_filename" + + # See if the file exists. If it doesn't we're in trouble since, even + # though the user may be able to reenter a valid filename at the tex + # prompt (assuming they're attending the terminal), this script won't + # be able to find the right xref files and so forth. + if test ! -r "$command_line_filename"; then + echo "$0: Could not read $command_line_filename, skipping." >&2 + continue + fi + + # Get the name of the current directory. We want the full path + # because in clean mode we are in tmp, in which case a relative + # path has no meaning. + filename_dir=`echo $command_line_filename | sed 's!/[^/]*$!!;s!^$!.!'` + filename_dir=`cd "$filename_dir" >/dev/null && pwd` + + # Strip directory part but leave extension. + filename_ext=`basename "$command_line_filename"` + # Strip extension. + filename_noext=`echo "$filename_ext" | sed 's/\.[^.]*$//'` + ext=`echo "$filename_ext" | sed 's/^.*\.//'` + + # _src. Use same basename since we want to generate aux files with + # the same basename as the manual. If --expand, then output the + # macro-expanded file to here, else copy the original file. + tmpdir_src=$tmpdir/src + filename_src=$tmpdir_src/$filename_noext.$ext + + # _xtr. The file with the user's extra commands. + tmpdir_xtr=$tmpdir/xtr + filename_xtr=$tmpdir_xtr/$filename_noext.$ext + + # _bak. Copies of the previous xref files (another round is run if + # they differ from the new one). + tmpdir_bak=$tmpdir/bak + + # Make all those directories and give up if we can't succeed. + mkdir $tmpdir_src $tmpdir_xtr $tmpdir_bak || exit 1 + + # Source file might include additional sources. + # We want `.:$orig_pwd' before anything else. (We'll add `.:' later + # after all other directories have been turned into absolute paths.) + # `.' goes first to ensure that any old .aux, .cps, + # etc. files in ${directory} don't get used in preference to fresher + # files in `.'. Include orig_pwd in case we are in clean mode, where + # we've cd'd to a temp directory. + common="$orig_pwd$path_sep$filename_dir$path_sep$txincludes" + TEXINPUTS="$common$TEXINPUTS_orig" + INDEXSTYLE="$common$INDEXSTYLE_orig" + + # Convert relative paths to absolute paths, so we can run in another + # directory (e.g., in --clean mode, or during the macro-support + # detection.) + # + # Empty path components are meaningful to tex. We rewrite them + # as `EMPTY' so they don't get lost when we split on $path_sep. + TEXINPUTS=`echo $TEXINPUTS |sed 's/^:/EMPTY:/;s/:$/:EMPTY/;s/::/:EMPTY:/g'` + INDEXSTYLE=`echo $INDEXSTYLE |sed 's/^:/EMPTY:/;s/:$/:EMPTY/;s/::/:EMPTY:/g'` + save_IFS=$IFS + IFS=$path_sep + set x $TEXINPUTS; shift + TEXINPUTS=. + for dir + do + case $dir in + EMPTY) + TEXINPUTS=$TEXINPUTS$path_sep + ;; + [\\/]* | ?:[\\/]*) # Absolute paths don't need to be expansed. + TEXINPUTS=$TEXINPUTS$path_sep$dir + ;; + *) + abs=`cd "$dir" && pwd` && TEXINPUTS=$TEXINPUTS$path_sep$abs + ;; + esac + done + set x $INDEXSTYLE; shift + INDEXSTYLE=. + for dir + do + case $dir in + EMPTY) + INDEXSTYLE=$INDEXSTYLE$path_sep + ;; + [\\/]* | ?:[\\/]*) # Absolute paths don't need to be expansed. + INDEXSTYLE=$INDEXSTYLE$path_sep$dir + ;; + *) + abs=`cd "$dir" && pwd` && INDEXSTYLE=$INDEXSTYLE$path_sep$abs + ;; + esac + done + IFS=$save_IFS + + # If the user explicitly specified the language, use that. + # Otherwise, if the first line is \input texinfo, assume it's texinfo. + # Otherwise, guess from the file extension. + if test -n "$set_language"; then + language=$set_language + elif sed 1q "$command_line_filename" | grep 'input texinfo' >/dev/null; then + language=texinfo + else + language= + fi + + # Get the type of the file (latex or texinfo) from the given language + # we just guessed, or from the file extension if not set yet. + case ${language:-$filename_ext} in + [lL]a[tT]e[xX] | *.ltx | *.tex) + # Assume a LaTeX file. LaTeX needs bibtex and uses latex for + # compilation. No makeinfo. + bibtex=${BIBTEX:-bibtex} + makeinfo= # no point in running makeinfo on latex source. + texindex=${MAKEINDEX:-makeindex} + if test $oformat = dvi; then + tex=${LATEX:-latex} + else + tex=${PDFLATEX:-pdflatex} + fi + ;; + + *) + # Assume a Texinfo file. Texinfo files need makeinfo, texindex and tex. + bibtex= + texindex=${TEXINDEX:-texindex} + if test $oformat = dvi; then + tex=${TEX:-tex} + else + tex=${PDFTEX:-pdftex} + fi + # Unless required by the user, makeinfo expansion is wanted only + # if texinfo.tex is too old. + if test "$expand" = t; then + makeinfo=${MAKEINFO:-makeinfo} + else + # Check if texinfo.tex performs macro expansion by looking for + # its version. The version is a date of the form YEAR-MO-DA. + # We don't need to use [0-9] to match the digits since anyway + # the comparison with $txiprereq, a number, will fail with non + # digits. + txiversion_tex=txiversion.tex + echo '\input texinfo.tex @bye' >$tmpdir/$txiversion_tex + # Run in the tmpdir to avoid leaving files. + eval `cd $tmpdir >/dev/null && + $tex $txiversion_tex 2>/dev/null | + sed -n 's/^.*\[\(.*\)version \(....\)-\(..\)-\(..\).*$/txiformat=\1 txiversion="\2\3\4"/p'` + $verbose "texinfo.tex preloaded as \`$txiformat', version is \`$txiversion' ..." + if test "$txiprereq" -le "$txiversion" >/dev/null 2>&1; then + makeinfo= + else + makeinfo=${MAKEINFO:-makeinfo} + fi + # As long as we had to run TeX, offer the user this convenience + if test "$txiformat" = Texinfo; then + escape=@ + fi + fi + ;; + esac + + # Expand macro commands in the original source file using Makeinfo. + # Always use `end' footnote style, since the `separate' style + # generates different output (arguably this is a bug in -E). + # Discard main info output, the user asked to run TeX, not makeinfo. + if test -n "$makeinfo"; then + $verbose "Macro-expanding $command_line_filename to $filename_src ..." + sed -f $comment_iftex_sed "$command_line_filename" \ + | $makeinfo --footnote-style=end -I "$filename_dir" $miincludes \ + -o /dev/null --macro-expand=- \ + | sed -f $uncomment_iftex_sed >"$filename_src" + filename_input=$filename_src + fi + + # If makeinfo failed (or was not even run), use the original file as input. + if test $? -ne 0 \ + || test ! -r "$filename_src"; then + $verbose "Reverting to $command_line_filename ..." + filename_input=$filename_dir/$filename_ext + fi + + # Used most commonly for @finalout, @smallbook, etc. + if test -n "$textra"; then + $verbose "Inserting extra commands: $textra" + sed '/^@setfilename/a\ +'"$textra" "$filename_input" >$filename_xtr + filename_input=$filename_xtr + fi + + # If clean mode was specified, then move to the temporary directory. + if test "$clean" = t; then + $verbose "cd $tmpdir_src" + cd "$tmpdir_src" || exit 1 + fi + + while :; do # will break out of loop below + orig_xref_files=`$get_xref_files "$filename_noext"` + + # Save copies of originals for later comparison. + if test -n "$orig_xref_files"; then + $verbose "Backing up xref files: `echo $orig_xref_files | sed 's|\./||g'`" + cp $orig_xref_files $tmpdir_bak + fi + + # Run bibtex on current file. + # - If its input (AUX) exists. + # - If AUX contains both `\bibdata' and `\bibstyle'. + # - If some citations are missing (LOG contains `Citation'). + # or the LOG complains of a missing .bbl + # + # We run bibtex first, because I can see reasons for the indexes + # to change after bibtex is run, but I see no reason for the + # converse. + # + # Don't try to be too smart. Running bibtex only if the bbl file + # exists and is older than the LaTeX file is wrong, since the + # document might include files that have changed. Because there + # can be several AUX (if there are \include's), but a single LOG, + # looking for missing citations in LOG is easier, though we take + # the risk to match false messages. + if test -n "$bibtex" \ + && test -r "$filename_noext.aux" \ + && test -r "$filename_noext.log" \ + && (grep '^\\bibdata[{]' "$filename_noext.aux" \ + && grep '^\\bibstyle[{]' "$filename_noext.aux" \ + && (grep 'Warning:.*Citation.*undefined' "$filename_noext.log" \ + || grep 'No file .*\.bbl\.' "$filename_noext.log")) \ + >/dev/null 2>&1; \ + then + $verbose "Running $bibtex $filename_noext ..." + if $bibtex "$filename_noext" >&5; then :; else + echo "$0: $bibtex exited with bad status, quitting." >&2 + exit 1 + fi + fi + + # What we'll run texindex on -- exclude non-index files. + # Since we know index files are last, it is correct to remove everything + # before .aux and .?o?. But don't really do o + # -- don't match whitespace as . + # Otherwise, if orig_xref_files contains something like + # foo.xo foo.whatever + # the space after the o will get matched. + index_files=`echo "$orig_xref_files" \ + | sed "s!.*\.aux!!g; + s!./$filename_noext\.[^ ]o[^ ]!!g; + s/^[ ]*//;s/[ ]*$//"` + # Run texindex (or makeindex) on current index files. If they + # already exist, and after running TeX a first time the index + # files don't change, then there's no reason to run TeX again. + # But we won't know that if the index files are out of date or + # nonexistent. + if test -n "$texindex" && test -n "$index_files"; then + $verbose "Running $texindex $index_files ..." + if $texindex $index_files 2>&5 1>&2; then :; else + echo "$0: $texindex exited with bad status, quitting." >&2 + exit 1 + fi + fi + + # Finally, run TeX. + # Prevent $ESCAPE from being interpreted by the shell if it happens + # to be `/'. + $batch tex_args="\\${escape}nonstopmode\ \\${escape}input" + cmd="$tex $tex_args $filename_input" + $verbose "Running $cmd ..." + if $cmd >&5; then :; else + echo "$0: $tex exited with bad status, quitting." >&2 + echo "$0: see $filename_noext.log for errors." >&2 + test "$clean" = t \ + && cp "$filename_noext.log" "$orig_pwd" + exit 1 + fi + + + # Decide if looping again is needed. + finished=t + + # LaTeX (and the package changebar) report in the LOG file if it + # should be rerun. This is needed for files included from + # subdirs, since texi2dvi does not try to compare xref files in + # subdirs. Performing xref files test is still good since LaTeX + # does not report changes in xref files. + if grep "Rerun to get" "$filename_noext.log" >/dev/null 2>&1; then + finished= + fi + + # Check if xref files changed. + new_xref_files=`$get_xref_files "$filename_noext"` + $verbose "Original xref files = `echo $orig_xref_files | sed 's|\./||g'`" + $verbose "New xref files = `echo $new_xref_files | sed 's|\./||g'`" + + # If old and new lists don't at least have the same file list, + # then one file or another has definitely changed. + test "x$orig_xref_files" != "x$new_xref_files" && finished= + + # File list is the same. We must compare each file until we find + # a difference. + if test -n "$finished"; then + for this_file in $new_xref_files; do + $verbose "Comparing xref file `echo $this_file | sed 's|\./||g'` ..." + # cmp -s returns nonzero exit status if files differ. + if cmp -s "$this_file" "$tmpdir_bak/$this_file"; then :; else + # We only need to keep comparing until we find one that + # differs, because we'll have to run texindex & tex again no + # matter how many more there might be. + finished= + $verbose "xref file `echo $this_file | sed 's|\./||g'` differed ..." + test "$debug" = t && diff -c "$tmpdir_bak/$this_file" "$this_file" + break + fi + done + fi + + # If finished, exit the loop, else rerun the loop. + test -n "$finished" && break + done + + # If we were in clean mode, compilation was in a tmp directory. + # Copy the DVI (or PDF) file into the directory where the compilation + # has been done. (The temp dir is about to get removed anyway.) + # We also return to the original directory so that + # - the next file is processed in correct conditions + # - the temporary file can be removed + if test -n "$clean"; then + if test -n "$oname"; then + dest=$oname + else + dest=$orig_pwd + fi + $verbose "Copying $oformat file from `pwd` to $dest" + cp -p "./$filename_noext.$oformat" "$dest" + cd / # in case $orig_pwd is on a different drive (for DOS) + cd $orig_pwd || exit 1 + fi + + # Remove temporary files. + if test "x$debug" = "x"; then + $verbose "Removing $tmpdir_src $tmpdir_xtr $tmpdir_bak ..." + cd / + rm -rf $tmpdir_src $tmpdir_xtr $tmpdir_bak + fi +done + +$verbose "$0 done." +exit 0 # exit successfully, not however we ended the loop. diff --git a/configure.ac b/configure.ac new file mode 100644 index 000000000..e1a91549e --- /dev/null +++ b/configure.ac @@ -0,0 +1,94 @@ +dnl Hey Emacs, I want this in -*- autoconf -*- mode, please. + +dnl Copyright 2000, 2001, 2002 Free Software Foundation, Inc. +dnl Please see COPYING for a description your rights and responsibilities +dnl with this software. +dnl Process this file with autoconf to produce a configure script. + +dnl ----------------------------- HOST SYSTEM ----------------------------------- + +AC_PREREQ(2.54) +AC_INIT([GNU lightning], 1.2a, bonzini@gnu.org, lightning) +AC_CONFIG_AUX_DIR(config) +AC_CONFIG_SRCDIR([lightning.h.in]) + +AC_CANONICAL_TARGET +AM_CONFIG_HEADER(lightning.h) +AM_INIT_AUTOMAKE + +# We don't use autoheader. +AUTOHEADER="touch lightning.h.in" + +AC_PROG_CC +AC_PROG_CPP +AC_PROG_LN_S +AC_PROG_RANLIB +AC_PROG_INSTALL +AC_PROG_MAKE_SET +AC_PATH_PROG(INSTALL_INFO, install-info, :, $PATH:/sbin) +AC_EXEEXT + +AC_CHECK_FUNCS(memcpy) + +BACKENDS="i386 sparc ppc" +AC_SUBST(BACKENDS) + +case "$target_cpu" in + i?86) cpu=i386; AC_DEFINE(LIGHTNING_I386, 1) ;; + sparc*) cpu=sparc; AC_DEFINE(LIGHTNING_SPARC, 1) ;; + powerpc) cpu=ppc; AC_DEFINE(LIGHTNING_PPC, 1) ;; + *) AC_MSG_ERROR([cpu $target_cpu not supported]) ;; +esac + +dnl ---------------------------- COMMAND LINE --------------------------------- + +AC_ARG_ENABLE( disassembling, +[ --enable-disassembling make the test programs disassemble the code + enabled by default if host != target], +, enable_disassembling=no) + +AM_CONDITIONAL(REGRESSION_TESTING, test "$host_cpu" = "$target_cpu") +if test "$host_cpu" != "$target_cpu"; then + AC_DEFINE(LIGHTNING_CROSS, 1) + enable_disassembling=yes +fi + +if test "$enable_disassembling" != no; then + AC_DEFINE(LIGHTNING_DISASSEMBLE, 1) +fi +LIBDISASS="" +AM_CONDITIONAL(DISASS, test "$enable_disassembling" != no) +test "$enable_disassembling" != no && LIBDISASS="libdisass.a" + +AC_ARG_ENABLE( assertions, +[ --enable-assertions perform internal consistency checks], +, enable_assertions=no) + +if test "$enable_assertions" != no; then + AC_DEFINE(_ASM_SAFETY, 1) +fi + +AM_CONDITIONAL(LIGHTNING_MAIN, :) + +dnl --------------------------- PRODUCE OUTPUT -------------------------------- + +cpu_dir=lightning/$cpu +AC_CONFIG_LINKS(lightning/asm.h:$cpu_dir/asm.h dnl + lightning/fp.h:$cpu_dir/fp.h dnl + lightning/core.h:$cpu_dir/core.h dnl + lightning/funcs.h:$cpu_dir/funcs.h, [], + [cpu_dir=$cpu_dir]) + +AC_SUBST(LIBDISASS) + +AC_CONFIG_FILES(Makefile doc/Makefile tests/Makefile opcode/Makefile + lightning/Makefile) +AC_CONFIG_FILES(lightningize, chmod +x lightningize) + +AC_OUTPUT + +# A small sanity check +echo "#include " > confdefs.h # dummy input file +CPPFLAGS="$CPPFLAGS -I. -I$srcdir" +AC_TRY_COMPILE([#include "lightning.h"], , , + AC_MSG_WARN(the compiler that was found could not compile GNU lightning)) diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 000000000..968812fca --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,18 @@ +EXTRA_DIST=lightning.info lightning.info-1 lightning.info-2 lightning.info-3 + +TEXI2DVI=$(top_srcdir)/config/texi2dvi +HELP2MAN = $(top_srcdir)/config/help2man + +dist_man1_MANS = lightningize.1 +info_TEXINFOS = lightning.texi +EXTRA_TEXINFOS = u-lightning.texi p-lightning.texi +MOSTLYCLEANFILES = lightning.tmp + +lightning_TEXINFOS = body.texi toc.texi using.texi porting.texi version.texi +u_lightning_TEXINFOS = body.texi toc.texi using.texi version.texi +p_lightning_TEXINFOS = body.texi toc.texi porting.texi version.texi + +lightningize.1: $(top_srcdir)/lightningize.in $(top_srcdir)/configure.ac + cd $(top_srcdir) && $(MAKE) lightningize + $(HELP2MAN) -p lightning $(top_srcdir)/lightningize > $(srcdir)/lightningize.1 + diff --git a/doc/body.texi b/doc/body.texi new file mode 100644 index 000000000..cccadd049 --- /dev/null +++ b/doc/body.texi @@ -0,0 +1,306 @@ +@ifinfo +@dircategory @lightning{}, a library for dynamic code generation +@direntry + * @value{TITLE}: (lightning). +@end direntry + +This file documents GNU lightning, Version @value{VERSION}. +It was last updated on @value{UPDATED}. + +Copyright @copyright{} 2000 Free Software Foundation, Inc. +Authored by Paolo Bonzini. + +This document is released under the terms of the GNU Free Documentation +License as published by the Free Software Foundation; either version 1.1, or +(at your option) any later version. + +You should have received a copy of the GNU Free Documentation License along +with GNU lightning; see the file @file{COPYING.DOC}. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +There are no Secondary Sections, no Cover Texts and no Invariant Sections +(as defined in the license); this text, along with its equivalent in the +printed manual, constitutes the Title Page. +@end ifinfo + +@setchapternewpage odd + +@titlepage +@title @value{TITLE} +@subtitle Version @value{VERSION} +@subtitle @value{UPDATE-MONTH} + +@author by Paolo Bonzini + +@c The following two commands start the copyright page. +@page +@vskip 0pt plus 1filll +Copyright 1988-92, 1994-95, 1999, 2000 Free Software Foundation, Inc. + +This document is released under the terms of the @sc{gnu} Free Documentation +License as published by the Free Software Foundation; either version 1.1, or +(at your option) any later version. + +You should have received a copy of the @sc{gnu} Free Documentation License +along with @sc{gnu} @i{lightning}; see the file @file{COPYING.DOC}. If not, +write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. + +There are no Secondary Sections, no Cover Texts and no Invariant Sections +(as defined in the license); this text, along with its equivalent in the +Info documentation, constitutes the Title Page. +@end titlepage + +@ifclear ISTEX +@node Top +@top @lightning{} + +This document describes @value{TOPIC} the @lightning{} library for +dynamic code generation. Unlike other dynamic code generation systems, +which are usually either inefficient or non-portable, @lightning{} is +both retargetable and very fast. + +@include toc.texi +@end ifclear + +@node Overview +@chapter Introduction to @lightning{} + +@ifset ISTEX +This document describes @value{TOPIC} the @lightning{} library for +dynamic code generation. Unlike other dynamic code generation systems, +which are usually either inefficient or non-portable, @lightning{} is +both retargetable and very fast. +@end ifset + +@ifclear USING +This manual assumes that you are pretty comfortable with the usage of +@lightning{} for dynamic code generation, as described in +@usingref{The instruction set, @lightning{}'s instruction set}, and +instead focuses on the retargeting process. What follows is nothing +more then a brief overview of the system. +@end ifclear + +Dynamic code generation is the generation of machine code +at runtime. It is typically used to strip a layer of interpretation +by allowing compilation to occur at runtime. One of the most +well-known applications of dynamic code generation is perhaps that +of interpreters that compile source code to an intermediate bytecode +form, which is then recompiled to machine code at run-time: this +approach effectively combines the portability of bytecode +representations with the speed of machine code. Another common +application of dynamic code generation is in the field of hardware +simulators and binary emulators, which can use the same techniques +to translate simulated instructions to the instructions of the +underlying machine. + +Yet other applications come to mind: for example, windowing +@dfn{bitblt} operations, matrix manipulations, and network packet +filters. Albeit very powerful and relatively well known within the +compiler community, dynamic code generation techniques are rarely +exploited to their full potential and, with the exception of the +two applications described above, have remained curiosities because +of their portability and functionality barriers: binary instructions +are generated, so programs using dynamic code generation must be +retargeted for each machine; in addition, coding a run-time code +generator is a tedious and error-prone task more than a difficult one. + +@ifset USING +This manual describes the @lightning{} dynamic code generation library. +@lightning{} provides a portable, fast and easily retargetable dynamic +code generation system. +@end ifset +@ifclear USING +@lightning{} provides a portable, fast and easily retargetable dynamic +code generation system. +@end ifclear + +To be fast, @lightning{} emits machine code without first creating +intermediate data structures such as RTL representations traditionally +used by optimizing compilers (@pxref{RTL representation, , , gcc, Using +and porting GNU CC}). @lightning{} translates code directly from a +machine independent interface to that of the underlying architecture. +This makes code generation more efficient, since no intermediate data +structures have to be constructed and consumed. A collateral benefit +it that @lightning{} consumes little space: other than the memory +needed to store generated instructions and data structures such as +parse trees, the only data structure that client will usually need +is an array of pointers to labels and unresolved jumps, which you +can often allocate directly on the system stack. + +To be portable, @lightning{} abstracts over current architectures' +quirks and unorthogonalities. The interface that it exposes to is that +of a standardized RISC architecture loosely based on the SPARC and MIPS +chips. There are a few general-purpose registers (six, not including +those used to receive and pass parameters between subroutines), and +arithmetic operations involve three operands---either three registers +or two registers and an arbitrarily sized immediate value. + +On one hand, this architecture is general enough that it is possible to +generate pretty efficient code even on CISC architectures such as the +Intel x86 or the Motorola 68k families. On the other hand, it matches +real architectures closely enough that, most of the time, the +compiler's constant folding pass ends up generating code which +assembles machine instructions without further tests. + +@section Drawbacks + +@lightning{} has been useful in practice; however, it does have +at least four drawbacks: it has limited registers, no peephole +optimizer, no instruction scheduler and no symbolic debugger. Of +these, the last is the most critical even though it does not +affect the quality of generated code: the only way to debug code +generated at run-time is to step through it at the level of +host specific machine code. A decent knowledge of the underlying +instruction set is thus needed to make sense of the debugger's +output. + +The low number of available registers (six) is also an important +limitation. However, let's take the primary application of dynamic +code generation, that is, bytecode translators. The underlying +virtual machines tend to have very few general purpose registers +(usually 0 to 2) and the translators seldom rely on sophisticated +graph-coloring algorithms to allocate registers to temporary +variables. Rather, these translators usually obtain performance +increases because: a) they remove indirect jumps, which are usually +poorly predicted, and thus often form a bottleneck, b) they +parameterize the generated code and go through the process of decoding +the bytecodes just once. So, their usage of registers is rather +sparse---in fact, in practice, six registers were found to be +enough for most purposes. + +The lack of a peephole optimizer is most important on machines where a +single instruction can map to multiple native instructions. For +instance, Intel chips' division instruction hard-codes the dividend +to be in EAX and the quotient and remainder to be output, respectively, +in EAX and EDX: on such chips, @lightning{} does lots of pushing and +popping of EAX and EDX to save those registers that are not used. +Unnecessary stack operations could be removed by looking at whether +preserved registers are destroyed soon. Unfortunately, the current +implementation of @lightning{} is so fast because it only knows about +the single instruction that is being generated; performing these +optimizations would require a flow analysis pass that would probably +hinder @lightning{}'s speed. + +The lack of an instruction scheduler is not very important---pretty +good instruction scheduling can actually be obtained by separating +register writes from register reads. The only architectures on which +a scheduler would be useful are those on which arithmetic instructions +have two operands; an example is, again, the x86, on which the single +instruction +@example + subr_i R0, R1, R2 @rem{!Compute R0 = R1 - R2} +@end example +@noindent +is translated to two instruction, of which the second depends on the +result of the first: +@example + movl %ebx, %eax @rem{! Move R1 into R0} + subl %edx, %eax @rem{! Subtract R2 from R0} +@end example + +@ifset BOTH +@node Using GNU lightning +@chapter Using @lightning{} + +This chapter describes installing and using @lightning{}. + +@menu +@usingmenu{} +@end menu + +@lowersections +@end ifset + +@ifset USING +@include using.texi +@end ifset + +@ifset BOTH +@raisesections + +@node Porting GNU lightning +@chapter Porting @lightning{} + +This chapter describes the process of porting @lightning{}. +It assumes that you are pretty comfortable with the usage of +@lightning{} for dynamic code generation, as described in +@ref{Using GNU lightning}. + +@menu +@portingmenu{} +@end menu + +@lowersections +@end ifset + +@ifset PORTING +@include porting.texi +@end ifset + +@ifset BOTH +@raisesections +@end ifset + +@node Future +@chapter The future of @lightning{} + +Presented below is the set of tasks that I feel need to be performed +to make @lightning{} a more fully functional, viable system. They are +presented in no particular order. I would @emph{very much} welcome any +volunteers who would like to help with the implementation of one or +more of these tasks. Please write to me, Paolo Bonzini, at +@email{bonzini@@gnu.org} if you are interested in adding your efforts +to the @lightning{} project. + +Tasks: +@itemize @bullet +@item +The most important task to make @lightning{} more widely usable +is to retarget it. Although currently supported architectures +(x86, SPARC, PowerPC) are certainly some of the most widely used, +@lightning{} could be ported to others---namely, the Alpha and +MIPS architectures. + +@item +Another interesting task is to allow the instruction stream to grow +dynamically. This is a problem because not all architectures allow +to write position independent code.@footnote{The x86's absolute +jumps, for example, are actually slow indirect jumps, and need a +register.} + +@item +Optimize leaf procedures on the SPARC. This involves using the +output registers (@code{%o@i{X}}) instead of the local registers +(@code{%l@i{X}}) when writing leaf procedures; the problem is, +leaf procedures also receive parameters in the output registers, +so they would be overwritten by write accesses to general-purpose +registers. +@end itemize + + +@node Acknowledgements +@chapter Acknowledgements + +As far as I know, the first general-purpose portable dynamic code +generator is @sc{dcg}, by Dawson R.@: Engler and T.@: A.@: Proebsting. +Further work by Dawson R. Engler resulted in the @sc{vcode} system; +unlike @sc{dcg}, @sc{vcode} used no intermediate representation and +directly inspired @lightning{}. + +Thanks go to Ian Piumarta, who kindly accepted to release his own +program @sc{ccg} under the GNU General Public License, thereby allowing +@lightning{} to use the run-time assemblers he had wrote for @sc{ccg}. +@sc{ccg} provides a way of dynamically assemble programs written in the +underlying architecture's assembly language. So it is not portable, +yet very interesting. + +I also thank Steve Byrne for writing GNU Smalltalk, since @lightning{} +was first developed as a tool to be used in GNU Smalltalk's dynamic +translator from bytecodes to native code. + +@iftex +@contents +@end iftex + +@bye diff --git a/doc/lightning.texi b/doc/lightning.texi new file mode 100644 index 000000000..dee770e1d --- /dev/null +++ b/doc/lightning.texi @@ -0,0 +1,105 @@ +\input texinfo.tex @c -*- texinfo -*- +@c %**start of header (This is for running Texinfo on a region.) + +@setfilename lightning.info + +@set TITLE Using and porting @sc{gnu} @i{lightning} +@set TOPIC installing, using and porting +@set BOTH +@set USING +@set PORTING + +@settitle @value{TITLE} + +@c --------------------------------------------------------------------- +@c Common macros +@c --------------------------------------------------------------------- + +@macro bulletize{a} +@item +\a\ +@end macro + +@macro rem{a} +@r{@i{\a\}} +@end macro + +@macro gnu{} +@sc{gnu} +@end macro + +@macro lightning{} +@gnu{} @i{lightning} +@end macro + +@c --------------------------------------------------------------------- +@c Macros for Texinfo 3.1/4.0 compatibility +@c --------------------------------------------------------------------- + +@c Emulate the `@ifnottex' command which is found in Texinfo 4.0 +@iftex +@set ISTEX +@end iftex + +@c @hlink (macro), @url and @email are used instead of @uref for Texinfo 3.1 +@c compatibility +@macro hlink{url, link} +\link\ (\url\) +@end macro + +@c ifhtml can only be true in Texinfo 4.0, which has uref +@ifhtml +@unmacro hlink + +@macro hlink{url, link} +@uref{\url\, \link\} +@end macro + +@macro email{mail} +@uref{mailto:\mail\, , \mail\} +@end macro + +@macro url{url} +@uref{\url\} +@end macro +@end ifhtml + +@c --------------------------------------------------------------------- +@c References to the other half of the manual +@c --------------------------------------------------------------------- + +@ifset USING +@macro usingref{node, name} +@ref{\node\, , \name\} +@end macro +@end ifset + +@ifclear USING +@macro usingref{node, name} +@ref{\node\, , \name\, u-lightning, Using @sc{gnu} @i{lightning}} +@end macro +@end ifclear + +@ifset PORTING +@macro portingref{node, name} +@ref{\node\, , \name\} +@end macro +@end ifset + +@ifclear PORTING +@macro portingref{node, name} +@ref{\node\, , \name\, p-lightning, Porting @sc{gnu} @i{lightning}} +@end macro +@end ifclear + +@c --------------------------------------------------------------------- +@c End of macro section +@c --------------------------------------------------------------------- + +@include version.texi +@include body.texi + +@c %**end of header (This is for running Texinfo on a region.) + +@c *********************************************************************** + diff --git a/doc/porting.texi b/doc/porting.texi new file mode 100644 index 000000000..74233975d --- /dev/null +++ b/doc/porting.texi @@ -0,0 +1,1415 @@ +@node Structure of a port +@chapter An overview of the porting process + +A particular port of @lightning{} is composed of four files. These +have a common suffix which identifies the port (for example, +@code{i386} or @code{ppc}), and a prefix that identifies their +function; they are: + +@itemize @bullet +@item +@file{asm-@var{suffix}.h}, which contains the description of the +target machine's instruction format. The creation of this file +is discussed in @ref{Run-time assemblers, , Creating the run-time +assembler}. + +@item +@file{core-@var{suffix}.h}, which contains the mappings from +@lightning{}'s instruction set to the target machine's assembly +language format. The creation of this file is discussed in +@ref{Standard macros, , Creating the platform-independent layer}. + +@item +@file{funcs-@var{suffix}.h}, for now, only contains the definition +of @code{jit_flush_code}. The creation of this file is briefly +discussed in @ref{Standard functions, , More complex tasks in +the platform-independent layer}. + +@item +@file{fp-@var{suffix}.h}, which contains the description of the +target machine's instruction format and the internal macros for doing +floating point computation. The creation of this file is discussed +in @ref{Floating-point macros, , Implementing macros for floating +point}. +@end itemize + +Before doing anything, you have to add the ability to recognize the +new port during the configuration process. This is explained in +@ref{Adjusting configure, , Automatically recognizing the new platform}. + +@node Adjusting configure +@chapter Automatically recognizing the new platform + +Before starting your port, you have to add the ability to recognize the +new port during the configure process. You only have to run +@file{config.guess}, which you'll find in the main distribution +directory, and note down the first part of the output (up to the first +dash). + +Then, in the two files @file{configure.in} and @file{lightning.m4}, +lookup the line +@example + case "$host_cpu" in +@end example + +@noindent +and, right after it, add the line: +@example + @var{cpu-name}) cpu=@var{file-suffix} ;; +@end example + +@noindent +where @var{cpu-name} is the cpu as output by @file{config.guess}, and +@var{file-suffix} is the suffix that you are going to use for your files +(@pxref{Structure of a port, , An overview of the porting process}). + +Now create empty files for your new port: +@example + touch lightning/asm-xxx.h + touch lightning/fp-xxx.h + touch lightning/core-xxx.h + touch lightning/funcs-xxx.h +@end example + +@noindent +and run @file{configure}, which should create the symlinks that are +needed by @code{lightning.h}. This is important because it will allow +you to use @lightning{} (albeit in a limited way) for testing even +before the port is completed. + +@node Run-time assemblers +@chapter Creating the run-time assembler + +The run-time assembler is a set of macros whose purpose is to assemble +instructions for the target machine's assembly language, translating +mnemonics to machine language together with their operands. While a +run-time assembler is not, strictly speaking, part of @lightning{} +(it is a private layer to be used while implementing the standard +macros that are ultimately used by clients), designing a run-time +assembler first allows you to think in terms of assembly language +rather than binary code (ouch!@dots{}), making it considerably easier +to write the standard macros. + +Creating a run-time assembler is a tedious process rather than a +difficult one, because most of the time will be spent collecting and +copying information from the architecture's manual. + +Macros defined by a run-time assembler are conventionally named after +the mnemonic and the type of its operands. Examples took from the +SPARC's run-time assembler are @code{ADDrrr}, a macro that assembles +an @code{ADD} instruction with three register operands, and +@code{SUBCCrir}, which assembles a @code{SUBCC} instruction whose second +operand is an immediate and the remaining two are registers. + +The first step in creating the assembler is to pick a convention for +operand specifiers (@code{r} and @code{i} in the example above) and for +register names. On the SPARC, this convention is as follows + +@table @code +@item @b{r} +A register name. For every @code{r} in the macro name, a numeric +parameter @code{RR} is passed to the macro, and the operand is assembled +as @code{%r@var{RR}}. + +@item @b{i} +An immediate, usually a 13-bit signed integer (with exception for +instructions such as @code{SETHI} and branches). The macros check +the size of the passed parameter if @lightning{} is configured with +@code{--enable-assertions}. + +@item @b{x} +A combination of two @code{r} parameters, which are summed to determine +the effective address in a memory load/store operation. + +@item @b{m} +A combination of an @code{r} and @code{i} parameter, which are summed to +determine the effective address in a memory load/store operation. +@end table + +Additional macros can be defined that provide easier access to register +names. For example, on the SPARC, @code{_Ro(3)} and @code{_Rg(5)} map +respectively to @code{%o3} and @code{%g5}; on the x86, instead, symbolic +representations of the register names are provided (for example, +@code{_EAX} and @code{_EBX}). + +CISC architectures sometimes have registers of different sizes--this is +the case on the x86 where @code{%ax} is a 16-bit register while +@code{%esp} is a 32-bit one. In this case, it can be useful to embed +information on the size in the definition of register names. The x86 +machine language, for example, represents all three of @code{%bh}, +@code{%di} and @code{%edi} as 7; but the x86 run-time assemblers defines +them with different numbers, putting the register's size in the upper +nybble (for example, @samp{17h} for @code{%bh} and @samp{27h} for +@code{%di}) so that consistency checks can be made on the operands' +sizes when @code{--enable-assertions} is used. + +The next important part defines the native architecture's instruction +formats. These can be as few as ten on RISC architectures, and as many +as fifty on CISC architectures. In the latter case it can be useful +to define more macros for sub-formats (such as macros for different +addressing modes) or even for sub-fields in an instruction. Let's see +an example of these macros. + +@example +#define _2i( OP, RD, OP2, IMM) + _I((_u2 (OP )<<30) | (_u5(RD)<<25) | (_u3(OP2)<<22) | + _u22(IMM) ) +@end example + +The name of the macro, @code{_2i}, indicates a two-operand instruction +comprising an immediate operand. The instruction format is: + +@example + .------.---------.------.-------------------------------------------. + | OP | RD | OP2 | IMM | + |------+---------+------+-------------------------------------------| + |2 bits| 5 bits |3 bits| 22 bits | + |31-30 | 29-25 | 22-24| 0-21 | + '------'---------'------'-------------------------------------------' +@end example + +@lightning{} provides macros named @code{_sXX(OP)} and @code{_uXX(OP)}, +where XX is a number between 1 and 31, which test@footnote{Only when +@code{--enable-assertions} is used.} whether @code{OP} can be +represented as (respectively) a signed or unsigned integer of the +given size. What the macro above does, then, is to shift and @sc{or} +together the different fields, ensuring that each of them fits the field. + +Here is another definition, this time for the PowerPC architecture. + +@example +#define _X(OP,RD,RA,RB,XO,RC) + _I((_u6 (OP)<<26) | (_u5(RD)<<21) | (_u5(RA)<<16) | + ( _u5(RB)<<11) | (_u10(XO)<<1) | _u1(RC) ) +@end example + +Here is the bit layout corresponding to this instruction format: + +@example + .--------.--------.--------.--------.---------------------.-------. + | OP | RD | RA | RB | X0 | RC | + |--------+--------+--------+--------+-----------------------------| + | 6 bits | 5 bits | 5 bits | 5 bits | 10 bits | 1 bit | + | 31-26 | 25-21 | 16-20 | 11-15 | 1-10 | 0 | + '--------'---------'-------'--------'-----------------------------' +@end example + +How do these macros actually generate code? The secret lies in the +@code{_I} macro, which is one of four predefined macros which actually +store machine language instructions in memory. They are @code{_B}, +@code{_W}, @code{_I} and @code{_L}, respectively for 8-bit, 16-bit, +32-bit, and @code{long} (either 32-bit or 64-bit, depending on the +architecture) values. + +Next comes another set of macros (usually the biggest) which represents +the actual mnemonics---macros such as @code{ADDrrr} and @code{SUBCCrir}, +which were cited earlier in this chapter, belong to this set. Most of +the times, all these macros will do is to use the ``instruction format'' +macros, specifying the values of the fields in the different instruction +formats. Let's see a few of these definitions, again taken from the +SPARC assembler: + +@example +#define BAi(DISP) _2 (0, 0, 8, 2, DISP) +#define BA_Ai(DISP) _2 (0, 1, 8, 2, DISP) + +#define SETHIir(IMM, RD) _2i (0, RD, 4, IMM) + +#define ADDrrr(RS1, RS2, RD) _3 (2, RD, 0, RS1, 0, 0, RS2) +#define ADDrir(RS1, IMM, RD) _3i (2, RD, 0, RS1, 1, IMM) +#define ADDCCrrr(RS1, RS2, RD) _3 (2, RD, 16, RS1, 0, 0, RS2) +#define ADDCCrir(RS1, IMM, RD) _3i (2, RD, 16, RS1, 1, IMM) +#define ANDrrr(RS1, RS2, RD) _3 (2, RD, 1, RS1, 0, 0, RS2) +#define ANDrir(RS1, IMM, RD) _3i (2, RD, 1, RS1, 1, IMM) +#define ANDCCrrr(RS1, RS2, RD) _3 (2, RD, 17, RS1, 0, 0, RS2) +#define ANDCCrir(RS1, IMM, RD) _3i (2, RD, 17, RS1, 1, IMM) +@end example + +A few things have to be noted. For example: +@itemize @bullet +@item +The SPARC assembly language sometimes uses a comma inside a mnemonic +(for example, @code{ba,a}). This symbol is not allowed inside a +@sc{cpp} macro name, so it is replaced with an underscore; the same +is done with the dots found in the PowerPC assembly language (for +example, @code{andi.} is defined as @code{ANDI_rri}). + +@item +It can be useful to group together instructions with the same +instruction format, as doing this tends to make the source code +more readable (numbers are put in the same columns). + +@item +Using an editor without automatic wrap at end of line can be useful, +since run-time assemblers tend to have very long lines. +@end itemize + +A final touch is to define the synthetic instructions, which are +usually found on RISC machines. For example, on the SPARC, the +@code{LD} instruction has two synonyms (@code{LDUW} and @code{LDSW}) +which are defined thus: + +@example +#define LDUWxr(RS1, RS2, RD) LDxr(RS1, RS2, RD) +#define LDUWmr(RS1, IMM, RD) LDmr(RS1, IMM, RD) +#define LDSWxr(RS1, RS2, RD) LDxr(RS1, RS2, RD) +#define LDSWmr(RS1, IMM, RD) LDmr(RS1, IMM, RD) +@end example + +Other common case are instructions which take advantage of registers +whose value is hard-wired to zero, and short-cut instructions which +hard-code some or all of the operands: + +@example +@rem{/* Destination is %g0\, which the processor never overwrites. */} +#define CMPrr(R1, R2) SUBCCrrr(R1, R2, 0) @rem{/* subcc %r1\, %r2\, %g0 */} + +@rem{/* One of the source registers is hard-coded to be %g0. */} +#define NEGrr(R,S) SUBrrr(0, R, S) @rem{/* sub %g0\, %rR\, %rS */} + +@rem{/* All of the operands are hard-coded. */} +#define RET() JMPLmr(31,8 ,0) @rem{/* jmpl [%r31+8]\, %g0 */} + +@rem{/* One of the operands acts as both source and destination */} +#define BSETrr(R,S) ORrrr(R, S, S) @rem{/* or %rR\, %rS\, %rS */} +@end example + +Specific to RISC computers, finally, is the instruction to load an +arbitrarily sized immediate into a register. This instruction is +usually implemented as one or two basic instructions: + +@enumerate +@item +If the number is small enough, an instruction is sufficient +(@code{LI} or @code{ORI} on the PowerPC, @code{MOV} on the SPARC). + +@item +If the lowest bits are all zeroed, an instruction is sufficient +(@code{LIS} on the PowerPC, @code{SETHI} on the SPARC). + +@item +Otherwise, the high bits are set first (with @code{LIS} or +@code{SETHI}), and the result is then @sc{or}ed with the low +bits +@end enumerate + +Here is the definition of such an instruction for the PowerPC: + +@example +#define MOVEIri(R,I) (_siP(16,I) ? LIri(R,I) : \ @rem{/* case 1 */} + (_uiP(16,I) ? ORIrri(R,0,I) : \ @rem{/* case 1 */} + _MOVEIri(R, _HI(I), _LO(I)) )) @rem{/* case 2/3 */} + +#define _MOVEIri(H,L,R) (LISri(R,H), (L ? ORIrri(R,R,L) : 0)) +@end example + +@noindent +and for the SPARC: + +@example +#define SETir(I,R) (_siP(13,I) ? MOVir(I,R) : \ + _SETir(_HI(I), _LO(I), R)) + +#define _SETir(H,L,R) (SETHIir(H,R), (L ? ORrir(R,L,R) : 0)) +@end example + +In both cases, @code{_HI} and @code{_LO} are macros for internal use +that extract different parts of the immediate operand. + +You should take a look at the run-time assemblers distributed with +@lightning{} before trying to craft your own. In particular, make +sure you understand the RISC run-time assemblers (the SPARC's is +the simplest) before trying to decypher the x86 run-time assembler, +which is significantly more complex. + + +@node Standard macros +@chapter Creating the platform-independent layer + +The platform-independent layer is the one that is ultimately used +by @lightning{} clients. Creating this layer is a matter of creating +a hundred or so macros that comprise part of the interface used by +the clients, as described in +@usingref{The instruction set, @lightning{}'s instruction set}. + +Fortunately, a number of these definitions are common to the different +platforms and are defined just once in one of the header files that +make up @lightning{}, that is, @file{core-common.h}. + +Most of the macros are relatively straight-forward to implement (with +a few caveats for architectures whose assembly language only offers +two-operand arithmetic instructions). This section will cover the +tricky points, before presenting the complete listing of the macros +that make up the platform-independent interface provided by +@lightning{}. + +@menu +@standardmacrosmenu{} +@end menu + +@node Forward references +@section Implementing forward references + +Implementation of forward references takes place in: + +@itemize @bullet +@bulletize The branch macros +@bulletize The @code{jit_patch} macros +@end itemize + +Roughly speaking, the branch macros, as seen in @usingref{GNU lightning +macros, Generating code at run-time}, return a value that later calls +to @code{jit_patch} use to complete the assembly of the forward +reference. This value is usually the contents of the program counter +after the branch instruction is compiled (which is accessible in the +@code{_jit.pc} variable). Let's see an example from the x86 back-end: + +@example +#define jit_bmsr_i(label, s1, s2) \ + (TESTLrr((s1), (s2)), JNZm(label,0,0,0), _jit.pc) +@end example + +The @code{bms} (@dfn{branch if mask set}) instruction is assembled as +the combination of a @code{TEST} instruction (bit-wise @sc{and} between +the two operands) and a @code{JNZ} instruction (jump if non-zero). The +macro then returns the final value of the program counter. + +@code{jit_patch} is one of the few macros that need to possess a +knowledge of the machine's instruction formats. Its purpose is to +patch a branch instruction (identified by the value returned at the +moment the branch was compiled) to jump to the current position (that +is, to the address identified by @code{_jit.pc}). + +On the x86, the displacement between the jump and the landing point is +expressed as a 32-bit signed integer lying in the last four bytes of the +jump instruction. The definition of @code{_jit_patch} is: + +@example +#define jit_patch(jump_pc) (*_PSL((jump_pc) - 4) = \ + _jit.pc - (jump_pc)) +@end example + +The @code{_PSL} macro is nothing more than a cast to @code{long *}, +and is used here to shorten the definition and avoid cluttering it with +excessive parentheses. These type-cast macros are: + +@itemize @bullet +@bulletize @code{_PUC(X)} to cast to a @code{unsigned char *}. +@bulletize @code{_PUS(X)} to cast to a @code{unsigned short *}. +@bulletize @code{_PUI(X)} to cast to a @code{unsigned int *}. +@bulletize @code{_PSL(X)} to cast to a @code{long *}. +@bulletize @code{_PUL(X)} to cast to a @code{unsigned long *}. +@end itemize + +On other platforms, notably RISC ones, the displacement is embedded into +the instruction itself. In this case, @code{jit_patch} must first zero +out the field, and then @sc{or} in the correct displacement. The SPARC, +for example, encodes the displacement in the bottom 22 bits; in addition +the right-most two bits are suppressed, which are always zero because +instruction have to be word-aligned. + +@example +#define jit_patch(delay_pc) jit_patch_ ( ((delay_pc) - 1) ) + +@rem{/* branch instructions return the address of the @emph{delay} + * instruction---this is just a helper macro that makes the code more + * readable. + */} +#define jit_patch_(jump_pc) (*jump_pc = \ + (*jump_pc & ~_MASK(22)) | \ + ((_UL(_jit.pc) - _UL(jump_pc)) >> 2) & _MASK(22)) +@end example + +This introduces more predefined shortcut macros: +@itemize @bullet +@bulletize @code{_UC(X)} to cast to a @code{unsigned char}. +@bulletize @code{_US(X)} to cast to a @code{unsigned short}. +@bulletize @code{_UI(X)} to cast to a @code{unsigned int}. +@bulletize @code{_SL(X)} to cast to a @code{long}. +@bulletize @code{_UL(X)} to cast to a @code{unsigned long}. +@bulletize @code{_MASK(N)} gives a binary number made of N ones. +@end itemize + + +@node Common features +@section Common features supported by @file{core-common.h} + +The @file{core-common.h} file contains hundreds of macro definitions +which will spare you defining a lot of things in the files the are +specific to your port. Here is a list of the features that +@file{core-common.h} provides. + +@table @b +@item Support for common synthetic instructions +These are instructions that can be represented as a simple operation, +for example a bit-wise @sc{and} or a subtraction. @file{core-common.h} +recognizes when the port-specific header file defines these macros and +avoids compiler warnings about redefined macros, but there should be +no need to define them. They are: +@example +#define jit_extr_c_ui(d, rs) +#define jit_extr_i_ul(d, rs) +#define jit_extr_s_ui(d, rs) +#define jit_negr_i(d, rs) +#define jit_negr_l(d, rs) +@end example + +@item Support for the @sc{abi} +Both @code{jit_prolog}, @code{jit_leaf} and @code{jit_finish} are not +mandatory. If not defined, they will be defined respectively as an +empty macro, as a synonym for @code{jit_prolog}, and as a synonym for +@code{jit_calli}. Whether to define them or not in the port-specific +header file, it depends on the underlying architecture's @sc{abi}---in +general, however, you'll need to define at least @code{jit_prolog}. + +@item Support for uncommon instructions +These are instructions that many widespread architectures lack. +@file{core-common.h} is able to provide default definitions, but they +are usually inefficient if the hardware provides a way to do these +operations with a single instruction. They are extension with sign +and ``reverse subtraction'' (that is, REG2@math{=}IMM@math{-}REG1): +@example +#define jit_extr_c_i(d, rs) +#define jit_extr_s_i(d, rs) +#define jit_rsbi_i(d, rs, is) +#define jit_rsbi_l(d, rs, is) +@end example + +@item Conversion between network and host byte ordering +These macros are no-ops on big endian systems. Don't define them on +such systems; on the other hand, they are mandatory on little endian +systems. They are: +@example +#define jit_ntoh_ui(d, rs) +#define jit_ntoh_us(d, rs) +@end example + +@item Support for a ``zero'' register +Many RISC architectures provide a read-only register whose value is +hard-coded to be zero; this register is then used implicitly when +referring to a memory location using a single register. For example, +on the SPARC, an operand like @code{[%l6]} is actually assembled as +@code{[%l6+%g0]}. If this is the case, you should define +@code{JIT_RZERO} to be the number of this register; @file{core-common.h} +will use it to implement all variations of the @code{ld} and @code{st} +instructions. For example: +@example +#define jit_ldi_c(d, is) jit_ldxi_c(d, JIT_RZERO, is) +#define jit_ldr_i(d, rs) jit_ldxr_c(d, JIT_RZERO, rs) +@end example + +If available, JIT_RZERO is also used to provide more efficient +definitions of the @code{neg} instruction (see ``Support for common +synthetic instructions'', above). + +@item Synonyms +@file{core-common.h} provides a lot of trivial definitions which make +the instruction set as orthogonal as possible. For example, adding two +unsigned integers is exactly the same as adding two signed integers +(assuming a two's complement representation of negative numbers); yet, +@lightning{} provides both @code{jit_addr_i} and @code{jit_addr_ui} +macros. Similarly, pointers and unsigned long integers behave in the +same way, but @lightning{} has separate instruction for the two data +types---those that operate on pointers usually comprise a typecast +that makes programs clearer. + +@item Shortcuts +These define ``synthetic'' instructions whose definition is not as +trivial as in the case of synonyms, but is anyway standard. This +is the case for bitwise @sc{not} (which is implemented by XORing a +string of ones), ``reverse subtraction'' between registers (which is +converted to a normal subtraction with the two source operands +inverted), and subtraction of an immediate from a register (which is +converted to an addition). Unlike @code{neg} and @code{ext} (see +``Support for common synthetic instructions'', above), which are +simply non-mandatory, you must not define these functions. + +@item Support for @code{long}s +On most systems, @code{long}s and @code{unsigned long}s are the same +as, respectively, @code{int}s and @code{unsigned int}s. In this case, +@file{core-common.h} defines operations on these types to be synonyms. + +@item @code{jit_state} +Last but not least, @file{core-common.h} defines the @code{jit_state} +type. Part of this @code{struct} is machine-dependent and includes +all kinds of state needed by the back-end; this part is always +accessible in a re-entrant way as @code{_jitl}. @code{_jitl} will be +of type @code{struct jit_local_state}; this struct must be defined +even if no state is required. + +@end table + +@node Delay slots +@section Supporting scheduling of delay slots + +Delay slot scheduling is obtained by clients through the +@code{jit_delay} macro. However this macro is not to be defined +in the platform-independent layer, because @lightning{} provides +a common definition in @file{core-common.h}. + +Instead, the platform-independent layer must define another macro, +called @code{jit_fill_delay_after}, which has to exchange the +instruction to be scheduled in the delay slot with the branch +instruction. The only parameter accepted by the macro is a call +to a branch macro, which must be expanded @strong{exactly once} by +@code{jit_fill_delay_after}. The client must be able to pass the +return value of @code{jit_fill_delay_after} to @code{jit_patch}. + +There are two possible approaches that can be used in +@code{jit_fill_delay_after}. They are summarized in the following +pictures: + +@itemize @bullet +@item +The branch instructions assemble a @sc{nop} instruction which is +then removed by @code{jit_fill_delay_after}. + +@example + before | after + ---------------------------------+----------------------------- + ... | + | + | + NOP | <--- _jit.pc + <--- _jit.pc | +@end example + +@item +The branch instruction assembles the branch so that the delay +slot is annulled, @code{jit_fill_delay_after} toggles the bit: + +@example + before | after + ---------------------------------+----------------------------- + ... | + | + | + <--- _jit.pc | <--- _jit.pc +@end example +@end itemize + +Don't forget that you can take advantage of delay slots in the +implementation of boolean instructions such as @code{le} or @code{gt}. + +@node Immediate values +@section Supporting arbitrarily sized immediate values + +This is a problem that is endemic to RISC machines. The basic idea +is to reserve one or two register to represent large immediate values. +Let's see an example from the SPARC: + +@example + addi_i R0, V2, 45 | addi_i R0, V2, 10000 + ---------------------------+--------------------------- + add %l5, 45, %l0 | set 10000, %l6 + | add %l5, %l6, %l0 +@end example + +In this case, @code{%l6} is reserved to be used for large immediates. +An elegant solution is to use an internal macro which automatically +decides which version is to be compiled. + +Beware of register conflicts on machines with delay slots. This is +the case for the SPARC, where @code{%l7} is used instead for large +immediates in compare-and-branch instructions. So the sequence + +@example + jit_delay( + jit_addi_i(JIT_R0, JIT_V2, 10000), + jit_blei_i(label, JIT_R1, 20000) + ); +@end example + +@noindent +is assembled this way: + +@example + set 10000, %l6 @rem{! prepare immediate for add} + set 20000, %l7 @rem{! prepare immediate for cmp} + cmp %l1, %l7 + ble label + add %l5, %l6, %l0 @rem{! delay slot} + @end example + +Note that using @code{%l6} in the branch instruction would have given +an incorrect result---@code{R0} would have been filled with the value of +@code{V2+@i{20000}} rather than @code{V2+@i{10000}}. + +@node Implementing the ABI +@section Implementing the ABI + +Implementing the underlying architecture's @sc{abi} is done in the +macros that handle function prologs and epilogs and argument passing. + +Let's look at the prologs and epilogs first. These are usually pretty +simple and, what's more important, with constant content---that is, +they always generate exactly the same instruction sequence. Here is +an example: + +@example + SPARC x86 + save %sp, -96, %sp push %ebp + push %ebx + push %esi + push %edi + movl %esp, %ebp + ... ... + ret popl %edi + restore popl %esi + popl %ebx + popl %ebp + ret +@end example + +The registers that are saved (@code{%ebx}, @code{%esi}, @code{%edi}) are +mapped to the @code{V0} through @code{V2} registers in the @lightning{} +instruction set. + +Argument passing is more tricky. There are basically three +cases@footnote{For speed and ease of implementation, @lightning{} does not +currently support passing some of the parameters on the stack and some +in registers.}: +@table @b +@item Register windows +Output registers are different from input registers---the prolog takes +care of moving the caller's output registers to the callee's input +registers. This is the case with the SPARC. + +@item Passing parameters via registers +In this case, output registers are the same as input registers. The +program must take care of saving input parameters somewhere (on the +stack, or in non-argument registers). This is the case with the +PowerPC. + +@item All the parameters are passed on the stack +This case is by far the simplest and is the most common in CISC +architectures, like the x86 and Motorola 68000. +@end table + +In all cases, the port-specific header file will define two variable +for private use---one to be used by the caller during the +@code{prepare}/@code{pusharg}/@code{finish} sequence, one to be used +by the callee, specifically in the @code{jit_prolog} and @code{jit_arg} +macros. + +Let's look again, this time with more detail, at each of the cases. + +@table @b +@item Register windows +@code{jit_finish} is the same as @code{jit_calli}, and is defined +in @file{core-common.h} (@pxref{Common features, , Common features +supported by @file{core-common.h}}). + +@example +#define jit_prepare(numargs) (_jitl.pusharg = _Ro(numargs)) +#define jit_pusharg_i(rs) (--_jitl.pusharg, \ + MOVrr((rs), _jitl.pusharg)) +@end example + +Remember that arguments pushing takes place in reverse order, thus +giving a pre-decrement (rather than post-increment) in +@code{jit_pusharg_i}. + +Here is what happens on the callee's side: + +@example +#define jit_arg_c() (_jitl.getarg++) +#define jit_getarg_c(rd, ofs) jit_extr_c_i ((rd), (ofs)) +#define jit_prolog(numargs) (SAVErir(JIT_SP, -96, JIT_SP), \ + _jitl.getarg = _Ri(0)) +@end example + +The @code{jit_arg} macros return nothing more than a register index, +which is then used by the @code{jit_getarg} macros. @code{jit_prolog} +resets the counter used by @code{jit_arg} to zero; the @code{numargs} +parameter is not used. It is sufficient for @code{jit_leaf} to be a +synonym for @code{jit_prolog}. + +@item Passing parameter via registers +The code is almost the same as that for the register windows case, but +with an additional complexity---@code{jit_arg} will transfer the +argument from the input register to a non-argument register so that +function calls will not clobber it. The prolog and epilog code can then +become unbearably long, up to 20 instructions on the PPC; a common +solution in this case is that of @dfn{trampolines}. + +The prolog does nothing more than put the function's actual address in a +caller-preserved register and then call the trampoline: +@example + mflr r0 @rem{! grab return address} + movei r10, trampo_2args @rem{! jump to trampoline} + mtlr r10 + blrl +here: mflr r31 @rem{! r31 = address of epilog} + @rem{...actual code...} + mtlr r31 @rem{! return to the trampoline} + blr +@end example + +In this case, @code{jit_prolog} does use its argument containing the +number of parameters to pick the appropriate trampoline. Here, +@code{trampo_2args} is the address of a trampoline designed for +2-argument functions. + +The trampoline executes the prolog code, jumps to the contents of +@code{r10}, and upon return from the subroutine it executes the +epilog code. + +@item All the parameters are passed on the stack +@code{jit_pusharg} uses a hardware push operation, which is commonly +available on CISC machines (where this approach is most likely +followed). Since the stack has to be cleaned up after the call, +@code{jit_prepare} remembers how many parameters have been put there, +and @code{jit_finish} adjusts the stack pointer after the call. + +@example +#define jit_prepare(numargs) (_jitl.args += (numargs)) +#define jit_pusharg_i(rs) PUSHLr(rs) +#define jit_finish(sub) (jit_calli((sub)), \ + ADDLir(4 * _jitl.args, JIT_SP), \ + _jitl.numargs = 0) +@end example + +Note the usage of @code{+=} in @code{jit_prepare}. This is done +so that one can defer the popping of the arguments that were saved +on the stack (@dfn{stack pollution}). To do so, it is sufficient to +use @code{jit_calli} instead of @code{jit_finish} in all but the +last call. + +On the caller's side, @code{arg} returns an offset relative to the +frame pointer, and @code{getarg} loads the argument from the stack: + +@example +#define jit_getarg_c(rd, ofs) jit_ldxi_c((rd), _EBP, (ofs)); +#define jit_arg_c() ((_jitl.frame += sizeof(int) \ + - sizeof(int)) +@end example + +The @code{_jitl.frame} variable is initialized by @code{jit_prolog} +with the displacement between the value of the frame pointer +(@code{%ebp}) and the address of the first parameter. +@end table + +These schemes are the most used, so @file{core-common.h} provides a way +to employ them automatically. If you do not define the +@code{jit_getarg_c} macro and its companions, @file{core-common.h} will +presume that you intend to pass parameters through either the registers +or the stack. + +If you define @code{JIT_FP}, stack-based parameter passing will be +employed and the @code{jit_getarg} macros will be defined like this: + +@example +#define jit_getarg_c(reg, ofs) jit_ldxi_c((reg), JIT_FP, (ofs)); +@end example + +In other words, the @code{jit_arg} macros (which are still to be defined +by the platform-specific back-end) shall return an offset into the stack +frame. On the other hand, if you don't define @code{JIT_FP}, +register-based parameter passing will be employed and the @code{jit_arg} +macros shall return a register number; in this case, @code{jit_getarg} +will be implemented in terms of @code{jit_extr} and @code{jit_movr} +operations: + +@example +#define jit_getarg_c(reg, ofs) jit_extr_c_i ((reg), (ofs)) +#define jit_getarg_i(reg, ofs) jit_movr_i ((reg), (ofs)) +@end example + + +@node Macro list +@section Macros composing the platform-independent layer + +@table @b +@item Register names (all mandatory but the last two) +@example +#define JIT_R0 +#define JIT_R1 +#define JIT_R2 +#define JIT_V0 +#define JIT_V1 +#define JIT_V2 +#define JIT_SP +#define JIT_FP +#define JIT_RZERO +@end example + +@item Helper macros (non-mandatory): +@example +#define jit_fill_delay_after(branch) +@end example + +@item Mandatory: +@example +#define jit_arg_c() +#define jit_arg_i() +#define jit_arg_l() +#define jit_arg_p() +#define jit_arg_s() +#define jit_arg_uc() +#define jit_arg_ui() +#define jit_arg_ul() +#define jit_arg_us() +#define jit_addi_i(d, rs, is) +#define jit_addr_i(d, s1, s2) +#define jit_addxi_i(d, rs, is) +#define jit_addxr_i(d, s1, s2) +#define jit_andi_i(d, rs, is) +#define jit_andr_i(d, s1, s2) +#define jit_beqi_i(label, rs, is) +#define jit_beqr_i(label, s1, s2) +#define jit_bgei_i(label, rs, is) +#define jit_bgei_ui(label, rs, is) +#define jit_bger_i(label, s1, s2) +#define jit_bger_ui(label, s1, s2) +#define jit_bgti_i(label, rs, is) +#define jit_bgti_ui(label, rs, is) +#define jit_bgtr_i(label, s1, s2) +#define jit_bgtr_ui(label, s1, s2) +#define jit_blei_i(label, rs, is) +#define jit_blei_ui(label, rs, is) +#define jit_bler_i(label, s1, s2) +#define jit_bler_ui(label, s1, s2) +#define jit_blti_i(label, rs, is) +#define jit_blti_ui(label, rs, is) +#define jit_bltr_i(label, s1, s2) +#define jit_bltr_ui(label, s1, s2) +#define jit_boaddi_i(label, rs, is) +#define jit_boaddi_ui(label, rs, is) +#define jit_boaddr_i(label, s1, s2) +#define jit_boaddr_ui(label, s1, s2) +#define jit_bosubi_i(label, rs, is) +#define jit_bosubi_ui(label, rs, is) +#define jit_bosubr_i(label, s1, s2) +#define jit_bosubr_ui(label, s1, s2) +#define jit_bmci_i(label, rs, is) +#define jit_bmcr_i(label, s1, s2) +#define jit_bmsi_i(label, rs, is) +#define jit_bmsr_i(label, s1, s2) +#define jit_bnei_i(label, rs, is) +#define jit_bner_i(label, s1, s2) +#define jit_calli(label) +#define jit_divi_i(d, rs, is) +#define jit_divi_ui(d, rs, is) +#define jit_divr_i(d, s1, s2) +#define jit_divr_ui(d, s1, s2) +#define jit_eqi_i(d, rs, is) +#define jit_eqr_i(d, s1, s2) +#define jit_gei_i(d, rs, is) +#define jit_gei_ui(d, s1, s2) +#define jit_ger_i(d, s1, s2) +#define jit_ger_ui(d, s1, s2) +#define jit_gti_i(d, rs, is) +#define jit_gti_ui(d, s1, s2) +#define jit_gtr_i(d, s1, s2) +#define jit_gtr_ui(d, s1, s2) +#define jit_hmuli_i(d, rs, is) +#define jit_hmuli_ui(d, rs, is) +#define jit_hmulr_i(d, s1, s2) +#define jit_hmulr_ui(d, s1, s2) +#define jit_jmpi(label) +#define jit_jmpr(reg) +#define jit_ldxi_c(d, rs, is) +#define jit_ldxi_i(d, rs, is) +#define jit_ldxi_s(d, rs, is) +#define jit_ldxi_uc(d, rs, is) +#define jit_ldxi_us(d, rs, is) +#define jit_ldxr_c(d, s1, s2) +#define jit_ldxr_i(d, s1, s2) +#define jit_ldxr_s(d, s1, s2) +#define jit_ldxr_uc(d, s1, s2) +#define jit_ldxr_us(d, s1, s2) +#define jit_lei_i(d, rs, is) +#define jit_lei_ui(d, s1, s2) +#define jit_ler_i(d, s1, s2) +#define jit_ler_ui(d, s1, s2) +#define jit_lshi_i(d, rs, is) +#define jit_lshr_i(d, r1, r2) +#define jit_lti_i(d, rs, is) +#define jit_lti_ui(d, s1, s2) +#define jit_ltr_i(d, s1, s2) +#define jit_ltr_ui(d, s1, s2) +#define jit_modi_i(d, rs, is) +#define jit_modi_ui(d, rs, is) +#define jit_modr_i(d, s1, s2) +#define jit_modr_ui(d, s1, s2) +#define jit_movi_i(d, is) +#define jit_movr_i(d, rs) +#define jit_muli_i(d, rs, is) +#define jit_muli_ui(d, rs, is) +#define jit_mulr_i(d, s1, s2) +#define jit_mulr_ui(d, s1, s2) +#define jit_nei_i(d, rs, is) +#define jit_ner_i(d, s1, s2) +#define jit_nop() +#define jit_ori_i(d, rs, is) +#define jit_orr_i(d, s1, s2) +#define jit_patch(jump_pc) +#define jit_pop_i(rs) +#define jit_prepare(numargs) +#define jit_push_i(rs) +#define jit_pusharg_i(rs) +#define jit_ret() +#define jit_retval_i(rd) +#define jit_rshi_i(d, rs, is) +#define jit_rshi_ui(d, rs, is) +#define jit_rshr_i(d, r1, r2) +#define jit_rshr_ui(d, r1, r2) +#define jit_stxi_c(rd, id, rs) +#define jit_stxi_i(rd, id, rs) +#define jit_stxi_s(rd, id, rs) +#define jit_stxr_c(d1, d2, rs) +#define jit_stxr_i(d1, d2, rs) +#define jit_stxr_s(d1, d2, rs) +#define jit_subr_i(d, s1, s2) +#define jit_subxi_i(d, rs, is) +#define jit_subxr_i(d, s1, s2) +#define jit_xori_i(d, rs, is) +#define jit_xorr_i(d, s1, s2) +@end example + +@item Non mandatory---there should be no need to define them: +@example +#define jit_extr_c_ui(d, rs) +#define jit_extr_i_ul(d, rs) +#define jit_extr_s_ui(d, rs) +#define jit_negr_i(d, rs) +#define jit_negr_l(d, rs) +@end example + +@item Non mandatory---whether to define them depends on the @sc{abi}: +@example +#define jit_prolog() +#define jit_finish() +#define jit_leaf() +#define jit_getarg_c(reg, ofs) +#define jit_getarg_i(reg, ofs) +#define jit_getarg_l(reg, ofs) +#define jit_getarg_p(reg, ofs) +#define jit_getarg_s(reg, ofs) +#define jit_getarg_uc(reg, ofs) +#define jit_getarg_ui(reg, ofs) +#define jit_getarg_ul(reg, ofs) +#define jit_getarg_us(reg, ofs) +@end example + +@item Non mandatory---define them if instructions that do this exist: +@example +#define jit_extr_c_i(d, rs) +#define jit_extr_s_i(d, rs) +#define jit_rsbi_i(d, rs, is) +#define jit_rsbi_l(d, rs, is) +@end example + +@item Non mandatory if condition code are always set by add/sub, needed on other systems: +@example +#define jit_addci_i(d, rs, is) +#define jit_addci_l(d, rs, is) +#define jit_subci_i(d, rs, is) +#define jit_subci_l(d, rs, is) +@end example + +@item Mandatory on little endian systems---don't define them on other systems: +@example +#define jit_ntoh_ui(d, rs) +#define jit_ntoh_us(d, rs) +@end example + +@item Mandatory if JIT_RZERO not defined---don't define them if it is defined: +@example +#define jit_ldi_c(d, is) +#define jit_ldi_i(d, is) +#define jit_ldi_s(d, is) +#define jit_ldr_c(d, rs) +#define jit_ldr_i(d, rs) +#define jit_ldr_s(d, rs) +#define jit_ldi_uc(d, is) +#define jit_ldi_ui(d, is) +#define jit_ldi_ul(d, is) +#define jit_ldi_us(d, is) +#define jit_ldr_uc(d, rs) +#define jit_ldr_ui(d, rs) +#define jit_ldr_ul(d, rs) +#define jit_ldr_us(d, rs) +#define jit_sti_c(id, rs) +#define jit_sti_i(id, rs) +#define jit_sti_s(id, rs) +#define jit_str_c(rd, rs) +#define jit_str_i(rd, rs) +#define jit_str_s(rd, rs) +@end example + +@item Synonyms---don't define them: +@example +#define jit_addi_p(d, rs, is) +#define jit_addi_ui(d, rs, is) +#define jit_addi_ul(d, rs, is) +#define jit_addr_p(d, s1, s2) +#define jit_addr_ui(d, s1, s2) +#define jit_addr_ul(d, s1, s2) +#define jit_andi_ui(d, rs, is) +#define jit_andi_ul(d, rs, is) +#define jit_andr_ui(d, s1, s2) +#define jit_andr_ul(d, s1, s2) +#define jit_beqi_p(label, rs, is) +#define jit_beqi_ui(label, rs, is) +#define jit_beqi_ul(label, rs, is) +#define jit_beqr_p(label, s1, s2) +#define jit_beqr_ui(label, s1, s2) +#define jit_beqr_ul(label, s1, s2) +#define jit_bmci_ui(label, rs, is) +#define jit_bmci_ul(label, rs, is) +#define jit_bmcr_ui(label, s1, s2) +#define jit_bmcr_ul(label, s1, s2) +#define jit_bmsi_ui(label, rs, is) +#define jit_bmsi_ul(label, rs, is) +#define jit_bmsr_ui(label, s1, s2) +#define jit_bmsr_ul(label, s1, s2) +#define jit_bgei_p(label, rs, is) +#define jit_bger_p(label, s1, s2) +#define jit_bgti_p(label, rs, is) +#define jit_bgtr_p(label, s1, s2) +#define jit_blei_p(label, rs, is) +#define jit_bler_p(label, s1, s2) +#define jit_blti_p(label, rs, is) +#define jit_bltr_p(label, s1, s2) +#define jit_bnei_p(label, rs, is) +#define jit_bnei_ui(label, rs, is) +#define jit_bnei_ul(label, rs, is) +#define jit_bner_p(label, s1, s2) +#define jit_bner_ui(label, s1, s2) +#define jit_bner_ul(label, s1, s2) +#define jit_eqi_p(d, rs, is) +#define jit_eqi_ui(d, rs, is) +#define jit_eqi_ul(d, rs, is) +#define jit_eqr_p(d, s1, s2) +#define jit_eqr_ui(d, s1, s2) +#define jit_eqr_ul(d, s1, s2) +#define jit_extr_uc_i(d, rs) +#define jit_extr_uc_ui(d, rs) +#define jit_extr_ui_l(d, rs) +#define jit_extr_ui_l(d, rs) +#define jit_extr_ui_ul(d, rs) +#define jit_extr_ui_ul(d, rs) +#define jit_extr_us_i(d, rs) +#define jit_extr_us_ui(d, rs) +#define jit_gei_p(d, rs, is) +#define jit_ger_p(d, s1, s2) +#define jit_gti_p(d, rs, is) +#define jit_gtr_p(d, s1, s2) +#define jit_ldr_p(d, rs) +#define jit_ldi_p(d, is) +#define jit_ldxi_p(d, rs, is) +#define jit_ldxr_p(d, s1, s2) +#define jit_lei_p(d, rs, is) +#define jit_ler_p(d, s1, s2) +#define jit_lshi_ui(d, rs, is) +#define jit_lshi_ul(d, rs, is) +#define jit_lshr_ui(d, s1, s2) +#define jit_lshr_ul(d, s1, s2) +#define jit_lti_p(d, rs, is) +#define jit_ltr_p(d, s1, s2) +#define jit_movi_p(d, is) +#define jit_movi_ui(d, rs) +#define jit_movi_ul(d, rs) +#define jit_movr_p(d, rs) +#define jit_movr_ui(d, rs) +#define jit_movr_ul(d, rs) +#define jit_nei_p(d, rs, is) +#define jit_nei_ui(d, rs, is) +#define jit_nei_ul(d, rs, is) +#define jit_ner_p(d, s1, s2) +#define jit_ner_ui(d, s1, s2) +#define jit_ner_ul(d, s1, s2) +#define jit_hton_ui(d, rs) +#define jit_hton_us(d, rs) +#define jit_ori_ui(d, rs, is) +#define jit_ori_ul(d, rs, is) +#define jit_orr_ui(d, s1, s2) +#define jit_orr_ul(d, s1, s2) +#define jit_pop_ui(rs) +#define jit_pop_ul(rs) +#define jit_push_ui(rs) +#define jit_push_ul(rs) +#define jit_pusharg_c(rs) +#define jit_pusharg_p(rs) +#define jit_pusharg_s(rs) +#define jit_pusharg_uc(rs) +#define jit_pusharg_ui(rs) +#define jit_pusharg_ul(rs) +#define jit_pusharg_us(rs) +#define jit_retval_c(rd) +#define jit_retval_p(rd) +#define jit_retval_s(rd) +#define jit_retval_uc(rd) +#define jit_retval_ui(rd) +#define jit_retval_ul(rd) +#define jit_retval_us(rd) +#define jit_rsbi_ui(d, rs, is) +#define jit_rsbi_ul(d, rs, is) +#define jit_rsbr_ui(d, s1, s2) +#define jit_rsbr_ul(d, s1, s2) +#define jit_sti_p(d, is) +#define jit_sti_uc(d, is) +#define jit_sti_ui(d, is) +#define jit_sti_ul(d, is) +#define jit_sti_us(d, is) +#define jit_str_p(d, rs) +#define jit_str_uc(d, rs) +#define jit_str_ui(d, rs) +#define jit_str_ul(d, rs) +#define jit_str_us(d, rs) +#define jit_stxi_p(d, rs, is) +#define jit_stxi_uc(d, rs, is) +#define jit_stxi_ui(d, rs, is) +#define jit_stxi_ul(d, rs, is) +#define jit_stxi_us(d, rs, is) +#define jit_stxr_p(d, s1, s2) +#define jit_stxr_uc(d, s1, s2) +#define jit_stxr_ui(d, s1, s2) +#define jit_stxr_ul(d, s1, s2) +#define jit_stxr_us(d, s1, s2) +#define jit_subi_p(d, rs, is) +#define jit_subi_ui(d, rs, is) +#define jit_subi_ul(d, rs, is) +#define jit_subr_p(d, s1, s2) +#define jit_subr_ui(d, s1, s2) +#define jit_subr_ul(d, s1, s2) +#define jit_xori_ui(d, rs, is) +#define jit_xori_ul(d, rs, is) +#define jit_xorr_ui(d, s1, s2) +#define jit_xorr_ul(d, s1, s2) +@end example + +@item Shortcuts---don't define them: +@example +#define jit_notr_c(d, rs) +#define jit_notr_i(d, rs) +#define jit_notr_l(d, rs) +#define jit_notr_s(d, rs) +#define jit_notr_uc(d, rs) +#define jit_notr_ui(d, rs) +#define jit_notr_ul(d, rs) +#define jit_notr_us(d, rs) +#define jit_rsbr_i(d, s1, s2) +#define jit_rsbr_l(d, s1, s2) +#define jit_subi_i(d, rs, is) +#define jit_subi_l(d, rs, is) +@end example + +@item Mandatory if sizeof(long) != sizeof(int)---don't define them on other systems: +@example +#define jit_addi_l(d, rs, is) +#define jit_addr_l(d, s1, s2) +#define jit_andi_l(d, rs, is) +#define jit_andr_l(d, s1, s2) +#define jit_beqi_l(label, rs, is) +#define jit_beqr_l(label, s1, s2) +#define jit_bgei_l(label, rs, is) +#define jit_bgei_ul(label, rs, is) +#define jit_bger_l(label, s1, s2) +#define jit_bger_ul(label, s1, s2) +#define jit_bgti_l(label, rs, is) +#define jit_bgti_ul(label, rs, is) +#define jit_bgtr_l(label, s1, s2) +#define jit_bgtr_ul(label, s1, s2) +#define jit_blei_l(label, rs, is) +#define jit_blei_ul(label, rs, is) +#define jit_bler_l(label, s1, s2) +#define jit_bler_ul(label, s1, s2) +#define jit_blti_l(label, rs, is) +#define jit_blti_ul(label, rs, is) +#define jit_bltr_l(label, s1, s2) +#define jit_bltr_ul(label, s1, s2) +#define jit_bosubi_l(label, rs, is) +#define jit_bosubi_ul(label, rs, is) +#define jit_bosubr_l(label, s1, s2) +#define jit_bosubr_ul(label, s1, s2) +#define jit_boaddi_l(label, rs, is) +#define jit_boaddi_ul(label, rs, is) +#define jit_boaddr_l(label, s1, s2) +#define jit_boaddr_ul(label, s1, s2) +#define jit_bmci_l(label, rs, is) +#define jit_bmcr_l(label, s1, s2) +#define jit_bmsi_l(label, rs, is) +#define jit_bmsr_l(label, s1, s2) +#define jit_bnei_l(label, rs, is) +#define jit_bner_l(label, s1, s2) +#define jit_divi_l(d, rs, is) +#define jit_divi_ul(d, rs, is) +#define jit_divr_l(d, s1, s2) +#define jit_divr_ul(d, s1, s2) +#define jit_eqi_l(d, rs, is) +#define jit_eqr_l(d, s1, s2) +#define jit_gei_l(d, rs, is) +#define jit_gei_ul(d, rs, is) +#define jit_ger_l(d, s1, s2) +#define jit_ger_ul(d, s1, s2) +#define jit_gti_l(d, rs, is) +#define jit_gti_ul(d, rs, is) +#define jit_gtr_l(d, s1, s2) +#define jit_gtr_ul(d, s1, s2) +#define jit_hmuli_l(d, rs, is) +#define jit_hmuli_ul(d, rs, is) +#define jit_hmulr_l(d, s1, s2) +#define jit_hmulr_ul(d, s1, s2) +#define jit_ldi_l(d, is) +#define jit_ldi_ui(d, is) +#define jit_ldr_l(d, rs) +#define jit_ldr_ui(d, rs) +#define jit_ldxi_l(d, rs, is) +#define jit_ldxi_ui(d, rs, is) +#define jit_ldxi_ul(d, rs, is) +#define jit_ldxr_l(d, s1, s2) +#define jit_ldxr_ui(d, s1, s2) +#define jit_ldxr_ul(d, s1, s2) +#define jit_lei_l(d, rs, is) +#define jit_lei_ul(d, rs, is) +#define jit_ler_l(d, s1, s2) +#define jit_ler_ul(d, s1, s2) +#define jit_lshi_l(d, rs, is) +#define jit_lshr_l(d, s1, s2) +#define jit_lti_l(d, rs, is) +#define jit_lti_ul(d, rs, is) +#define jit_ltr_l(d, s1, s2) +#define jit_ltr_ul(d, s1, s2) +#define jit_modi_l(d, rs, is) +#define jit_modi_ul(d, rs, is) +#define jit_modr_l(d, s1, s2) +#define jit_modr_ul(d, s1, s2) +#define jit_movi_l(d, rs) +#define jit_movr_l(d, rs) +#define jit_muli_l(d, rs, is) +#define jit_muli_ul(d, rs, is) +#define jit_mulr_l(d, s1, s2) +#define jit_mulr_ul(d, s1, s2) +#define jit_nei_l(d, rs, is) +#define jit_ner_l(d, s1, s2) +#define jit_ori_l(d, rs, is) +#define jit_orr_l(d, s1, s2) +#define jit_pop_l(rs) +#define jit_push_l(rs) +#define jit_pusharg_l(rs) +#define jit_retval_l(rd) +#define jit_rshi_l(d, rs, is) +#define jit_rshi_ul(d, rs, is) +#define jit_rshr_l(d, s1, s2) +#define jit_rshr_ul(d, s1, s2) +#define jit_sti_l(d, is) +#define jit_str_l(d, rs) +#define jit_stxi_l(d, rs, is) +#define jit_stxr_l(d, s1, s2) +#define jit_subr_l(d, s1, s2) +#define jit_xori_l(d, rs, is) +#define jit_xorr_l(d, s1, s2) +@end example +@end table + +@node Standard functions +@chapter More complex tasks in the platform-independent layer + +There is actually a single function that you @strong{must} define +in the @file{funcs-@var{suffix}.h} file, that is, @code{jit_flush_code}. + +As explained in @usingref{GNU lightning macros, Generating code at +run-time}, its purpose is to flush part of the processor's +instruction cache (usually the part of memory that contains the +generated code), avoiding the processor executing bogus data +that it happens to find in the cache. The @code{jit_flush_code} +function takes the first and the last address to flush. + +On many processors (for example, the x86 and the all the processors +in the 68k family up to the 68030), it is not even necessary to flush +the cache. In this case, the contents of the file will simply be + +@example +#ifndef __lightning_funcs_h +#define __lightning_funcs_h + +#define jit_flush_code(dest, end) + +#endif @rem{/* __lightning_core_h */} +@end example + +On other processors, flushing the cache is necessary for +proper behavior of the program; in this case, the file will contain +a proper definition of the function. However, we must make yet +another distinction. + +On some processors, flushing the cache is obtained through a call +to the operating system or to the C run-time library. In this case, +the definition of @code{jit_flush_code} will be very simple: two +examples are the Alpha and the 68040. For the Alpha the code will +be: +@example +#define jit_flush_code(dest, end) \ + __asm__ __volatile__("call_pal 0x86"); +@end example + +@noindent +and, for the Motorola +@example +#define jit_flush_code(start, end) \ + __clear_cache((start), (end)) +@end example + +As you can see, the Alpha does not even need to pass the start and +end address to the function. It is good practice to protect usage of +the @acronym{GNU CC}-specific @code{__asm__} directive by relying +on the preprocessor. For example: + +@example +#if !defined(__GNUC__) && !defined(__GNUG__) +#error Go get GNU C, I do not know how to flush the cache +#error with this compiler. +#else +#define jit_flush_code(dest, end) \ + __asm__ __volatile__("call_pal 0x86"); +#endif +@end example + +@lightning{}'s configuration process tries to compile a dummy file that +includes @code{lightning.h}, and gives a warning if there are problem +with the compiler that is installed on the system. + +In more complex cases, you'll need to write a full-fledged function. +Don't forget to make it @code{static}, otherwise you'll have problems +linking programs that include @code{lightning.h} multiple times. An +example, taken from the @file{funcs-ppc.h} file, is: + +@example +#ifndef __lightning_funcs_h +#define __lightning_funcs_h + +#if !defined(__GNUC__) && !defined(__GNUG__) +#error Go get GNU C, I do not know how to flush the cache +#error with this compiler. +#else +static void +jit_flush_code(start, end) + void *start; + void *end; +@{ + register char *dest = start; + + for (; dest <= end; dest += SIZEOF_CHAR_P) + __asm__ __volatile__ + ("dcbst 0,%0; sync; icbi 0,%0; isync"::"r"(dest)); +@} +#endif + +#endif /* __lightning_funcs_h */ +@end example + +The @file{funcs-@var{suffix}.h} file is also the right place to put +helper functions that do complex tasks for the +@file{core-@var{suffix}.h} file. For example, the PowerPC assembler +defines @code{jit_prolog} as a function and puts it in that file (for more +information, @pxref{Implementing the ABI}). Take special care when +defining such a function, as explained in @usingref{Reentrancy, +Reentrant usage of @lightning{}}. + + +@node Floating-point macros +@chapter Implementing macros for floating point + diff --git a/doc/toc.texi b/doc/toc.texi new file mode 100644 index 000000000..8a3702291 --- /dev/null +++ b/doc/toc.texi @@ -0,0 +1,77 @@ +@c These macros are used because these items could go both in the +@c short listing (for partial books) and in the detailed listing +@c (for full books - i.e. using & porting) + +@macro usingmenu{} +@ifset USING +* Installation:: Configuring and installing GNU lightning +* The instruction set:: The RISC instruction set used i GNU lightning +* GNU lightning macros:: GNU lightning's macros +* Floating-point:: Doing floating point computations. +* Reentrancy:: Re-entrant usage of GNU lightning +* Autoconf support:: Using @code{autoconf} with GNU lightning +@end ifset +@end macro + +@macro portingmenu{} +@ifset PORTING +* Structure of a port:: An overview of the porting process +* Adjusting configure:: Automatically recognizing the new platform +* Run-time assemblers:: An internal layer to simplify porting +* Standard macros:: The platform-independent layer used by clients. +* Standard functions:: Doing more complex tasks. +* Floating-point macros:: Implementing macros for floating point. +@end ifset +@end macro + +@macro standardmacrosmenu{} +@c This comment is needed because of makeinfo's vagaries... +* Forward references:: Implementing forward references +* Common features:: Common features supported by @file{core-common.h} +* Delay slots:: Supporting scheduling of delay slots +* Immediate values:: Supporting arbitrarily sized immediate values +* Implementing the ABI:: Function prologs and epilogs, and argument passing +* Macro list:: Macros composing the platform-independent layer +@end macro + +@menu +@ifclear BOTH +* Overview:: What GNU lightning is +@usingmenu{} +@portingmenu{} +* Future:: Tasks for GNU lightning's subsequent releases +* Acknowledgements:: Acknowledgements for GNU lightning + +@ifset PORTING +@detailmenu +--- The detailed node listing --- + +Standard macros: +@standardmacrosmenu{} +@end detailmenu +@end ifset +@end ifclear + +@ifset BOTH +* Overview:: What GNU lightning is. +* Using GNU lightning:: Using GNU lightning in your programs +* Porting GNU lightning:: Retargeting GNU lightning to a new system +* Future:: Tasks for GNU lightning's subsequent releases +* Acknowledgements:: Acknowledgements for GNU lightning + +@detailmenu +--- The detailed node listing --- + +Using @lightning{}: +@usingmenu{} + +Porting @lightning{}: +@portingmenu{} + +Standard macros: +@standardmacrosmenu{} +@end detailmenu + +@end ifset + +@end menu diff --git a/doc/using.texi b/doc/using.texi new file mode 100644 index 000000000..a65a048e5 --- /dev/null +++ b/doc/using.texi @@ -0,0 +1,1086 @@ +@node Installation +@chapter Configuring and installing @lightning{} + +The first thing to do to use @lightning{} is to configure the +program, picking the set of macros to be used on the host +architecture; this configuration is automatically performed by +the @file{configure} shell script; to run it, merely type: +@example + ./configure +@end example + +@lightning{} supports cross-compiling in that you can choose a +different set of macros from the one needed on the computer that +you are compiling @lightning{} on. For example, +@example + ./configure --host=sparc-sun-linux +@end example + +@noindent will select the SPARC set of runtime assemblers. You can use +configure's ability to make reasonable assumptions about the vendor +and operating system and simply type +@example + ./configure --host=i386 + ./configure --host=ppc + ./configure --host=sparc +@end example + +Another option that @file{configure} accepts is +@code{--enable-assertions}, which enables several consistency checks in +the run-time assemblers. These are not usually needed, so you can +decide to simply forget about it; also remember that these consistency +checks tend to slow down your code generator. + +After you've configured @lightning{}, you don't have to compile it +because it is nothing more than a set of include files. If you want to +compile the examples, run @file{make} as usual. The next important +step is: +@example + make install +@end example + +This ends the process of installing @lightning{}. + +@node The instruction set +@chapter @lightning{}'s instruction set + +@lightning{}'s instruction set was designed by deriving instructions +that closely match those of most existing RISC architectures, or +that can be easily syntesized if absent. Each instruction is composed +of: +@itemize @bullet +@bulletize an operation (like @code{sub} or @code{mul}) +@bulletize sometimes, an register/immediate flag (@code{r} or @code{i}) +@bulletize a type identifier (occasionally, two) +@end itemize + +The second and third field are separated by an underscore; thus, +examples of legal mnemonics are @code{addr_i} (integer add, with three +register operands) and @code{muli_l} (long integer multiply, with two +register operands and an immediate operand). Each instruction takes +two or three operands; in most cases, one of them can be an immediate +value instead of a register. + +@lightning{} supports a full range of integer types: operands can be 1, +2 or 4 bytes long (64-bit architectures might support 8 bytes long +operands), either signed or unsigned. The types are listed in the +following table together with the C types they represent: + +@example + c @r{signed char} + uc @r{unsigned char} + s @r{short} + us @r{unsigned short} + i @r{int} + ui @r{unsigned int} + l @r{long} + ul @r{unsigned long} + p @r{void *} +@end example + +Some of these types may not be distinct: for example, (e.g., @code{l} +is equivalent to @code{i} on 32-bit machines, and @code{p} is +substantially equivalent to @code{ul}). + +There are seven registers, of which six are general-purpose, while +the last is used to contain the stack pointer (@code{SP}). The +stack pointer can be used to allocate and access local variables +on the stack (which is supposed to grow downwards in memory on all +architectures). + +Of the six general-purpose registers, three are guaranteed to be +preserved across function calls (@code{V0}, @code{V1} and +@code{V2}) and three are not (@code{R0}, @code{R1} and +@code{R2}).@footnote{Six registers are not very much, but this +restriction was forced by the need to target CISC architectures +which, like the x86, are poor of registers. Anyway, consider +that even on a RISC architecture you don't have many more registers +which are not devoted to function calls: on the SPARC, you have nine +(@code{%g1} and the eight registers @code{%l0} through @code{%l7}).} + +In addition, there is a special @code{RET} register which contains +the return value. You should always remember, however, that writing +this register could overwrite either a general-purpose register or +an incoming parameter, depending on the architecture. + +The complete instruction set follows; as you can see, most non-memory +operations only take integers, long integers (either signed or +unsigned) and pointers as operands; this was done in order to reduce +the instruction set, and because most architectures only provide word +and long word operations on registers. There are instructions that +allow operands to be extended to fit a larger data type, both in a +signed and in an unsigned way. + +@table @b +@item Binary ALU operations +These accept three operands, of which the last can be an immediate +value. @code{addx} operations must directly follow @code{addc}, and +@code{subx} must follow @code{subc}; otherwise, results are undefined. +@example +addr/addi i ui l ul p O1 = O2 + O3 +addxr/addxi i ui l ul O1 = O2 + (O3 + carry) +addcr/addci i ui l ul O1 = O2 + O3, set carry +subr/subi i ui l ul p O1 = O2 - O3 +subxr/subxi i ui l ul O1 = O2 - (O3 + carry) +subcr/subci i ui l ul O1 = O2 - O3, set carry +rsbr/rsbi i ui l ul p O1 = O3 - O2 +mulr/muli i ui l ul O1 = O2 * O3 +hmulr/hmuli i ui l ul O1 = @r{high bits of} O2 * O3 +divr/divi i ui l ul O1 = O2 / O3 +modr/modi i ui l ul O1 = O2 % O3 +andr/andi i ui l ul O1 = O2 & O3 +orr/ori i ui l ul O1 = O2 | O3 +xorr/xori i ui l ul O1 = O2 ^ O3 +lshr/lshi i ui l ul O1 = O2 << O3 +rshr/rshi i ui l ul O1 = O2 >> O3@footnote{The sign bit is propagated for signed types.} +@end example + +@item Unary ALU operations +These accept two operands, both of which must be registers. +@example +negr i l O1 = -O2 +notr i ui l ul O1 = ~O2 +@end example + +@item Compare instructions +These accept three operands, of which the last can be an immediate +value. The last two operands are compared, and the first operand is +set to either 0 or 1, according to whether the given condition was +met or not. + +@example +ltr/lti i ui l ul p O1 = (O2 < O3) +ler/lei i ui l ul p O1 = (O2 <= O3) +gtr/gti i ui l ul p O1 = (O2 > O3) +ger/gei i ui l ul p O1 = (O2 >= O3) +eqr/eqi i ui l ul p O1 = (O2 == O3) +ner/nei i ui l ul p O1 = (O2 != O3) +@end example + +@item Transfer operations +These accept two operands; for @code{ext} both of them must be +registers, while @code{mov} accepts an immediate value as the second +operand. @code{ext} needs @strong{two} data type specifications, of +which the first must be smaller in size than the second; for example +@code{extr_c_ui} is correct while @code{extr_ul_us} is not. +@example +movr/movi i ui l ul p O1 = O2 +extr c uc s us i ui l ul O1 = O2@footnote{Unlike @code{movr} and @code{movi}, @code{extr} is applied between operands of different sizes.} +@end example + +@item Network extensions +These accept two operands, both of which must be registers; these +two instructions actually perform the same task, yet they are +assigned to two mnemonics for the sake of convenience and +completeness. As usual, the first operand is the destination and +the second is the source. +@example +hton us ui @r{Host-to-network (big endian) order} +ntoh us ui @r{Network-to-host order } +@end example + +@item Load operations +@code{ld} accepts two operands while @code{ldx} accepts three; +in both cases, the last can be either a register or an immediate +value. Values are extended (with or without sign, according to +the data type specification) to fit a whole register. +@example +ldr/ldi c uc s us i ui l ul p O1 = *O2 +ldxr/ldxi c uc s us i ui l ul p O1 = *(O2+O3) +@end example + +@item Store operations +@code{st} accepts two operands while @code{stx} accepts three; in +both cases, the first can be either a register or an immediate +value. Values are sign-extended to fit a whole register. +@example +str/sti c uc s us i ui l ul p *O1 = O2 +stxr/stxi c uc s us i ui l ul p *(O1+O2) = O3 +@end example + +@item Stack management +These accept a single register parameter. These operations are not +guaranteed to be efficient on all architectures. + +@example +pushr i ui l ul p @r{push }O1@r{ on the stack} +popr i ui l ul p @r{pop }O1@r{ off the stack} +@end example + +@item Argument management +These are: +@example +prepare (not specified) +pusharg c uc s us i ui l ul p +getarg c uc s us i ui l ul p +arg c uc s us i ui l ul p +@end example + +Of these, the first two are used by the caller, while the last two +are used by the callee. A code snippet that wants to call another +procedure and has to pass registers must, in order: use the +@code{prepare} instruction, giving the number of arguments to +be passed to the procedure; use @code{pusharg} to push the arguments +@strong{in reverse order}; and use @code{calli} or @code{finish} +(explained below) to perform the actual call. + +@code{arg} and @code{getarg} are used by the callee. +@code{arg} is different from other instruction in that it does not +actually generate any code: instead, it is a function which returns +a value to be passed to @code{getarg}.@footnote{``Return a +value'' means that @lightning{} macros that compile these +instructions return a value when expanded.} You should call +@code{arg} as soon as possible, before any function call or, more +easily, right after the @code{prolog} or @code{leaf} instructions +(which are treated later). + +@code{getarg} accepts a register argument and a value returned by +@code{arg}, and will move that argument to the register, extending +it (with or without sign, according to the data type specification) +to fit a whole register. These instructions are more intimately +related to the usage of the @lightning{} instruction set in code +that generates other code, so they will be treated more +specifically in @ref{GNU lightning macros, , Generating code at +run-time}. + +You should observe a few rules when using these macros. First of +all, it is not allowed to call functions with more than six arguments; +this was done to simplify and speed up the implementation on +architectures that use registers for parameter passing. + +You should not nest calls to @code{prepare}, nor call zero-argument +functions (which do not need a call to @code{prepare}) inside a +@code{prepare/calli} or @code{prepare/finish} block. Doing this +might corrupt already pushed arguments. + +You @strong{cannot} pass parameters between subroutines using +the six general-purpose registers. This might work only when +targeting particular architectures. + +On the other hand, it is possible to assume that callee-saved registers +(@code{R0} through @code{R2}) are not clobbered by another dynamically +generated function which does not use them as operands in its code and +which does not return a value. + +@item Branch instructions +Like @code{arg}, these also return a value which, in this case, +is to be used to compile forward branches as explained in +@ref{Fibonacci, , Fibonacci numbers}. They accept a pointer to the +destination of the branch and two operands to be compared; of these, +the last can be either a register or an immediate. They are: +@example +bltr/blti i ui l ul p @r{if }O2 < O3@r{ goto }O1 +bler/blei i ui l ul p @r{if }O2 <= O3@r{ goto }O1 +bgtr/bgti i ui l ul p @r{if }O2 > O3@r{ goto }O1 +bger/bgei i ui l ul p @r{if }O2 >= O3@r{ goto }O1 +beqr/beqi i ui l ul p @r{if }O2 == O3@r{ goto }O1 +bner/bnei i ui l ul p @r{if }O2 != O3@r{ goto }O1 + +bmsr/bmsi i ui l ul @r{if }O2 & O3@r{ goto }O1 +bmcr/bmci i ui l ul @r{if }!(O2 & O3)@r{ goto }O1@footnote{These two mnemonics mean, respectively, @dfn{branch if mask set} and @dfn{branch if mask cleared}.} + +boaddr/boaddi i ui l ul O2 += O3@r{, goto }O1@r{ on overflow} +bosubr/bosubi i ui l ul O2 -= O3@r{, goto }O1@r{ on overflow} +@end example + +@item Jump and return operations +These accept one argument except @code{ret} which has none; the +difference between @code{finish} and @code{calli} is that the +latter does not clean the stack from pushed parameters (if any) +and the former must @strong{always} follow a @code{prepare} +instruction. Results are undefined when using function calls +in a leaf function. +@example +calli (not specified) @r{function call to O1} +finish (not specified) @r{function call to O1} +jmpi/jmpr (not specified) @r{unconditional jump to O1} +prolog (not specified) @r{function prolog for O1 args} +leaf (not specified) @r{the same for leaf functions} +ret (not specified) @r{return from subroutine} +retval c uc s us i ui l ul p @r{move return value} + @r{to register} +@end example + +Like branch instruction, @code{jmpi} also returns a value which is to +be used to compile forward branches. @xref{Fibonacci, , Fibonacci +numbers}. + +@end table + +As a small appetizer, here is a small function that adds 1 to the input +parameter (an @code{int}). I'm using an assembly-like syntax here which +is a bit different from the one used when writing real subroutines with +@lightning{}; the real syntax will be introduced in @xref{GNU lightning +macros, , Generating code at run-time}. + +@example +incr: + leaf 1 +in = arg_i @rem{! We have an integer argument} + getarg_i R0, in @rem{! Move it to R0} + addi_i RET, R0, 1 @rem{! Add 1\, put result in return value} + ret @rem{! And return the result} +@end example + +And here is another function which uses the @code{printf} function from +the standard C library to write a number in hexadecimal notation: + +@example +printhex: + prolog 1 +in = arg_i @rem{! Same as above} + getarg_i R0, in + prepare 2 @rem{! Begin call sequence for printf} + pusharg_i R0 @rem{! Push second argument} + pusharg_p "%x" @rem{! Push format string} + finish printf @rem{! Call printf} + ret @rem{! Return to caller} +@end example + +@node GNU lightning macros +@chapter Generating code at run-time + +To use @lightning{}, you should include the @file{lightning.h} file that +is put in your include directory by the @samp{make install} command. +That include files defines about four hundred public macros (plus +others that are private to @lightning{}), one for each opcode listed +above. + +Each of the instructions above translates to a macro. All you have to +do is prepend @code{jit_} (lowercase) to opcode names and @code{JIT_} +(uppercase) to register names. Of course, parameters are to be put +between parentheses, just like with every other @sc{cpp} macro. + +This small tutorial presents three examples: + +@ifset ISTEX +@itemize @bullet +@item +The @code{incr} function found in @ref{The instruction set, , +@lightning{}'s instruction set}: + +@item +A simple function call to @code{printf} + +@item +An RPN calculator. + +@item +Fibonacci numbers +@end itemize +@end ifset +@ifclear ISTEX +@menu +* incr:: A function which increments a number by one +* printf:: A simple function call to printf +* RPN calculator:: A more complex example, an RPN calculator +* Fibonacci:: Calculating Fibonacci numbers +@end menu +@end ifclear + +@node incr +@section A function which increments a number by one + +Let's see how to create and use the sample @code{incr} function created +in @ref{The instruction set, , @lightning{}'s instruction set}: + +@example +#include +#include "lightning.h" + +static jit_insn codeBuffer[1024]; + +typedef int (*pifi)(int); @rem{/* Pointer to Int Function of Int */} + +int main() +@{ + pifi incr = (pifi) (jit_set_ip(codeBuffer).iptr); + int in; + + jit_leaf(1); @rem{/* @t{ leaf 1 } */} + in = jit_arg_i(); @rem{/* @t{in = arg_i } */} + jit_getarg_i(JIT_R0, in); @rem{/* @t{ getarg_i R0 } */} + jit_addi_i(JIT_RET, JIT_R0, 1); @rem{/* @t{ addi_i RET\, R0\, 1} */} + jit_ret(); @rem{/* @t{ ret } */} + + jit_flush_code(codeBuffer, jit_get_ip().ptr); + + @rem{/* call the generated code\, passing 5 as an argument */} + printf("%d + 1 = %d\n", 5, incr(5)); + return 0; +@} +@end example + +Let's examine the code line by line (well, almost@dots{}): + +@table @t +@item #include "lightning.h" +You already know about this. It defines all of @lightning{}'s macros. + +@item static jit_insn codeBuffer[1024]; +You might wonder about what is @code{jit_insn}. It is just a type that +is defined by @lightning{}. Its exact definition depends on the +architecture; in general, defining an array of 1024 @code{jit_insn}s +allows one to write 100 to 400 @lightning{} instructions (depending on +the architecture and exact instructions). + +@item typedef int (*pifi)(int); +Just a handy typedef for a pointer to a function that takes an +@code{int} and returns another. + +@item pifi incr = (pifi) (jit_set_ip(codeBuffer).iptr); +This is the first @lightning{} macro we encounter that does not map to +an instruction. It is @code{jit_set_ip}, which takes a pointer to an +area of memory where compiled code will be put and returns the same +value, cast to a @code{union} type whose members are pointers to +functions returning different C types. This union is called +@code{jit_code} and is defined as follows: + +@example + typedef union jit_code @{ + char *ptr; + void (*vptr)(); + char (*cptr)(); + unsigned char (*ucptr)(); + short (*sptr)(); + unsigned short (*usptr)(); + int (*iptr)(); + unsigned int (*uiptr)(); + long (*lptr)(); + unsigned long (*ulptr)(); + void * (*pptr)(); + float (*fptr)(); + double (*dptr)(); + @} jit_code; +@end example + +Any of the members could have been used, since the result is soon casted +to type @code{pifi} but, for the sake of clarity, the program uses +@code{iptr}, a pointer to a function with no prototype and returning an +@code{int}. + +Analogous to @code{jit_set_ip} is @code{jit_get_ip}, which does not +modify the instruction pointer---it is nothing more than a cast of the +current @sc{ip} to @code{jit_code}. + +@item int in; +A footnote in @ref{The instruction set, , @lightning{}'s instruction +set}, under the description of @code{arg}, says that macros implementing +@code{arg} return a value---we'll be using this variable to store the +result of @code{arg}. + +@item jit_leaf(1); +Ok, so we start generating code for our beloved function@dots{} it will +accept one argument and won't call any other function. + +@item in = jit_arg_i(); +@itemx jit_getarg_i(JIT_R0, in); +We retrieve the first (and only) argument, an integer, and store it +into the general-purpose register @code{R0}. + +@item jit_addi_i(JIT_RET, JIT_R0, 1); +We add one to the content of the register and store the result in the +return value. + +@item jit_ret(); +This instruction generates a standard function epilog that returns +the contents of the @code{RET} register. + +@item jit_flush_code(codeBuffer, jit_get_ip().ptr); +This instruction is very important. It flushes the generated code +area out of the processor's instruction cache, avoiding the processor +executes bogus data that it happens to find there. The +@code{jit_flush_code} function accepts the first and the last address +to flush; we use @code{jit_get_ip} to find out the latter. + +@item printf("%d + 1 = %d", 5, incr(5)); +Calling our function is this simple---it is not distinguishable from +a normal C function call, the only difference being that @code{incr} +is a variable. +@end table + +@lightning{} abstracts two phases of dynamic code generation: selecting +instructions that map the standard representation, and emitting binary +code for these instructions. The client program has the responsibility +of describing the code to be generated using the standard @lightning{} +instruction set. + +Let's examine the code generated for @code{incr} on the SPARC and x86 +architectures (on the right is the code that an assembly-language +programmer would write): + +@table @b +@item SPARC +@example + save %sp, -96, %sp + mov %i0, %l0 retl + add %l0, 1, %i0 add %o0, 1, %o0 + ret + restore +@end example +In this case, @lightning{} introduces overhead to create a register +window (not knowing that the procedure is a leaf procedure) and to +move the argument to the general purpose register @code{R0} (which +maps to @code{%l0} on the SPARC). The former overhead could be +avoided by teaching @lightning{} about leaf procedures (@pxref{Future}); +the latter could instead be avoided by rewriting the getarg instruction +as @code{jit_getarg_i(JIT_RET, in)}, which was not done in this +example. + +@item x86 +@example + pushl %ebp + movl %esp, %ebp + pushl %ebx + pushl %esi + pushl %edi + movl 8(%ebp), %eax movl 4(%esp), %eax + addl $1, %eax incl %eax + popl %edi + popl %esi + popl %ebx + popl %ebp + ret ret +@end example +In this case, the main overhead is due to the function's prolog and +epilog, which is nine instructions long on the x86; a hand-written +routine would not save unused callee-preserved registers on the stack. +It is to be said, however, that this is not a problem in more +complicated uses, because more complex procedure would probably use +the @code{V0} through @code{V2} registers (@code{%ebx}, @code{%esi}, +@code{%edi}); in this case, a hand-written routine would have included +the prolog too. Also, a ten byte prolog would probably be a small +overhead in a more complex function. +@end table + +In such a simple case, the macros that make up the back-end compile +reasonably efficient code, with the notable exception of prolog/epilog +code. + +@node printf +@section A simple function call to @code{printf} + +Again, here is the code for the example: + +@example +#include +#include "lightning.h" + +static jit_insn codeBuffer[1024]; + +typedef void (*pvfi)(int); @rem{/* Pointer to Void Function of Int */} + +int main() +@{ + pvfi myFunction; @rem{/* ptr to generated code */} + char *start, *end; @rem{/* a couple of labels */} + int in; @rem{/* to get the argument */} + + myFunction = (pvfi) (jit_set_ip(codeBuffer).vptr); + start = jit_get_ip().ptr; + jit_prolog(1); + in = jit_arg_i(); + jit_movi_p(JIT_R0, "generated %d bytes\n"); + jit_getarg_i(JIT_R1, in); + jit_prepare(2); + jit_pusharg_i(JIT_R1); @rem{/* push in reverse order */} + jit_pusharg_p(JIT_R0); + jit_finish(printf); + jit_ret(); + end = jit_get_ip().ptr; + + @rem{/* call the generated code\, passing its size as argument */} + jit_flush_code(start, end); + myFunction(end - start); +@} +@end example + +The function shows how many bytes were generated. Most of the code +is not very interesting, as it resembles very closely the program +presented in @ref{incr, , A function which increments a number by one}. + +For this reason, we're going to concentrate on just a few statements. + +@table @t +@item start = jit_get_ip().ptr; +@itemx @r{@dots{}} +@itemx end = jit_get_ip().ptr; +These two instruction call the @code{jit_get_ip} macro which was +mentioned in @ref{incr, , A function which increments a number by one} +too. In this case we use the only field of @code{jit_code} that is +not a function pointer: @code{ptr}, which is a simple @code{char *}. + +@item jit_movi_p(JIT_R0, "generated %d bytes\n"); +Note the use of the @samp{p} type specifier, which automatically +casts the second parameter to an @code{unsigned long} to make the +code more clear and less cluttered by typecasts. + +@item jit_prepare(2); +@itemx jit_pusharg_i(JIT_R1); +@itemx jit_pusharg_p(JIT_R0); +@itemx jit_finish(printf); +Once the arguments to @code{printf} have been put in general-purpose +registers, we can start a prepare/pusharg/finish sequence that +moves the argument to either the stack or registers, then calls +@code{printf}, then cleans up the stack. Note how @lightning{} +abstracts the differences between different architectures and +ABI's -- the client program does not know how parameter passing +works on the host architecture. +@end table + +@node RPN calculator +@section A more complex example, an RPN calculator + +We create a small stack-based RPN calculator which applies a series +of operators to a given parameter and to other numeric operands. +Unlike previous examples, the code generator is fully parameterized +and is able to compile different formulas to different functions. +Here is the code for the expression compiler; a sample usage will +follow. + +@example +#include +#include "lightning.h" + +typedef int (*pifi)(int); @rem{/* Pointer to Int Function of Int */} + +pifi compile_rpn(char *expr) +@{ + pifi fn; + int in; + fn = (pifi) (jit_get_ip().iptr); + jit_leaf(1); + in = jit_arg_i(); + jit_getarg_i(JIT_R0, in); + + while (*expr) @{ + char buf[32]; + int n; + if (sscanf(expr, "%[0-9]%n", buf, &n)) @{ + expr += n - 1; + jit_push_i(JIT_R0); + jit_movi_i(JIT_R0, atoi(buf)); + @} else if (*expr == '+') @{ + jit_pop_i(JIT_R1); + jit_addr_i(JIT_R0, JIT_R1, JIT_R0); + @} else if (*expr == '-') @{ + jit_pop_i(JIT_R1); + jit_subr_i(JIT_R0, JIT_R1, JIT_R0); + @} else if (*expr == '*') @{ + jit_pop_i(JIT_R1); + jit_mulr_i(JIT_R0, JIT_R1, JIT_R0); + @} else if (*expr == '/') @{ + jit_pop_i(JIT_R1); + jit_divr_i(JIT_R0, JIT_R1, JIT_R0); + @} else @{ + fprintf(stderr, "cannot compile: %s\n", expr); + abort(); + @} + ++expr; + @} + jit_movr_i(JIT_RET, JIT_R0); + jit_ret(); + return fn; +@} +@end example + +The principle on which the calculator is based is easy: the stack +top is held in R0, while the remaining items of the stack are held +on the hardware stack. Compiling an operand pushes the old stack +top onto the stack and moves the operand into R0; compiling an +operator pops the second operand off the stack into R1, and +compiles the operation so that the result goes into R0, thus +becoming the new stack top. + +Try to locate a call to @code{jit_set_ip} in the source code. You +will not find one; this means that the client has to manually set +the instruction pointer. This technique has one advantage and one +drawback. The advantage is that the client can simply set the +instruction pointer once and then generate code for multiple functions, +one after another, without caring about passing a different instruction +pointer each time; see @ref{Reentrancy, , Re-entrant usage of +@lightning{}} for the disadvantage. + +Source code for the client (which lies in the same source file) follows: + +@example +static jit_insn codeBuffer[1024]; + +int main() +@{ + pifi c2f, f2c; + int i; + + jit_set_ip(codeBuffer); + c2f = compile_rpn("9*5/32+"); + f2c = compile_rpn("32-5*9/"); + jit_flush_code(codeBuffer, jit_get_ip().ptr); + + printf("\nC:"); + for (i = 0; i <= 100; i += 10) printf("%3d ", i); + printf("\nF:"); + for (i = 0; i <= 100; i += 10) printf("%3d ", c2f(i)); + printf("\n"); + + printf("\nF:"); + for (i = 32; i <= 212; i += 10) printf("%3d ", i); + printf("\nC:"); + for (i = 32; i <= 212; i += 10) printf("%3d ", f2c(i)); + printf("\n"); + return 0; +@} +@end example + +The client displays a conversion table between Celsius and Fahrenheit +degrees (both Celsius-to-Fahrenheit and Fahrenheit-to-Celsius). The +formulas are, @math{F(c) = c*9/5+32} and @math{C(f) = (f-32)*5/9}, +respectively. + +Providing the formula as an argument to @code{compile_rpn} effectively +parameterizes code generation, making it possible to use the same code +to compile different functions; this is what makes dynamic code +generation so powerful. + +The @file{rpn.c} file in the @lightning{} distribution includes a more +complete (and more complex) implementation of @code{compile_rpn}, +which does constant folding, allows the argument to the functions +to be used more than once, and is able to assemble instructions with +an immediate parameter. + +@node Fibonacci +@section Fibonacci numbers + +The code in this section calculates a variant of the Fibonacci sequence. +While the traditional Fibonacci sequence is modeled by the recurrence +relation: +@display + f(0) = f(1) = 1 + f(n) = f(n-1) + f(n-2) +@end display + +@noindent +the functions in this section calculates the following sequence, which +is more interesting as a benchmark@footnote{That's because, as is +easily seen, the sequence represents the number of activations of the +@code{nfibs} procedure that are needed to compute its value through +recursion.}: +@display + nfibs(0) = nfibs(1) = 1 + nfibs(n) = nfibs(n-1) + nfibs(n-2) + 1 +@end display + +The purpose of this example is to introduce branches. There are two +kind of branches: backward branches and forward branches. We'll +present the calculation in a recursive and iterative form; the +former only uses forward branches, while the latter uses both. + +@example +#include +#include "lightning.h" + +static jit_insn codeBuffer[1024]; + +typedef int (*pifi)(int); @rem{/* Pointer to Int Function of Int */} + +int main() +@{ + pifi nfibs = (pifi) (jit_set_ip(codeBuffer).iptr); + int in; @rem{/* offset of the argument */} + jit_insn *ref; @rem{/* to patch the forward reference */} + + jit_prolog (1); + in = jit_arg_ui (); + jit_getarg_ui(JIT_V0, in); @rem{/* V0 = n */} + ref = jit_blti_ui (jit_forward(), JIT_V0, 2); + jit_subi_ui (JIT_V1, JIT_V0, 1); @rem{/* V1 = n-1 */} + jit_subi_ui (JIT_V2, JIT_V0, 2); @rem{/* V2 = n-2 */} + jit_prepare(1); + jit_pusharg_ui(JIT_V1); + jit_finish(nfibs); + jit_retval(JIT_V1); @rem{/* V1 = nfibs(n-1) */} + jit_prepare(1); + jit_pusharg_ui(JIT_V2); + jit_finish(nfibs); + jit_retval(JIT_V2); @rem{/* V2 = nfibs(n-2) */} + jit_addi_ui(JIT_V1, JIT_V1, 1); + jit_addr_ui(JIT_RET, JIT_V1, JIT_V2); @rem{/* RET = V1 + V2 + 1 */} + jit_ret(); + + jit_patch(ref); @rem{/* patch jump */} + jit_movi_i(JIT_RET, 1); @rem{/* RET = 1 */} + jit_ret(); + + @rem{/* call the generated code\, passing 32 as an argument */} + jit_flush_code(codeBuffer, jit_get_ip().ptr); + printf("nfibs(%d) = %d", 32, nfibs(32)); + return 0; +@} +@end example + +As said above, this is the first example of dynamically compiling +branches. Branch instructions have three operands: two contains the +values to be compared, while the first is a @dfn{label}; @lightning{} +label's are represented as @code{jit_insn *} values. Unlike other +instructions (apart from @code{arg}, which is actually a directive +rather than an instruction), branch instructions also return a value +which, as we see in the example above, can be used to compile +forward references. + +Compiling a forward reference is a two-step operation. First, a +branch is compiled with a dummy label, since the actual destination +of the jump is not yet known; the dummy label is returned by the +@code{jit_forward()} macro. The value returned by the branch +instruction is saved to be used later. + +Then, when the destination of the jump is reached, another macro +is used, @code{jit_patch()}. This macro must be called once for +@strong{every} point in which the code had a forward branch to the +instruction following @code{jit_patch} (in this case a @code{movi_i} +instruction). + +Now, here is the iterative version: + +@example +#include +#include "lightning.h" + +static jit_insn codeBuffer[1024]; + +typedef int (*pifi)(int); @rem{/* Pointer to Int Function of Int */} + +int main() +@{ + pifi nfibs = (pifi) (jit_set_ip(codeBuffer).iptr); + int in; @rem{/* offset of the argument */} + jit_insn *ref; @rem{/* to patch the forward reference */} + jit_insn *loop; @rem{/* start of the loop */} + + jit_leaf (1); + in = jit_arg_ui (); + jit_getarg_ui(JIT_R2, in); @rem{/* R2 = n */} + jit_movi_ui (JIT_R1, 1); + ref = jit_blti_ui (jit_forward(), JIT_R2, 2); + jit_subi_ui (JIT_R2, JIT_R2, 1); + jit_movi_ui (JIT_R0, 1); + + loop= jit_get_label(); + jit_subi_ui (JIT_R2, JIT_R2, 1); @rem{/* decr. counter */} + jit_addr_ui (JIT_V0, JIT_R0, JIT_R1); @rem{/* V0 = R0 + R1 */} + jit_movr_ui (JIT_R0, JIT_R1); @rem{/* R0 = R1 */} + jit_addi_ui (JIT_R1, JIT_V0, 1); @rem{/* R1 = V0 + 1 */} + jit_bnei_ui (loop, JIT_R2, 0); @rem{/* if (R2) goto loop; */} + + jit_patch(ref); @rem{/* patch forward jump */} + jit_movr_ui (JIT_RET, JIT_R1); @rem{/* RET = R1 */} + jit_ret (); + + @rem{/* call the generated code\, passing 36 as an argument */} + jit_flush_code(codeBuffer, jit_get_ip().ptr); + printf("nfibs(%d) = %d", 36, nfibs(36)); + return 0; +@} +@end example + +This code calculates the recurrence relation using iteration (a +@code{for} loop in high-level languages). There is still a forward +reference (indicated by the @code{jit_forward}/@code{jit_patch} pair); +there are no function calls anymore: instead, there is a backward +jump (the @code{bnei} at the end of the loop). + +In this case, the destination address should be known, because the +jumps lands on an instruction that has already been compiled. +However the program must make a provision and remember the address +where the jump will land. This is achieved with @code{jit_get_label}, +yet another macro that is much similar to @code{jit_get_ip} but, +instead of a @code{jit_code} union, it answers an @code{jit_insn *} +that the branch macros accept. + +Now, let's make one more change: let's rewrite the loop like this: + +@example + @r{@dots{}} + + jit_delay( + jit_movi_ui (JIT_R1, 1), + ref = jit_blti_ui (jit_forward(), JIT_R2, 2)); + jit_subi_ui (JIT_R2, JIT_R2, 1); + + loop= jit_get_label(); + jit_subi_ui (JIT_R2, JIT_R2, 1); @rem{/* decr. counter */} + jit_addr_ui (JIT_V0, JIT_R0, JIT_R1); @rem{/* V0 = R0 + R1 */} + jit_movr_ui (JIT_R0, JIT_R1); @rem{/* R0 = R1 */} + jit_delay( + jit_addi_ui (JIT_R1, JIT_V0, 1), @rem{/* R1 = V0 + 1 */} + jit_bnei_ui (loop, JIT_R2, 0)); @rem{/* if (R2) goto loop; */} + + @r{@dots{}} +@end example + +The @code{jit_delay} macro is used to schedule delay slots in jumps and +branches. This is optional, but might lead to performance improvements +in tight inner loops (of course not in a loop that is executed 35 +times, but this is just an example). + +@code{jit_delay} takes two @lightning{} instructions, a @dfn{delay +instruction} and a @dfn{branch instruction}. Note that the two +instructions must be written in execution order (first the delay +instruction, then the branch instruction), @strong{not} with the branch +first. If the current machine has a delay slot, the delay instruction +(or part of it) is placed in the delay slot after the branch +instruction; otherwise, it emits the delay instruction before the branch +instruction. The delay instruction must not depend on being executed +before or after the branch. + +@node Floating-point +@chapter Doing floating point computations + +@node Reentrancy +@chapter Re-entrant usage of @lightning{} + +By default, @lightning{} is able to compile different functions at the +same time as long as it happens in different object files, and on the +other hand constrains code generation tasks to reside in a single +object file. + +The reason for this is not apparent, but is easily explained: +the @file{lightning.h} header file defines its state as a +@code{static} variable, so calls to @code{jit_set_ip} and +@code{jit_get_ip} residing in different files access different +instruction pointers. This was not done without reason: it makes +the usage of @lightning{} much simpler, as it limits the initialization +tasks to the bare minimum and removes the need to link the program +with a separate library. + +On the other hand, multi-threaded or otherwise concurrent programs +require reentrancy in the code generator, so this approach cannot be +the only one. In fact, it is possible to define your own copy of +@lightning{}'s instruction state by defining a variable of type +@code{jit_state} and @code{#define}-ing @code{_jit} to it: + +@example + struct jit_state lightning; + #define _jit lightning +@end example + +You are free to define the @code{jit_state} variable as you like: +@code{extern}, @code{static} to a function, @code{auto}, or global. + +This feature takes advantage of an aspect of macros (@dfn{cascaded +macros}), which is documented thus in @acronym{CPP}'s reference manual: + +@quotation +A cascade of macros is when one macro's body contains a reference to +another macro. This is very common practice. For example, +@example +#define BUFSIZE 1020 +#define TABLESIZE BUFSIZE +@end example +This is not at all the same as defining @code{TABLESIZE} to be +@samp{1020}. The @code{#define} for @code{TABLESIZE} uses exactly the +body you specify---in this case, @code{BUFSIZE}---and does not check to +see whether it too is the name of a macro; it's only when you use +@code{TABLESIZE} that the result of its expansion is checked for more +macro names. + +This makes a difference if you change the definition of @code{BUFSIZE} +at some point in the source file. @code{TABLESIZE}, defined as shown, +will always expand using the definition of @code{BUFSIZE} that is +currently in effect: +#define BUFSIZE 1020 +#define TABLESIZE BUFSIZE +#undef BUFSIZE +#define BUFSIZE 37 + +Now @code{TABLESIZE} expands (in two stages) to `37'. (The @code{#undef} +is to prevent any warning about the nontrivial redefinition of +@code{BUFSIZE}.) +@end quotation + +@noindent +In the same way, @code{jit_get_label} will adopt whatever definition of +@code{_jit} is in effect: +@example +#define jit_get_label() (_jit.pc) +@end example + +Special care must be taken when functions residing in separate files +must access the same state. This could be the case, for example, if a +special library contained function for strength reduction of +multiplications to adds & shifts, or maybe of divisions to +multiplications and shifts. The function would be compiled using a +single definition of @code{_jit} and that definition would be used +whenever the function would be called. + +Since @lightning{} uses a feature of the preprocessor to obtain +re-entrancy, it makes sense to rely on the preprocessor in this case +too. + +The idea is to pass the current @code{struct jit_state} to the +function: + +@example +static void +_opt_muli_i(jit, dest, source, n) + register struct jit_state *jit; + register int dest, source, n; +@{ +#define _jit jit +@dots{} +#undef _jit +@} +@end example + +@noindent +doing this unbeknownst to the client, using a macro in the header file: + +@example +extern void _opt_muli_i(struct jit_state *, int, int, int); + +#define opt_muli_i(rd, rs, n) _opt_muli_i(&_jit, (rd), (rs), (n)) +@end example + + +@node Autoconf support +@chapter Using @code{autoconf} with @lightning{} + +It is very easy to include @lightning{}'s source code (without the +documentation and examples) into your program's distribution +so that people don't need to have it installed in order to use it. + +Here is a step by step explanation of what to do: + +@enumerate +@item Run @command{lightningize} from your package's main +distribution directory. +@example + lightningize +@end example + +@noindent +If you're using Automake, you might be pleased to know that +@file{Makefile.am} files will be already there. + +@item If you're not using Automake and @code{aclocal}, instead, +you should delete the @file{Makefile.am} files (they are of no use +to you) and copy the contents of the @file{lightning.m4} file, found in +@command{aclocal}'s macro repository (usually @file{/usr/share/aclocal}, +to your @file{configure.in} or @file{acinclude.m4} or @file{aclocal.m4} file. + +@item Include a call to the @code{LIGHTNING_CONFIGURE_IF_NOT_FOUND} +macro in your @file{configure.in} file. +@end enumerate + +@code{LIGHTNING_CONFIGURE_IF_NOT_FOUND} will first look for a +pre-installed copy of @lightning{} and, if it can be found, it will +use it; otherwise, it will do exactly the same things that +@lightning{}'s own configure script does. If @lightning{} is +already installed, or if the configuration process succeeds, it +will define the @code{HAVE_LIGHTNING} symbol. + +In addtion, an Automake conditional named @code{HAVE_INSTALLED_LIGHTNING} +will be set if @lightning{} is already installed, which can be used to +set up include paths appropriately. + +Finally, @code{LIGHTNING_CONFIGURE_IF_NOT_FOUND} accepts two +optional parameters: respectively, an action to be taken if @lightning{} +is available, and an action to be taken if it is not. diff --git a/doc/version.texi b/doc/version.texi new file mode 100644 index 000000000..b112f90f5 --- /dev/null +++ b/doc/version.texi @@ -0,0 +1,4 @@ +@set UPDATED 2 November 2001 +@set UPDATED-MONTH November 2001 +@set EDITION 1.2a +@set VERSION 1.2a diff --git a/lightning-inst.h b/lightning-inst.h new file mode 100644 index 000000000..5cf1af2ca --- /dev/null +++ b/lightning-inst.h @@ -0,0 +1,65 @@ +/******************************** -*- C -*- **************************** + * + * lightning main include file + * + ***********************************************************************/ + + +/*********************************************************************** + * + * Copyright 2000 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 2.1, 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. + * + ***********************************************************************/ + + + +#ifndef __lightning_h +#define __lightning_h + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#ifndef LIGHTNING_DEBUG +#include +#endif + +#include +#include +#include +#include + +#ifdef jit_cmp +#include +#endif + +#ifndef JIT_R0 +#error GNU lightning does not support the current target +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __lightning_h */ diff --git a/lightning.h.in b/lightning.h.in new file mode 100644 index 000000000..fd1a4d79c --- /dev/null +++ b/lightning.h.in @@ -0,0 +1,88 @@ +/******************************** -*- C -*- **************************** + * + * lightning main include file + * Unlike lightning-dist.h, this contains a few definitions + * used by the test suite. + * + ***********************************************************************/ + + +/*********************************************************************** + * + * Copyright 2000 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 2.1, 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. + * + ***********************************************************************/ + + + +#ifndef __lightning_h +#define __lightning_h + +/* Define if you want assertions enabled. */ +#undef _ASM_SAFETY + +/* Define if lightning is compiling for i386 */ +#undef LIGHTNING_I386 + +/* Define if lightning is compiling for Sparc */ +#undef LIGHTNING_SPARC + +/* Define if lightning is compiling for PowerPC */ +#undef LIGHTNING_PPC + +/* Define if you want the test programs to disassemble their output */ +#undef LIGHTNING_DISASSEMBLE + +/* Define if creating a cross-assembler */ +#undef LIGHTNING_CROSS + +/* Define if you have the memcpy function */ +#undef HAVE_MEMCPY + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#ifndef LIGHTNING_DEBUG +#include +#endif + +#include +#include +#include +#include + +#ifdef jit_cmp +#include +#endif + +#ifdef LIGHTNING_DISASSEMBLE +extern void disassemble(FILE *stream, char *from, char *to); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __lightning_h */ diff --git a/lightning.m4 b/lightning.m4 new file mode 100644 index 000000000..280a63e9f --- /dev/null +++ b/lightning.m4 @@ -0,0 +1,57 @@ +dnl I'd like this to be edited in -*- Autoconf -*- mode... +dnl +# serial 1 LIGHTNING_CONFIGURE_IF_NOT_FOUND +AC_DEFUN([LIGHTNING_CONFIGURE_IF_NOT_FOUND], [ +AC_REQUIRE([AC_PROG_LN_S])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_CHECK_HEADER(lightning.h) +AM_CONDITIONAL(LIGHTNING_MAIN, (exit 1)) +AM_CONDITIONAL(HAVE_INSTALLED_LIGHTNING, test "$ac_cv_header_lightning_h" = yes) + +lightning= +if test "$ac_cv_header_lightning_h" = yes; then + lightning=yes +else + case "$host_cpu" in + i?86) cpu_subdir=i386 ;; + sparc*) cpu_subdir=sparc ;; + powerpc) cpu_subdir=ppc ;; + *) ;; + esac + test -n "$cpu_subdir" && lightning=yes +fi + +ifdef([AC_HELP_STRING], [ + dnl autoconf 2.50 style + if test -n "$cpu_subdir"; then + AC_CONFIG_LINKS(lightning/asm.h:lightning/$cpu_subdir/asm.h + lightning/core.h:lightning/$cpu_subdir/core.h + lightning/fp.h:lightning/$cpu_subdir/fp.h + lightning/funcs.h:lightning/$cpu_subdir/funcs.h, , [ + cpu_subdir=$cpu_subdir + ]) + fi +], [ + dnl autoconf 2.13 style + AC_OUTPUT_COMMANDS([ + if test -n "$cpu_subdir"; then + for i in asm fp core funcs; do + echo linking $srcdir/lightning/$cpu_subdir/$i.h to lightning/$i.h + (cd lightning && $LN_S -f $srcdir/$cpu_subdir/$i.h $i.h) + done + fi + ], [ + LN_S='$LN_S' + cpu_subdir=$cpu_subdir + ]) +]) + +if test -n "$lightning"; then + AC_DEFINE(HAVE_LIGHTNING, 1, [Define if GNU lightning can be used]) + lightning= + ifelse([$1], , :, [$1]) +else + ifelse([$2], , :, [$2]) +fi + +])dnl diff --git a/lightning/Makefile.am b/lightning/Makefile.am new file mode 100644 index 000000000..d032e2a89 --- /dev/null +++ b/lightning/Makefile.am @@ -0,0 +1,16 @@ +DISTCLEANFILES = asm.h core.h funcs.h fp.h + +LIGHTNING_FILES = funcs-common.h core-common.h fp-common.h \ + asm-common.h \ + i386/asm.h i386/core.h i386/funcs.h i386/fp.h \ + sparc/asm.h sparc/core.h sparc/funcs.h sparc/fp.h \ + ppc/asm.h ppc/core.h ppc/funcs.h ppc/fp.h + +if LIGHTNING_MAIN +lightningdir = $(includedir)/lightning +dist_pkgdata_DATA = Makefile.am +nobase_dist_lightning_HEADERS = $(LIGHTNING_FILES) +nodist_lightning_HEADERS = asm.h core.h funcs.h fp.h +else +dist_noinst_HEADERS = $(LIGHTNING_FILES) lightning.h +endif diff --git a/lightning/asm-common.h b/lightning/asm-common.h new file mode 100644 index 000000000..b0a11948b --- /dev/null +++ b/lightning/asm-common.h @@ -0,0 +1,197 @@ +/******************************** -*- 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 2.1, 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. + * + ***********************************************************************/ + + +#ifndef __lightning_asm_common_h +#define __lightning_asm_common_h_ + + +#ifndef _ASM_SAFETY +#define JITFAIL(MSG) 0 +#else +#if defined __GNUC__ && (__GNUC__ == 3 ? __GNUC_MINOR__ >= 2 : __GNUC__ > 3) +#define JITFAIL(MSG) jit_fail(MSG, __FILE__, __LINE__, __func__) +#else +#define JITFAIL(MSG) jit_fail(MSG, __FILE__, __LINE__, __FUNCTION__) +#endif +#endif + +#if defined __GNUC__ && (__GNUC__ == 3 ? __GNUC_MINOR__ >= 2 : __GNUC__ > 3) +#define JITSORRY(MSG) jit_fail("sorry, unimplemented: " MSG, __FILE__, __LINE__, __func__) +#else +#define JITSORRY(MSG) jit_fail("sorry, unimplemented: " MSG, __FILE__, __LINE__, __FUNCTION__) +#endif + +#ifdef __GNUC__ +#define JIT_UNUSED __attribute__((unused)) +#else +#define JIT_UNUSED +#endif + + +/* 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 + +typedef char _sc; +typedef unsigned char _uc; +typedef unsigned short _us; +typedef unsigned int _ui; +typedef long _sl; +typedef unsigned long _ul; + +#define _jit_UC(X) ((_uc )(X)) +#define _jit_US(X) ((_us )(X)) +#define _jit_UI(X) ((_ui )(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 _PSL(X) ((_sl *)(X)) +# define _PUL(X) ((_ul *)(X)) + +#define _jit_B(B) _jit_UL(((*_jit.x.uc_pc++)= _jit_UC((B)& 0xff))) +#define _jit_W(W) _jit_UL(((*_jit.x.us_pc++)= _jit_US((W)&0xffff))) +#define _jit_I(I) _jit_UL(((*_jit.x.ui_pc++)= _jit_UI((I) ))) +#define _jit_L(L) _jit_UL(((*_jit.x.ul_pc++)= _jit_UL((L) ))) + +#define _MASK(N) ((unsigned)((1<<(N)))-1) +#define _siP(N,I) (!((((unsigned)(I))^(((unsigned)(I))<<1))&~_MASK(N))) +#define _uiP(N,I) (!(((unsigned)(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 _u8P(I) _uiP(8,I) +#define _u16P(I) _uiP(16,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) +#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) + +#endif /* __lightning_asm_common_h */ diff --git a/lightning/core-common.h b/lightning/core-common.h new file mode 100644 index 000000000..23b474706 --- /dev/null +++ b/lightning/core-common.h @@ -0,0 +1,568 @@ +/******************************** -*- 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 2.1, 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. + * + ***********************************************************************/ + + +#ifndef __lightning_core_common_h +#define __lightning_core_common_h_ + +typedef struct { + union { + jit_insn *pc; + _uc *uc_pc; + _us *us_pc; + _ui *ui_pc; + _ul *ul_pc; + } x; + struct jit_fp *fp; + struct jit_local_state jitl; +} jit_state; + +static jit_state _jit; + +#define JIT_NOREG (-1) + +#define _jitl _jit.jitl + +#define jit_get_ip() (*(jit_code *) &_jit.x.pc) +#define jit_set_ip(ptr) (_jit.x.pc = (jit_insn *) ptr, jit_get_ip()) +#define jit_get_label() (_jit.x.pc) +#define jit_forward() (_jit.x.pc) + +#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 */ +#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_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_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_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)) +#define jit_movi_ui(d, rs) jit_movi_i((d), (rs)) +#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_subci_ui(d, rs, is) jit_subci_i((d), (rs), (is)) +#define jit_subcr_ui(d, s1, s2) jit_subcr_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)) +#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)) + +#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_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_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_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)) +#define jit_movi_ul(d, rs) jit_movi_l((d), (rs)) +#define jit_movr_ul(d, rs) jit_movr_l((d), (rs)) +#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_subci_ul(d, rs, is) jit_subci_l((d), (rs), (is)) +#define jit_subcr_ul(d, s1, s2) jit_subcr_l((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)) +#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)) +#define jit_movr_p(d, rs) jit_movr_ul((d), (rs)) +#define jit_movi_p(d, is) jit_movi_ul((d), (long) (is)) +#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)) + +#ifndef jit_addci_i +#define jit_addci_i(d, rs, is) jit_addi_i((d), (rs), (is)) +#define jit_addcr_i(d, s1, s2) jit_addr_i((d), (s1), (s2)) +#define jit_addci_l(d, rs, is) jit_addi_l((d), (rs), (is)) +#define jit_addcr_l(d, s1, s2) jit_addr_l((d), (s1), (s2)) +#endif + +#ifndef jit_subcr_i +#define jit_subcr_i(d, s1, s2) jit_subr_i((d), (s1), (s2)) +#endif + +/* 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)) +# define jit_negr_l(d, rs) jit_subr_l((d), JIT_RZERO, (rs)) +# 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 */ + +/* 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 + +/* Common 'shortcut' implementations */ +#define jit_subi_i(d, rs, is) jit_addi_i((d), (rs), -(is)) +#define jit_subi_l(d, rs, is) jit_addi_l((d), (rs), -(is)) +#define jit_subci_i(d, rs, is) jit_addci_i((d), (rs), -(is)) +#define jit_subci_l(d, rs, is) jit_addci_l((d), (rs), -(is)) +#define jit_rsbr_i(d, s1, s2) jit_subr_i((d), (s2), (s1)) +#define jit_rsbr_l(d, s1, s2) jit_subr_l((d), (s2), (s1)) + +/* Unary */ +#define jit_notr_c(d, rs) jit_xori_c((d), (rs), 255) +#define jit_notr_uc(d, rs) jit_xori_c((d), (rs), 255) +#define jit_notr_s(d, rs) jit_xori_s((d), (rs), 65535) +#define jit_notr_us(d, rs) jit_xori_s((d), (rs), 65535) +#define jit_notr_i(d, rs) jit_xori_i((d), (rs), ~0) +#define jit_notr_ui(d, rs) jit_xori_i((d), (rs), ~0) +#define jit_notr_l(d, rs) jit_xori_l((d), (rs), ~0L) +#define jit_notr_ul(d, rs) jit_xori_l((d), (rs), ~0L) + +#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 + + +#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)) + +#ifndef jit_extr_i_ul +#ifdef jit_addi_l /* sizeof(long) != sizeof(int) */ +#define jit_extr_i_ul(d, rs) jit_andi_ui((d), (rs), 0xFF) +#else /* sizeof(long) == sizeof(int) */ +#define jit_extr_i_ul(d, rs) jit_movr_i(d, rs) +#endif /* sizeof(long) == sizeof(int) */ +#endif + +#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) jitfp_prepare((nint), 0, 0) +#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) + +/* 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)) +#define jit_ldi_ul(rd, is) jit_ldxi_ul((rd), JIT_RZERO, (is)) +#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)) +#define jit_ldr_ul(rd, rs) jit_ldxr_ul((rd), JIT_RZERO, (rs)) +#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)) +#define jit_ldxi_p(rd, rs, is) jit_ldxi_l((rd), (rs), (is)) + + +/* 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), (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), (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), (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), (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), (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), (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), (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), (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), (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), (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), (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), (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)) + +#ifndef jit_finish +#define jit_finish(sub) jit_calli(sub) +#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_FP +#define jit_getarg_c(reg, ofs) jit_extr_c_i ((reg), (ofs)) +#define jit_getarg_i(reg, ofs) jit_movr_i ((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_i ((reg), (ofs)) +#define jit_getarg_uc(reg, ofs) jit_extr_uc_ui((reg), (ofs)) +#define jit_getarg_ui(reg, ofs) jit_movr_ui ((reg), (ofs)) +#define jit_getarg_ul(reg, ofs) jit_extr_uc_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_FP, (ofs)); +#define jit_getarg_uc(reg, ofs) jit_ldxi_uc((reg), JIT_FP, (ofs)); +#define jit_getarg_s(reg, ofs) jit_ldxi_s((reg), JIT_FP, (ofs)); +#define jit_getarg_us(reg, ofs) jit_ldxi_us((reg), JIT_FP, (ofs)); +#define jit_getarg_i(reg, ofs) jit_ldxi_i((reg), JIT_FP, (ofs)); +#define jit_getarg_ui(reg, ofs) jit_ldxi_ui((reg), JIT_FP, (ofs)); +#define jit_getarg_l(reg, ofs) jit_ldxi_l((reg), JIT_FP, (ofs)); +#define jit_getarg_ul(reg, ofs) jit_ldxi_ul((reg), JIT_FP, (ofs)); +#define jit_getarg_p(reg, ofs) jit_ldxi_p((reg), JIT_FP, (ofs)); +#endif +#endif + + +/* Common definitions when sizeof(long) = sizeof(int) */ +#ifndef jit_addi_l +#define JIT_LONG_IS_INT + +/* 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_addci_l(d, rs, is) jit_addci_i((d), (rs), (is)) +#define jit_addcr_l(d, s1, s2) jit_addcr_i((d), (s1), (s2)) +#define jit_addxi_l(d, rs, is) jit_addxi_i((d), (rs), (is)) +#define jit_addxr_l(d, s1, s2) jit_addxr_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)) +#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_subcr_l(d, s1, s2) jit_subcr_i((d), (s1), (s2)) +#define jit_subxi_l(d, rs, is) jit_subxi_i((d), (rs), (is)) +#define jit_subxr_l(d, s1, s2) jit_subxr_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)) + +#ifndef jit_rsbi_l +#define jit_rsbi_l(d, rs, is) jit_rsbi_i((d), (rs), (is)) +#endif + +#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)) + +/* 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)) +#define jit_ldr_ul(d, rs) jit_ldr_ui((d), (rs)) +#define jit_ldi_ul(d, is) jit_ldi_ui((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)) +#define jit_ldxr_ui(d, s1, s2) jit_ldxr_i((d), (s1), (s2)) +#define jit_ldxi_ui(d, rs, is) jit_ldxi_i((d), (rs), (is)) +#define jit_ldxr_ul(d, s1, s2) jit_ldxr_ui((d), (s1), (s2)) +#define jit_ldxi_ul(d, rs, is) jit_ldxi_ui((d), (rs), (is)) + + +/* 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 + +#endif /* __lightning_core_common_h_ */ diff --git a/lightning/fp-common.h b/lightning/fp-common.h new file mode 100644 index 000000000..de25fbba8 --- /dev/null +++ b/lightning/fp-common.h @@ -0,0 +1,260 @@ +/******************************** -*- C -*- **************************** + * + * Platform-independent layer floating-point interface + * + ***********************************************************************/ + + +/*********************************************************************** + * + * 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 2.1, 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. + * + ***********************************************************************/ + +struct jit_fp { + char kind; + char subkind; + union { + struct { + int displ; + char reg1; + char reg2; + } addr; + union { + double number; + long split[sizeof(double) / sizeof(long)]; + } imm; + struct { + struct jit_fp *lhs, *rhs; + } ops; + } d; +}; + +#ifdef jit_trunc + +enum { JIT_NULL, /* unused */ + + JIT_CMP, JIT_FLOOR, JIT_CEIL, JIT_ROUND, JIT_TRUNC, /* integer */ + + JIT_XI, JIT_ADD, JIT_XR, JIT_SUB, /* subkinds */ + JIT_I, JIT_MUL, JIT_R, JIT_DIV, + JIT_INT, + + JIT_ABS, JIT_SIN, JIT_COS, JIT_TAN, JIT_ATN, /* functions */ + JIT_EXP, JIT_LOG, JIT_NEG, JIT_SQRT, + + JIT_OP, JIT_FN, JIT_LD, JIT_IMM }; /* kinds */ + +/* Declarations */ + +static void _jit_emit(jit_state *, struct jit_fp *, + int, int, int, int) JIT_UNUSED; +static struct jit_fp *_jit_op(struct jit_fp *, int, + struct jit_fp *, struct jit_fp *) JIT_UNUSED; +static struct jit_fp *_jit_ld(struct jit_fp *, int, + int, int) JIT_UNUSED; +static struct jit_fp *_jit_fn(struct jit_fp *, int, + struct jit_fp *) JIT_UNUSED; +static struct jit_fp *_jit_imm(struct jit_fp *, double) JIT_UNUSED; + +/* Internal function to walk the tree */ + +void +_jit_emit(jit_state *jit, struct jit_fp *head, + int store_kind, int store1, int store2, int reg0) +{ +#define _jit (*jit) + switch (head->kind) { + case JIT_OP: + _jit_emit(jit, head->d.ops.lhs, JIT_NULL, 0, 0, reg0); + _jit_emit(jit, head->d.ops.rhs, JIT_NULL, 0, 0, reg0 + 1); + switch (head->subkind) { + case JIT_ADD: jit_add_two(reg0); break; + case JIT_SUB: jit_sub_two(reg0); break; + case JIT_MUL: jit_mul_two(reg0); break; + case JIT_DIV: jit_div_two(reg0); break; + } + break; + + case JIT_IMM: +#ifdef JIT_LONG_IS_INT + jit_fpimm(reg0, head->d.imm.split[0], head->d.imm.split[1]); +#else + jit_fpimm(reg0, head->d.imm.split[0]); +#endif + break; + + case JIT_FN: + _jit_emit(jit, head->d.ops.lhs, JIT_NULL, 0, 0, reg0); + switch (head->subkind) { + case JIT_ABS: jit_abs(reg0); break; + case JIT_NEG: jit_neg(reg0); break; +#ifdef JIT_TRANSCENDENTAL + case JIT_SIN: jit_sin(reg0); break; + case JIT_SQRT: jit_sqrt(reg0); break; + case JIT_COS: jit_cos(reg0); break; + case JIT_TAN: jit_tan(reg0); break; + case JIT_ATN: jit_atn(reg0); break; + case JIT_EXP: jit_exp(reg0); break; + case JIT_LOG: jit_log(reg0); break; +#endif + } + break; + + case JIT_LD: + switch (head->subkind) { + case JIT_INT: jit_exti_d(reg0, head->d.addr.reg1); break; + case JIT_XI: jit_ldxi_f(reg0, head->d.addr.reg1, head->d.addr.displ); break; + case JIT_XR: jit_ldxr_f(reg0, head->d.addr.reg1, head->d.addr.reg2); break; + case JIT_XI | 1: jit_ldxi_d(reg0, head->d.addr.reg1, head->d.addr.displ); break; + case JIT_XR | 1: jit_ldxr_d(reg0, head->d.addr.reg1, head->d.addr.reg2); break; +#ifndef JIT_RZERO + case JIT_I: jit_ldi_f(reg0, head->d.addr.displ); break; + case JIT_R: jit_ldr_f(reg0, head->d.addr.reg1); break; + case JIT_I | 1: jit_ldi_d(reg0, head->d.addr.displ); break; + case JIT_R | 1: jit_ldr_d(reg0, head->d.addr.reg1); break; +#endif + } + break; + } + + switch (store_kind) { + case JIT_FLOOR: jit_floor(store1, reg0); break; + case JIT_CEIL: jit_ceil(store1, reg0); break; + case JIT_TRUNC: jit_trunc(store1, reg0); break; + case JIT_ROUND: jit_round(store1, reg0); break; + case JIT_CMP: jit_cmp(store1, store2, reg0); break; + case JIT_XI: jit_stxi_f(store2, store1, reg0); break; + case JIT_XR: jit_stxr_f(store2, store1, reg0); break; + case JIT_XI | 1: jit_stxi_d(store2, store1, reg0); break; + case JIT_XR | 1: jit_stxr_d(store2, store1, reg0); break; +#ifndef JIT_RZERO + case JIT_I: jit_sti_f(store2, reg0); break; + case JIT_R: jit_str_f(store2, reg0); break; + case JIT_I | 1: jit_sti_d(store2, reg0); break; + case JIT_R | 1: jit_str_d(store2, reg0); break; +#endif + case JIT_NULL: break; + } +#undef _jit +} + +/* Internal functions to build the tree */ + +struct jit_fp * +_jit_op(struct jit_fp *where, int which, + struct jit_fp *op1, struct jit_fp *op2) +{ + where->kind = JIT_OP; + where->subkind = which; + where->d.ops.lhs = op1; + where->d.ops.rhs = op2; + return (where); +} + +struct jit_fp * +_jit_ld(struct jit_fp *where, int which, int op1, int op2) +{ + where->kind = JIT_LD; + where->subkind = which; + switch (which & ~1) { + case JIT_XI: where->d.addr.reg1 = op1; + case JIT_I: where->d.addr.displ = op2; break; + case JIT_XR: where->d.addr.reg2 = op2; + case JIT_INT: + case JIT_R: where->d.addr.reg1 = op1; break; + } + return (where); +} + +struct jit_fp * +_jit_fn(struct jit_fp *where, int which, struct jit_fp *op1) +{ + where->kind = JIT_FN; + where->subkind = which; + where->d.ops.lhs = op1; + return (where); +} + +struct jit_fp * +_jit_imm(struct jit_fp *where, double number) +{ + where->kind = JIT_IMM; + where->d.imm.number = number; + return (where); +} + +#define jitfp_begin(buf) (_jit.fp = (buf), --_jit.fp) +#define jitfp_add(op1, op2) _jit_op(++_jit.fp, JIT_ADD, (op1), (op2)) +#define jitfp_sub(op1, op2) _jit_op(++_jit.fp, JIT_SUB, (op1), (op2)) +#define jitfp_mul(op1, op2) _jit_op(++_jit.fp, JIT_MUL, (op1), (op2)) +#define jitfp_div(op1, op2) _jit_op(++_jit.fp, JIT_DIV, (op1), (op2)) +#define jitfp_imm(imm) _jit_imm(++_jit.fp, (imm)) +#define jitfp_exti_d(reg1) _jit_ld(++_jit.fp, JIT_INT, (reg1), 0) +#define jitfp_ldxi_f(reg1, imm) _jit_ld(++_jit.fp, JIT_XI, (reg1), (long)(imm)) +#define jitfp_ldxr_f(reg1, reg2) _jit_ld(++_jit.fp, JIT_XR, (reg1), (reg2)) +#define jitfp_ldxi_d(reg1, imm) _jit_ld(++_jit.fp, JIT_XI | 1, (reg1), (long)(imm)) +#define jitfp_ldxr_d(reg1, reg2) _jit_ld(++_jit.fp, JIT_XR | 1, (reg1), (reg2)) +#define jitfp_abs(op1) _jit_fn(++_jit.fp, JIT_ABS, (op1)) +#define jitfp_sqrt(op1) _jit_fn(++_jit.fp, JIT_SQRT, (op1)) +#define jitfp_neg(op1) _jit_fn(++_jit.fp, JIT_NEG, (op1)) +#define jitfp_stxi_f(imm, reg1, op1) _jit_emit(&_jit, (op1), JIT_XI, (reg1), (long)(imm), 0) +#define jitfp_stxr_f(reg1, reg2, op1) _jit_emit(&_jit, (op1), JIT_XR, (reg1), (reg2), 0) +#define jitfp_stxi_d(imm, reg1, op1) _jit_emit(&_jit, (op1), JIT_XI | 1, (reg1), (long)(imm), 0) +#define jitfp_stxr_d(reg1, reg2, op1) _jit_emit(&_jit, (op1), JIT_XR | 1, (reg1), (reg2), 0) +#define jitfp_cmp(regle, regge, op1) _jit_emit(&_jit, (op1), JIT_CMP, regle, regge, 0) +#define jitfp_floor(reg1, op1) _jit_emit(&_jit, (op1), JIT_FLOOR, reg1, 0, 0) +#define jitfp_ceil(reg1, op1) _jit_emit(&_jit, (op1), JIT_CEIL, reg1, 0, 0) +#define jitfp_trunc(reg1, op1) _jit_emit(&_jit, (op1), JIT_TRUNC, reg1, 0, 0) +#define jitfp_round(reg1, op1) _jit_emit(&_jit, (op1), JIT_ROUND, reg1, 0, 0) + + +#ifdef JIT_TRANSCENDENTAL +#define jitfp_sin(op1) _jit_fn(++_jit.fp, JIT_SIN, (op1)) +#define jitfp_cos(op1) _jit_fn(++_jit.fp, JIT_COS, (op1)) +#define jitfp_tan(op1) _jit_fn(++_jit.fp, JIT_TAN, (op1)) +#define jitfp_atn(op1) _jit_fn(++_jit.fp, JIT_ATN, (op1)) +#define jitfp_exp(op1) _jit_fn(++_jit.fp, JIT_EXP, (op1)) +#define jitfp_log(op1) _jit_fn(++_jit.fp, JIT_LOG, (op1)) +#endif + +#ifdef JIT_RZERO +#define jitfp_ldi_f(imm) _jit_ld(++_jit.fp, JIT_XI, JIT_RZERO, (long)(imm)) +#define jitfp_ldr_f(reg1) _jit_ld(++_jit.fp, JIT_XR, JIT_RZERO, (reg1)) +#define jitfp_ldi_d(imm) _jit_ld(++_jit.fp, JIT_XI | 1, JIT_RZERO, (long)(imm)) +#define jitfp_ldr_d(reg1) _jit_ld(++_jit.fp, JIT_XR | 1, JIT_RZERO, (reg1)) +#define jitfp_sti_f(imm, op1) _jit_emit(&_jit, (op1), JIT_XI, JIT_RZERO, (long)(imm), 0) +#define jitfp_str_f(reg1, op1) _jit_emit(&_jit, (op1), JIT_XR, JIT_RZERO, (reg1), 0) +#define jitfp_sti_d(imm, op1) _jit_emit(&_jit, (op1), JIT_XI | 1, JIT_RZERO, (long)(imm), 0) +#define jitfp_str_d(reg1, op1) _jit_emit(&_jit, (op1), JIT_XR | 1, JIT_RZERO, (reg1), 0) +#else +#define jitfp_ldi_f(imm) _jit_ld(++_jit.fp, JIT_I, 0, (long)(imm)) +#define jitfp_ldr_f(reg1) _jit_ld(++_jit.fp, JIT_R, (reg1), 0) +#define jitfp_ldi_d(imm) _jit_ld(++_jit.fp, JIT_I | 1, 0, (long)(imm)) +#define jitfp_ldr_d(reg1) _jit_ld(++_jit.fp, JIT_R | 1, (reg1), 0) +#define jitfp_sti_f(imm, op1) _jit_emit(&_jit, (op1), JIT_I, 0, (long)(imm), 0) +#define jitfp_str_f(reg1, op1) _jit_emit(&_jit, (op1), JIT_R, 0, (reg1), 0) +#define jitfp_sti_d(imm, op1) _jit_emit(&_jit, (op1), JIT_I | 1, 0, (long)(imm), 0) +#define jitfp_str_d(reg1, op1) _jit_emit(&_jit, (op1), JIT_R | 1, 0, (reg1), 0) +#endif + + +#endif diff --git a/lightning/funcs-common.h b/lightning/funcs-common.h new file mode 100644 index 000000000..dafae1f9e --- /dev/null +++ b/lightning/funcs-common.h @@ -0,0 +1,48 @@ +/******************************** -*- 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 2.1, 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. + * + ***********************************************************************/ + +#ifndef __lightning_funcs_common_h +#define __lightning_funcs_common_h + +#include +#include + +static int jit_fail(const char *, const char*, int, const char *) JIT_UNUSED; + +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/lightning/i386/asm.h b/lightning/i386/asm.h new file mode 100644 index 000000000..d805716b4 --- /dev/null +++ b/lightning/i386/asm.h @@ -0,0 +1,1060 @@ +/******************************** -*- C -*- **************************** + * + * Run-time assembler for the i386 + * + ***********************************************************************/ + + +/*********************************************************************** + * + * Copyright 1999, 2000, 2001, 2002 Ian Piumarta + * + * 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 2.1, 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. + * + ***********************************************************************/ + + + + +#ifndef __lightning_asm_h +#define __lightning_asm_h + +/* OPCODE + i = immediate operand + * + r = register operand + * + m = memory operand (disp,base,index,scale) + * + sr/sm = a star preceding a register or memory + */ + + +typedef _uc jit_insn; + +#define _b00 0 +#define _b01 1 +#define _b10 2 +#define _b11 3 + +#define _b000 0 +#define _b001 1 +#define _b010 2 +#define _b011 3 +#define _b100 4 +#define _b101 5 +#define _b110 6 +#define _b111 7 + +/*** REGISTERS ***/ /* [size,,number] */ + + +#define _AL 0x10 +#define _CL 0x11 +#define _DL 0x12 +#define _BL 0x13 +#define _AH 0x14 +#define _CH 0x15 +#define _DH 0x16 +#define _BH 0x17 + +#define _AX 0x20 +#define _CX 0x21 +#define _DX 0x22 +#define _BX 0x23 +#define _SP 0x24 +#define _BP 0x25 +#define _SI 0x26 +#define _DI 0x27 + +#define _EAX 0x40 +#define _ECX 0x41 +#define _EDX 0x42 +#define _EBX 0x43 +#define _ESP 0x44 +#define _EBP 0x45 +#define _ESI 0x46 +#define _EDI 0x47 + +#define _ST0 0 +#define _ST1 1 +#define _ST2 2 +#define _ST3 3 +#define _ST4 4 +#define _ST5 5 +#define _ST6 6 +#define _ST7 7 + +#define _rS(R) ((R)>>4) +#define _rN(R) ((R)&0x7) +#define _r0P(R) ((R)==0) + +#ifndef _ASM_SAFETY +#define _r1(R) _rN(R) +#define _r2(R) _rN(R) +#define _r4(R) _rN(R) +#else +#define _r1(R) ((_rS(R)==1) ? _rN(R) : JITFAIL( "8-bit register required")) +#define _r2(R) ((_rS(R)==2) ? _rN(R) : JITFAIL("16-bit register required")) +#define _r4(R) ((_rS(R)==4) ? _rN(R) : JITFAIL("32-bit register required")) +#endif + +/*** ASSEMBLER ***/ + +#define _OFF4(D) (_jit_UL(D) - _jit_UL(_jit.x.pc)) +#define _CKD8(D) _ck_d(8, ((_uc) _OFF4(D)) ) + +#define _D8(D) (_jit_B(0), ((*(_PUC(_jit.x.pc)-1))= _CKD8(D))) +#define _D32(D) (_jit_L(0), ((*(_PUL(_jit.x.pc)-1))= _OFF4(D))) + +#ifndef _ASM_SAFETY +# define _M(M) (M) +# define _r(R) (R) +# define _m(M) (M) +# define _s(S) (S) +# define _i(I) (I) +# define _b(B) (B) +# define _noESP(I,OK) (OK) +#else +# define _M(M) (((M)>3) ? JITFAIL("internal error: mod = " #M) : (M)) +# define _r(R) (((R)>7) ? JITFAIL("internal error: reg = " #R) : (R)) +# define _m(M) (((M)>7) ? JITFAIL("internal error: r/m = " #M) : (M)) +# define _s(S) (((S)>3) ? JITFAIL("internal error: memory scale = " #S) : (S)) +# define _i(I) (((I)>7) ? JITFAIL("internal error: memory index = " #I) : (I)) +# define _b(B) (((B)>7) ? JITFAIL("internal error: memory base = " #B) : (B)) +# define _noESP(I,OK) (((I)==_ESP) ? JITFAIL("illegal index register: %esp") : (OK)) +#endif + +#define _Mrm(Md,R,M) _jit_B((_M(Md)<<6)|(_r(R)<<3)|_m(M)) +#define _SIB(Sc,I, B) _jit_B((_s(Sc)<<6)|(_i(I)<<3)|_b(B)) + +#define _SCL(S) ((((S)==1) ? _b00 : \ + (((S)==2) ? _b01 : \ + (((S)==4) ? _b10 : \ + (((S)==8) ? _b11 : JITFAIL("illegal scale: " #S)))))) + +/* memory subformats - urgh! */ + +#define _r_D( R, D ) (_Mrm(_b00,_rN(R),_b101 ) ,_jit_L((long)(D))) +#define _r_0B( R, B ) (_Mrm(_b00,_rN(R),_r4(B)) ) +#define _r_0BIS(R, B,I,S) (_Mrm(_b00,_rN(R),_b100 ),_SIB(_SCL(S),_r4(I),_r4(B)) ) +#define _r_1B( R, D,B ) (_Mrm(_b01,_rN(R),_r4(B)) ,_jit_B((long)(D))) +#define _r_1BIS(R, D,B,I,S) (_Mrm(_b01,_rN(R),_b100 ),_SIB(_SCL(S),_r4(I),_r4(B)),_jit_B((long)(D))) +#define _r_4B( R, D,B ) (_Mrm(_b10,_rN(R),_r4(B)) ,_jit_L((long)(D))) +#define _r_4IS( R, D,I,S) (_Mrm(_b00,_rN(R),_b100 ),_SIB(_SCL(S),_r4(I),_b101 ),_jit_L((long)(D))) +#define _r_4BIS(R, D,B,I,S) (_Mrm(_b10,_rN(R),_b100 ),_SIB(_SCL(S),_r4(I),_r4(B)),_jit_L((long)(D))) + +#define _r_DB( R, D,B ) ((_s0P(D) && (B != _EBP) ? _r_0B (R, B ) : (_s8P(D) ? _r_1B( R,D,B ) : _r_4B( R,D,B )))) +#define _r_DBIS(R, D,B,I,S) ((_s0P(D) ? _r_0BIS(R, B,I,S) : (_s8P(D) ? _r_1BIS(R,D,B,I,S) : _r_4BIS(R,D,B,I,S)))) + +#define _r_X( R, D,B,I,S) (_r0P(I) ? (_r0P(B) ? _r_D (R,D ) : \ + (_ESP==(B) ? _r_DBIS(R,D,_ESP,_ESP,1) : \ + _r_DB (R,D, B ))) : \ + (_r0P(B) ? _r_4IS (R,D, I,S) : \ + (((I)!=_ESP) ? _r_DBIS(R,D, B, I,S) : \ + JITFAIL("illegal index register: %esp")))) + + +/* instruction formats */ + +/* _format Opcd ModR/M dN(rB,rI,Sc) imm... */ + +#define _d16() ( _jit_B(0x66 ) ) +#define _O( OP ) ( _jit_B( OP ) ) +#define _Or( OP,R ) ( _jit_B( (OP)|_r(R)) ) +#define _OO( OP ) ( _jit_B((OP)>>8), _jit_B( (OP) ) ) +#define _OOr( OP,R ) ( _jit_B((OP)>>8), _jit_B( (OP)|_r(R)) ) +#define _Os( OP,B ) ( _s8P(B) ? _jit_B(((OP)|_b10)) : _jit_B(OP) ) +#define _sW( W ) ( _s8P(W) ? _jit_B(W):_jit_W(W) ) +#define _sL( L ) ( _s8P(L) ? _jit_B(L):_jit_L(L) ) +#define _O_W( OP ,W ) ( _O ( OP ) ,_jit_W(W) ) +#define _O_D8( OP ,D ) ( _O ( OP ) ,_D8(D) ) +#define _O_D32( OP ,D ) ( _O ( OP ) ,_D32(D) ) +#define _OO_D32( OP ,D ) ( _OO ( OP ) ,_D32(D) ) +#define _Os_sW( OP ,W ) ( _Os ( OP,W) ,_sW(W) ) +#define _Os_sL( OP ,L ) ( _Os ( OP,L) ,_sL(L) ) +#define _O_W_B( OP ,W,B) ( _O ( OP ) ,_jit_W(W),_jit_B(B)) +#define _Or_B( OP,R ,B ) ( _Or ( OP,R) ,_jit_B(B) ) +#define _Or_W( OP,R ,W ) ( _Or ( OP,R) ,_jit_W(W) ) +#define _Or_L( OP,R ,L ) ( _Or ( OP,R) ,_jit_L(L) ) +#define _O_Mrm( OP ,MO,R,M ) ( _O ( OP ),_Mrm(MO,R,M ) ) +#define _OO_Mrm( OP ,MO,R,M ) ( _OO ( OP ),_Mrm(MO,R,M ) ) +#define _O_Mrm_B( OP ,MO,R,M ,B ) ( _O ( OP ),_Mrm(MO,R,M ) ,_jit_B(B) ) +#define _O_Mrm_W( OP ,MO,R,M ,W ) ( _O ( OP ),_Mrm(MO,R,M ) ,_jit_W(W) ) +#define _O_Mrm_L( OP ,MO,R,M ,L ) ( _O ( OP ),_Mrm(MO,R,M ) ,_jit_L(L) ) +#define _OO_Mrm_B( OP ,MO,R,M ,B ) ( _OO ( OP ),_Mrm(MO,R,M ) ,_jit_B(B) ) +#define _Os_Mrm_sW(OP ,MO,R,M ,W ) ( _Os ( OP,W),_Mrm(MO,R,M ),_sW(W) ) +#define _Os_Mrm_sL(OP ,MO,R,M ,L ) ( _Os ( OP,L),_Mrm(MO,R,M ),_sL(L) ) +#define _O_r_X( OP ,R ,MD,MB,MI,MS ) ( _O ( OP ),_r_X( R ,MD,MB,MI,MS) ) +#define _OO_r_X( OP ,R ,MD,MB,MI,MS ) ( _OO ( OP ),_r_X( R ,MD,MB,MI,MS) ) +#define _O_r_X_B( OP ,R ,MD,MB,MI,MS,B ) ( _O ( OP ),_r_X( R ,MD,MB,MI,MS) ,_jit_B(B) ) +#define _O_r_X_W( OP ,R ,MD,MB,MI,MS,W ) ( _O ( OP ),_r_X( R ,MD,MB,MI,MS) ,_jit_W(W) ) +#define _O_r_X_L( OP ,R ,MD,MB,MI,MS,L ) ( _O ( OP ),_r_X( R ,MD,MB,MI,MS) ,_jit_L(L) ) +#define _OO_r_X_B( OP ,R ,MD,MB,MI,MS,B ) ( _OO ( OP ),_r_X( R ,MD,MB,MI,MS) ,_jit_B(B) ) +#define _Os_r_X_sW(OP ,R ,MD,MB,MI,MS,W ) ( _Os ( OP,W),_r_X( R ,MD,MB,MI,MS),_sW(W) ) +#define _Os_r_X_sL(OP ,R ,MD,MB,MI,MS,L ) ( _Os ( OP,L),_r_X( R ,MD,MB,MI,MS),_sL(L) ) +#define _O_X_B( OP ,MD,MB,MI,MS,B ) ( _O_r_X_B( OP ,0 ,MD,MB,MI,MS ,B) ) +#define _O_X_W( OP ,MD,MB,MI,MS,W ) ( _O_r_X_W( OP ,0 ,MD,MB,MI,MS ,W) ) +#define _O_X_L( OP ,MD,MB,MI,MS,L ) ( _O_r_X_L( OP ,0 ,MD,MB,MI,MS ,L) ) +#define _wO( OP ) (_d16(), _O( OP ) ) +#define _wOr( OP,R ) (_d16(), _Or( OP,R ) ) +#define _wOr_W( OP,R ,W ) (_d16(), _Or_W( OP,R ,W) ) +#define _wOs_sW( OP ,W ) (_d16(), _Os_sW( OP ,W) ) +#define _wO_Mrm( OP ,MO,R,M ) (_d16(), _O_Mrm( OP ,MO,R,M ) ) +#define _wOO_Mrm( OP ,MO,R,M ) (_d16(),_OO_Mrm( OP ,MO,R,M ) ) +#define _wO_Mrm_B( OP ,MO,R,M ,B ) (_d16(), _O_Mrm_B( OP ,MO,R,M ,B) ) +#define _wOO_Mrm_B( OP ,MO,R,M ,B ) (_d16(),_OO_Mrm_B( OP ,MO,R,M ,B) ) +#define _wO_Mrm_W( OP ,MO,R,M ,W ) (_d16(), _O_Mrm_W( OP ,MO,R,M ,W) ) +#define _wOs_Mrm_sW(OP ,MO,R,M ,W ) (_d16(), _Os_Mrm_sW(OP ,MO,R,M ,W) ) +#define _wO_X_W( OP ,MD,MB,MI,MS,W ) (_d16(), _O_X_W( OP ,MD,MB,MI,MS ,W) ) +#define _wO_r_X( OP ,R ,MD,MB,MI,MS ) (_d16(), _O_r_X( OP ,R ,MD,MB,MI,MS ) ) +#define _wOO_r_X( OP ,R ,MD,MB,MI,MS ) (_d16(),_OO_r_X( OP ,R ,MD,MB,MI,MS ) ) +#define _wO_r_X_B( OP ,R ,MD,MB,MI,MS,B ) (_d16(), _O_r_X_B( OP ,R ,MD,MB,MI,MS ,B) ) +#define _wOO_r_X_B( OP ,R ,MD,MB,MI,MS,B ) (_d16(),_OO_r_X_B( OP ,R ,MD,MB,MI,MS ,B) ) +#define _wO_r_X_W( OP ,R ,MD,MB,MI,MS,W ) (_d16(), _O_r_X_W( OP ,R ,MD,MB,MI,MS ,W) ) +#define _wOs_r_X_sW(OP ,R ,MD,MB,MI,MS,W ) (_d16(), _Os_r_X_sW(OP ,R ,MD,MB,MI,MS ,W) ) + +/* +++ fully-qualified intrinsic instructions */ + +/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ + +#define ADCBrr(RS, RD) _O_Mrm (0x10 ,_b11,_r1(RS),_r1(RD) ) +#define ADCBmr(MD, MB, MI, MS, RD) _O_r_X (0x12 ,_r1(RD) ,MD,MB,MI,MS ) +#define ADCBrm(RS, MD, MB, MI, MS) _O_r_X (0x10 ,_r1(RS) ,MD,MB,MI,MS ) +#define ADCBir(IM, RD) _O_Mrm_B (0x80 ,_b11,_b010 ,_r1(RD) ,_su8(IM)) +#define ADCBim(IM, MD, MB, MI, MS) _O_r_X_B (0x80 ,_b010 ,MD,MB,MI,MS ,_su8(IM)) + +#define ADCWrr(RS, RD) _wO_Mrm (0x11 ,_b11,_r2(RS),_r2(RD) ) +#define ADCWmr(MD, MB, MI, MS, RD) _wO_r_X (0x13 ,_r2(RD) ,MD,MB,MI,MS ) +#define ADCWrm(RS, MD, MB, MI, MS) _wO_r_X (0x11 ,_r2(RS) ,MD,MB,MI,MS ) +#define ADCWir(IM, RD) _wOs_Mrm_sW (0x81 ,_b11,_b010 ,_r2(RD) ,_su16(IM)) +#define ADCWim(IM, MD, MB, MI, MS) _wOs_r_X_sW (0x81 ,_b010 ,MD,MB,MI,MS ,_su16(IM)) + +#define ADCLrr(RS, RD) _O_Mrm (0x11 ,_b11,_r4(RS),_r4(RD) ) +#define ADCLmr(MD, MB, MI, MS, RD) _O_r_X (0x13 ,_r4(RD) ,MD,MB,MI,MS ) +#define ADCLrm(RS, MD, MB, MI, MS) _O_r_X (0x11 ,_r4(RS) ,MD,MB,MI,MS ) +#define ADCLir(IM, RD) _Os_Mrm_sL (0x81 ,_b11,_b010 ,_r4(RD) ,IM ) +#define ADCLim(IM, MD, MB, MI, MS) _Os_r_X_sL (0x81 ,_b010 ,MD,MB,MI,MS ,IM ) + + +#define ADDBrr(RS, RD) _O_Mrm (0x00 ,_b11,_r1(RS),_r1(RD) ) +#define ADDBmr(MD, MB, MI, MS, RD) _O_r_X (0x02 ,_r1(RD) ,MD,MB,MI,MS ) +#define ADDBrm(RS, MD, MB, MI, MS) _O_r_X (0x00 ,_r1(RS) ,MD,MB,MI,MS ) +#define ADDBir(IM, RD) _O_Mrm_B (0x80 ,_b11,_b000 ,_r1(RD) ,_su8(IM)) +#define ADDBim(IM, MD, MB, MI, MS) _O_r_X_B (0x80 ,_b000 ,MD,MB,MI,MS ,_su8(IM)) + +#define ADDWrr(RS, RD) _wO_Mrm (0x01 ,_b11,_r2(RS),_r2(RD) ) +#define ADDWmr(MD, MB, MI, MS, RD) _wO_r_X (0x03 ,_r2(RD) ,MD,MB,MI,MS ) +#define ADDWrm(RS, MD, MB, MI, MS) _wO_r_X (0x01 ,_r2(RS) ,MD,MB,MI,MS ) +#define ADDWir(IM, RD) _wOs_Mrm_sW (0x81 ,_b11,_b000 ,_r2(RD) ,_su16(IM)) +#define ADDWim(IM, MD, MB, MI, MS) _wOs_r_X_sW (0x81 ,_b000 ,MD,MB,MI,MS ,_su16(IM)) + +#define ADDLrr(RS, RD) _O_Mrm (0x01 ,_b11,_r4(RS),_r4(RD) ) +#define ADDLmr(MD, MB, MI, MS, RD) _O_r_X (0x03 ,_r4(RD) ,MD,MB,MI,MS ) +#define ADDLrm(RS, MD, MB, MI, MS) _O_r_X (0x01 ,_r4(RS) ,MD,MB,MI,MS ) +#define ADDLir(IM, RD) _Os_Mrm_sL (0x81 ,_b11,_b000 ,_r4(RD) ,IM ) +#define ADDLim(IM, MD, MB, MI, MS) _Os_r_X_sL (0x81 ,_b000 ,MD,MB,MI,MS ,IM ) + + +#define ANDBrr(RS, RD) _O_Mrm (0x20 ,_b11,_r1(RS),_r1(RD) ) +#define ANDBmr(MD, MB, MI, MS, RD) _O_r_X (0x22 ,_r1(RD) ,MD,MB,MI,MS ) +#define ANDBrm(RS, MD, MB, MI, MS) _O_r_X (0x20 ,_r1(RS) ,MD,MB,MI,MS ) +#define ANDBir(IM, RD) _O_Mrm_B (0x80 ,_b11,_b100 ,_r1(RD) ,_su8(IM)) +#define ANDBim(IM, MD, MB, MI, MS) _O_r_X_B (0x80 ,_b100 ,MD,MB,MI,MS ,_su8(IM)) + +#define ANDWrr(RS, RD) _wO_Mrm (0x21 ,_b11,_r2(RS),_r2(RD) ) +#define ANDWmr(MD, MB, MI, MS, RD) _wO_r_X (0x23 ,_r2(RD) ,MD,MB,MI,MS ) +#define ANDWrm(RS, MD, MB, MI, MS) _wO_r_X (0x21 ,_r2(RS) ,MD,MB,MI,MS ) +#define ANDWir(IM, RD) _wOs_Mrm_sW (0x81 ,_b11,_b100 ,_r2(RD) ,_su16(IM)) +#define ANDWim(IM, MD, MB, MI, MS) _wOs_r_X_sW (0x81 ,_b100 ,MD,MB,MI,MS ,_su16(IM)) + +#define ANDLrr(RS, RD) _O_Mrm (0x21 ,_b11,_r4(RS),_r4(RD) ) +#define ANDLmr(MD, MB, MI, MS, RD) _O_r_X (0x23 ,_r4(RD) ,MD,MB,MI,MS ) +#define ANDLrm(RS, MD, MB, MI, MS) _O_r_X (0x21 ,_r4(RS) ,MD,MB,MI,MS ) +#define ANDLir(IM, RD) _Os_Mrm_sL (0x81 ,_b11,_b100 ,_r4(RD) ,IM ) +#define ANDLim(IM, MD, MB, MI, MS) _Os_r_X_sL (0x81 ,_b100 ,MD,MB,MI,MS ,IM ) + + +#define BSWAPLr(R) _OOr (0x0fc8,_r4(R) ) + + +#define BTWir(IM,RD) _wOO_Mrm_B (0x0fba ,_b11,_b100 ,_r2(RD) ,_u8(IM)) +#define BTWim(IM,MD,MB,MI,MS) _wOO_r_X_B (0x0fba ,_b100 ,MD,MB,MI,MS ,_u8(IM)) +#define BTWrr(RS,RD) _wOO_Mrm (0x0fa3 ,_b11,_r2(RS),_r2(RD) ) +#define BTWrm(RS,MD,MB,MI,MS) _wOO_r_X (0x0fa3 ,_r2(RS) ,MD,MB,MI,MS ) + +#define BTLir(IM,RD) _OO_Mrm_B (0x0fba ,_b11,_b100 ,_r4(RD) ,_u8(IM)) +#define BTLim(IM,MD,MB,MI,MS) _OO_r_X_B (0x0fba ,_b100 ,MD,MB,MI,MS ,_u8(IM)) +#define BTLrr(RS,RD) _OO_Mrm (0x0fa3 ,_b11,_r4(RS),_r4(RD) ) +#define BTLrm(RS,MD,MB,MI,MS) _OO_r_X (0x0fa3 ,_r4(RS) ,MD,MB,MI,MS ) + + +#define BTCWir(IM,RD) _wOO_Mrm_B (0x0fba ,_b11,_b111 ,_r2(RD) ,_u8(IM)) +#define BTCWim(IM,MD,MB,MI,MS) _wOO_r_X_B (0x0fba ,_b111 ,MD,MB,MI,MS ,_u8(IM)) +#define BTCWrr(RS,RD) _wOO_Mrm (0x0fbb ,_b11,_r2(RS),_r2(RD) ) +#define BTCWrm(RS,MD,MB,MI,MS) _wOO_r_X (0x0fbb ,_r2(RS) ,MD,MB,MI,MS ) + +#define BTCLir(IM,RD) _OO_Mrm_B (0x0fba ,_b11,_b111 ,_r4(RD) ,_u8(IM)) +#define BTCLim(IM,MD,MB,MI,MS) _OO_r_X_B (0x0fba ,_b111 ,MD,MB,MI,MS ,_u8(IM)) +#define BTCLrr(RS,RD) _OO_Mrm (0x0fbb ,_b11,_r4(RS),_r4(RD) ) +#define BTCLrm(RS,MD,MB,MI,MS) _OO_r_X (0x0fbb ,_r4(RS) ,MD,MB,MI,MS ) + + +#define BTRWir(IM,RD) _wOO_Mrm_B (0x0fba ,_b11,_b110 ,_r2(RD) ,_u8(IM)) +#define BTRWim(IM,MD,MB,MI,MS) _wOO_r_X_B (0x0fba ,_b110 ,MD,MB,MI,MS ,_u8(IM)) +#define BTRWrr(RS,RD) _wOO_Mrm (0x0fb3 ,_b11,_r2(RS),_r2(RD) ) +#define BTRWrm(RS,MD,MB,MI,MS) _wOO_r_X (0x0fb3 ,_r2(RS) ,MD,MB,MI,MS ) + +#define BTRLir(IM,RD) _OO_Mrm_B (0x0fba ,_b11,_b110 ,_r4(RD) ,_u8(IM)) +#define BTRLim(IM,MD,MB,MI,MS) _OO_r_X_B (0x0fba ,_b110 ,MD,MB,MI,MS ,_u8(IM)) +#define BTRLrr(RS,RD) _OO_Mrm (0x0fb3 ,_b11,_r4(RS),_r4(RD) ) +#define BTRLrm(RS,MD,MB,MI,MS) _OO_r_X (0x0fb3 ,_r4(RS) ,MD,MB,MI,MS ) + + +#define BTSWir(IM,RD) _wOO_Mrm_B (0x0fba ,_b11,_b101 ,_r2(RD) ,_u8(IM)) +#define BTSWim(IM,MD,MB,MI,MS) _wOO_r_X_B (0x0fba ,_b101 ,MD,MB,MI,MS ,_u8(IM)) +#define BTSWrr(RS,RD) _wOO_Mrm (0x0fab ,_b11,_r2(RS),_r2(RD) ) +#define BTSWrm(RS,MD,MB,MI,MS) _wOO_r_X (0x0fab ,_r2(RS) ,MD,MB,MI,MS ) + +#define BTSLir(IM,RD) _OO_Mrm_B (0x0fba ,_b11,_b101 ,_r4(RD) ,_u8(IM)) +#define BTSLim(IM,MD,MB,MI,MS) _OO_r_X_B (0x0fba ,_b101 ,MD,MB,MI,MS ,_u8(IM)) +#define BTSLrr(RS,RD) _OO_Mrm (0x0fab ,_b11,_r4(RS),_r4(RD) ) +#define BTSLrm(RS,MD,MB,MI,MS) _OO_r_X (0x0fab ,_r4(RS) ,MD,MB,MI,MS ) + + +#define CALLm(D,B,I,S) ((_r0P(B) && _r0P(I)) ? _O_D32 (0xe8 ,(int)(D) ) : \ + JITFAIL("illegal mode in direct jump")) + +#define CALLsr(R) _O_Mrm (0xff ,_b11,_b010,_r4(R) ) + +#define CALLsm(D,B,I,S) _O_r_X (0xff ,_b010 ,(int)(D),B,I,S ) + +#define CBW() _O (0x98 ) +#define CLC() _O (0xf8 ) +#define CLTD() _O (0x99 ) +#define CMC() _O (0xf5 ) + + +#define CMPBrr(RS, RD) _O_Mrm (0x38 ,_b11,_r1(RS),_r1(RD) ) +#define CMPBmr(MD, MB, MI, MS, RD) _O_r_X (0x3a ,_r1(RD) ,MD,MB,MI,MS ) +#define CMPBrm(RS, MD, MB, MI, MS) _O_r_X (0x38 ,_r1(RS) ,MD,MB,MI,MS ) +#define CMPBir(IM, RD) _O_Mrm_B (0x80 ,_b11,_b111 ,_r1(RD) ,_su8(IM)) +#define CMPBim(IM, MD, MB, MI, MS) _O_r_X_B (0x80 ,_b111 ,MD,MB,MI,MS ,_su8(IM)) + +#define CMPWrr(RS, RD) _wO_Mrm (0x39 ,_b11,_r2(RS),_r2(RD) ) +#define CMPWmr(MD, MB, MI, MS, RD) _wO_r_X (0x3b ,_r2(RD) ,MD,MB,MI,MS ) +#define CMPWrm(RS, MD, MB, MI, MS) _wO_r_X (0x39 ,_r2(RS) ,MD,MB,MI,MS ) +#define CMPWir(IM, RD) _wOs_Mrm_sW (0x81 ,_b11,_b111 ,_r2(RD) ,_su16(IM)) +#define CMPWim(IM, MD, MB, MI, MS) _wOs_r_X_sW (0x81 ,_b111 ,MD,MB,MI,MS ,_su16(IM)) + +#define CMPLrr(RS, RD) _O_Mrm (0x39 ,_b11,_r4(RS),_r4(RD) ) +#define CMPLmr(MD, MB, MI, MS, RD) _O_r_X (0x3b ,_r4(RD) ,MD,MB,MI,MS ) +#define CMPLrm(RS, MD, MB, MI, MS) _O_r_X (0x39 ,_r4(RS) ,MD,MB,MI,MS ) +#define CMPLir(IM, RD) _O_Mrm_L (0x81 ,_b11,_b111 ,_r4(RD) ,IM ) +#define CMPLim(IM, MD, MB, MI, MS) _O_r_X_L (0x81 ,_b111 ,MD,MB,MI,MS ,IM ) + + +#define CWD() _O (0x99 ) + + +#define CMPXCHGBrr(RS,RD) _OO_Mrm (0x0fb0 ,_b11,_r1(RS),_r1(RD) ) +#define CMPXCHGBrm(RS,MD,MB,MI,MS) _OO_r_X (0x0fb0 ,_r1(RS) ,MD,MB,MI,MS ) + +#define CMPXCHGWrr(RS,RD) _wOO_Mrm (0x0fb1 ,_b11,_r2(RS),_r2(RD) ) +#define CMPXCHGWrm(RS,MD,MB,MI,MS) _wOO_r_X (0x0fb1 ,_r2(RS) ,MD,MB,MI,MS ) + +#define CMPXCHGLrr(RS,RD) _OO_Mrm (0x0fb1 ,_b11,_r4(RS),_r4(RD) ) +#define CMPXCHGLrm(RS,MD,MB,MI,MS) _OO_r_X (0x0fb1 ,_r4(RS) ,MD,MB,MI,MS ) + + +#define DECBr(RD) _O_Mrm (0xfe ,_b11,_b001 ,_r1(RD) ) +#define DECBm(MD,MB,MI,MS) _O_r_X (0xfe ,_b001 ,MD,MB,MI,MS ) + +#define DECWr(RD) _wOr (0x48,_r2(RD) ) +#define DECWm(MD,MB,MI,MS) _wO_r_X (0xff ,_b001 ,MD,MB,MI,MS ) + +#define DECLr(RD) _Or (0x48,_r4(RD) ) +#define DECLm(MD,MB,MI,MS) _O_r_X (0xff ,_b001 ,MD,MB,MI,MS ) + + +#define DIVBr(RS) _O_Mrm (0xf6 ,_b11,_b110 ,_r1(RS) ) +#define DIVBm(MD,MB,MI,MS) _O_r_X (0xf6 ,_b110 ,MD,MB,MI,MS ) + +#define DIVWr(RS) _wO_Mrm (0xf7 ,_b11,_b110 ,_r2(RS) ) +#define DIVWm(MD,MB,MI,MS) _wO_r_X (0xf7 ,_b110 ,MD,MB,MI,MS ) + +#define DIVLr(RS) _O_Mrm (0xf7 ,_b11,_b110 ,_r4(RS) ) +#define DIVLm(MD,MB,MI,MS) _O_r_X (0xf7 ,_b110 ,MD,MB,MI,MS ) + + +#define ENTERii(W, B) _O_W_B (0xc8 ,_su16(W),_su8(B)) +#define HLT() _O (0xf4 ) + + +#define IDIVBr(RS) _O_Mrm (0xf6 ,_b11,_b111 ,_r1(RS) ) +#define IDIVBm(MD,MB,MI,MS) _O_r_X (0xf6 ,_b111 ,MD,MB,MI,MS ) + +#define IDIVWr(RS) _wO_Mrm (0xf7 ,_b11,_b111 ,_r2(RS) ) +#define IDIVWm(MD,MB,MI,MS) _wO_r_X (0xf7 ,_b111 ,MD,MB,MI,MS ) + +#define IDIVLr(RS) _O_Mrm (0xf7 ,_b11,_b111 ,_r4(RS) ) +#define IDIVLm(MD,MB,MI,MS) _O_r_X (0xf7 ,_b111 ,MD,MB,MI,MS ) + +#define IMULBr(RS) _O_Mrm (0xf6 ,_b11,_b101 ,_r1(RS) ) +#define IMULBm(MD,MB,MI,MS) _O_r_X (0xf6 ,_b101 ,MD,MB,MI,MS ) + +#define IMULWr(RS) _wO_Mrm (0xf7 ,_b11,_b101 ,_r2(RS) ) +#define IMULWm(MD,MB,MI,MS) _wO_r_X (0xf7 ,_b101 ,MD,MB,MI,MS ) + +#define IMULLr(RS) _O_Mrm (0xf7 ,_b11,_b101 ,_r4(RS) ) +#define IMULLm(MD,MB,MI,MS) _O_r_X (0xf7 ,_b101 ,MD,MB,MI,MS ) + + +#define IMULWrr(RS,RD) _wOO_Mrm (0x0faf ,_b11,_r2(RS),_r2(RD) ) +#define IMULWmr(MD,MB,MI,MS,RD) _wOO_r_X (0x0faf ,_r2(RD) ,MD,MB,MI,MS ) +#define IMULWirr(IM,RS,RD) _wOs_Mrm_sW (0x69 ,_b11,_r2(RS),_r2(RD) ,_su16(IM) ) +#define IMULWimr(IM,MD,MB,MI,MS,RD) _wOs_r_X_sW (0x69 ,_r2(RD) ,MD,MB,MI,MS ,_su16(IM) ) + +#define IMULLir(IM,RD) _Os_Mrm_sL (0x69 ,_b11,_r4(RD),_r4(RD) ,IM ) +#define IMULLrr(RS,RD) _OO_Mrm (0x0faf ,_b11,_r4(RD),_r4(RS) ) +#define IMULLmr(MD,MB,MI,MS,RD) _OO_r_X (0x0faf ,_r4(RD) ,MD,MB,MI,MS ) +#define IMULLirr(IM,RS,RD) _Os_Mrm_sL (0x69 ,_b11,_r4(RS),_r4(RD) ,IM ) +#define IMULLimr(IM,MD,MB,MI,MS,RD) _Os_r_X_sL (0x69 ,_r4(RD) ,MD,MB,MI,MS ,IM ) + + +#define INCBr(RD) _O_Mrm (0xfe ,_b11,_b000 ,_r1(RD) ) +#define INCBm(MD,MB,MI,MS) _O_r_X (0xfe ,_b000 ,MD,MB,MI,MS ) + +#define INCWr(RD) _wOr (0x40,_r2(RD) ) +#define INCWm(MD,MB,MI,MS) _wO_r_X (0xff ,_b000 ,MD,MB,MI,MS ) + +#define INCLr(RD) _Or (0x40,_r4(RD) ) +#define INCLm(MD,MB,MI,MS) _O_r_X (0xff ,_b000 ,MD,MB,MI,MS ) + + +#define INVD() _OO (0x0f08 ) +#define INVLPGm(MD, MB, MI, MS) _OO_r_X (0x0f01 ,_b111 ,MD,MB,MI,MS ) + + +#define JCCSim(CC,D,B,I,S) ((_r0P(B) && _r0P(I)) ? _O_D8 (0x70|(CC) ,(int)(D) ) : \ + JITFAIL("illegal mode in conditional jump")) + +#define JOSm(D,B,I,S) JCCSim(0x0,D,B,I,S) +#define JNOSm(D,B,I,S) JCCSim(0x1,D,B,I,S) +#define JBSm(D,B,I,S) JCCSim(0x2,D,B,I,S) +#define JNAESm(D,B,I,S) JCCSim(0x2,D,B,I,S) +#define JNBSm(D,B,I,S) JCCSim(0x3,D,B,I,S) +#define JAESm(D,B,I,S) JCCSim(0x3,D,B,I,S) +#define JESm(D,B,I,S) JCCSim(0x4,D,B,I,S) +#define JZSm(D,B,I,S) JCCSim(0x4,D,B,I,S) +#define JNESm(D,B,I,S) JCCSim(0x5,D,B,I,S) +#define JNZSm(D,B,I,S) JCCSim(0x5,D,B,I,S) +#define JBESm(D,B,I,S) JCCSim(0x6,D,B,I,S) +#define JNASm(D,B,I,S) JCCSim(0x6,D,B,I,S) +#define JNBESm(D,B,I,S) JCCSim(0x7,D,B,I,S) +#define JASm(D,B,I,S) JCCSim(0x7,D,B,I,S) +#define JSSm(D,B,I,S) JCCSim(0x8,D,B,I,S) +#define JNSSm(D,B,I,S) JCCSim(0x9,D,B,I,S) +#define JPSm(D,B,I,S) JCCSim(0xa,D,B,I,S) +#define JPESm(D,B,I,S) JCCSim(0xa,D,B,I,S) +#define JNPSm(D,B,I,S) JCCSim(0xb,D,B,I,S) +#define JPOSm(D,B,I,S) JCCSim(0xb,D,B,I,S) +#define JLSm(D,B,I,S) JCCSim(0xc,D,B,I,S) +#define JNGESm(D,B,I,S) JCCSim(0xc,D,B,I,S) +#define JNLSm(D,B,I,S) JCCSim(0xd,D,B,I,S) +#define JGESm(D,B,I,S) JCCSim(0xd,D,B,I,S) +#define JLESm(D,B,I,S) JCCSim(0xe,D,B,I,S) +#define JNGSm(D,B,I,S) JCCSim(0xe,D,B,I,S) +#define JNLESm(D,B,I,S) JCCSim(0xf,D,B,I,S) +#define JGSm(D,B,I,S) JCCSim(0xf,D,B,I,S) + +#define JCCim(CC,D,B,I,S) ((_r0P(B) && _r0P(I)) ? _OO_D32 (0x0f80|(CC) ,(int)(D) ) : \ + JITFAIL("illegal mode in conditional jump")) + +#define JOm(D,B,I,S) JCCim(0x0,D,B,I,S) +#define JNOm(D,B,I,S) JCCim(0x1,D,B,I,S) +#define JBm(D,B,I,S) JCCim(0x2,D,B,I,S) +#define JNAEm(D,B,I,S) JCCim(0x2,D,B,I,S) +#define JNBm(D,B,I,S) JCCim(0x3,D,B,I,S) +#define JAEm(D,B,I,S) JCCim(0x3,D,B,I,S) +#define JEm(D,B,I,S) JCCim(0x4,D,B,I,S) +#define JZm(D,B,I,S) JCCim(0x4,D,B,I,S) +#define JNEm(D,B,I,S) JCCim(0x5,D,B,I,S) +#define JNZm(D,B,I,S) JCCim(0x5,D,B,I,S) +#define JBEm(D,B,I,S) JCCim(0x6,D,B,I,S) +#define JNAm(D,B,I,S) JCCim(0x6,D,B,I,S) +#define JNBEm(D,B,I,S) JCCim(0x7,D,B,I,S) +#define JAm(D,B,I,S) JCCim(0x7,D,B,I,S) +#define JSm(D,B,I,S) JCCim(0x8,D,B,I,S) +#define JNSm(D,B,I,S) JCCim(0x9,D,B,I,S) +#define JPm(D,B,I,S) JCCim(0xa,D,B,I,S) +#define JPEm(D,B,I,S) JCCim(0xa,D,B,I,S) +#define JNPm(D,B,I,S) JCCim(0xb,D,B,I,S) +#define JPOm(D,B,I,S) JCCim(0xb,D,B,I,S) +#define JLm(D,B,I,S) JCCim(0xc,D,B,I,S) +#define JNGEm(D,B,I,S) JCCim(0xc,D,B,I,S) +#define JNLm(D,B,I,S) JCCim(0xd,D,B,I,S) +#define JGEm(D,B,I,S) JCCim(0xd,D,B,I,S) +#define JLEm(D,B,I,S) JCCim(0xe,D,B,I,S) +#define JNGm(D,B,I,S) JCCim(0xe,D,B,I,S) +#define JNLEm(D,B,I,S) JCCim(0xf,D,B,I,S) +#define JGm(D,B,I,S) JCCim(0xf,D,B,I,S) + + +#define JMPSm(D,B,I,S) ((_r0P(B) && _r0P(I)) ? _O_D8 (0xeb ,(int)(D) ) : \ + JITFAIL("illegal mode in short jump")) + +#define JMPm(D,B,I,S) ((_r0P(B) && _r0P(I)) ? _O_D32 (0xe9 ,(int)(D) ) : \ + JITFAIL("illegal mode in direct jump")) + +#define JMPsr(R) _O_Mrm (0xff ,_b11,_b100,_r4(R) ) + +#define JMPsm(D,B,I,S) _O_r_X (0xff ,_b100 ,(int)(D),B,I,S ) + + +#define LAHF() _O (0x9f ) +#define LEALmr(MD, MB, MI, MS, RD) _O_r_X (0x8d ,_r4(RD) ,MD,MB,MI,MS ) +#define LEAVE() _O (0xc9 ) + + +#define LMSWr(RS) _OO_Mrm (0x0f01 ,_b11,_b110,_r4(RS) ) +#define LMSWm(MD,MB,MI,MS) _OO_r_X (0x0f01 ,_b110 ,MD,MB,MI,MS ) + +#define LOOPm(MD,MB,MI,MS) ((_r0P(MB) && _r0P(MI)) ? _O_D8 (0xe2 ,MD ) : \ + JITFAIL("illegal mode in loop")) + +#define LOOPEm(MD,MB,MI,MS) ((_r0P(MB) && _r0P(MI)) ? _O_D8 (0xe1 ,MD ) : \ + JITFAIL("illegal mode in loope")) + +#define LOOPZm(MD,MB,MI,MS) ((_r0P(MB) && _r0P(MI)) ? _O_D8 (0xe1 ,MD ) : \ + JITFAIL("illegal mode in loopz")) + +#define LOOPNEm(MD,MB,MI,MS) ((_r0P(MB) && _r0P(MI)) ? _O_D8 (0xe0 ,MD ) : \ + JITFAIL("illegal mode in loopne")) + +#define LOOPNZm(MD,MB,MI,MS) ((_r0P(MB) && _r0P(MI)) ? _O_D8 (0xe0 ,MD ) : \ + JITFAIL("illegal mode in loopnz")) + + +#define MOVBrr(RS, RD) _O_Mrm (0x80 ,_b11,_r1(RS),_r1(RD) ) +#define MOVBmr(MD, MB, MI, MS, RD) _O_r_X (0x8a ,_r1(RD) ,MD,MB,MI,MS ) +#define MOVBrm(RS, MD, MB, MI, MS) _O_r_X (0x88 ,_r1(RS) ,MD,MB,MI,MS ) +#define MOVBir(IM, R) _Or_B (0xb0,_r1(R) ,_su8(IM)) +#define MOVBim(IM, MD, MB, MI, MS) _O_X_B (0xc6 ,MD,MB,MI,MS ,_su8(IM)) + +#define MOVWrr(RS, RD) _wO_Mrm (0x89 ,_b11,_r2(RS),_r2(RD) ) +#define MOVWmr(MD, MB, MI, MS, RD) _wO_r_X (0x8b ,_r2(RD) ,MD,MB,MI,MS ) +#define MOVWrm(RS, MD, MB, MI, MS) _wO_r_X (0x89 ,_r2(RS) ,MD,MB,MI,MS ) +#define MOVWir(IM, R) _wOr_W (0xb8,_r2(R) ,_su16(IM)) +#define MOVWim(IM, MD, MB, MI, MS) _wO_X_W (0xc7 ,MD,MB,MI,MS ,_su16(IM)) + +#define MOVLrr(RS, RD) _O_Mrm (0x89 ,_b11,_r4(RS),_r4(RD) ) +#define MOVLmr(MD, MB, MI, MS, RD) _O_r_X (0x8b ,_r4(RD) ,MD,MB,MI,MS ) +#define MOVLrm(RS, MD, MB, MI, MS) _O_r_X (0x89 ,_r4(RS) ,MD,MB,MI,MS ) +#define MOVLir(IM, R) _Or_L (0xb8,_r4(R) ,IM ) +#define MOVLim(IM, MD, MB, MI, MS) _O_X_L (0xc7 ,MD,MB,MI,MS ,IM ) + +#define MOVZBLrr(RS, RD) _OO_Mrm (0x0fb6 ,_b11,_r1(RD),_r1(RS) ) +#define MOVZBLmr(MD, MB, MI, MS, RD) _OO_r_X (0x0fb6 ,_r1(RD) ,MD,MB,MI,MS ) +#define MOVZBWrr(RS, RD) _wOO_Mrm (0x0fb6 ,_b11,_r2(RD),_r2(RS) ) +#define MOVZBWmr(MD, MB, MI, MS, RD) _wOO_r_X (0x0fb6 ,_r2(RD) ,MD,MB,MI,MS ) +#define MOVZWLrr(RS, RD) _OO_Mrm (0x0fb7 ,_b11,_r1(RD),_r1(RS) ) +#define MOVZWLmr(MD, MB, MI, MS, RD) _OO_r_X (0x0fb7 ,_r1(RD) ,MD,MB,MI,MS ) + +#define MOVSBLrr(RS, RD) _OO_Mrm (0x0fbe ,_b11,_r1(RD),_r1(RS) ) +#define MOVSBLmr(MD, MB, MI, MS, RD) _OO_r_X (0x0fbe ,_r1(RD) ,MD,MB,MI,MS ) +#define MOVSBWrr(RS, RD) _wOO_Mrm (0x0fbe ,_b11,_r2(RD),_r2(RS) ) +#define MOVSBWmr(MD, MB, MI, MS, RD) _wOO_r_X (0x0fbe ,_r2(RD) ,MD,MB,MI,MS ) +#define MOVSWLrr(RS, RD) _OO_Mrm (0x0fbf ,_b11,_r1(RD),_r1(RS) ) +#define MOVSWLmr(MD, MB, MI, MS, RD) _OO_r_X (0x0fbf ,_r1(RD) ,MD,MB,MI,MS ) + + +#define MULBr(RS) _O_Mrm (0xf6 ,_b11,_b100 ,_r1(RS) ) +#define MULBm(MD,MB,MI,MS) _O_r_X (0xf6 ,_b100 ,MD,MB,MI,MS ) + +#define MULWr(RS) _wO_Mrm (0xf7 ,_b11,_b100 ,_r2(RS) ) +#define MULWm(MD,MB,MI,MS) _wO_r_X (0xf7 ,_b100 ,MD,MB,MI,MS ) + +#define MULLr(RS) _O_Mrm (0xf7 ,_b11,_b100 ,_r4(RS) ) +#define MULLm(MD,MB,MI,MS) _O_r_X (0xf7 ,_b100 ,MD,MB,MI,MS ) + + +#define NEGBr(RD) _O_Mrm (0xf6 ,_b11,_b011 ,_r1(RD) ) +#define NEGBm(MD,MB,MI,MS) _O_r_X (0xf6 ,_b011 ,MD,MB,MI,MS ) + +#define NEGWr(RD) _wO_Mrm (0xf7 ,_b11,_b011 ,_r2(RD) ) +#define NEGWm(MD,MB,MI,MS) _wO_r_X (0xf7 ,_b011 ,MD,MB,MI,MS ) + +#define NEGLr(RD) _O_Mrm (0xf7 ,_b11,_b011 ,_r4(RD) ) +#define NEGLm(MD,MB,MI,MS) _O_r_X (0xf7 ,_b011 ,MD,MB,MI,MS ) + + +#define NOP() _O (0x90 ) + + +#define NOTBr(RD) _O_Mrm (0xf6 ,_b11,_b010 ,_r1(RD) ) +#define NOTBm(MD,MB,MI,MS) _O_r_X (0xf6 ,_b010 ,MD,MB,MI,MS ) + +#define NOTWr(RD) _wO_Mrm (0xf7 ,_b11,_b010 ,_r2(RD) ) +#define NOTWm(MD,MB,MI,MS) _wO_r_X (0xf7 ,_b010 ,MD,MB,MI,MS ) + +#define NOTLr(RD) _O_Mrm (0xf7 ,_b11,_b010 ,_r4(RD) ) +#define NOTLm(MD,MB,MI,MS) _O_r_X (0xf7 ,_b010 ,MD,MB,MI,MS ) + + +#define ORBrr(RS, RD) _O_Mrm (0x08 ,_b11,_r1(RS),_r1(RD) ) +#define ORBmr(MD, MB, MI, MS, RD) _O_r_X (0x0a ,_r1(RD) ,MD,MB,MI,MS ) +#define ORBrm(RS, MD, MB, MI, MS) _O_r_X (0x08 ,_r1(RS) ,MD,MB,MI,MS ) +#define ORBir(IM, RD) _O_Mrm_B (0x80 ,_b11,_b001 ,_r1(RD) ,_su8(IM)) +#define ORBim(IM, MD, MB, MI, MS) _O_r_X_B (0x80 ,_b001 ,MD,MB,MI,MS ,_su8(IM)) + +#define ORWrr(RS, RD) _wO_Mrm (0x09 ,_b11,_r2(RS),_r2(RD) ) +#define ORWmr(MD, MB, MI, MS, RD) _wO_r_X (0x0b ,_r2(RD) ,MD,MB,MI,MS ) +#define ORWrm(RS, MD, MB, MI, MS) _wO_r_X (0x09 ,_r2(RS) ,MD,MB,MI,MS ) +#define ORWir(IM, RD) _wOs_Mrm_sW (0x81 ,_b11,_b001 ,_r2(RD) ,_su16(IM)) +#define ORWim(IM, MD, MB, MI, MS) _wOs_r_X_sW (0x81 ,_b001 ,MD,MB,MI,MS ,_su16(IM)) + +#define ORLrr(RS, RD) _O_Mrm (0x09 ,_b11,_r4(RS),_r4(RD) ) +#define ORLmr(MD, MB, MI, MS, RD) _O_r_X (0x0b ,_r4(RD) ,MD,MB,MI,MS ) +#define ORLrm(RS, MD, MB, MI, MS) _O_r_X (0x09 ,_r4(RS) ,MD,MB,MI,MS ) +#define ORLir(IM, RD) _Os_Mrm_sL (0x81 ,_b11,_b001 ,_r4(RD) ,IM ) +#define ORLim(IM, MD, MB, MI, MS) _Os_r_X_sL (0x81 ,_b001 ,MD,MB,MI,MS ,IM ) + + +#define POPWr(RD) _wOr (0x58,_r2(RD) ) +#define POPWm(MD,MB,MI,MS) _wO_r_X (0x8f ,_b000 ,MD,MB,MI,MS ) + +#define POPLr(RD) _Or (0x58,_r4(RD) ) +#define POPLm(MD,MB,MI,MS) _O_r_X (0x8f ,_b000 ,MD,MB,MI,MS ) + + +#define POPA() _wO (0x61 ) +#define POPAD() _O (0x61 ) + +#define POPF() _wO (0x9d ) +#define POPFD() _O (0x9d ) + + +#define PUSHWr(R) _wOr (0x50,_r2(R) ) +#define PUSHWm(MD,MB,MI,MS) _wO_r_X (0xff, ,_b110 ,MD,MB,MI,MS ) +#define PUSHWi(IM) _wOs_sW (0x68 ,IM ) + +#define PUSHLr(R) _Or (0x50,_r4(R) ) +#define PUSHLm(MD,MB,MI,MS) _O_r_X (0xff ,_b110 ,MD,MB,MI,MS ) +#define PUSHLi(IM) _Os_sL (0x68 ,IM ) + + +#define PUSHA() _wO (0x60 ) +#define PUSHAD() _O (0x60 ) + +#define PUSHF() _O (0x9c ) +#define PUSHFD() _wO (0x9c ) + +#define RET() _O (0xc3 ) +#define RETi(IM) _O_W (0xc2 ,_su16(IM)) + + +#define ROLBir(IM,RD) (((IM)==1) ? _O_Mrm (0xd0 ,_b11,_b000,_r1(RD) ) : \ + _O_Mrm_B (0xc0 ,_b11,_b000,_r1(RD) ,_u8(IM) ) ) +#define ROLBim(IM,MD,MB,MS,MI) (((IM)==1) ? _O_r_X (0xd0 ,_b000 ,MD,MB,MI,MS ) : \ + _O_r_X_B (0xc0 ,_b000 ,MD,MB,MI,MS ,_u8(IM) ) ) +#define ROLBrr(RS,RD) (((RS)==_CL) ? _O_Mrm (0xd2 ,_b11,_b000,_r1(RD) ) : \ + JITFAIL ("source register must be CL" ) ) +#define ROLBrm(RS,MD,MB,MS,MI) (((RS)==_CL) ? _O_r_X (0xd2 ,_b000 ,MD,MB,MI,MS ) : \ + JITFAIL ("source register must be CL" ) ) + +#define ROLWir(IM,RD) (((IM)==1) ? _wO_Mrm (0xd1 ,_b11,_b000,_r2(RD) ) : \ + _wO_Mrm_B (0xc1 ,_b11,_b000,_r2(RD) ,_u8(IM) ) ) +#define ROLWim(IM,MD,MB,MS,MI) (((IM)==1) ? _wO_r_X (0xd1 ,_b000 ,MD,MB,MI,MS ) : \ + _wO_r_X_B (0xc1 ,_b000 ,MD,MB,MI,MS ,_u8(IM) ) ) +#define ROLWrr(RS,RD) (((RS)==_CL) ? _wO_Mrm (0xd3 ,_b11,_b000,_r2(RD) ) : \ + JITFAIL ("source register must be CL" ) ) +#define ROLWrm(RS,MD,MB,MS,MI) (((RS)==_CL) ? _wO_r_X (0xd3 ,_b000 ,MD,MB,MI,MS ) : \ + JITFAIL ("source register must be CL" ) ) + +#define ROLLir(IM,RD) (((IM)==1) ? _O_Mrm (0xd1 ,_b11,_b000,_r4(RD) ) : \ + _O_Mrm_B (0xc1 ,_b11,_b000,_r4(RD) ,_u8(IM) ) ) +#define ROLLim(IM,MD,MB,MS,MI) (((IM)==1) ? _O_r_X (0xd1 ,_b000 ,MD,MB,MI,MS ) : \ + _O_r_X_B (0xc1 ,_b000 ,MD,MB,MI,MS ,_u8(IM) ) ) +#define ROLLrr(RS,RD) (((RS)==_CL) ? _O_Mrm (0xd3 ,_b11,_b000,_r4(RD) ) : \ + JITFAIL ("source register must be CL" ) ) +#define ROLLrm(RS,MD,MB,MS,MI) (((RS)==_CL) ? _O_r_X (0xd3 ,_b000 ,MD,MB,MI,MS ) : \ + JITFAIL ("source register must be CL" ) ) + + +#define RORBir(IM,RD) (((IM)==1) ? _O_Mrm (0xd0 ,_b11,_b001,_r1(RD) ) : \ + _O_Mrm_B (0xc0 ,_b11,_b001,_r1(RD) ,_u8(IM) ) ) +#define RORBim(IM,MD,MB,MS,MI) (((IM)==1) ? _O_r_X (0xd0 ,_b001 ,MD,MB,MI,MS ) : \ + _O_r_X_B (0xc0 ,_b001 ,MD,MB,MI,MS ,_u8(IM) ) ) +#define RORBrr(RS,RD) (((RS)==_CL) ? _O_Mrm (0xd2 ,_b11,_b001,_r1(RD) ) : \ + JITFAIL ("source register must be CL" ) ) +#define RORBrm(RS,MD,MB,MS,MI) (((RS)==_CL) ? _O_r_X (0xd2 ,_b001 ,MD,MB,MI,MS ) : \ + JITFAIL ("source register must be CL" ) ) + +#define RORWir(IM,RD) (((IM)==1) ? _wO_Mrm (0xd1 ,_b11,_b001,_r2(RD) ) : \ + _wO_Mrm_B (0xc1 ,_b11,_b001,_r2(RD) ,_u8(IM) ) ) +#define RORWim(IM,MD,MB,MS,MI) (((IM)==1) ? _wO_r_X (0xd1 ,_b001 ,MD,MB,MI,MS ) : \ + _wO_r_X_B (0xc1 ,_b001 ,MD,MB,MI,MS ,_u8(IM) ) ) +#define RORWrr(RS,RD) (((RS)==_CL) ? _wO_Mrm (0xd3 ,_b11,_b001,_r2(RD) ) : \ + JITFAIL ("source register must be CL" ) ) +#define RORWrm(RS,MD,MB,MS,MI) (((RS)==_CL) ? _wO_r_X (0xd3 ,_b001 ,MD,MB,MI,MS ) : \ + JITFAIL ("source register must be CL" ) ) + +#define RORLir(IM,RD) (((IM)==1) ? _O_Mrm (0xd1 ,_b11,_b001,_r4(RD) ) : \ + _O_Mrm_B (0xc1 ,_b11,_b001,_r4(RD) ,_u8(IM) ) ) +#define RORLim(IM,MD,MB,MS,MI) (((IM)==1) ? _O_r_X (0xd1 ,_b001 ,MD,MB,MI,MS ) : \ + _O_r_X_B (0xc1 ,_b001 ,MD,MB,MI,MS ,_u8(IM) ) ) +#define RORLrr(RS,RD) (((RS)==_CL) ? _O_Mrm (0xd3 ,_b11,_b001,_r4(RD) ) : \ + JITFAIL ("source register must be CL" ) ) +#define RORLrm(RS,MD,MB,MS,MI) (((RS)==_CL) ? _O_r_X (0xd3 ,_b001 ,MD,MB,MI,MS ) : \ + JITFAIL ("source register must be CL" ) ) + + +#define SAHF() _O (0x9e ) + + +#define SALBir SHLBir +#define SALBim SHLBim +#define SALBrr SHLBrr +#define SALBrm SHLBrm +#define SALWir SHLWir +#define SALWim SHLWim +#define SALWrr SHLWrr +#define SALWrm SHLWrm +#define SALLir SHLLir +#define SALLim SHLLim +#define SALLrr SHLLrr +#define SALLrm SHLLrm + + +#define SARBir(IM,RD) (((IM)==1) ? _O_Mrm (0xd0 ,_b11,_b111,_r1(RD) ) : \ + _O_Mrm_B (0xc0 ,_b11,_b111,_r1(RD) ,_u8(IM) ) ) +#define SARBim(IM,MD,MB,MS,MI) (((IM)==1) ? _O_r_X (0xd0 ,_b111 ,MD,MB,MI,MS ) : \ + _O_r_X_B (0xc0 ,_b111 ,MD,MB,MI,MS ,_u8(IM) ) ) +#define SARBrr(RS,RD) (((RS)==_CL) ? _O_Mrm (0xd2 ,_b11,_b111,_r1(RD) ) : \ + JITFAIL ("source register must be CL" ) ) +#define SARBrm(RS,MD,MB,MS,MI) (((RS)==_CL) ? _O_r_X (0xd2 ,_b111 ,MD,MB,MI,MS ) : \ + JITFAIL ("source register must be CL" ) ) + +#define SARWir(IM,RD) (((IM)==1) ? _wO_Mrm (0xd1 ,_b11,_b111,_r2(RD) ) : \ + _wO_Mrm_B (0xc1 ,_b11,_b111,_r2(RD) ,_u8(IM) ) ) +#define SARWim(IM,MD,MB,MS,MI) (((IM)==1) ? _wO_r_X (0xd1 ,_b111 ,MD,MB,MI,MS ) : \ + _wO_r_X_B (0xc1 ,_b111 ,MD,MB,MI,MS ,_u8(IM) ) ) +#define SARWrr(RS,RD) (((RS)==_CL) ? _wO_Mrm (0xd3 ,_b11,_b111,_r2(RD) ) : \ + JITFAIL ("source register must be CL" ) ) +#define SARWrm(RS,MD,MB,MS,MI) (((RS)==_CL) ? _wO_r_X (0xd3 ,_b111 ,MD,MB,MI,MS ) : \ + JITFAIL ("source register must be CL" ) ) + +#define SARLir(IM,RD) (((IM)==1) ? _O_Mrm (0xd1 ,_b11,_b111,_r4(RD) ) : \ + _O_Mrm_B (0xc1 ,_b11,_b111,_r4(RD) ,_u8(IM) ) ) +#define SARLim(IM,MD,MB,MS,MI) (((IM)==1) ? _O_r_X (0xd1 ,_b111 ,MD,MB,MI,MS ) : \ + _O_r_X_B (0xc1 ,_b111 ,MD,MB,MI,MS ,_u8(IM) ) ) +#define SARLrr(RS,RD) (((RS)==_CL) ? _O_Mrm (0xd3 ,_b11,_b111,_r4(RD) ) : \ + JITFAIL ("source register must be CL" ) ) +#define SARLrm(RS,MD,MB,MS,MI) (((RS)==_CL) ? _O_r_X (0xd3 ,_b111 ,MD,MB,MI,MS ) : \ + JITFAIL ("source register must be CL" ) ) + + +#define SBBBrr(RS, RD) _O_Mrm (0x18 ,_b11,_r1(RS),_r1(RD) ) +#define SBBBmr(MD, MB, MI, MS, RD) _O_r_X (0x1a ,_r1(RD) ,MD,MB,MI,MS ) +#define SBBBrm(RS, MD, MB, MI, MS) _O_r_X (0x18 ,_r1(RS) ,MD,MB,MI,MS ) +#define SBBBir(IM, RD) _O_Mrm_B (0x80 ,_b11,_b011 ,_r1(RD) ,_su8(IM)) +#define SBBBim(IM, MD, MB, MI, MS) _O_r_X_B (0x80 ,_b011 ,MD,MB,MI,MS ,_su8(IM)) + +#define SBBWrr(RS, RD) _wO_Mrm (0x19 ,_b11,_r2(RS),_r2(RD) ) +#define SBBWmr(MD, MB, MI, MS, RD) _wO_r_X (0x1b ,_r2(RD) ,MD,MB,MI,MS ) +#define SBBWrm(RS, MD, MB, MI, MS) _wO_r_X (0x19 ,_r2(RS) ,MD,MB,MI,MS ) +#define SBBWir(IM, RD) _wOs_Mrm_sW (0x81 ,_b11,_b011 ,_r2(RD) ,_su16(IM)) +#define SBBWim(IM, MD, MB, MI, MS) _wOs_r_X_sW (0x81 ,_b011 ,MD,MB,MI,MS ,_su16(IM)) + +#define SBBLrr(RS, RD) _O_Mrm (0x19 ,_b11,_r4(RS),_r4(RD) ) +#define SBBLmr(MD, MB, MI, MS, RD) _O_r_X (0x1b ,_r4(RD) ,MD,MB,MI,MS ) +#define SBBLrm(RS, MD, MB, MI, MS) _O_r_X (0x19 ,_r4(RS) ,MD,MB,MI,MS ) +#define SBBLir(IM, RD) _Os_Mrm_sL (0x81 ,_b11,_b011 ,_r4(RD) ,IM ) +#define SBBLim(IM, MD, MB, MI, MS) _Os_r_X_sL (0x81 ,_b011 ,MD,MB,MI,MS ,IM ) + + +#define SETCCir(CC,RD) _OO_Mrm (0x0f90|(CC) ,_b11,_b000,_r1(RD) ) + +#define SETOr(RD) SETCCir(0x0,RD) +#define SETNOr(RD) SETCCir(0x1,RD) +#define SETBr(RD) SETCCir(0x2,RD) +#define SETNAEr(RD) SETCCir(0x2,RD) +#define SETNBr(RD) SETCCir(0x3,RD) +#define SETAEr(RD) SETCCir(0x3,RD) +#define SETEr(RD) SETCCir(0x4,RD) +#define SETZr(RD) SETCCir(0x4,RD) +#define SETNEr(RD) SETCCir(0x5,RD) +#define SETNZr(RD) SETCCir(0x5,RD) +#define SETBEr(RD) SETCCir(0x6,RD) +#define SETNAr(RD) SETCCir(0x6,RD) +#define SETNBEr(RD) SETCCir(0x7,RD) +#define SETAr(RD) SETCCir(0x7,RD) +#define SETSr(RD) SETCCir(0x8,RD) +#define SETNSr(RD) SETCCir(0x9,RD) +#define SETPr(RD) SETCCir(0xa,RD) +#define SETPEr(RD) SETCCir(0xa,RD) +#define SETNPr(RD) SETCCir(0xb,RD) +#define SETPOr(RD) SETCCir(0xb,RD) +#define SETLr(RD) SETCCir(0xc,RD) +#define SETNGEr(RD) SETCCir(0xc,RD) +#define SETNLr(RD) SETCCir(0xd,RD) +#define SETGEr(RD) SETCCir(0xd,RD) +#define SETLEr(RD) SETCCir(0xe,RD) +#define SETNGr(RD) SETCCir(0xe,RD) +#define SETNLEr(RD) SETCCir(0xf,RD) +#define SETGr(RD) SETCCir(0xf,RD) + +#define SETCCim(CC,MD,MB,MI,MS) _OO_r_X (0x0f90|(CC) ,_b000 ,MD,MB,MI,MS ) + +#define SETOm(D,B,I,S) SETCCim(0x0,D,B,I,S) +#define SETNOm(D,B,I,S) SETCCim(0x1,D,B,I,S) +#define SETBm(D,B,I,S) SETCCim(0x2,D,B,I,S) +#define SETNAEm(D,B,I,S) SETCCim(0x2,D,B,I,S) +#define SETNBm(D,B,I,S) SETCCim(0x3,D,B,I,S) +#define SETAEm(D,B,I,S) SETCCim(0x3,D,B,I,S) +#define SETEm(D,B,I,S) SETCCim(0x4,D,B,I,S) +#define SETZm(D,B,I,S) SETCCim(0x4,D,B,I,S) +#define SETNEm(D,B,I,S) SETCCim(0x5,D,B,I,S) +#define SETNZm(D,B,I,S) SETCCim(0x5,D,B,I,S) +#define SETBEm(D,B,I,S) SETCCim(0x6,D,B,I,S) +#define SETNAm(D,B,I,S) SETCCim(0x6,D,B,I,S) +#define SETNBEm(D,B,I,S) SETCCim(0x7,D,B,I,S) +#define SETAm(D,B,I,S) SETCCim(0x7,D,B,I,S) +#define SETSm(D,B,I,S) SETCCim(0x8,D,B,I,S) +#define SETNSm(D,B,I,S) SETCCim(0x9,D,B,I,S) +#define SETPm(D,B,I,S) SETCCim(0xa,D,B,I,S) +#define SETPEm(D,B,I,S) SETCCim(0xa,D,B,I,S) +#define SETNPm(D,B,I,S) SETCCim(0xb,D,B,I,S) +#define SETPOm(D,B,I,S) SETCCim(0xb,D,B,I,S) +#define SETLm(D,B,I,S) SETCCim(0xc,D,B,I,S) +#define SETNGEm(D,B,I,S) SETCCim(0xc,D,B,I,S) +#define SETNLm(D,B,I,S) SETCCim(0xd,D,B,I,S) +#define SETGEm(D,B,I,S) SETCCim(0xd,D,B,I,S) +#define SETLEm(D,B,I,S) SETCCim(0xe,D,B,I,S) +#define SETNGm(D,B,I,S) SETCCim(0xe,D,B,I,S) +#define SETNLEm(D,B,I,S) SETCCim(0xf,D,B,I,S) +#define SETGm(D,B,I,S) SETCCim(0xf,D,B,I,S) + + +#define SHLBir(IM,RD) (((IM)==1) ? _O_Mrm (0xd0 ,_b11,_b100,_r1(RD) ) : \ + _O_Mrm_B (0xc0 ,_b11,_b100,_r1(RD) ,_u8(IM) ) ) +#define SHLBim(IM,MD,MB,MS,MI) (((IM)==1) ? _O_r_X (0xd0 ,_b100 ,MD,MB,MI,MS ) : \ + _O_r_X_B (0xc0 ,_b100 ,MD,MB,MI,MS ,_u8(IM) ) ) +#define SHLBrr(RS,RD) (((RS)==_CL) ? _O_Mrm (0xd2 ,_b11,_b100,_r1(RD) ) : \ + JITFAIL ("source register must be CL" ) ) +#define SHLBrm(RS,MD,MB,MS,MI) (((RS)==_CL) ? _O_r_X (0xd2 ,_b100 ,MD,MB,MI,MS ) : \ + JITFAIL ("source register must be CL" ) ) + +#define SHLWir(IM,RD) (((IM)==1) ? _wO_Mrm (0xd1 ,_b11,_b100,_r2(RD) ) : \ + _wO_Mrm_B (0xc1 ,_b11,_b100,_r2(RD) ,_u8(IM) ) ) +#define SHLWim(IM,MD,MB,MS,MI) (((IM)==1) ? _wO_r_X (0xd1 ,_b100 ,MD,MB,MI,MS ) : \ + _wO_r_X_B (0xc1 ,_b100 ,MD,MB,MI,MS ,_u8(IM) ) ) +#define SHLWrr(RS,RD) (((RS)==_CL) ? _wO_Mrm (0xd3 ,_b11,_b100,_r2(RD) ) : \ + JITFAIL ("source register must be CL" ) ) +#define SHLWrm(RS,MD,MB,MS,MI) (((RS)==_CL) ? _wO_r_X (0xd3 ,_b100 ,MD,MB,MI,MS ) : \ + JITFAIL ("source register must be CL" ) ) + +#define SHLLir(IM,RD) (((IM)==1) ? _O_Mrm (0xd1 ,_b11,_b100,_r4(RD) ) : \ + _O_Mrm_B (0xc1 ,_b11,_b100,_r4(RD) ,_u8(IM) ) ) +#define SHLLim(IM,MD,MB,MS,MI) (((IM)==1) ? _O_r_X (0xd1 ,_b100 ,MD,MB,MI,MS ) : \ + _O_r_X_B (0xc1 ,_b100 ,MD,MB,MI,MS ,_u8(IM) ) ) +#define SHLLrr(RS,RD) (((RS)==_CL) ? _O_Mrm (0xd3 ,_b11,_b100,_r4(RD) ) : \ + JITFAIL ("source register must be CL" ) ) +#define SHLLrm(RS,MD,MB,MS,MI) (((RS)==_CL) ? _O_r_X (0xd3 ,_b100 ,MD,MB,MI,MS ) : \ + JITFAIL ("source register must be CL" ) ) + + +#define SHRBir(IM,RD) (((IM)==1) ? _O_Mrm (0xd0 ,_b11,_b101,_r1(RD) ) : \ + _O_Mrm_B (0xc0 ,_b11,_b101,_r1(RD) ,_u8(IM) ) ) +#define SHRBim(IM,MD,MB,MS,MI) (((IM)==1) ? _O_r_X (0xd0 ,_b101 ,MD,MB,MI,MS ) : \ + _O_r_X_B (0xc0 ,_b101 ,MD,MB,MI,MS ,_u8(IM) ) ) +#define SHRBrr(RS,RD) (((RS)==_CL) ? _O_Mrm (0xd2 ,_b11,_b101,_r1(RD) ) : \ + JITFAIL ("source register must be CL" ) ) +#define SHRBrm(RS,MD,MB,MS,MI) (((RS)==_CL) ? _O_r_X (0xd2 ,_b101 ,MD,MB,MI,MS ) : \ + JITFAIL ("source register must be CL" ) ) + +#define SHRWir(IM,RD) (((IM)==1) ? _wO_Mrm (0xd1 ,_b11,_b101,_r2(RD) ) : \ + _wO_Mrm_B (0xc1 ,_b11,_b101,_r2(RD) ,_u8(IM) ) ) +#define SHRWim(IM,MD,MB,MS,MI) (((IM)==1) ? _wO_r_X (0xd1 ,_b101 ,MD,MB,MI,MS ) : \ + _wO_r_X_B (0xc1 ,_b101 ,MD,MB,MI,MS ,_u8(IM) ) ) +#define SHRWrr(RS,RD) (((RS)==_CL) ? _wO_Mrm (0xd3 ,_b11,_b101,_r2(RD) ) : \ + JITFAIL ("source register must be CL" ) ) +#define SHRWrm(RS,MD,MB,MS,MI) (((RS)==_CL) ? _wO_r_X (0xd3 ,_b101 ,MD,MB,MI,MS ) : \ + JITFAIL ("source register must be CL" ) ) + +#define SHRLir(IM,RD) (((IM)==1) ? _O_Mrm (0xd1 ,_b11,_b101,_r4(RD) ) : \ + _O_Mrm_B (0xc1 ,_b11,_b101,_r4(RD) ,_u8(IM) ) ) +#define SHRLim(IM,MD,MB,MS,MI) (((IM)==1) ? _O_r_X (0xd1 ,_b101 ,MD,MB,MI,MS ) : \ + _O_r_X_B (0xc1 ,_b101 ,MD,MB,MI,MS ,_u8(IM) ) ) +#define SHRLrr(RS,RD) (((RS)==_CL) ? _O_Mrm (0xd3 ,_b11,_b101,_r4(RD) ) : \ + JITFAIL ("source register must be CL" ) ) +#define SHRLrm(RS,MD,MB,MS,MI) (((RS)==_CL) ? _O_r_X (0xd3 ,_b101 ,MD,MB,MI,MS ) : \ + JITFAIL ("source register must be CL" ) ) + + +#define STC() _O (0xf9 ) + + +#define SUBBrr(RS, RD) _O_Mrm (0x28 ,_b11,_r1(RS),_r1(RD) ) +#define SUBBmr(MD, MB, MI, MS, RD) _O_r_X (0x2a ,_r1(RD) ,MD,MB,MI,MS ) +#define SUBBrm(RS, MD, MB, MI, MS) _O_r_X (0x28 ,_r1(RS) ,MD,MB,MI,MS ) +#define SUBBir(IM, RD) _O_Mrm_B (0x80 ,_b11,_b101 ,_r1(RD) ,_su8(IM)) +#define SUBBim(IM, MD, MB, MI, MS) _O_r_X_B (0x80 ,_b101 ,MD,MB,MI,MS ,_su8(IM)) + +#define SUBWrr(RS, RD) _wO_Mrm (0x29 ,_b11,_r2(RS),_r2(RD) ) +#define SUBWmr(MD, MB, MI, MS, RD) _wO_r_X (0x2b ,_r2(RD) ,MD,MB,MI,MS ) +#define SUBWrm(RS, MD, MB, MI, MS) _wO_r_X (0x29 ,_r2(RS) ,MD,MB,MI,MS ) +#define SUBWir(IM, RD) _wOs_Mrm_sW (0x81 ,_b11,_b101 ,_r2(RD) ,_su16(IM)) +#define SUBWim(IM, MD, MB, MI, MS) _wOs_r_X_sW (0x81 ,_b101 ,MD,MB,MI,MS ,_su16(IM)) + +#define SUBLrr(RS, RD) _O_Mrm (0x29 ,_b11,_r4(RS),_r4(RD) ) +#define SUBLmr(MD, MB, MI, MS, RD) _O_r_X (0x2b ,_r4(RD) ,MD,MB,MI,MS ) +#define SUBLrm(RS, MD, MB, MI, MS) _O_r_X (0x29 ,_r4(RS) ,MD,MB,MI,MS ) +#define SUBLir(IM, RD) _Os_Mrm_sL (0x81 ,_b11,_b101 ,_r4(RD) ,IM ) +#define SUBLim(IM, MD, MB, MI, MS) _Os_r_X_sL (0x81 ,_b101 ,MD,MB,MI,MS ,IM ) + + +#define TESTBrr(RS, RD) _O_Mrm (0x84 ,_b11,_r1(RS),_r1(RD) ) +#define TESTBrm(RS, MD, MB, MI, MS) _O_r_X (0x84 ,_r1(RS) ,MD,MB,MI,MS ) +#define TESTBir(IM, RD) _O_Mrm_B (0xf6 ,_b11,_b000 ,_r1(RD) ,_u8(IM)) +#define TESTBim(IM, MD, MB, MI, MS) _O_r_X_B (0xf6 ,_b000 ,MD,MB,MI,MS ,_u8(IM)) + +#define TESTWrr(RS, RD) _wO_Mrm (0x85 ,_b11,_r2(RS),_r2(RD) ) +#define TESTWrm(RS, MD, MB, MI, MS) _wO_r_X (0x85 ,_r2(RS) ,MD,MB,MI,MS ) +#define TESTWir(IM, RD) _wO_Mrm_W (0xf7 ,_b11,_b000 ,_r2(RD) ,_u16(IM)) +#define TESTWim(IM, MD, MB, MI, MS) _wO_r_X_W (0xf7 ,_b000 ,MD,MB,MI,MS ,_u16(IM)) + +#define TESTLrr(RS, RD) _O_Mrm (0x85 ,_b11,_r4(RS),_r4(RD) ) +#define TESTLrm(RS, MD, MB, MI, MS) _O_r_X (0x85 ,_r4(RS) ,MD,MB,MI,MS ) +#define TESTLir(IM, RD) _O_Mrm_L (0xf7 ,_b11,_b000 ,_r4(RD) ,IM ) +#define TESTLim(IM, MD, MB, MI, MS) _O_r_X_L (0xf7 ,_b000 ,MD,MB,MI,MS ,IM ) + + +#define XADDBrr(RS,RD) _OO_Mrm (0x0fc0 ,_b11,_r1(RS),_r1(RD) ) +#define XADDBrm(RS,MD,MB,MI,MS) _OO_r_X (0x0fc0 ,_r1(RS) ,MD,MB,MI,MS ) + +#define XADDWrr(RS,RD) _wOO_Mrm (0x0fc1 ,_b11,_r2(RS),_r2(RD) ) +#define XADDWrm(RS,MD,MB,MI,MS) _wOO_r_X (0x0fc1 ,_r2(RS) ,MD,MB,MI,MS ) + +#define XADDLrr(RS,RD) _OO_Mrm (0x0fc1 ,_b11,_r4(RS),_r4(RD) ) +#define XADDLrm(RS,MD,MB,MI,MS) _OO_r_X (0x0fc1 ,_r4(RS) ,MD,MB,MI,MS ) + + +#define XCHGBrr(RS,RD) _O_Mrm (0x86 ,_b11,_r1(RS),_r1(RD) ) +#define XCHGBrm(RS,MD,MB,MI,MS) _O_r_X (0x86 ,_r1(RS) ,MD,MB,MI,MS ) + +#define XCHGWrr(RS,RD) _wO_Mrm (0x87 ,_b11,_r2(RS),_r2(RD) ) +#define XCHGWrm(RS,MD,MB,MI,MS) _wO_r_X (0x87 ,_r2(RS) ,MD,MB,MI,MS ) + +#define XCHGLrr(RS,RD) _O_Mrm (0x87 ,_b11,_r4(RS),_r4(RD) ) +#define XCHGLrm(RS,MD,MB,MI,MS) _O_r_X (0x87 ,_r4(RS) ,MD,MB,MI,MS ) + + +#define XORBrr(RS, RD) _O_Mrm (0x30 ,_b11,_r1(RS),_r1(RD) ) +#define XORBmr(MD, MB, MI, MS, RD) _O_r_X (0x32 ,_r1(RD) ,MD,MB,MI,MS ) +#define XORBrm(RS, MD, MB, MI, MS) _O_r_X (0x30 ,_r1(RS) ,MD,MB,MI,MS ) +#define XORBir(IM, RD) _O_Mrm_B (0x80 ,_b11,_b110 ,_r1(RD) ,_su8(IM)) +#define XORBim(IM, MD, MB, MI, MS) _O_r_X_B (0x80 ,_b110 ,MD,MB,MI,MS ,_su8(IM)) + +#define XORWrr(RS, RD) _wO_Mrm (0x31 ,_b11,_r2(RS),_r2(RD) ) +#define XORWmr(MD, MB, MI, MS, RD) _wO_r_X (0x33 ,_r2(RD) ,MD,MB,MI,MS ) +#define XORWrm(RS, MD, MB, MI, MS) _wO_r_X (0x31 ,_r2(RS) ,MD,MB,MI,MS ) +#define XORWir(IM, RD) _wOs_Mrm_sW (0x81 ,_b11,_b110 ,_r2(RD) ,_su16(IM)) +#define XORWim(IM, MD, MB, MI, MS) _wOs_r_X_sW (0x81 ,_b110 ,MD,MB,MI,MS ,_su16(IM)) + +#define XORLrr(RS, RD) _O_Mrm (0x31 ,_b11,_r4(RS),_r4(RD) ) +#define XORLmr(MD, MB, MI, MS, RD) _O_r_X (0x33 ,_r4(RD) ,MD,MB,MI,MS ) +#define XORLrm(RS, MD, MB, MI, MS) _O_r_X (0x31 ,_r4(RS) ,MD,MB,MI,MS ) +#define XORLir(IM, RD) _Os_Mrm_sL (0x81 ,_b11,_b110 ,_r4(RD) ,IM ) +#define XORLim(IM, MD, MB, MI, MS) _Os_r_X_sL (0x81 ,_b110 ,MD,MB,MI,MS ,IM ) + +/* x87 instructions -- yay, we found a use for octal constants :-) */ + +#define ESCmi(D,B,I,S,OP) _O_r_X(0xd8|(OP >> 3), (OP & 7), D,B,I,S) +#define ESCri(RD,OP) _O_Mrm(0xd8|(OP >> 3), _b11, (OP & 7), RD) + +#define ESCrri(RS,RD,OP) ((RS) = _ST0 ? ESCri(RD,(OP|040)) \ + : (RD) = _ST0 ? ESCri(RS,OP) \ + : JITFAIL ("coprocessor instruction without st0")) + +#define FLDSm(D,B,I,S) ESCmi(D,B,I,S,010) /* fld m32real */ +#define FILDLm(D,B,I,S) ESCmi(D,B,I,S,030) /* fild m32int */ +#define FLDLm(D,B,I,S) ESCmi(D,B,I,S,050) /* fld m64real */ +#define FILDWm(D,B,I,S) ESCmi(D,B,I,S,070) /* fild m16int */ +#define FSTSm(D,B,I,S) ESCmi(D,B,I,S,012) /* fst m32real */ +#define FISTLm(D,B,I,S) ESCmi(D,B,I,S,032) /* fist m32int */ +#define FSTLm(D,B,I,S) ESCmi(D,B,I,S,052) /* fst m64real */ +#define FISTWm(D,B,I,S) ESCmi(D,B,I,S,072) /* fist m16int */ +#define FSTPSm(D,B,I,S) ESCmi(D,B,I,S,013) /* fstp m32real */ +#define FISTPLm(D,B,I,S) ESCmi(D,B,I,S,033) /* fistp m32int */ +#define FSTPLm(D,B,I,S) ESCmi(D,B,I,S,053) /* fstp m64real */ +#define FISTPWm(D,B,I,S) ESCmi(D,B,I,S,073) /* fistp m16int */ +#define FLDTm(D,B,I,S) ESCmi(D,B,I,S,035) /* fld m80real */ +#define FILDQm(D,B,I,S) ESCmi(D,B,I,S,075) /* fild m64int */ +#define FSTPTm(D,B,I,S) ESCmi(D,B,I,S,037) /* fstp m80real */ +#define FISTPQm(D,B,I,S) ESCmi(D,B,I,S,077) /* fistp m64int */ + +#define FADDrr(RS,RD) ESCrri(RS,RD,000) +#define FMULrr(RS,RD) ESCrri(RS,RD,001) +#define FSUBrr(RS,RD) ESCrri(RS,RD,004) +#define FSUBRrr(RS,RD) ESCrri(RS,RD,005) +#define FDIVrr(RS,RD) ESCrri(RS,RD,006) +#define FDIVRrr(RS,RD) ESCrri(RS,RD,007) + +#define FLDr(RD) ESCri(RD,010) +#define FXCHr(RD) ESCri(RD,011) +#define FFREEr(RD) ESCri(RD,050) +#define FSTr(RD) ESCri(RD,052) +#define FSTPr(RD) ESCri(RD,053) +#define FCOMr(RD) ESCri(RD,002) +#define FCOMPr(RD) ESCri(RD,003) +#define FCOMIr(RD) ESCri(RD,036) +#define FCOMIPr(RD) ESCri(RD,076) +#define FUCOMr(RD) ESCri(RD,054) +#define FUCOMPr(RD) ESCri(RD,055) +#define FUCOMIr(RD) ESCri(RD,035) +#define FUCOMIPr(RD) ESCri(RD,075) +#define FADDPr(RD) ESCri(RD,060) +#define FMULPr(RD) ESCri(RD,061) +#define FSUBPr(RD) ESCri(RD,064) +#define FSUBRPr(RD) ESCri(RD,065) +#define FDIVPr(RD) ESCri(RD,066) +#define FDIVRPr(RD) ESCri(RD,067) + +#define FNSTSWr(RD) ((RD == _AX || RD == _EAX) ? _OO (0xdfe0) \ + : JITFAIL ("AX or EAX expected")) +/* N byte NOPs */ +#define _NOPi(N) ((( (N) >= 8) ? (_jit_B(0x8d),_jit_B(0xb4),_jit_B(0x26),_jit_L(0x00),_jit_B(0x90)) : (void) 0), \ + (( ((N)&7) == 7) ? (_jit_B(0x8d),_jit_B(0xb4),_jit_B(0x26),_jit_L(0x00)) : \ + ( ((N)&7) == 6) ? (_jit_B(0x8d),_jit_B(0xb6),_jit_L(0x00)) : \ + ( ((N)&7) == 5) ? (_jit_B(0x90),_jit_B(0x8d),_jit_B(0x74),_jit_B(0x26),_jit_B(0x00)) : \ +/* leal 0(,%esi), %esi */ ( ((N)&7) == 4) ? (_jit_B(0x8d),_jit_B(0x74),_jit_B(0x26),_jit_B(0x00)) : \ +/* leal (,%esi), %esi */ ( ((N)&7) == 3) ? (_jit_B(0x8d),_jit_B(0x76),_jit_B(0x00)) : \ +/* movl %esi, %esi */ ( ((N)&7) == 2) ? (_jit_B(0x89),_jit_B(0xf6)) : \ + ( ((N)&7) == 1) ? (_jit_B(0x90)) : \ + ( ((N)&7) == 0) ? 0 : \ + JITFAIL(".align argument too large"))) + + +/*** References: */ +/* */ +/* [1] "Intel Architecture Software Developer's Manual Volume 1: Basic Architecture", */ +/* Intel Corporation 1997. */ +/* */ +/* [2] "Intel Architecture Software Developer's Manual Volume 2: Instruction Set Reference", */ +/* Intel Corporation 1997. */ + +#endif /* __lightning_asm_h */ + diff --git a/lightning/i386/core.h b/lightning/i386/core.h new file mode 100644 index 000000000..79f4d645e --- /dev/null +++ b/lightning/i386/core.h @@ -0,0 +1,408 @@ +/******************************** -*- C -*- **************************** + * + * Platform-independent layer (i386 version) + * + ***********************************************************************/ + + +/*********************************************************************** + * + * 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 2.1, 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. + * + ***********************************************************************/ + + + +#ifndef __lightning_core_h +#define __lightning_core_h + +#define JIT_R0 _EAX +#define JIT_R1 _ECX +#define JIT_R2 _EDX +#define JIT_V0 _EBX +#define JIT_V1 _ESI +#define JIT_V2 _EDI +#define JIT_FP _EBP +#define JIT_SP _ESP +#define JIT_RET _EAX + +struct jit_local_state { + int framesize; + int argssize; +}; + +/* 3-parameter operation */ +#define jit_opr_(d, s1, s2, op1d, op2d) \ + ( (s2 == d) ? op1d : \ + ( ((s1 == d) ? (void)0 : (void)MOVLrr(s1, d)), op2d ) \ + ) + +/* 3-parameter operation, with immediate */ +#define jit_op_(d, s1, op2d) \ + ((s1 == d) ? op2d : (MOVLrr(s1, d), op2d)) \ + +/* 3-parameter operation, optimizable */ +#define jit_opo_(d, s1, s2, op1d, op2d, op12d) \ + ((s2 == d) ? op2d : \ + ((s1 == d) ? op1d : op12d)) + +/* 3-parameter operation, optimizable, with immediate */ +#define jit_opi_(d, rs, opdi, opdri) \ + ((rs == d) ? opdi : opdri) + +/* An operand is forced into a register */ +#define jit_replace(rd, rs, forced, op) \ + ((rd == forced) ? JITSORRY("Register conflict for " # op) : \ + (rs == forced) ? op : (PUSHLr(forced), MOVLrr(rs, forced), op, POPLr(forced))) + +/* For LT, LE, ... */ +#define jit_replace8(d, op) \ + (jit_check8(d) \ + ? (MOVLir(0, d), op(d)) \ + : (PUSHLr(_EAX), MOVLir(0, _EAX), op(_EAX), MOVLrr(_EAX, (d)), POPLr(_EAX))) + +#define jit_bool_r(d, s1, s2, op) \ + (CMPLrr(s2, s1), jit_replace8(d, op)) + +#define jit_bool_i(d, rs, is, op) \ + (CMPLir(is, rs), jit_replace8(d, op)) + +/* When CMP with 0 can be replaced with TEST */ +#define jit_bool_i0(d, rs, is, op, op0) \ + ((is) != 0 \ + ? (CMPLir(is, rs), jit_replace8(d, op)) \ + : (TESTLrr(rs, rs), jit_replace8(d, op0))) + +/* For BLT, BLE, ... */ +#define jit_bra_r(s1, s2, op) (CMPLrr(s2, s1), op, _jit.x.pc) +#define jit_bra_i(rs, is, op) (CMPLir(is, rs), op, _jit.x.pc) + +/* When CMP with 0 can be replaced with TEST */ +#define jit_bra_i0(rs, is, op, op0) \ + ( (is) == 0 ? (TESTLrr(rs, rs), op0, _jit.x.pc) : (CMPLir(is, rs), op, _jit.x.pc)) + +/* Used to implement ldc, stc, ... */ +#define jit_check8(rs) ( (rs) <= _EBX ) +#define jit_reg8(rs) ( ((rs) == _SI || (rs) == _DI) ? _AL : ((rs) & _BH) | _AL ) +#define jit_reg16(rs) ( ((rs) & _BH) | _AX ) + +/* In jit_replace below, _EBX is dummy */ +#define jit_movbrm(rs, dd, db, di, ds) \ + (jit_check8(rs) \ + ? MOVBrm(jit_reg8(rs), dd, db, di, ds) \ + : jit_replace(_EBX, rs, _EAX, MOVBrm(_AL, dd, db, di, ds))) + +/* Reduce arguments of XOR/OR/TEST */ +#define jit_reduce_(op) op +#define jit_reduce(op, is, rs) \ + (_u8P(is) && jit_check8(rs) ? jit_reduce_(op##Bir(is, jit_reg8(rs))) : \ + (_u16P(is) ? jit_reduce_(op##Wir(is, jit_reg16(rs))) : \ + jit_reduce_(op##Lir(is, rs)) )) + +/* Helper macros for MUL/DIV/IDIV */ +#define jit_might(d, s1, op) \ + ((s1 == d) ? 0 : op) + +#define jit_mulr_ui_(s1, s2) jit_opr_(_EAX, s1, s2, MULLr(s1), MULLr(s2)) +#define jit_mulr_i_(s1, s2) jit_opr_(_EAX, s1, s2, IMULLr(s1), IMULLr(s2)) + + +#define jit_muli_i_(is, rs) \ + (MOVLir(is, rs == _EAX ? _EDX : _EAX), \ + IMULLr(rs == _EAX ? _EDX : rs)) + +#define jit_muli_ui_(is, rs) \ + (MOVLir(is, rs == _EAX ? _EDX : _EAX), \ + IMULLr(rs == _EAX ? _EDX : rs)) + +#define jit_divi_i_(result, d, rs, is) \ + (jit_might (d, _EAX, PUSHLr(_EAX)), \ + jit_might (d, _ECX, PUSHLr(_ECX)), \ + jit_might (d, _EDX, PUSHLr(_EDX)), \ + jit_might (rs, _EAX, MOVLrr(rs, _EAX)), \ + jit_might (rs, _EDX, MOVLrr(rs, _EDX)), \ + MOVLir(is, _ECX), \ + SARLir(31, _EDX), \ + IDIVLr(_ECX), \ + jit_might(d, result, MOVLrr(result, d)), \ + jit_might(d, _EDX, POPLr(_EDX)), \ + jit_might(d, _ECX, POPLr(_ECX)), \ + jit_might(d, _EAX, POPLr(_EAX))) + +#define jit_divr_i_(result, d, s1, s2) \ + (jit_might (d, _EAX, PUSHLr(_EAX)), \ + jit_might (d, _ECX, PUSHLr(_ECX)), \ + jit_might (d, _EDX, PUSHLr(_EDX)), \ + ((s1 == _ECX) ? PUSHLr(_ECX) : 0), \ + jit_might (s2, _ECX, MOVLrr(s2, _ECX)), \ + ((s1 == _ECX) ? POPLr(_EDX) : \ + jit_might (s1, _EDX, MOVLrr(s1, _EDX))), \ + MOVLrr(_EDX, _EAX), \ + SARLir(31, _EDX), \ + IDIVLr(_ECX), \ + jit_might(d, result, MOVLrr(result, d)), \ + jit_might(d, _EDX, POPLr(_EDX)), \ + jit_might(d, _ECX, POPLr(_ECX)), \ + jit_might(d, _EAX, POPLr(_EAX))) + +#define jit_divi_ui_(result, d, rs, is) \ + (jit_might (d, _EAX, PUSHLr(_EAX)), \ + jit_might (d, _ECX, PUSHLr(_ECX)), \ + jit_might (d, _EDX, PUSHLr(_EDX)), \ + jit_might (rs, _EAX, MOVLrr(rs, _EAX)), \ + MOVLir(is, _ECX), \ + XORLrr(_EDX, _EDX), \ + DIVLr(_ECX), \ + jit_might(d, result, MOVLrr(result, d)), \ + jit_might(d, _EDX, POPLr(_EDX)), \ + jit_might(d, _ECX, POPLr(_ECX)), \ + jit_might(d, _EAX, POPLr(_EAX))) + +#define jit_divr_ui_(result, d, s1, s2) \ + (jit_might (d, _EAX, PUSHLr(_EAX)), \ + jit_might (d, _ECX, PUSHLr(_ECX)), \ + jit_might (d, _EDX, PUSHLr(_EDX)), \ + ((s1 == _ECX) ? PUSHLr(_ECX) : 0), \ + jit_might (s2, _ECX, MOVLrr(s2, _ECX)), \ + ((s1 == _ECX) ? POPLr(_EAX) : \ + jit_might (s1, _EAX, MOVLrr(s1, _EAX))), \ + XORLrr(_EDX, _EDX), \ + DIVLr(_ECX), \ + jit_might(d, result, MOVLrr(result, d)), \ + jit_might(d, _EDX, POPLr(_EDX)), \ + jit_might(d, _ECX, POPLr(_ECX)), \ + jit_might(d, _EAX, POPLr(_EAX))) + + +/* ALU */ +#define jit_addi_i(d, rs, is) jit_opi_((d), (rs), ADDLir((is), (d)), LEALmr((is), (rs), 0, 0, (d)) ) +#define jit_addr_i(d, s1, s2) jit_opo_((d), (s1), (s2), ADDLrr((s2), (d)), ADDLrr((s1), (d)), LEALmr(0, (s1), (s2), 1, (d)) ) +#define jit_addci_i(d, rs, is) jit_op_ ((d), (rs), ADDLir((is), (d)) ) +#define jit_addcr_i(d, s1, s2) jit_opr_((d), (s1), (s2), ADDLrr((s1), (d)), ADDLrr((s2), (d)) ) +#define jit_addxi_i(d, rs, is) jit_op_ ((d), (rs), ADCLir((is), (d)) ) +#define jit_addxr_i(d, s1, s2) jit_opr_((d), (s1), (s2), ADCLrr((s1), (d)), ADCLrr((s2), (d)) ) +#define jit_andi_i(d, rs, is) jit_op_ ((d), (rs), ANDLir((is), (d)) ) +#define jit_andr_i(d, s1, s2) jit_opr_((d), (s1), (s2), ANDLrr((s1), (d)), ANDLrr((s2), (d)) ) +#define jit_orr_i(d, s1, s2) jit_opr_((d), (s1), (s2), ORLrr((s1), (d)), ORLrr((s2), (d)) ) +#define jit_subr_i(d, s1, s2) jit_opr_((d), (s1), (s2), (SUBLrr((s1), (d)), NEGLr(d)), SUBLrr((s2), (d)) ) +#define jit_subcr_i(d, s1, s2) jit_subr_i((d), (s1), (s2)) +#define jit_subxr_i(d, s1, s2) jit_opr_((d), (s1), (s2), SBBLrr((s1), (d)), SBBLrr((s2), (d)) ) +#define jit_subxi_i(d, rs, is) jit_op_ ((d), (rs), SBBLir((is), (d)) ) +#define jit_xorr_i(d, s1, s2) jit_opr_((d), (s1), (s2), XORLrr((s1), (d)), XORLrr((s2), (d)) ) + +/* These can sometimes use byte or word versions! */ +#define jit_ori_i(d, rs, is) jit_op_ ((d), (rs), jit_reduce(OR, (is), (d)) ) +#define jit_xori_i(d, rs, is) jit_op_ ((d), (rs), jit_reduce(XOR, (is), (d)) ) + +#define jit_muli_i(d, rs, is) jit_op_ ((d), (rs), IMULLir((is), (d)) ) +#define jit_mulr_i(d, s1, s2) jit_opr_((d), (s1), (s2), IMULLrr((s1), (d)), IMULLrr((s2), (d)) ) + +/* As far as low bits are concerned, signed and unsigned multiplies are + exactly the same. */ +#define jit_muli_ui(d, rs, is) jit_op_ ((d), (rs), IMULLir((is), (d)) ) +#define jit_mulr_ui(d, s1, s2) jit_opr_((d), (s1), (s2), IMULLrr((s1), (d)), IMULLrr((s2), (d)) ) + +#define jit_hmuli_i(d, rs, is) \ + ((d) == _EDX ? ( PUSHLr(_EAX), jit_muli_i_((is), (rs)), POPLr(_EAX) ) : \ + ((d) == _EAX ? (PUSHLr(_EDX), jit_muli_i_((is), (rs)), MOVLrr(_EDX, _EAX), POPLr(_EDX) ) : \ + (PUSHLr(_EDX), PUSHLr(_EAX), jit_muli_i_((is), (rs)), MOVLrr(_EDX, (d)), POPLr(_EAX), POPLr(_EDX) ))) + +#define jit_hmulr_i(d, s1, s2) \ + ((d) == _EDX ? ( PUSHLr(_EAX), jit_mulr_i_((s1), (s2)), POPLr(_EAX) ) : \ + ((d) == _EAX ? (PUSHLr(_EDX), jit_mulr_i_((s1), (s2)), MOVLrr(_EDX, _EAX), POPLr(_EDX) ) : \ + (PUSHLr(_EDX), PUSHLr(_EAX), jit_mulr_i_((s1), (s2)), MOVLrr(_EDX, (d)), POPLr(_EAX), POPLr(_EDX) ))) + +#define jit_hmuli_ui(d, rs, is) \ + ((d) == _EDX ? ( PUSHLr(_EAX), jit_muli_ui_((is), (rs)), POPLr(_EAX) ) : \ + ((d) == _EAX ? (PUSHLr(_EDX), jit_muli_ui_((is), (rs)), MOVLrr(_EDX, _EAX), POPLr(_EDX) ) : \ + (PUSHLr(_EDX), PUSHLr(_EAX), jit_muli_ui_((is), (rs)), MOVLrr(_EDX, (d)), POPLr(_EAX), POPLr(_EDX) ))) + +#define jit_hmulr_ui(d, s1, s2) \ + ((d) == _EDX ? ( PUSHLr(_EAX), jit_mulr_ui_((s1), (s2)), POPLr(_EAX) ) : \ + ((d) == _EAX ? (PUSHLr(_EDX), jit_mulr_ui_((s1), (s2)), MOVLrr(_EDX, _EAX), POPLr(_EDX) ) : \ + (PUSHLr(_EDX), PUSHLr(_EAX), jit_mulr_ui_((s1), (s2)), MOVLrr(_EDX, (d)), POPLr(_EAX), POPLr(_EDX) ))) + +#define jit_divi_i(d, rs, is) jit_divi_i_(_EAX, (d), (rs), (is)) +#define jit_divi_ui(d, rs, is) jit_divi_ui_(_EAX, (d), (rs), (is)) +#define jit_modi_i(d, rs, is) jit_divi_i_(_EDX, (d), (rs), (is)) +#define jit_modi_ui(d, rs, is) jit_divi_ui_(_EDX, (d), (rs), (is)) +#define jit_divr_i(d, s1, s2) jit_divr_i_(_EAX, (d), (s1), (s2)) +#define jit_divr_ui(d, s1, s2) jit_divr_ui_(_EAX, (d), (s1), (s2)) +#define jit_modr_i(d, s1, s2) jit_divr_i_(_EDX, (d), (s1), (s2)) +#define jit_modr_ui(d, s1, s2) jit_divr_ui_(_EDX, (d), (s1), (s2)) + + +/* Shifts */ +#define jit_lshi_i(d, rs, is) ((is) <= 3 ? LEALmr(0, 0, (rs), 1 << (is), (d)) : jit_op_ ((d), (rs), SHLLir((is), (d)) )) +#define jit_rshi_i(d, rs, is) jit_op_ ((d), (rs), SARLir((is), (d)) ) +#define jit_rshi_ui(d, rs, is) jit_op_ ((d), (rs), SHRLir((is), (d)) ) +#define jit_lshr_i(d, r1, r2) jit_replace((r1), (r2), _ECX, jit_op_ ((d), (r1), SHLLrr(_CL, (d)) )) +#define jit_rshr_i(d, r1, r2) jit_replace((r1), (r2), _ECX, jit_op_ ((d), (r1), SARLrr(_CL, (d)) )) +#define jit_rshr_ui(d, r1, r2) jit_replace((r1), (r2), _ECX, jit_op_ ((d), (r1), SHRLrr(_CL, (d)) )) + +/* Stack */ +#define jit_pushr_i(rs) PUSHLr(rs) +#define jit_popr_i(rs) POPLr(rs) +#define jit_prolog(n) (_jitl.framesize = 8, PUSHLr(_EBP), MOVLrr(_ESP, _EBP), PUSHLr(_EBX), PUSHLr(_ESI), PUSHLr(_EDI)) + +/* The += allows for stack pollution */ + +#define jitfp_prepare(ni,nf,nd) ((void) (_jitl.argssize += (ni) + (nf) + 2*(nd))) +#define jit_pusharg_i(rs) PUSHLr(rs) +#define jit_finish(sub) (jit_calli((sub)), ADDLir(4 * _jitl.argssize, JIT_SP), _jitl.argssize = 0) +#define jit_retval(rd) jit_movr_i ((rd), _EAX) + +#define jit_arg_c() ((_jitl.framesize += sizeof(int)) - sizeof(int)) +#define jit_arg_uc() ((_jitl.framesize += sizeof(int)) - sizeof(int)) +#define jit_arg_s() ((_jitl.framesize += sizeof(int)) - sizeof(int)) +#define jit_arg_us() ((_jitl.framesize += sizeof(int)) - sizeof(int)) +#define jit_arg_i() ((_jitl.framesize += sizeof(int)) - sizeof(int)) +#define jit_arg_ui() ((_jitl.framesize += sizeof(int)) - sizeof(int)) +#define jit_arg_l() ((_jitl.framesize += sizeof(long)) - sizeof(long)) +#define jit_arg_ul() ((_jitl.framesize += sizeof(long)) - sizeof(long)) +#define jit_arg_p() ((_jitl.framesize += sizeof(long)) - sizeof(long)) + +#define jit_arg_f() ((_jitl.framesize += sizeof(float)) - sizeof(float)) +#define jit_arg_d() ((_jitl.framesize += sizeof(double)) - sizeof(double)) + +/* Unary */ +#define jit_negr_i(d, rs) jit_opi_((d), (rs), NEGLr(d), (XORLrr((d), (d)), SUBLrr((rs), (d))) ) +#define jit_negr_l(d, rs) jit_opi_((d), (rs), NEGLr(d), (XORLrr((d), (d)), SUBLrr((rs), (d))) ) + +#define jit_movr_i(d, rs) ((rs) == (d) ? 0 : MOVLrr((rs), (d))) +#define jit_movi_i(d, is) ((is) ? MOVLir((is), (d)) : XORLrr ((d), (d)) ) + +#define jit_ntoh_ui(d, rs) jit_op_((d), (rs), BSWAPLr(d)) +#define jit_ntoh_us(d, rs) jit_op_((d), (rs), RORWir(8, d)) + +/* Boolean */ +#define jit_ltr_i(d, s1, s2) jit_bool_r((d), (s1), (s2), SETLr ) +#define jit_ler_i(d, s1, s2) jit_bool_r((d), (s1), (s2), SETLEr ) +#define jit_gtr_i(d, s1, s2) jit_bool_r((d), (s1), (s2), SETGr ) +#define jit_ger_i(d, s1, s2) jit_bool_r((d), (s1), (s2), SETGEr ) +#define jit_eqr_i(d, s1, s2) jit_bool_r((d), (s1), (s2), SETEr ) +#define jit_ner_i(d, s1, s2) jit_bool_r((d), (s1), (s2), SETNEr ) +#define jit_ltr_ui(d, s1, s2) jit_bool_r((d), (s1), (s2), SETBr ) +#define jit_ler_ui(d, s1, s2) jit_bool_r((d), (s1), (s2), SETBEr ) +#define jit_gtr_ui(d, s1, s2) jit_bool_r((d), (s1), (s2), SETAr ) +#define jit_ger_ui(d, s1, s2) jit_bool_r((d), (s1), (s2), SETAEr ) + +#define jit_lti_i(d, rs, is) jit_bool_i0((d), (rs), (is), SETLr, SETSr ) +#define jit_lei_i(d, rs, is) jit_bool_i ((d), (rs), (is), SETLEr ) +#define jit_gti_i(d, rs, is) jit_bool_i ((d), (rs), (is), SETGr ) +#define jit_gei_i(d, rs, is) jit_bool_i0((d), (rs), (is), SETGEr, SETNSr ) +#define jit_eqi_i(d, rs, is) jit_bool_i0((d), (rs), (is), SETEr, SETEr ) +#define jit_nei_i(d, rs, is) jit_bool_i0((d), (rs), (is), SETNEr, SETNEr ) +#define jit_lti_ui(d, rs, is) jit_bool_i ((d), (rs), (is), SETB ) +#define jit_lei_ui(d, rs, is) jit_bool_i0((d), (rs), (is), SETBEr, SETEr ) +#define jit_gti_ui(d, rs, is) jit_bool_i0((d), (rs), (is), SETAr, SETNEr ) +#define jit_gei_ui(d, rs, is) jit_bool_i0((d), (rs), (is), SETAEr, INCLr ) + +/* Jump */ +#define jit_bltr_i(label, s1, s2) jit_bra_r((s1), (s2), JLm(label, 0,0,0) ) +#define jit_bler_i(label, s1, s2) jit_bra_r((s1), (s2), JLEm(label,0,0,0) ) +#define jit_bgtr_i(label, s1, s2) jit_bra_r((s1), (s2), JGm(label, 0,0,0) ) +#define jit_bger_i(label, s1, s2) jit_bra_r((s1), (s2), JGEm(label,0,0,0) ) +#define jit_beqr_i(label, s1, s2) jit_bra_r((s1), (s2), JEm(label, 0,0,0) ) +#define jit_bner_i(label, s1, s2) jit_bra_r((s1), (s2), JNEm(label,0,0,0) ) +#define jit_bltr_ui(label, s1, s2) jit_bra_r((s1), (s2), JBm(label, 0,0,0) ) +#define jit_bler_ui(label, s1, s2) jit_bra_r((s1), (s2), JBEm(label,0,0,0) ) +#define jit_bgtr_ui(label, s1, s2) jit_bra_r((s1), (s2), JAm(label, 0,0,0) ) +#define jit_bger_ui(label, s1, s2) jit_bra_r((s1), (s2), JAEm(label,0,0,0) ) +#define jit_bmsr_i(label, s1, s2) (TESTLrr((s1), (s2)), JNZm(label,0,0,0), _jit.x.pc) +#define jit_bmcr_i(label, s1, s2) (TESTLrr((s1), (s2)), JZm(label,0,0,0), _jit.x.pc) +#define jit_boaddr_i(label, s1, s2) (ADDLrr((s2), (s1)), JOm(label,0,0,0), _jit.x.pc) +#define jit_bosubr_i(label, s1, s2) (SUBLrr((s2), (s1)), JOm(label,0,0,0), _jit.x.pc) +#define jit_boaddr_ui(label, s1, s2) (ADDLrr((s2), (s1)), JCm(label,0,0,0), _jit.x.pc) +#define jit_bosubr_ui(label, s1, s2) (SUBLrr((s2), (s1)), JCm(label,0,0,0), _jit.x.pc) + +#define jit_blti_i(label, rs, is) jit_bra_i0((rs), (is), JLm(label, 0,0,0), JSm(label, 0,0,0) ) +#define jit_blei_i(label, rs, is) jit_bra_i ((rs), (is), JLEm(label,0,0,0) ) +#define jit_bgti_i(label, rs, is) jit_bra_i ((rs), (is), JGm(label, 0,0,0) ) +#define jit_bgei_i(label, rs, is) jit_bra_i0((rs), (is), JGEm(label,0,0,0), JNSm(label,0,0,0) ) +#define jit_beqi_i(label, rs, is) jit_bra_i0((rs), (is), JEm(label, 0,0,0), JEm(label, 0,0,0) ) +#define jit_bnei_i(label, rs, is) jit_bra_i0((rs), (is), JNEm(label,0,0,0), JNEm(label,0,0,0) ) +#define jit_blti_ui(label, rs, is) jit_bra_i ((rs), (is), JLm(label, 0,0,0) ) +#define jit_blei_ui(label, rs, is) jit_bra_i0((rs), (is), JLEm(label,0,0,0), JEm(label, 0,0,0) ) +#define jit_bgti_ui(label, rs, is) jit_bra_i0((rs), (is), JGm(label, 0,0,0), JNEm(label,0,0,0) ) +#define jit_bgei_ui(label, rs, is) jit_bra_i ((rs), (is), JGEm(label,0,0,0) ) +#define jit_boaddi_i(label, rs, is) (ADDLir((is), (rs)), JOm(label,0,0,0), _jit.x.pc) +#define jit_bosubi_i(label, rs, is) (SUBLir((is), (rs)), JOm(label,0,0,0), _jit.x.pc) +#define jit_boaddi_ui(label, rs, is) (ADDLir((is), (rs)), JCm(label,0,0,0), _jit.x.pc) +#define jit_bosubi_ui(label, rs, is) (SUBLir((is), (rs)), JCm(label,0,0,0), _jit.x.pc) + +#define jit_bmsi_i(label, rs, is) (jit_reduce(TEST, (is), (rs)), JNZm(label,0,0,0), _jit.x.pc) +#define jit_bmci_i(label, rs, is) (jit_reduce(TEST, (is), (rs)), JZm(label,0,0,0), _jit.x.pc) + +#define jit_jmpi(label) (JMPm( ((unsigned long) (label)), 0, 0, 0), _jit.x.pc) +#define jit_calli(label) (CALLm( ((unsigned long) (label)), 0, 0, 0), _jit.x.pc) +#define jit_jmpr(reg) JMPsr(reg) +#define jit_patch(jump_pc) (*_PSL((jump_pc) - 4) = _jit_SL(_jit.x.pc - (jump_pc))) +#define jit_ret() (POPLr(_EDI), POPLr(_ESI), POPLr(_EBX), POPLr(_EBP), RET()) + +/* Memory */ +#define jit_ldi_c(d, is) MOVSBLmr((is), 0, 0, 0, (d)) +#define jit_ldr_c(d, rs) MOVSBLmr(0, (rs), 0, 0, (d)) +#define jit_ldxr_c(d, s1, s2) MOVSBLmr(0, (s1), (s2), 1, (d)) +#define jit_ldxi_c(d, rs, is) MOVSBLmr((is), (rs), 0, 0, (d)) + +#define jit_ldi_uc(d, is) MOVZBLmr((is), 0, 0, 0, (d)) +#define jit_ldr_uc(d, rs) MOVZBLmr(0, (rs), 0, 0, (d)) +#define jit_ldxr_uc(d, s1, s2) MOVZBLmr(0, (s1), (s2), 1, (d)) +#define jit_ldxi_uc(d, rs, is) MOVZBLmr((is), (rs), 0, 0, (d)) + +#define jit_sti_c(id, rs) jit_movbrm((rs), (id), 0, 0, 0) +#define jit_str_c(rd, rs) jit_movbrm((rs), 0, (rd), 0, 0) +#define jit_stxr_c(d1, d2, rs) jit_movbrm((rs), 0, (d1), (d2), 1) +#define jit_stxi_c(id, rd, rs) jit_movbrm((rs), (id), (rd), 0, 0) + +#define jit_ldi_s(d, is) MOVSWLmr((is), 0, 0, 0, (d)) +#define jit_ldr_s(d, rs) MOVSWLmr(0, (rs), 0, 0, (d)) +#define jit_ldxr_s(d, s1, s2) MOVSWLmr(0, (s1), (s2), 1, (d)) +#define jit_ldxi_s(d, rs, is) MOVSWLmr((is), (rs), 0, 0, (d)) + +#define jit_ldi_us(d, is) MOVZWLmr((is), 0, 0, 0, (d)) +#define jit_ldr_us(d, rs) MOVZWLmr(0, (rs), 0, 0, (d)) +#define jit_ldxr_us(d, s1, s2) MOVZWLmr(0, (s1), (s2), 1, (d)) +#define jit_ldxi_us(d, rs, is) MOVZWLmr((is), (rs), 0, 0, (d)) + +#define jit_sti_s(id, rs) MOVWrm(jit_reg16(rs), (id), 0, 0, 0) +#define jit_str_s(rd, rs) MOVWrm(jit_reg16(rs), 0, (rd), 0, 0) +#define jit_stxr_s(d1, d2, rs) MOVWrm(jit_reg16(rs), 0, (d1), (d2), 1) +#define jit_stxi_s(id, rd, rs) MOVWrm(jit_reg16(rs), (id), (rd), 0, 0) + +#define jit_ldi_i(d, is) MOVLmr((is), 0, 0, 0, (d)) +#define jit_ldr_i(d, rs) MOVLmr(0, (rs), 0, 0, (d)) +#define jit_ldxr_i(d, s1, s2) MOVLmr(0, (s1), (s2), 1, (d)) +#define jit_ldxi_i(d, rs, is) MOVLmr((is), (rs), 0, 0, (d)) + +#define jit_sti_i(id, rs) MOVLrm((rs), (id), 0, 0, 0) +#define jit_str_i(rd, rs) MOVLrm((rs), 0, (rd), 0, 0) +#define jit_stxr_i(d1, d2, rs) MOVLrm((rs), 0, (d1), (d2), 1) +#define jit_stxi_i(id, rd, rs) MOVLrm((rs), (id), (rd), 0, 0) + +/* Extra */ +#define jit_nop() NOP() + +#define _jit_alignment(pc, n) (((pc ^ _MASK(4)) + 1) & _MASK(n)) +#define jit_align(n) _NOPi(_jit_alignment(_jit_UL(_jit.x.pc), (n))) + +#endif /* __lightning_core_h */ diff --git a/lightning/i386/fp.h b/lightning/i386/fp.h new file mode 100644 index 000000000..c347e3d58 --- /dev/null +++ b/lightning/i386/fp.h @@ -0,0 +1,252 @@ +/******************************** -*- C -*- **************************** + * + * Run-time assembler & support macros for the i386 math coprocessor + * + ***********************************************************************/ + + +/*********************************************************************** + * + * Copyright 2000, 2001, 2002, 2004 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 2.1, 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. + * + ***********************************************************************/ + + +#ifndef __lightning_asm_fp_h +#define __lightning_asm_fp_h + +/* Actually, we should redesign the jitfp interface. As a first step, I have + defined the macros for many x87 instructions, and I am using them here. + + In practice, we can provide something sensible and make it work on the x86 + using the stack like a file of eight registers. Then this awful stuff goes + away, and everything is "beautiful" as the rest of GNU lightning---and we'll + document it, promised. + + Well, let's use six or seven registers so as to have some freedom + for floor, ceil, round, log, tan, atn and exp. + + Not hard at all, basically play with FXCH. FXCH is mostly free, + so the generated code is not bad. Of course we special case when one + of the operands turns out to be ST0. + + - binary ops: + + add FRR3 to FPR0 + FADD ST0,ST3 + + add FPR0 to FPR3 + FADD ST3,ST0 + + add FPR3 to FPR7 (I'm using nasm syntax here) + FXCH ST3 + FADD ST7,ST0 + FXCH ST3 + + - stores: + + store FPR3 + + FXCH ST3 + FST [FUBAR] + FXCH ST3 + + store FPR0 + + FST [FUBAR] + + (and similarly for other unary ops like FCHS or FABS) + + - moves: + + move FPR0 to FPR3 + FST ST3 + + move FPR3 to FPR0 + FXCH ST3 + FST ST3 + + move FPR3 to FPR1 + FSTP ST1 Save old st0 into destination register + FLD ST2 Stack is rotated, so FPRn becomes STn-1 + FXCH ST1 Get back old st0 + + - loads: + + load into FPR0 + FSTP ST0 + FLD [FUBAR] + + load into FPR3 + FSTP ST3 Save old st0 into destination register + FLD [FUBAR] + FXCH ST3 Get back old st0 + + (and similarly for immediates, using the stack) */ + +#define jit_add_two(reg0) FADDPr(1) +#define jit_sub_two(reg0) FSUBRPr(1) +#define jit_mul_two(reg0) FMULPr(1) +#define jit_div_two(reg0) FDIVRPr(1) + +#define jit_abs(reg0) _OO(0xd9e1) /* fabs */ +#define jit_sqr(reg0) FMULrr(0,0) +#define jit_sqrt(reg0) _OO(0xd9fa) /* fsqrt */ + +#define jit_exti_d(reg0, rs) (PUSHLr((rs)), FILDLm(0, _ESP, 0, 0), POPLr((rs))) + +#define jit_neg(reg0) _OO(0xd9e0) /* fchs */ + +#define jit_ldxr_f(reg0, s1, s2) FLDSm(0, (s1), (s2), 1) +#define jit_ldxi_f(reg0, rs, is) FLDSm((is), (rs), 0, 0) +#define jit_ldxr_f(reg0, s1, s2) FLDSm(0, (s1), (s2), 1) +#define jit_ldxi_d(reg0, rs, is) FLDLm((is), (rs), 0, 0) +#define jit_ldxr_d(reg0, s1, s2) FLDLm(0, (s1), (s2), 1) +#define jit_ldi_f(reg0, is) FLDSm((is), 0, 0, 0) +#define jit_ldr_f(reg0, rs) FLDSm(0, (rs), 0, 0) +#define jit_ldi_d(reg0, is) FLDLm((is), 0, 0, 0) +#define jit_ldr_d(reg0, rs) FLDLm(0, (rs), 0, 0) +#define jit_stxi_f(id, rd, reg0) FSTPSm((id), (rd), 0, 0) +#define jit_stxr_f(d1, d2, reg0) FSTPSm(0, (d1), (d2), 1) +#define jit_stxi_d(id, rd, reg0) FSTPLm((id), (rd), 0, 0) +#define jit_stxr_d(d1, d2, reg0) FSTPLm(0, (d1), (d2), 1) +#define jit_sti_f(id, reg0) FSTPSm((id), 0, 0, 0) +#define jit_str_f(rd, reg0) FSTPSm(0, (rd), 0, 0) +#define jit_sti_d(id, reg0) FSTPLm((id), 0, 0, 0) +#define jit_str_d(rd, reg0) FSTPLm(0, (rd), 0, 0) + +#define jit_fpimm(reg0, first, second) \ + (PUSHLi(second), \ + PUSHLi(first), \ + FLDLm(0, _ESP, 0, 0), \ + ADDLir(8, _ESP)) + + +/* Assume round to near mode */ +#define jit_floor(rd, reg0) \ + jit_floor2((rd), ((rd) == _EDX ? _EAX : _EDX)) + +#define jit_ceil(rd, reg0) \ + jit_ceil2((rd), ((rd) == _EDX ? _EAX : _EDX)) + +#define jit_trunc(rd, reg0) \ + jit_trunc2((rd), ((rd) == _EDX ? _EAX : _EDX)) + +#define jit_calc_diff(ofs) \ + FISTLm(ofs, _ESP, 0, 0), \ + FILDLm(ofs, _ESP, 0, 0), \ + FSUBRPr(1), \ + FSTPSm(4+ofs, _ESP, 0, 0) \ + +/* The real meat */ +#define jit_floor2(rd, aux) \ + (PUSHLr(aux), \ + SUBLir(8, _ESP), \ + jit_calc_diff(0), \ + POPLr(rd), /* floor in rd */ \ + POPLr(aux), /* x-round(x) in aux */ \ + ADDLir(0x7FFFFFFF, aux), /* carry if x-round(x) < -0 */ \ + SBBLir(0, rd), /* subtract 1 if carry */ \ + POPLr(aux)) + +#define jit_ceil2(rd, aux) \ + (PUSHLr(aux), \ + SUBLir(8, _ESP), \ + jit_calc_diff(0), \ + POPLr(rd), /* floor in rd */ \ + POPLr(aux), /* x-round(x) in aux */ \ + TESTLrr(aux, aux), \ + SETGr(jit_reg8(aux)), \ + SHRLir(1, aux), \ + ADCLir(0, rd), \ + POPLr(aux)) + +/* a mingling of the two above */ +#define jit_trunc2(rd, aux) \ + (PUSHLr(aux), \ + SUBLir(12, _ESP), \ + FSTSm(0, _ESP, 0, 0), \ + jit_calc_diff(4), \ + POPLr(aux), \ + POPLr(rd), \ + TESTLrr(aux, aux), \ + POPLr(aux), \ + JSSm(_jit.x.pc + 11, 0, 0, 0), \ + ADDLir(0x7FFFFFFF, aux), /* 6 */ \ + SBBLir(0, rd), /* 3 */ \ + JMPSm(_jit.x.pc + 10, 0, 0, 0), /* 2 */ \ + TESTLrr(aux, aux), /* 2 */ \ + SETGr(jit_reg8(aux)), /* 3 */ \ + SHRLir(1, aux), /* 2 */ \ + ADCLir(0, rd), /* 3 */ \ + POPLr(aux)) + +/* the easy one */ +#define jit_round(rd, reg0) \ + (PUSHLr(_EAX), \ + FISTPLm(0, _ESP, 0, 0), \ + POPLr((rd))) + +#define jit_cmp(le, ge, reg0) ( \ + ((le) == _EAX || (ge) == _EAX ? 0 : PUSHLr(_EAX)), \ + FCOMr(0), \ + FNSTSWr(_AX), \ + TESTBir(0x40, _AH), \ + MOVLir(0, (le)), \ + MOVLrr((le), (ge)), \ + JZSm(_jit.x.pc + 11, 0, 0, 0), \ + _OO(0xd9e4), /* ftst */ /* 2 */ \ + FNSTSWr(_AX), /* 2 */ \ + SAHF(), /* 1 */ \ + SETLEr( ((le) & 15) | 0x10), /* 3 */ \ + SETGEr( ((ge) & 15) | 0x10), /* 3 */ \ + ((le) == _EAX || (ge) == _EAX ? ANDLir (1, _EAX) : POPLr(_EAX)) ) + +#define jitfp_getarg_f(ofs) jitfp_ldxi_f(JIT_FP,(ofs)) +#define jitfp_getarg_d(ofs) jitfp_ldxi_d(JIT_FP,(ofs)) +#define jitfp_pusharg_d(op1) (jit_subi_i(JIT_SP,JIT_SP,sizeof(double)), jitfp_str_d(JIT_SP,(op1))) +#define jitfp_pusharg_f(op1) (jit_subi_i(JIT_SP,JIT_SP,sizeof(float)), jitfp_str_f(JIT_SP,(op1))) +#define jitfp_retval(op1) _jit_emit(&_jit, (op1), JIT_NULL, 0, 0, 0) + +#define JIT_TRANSCENDENTAL + +#define jit_sin(reg0) _OO(0xd9fe) /* fsin */ +#define jit_cos(reg0) _OO(0xd9ff) /* fcos */ +#define jit_tan(reg0) (_OO(0xd9f2), /* fptan */ \ + FSTPr(0)) /* fstp st */ +#define jit_atn(reg0) (_OO(0xd9e8), /* fld1 */ \ + _OO(0xd9f3)) /* fpatan */ +#define jit_exp(reg0) (_OO(0xd9ea), /* fldl2e */ \ + FMULPr(1), /* fmulp */ \ + _OO(0xd9c0), /* fld st */ \ + _OO(0xd9fc), /* frndint */ \ + _OO(0xdce9), /* fsubr */ \ + FXCHr(1), /* fxch st(1) */ \ + _OO(0xd9f0), /* f2xm1 */ \ + _OO(0xd9e8), /* fld1 */ \ + _OO(0xdec1), /* faddp */ \ + _OO(0xd9fd), /* fscale */ \ + FSTPr(1)) /* fstp st(1) */ +#define jit_log(reg0) (_OO(0xd9ed), /* fldln2 */ \ + FXCHr(1), /* fxch st(1) */ \ + _OO(0xd9f1)) /* fyl2x */ + +#endif /* __lightning_asm_h */ diff --git a/lightning/i386/funcs.h b/lightning/i386/funcs.h new file mode 100644 index 000000000..a618a8573 --- /dev/null +++ b/lightning/i386/funcs.h @@ -0,0 +1,39 @@ +/******************************** -*- C -*- **************************** + * + * Platform-independent layer inline functions (i386) + * + ***********************************************************************/ + + +/*********************************************************************** + * + * 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 2.1, 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. + * + ***********************************************************************/ + + + +#ifndef __lightning_funcs_h +#define __lightning_funcs_h + +#define jit_flush_code(dest, end) + +#endif /* __lightning_funcs_h */ diff --git a/lightning/ppc/asm.h b/lightning/ppc/asm.h new file mode 100644 index 000000000..d102283b4 --- /dev/null +++ b/lightning/ppc/asm.h @@ -0,0 +1,597 @@ +/******************************** -*- C -*- **************************** + * + * Run-time assembler for the PowerPC + * + ***********************************************************************/ + + +/*********************************************************************** + * + * Copyright 1999, 2000, 2001, 2002 Ian Piumarta + * + * 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 2.1, 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. + * + ***********************************************************************/ + +#ifndef __lightning_asm_h +#define __lightning_asm_h + +/* = [0-9]+ | (.+) -> add i, one parameter (imm) + * = r -> add r, one parameter (imm) + * = () -> add m, two parameters (imm,reg) + * = () -> add x, two parameters (reg,reg) + * + * `x' operands have two forms. For example `stwu source, rega(regb)' + * could be written as either + * STWUrx(source, rega, regb) + * or + * STWUXrrr(source, rega, regb) + */ + + + +/*** a brief NOTE about halfwords and "shifted" operands + * + * LOGICAL insns require UNSIGNED args in 0..65535, whether or not shifted + * + * ARITHMETIC insns require SIGNED args in -32768..32767, even when shifted + * + * as a special case: "lis/addis" also accepts UNSIGNED arguments in + * 0..65535 since it is often used immediately before "ori" to load a 32-bit + * constant (this is consistent with the GNU rs/6000 and PowerPC assemblers) + * + * thus: lis rD, expression@hi + * ori rD, rD, expression@lo ; load 32-bit constant + */ + +typedef unsigned int jit_insn; + +#define _cr0 0 +#define _cr1 1 +#define _cr2 2 +#define _cr3 3 +#define _cr4 4 +#define _cr5 5 +#define _cr6 6 +#define _cr7 7 + +#define _lt 0 +#define _gt 1 +#define _eq 2 +#define _so 3 +#define _un 3 + +#define _d16(D) (_ck_d(16,(_jit_UL(D)-_jit_UL(_jit.x.pc))) & ~3) +#define _d26(D) (_ck_d(26,(_jit_UL(D)-_jit_UL(_jit.x.pc))) & ~3) + +/* primitive instruction forms [1, Section A.4] */ + +#define _FB( OP, BD,AA,LK ) _jit_I((_u6(OP)<<26)| _d26(BD)| (_u1(AA)<<1)|_u1(LK)) +#define _FBA( OP, BD,AA,LK ) _jit_I((_u6(OP)<<26)| (_u26(BD)&~3)| (_u1(AA)<<1)|_u1(LK)) +#define _BB( OP,BO,BI, BD,AA,LK ) _jit_I((_u6(OP)<<26)|(_u5(BO)<<21)|(_u5(BI)<<16)| _d16(BD)| (_u1(AA)<<1)|_u1(LK)) +#define _D( OP,RD,RA, DD ) _jit_I((_u6(OP)<<26)|(_u5(RD)<<21)|(_u5(RA)<<16)| _s16(DD) ) +#define _Du( OP,RD,RA, DD ) _jit_I((_u6(OP)<<26)|(_u5(RD)<<21)|(_u5(RA)<<16)| _u16(DD) ) +#define _Ds( OP,RD,RA, DD ) _jit_I((_u6(OP)<<26)|(_u5(RD)<<21)|(_u5(RA)<<16)| _su16(DD) ) +#define _X( OP,RD,RA,RB, XO,RC ) _jit_I((_u6(OP)<<26)|(_u5(RD)<<21)|(_u5(RA)<<16)|( _u5(RB)<<11)| (_u10(XO)<<1)|_u1(RC)) +#define _XL( OP,BO,BI, XO,LK ) _jit_I((_u6(OP)<<26)|(_u5(BO)<<21)|(_u5(BI)<<16)|( _u5(00)<<11)| (_u10(XO)<<1)|_u1(LK)) +#define _XFX( OP,RD, SR,XO ) _jit_I((_u6(OP)<<26)|(_u5(RD)<<21)| (_u10(SR)<<11)| (_u10(XO)<<1)|_u1(00)) +#define _XO( OP,RD,RA,RB,OE,XO,RC ) _jit_I((_u6(OP)<<26)|(_u5(RD)<<21)|(_u5(RA)<<16)|( _u5(RB)<<11)|(_u1(OE)<<10)|( _u9(XO)<<1)|_u1(RC)) +#define _M( OP,RS,RA,SH,MB,ME,RC ) _jit_I((_u6(OP)<<26)|(_u5(RS)<<21)|(_u5(RA)<<16)|( _u5(SH)<<11)|(_u5(MB)<< 6)|( _u5(ME)<<1)|_u1(RC)) + +/* special purpose registers (form XFX) [1, Section 8.2, page 8-138] */ + +#define SPR_LR ((8<<5)|(0)) + +/* +++ intrinsic instructions */ + +#define ADDrrr(RD, RA, RB) _XO (31, RD, RA, RB, 0, 266, 0) +#define ADD_rrr(RD, RA, RB) _XO (31, RD, RA, RB, 0, 266, 1) +#define ADDCrrr(RD, RA, RB) _XO (31, RD, RA, RB, 0, 10, 0) +#define ADDC_rrr(RD, RA, RB) _XO (31, RD, RA, RB, 0, 10, 1) +#define ADDErrr(RD, RA, RB) _XO (31, RD, RA, RB, 0, 138, 0) +#define ADDE_rrr(RD, RA, RB) _XO (31, RD, RA, RB, 0, 138, 1) +#define ADDOrrr(RD, RA, RB) _XO (31, RD, RA, RB, 1, 266, 0) +#define ADDO_rrr(RD, RA, RB) _XO (31, RD, RA, RB, 1, 266, 1) +#define ADDIrri(RD, RA, IMM) _D (14, RD, RA, IMM) +#define ADDICrri(RD, RA, IMM) _D (12, RD, RA, IMM) +#define ADDIC_rri(RD, RA, IMM) _D (13, RD, RA, IMM) +#define ADDISrri(RD, RA, IMM) _Ds (15, RD, RA, IMM) + +#define ANDrrr(RA, RS, RB) _X (31, RS, RA, RB, 28, 0) +#define AND_rrr(RA, RS, RB) _X (31, RS, RA, RB, 28, 1) +#define ANDCrrr(RA, RS, RB) _X (31, RS, RA, RB, 60, 0) +#define ANDC_rrr(RA, RS, RB) _X (31, RS, RA, RB, 60, 1) +#define ANDI_rri(RA, RS, IMM) _Du (28, RS, RA, IMM) +#define ANDIS_rri(RA, RS, IMM) _Du (29, RS, RA, IMM) + +#define Bi(BD) _FB (18, BD, 0, 0) +#define BAi(BD) _FBA (18, BD, 1, 0) +#define BLi(BD) _FB (18, BD, 0, 1) +#define BLAi(BD) _FBA (18, BD, 1, 1) + +#define BCiii(BO,BI,BD) _BB (16, BO, BI, BD, 0, 0) +#define BCAiii(BO,BI,BD) _BB (16, BO, BI, BD, 1, 0) +#define BCLiii(BO,BI,BD) _BB (16, BO, BI, BD, 0, 1) +#define BCLAiii(BO,BI,BD) _BB (16, BO, BI, BD, 1, 1) + +#define BCCTRii(BO,BI) _XL (19, BO, BI, 528, 0) +#define BCCTRLii(BO,BI) _XL (19, BO, BI, 528, 1) + +#define BCLRii(BO,BI) _XL (19, BO, BI, 16, 0) +#define BCLRLii(BO,BI) _XL (19, BO, BI, 16, 1) + +#define CMPiirr(CR, LL, RA, RB) _X (31, ((CR)<<2)|(LL), RA, RB, 0, 0) +#define CMPIiiri(CR, LL, RA, IMM) _D (11, ((CR)<<2)|(LL), RA, IMM) + +#define CMPLiirr(CR, LL, RA, RB) _X (31, ((CR)<<2)|(LL), RA, RB, 32, 0) +#define CMPLIiiri(CR, LL, RA, IMM) _D (10, ((CR)<<2)|(LL), RA, IMM) + +#define CRANDiii(CRD,CRA,CRB) _X (19, CRD, CRA, CRB, 257, 0) +#define CRANDCiii(CRD,CRA,CRB) _X (19, CRD, CRA, CRB, 129, 0) +#define CREQViii(CRD,CRA,CRB) _X (19, CRD, CRA, CRB, 289, 0) +#define CRNANDiii(CRD,CRA,CRB) _X (19, CRD, CRA, CRB, 225, 0) +#define CRNORiii(CRD,CRA,CRB) _X (19, CRD, CRA, CRB, 33, 0) +#define CRORiii(CRD,CRA,CRB) _X (19, CRD, CRA, CRB, 449, 0) +#define CRORCiii(CRD,CRA,CRB) _X (19, CRD, CRA, CRB, 417, 0) +#define CRXORiii(CRD,CRA,CRB) _X (19, CRD, CRA, CRB, 193, 0) + +#define DCBSTrr(RA,RB) _X (31, 00, RA, RB, 54, 0) + +#define DIVWrrr(RD, RA, RB) _XO (31, RD, RA, RB, 0, 491, 0) +#define DIVW_rrr(RD, RA, RB) _XO (31, RD, RA, RB, 0, 491, 1) +#define DIVWOrrr(RD, RA, RB) _XO (31, RD, RA, RB, 1, 491, 0) +#define DIVWO_rrr(RD, RA, RB) _XO (31, RD, RA, RB, 1, 491, 1) + +#define DIVWUrrr(RD, RA, RB) _XO (31, RD, RA, RB, 0, 459, 0) +#define DIVWU_rrr(RD, RA, RB) _XO (31, RD, RA, RB, 0, 459, 1) +#define DIVWUOrrr(RD, RA, RB) _XO (31, RD, RA, RB, 1, 459, 0) +#define DIVWUO_rrr(RD, RA, RB) _XO (31, RD, RA, RB, 1, 459, 1) + +#define EQVrrr(Ra,RS,RB) _X (31, RS, RA, RB, 284, 0) +#define EQV_rrr(Ra,RS,RB) _X (31, RS, RA, RB, 284, 1) + +#define EXTSBrr(RA,RS) _X (31, RS, RA, 0, 954, 0) +#define EXTSB_rr(RA,RS) _X (31, RS, RA, 0, 954, 1) + +#define EXTSHrr(RA,RS) _X (31, RS, RA, 0, 922, 0) +#define EXTSH_rr(RA,RS) _X (31, RS, RA, 0, 922, 1) + +#define ICBIrr(RA,RB) _X (31, 00, RA, RB, 982, 0) + +#define ISYNC() _X (19, 00, 00, 00, 150, 0) + +#define LBZrm(RD,ID,RA) _D (34, RD, RA, ID) +#define LBZUrm(RD,ID,RA) _D (35, RD, RA, ID) +#define LBZUXrrr(RD,RA,RB) _X (31, RD, RA, RB, 119, 0) +#define LBZXrrr(RD,RA,RB) _X (31, RD, RA, RB, 87, 0) + +#define LHArm(RD,ID,RA) _D (42, RD, RA, ID) +#define LHAUrm(RD,ID,RA) _D (43, RD, RA, ID) +#define LHAUXrrr(RD,RA,RB) _X (31, RD, RA, RB, 375, 0) +#define LHAXrrr(RD,RA,RB) _X (31, RD, RA, RB, 343, 0) +#define LHBRXrrr(RD,RA,RB) _X (31, RD, RA, RB, 790, 0) + +#define LHZrm(RD,ID,RA) _D (40, RD, RA, ID) +#define LHZUrm(RD,ID,RA) _D (41, RD, RA, ID) +#define LHZUXrrr(RD,RA,RB) _X (31, RD, RA, RB, 311, 0) +#define LHZXrrr(RD,RA,RB) _X (31, RD, RA, RB, 279, 0) + +#define LMWrm(RD,ID,RA) _D (46, RD, RA, ID) + +#define LWBRXrrr(RD,RA,RB) _X (31, RD, RA, RB, 534, 0) + +#define LWZrm(RD, DISP, RA) _D (32, RD, RA, DISP) +#define LWZUrm(RD, DISP, RA) _D (33, RD, RA, DISP) +#define LWZUXrrr(RD, RA, RB) _X (31, RD, RA, RB, 56, 0) +#define LWZXrrr(RD, RA, RB) _X (31, RD, RA, RB, 23, 0) + +#define MCRFii(CD,CS) _X (19, ((CD)<<2), ((CS)<<2), 0, 0, 0) + +#define MFCRr(RD) _X (31, RD, 0, 0, 19, 0) +#define MCRXRi(RD) _XFX (31, (RD)<<2, 0, 512) + +#define MFSPRri(RD, SPR) _XFX (31, RD, (SPR)<<5, 339) +#define MTSPRir(SPR, RS) _XFX (31, RS, (SPR)<<5, 467) + +#define MULHWrrr(RD,RA,RB) _XO (31, RD, RA, RB, 0, 75, 0) +#define MULHW_rrr(RD,RA,RB) _XO (31, RD, RA, RB, 0, 75, 1) +#define MULHWUrrr(RD,RA,RB) _XO (31, RD, RA, RB, 0, 11, 0) +#define MULHWU_rrr(RD,RA,RB) _XO (31, RD, RA, RB, 0, 11, 1) + +#define MULLIrri(RD,RA,IM) _D (07, RD, RA, IM) + +#define MULLWrrr(RD,RA,RB) _XO (31, RD, RA, RB, 0, 235, 0) +#define MULLW_rrr(RD,RA,RB) _XO (31, RD, RA, RB, 0, 235, 1) +#define MULLWOrrr(RD,RA,RB) _XO (31, RD, RA, RB, 1, 235, 0) +#define MULLWO_rrr(RD,RA,RB) _XO (31, RD, RA, RB, 1, 235, 1) + +#define NANDrrr(RA,RS,RB) _X (31, RS, RA, RB, 476, 0) +#define NAND_rrr(RA,RS,RB) _X (31, RS, RA, RB, 476, 1) + +#define NEGrr(RD,RA) _XO (31, RD, RA, 0, 0, 104, 0) +#define NEG_rr(RD,RA) _XO (31, RD, RA, 0, 0, 104, 1) +#define NEGOrr(RD,RA) _XO (31, RD, RA, 0, 1, 104, 0) +#define NEGO_rr(RD,RA) _XO (31, RD, RA, 0, 1, 104, 1) + +#define NORrrr(RA,RS,RB) _X (31, RS, RA, RB, 124, 0) +#define NOR_rrr(RA,RS,RB) _X (31, RS, RA, RB, 124, 1) + +#define ORrrr(RA,RS,RB) _X (31, RS, RA, RB, 444, 0) +#define OR_rrr(RA,RS,RB) _X (31, RS, RA, RB, 444, 1) +#define ORCrrr(RA,RS,RB) _X (31, RS, RA, RB, 412, 0) +#define ORC_rrr(RA,RS,RB) _X (31, RS, RA, RB, 412, 1) +#define ORIrri(RA,RS,IM) _Du (24, RS, RA, IM) +#define ORISrri(RA,RS,IM) _Du (25, RS, RA, IM) + +#define RLWIMIrriii(RA,RS,SH,MB,ME) _M (20, RS, RA, SH, MB, ME, 0) +#define RLWIMI_rriii(RA,RS,SH,MB,ME) _M (20, RS, RA, SH, MB, ME, 1) + +#define RLWINMrriii(RA,RS,SH,MB,ME) _M (21, RS, RA, SH, MB, ME, 0) +#define RLWINM_rriii(RA,RS,SH,MB,ME) _M (21, RS, RA, SH, MB, ME, 1) + +#define RLWNMrrrii(RA,RS,RB,MB,ME) _M (23, RS, RA, RB, MB, ME, 0) +#define RLWNM_rrrii(RA,RS,RB,MB,ME) _M (23, RS, RA, RB, MB, ME, 1) + +#define SLWrrr(RA,RS,RB) _X (31, RS, RA, RB, 24, 0) +#define SLW_rrr(RA,RS,RB) _X (31, RS, RA, RB, 24, 1) + +#define SRAWrrr(RA,RS,RB) _X (31, RS, RA, RB, 792, 0) +#define SRAW_rrr(RA,RS,RB) _X (31, RS, RA, RB, 792, 1) + +#define SRAWIrri(RD, RS, SH) _X (31, RS, RD, SH, 824, 0) +#define SRAWI_rri(RD, RS, SH) _X (31, RS, RD, SH, 824, 1) + +#define SRWrrr(RA,RS,RB) _X (31, RS, RA, RB, 536, 0) +#define SRW_rrr(RA,RS,RB) _X (31, RS, RA, RB, 536, 1) + +#define STBrm(RS,ID,RA) _D (38, RS, RA, ID) +#define STBUrm(RS,ID,RA) _D (39, RS, RA, ID) +#define STBUXrrr(RS,RA,RB) _X (31, RS, RA, RB, 247, 0) +#define STBXrrr(RS,RA,RB) _X (31, RS, RA, RB, 215, 0) + +#define STHrm(RS,ID,RA) _D (44, RS, RA, ID) +#define STHUrm(RS,ID,RA) _D (45, RS, RA, ID) +#define STHBRXrrr(RS,RA,RB) _X (31, RS, RA, RB, 918, 0) +#define STHUXrrr(RS,RA,RB) _X (31, RS, RA, RB, 439, 0) +#define STHXrrr(RS,RA,RB) _X (31, RS, RA, RB, 407, 0) + +#define STMWrm(RS,ID,RA) _D (47, RS, RA, ID) + +#define STWrm(RS,ID,RA) _D (36, RS, RA, ID) +#define STWBRXrrr(RS,RA,RB) _X (31, RS, RA, RB, 662, 0) +#define STWCXrrr(RS,RA,RB) _X (31, RS, RA, RB, 150, 0) +#define STWCX_rrr(RS,RA,RB) _X (31, RS, RA, RB, 150, 1) +#define STWUrm(RS,ID,RA) _D (37, RS, RA, ID) +#define STWUXrrr(RS,RA,RB) _X (31, RS, RA, RB, 183, 0) +#define STWXrrr(RS,RA,RB) _X (31, RS, RA, RB, 151, 0) + +#define SUBFrrr(RD, RA, RB) _XO (31, RD, RA, RB, 0, 40, 0) +#define SUBF_rrr(RD, RA, RB) _XO (31, RD, RA, RB, 0, 40, 1) +#define SUBFrrr(RD, RA, RB) _XO (31, RD, RA, RB, 0, 40, 0) +#define SUBF_rrr(RD, RA, RB) _XO (31, RD, RA, RB, 0, 40, 1) +#define SUBFErrr(RD, RA, RB) _XO (31, RD, RA, RB, 1, 136, 0) +#define SUBFE_rrr(RD, RA, RB) _XO (31, RD, RA, RB, 1, 136, 1) +#define SUBFCrrr(RD, RA, RB) _XO (31, RD, RA, RB, 0, 8, 0) +#define SUBFC_rrr(RD, RA, RB) _XO (31, RD, RA, RB, 0, 8, 1) +#define SUBFCOrrr(RD, RA, RB) _XO (31, RD, RA, RB, 1, 8, 0) +#define SUBFCO_rrr(RD, RA, RB) _XO (31, RD, RA, RB, 1, 8, 1) +#define SUBFICrri(RD, RA, IMM) _D (8, RD, RA, IMM) + +#define ADDrrr(RD, RA, RB) _XO (31, RD, RA, RB, 0, 266, 0) +#define ADDOrrr(RD, RA, RB) _XO (31, RD, RA, RB, 1, 266, 0) +#define ADDIrri(RD, RA, IMM) _D (14, RD, RA, IMM) +#define ADDISrri(RD, RA, IMM) _Ds (15, RD, RA, IMM) + +#define SYNC() _X (31, 00, 00, 00, 598, 0) + +#define TWirr(TO,RA,RB) _X (31, TO, RA, RB, 4, 0) +#define TWIiri(TO,RA,IM) _D (03, TO, RA, IM) + +#define XORrrr(RA,RS,RB) _X (31, RS, RA, RB, 316, 0) +#define XOR_rrr(RA,RS,RB) _X (31, RS, RA, RB, 316, 1) +#define XORIrri(RA,RS,IM) _Du (26, RS, RA, IM) +#define XORISrri(RA,RS,IM) _Du (27, RS, RA, IM) + +/* simplified mnemonics [1, Appendix F] */ + +#define MOVEIri2(R,H,L) (LISri(R,H), (L ? ORIrri(R,R,L) : 0)) +#define MOVEIri(R,I) (_siP(16,I) ? LIri(R,I) : \ + MOVEIri2(R, _HI(I), _LO(I)) ) + +#define SUBIrri(RD,RA,IM) ADDIrri(RD,RA,-_jit_L((IM))) /* [1, Section F.2.1] */ +#define SUBISrri(RD,RA,IM) ADDISrri(RD,RA,-_jit_L((IM))) +#define SUBICrri(RD,RA,IM) ADDICrri(RD,RA,-_jit_L((IM))) +#define SUBIC_rri(RD,RA,IM) ADDIC_rri(RD,RA,-_jit_L((IM))) + +#define SUBrrr(RD,RA,RB) SUBFrrr(RD,RB,RA) /* [1, Section F.2.2] */ +#define SUBOrrr(RD,RA,RB) SUBFOrrr(RD,RB,RA) +#define SUB_rrr(RD,RA,RB) SUBF_rrr(RD,RB,RA) +#define SUBCrrr(RD,RA,RB) SUBFCrrr(RD,RB,RA) +#define SUBCOrrr(RD,RA,RB) SUBFCOrrr(RD,RB,RA) +#define SUBC_rrr(RD,RA,RB) SUBFC_rrr(RD,RB,RA) +#define SUBErrr(RD,RA,RB) SUBFErrr(RD,RB,RA) +#define SUBE_rrr(RD,RA,RB) SUBFE_rrr(RD,RB,RA) + +#define CMPWIiri(C,RA,IM) CMPIiiri(C,0,RA,IM) /* [1, Table F-2] */ +#define CMPWirr(C,RA,RB) CMPiirr(C,0,RA,RB) +#define CMPLWIiri(C,RA,IM) CMPLIiiri(C,0,RA,IM) +#define CMPLWirr(C,RA,RB) CMPLiirr(C,0,RA,RB) + +#define CMPWIri(RA,IM) CMPWIiri(0,RA,IM) /* with implicit _cr0 */ +#define CMPWrr(RA,RB) CMPWirr(0,RA,RB) +#define CMPLWIri(RA,IM) CMPLWIiri(0,RA,IM) +#define CMPLWrr(RA,RB) CMPLWirr(0,RA,RB) + +#define EXTLWIrrii(RA,RS,N,B) RLWINMrriii(RA, RS, B, 0, (N)-1) /* [1, Table F-3] */ +#define EXTRWIrrii(RA,RS,N,B) RLWINMrriii(RA, RS, (B)+(N), 32-(N), 31) +#define INSLWIrrii(RA,RS,N,B) RLWIMIrriii(RA, RS, 32-(B), B, (B)+(N)-1) +#define INSRWIrrii(RA,RS,N,B) RLWIMIrriii(RA, RS, 32-((B)+(N)), B, (B)+(N)-1) +#define ROTLWIrri(RA,RS,N) RLWINMrriii(RA, RS, N, 0, 31) +#define ROTRWIrri(RA,RS,N) RLWINMrriii(RA, RS, 32-(N), 0, 31) +#define ROTLWrrr(RA,RS,RB) RLWNMrrrii( RA, RS, RB, 0, 31) +#define SLWIrri(RA,RS,N) RLWINMrriii(RA, RS, N, 0, 31-(N)) +#define SRWIrri(RA,RS,N) RLWINMrriii(RA, RS, 32-(N), N, 31) +#define CLRLWIrri(RA,RS,N) RLWINMrriii(RA, RS, 0, N, 31) +#define CLRRWIrri(RA,RS,N) RLWINMrriii(RA, RS, 0, 0, 31-(N)) +#define CLRLSLWIrrii(RA,RS,B,N) RLWINMrriii(RA, RS, N, (B)-(N), 31-(N)) + +/* 9 below inverts the branch condition and the branch prediction. + * This has an incestuous knowledge of the fact that register 26 + * is used as auxiliary!!! */ +#define BC_EXT(A, C, D) (_siP(16, _jit_UL(D)-_jit_UL(_jit.x.pc)) \ + ? BCiii((A), (C), (D)) \ + : (BCiii((A)^9, (C), _jit.x.pc+5), LISri(26,_HI(D)), ORIrri(26,26,_LO(D)), \ + MTLRr(26), BLR() )) + +#define B_EXT(D) (_siP(16, _jit_UL(D)-_jit_UL(_jit.x.pc)) \ + ? Bi((D)) \ + : (LISri(26,_HI(D)), ORIrri(26,26,_LO(D)), MTLRr(26), BLR()) ) + +#define BTii(C,D) BC_EXT(12, C, D) /* [1, Table F-5] */ +#define BFii(C,D) BC_EXT( 4, C, D) +#define BDNZi(D) BCiii(16, 0, D) +#define BDNZTii(C,D) BC_EXT( 8, C, D) +#define BDNZFii(C,D) BC_EXT( 0, C, D) +#define BDZi(D) BCiii(18, 0, D) +#define BDZTii(C,D) BC_EXT(10, C, D) +#define BDZFii(C,D) BC_EXT( 2, C, D) + +#define BCTR() BCCTRii(20, 0) /* [1, Table F-6] */ +#define BCTRL() BCCTRLii(20, 0) + +#define BLR() BCLRii(20, 0) /* [1, Table F-6] */ +#define BLRL() BCLRLii(20, 0) + + +#define BLTLRi(CR) BCLRii(12, ((CR)<<2)+0) /* [1, Table F-10] */ +#define BLELRi(CR) BCLRii( 4 ((CR)<<2)+1) +#define BEQLRi(CR) BCLRii(12, ((CR)<<2)+2) +#define BGELRi(CR) BCLRii( 4, ((CR)<<2)+0) +#define BGTLRi(CR) BCLRii(12, ((CR)<<2)+1) +#define BNLLRi(CR) BCLRii( 4, ((CR)<<2)+0) +#define BNELRi(CR) BCLRii( 4, ((CR)<<2)+2) +#define BNGLRi(CR) BCLRii( 4, ((CR)<<2)+1) +#define BSOLRi(CR) BCLRii(12, ((CR)<<2)+3) +#define BNSLRi(CR) BCLRii( 4, ((CR)<<2)+3) +#define BUNLRi(CR) BCLRii(12, ((CR)<<2)+3) +#define BNULRi(CR) BCLRii( 4, ((CR)<<2)+3) + +#define BLTLRLi(CR) BCLRLii(12, ((CR)<<2)+0) /* [1, Table F-10] */ +#define BLELRLi(CR) BCLRLii( 4, ((CR)<<2)+1) +#define BEQLRLi(CR) BCLRLii(12, ((CR)<<2)+2) +#define BGELRLi(CR) BCLRLii( 4, ((CR)<<2)+0) +#define BGTLRLi(CR) BCLRLii(12, ((CR)<<2)+1) +#define BNLLRLi(CR) BCLRLii( 4, ((CR)<<2)+0) +#define BNELRLi(CR) BCLRLii( 4, ((CR)<<2)+2) +#define BNGLRLi(CR) BCLRLii( 4, ((CR)<<2)+1) +#define BSOLRLi(CR) BCLRLii(12, ((CR)<<2)+3) +#define BNSLRLi(CR) BCLRLii( 4, ((CR)<<2)+3) +#define BUNLRLi(CR) BCLRLii(12, ((CR)<<2)+3) +#define BNULRLi(CR) BCLRLii( 4, ((CR)<<2)+3) + +#define BLTCTRi(CR) BCCTRii(12, ((CR)<<2)+0) /* [1, Table F-10] */ +#define BLECTRi(CR) BCCTRii( 4 ((CR)<<2)+1) +#define BEQCTRi(CR) BCCTRii(12, ((CR)<<2)+2) +#define BGECTRi(CR) BCCTRii( 4, ((CR)<<2)+0) +#define BGTCTRi(CR) BCCTRii(12, ((CR)<<2)+1) +#define BNLCTRi(CR) BCCTRii( 4, ((CR)<<2)+0) +#define BNECTRi(CR) BCCTRii( 4, ((CR)<<2)+2) +#define BNGCTRi(CR) BCCTRii( 4, ((CR)<<2)+1) +#define BSOCTRi(CR) BCCTRii(12, ((CR)<<2)+3) +#define BNSCTRi(CR) BCCTRii( 4, ((CR)<<2)+3) +#define BUNCTRi(CR) BCCTRii(12, ((CR)<<2)+3) +#define BNUCTRi(CR) BCCTRii( 4, ((CR)<<2)+3) + +#define BLTCTRLi(CR) BCCTRLii(12, ((CR)<<2)+0) /* [1, Table F-10] */ +#define BLECTRLi(CR) BCCTRLii( 4, ((CR)<<2)+1) +#define BEQCTRLi(CR) BCCTRLii(12, ((CR)<<2)+2) +#define BGECTRLi(CR) BCCTRLii( 4, ((CR)<<2)+0) +#define BGTCTRLi(CR) BCCTRLii(12, ((CR)<<2)+1) +#define BNLCTRLi(CR) BCCTRLii( 4, ((CR)<<2)+0) +#define BNECTRLi(CR) BCCTRLii( 4, ((CR)<<2)+2) +#define BNGCTRLi(CR) BCCTRLii( 4, ((CR)<<2)+1) +#define BSOCTRLi(CR) BCCTRLii(12, ((CR)<<2)+3) +#define BNSCTRLi(CR) BCCTRLii( 4, ((CR)<<2)+3) +#define BUNCTRLi(CR) BCCTRLii(12, ((CR)<<2)+3) +#define BNUCTRLi(CR) BCCTRLii( 4, ((CR)<<2)+3) + + +#define BLTLR() BLTLRi(0) /* with implicit _cr0 */ +#define BLELR() BLELRi(0) +#define BEQLR() BEQLRi(0) +#define BGELR() BGELRi(0) +#define BGTLR() BGTLRi(0) +#define BNLLR() BNLLRi(0) +#define BNELR() BNELRi(0) +#define BNGLR() BNGLRi(0) +#define BSOLR() BSOLRi(0) +#define BNSLR() BNSLRi(0) +#define BUNLR() BUNLRi(0) +#define BNULR() BNULRi(0) + +#define BLTLRL() BLTLRLi(0) +#define BLELRL() BLELRLi(0) +#define BEQLRL() BEQLRLi(0) +#define BGELRL() BGELRLi(0) +#define BGTLRL() BGTLRLi(0) +#define BNLLRL() BNLLRLi(0) +#define BNELRL() BNELRLi(0) +#define BNGLRL() BNGLRLi(0) +#define BSOLRL() BSOLRLi(0) +#define BNSLRL() BNSLRLi(0) +#define BUNLRL() BUNLRLi(0) +#define BNULRL() BNULRLi(0) + +#define BLTCTR() BLTCTRi(0) +#define BLECTR() BLECTRi(0) +#define BEQCTR() BEQCTRi(0) +#define BGECTR() BGECTRi(0) +#define BGTCTR() BGTCTRi(0) +#define BNLCTR() BNLCTRi(0) +#define BNECTR() BNECTRi(0) +#define BNGCTR() BNGCTRi(0) +#define BSOCTR() BSOCTRi(0) +#define BNSCTR() BNSCTRi(0) +#define BUNCTR() BUNCTRi(0) +#define BNUCTR() BNUCTRi(0) + +#define BLTCTRL() BLTCTRLi(0) +#define BLECTRL() BLECTRLi(0) +#define BEQCTRL() BEQCTRLi(0) +#define BGECTRL() BGECTRLi(0) +#define BGTCTRL() BGTCTRLi(0) +#define BNLCTRL() BNLCTRLi(0) +#define BNECTRL() BNECTRLi(0) +#define BNGCTRL() BNGCTRLi(0) +#define BSOCTRL() BSOCTRLi(0) +#define BNSCTRL() BNSCTRLi(0) +#define BUNCTRL() BUNCTRLi(0) +#define BNUCTRL() BNUCTRLi(0) + + +#define BLTii(C,D) BC_EXT(12, ((C)<<2)+0, D) /* [1, Table F-11] */ +#define BNLii(C,D) BC_EXT( 4, ((C)<<2)+0, D) +#define BGEii(C,D) BC_EXT( 4, ((C)<<2)+0, D) +#define BGTii(C,D) BC_EXT(12, ((C)<<2)+1, D) +#define BNGii(C,D) BC_EXT( 4, ((C)<<2)+1, D) +#define BLEii(C,D) BC_EXT( 4, ((C)<<2)+1, D) +#define BEQii(C,D) BC_EXT(12, ((C)<<2)+2, D) +#define BNEii(C,D) BC_EXT( 4, ((C)<<2)+2, D) +#define BSOii(C,D) BC_EXT(12, ((C)<<2)+3, D) +#define BNSii(C,D) BC_EXT( 4, ((C)<<2)+3, D) +#define BUNii(C,D) BC_EXT(12, ((C)<<2)+3, D) +#define BNUii(C,D) BC_EXT( 4, ((C)<<2)+3, D) + +#define BLTi(D) BLTii(0,D) /* with implicit _cr0 */ +#define BLEi(D) BLEii(0,D) +#define BEQi(D) BEQii(0,D) +#define BGEi(D) BGEii(0,D) +#define BGTi(D) BGTii(0,D) +#define BNLi(D) BNLii(0,D) +#define BNEi(D) BNEii(0,D) +#define BNGi(D) BNGii(0,D) +#define BSOi(D) BSOii(0,D) +#define BNSi(D) BNSii(0,D) +#define BUNi(D) BUNii(0,D) +#define BNUi(D) BNUii(0,D) + +#define BLTLii(C,D) BCLiii(12, ((C)<<2)+0, D) /* [1, Table F-??] */ +#define BLELii(C,D) BCLiii( 4 ((C)<<2)+1, D) +#define BEQLii(C,D) BCLiii(12, ((C)<<2)+2, D) +#define BGELii(C,D) BCLiii( 4, ((C)<<2)+0, D) +#define BGTLii(C,D) BCLiii(12, ((C)<<2)+1, D) +#define BNLLii(C,D) BCLiii( 4, ((C)<<2)+0, D) +#define BNELii(C,D) BCLiii( 4, ((C)<<2)+2, D) +#define BNGLii(C,D) BCLiii( 4, ((C)<<2)+1, D) +#define BSOLii(C,D) BCLiii(12, ((C)<<2)+3, D) +#define BNSLii(C,D) BCLiii( 4, ((C)<<2)+3, D) +#define BUNLii(C,D) BCLiii(12, ((C)<<2)+3, D) +#define BNULii(C,D) BCLiii( 4, ((C)<<2)+3, D) + +#define BLTLi(D) BLTLii(0,D) /* with implicit _cr0 */ +#define BLELi(D) BLELii(0,D) +#define BEQLi(D) BEQLii(0,D) +#define BGELi(D) BGELii(0,D) +#define BGTLi(D) BGTLii(0,D) +#define BNLLi(D) BNLLii(0,D) +#define BNELi(D) BNELii(0,D) +#define BNGLi(D) BNGLii(0,D) +#define BSOLi(D) BSOLii(0,D) +#define BNSLi(D) BNSLii(0,D) +#define BUNLi(D) BUNLii(0,D) +#define BNULi(D) BNULii(0,D) + +/* Note: there are many tens of other simplified branches that are not (yet?) defined here */ + +#define CRSETi(BX) CREQViii(BX, BX, BX) /* [1, Table F-15] */ +#define CRCLRi(BX) CRXORiii(BX, BX, BX) +#define CRMOVEii(BX,BY) CRORiii(BX, BY, BY) +#define CRNOTii(BX,BY) CRNORiii(BX, BY, BY) + +#define MTLRr(RS) MTSPRir(8, RS) /* [1, Table F-20] */ +#define MFLRr(RD) MFSPRri(RD, 8) +#define MTCTRr(RS) MTSPRir(9, RS) +#define MFCTRr(RD) MFSPRri(RD, 9) +#define MTXERr(RS) MTSPRir(1, RS) +#define MFXERr(RD) MFSPRri(RD, 1) + +#define NOP() ORIrri(0, 0, 0) /* [1, Section F.9] */ +#define LIri(RD,IM) ADDIrri(RD, 0, IM) +#define LISri(RD,IM) ADDISrri(RD, 0, IM) +#define LArm(RD,D,RA) ADDIrri(RD, RA, D) +#define LArrr(RD,RB,RA) ADDIrrr(RD, RA, RB) +#define MRrr(RA,RS) ORrrr(RA, RS, RS) +#define NOTrr(RA,RS) NORrrr(RA, RS, RS) + +/* alternative parenthesised forms of extended indexed load/store insns */ + +#define LBZUrx(RD,RA,RB) LBZUXrrr(RD,RA,RB) +#define LBZrx(RD,RA,RB) LBZXrrr(RD,RA,RB) +#define LHAUrx(RD,RA,RB) LHAUXrrr(RD,RA,RB) +#define LHArx(RD,RA,RB) LHAXrrr(RD,RA,RB) +#define LHBRrx(RD,RA,RB) LHBRXrrr(RD,RA,RB) +#define LHZUrx(RD,RA,RB) LHZUXrrr(RD,RA,RB) +#define LHZrx(RD,RA,RB) LHZXrrr(RD,RA,RB) +#define LWBRrx(RD,RA,RB) LWBRXrrr(RD,RA,RB) +#define LWZUrx(RD, RA, RB) LWZUXrrr(RD, RA, RB) +#define LWZrx(RD, RA, RB) LWZXrrr(RD, RA, RB) +#define STBUrx(RD,RA,RB) STBUXrrr(RD,RA,RB) +#define STBrx(RD,RA,RB) STBXrrr(RD,RA,RB) +#define STHBRrx(RS,RA,RB) STHBRXrrr(RS,RA,RB) +#define STHUrx(RS,RA,RB) STHUXrrr(RS,RA,RB) +#define STHrx(RS,RA,RB) STHXrrr(RS,RA,RB) +#define STWBRrx(RS,RA,RB) STWBRXrrr(RS,RA,RB) +#define STWCrx(RS,RA,RB) STWCXrrr(RS,RA,RB) +#define STWCX_rx(RS,RA,RB) STWCX_rrr(RS,RA,RB) +#define STWUrx(RS,RA,RB) STWUXrrr(RS,RA,RB) +#define STWrx(RS,RA,RB) STWXrrr(RS,RA,RB) +#define LArx(RD,RB,RA) LArrr(RD,RB,RA) + + +#define _LO(I) (_jit_UL(I) & _MASK(16)) +#define _HI(I) (_jit_UL(I) >> (16)) + + + +/*** References: + * + * [1] "PowerPC Microprocessor Family: The Programming Environments For 32-Bit Microprocessors", Motorola, 1997. + */ + + +#endif /* __ccg_asm_ppc_h */ diff --git a/lightning/ppc/core.h b/lightning/ppc/core.h new file mode 100644 index 000000000..1377e5147 --- /dev/null +++ b/lightning/ppc/core.h @@ -0,0 +1,276 @@ +/******************************** -*- C -*- **************************** + * + * Platform-independent layer (PowerPC version) + * + ***********************************************************************/ + + +/*********************************************************************** + * + * 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 2.1, 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. + * + ***********************************************************************/ + + + + +#ifndef __lightning_core_h +#define __lightning_core_h + +struct jit_local_state { + int nextarg_put; /* Next r3-r8 reg. to be written */ + int nextarg_putfp; /* Next r3-r8 reg. to be written */ + int nextarg_get; /* Next r20-r25 reg. to be read */ +}; + +#define JIT_SP 1 +#define JIT_RET 3 +#define JIT_R0 9 +#define JIT_R1 10 +#define JIT_R2 30 /* using r8 would limit argument passing */ +#define JIT_V0 29 +#define JIT_V1 28 +#define JIT_V2 27 +#define JIT_AUX 26 /* for 32-bit operands & shift counts */ + +/* If possible, use the `small' instruction (rd, rs, imm) + * else load imm into r26 and use the `big' instruction (rd, rs, r26) + */ +#define jit_chk_ims(imm, small, big) (_siP(16,(imm)) ? (small) : (MOVEIri(JIT_AUX, imm), (big)) ) +#define jit_chk_imu(imm, small, big) (_uiP(16,(imm)) ? (small) : (MOVEIri(JIT_AUX, imm), (big)) ) +#define jit_chk_imu15(imm, small, big) (_uiP(15,(imm)) ? (small) : (MOVEIri(JIT_AUX, imm), (big)) ) + +/* Helper macros for branches */ +#define jit_s_brai(rs, is, jmp) (jit_chk_ims (is, CMPWIri(rs, is), CMPWrr(rs, JIT_AUX)), jmp, _jit.x.pc) +#define jit_s_brar(s1, s2, jmp) ( CMPWrr(s1, s2), jmp, _jit.x.pc) +#define jit_u_brai(rs, is, jmp) (jit_chk_imu (is, CMPLWIri(rs, is), CMPLWrr(rs, JIT_AUX)), jmp, _jit.x.pc) +#define jit_u_brar(s1, s2, jmp) ( CMPLWrr(s1, s2), jmp, _jit.x.pc) + +/* Helper macros for boolean tests. */ +#define jit_sbooli(d, rs, is, jmp) (jit_chk_ims (is, CMPWIri (rs, is), CMPWrr(rs, JIT_AUX)), MFCRr((d)), EXTRWIrrii((d), (d), 1, (jmp))) +#define jit_sboolr(d, s1, s2, jmp) ( CMPWrr (s1, s2), MFCRr((d)), EXTRWIrrii((d), (d), 1, (jmp))) +#define jit_sbooli2(d, rs, is, jmp) (jit_chk_ims (is, CMPWIri (rs, is), CMPWrr(rs, JIT_AUX)), MFCRr((d)), EXTRWIrrii((d), (d), 1, (jmp)), XORIrri((d), (d), 1)) +#define jit_sboolr2(d, s1, s2, jmp) ( CMPWrr (s1, s2), MFCRr((d)), EXTRWIrrii((d), (d), 1, (jmp)), XORIrri((d), (d), 1)) +#define jit_ubooli(d, rs, is, jmp) (jit_chk_imu (is, CMPLWIri(rs, is), CMPLWrr(rs, JIT_AUX)), MFCRr((d)), EXTRWIrrii((d), (d), 1, (jmp))) +#define jit_uboolr(d, s1, s2, jmp) ( CMPLWrr (s1, s2), MFCRr((d)), EXTRWIrrii((d), (d), 1, (jmp))) +#define jit_ubooli2(d, rs, is, jmp) (jit_chk_imu (is, CMPLWIri(rs, is), CMPLWrr(rs, JIT_AUX)), MFCRr((d)), EXTRWIrrii((d), (d), 1, (jmp)), XORIrri((d), (d), 1)) +#define jit_uboolr2(d, s1, s2, jmp) ( CMPLWrr (s1, s2), MFCRr((d)), EXTRWIrrii((d), (d), 1, (jmp)), XORIrri((d), (d), 1)) + +/* modulus with immediate + * movei r26, imm + * mtlr r31 + * divw r31, rs, r26 (or divwu) + * mullw r31, r31, r26 + * sub rs, rs, r26 + * mflr r31 + */ + +#define _jit_mod(div, rs, imm) (MOVEIri(JIT_AUX, (imm)), MTLRr(31), (div), \ + MULLWrrr(31, 31, JIT_AUX), SUBrrr((rs), (rs), JIT_AUX), \ + MFLRr(31)) + +/* Emit a 2-instruction MOVEI, even if a 1-instruction one is possible + * (it is a rare case for branches, and a fixed sequence of instructions + * is easier to patch). */ +#define jit_movei(reg, imm) (LISri(reg,_HI(imm)), ORIrri((reg),(reg),_LO(imm))) + +/* Patch a movei instruction made of a LIS at lis_pc and an ORI at ori_pc. */ +#define jit_patch_movei(lis_pc, ori_pc) \ + (*(lis_pc) &= ~_MASK(16), *lis_pc |= _HI(_jit.x.pc), \ + *(ori_pc) &= ~_MASK(16), *ori_pc |= _LO(_jit.x.pc)) \ + +/* Patch a branch instruction */ +#define jit_patch_branch(jump_pc) \ + (*(jump_pc) &= ~_MASK(16) | 3, \ + *(jump_pc) |= (_jit_UL(_jit.x.pc) - _jit_UL(jump_pc)) & _MASK(16)) + +#define _jit_blr_encoding ((19 << 26) | (20 << 21) | (00 << 16) | (00 << 11) | (16 << 1)) + +#define jit_patch(jump_pc) ( \ + ((*(jump_pc - 1) & ~1) == _jit_blr_encoding) \ + ? jit_patch_movei(((jump_pc) - 4), ((jump_pc) - 3)) \ + : jit_patch_branch((jump_pc) - 1)) + + +#define jit_arg_c() (_jitl.nextarg_get--) +#define jit_arg_i() (_jitl.nextarg_get--) +#define jit_arg_l() (_jitl.nextarg_get--) +#define jit_arg_p() (_jitl.nextarg_get--) +#define jit_arg_s() (_jitl.nextarg_get--) +#define jit_arg_uc() (_jitl.nextarg_get--) +#define jit_arg_ui() (_jitl.nextarg_get--) +#define jit_arg_ul() (_jitl.nextarg_get--) +#define jit_arg_us() (_jitl.nextarg_get--) +#define jit_addi_i(d, rs, is) jit_chk_ims((is), ADDICrri((d), (rs), (is)), ADDrrr((d), (rs), JIT_AUX)) +#define jit_addr_i(d, s1, s2) ADDrrr((d), (s1), (s2)) +#define jit_addci_i(d, rs, is) jit_chk_ims((is), ADDICrri((d), (rs), (is)), ADDCrrr((d), (rs), JIT_AUX)) +#define jit_addcr_i(d, s1, s2) ADDCrrr((d), (s1), (s2)) +#define jit_addxi_i(d, rs, is) (MOVEIri(JIT_AUX, (is)), ADDErrr((d), (rs), JIT_AUX)) +#define jit_addxr_i(d, s1, s2) ADDErrr((d), (s1), (s2)) +#define jit_andi_i(d, rs, is) jit_chk_imu((is), ANDI_rri((d), (rs), (is)), ANDrrr((d), (rs), JIT_AUX)) +#define jit_andr_i(d, s1, s2) ANDrrr((d), (s1), (s2)) +#define jit_bmsi_i(label, rs, is) (jit_chk_imu((is), ANDI_rri(JIT_AUX, (rs), (is)), AND_rrr(JIT_AUX, (rs), JIT_AUX)), BGTi((label)), _jit.x.pc) +#define jit_bmci_i(label, rs, is) (jit_chk_imu((is), ANDI_rri(JIT_AUX, (rs), (is)), AND_rrr(JIT_AUX, (rs), JIT_AUX)), BEQi((label)), _jit.x.pc) +#define jit_bmsr_i(label, s1, s2) ( AND_rrr(JIT_AUX, (s1), (s2)), BGTi((label)), _jit.x.pc) +#define jit_bmcr_i(label, s1, s2) ( AND_rrr(JIT_AUX, (s1), (s2)), BEQi((label)), _jit.x.pc) +#define jit_beqi_i(label, rs, is) jit_s_brai((rs), (is), BEQi((label)) ) +#define jit_beqr_i(label, s1, s2) jit_s_brar((s1), (s2), BEQi((label)) ) +#define jit_bgei_i(label, rs, is) jit_s_brai((rs), (is), BGEi((label)) ) +#define jit_bgei_ui(label, rs, is) jit_u_brai((rs), (is), BGEi((label)) ) +#define jit_bger_i(label, s1, s2) jit_s_brar((s1), (s2), BGEi((label)) ) +#define jit_bger_ui(label, s1, s2) jit_u_brar((s1), (s2), BGEi((label)) ) +#define jit_bgti_i(label, rs, is) jit_s_brai((rs), (is), BGTi((label)) ) +#define jit_bgti_ui(label, rs, is) jit_u_brai((rs), (is), BGTi((label)) ) +#define jit_bgtr_i(label, s1, s2) jit_s_brar((s1), (s2), BGTi((label)) ) +#define jit_bgtr_ui(label, s1, s2) jit_u_brar((s1), (s2), BGTi((label)) ) +#define jit_blei_i(label, rs, is) jit_s_brai((rs), (is), BLEi((label)) ) +#define jit_blei_ui(label, rs, is) jit_u_brai((rs), (is), BLEi((label)) ) +#define jit_bler_i(label, s1, s2) jit_s_brar((s1), (s2), BLEi((label)) ) +#define jit_bler_ui(label, s1, s2) jit_u_brar((s1), (s2), BLEi((label)) ) +#define jit_blti_i(label, rs, is) jit_s_brai((rs), (is), BLTi((label)) ) +#define jit_blti_ui(label, rs, is) jit_u_brai((rs), (is), BLTi((label)) ) +#define jit_bltr_i(label, s1, s2) jit_s_brar((s1), (s2), BLTi((label)) ) +#define jit_bltr_ui(label, s1, s2) jit_u_brar((s1), (s2), BLTi((label)) ) +#define jit_bnei_i(label, rs, is) jit_s_brai((rs), (is), BNEi((label)) ) +#define jit_bner_i(label, s1, s2) jit_s_brar((s1), (s2), BNEi((label)) ) +#define jit_boaddi_i(label, rs, is) (MOVEIri(JIT_AUX, (is)), ADDOrrr((rs), (rs), JIT_AUX), MCRXRi(0), BGTi((label)), _jit.x.pc) /* GT = bit 1 of XER = OV */ +#define jit_bosubi_i(label, rs, is) (MOVEIri(JIT_AUX, (is)), SUBCOrrr((rs), (rs), JIT_AUX), MCRXRi(0), BGTi((label)), _jit.x.pc) +#define jit_boaddr_i(label, s1, s2) ( ADDOrrr((s1), (s1), (s2)), MCRXRi(0), BGTi((label)), _jit.x.pc) +#define jit_bosubr_i(label, s1, s2) ( SUBCOrrr((s1), (s1), (s2)), MCRXRi(0), BGTi((label)), _jit.x.pc) +#define jit_boaddi_ui(label, rs, is) (jit_chk_ims ((is), ADDICri((rs), (rs), is), ADDCrr((rs), JIT_AUX)), MCRXRi(0), BEQi((label)), _jit.x.pc) /* EQ = bit 2 of XER = CA */ +#define jit_bosubi_ui(label, rs, is) (jit_chk_ims ((is), SUBICri((rs), (rs), is), SUBCrr((rs), JIT_AUX)), MCRXRi(0), BEQi((label)), _jit.x.pc) +#define jit_boaddr_ui(label, s1, s2) ( ADDCrr((s1), (s1), (s2)), MCRXRi(0), BEQi((label)), _jit.x.pc) +#define jit_bosubr_ui(label, s1, s2) ( SUBCrr((s1), (s1), (s2)), MCRXRi(0), BEQi((label)), _jit.x.pc) +#define jit_calli(label) (jit_movei(JIT_AUX, (label)), MTLRr(JIT_AUX), BLRL(), _jit.x.pc) +#define jit_divi_i(d, rs, is) jit_chk_ims(1111111, 0, DIVWrrr ((d), (rs), JIT_AUX)) +#define jit_divi_ui(d, rs, is) jit_chk_imu(1111111, 0, DIVWUrrr((d), (rs), JIT_AUX)) +#define jit_divr_i(d, s1, s2) DIVWrrr ((d), (s1), (s2)) +#define jit_divr_ui(d, s1, s2) DIVWUrrr((d), (s1), (s2)) +#define jit_eqi_i(d, rs, is) (jit_chk_ims((is), SUBIrri(JIT_AUX, (rs), (is)), SUBrrr(JIT_AUX, (rs), JIT_AUX)), SUBFICrri((d), JIT_AUX, 0), ADDErrr((d), (d), JIT_AUX)) +#define jit_eqr_i(d, s1, s2) (SUBrrr(JIT_AUX, (s1), (s2)), SUBFICrri((d), JIT_AUX, 0), ADDErrr((d), (d), JIT_AUX)) +#define jit_extr_c_i(d, rs) EXTSBrr((d), (rs)) +#define jit_extr_s_i(d, rs) EXTSHrr((d), (rs)) +#define jit_gei_i(d, rs, is) jit_sbooli2((d), (rs), (is), _lt) +#define jit_gei_ui(d, rs, is) jit_ubooli2((d), (rs), (is), _lt) +#define jit_ger_i(d, s1, s2) jit_sboolr2((d), (s1), (s2), _lt) +#define jit_ger_ui(d, s1, s2) jit_uboolr2((d), (s1), (s2), _lt) +#define jit_gti_i(d, rs, is) jit_sbooli ((d), (rs), (is), _gt) +#define jit_gti_ui(d, rs, is) jit_ubooli ((d), (rs), (is), _gt) +#define jit_gtr_i(d, s1, s2) jit_sboolr ((d), (s1), (s2), _gt) +#define jit_gtr_ui(d, s1, s2) jit_uboolr ((d), (s1), (s2), _gt) +#define jit_hmuli_i(d, rs, is) jit_chk_ims(1111111, 0, MULHWrrr ((d), (rs), JIT_AUX)) +#define jit_hmuli_ui(d, rs, is) jit_chk_imu(1111111, 0, MULHWUrrr((d), (rs), JIT_AUX)) +#define jit_hmulr_i(d, s1, s2) MULHWrrr ((d), (s1), (s2)) +#define jit_hmulr_ui(d, s1, s2) MULHWUrrr((d), (s1), (s2)) +#define jit_jmpi(label) (B_EXT((label)), _jit.x.pc) +#define jit_jmpr(reg) (MTLRr(reg), BLR()) +#define jit_ldxi_c(d, rs, is) (jit_ldxi_uc((d), (rs), (is)), jit_extr_c_i((d), (d))) +#define jit_ldxr_c(d, s1, s2) (jit_ldxr_uc((d), (s1), (s2)), jit_extr_c_i((d), (d))) +#define jit_ldxi_i(d, rs, is) jit_chk_ims((d), LWZrm((d), (is), (rs)), LWZrx((d), JIT_AUX, (rs))) +#define jit_ldxi_s(d, rs, is) jit_chk_ims((d), LHArm((d), (is), (rs)), LHArx((d), JIT_AUX, (rs))) +#define jit_ldxi_uc(d, rs, is) jit_chk_ims((d), LBZrm((d), (is), (rs)), LBZrx((d), JIT_AUX, (rs))) +#define jit_ldxi_us(d, rs, is) jit_chk_ims((d), LHZrm((d), (is), (rs)), LHZrx((d), JIT_AUX, (rs))) +#define jit_ldxr_i(d, s1, s2) LWZrx((d), (s1), (s2)) +#define jit_ldxr_s(d, s1, s2) LHArx((d), (s1), (s2)) +#define jit_ldxr_uc(d, s1, s2) LBZrx((d), (s1), (s2)) +#define jit_ldxr_us(d, s1, s2) LHZrx((d), (s1), (s2)) +#define jit_lei_i(d, rs, is) jit_sbooli2((d), (rs), (is), _gt ) +#define jit_lei_ui(d, rs, is) jit_ubooli2((d), (rs), (is), _gt ) +#define jit_ler_i(d, s1, s2) jit_sboolr2((d), (s1), (s2), _gt ) +#define jit_ler_ui(d, s1, s2) jit_uboolr2((d), (s1), (s2), _gt ) +#define jit_lshi_i(d, rs, is) SLWIrri((d), (rs), (is)) +#define jit_lshr_i(d, s1, s2) (ANDIrri(JIT_AUX, (s2), 31), SLWrrr ((d), (s1), JIT_AUX)) +#define jit_lti_i(d, rs, is) jit_sbooli ((d), (rs), (is), _lt ) +#define jit_lti_ui(d, rs, is) jit_ubooli ((d), (rs), (is), _lt ) +#define jit_ltr_i(d, s1, s2) jit_sboolr ((d), (s1), (s2), _lt ) +#define jit_ltr_ui(d, s1, s2) jit_uboolr ((d), (s1), (s2), _lt ) +#define jit_modi_i(d, rs, is) _jit_mod(jit_divi_i (31, (rs), JIT_AUX), (is)) +#define jit_modi_ui(d, rs, is) _jit_mod(jit_divi_ui(31, (rs), JIT_AUX), (irs)) +#define jit_modr_i(d, s1, s2) (DIVWrrr(JIT_AUX, (s1), (s2)), MULLWrrr(JIT_AUX, JIT_AUX, (s2)), SUBrrr((d), (s1), JIT_AUX)) +#define jit_modr_ui(d, s1, s2) (DIVWUrrr(JIT_AUX, (s1), (s2)), MULLWrrr(JIT_AUX, JIT_AUX, (s2)), SUBrrr((d), (s1), JIT_AUX)) +#define jit_movi_i(d, is) MOVEIri((d), (is)) +#define jit_movr_i(d, rs) MRrr((d), (rs)) +#define jit_muli_i(d, rs, is) jit_chk_ims ((is), MULLIrri((d), (rs), (is)), MULLWrrr((d), (rs), JIT_AUX)) +#define jit_muli_ui(d, rs, is) jit_chk_imu15((is), MULLIrri((d), (rs), (is)), MULLWrrr((d), (rs), JIT_AUX)) +#define jit_mulr_i(d, s1, s2) MULLWrrr((d), (s1), (s2)) +#define jit_mulr_ui(d, s1, s2) MULLWrrr((d), (s1), (s2)) +#define jit_nei_i(d, rs, is) (jit_chk_ims((is), SUBIrri(JIT_AUX, (rs), (is)), SUBrrr(JIT_AUX, (rs), JIT_AUX)), ADDICrri((d), JIT_AUX, -1), SUBFErrr((d), (d), JIT_AUX)) +#define jit_ner_i(d, s1, s2) (SUBrrr(JIT_AUX, (s1), (s2)), ADDICrri((d), JIT_AUX, -1), SUBFErrr((d), (d), JIT_AUX)) +#define jit_nop() NOP() +#define jit_ori_i(d, rs, is) jit_chk_imu((is), ORIrri((d), (rs), (is)), ORrrr((d), (rs), JIT_AUX)) +#define jit_orr_i(d, s1, s2) ORrrr((d), (s1), (s2)) +#define jit_popr_i(rs) (LWZrm((rs), 0, 1), ADDIrri(1, 1, 4)) +#define jitfp_prepare(numi, numf, numd) (_jitl.nextarg_put = 3 + (numi) + (numf) + 2*(numd)) +#define jit_prolog(n) _jit_prolog(&_jit, (n)) +#define jit_pushr_i(rs) STWUrm((rs), -4, 1) +#define jit_pusharg_i(rs) (--_jitl.nextarg_put, MRrr(_jitl.nextarg_put, (rs))) +#define jit_ret() jit_jmpr(31) +#define jit_retval(rd) MRrr((rd), 3) +#define jit_rsbi_i(d, rs, is) jit_chk_ims((is), SUBFICrri((d), (rs), (is)), SUBFCrrr((d), (rs), JIT_AUX)) +#define jit_rshi_i(d, rs, is) SRAWIrri((d), (rs), (is)) +#define jit_rshi_ui(d, rs, is) SRWIrri ((d), (rs), (is)) +#define jit_rshr_i(d, s1, s2) (ANDIrrr(JIT_AUX, (s2), 31), SRAWrrr ((d), (s1), JIT_AUX)) +#define jit_rshr_ui(d, s1, s2) (ANDIrrr(JIT_AUX, (s2), 31), SRWrrr ((d), (s1), JIT_AUX)) +#define jit_stxi_c(id, rd, rs) jit_chk_ims((id), STBrm((rs), (id), (rd)), STBrx((rs), (rd), JIT_AUX)) +#define jit_stxi_i(id, rd, rs) jit_chk_ims((id), STWrm((rs), (id), (rd)), STWrx((rs), (rd), JIT_AUX)) +#define jit_stxi_s(id, rd, rs) jit_chk_ims((id), STHrm((rs), (id), (rd)), STHrx((rs), (rd), JIT_AUX)) +#define jit_stxr_c(d1, d2, rs) STBrx((rs), (d1), (d2)) +#define jit_stxr_i(d1, d2, rs) STWrx((rs), (d1), (d2)) +#define jit_stxr_s(d1, d2, rs) STHrx((rs), (d1), (d2)) +#define jit_subr_i(d, s1, s2) SUBrrr((d), (s1), (s2)) +#define jit_subcr_i(d, s1, s2) SUBCrrr((d), (s1), (s2)) +#define jit_subxi_i(d, rs, is) jit_chk_ims(111111111, 0, SUBErrr((d), (rs), JIT_AUX)) +#define jit_subxr_i(d, s1, s2) SUBErrr((d), (s1), (s2)) +#define jit_xori_i(d, rs, is) jit_chk_imu((is), XORIrri((d), (rs), (is)), XORrrr((d), (rs), JIT_AUX)) +#define jit_xorr_i(d, s1, s2) XORrrr((d), (s1), (s2)) + +/* Cannot use JIT_RZERO because having 0 in a register field on the PowerPC + * does not mean `a register whose value is 0', but rather `no register at + * all' */ + +#define jit_negr_i(d, rs) jit_rsbi_i((d), (rs), 0) +#define jit_negr_l(d, rs) jit_rsbi_l((d), (rs), 0) +#define jit_ldr_c(rd, rs) jit_ldxr_c((rd), 0, (rs)) +#define jit_str_c(rd, rs) jit_stxr_c(0, (rd), (rs)) +#define jit_ldr_s(rd, rs) jit_ldxr_s((rd), 0, (rs)) +#define jit_str_s(rd, rs) jit_stxr_s(0, (rd), (rs)) +#define jit_ldr_i(rd, rs) jit_ldxr_i((rd), 0, (rs)) +#define jit_str_i(rd, rs) jit_stxr_i(0, (rd), (rs)) +#define jit_ldr_uc(rd, rs) jit_ldxr_uc((rd), 0, (rs)) +#define jit_ldr_us(rd, rs) jit_ldxr_us((rd), 0, (rs)) + +/* e.g. + * 0x01234567 _HA << 16 = 0x01230000 _LA = 0x00004567 _HA << 16 + LA = 0x01234567 + * 0x89abcdef _HA << 16 = 0x89ac0000 _LA = 0xffffcdef _HA << 16 + LA = 0x89abcdef + */ +#define _HA(addr) ((_jit_UL(addr) >> 16) + (_jit_US(_jit_UL(addr)) >> 15)) +#define _LA(addr) (_jit_UL(addr) - (_HA(addr) << 16)) + +#define jit_ldi_c(rd, is) (LISri(JIT_AUX, _HA(is)), jit_ldxi_c((rd), JIT_AUX, _LA(is))) +#define jit_sti_c(id, rs) (LISri(JIT_AUX, _HA(id)), jit_stxi_c(_LA(id), JIT_AUX, (rs))) +#define jit_ldi_s(rd, is) (LISri(JIT_AUX, _HA(is)), jit_ldxi_s((rd), JIT_AUX, _LA(is))) +#define jit_sti_s(id, rs) (LISri(JIT_AUX, _HA(id)), jit_stxi_s(_LA(id), JIT_AUX, (rs))) +#define jit_ldi_i(rd, is) (LISri(JIT_AUX, _HA(is)), jit_ldxi_i((rd), JIT_AUX, _LA(is))) +#define jit_sti_i(id, rs) (LISri(JIT_AUX, _HA(id)), jit_stxi_i(_LA(id), JIT_AUX, (rs))) +#define jit_ldi_uc(rd, is) (LISri(JIT_AUX, _HA(is)), jit_ldxi_uc((rd), JIT_AUX, _LA(is))) +#define jit_ldi_us(rd, is) (LISri(JIT_AUX, _HA(is)), jit_ldxi_us((rd), JIT_AUX, _LA(is))) + +#endif /* __lightning_core_h */ diff --git a/lightning/ppc/fp.h b/lightning/ppc/fp.h new file mode 100644 index 000000000..176719539 --- /dev/null +++ b/lightning/ppc/fp.h @@ -0,0 +1,104 @@ +/******************************** -*- C -*- **************************** + * + * Run-time assembler & support macros for the Sparc math unit + * + ***********************************************************************/ + + +/*********************************************************************** + * + * 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 2.1, 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. + * + ***********************************************************************/ + + + + +#ifndef __lightning_asm_fp_h +#define __lightning_asm_fp_h + +#if 0 + +/* dummy for now */ + +#define jit_add_two(reg0) FADDrrr(13 - (reg0), 13 - (reg0), 12 - (reg0)) +#define jit_sub_two(reg0) FSUBrrr(13 - (reg0), 13 - (reg0), 12 - (reg0)) +#define jit_mul_two(reg0) FMULrrr(13 - (reg0), 13 - (reg0), 12 - (reg0)) +#define jit_div_two(reg0) FDIVrrr(13 - (reg0), 13 - (reg0), 12 - (reg0)) + +#define jit_abs(reg0) FABSr(13 - (reg0)) +#define jit_sqrt(reg0) FSQRTr(13 - (reg0)) +#define jit_neg(reg0) FNEGr(13 - (reg0)) + +#define jit_ldxi_f(reg0, rs, is) 0 +#define jit_ldxr_f(reg0, s1, s2) 0 +#define jit_ldxi_d(reg0, rs, is) 0 +#define jit_ldxr_d(reg0, s1, s2) 0 +#define jit_ldi_f(reg0, is) 0 +#define jit_ldr_f(reg0, rs) 0 +#define jit_ldi_d(reg0, is) 0 +#define jit_ldr_d(reg0, rs) 0 +#define jit_stxi_f(id, rd, reg0) 0 +#define jit_stxr_f(d1, d2, reg0) 0 +#define jit_stxi_d(id, rd, reg0) 0 +#define jit_stxr_d(d1, d2, reg0) 0 +#define jit_sti_f(id, reg0) 0 +#define jit_str_f(rd, reg0) 0 +#define jit_sti_d(id, reg0) 0 +#define jit_str_d(rd, reg0) 0 + +/* Make space for 1 or 2 words, store address in REG */ +#define jit_data(REG, D1) (_FBA (18, 8, 0, 1), _jit_L(D1), MFLRr(REG)) +#define jit_data2(REG, D1, D2) (_FBA (18, 12, 0, 1), _jit_L(D1), _jit_L(D2), MFLRr(REG)) + +#define jit_fpimm(reg0, first, second) \ + (jit_data2(JIT_AUX, (first), (second)), \ + jit_ldxi_d((reg0), JIT_AUX, 0)) + +#define jit_floor(rd, reg0) jit_call_fp((rd), (reg0), floor) +#define jit_ceil(rd, reg0) jit_call_fp((rd), (reg0), ceil) + +#define jit_call_fp(rd, reg0, fn) \ + jit_fail(#fn " not supported", __FILE__, __LINE__, __FUNCTION__) +/* pass reg0 as first parameter of rd + bl fn + mr r3, rd */ + +#define jit_trunc(rd, reg0) (jit_data((rd), 0), \ + FCTIWZrr(13 - (reg0), 13 - (reg0)), \ + STFIWXrrr(13 - (reg0), 0, (rd)), \ + LWZrm((rd), 0, (rd))) + +#define jit_round(rd, reg0) (jit_data((rd), 0), \ + FCTIWrr(13 - (reg0), 13 - (reg0)), \ + STFIWXrrr(13 - (reg0), 0, (rd)), \ + LWZrm((rd), 0, (rd))) + +#define jit_cmp(le, ge, reg0) (FCMPOirr(7, 13 - (reg0), 0), \ + CRORiii(28 + _gt, 28 + _gt, 28 + _eq), \ + CRORiii(28 + _lt, 28 + _lt, 28 + _eq), \ + MFCRr((ge)), \ + EXTRWIrrii((le), (ge), 1, 28 + _lt), \ + EXTRWIrrii((ge), (ge), 1, 28 + _gt)) + +#endif + +#endif /* __lightning_asm_h */ diff --git a/lightning/ppc/funcs.h b/lightning/ppc/funcs.h new file mode 100644 index 000000000..38b6a6552 --- /dev/null +++ b/lightning/ppc/funcs.h @@ -0,0 +1,161 @@ +/******************************** -*- C -*- **************************** + * + * Platform-independent layer inline functions (PowerPC) + * + ***********************************************************************/ + + +/*********************************************************************** + * + * 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 2.1, 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. + * + ***********************************************************************/ + + + +#ifndef __lightning_funcs_h +#define __lightning_funcs_h + +#if !defined(__GNUC__) && !defined(__GNUG__) +#error Go get GNU C, I do not know how to flush the cache +#error with this compiler. +#else +static void +jit_flush_code(void *start, void *end) +{ +#ifndef LIGHTNING_CROSS + register char *ddest, *idest; + + static int cache_line_size; + if (cache_line_size == 0) { + char buffer[8192]; + int i, probe; + + /* Find out the size of a cache line by zeroing one */ + memset(buffer, 0xFF, 8192); + __asm__ __volatile__ ("dcbz 0,%0" : : "r"(buffer + 4096)); + + /* Probe for the beginning of the cache line. */ + for(i = 0, probe = 4096; probe; probe >>= 1) + if (buffer[i | probe] != 0x00) + i |= probe; + + /* i is now just before the start of the cache line */ + i++; + for(cache_line_size = 1; i + cache_line_size < 8192; cache_line_size <<= 1) + if (buffer[i + cache_line_size] != 0x00) + break; + } + + start -= ((long) start) & (cache_line_size - 1); + end -= ((long) end) & (cache_line_size - 1); + + /* Force data cache write-backs */ + for (ddest = start; ddest <= (char *) end; ddest += cache_line_size) { + __asm__ __volatile__ ("dcbst 0,%0" : : "r"(ddest)); + } + __asm__ __volatile__ ("sync" : : ); + + /* Now invalidate the instruction cache */ + for (idest = start; idest <= (char *) end; idest += cache_line_size) { + __asm__ __volatile__ ("icbi 0,%0" : : "r"(idest)); + } + __asm__ __volatile__ ("isync" : : ); +#endif /* !LIGHTNING_CROSS */ +} +#endif /* __GNUC__ || __GNUG__ */ + +#define _jit (*jit) + +/* Emit a trampoline for a function. + * Upon entrance to the trampoline: + * - R0 = return address for the function + * - LR = address where the real code for the function lies + * - R3-R8 = parameters + * After jumping to the address pointed to by R10: + * - LR = address where the epilog lies (the function must return there) + * - R25-R20 = parameters (order is reversed, 1st argument is R25) + */ +static jit_insn * +_jit_trampoline(jit, n) + register jit_state *jit; + register int n; +{ + static jit_insn trampolines[200]; + static jit_insn *p_trampolines[6], *free = trampolines; + jit_insn *trampo; + int i, ofs, frame_size; + + if (!p_trampolines[n]) { + _jit.x.pc = trampo = p_trampolines[n] = free; + + frame_size = 24 + (6 + n) * 4; /* r26..r31 + args */ + frame_size += 15; /* the stack must be quad-word */ + frame_size &= ~15; /* aligned */ + + STWUrm(1, -frame_size, 1); /* stwu r1, -x(r1) */ + + for (ofs = frame_size - (6 + n) * 4, i = 26 - n; i <= 31; ofs += 4, i++) { + STWrm(i, ofs, 1); /* stw rI, ofs(r1) */ + } + STWrm(0, ofs+4, 1); /* stw r0, x(r1) */ + for (i = 0; i < n; i++) { + MRrr(25-i, 3+i); /* save parameters in r25..r20 */ + } + BLRL(); /* blrl */ + LWZrm(0, ofs+4, 1); /* lwz r0, x(r1) (ret.addr.) */ + MTLRr(0); /* mtspr LR, r0 */ + + for (ofs = frame_size - (6 + n) * 4, i = 26 - n; i <= 31; ofs += 4, i++) { + LWZrm(i, ofs, 1); /* lwz rI, ofs(r1) */ + } + ADDIrri(1, 1, frame_size); /* addi r1, r1, x */ + BLR(); /* blr */ + + jit_flush_code(trampo, _jit.x.pc); + free = _jit.x.pc; + } + + return p_trampolines[n]; +} + +static void +_jit_prolog(jit, n) + register jit_state *jit; + register int n; +{ + register jit_insn *save_pc, *trampo; + + save_pc = _jit.x.pc; + trampo = _jit_trampoline(jit, n); + _jit.x.pc = save_pc; + + _jitl.nextarg_get = 25; + MFLRr(0); + MOVEIri(10, trampo); + MTLRr(10); + BLRL(); /* blrl */ + MFLRr(31); /* mflr r31 */ +} + +#undef _jit + +#endif /* __lightning_funcs_h */ diff --git a/lightning/sparc/asm.h b/lightning/sparc/asm.h new file mode 100644 index 000000000..808bb4ad3 --- /dev/null +++ b/lightning/sparc/asm.h @@ -0,0 +1,303 @@ +/******************************** -*- C -*- **************************** + * + * Run-time assembler for the SPARC + * + ***********************************************************************/ + + +/*********************************************************************** + * + * Copyright 1999, 2000, 2001, 2002 Ian Piumarta + * + * 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 2.1, 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. + * + ***********************************************************************/ + + + + + +#ifndef __lightning_asm_h +#define __lightning_asm_h + + +/* = [0-9]+ -> add i, one parameter (imm) + * = % -> add r, one parameter (imm or _Rr(imm) ) + * %g -> add r, one parameter (imm or _Rg(imm) ) + * %o -> add r, one parameter (imm+8 or _Ro(imm) ) + * %l -> add r, one parameter (imm+16 or _Rl(imm) ) + * %i -> add r, one parameter (imm+24 or _Ri(imm) ) + * = () -> add m, two parameters (reg,imm) + * = () -> add x, two parameters (reg,reg) + */ + + +typedef unsigned int jit_insn; + +#define _d30(BD) ((_jit_UL(BD) - _jit_UL(_jit.x.pc))>>2) +#define _d22(BD) _ck_d(22, _d30(BD)) + +#define _HI(I) (_jit_UL(I) >> (10)) +#define _LO(I) (_jit_UL(I) & _MASK(10)) + +/* register names */ + +#define _y 0 +#define _psr 1 + +#define _Rr(N) ( 0+(N)) +#define _Rg(N) ( 0+(N)) +#define _Ro(N) ( 8+(N)) +#define _Rl(N) (16+(N)) +#define _Ri(N) (24+(N)) + +/* instruction formats -- Figure 5-1, page 44 in */ +/* SPARC International, "The SPARC Architecture Manual, Version 8", Prentice-Hall, 1992. */ + +#define _0i(RD, OP2, IMM) _jit_I((0<<30)| (_u5(RD)<<25)|(_u3(OP2)<<22)| _u22(IMM)) +#define _0( A, CC, OP2, DSP) _jit_I((0<<30)|(_u1(A)<<29)|(_u4(CC)<<25)|(_u3(OP2)<<22)| _d22(DSP)) +#define _0d( A, CC, OP2, DSP) _jit_I((0<<30)|(_u1(A)<<29)|(_u4(CC)<<25)|(_u3(OP2)<<22)| _u22(DSP)) + +#define _1( DSP) _jit_I((1<<30)| _d30(DSP)) + +#define _2( RD, OP3, RS1, I, ASI, RS2) _jit_I((2<<30)| (_u5(RD)<<25)|(_u6(OP3)<<19)|(_u5(RS1)<<14)|(_u1(I)<<13)|(_u8(ASI)<<5)|_u5 (RS2)) +#define _2i(RD, OP3, RS1, I, IMM) _jit_I((2<<30)| (_u5(RD)<<25)|(_u6(OP3)<<19)|(_u5(RS1)<<14)|(_u1(I)<<13)| _s13(IMM)) +#define _2f(RD, OP3, RS1, OPF, RS2) _jit_I((2<<30)| (_u5(RD)<<25)|(_u6(OP3)<<19)|(_u5(RS1)<<14)| (_u9(OPF)<<5)|_u5 (RS2)) + +#define _3( RD, OP3, RS1, I, ASI, RS2) _jit_I((3<<30)| (_u5(RD)<<25)|(_u6(OP3)<<19)|(_u5(RS1)<<14)|(_u1(I)<<13)|(_u8(ASI)<<5)|_u5 (RS2)) +#define _3i(RD, OP3, RS1, I, IMM) _jit_I((3<<30)| (_u5(RD)<<25)|(_u6(OP3)<<19)|(_u5(RS1)<<14)|(_u1(I)<<13)| _s13(IMM)) + +/* basic instructions [Section B, page 87] */ + +#define ADDrrr(RS1, RS2, RD) _2 ((RD), 0, (RS1), 0, 0, (RS2)) +#define ADDrir(RS1, IMM, RD) _2i ((RD), 0, (RS1), 1, (IMM)) +#define ADDCCrrr(RS1, RS2, RD) _2 ((RD), 16, (RS1), 0, 0, (RS2)) +#define ADDCCrir(RS1, IMM, RD) _2i ((RD), 16, (RS1), 1, (IMM)) +#define ADDXrrr(RS1, RS2, RD) _2 ((RD), 8, (RS1), 0, 0, (RS2)) +#define ADDXrir(RS1, IMM, RD) _2i ((RD), 8, (RS1), 1, (IMM)) +#define ADDXCCrrr(RS1, RS2, RD) _2 ((RD), 24, (RS1), 0, 0, (RS2)) +#define ADDXCCrir(RS1, IMM, RD) _2i ((RD), 24, (RS1), 1, (IMM)) +#define ANDrrr(RS1, RS2, RD) _2 ((RD), 1, (RS1), 0, 0, (RS2)) +#define ANDrir(RS1, IMM, RD) _2i ((RD), 1, (RS1), 1, (IMM)) +#define ANDCCrrr(RS1, RS2, RD) _2 ((RD), 17, (RS1), 0, 0, (RS2)) +#define ANDCCrir(RS1, IMM, RD) _2i ((RD), 17, (RS1), 1, (IMM)) + +#define BNi(DISP) _0 (0, 0, 2, (DISP)) +#define BN_Ai(DISP) _0 (1, 0, 2, (DISP)) +#define BEi(DISP) _0 (0, 1, 2, (DISP)) +#define BE_Ai(DISP) _0 (1, 1, 2, (DISP)) +#define BLEi(DISP) _0 (0, 2, 2, (DISP)) +#define BLE_Ai(DISP) _0 (1, 2, 2, (DISP)) +#define BLi(DISP) _0 (0, 3, 2, (DISP)) +#define BL_Ai(DISP) _0 (1, 3, 2, (DISP)) +#define BLEUi(DISP) _0 (0, 4, 2, (DISP)) +#define BLEU_Ai(DISP) _0 (1, 4, 2, (DISP)) +#define BCSi(DISP) _0 (0, 5, 2, (DISP)) +#define BCS_Ai(DISP) _0 (1, 5, 2, (DISP)) +#define BNEGi(DISP) _0 (0, 6, 2, (DISP)) +#define BNEG_Ai(DISP) _0 (1, 6, 2, (DISP)) +#define BVSi(DISP) _0 (0, 7, 2, (DISP)) +#define BVS_Ai(DISP) _0 (1, 7, 2, (DISP)) +#define BAi(DISP) _0 (0, 8, 2, (DISP)) +#define BA_Ai(DISP) _0 (1, 8, 2, (DISP)) +#define BNEi(DISP) _0 (0, 9, 2, (DISP)) +#define BNE_Ai(DISP) _0 (1, 9, 2, (DISP)) +#define BGi(DISP) _0 (0, 10, 2, (DISP)) +#define BG_Ai(DISP) _0 (1, 10, 2, (DISP)) +#define BGEi(DISP) _0 (0, 11, 2, (DISP)) +#define BGE_Ai(DISP) _0 (1, 11, 2, (DISP)) +#define BGUi(DISP) _0 (0, 12, 2, (DISP)) +#define BGU_Ai(DISP) _0 (1, 12, 2, (DISP)) +#define BCCi(DISP) _0 (0, 13, 2, (DISP)) +#define BCC_Ai(DISP) _0 (1, 13, 2, (DISP)) +#define BPOSi(DISP) _0 (0, 14, 2, (DISP)) +#define BPOS_Ai(DISP) _0 (1, 14, 2, (DISP)) +#define BVCi(DISP) _0 (0, 15, 2, (DISP)) +#define BVC_Ai(DISP) _0 (1, 15, 2, (DISP)) + +#define CALLi(DISP) _1 ((DISP)) + +#define FLUSHrr(RS1, RS2) _2 (0, 0x3b, (RS1), 0, 0, (RS2)) +#define FLUSHir(IMM, RS1) _2i (0, 0x3b, (RS1), 1, (IMM)) + +#define JMPLxr(RS1, RS2, RD) _2 ((RD), 56, (RS1), 0, 0, (RS2)) +#define JMPLmr(RS1, IMM, RD) _2i ((RD), 56, (RS1), 1, (IMM)) + +#define LDxr(RS1, RS2, RD) _3 ((RD), 0, (RS1), 0, 0, (RS2)) +#define LDmr(RS1, IMM, RD) _3i ((RD), 0, (RS1), 1, (IMM)) +#define LDUBxr(RS1, RS2, RD) _3 ((RD), 1, (RS1), 0, 0, (RS2)) +#define LDUBmr(RS1, IMM, RD) _3i ((RD), 1, (RS1), 1, (IMM)) +#define LDUHxr(RS1, RS2, RD) _3 ((RD), 2, (RS1), 0, 0, (RS2)) +#define LDUHmr(RS1, IMM, RD) _3i ((RD), 2, (RS1), 1, (IMM)) +#define LDDxr(RS1, RS2, RD) _3 ((RD), 3, (RS1), 0, 0, (RS2)) +#define LDDmr(RS1, IMM, RD) _3i ((RD), 3, (RS1), 1, (IMM)) +#define LDSBxr(RS1, RS2, RD) _3 ((RD), 9, (RS1), 0, 0, (RS2)) +#define LDSBmr(RS1, IMM, RD) _3i ((RD), 9, (RS1), 1, (IMM)) +#define LDSHxr(RS1, RS2, RD) _3 ((RD), 10, (RS1), 0, 0, (RS2)) +#define LDSHmr(RS1, IMM, RD) _3i ((RD), 10, (RS1), 1, (IMM)) + +#define ORrrr(RS1, RS2, RD) _2 ((RD), 2, (RS1), 0, 0, (RS2)) +#define ORrir(RS1, IMM, RD) _2i ((RD), 2, (RS1), 1, (IMM)) +#define ORCCrrr(RS1, RS2, RD) _2 ((RD), 18, (RS1), 0, 0, (RS2)) +#define ORCCrir(RS1, IMM, RD) _2i ((RD), 18, (RS1), 1, (IMM)) + +#define RDir(RS, RD) _2 ((RD), (RS)|0x28, 0, 0, 0,0) +#define RESTORErrr(RS1, RS2, RD) _2 ((RD), 61, (RS1), 0, 0, (RS2)) +#define RESTORErir(RS1, IMM, RD) _2i ((RD), 61, (RS1), 1, (IMM)) + +#define SAVErrr(RS1, RS2, RD) _2 ((RD), 60, (RS1), 0, 0, (RS2)) +#define SAVErir(RS1, IMM, RD) _2i ((RD), 60, (RS1), 1, (IMM)) +#define SDIVrrr(RS1, RS2, RD) _2 ((RD), 15, (RS1), 0, 0, (RS2)) +#define SDIVrir(RS1, IMM, RD) _2i ((RD), 15, (RS1), 1, (IMM)) +#define SDIVCCrrr(RS1, RS2, RD) _2 ((RD), 31, (RS1), 0, 0, (RS2)) +#define SDIVCCrir(RS1, IMM, RD) _2i ((RD), 31, (RS1), 1, (IMM)) +#define SETHIir(IMM, RD) _0i ((RD), 4, (IMM)) +#define SLLrrr(RS1, RS2, RD) _2 ((RD), 37, (RS1), 0, 0, (RS2)) +#define SLLrir(RS1, IMM, RD) _2i ((RD), 37, (RS1), 1, (IMM)) +#define SMULrrr(RS1, RS2, RD) _2 ((RD), 11, (RS1), 0, 0, (RS2)) +#define SMULrir(RS1, IMM, RD) _2i ((RD), 11, (RS1), 1, (IMM)) +#define SMULCCrrr(RS1, RS2, RD) _2 ((RD), 27, (RS1), 0, 0, (RS2)) +#define SMULCCrir(RS1, IMM, RD) _2i ((RD), 27, (RS1), 1, (IMM)) +#define SRArrr(RS1, RS2, RD) _2 ((RD), 39, (RS1), 0, 0, (RS2)) +#define SRArir(RS1, IMM, RD) _2i ((RD), 39, (RS1), 1, (IMM)) +#define SRLrrr(RS1, RS2, RD) _2 ((RD), 38, (RS1), 0, 0, (RS2)) +#define SRLrir(RS1, IMM, RD) _2i ((RD), 38, (RS1), 1, (IMM)) +#define STrx(RS, RD1, RD2) _3 ((RS), 4, (RD1), 0, 0, (RD2)) +#define STrm(RS, RD, IMM) _3i ((RS), 4, (RD), 1, (IMM)) +#define STBrx(RS, RD1, RD2) _3 ((RS), 5, (RD1), 0, 0, (RD2)) +#define STBrm(RS, RD, IMM) _3i ((RS), 5, (RD), 1, (IMM)) +#define STBAR() _0i (0, 0x28, 15, 0, 0) +#define STHrx(RS, RD1, RD2) _3 ((RS), 6, (RD1), 0, 0, (RD2)) +#define STHrm(RS, RD, IMM) _3i ((RS), 6, (RD), 1, (IMM)) +#define STDrx(RS, RD1, RD2) _3 ((RS), 7, (RD1), 0, 0, (RD2)) +#define STDrm(RS, RD, IMM) _3i ((RS), 7, (RD), 1, (IMM)) +#define SUBrrr(RS1, RS2, RD) _2 ((RD), 4, (RS1), 0, 0, (RS2)) +#define SUBrir(RS1, IMM, RD) _2i ((RD), 4, (RS1), 1, (IMM)) +#define SUBCCrrr(RS1, RS2, RD) _2 ((RD), 20, (RS1), 0, 0, (RS2)) +#define SUBCCrir(RS1, IMM, RD) _2i ((RD), 20, (RS1), 1, (IMM)) +#define SUBXrrr(RS1, RS2, RD) _2 ((RD), 12, (RS1), 0, 0, (RS2)) +#define SUBXrir(RS1, IMM, RD) _2i ((RD), 12, (RS1), 1, (IMM)) +#define SUBXCCrrr(RS1, RS2, RD) _2 ((RD), 28, (RS1), 0, 0, (RS2)) +#define SUBXCCrir(RS1, IMM, RD) _2i ((RD), 28, (RS1), 1, (IMM)) + +#define UDIVrrr(RS1, RS2, RD) _2 ((RD), 14, (RS1), 0, 0, (RS2)) +#define UDIVrir(RS1, IMM, RD) _2i ((RD), 14, (RS1), 1, (IMM)) +#define UDIVCCrrr(RS1, RS2, RD) _2 ((RD), 30, (RS1), 0, 0, (RS2)) +#define UDIVCCrir(RS1, IMM, RD) _2i ((RD), 30, (RS1), 1, (IMM)) +#define UMULrrr(RS1, RS2, RD) _2 ((RD), 10, (RS1), 0, 0, (RS2)) +#define UMULrir(RS1, IMM, RD) _2i ((RD), 10, (RS1), 1, (IMM)) +#define UMULCCrrr(RS1, RS2, RD) _2 ((RD), 26, (RS1), 0, 0, (RS2)) +#define UMULCCrir(RS1, IMM, RD) _2i ((RD), 26, (RS1), 1, (IMM)) + +#define WRrri(RS1, RS2, RD) _2 (0, (RD)|0x30, RS1, 0, 0, (RS2)) +#define WRrii(RS1, IMM, RD) _2i (0, (RD)|0x30, RS1, 1, (IMM)) + +#define XORrrr(RS1, RS2, RD) _2 ((RD), 3, (RS1), 0, 0, (RS2)) +#define XORrir(RS1, IMM, RD) _2i ((RD), 3, (RS1), 1, (IMM)) +#define XORCCrrr(RS1, RS2, RD) _2 ((RD), 19, (RS1), 0, 0, (RS2)) +#define XORCCrir(RS1, IMM, RD) _2i ((RD), 19, (RS1), 1, (IMM)) + +/* synonyms */ + +#define Bi(DISP) BAi((DISP)) +#define B_Ai(DISP) BA_Ai((DISP)) +#define BNZi(DISP) BNEi((DISP)) +#define BNZ_Ai(DISP) BNE_Ai((DISP)) +#define BZi(DISP) BEi((DISP)) +#define BZ_Ai(DISP) BE_Ai((DISP)) +#define BGEUi(DISP) BCCi((DISP)) +#define BGEU_Ai(DISP) BCC_Ai((DISP)) +#define BLUi(DISP) BCSi((DISP)) +#define BLU_Ai(DISP) BCS_Ai((DISP)) + +#define LDUWxr(RS1, RS2, RD) LDxr((RS1), (RS2), (RD)) +#define LDUWmr(RS1, IMM, RD) LDmr((RS1), (IMM), (RD)) +#define LDSWxr(RS1, RS2, RD) LDxr((RS1), (RS2), (RD)) +#define LDSWmr(RS1, IMM, RD) LDmr((RS1), (IMM), (RD)) + +#define STWrx(RS, RD1, RD2) STrx((RS), (RD1), (RD2)) +#define STWrm(RS, RD, IMM) STrm((RS), (RD), (IMM)) + +/* synthetic instructions [Table A-1, page 85] */ + +#define BCLRrr(R,S) ANDNrrr((R), (S), (S)) +#define BCLRir(I,R) ANDNrir((R), (I), (R)) +#define BSETrr(R,S) ORrrr((R), (S), (S)) +#define BSETir(I,R) ORrir((R), (I), (R)) +#define BTOGrr(R,S) XORrrr((R), (S), (S)) +#define BTOGir(I,R) XORrir((R), (I), (R)) +#define BTSTrr(R,S) ANDCCrrr((R), (S), 0) +#define BTSTir(I,R) ANDCCrir((R), (I), 0) + +#define CALLm(R,I) JMPLmr((R), (I), _Ro(7)) +#define CALLx(R,S) JMPLxr((R), (S), _Ro(7)) + +#define CLRr(R) ORrrr(0, 0, (R)) +#define CLRBm(R,I) STBrm(0, (R), (I)) +#define CLRBx(R,S) STBrm(0, (R), (S)) +#define CLRHm(R,I) STHrm(0, (R), (I)) +#define CLRHx(R,S) STHrm(0, (R), (S)) +#define CLRm(R,I) STrm(0, (R), (I)) +#define CLRx(R,S) STrm(0, (R), (S)) + +#define CMPrr(RS1, RS2) SUBCCrrr((RS1), (RS2), 0) +#define CMPri(RS1, IMM) SUBCCrir((RS1), (IMM), 0) + +#define DECr(R) SUBrir((R), 1, (R)) +#define DECir(I,R) SUBrir((R), (I), (R)) +#define DECCCr(R) SUBCCrir((R), 1, (R)) +#define DECCCir(I,R) SUBCCrir((R), (I), (R)) + +#define INCr(R) ADDrir((R), 1, (R)) +#define INCir(I,R) ADDrir((R), (I), (R)) +#define INCCCr(R) ADDCCrir((R), 1, (R)) +#define INCCCir(I,R) ADDCCrir((R), (I), (R)) + +#define JMPm(R,I) JMPLmr((R), (I), 0) +#define JMPx(R,S) JMPLxr((R), (S), 0) + +#define MOVrr(R,S) ORrrr(0, (R), (S)) +#define MOVir(I, R) ORrir(0, (I), (R)) + +#define NEGrr(R,S) SUBrrr(0, (R), (S)) +#define NEGr(R) SUBrrr(0, (R), (R)) +#define NOP() SETHIir(0, 0) + +#define NOTrr(R,S) XNORrrr((R), 0, (S)) +#define NOTr(R) XNORrrr((R), 0, (R)) + +#define RESTORE() RESTORErrr(0, 0, 0) +#define RET() JMPLmr(_Ri(7),8 ,0) +#define RETL() JMPLmr(_Ro(7),8 ,0) + +#define SAVE() SAVErrr(0, 0, 0) +#define SETir(I,R) (_siP(13,(I)) ? MOVir((I),(R)) : SETir2(_HI(I), _LO(I), (R))) +#define SETir2(H,L,R) (SETHIir(H,R), (L ? ORrir(R,L,R) : 0)) + +/* BNZ,a executes the delay instruction if NZ (so skips if Z) + * BZ,a executes the delay instruction if Z (so skips if NZ). */ +#define SKIPZ() _0d (1, 9, 2, 2) /* BNZ,a .+8 */ +#define SKIPNZ() _0d (1, 1, 2, 2) /* BZ,a .+8 */ +#define SKIP() _0d (1, 0, 2, 0) /* BN,a . */ + +#define TSTr(R) ORCCrrr(0, (R), 0) + +#define WRii(IMM, RD) WRrii(0, (IMM), (RD)) +#define WRri(RS2, RD) WRrri(0, (RS2), (RD)) + +#endif /* __ccg_asm_sparc_h */ diff --git a/lightning/sparc/core.h b/lightning/sparc/core.h new file mode 100644 index 000000000..b70259e9b --- /dev/null +++ b/lightning/sparc/core.h @@ -0,0 +1,249 @@ +/******************************** -*- C -*- **************************** + * + * Platform-independent layer (Sparc version) + * + ***********************************************************************/ + + +/*********************************************************************** + * + * 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 2.1, 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. + * + ***********************************************************************/ + + +#ifndef __lightning_core_h +#define __lightning_core_h + +#define JIT_R0 _Rl(0) +#define JIT_R1 _Rl(1) +#define JIT_R2 _Rl(2) +#define JIT_V0 _Rl(3) +#define JIT_V1 _Rl(4) +#define JIT_V2 _Rl(5) +#define JIT_BIG _Rg(1) /* %g1 used to make 32-bit operands */ +#define JIT_BIG2 _Rg(2) /* %g2 used to make 32-bit compare operands */ +#define JIT_SP _Ro(6) +#define JIT_RZERO _Rg(0) +#define JIT_RET _Ri(0) + +/* Delay slot scheduling: jmp generates branches with annulled delay + * slots; we toggle the annul bit if we can fill the slot. CALLs and + * cond. branches have a different meaning for the annul bit, so we + * automatically generate a NOP and eventually copy the delay insn onto + * it. Delay slots in RET are already used for RESTORE, so we don't + * schedule them. + * + * ,--- _jit.x.pc + * insn X X before + * cmp branch insn X X after (branch) + * `--- _jit.x.pc + * call insn insn X after (call) + * `--- _jit.x.pc + */ + +struct jit_local_state { + int nextarg_put; /* Next %o reg. to be written */ + int nextarg_get; /* Next %i reg. to be read */ + jit_insn delay; +}; + +#define jit_fill_delay_after(branch) (_jitl.delay = *--_jit.x.pc, \ + ((branch) == _jit.x.pc /* check if NOP was inserted */ \ + ? (_jit.x.pc[-1] ^= 1<<29) /* no if branch, toggle annul bit */ \ + : (_jit.x.pc[-1] = _jitl.delay)), /* yes if call, replace NOP with delay insn */ \ + *_jit.x.pc = _jitl.delay, _jit.x.pc - 1) /* return addr of delay insn */ + +/* If possible, use the `small' instruction (rs, imm, rd) + * else load imm into %l6 and use the `big' instruction (rs, %l6, rd) + * jit_chk_imm2 uses %l7 instead of %l6 to avoid conflicts when using delay slots + */ +#define jit_chk_imm(imm, small, big) (_siP(13,(imm)) ? (small) : (SETir((imm), JIT_BIG), (big)) ) +#define jit_chk_imm2(imm, small, big) (_siP(13,(imm)) ? (small) : (SETir((imm), JIT_BIG2), (big)) ) + +/* Helper macros for branches */ +#define jit_branchi(rs, is, jmp, nop) (jit_chk_imm2(is, CMPri(rs, is), CMPrr(rs, JIT_BIG2)), jmp, nop, _jit.x.pc - 1) +#define jit_branchr(s1, s2, jmp, nop) ( CMPrr(s1, s2), jmp, nop, _jit.x.pc - 1) + +/* Helper macros for boolean tests -- delay slot sets d to 1; + * taken branch leaves it to 1, not-taken branch resets it to 0 */ +#define jit_booli(d, rs, is, jmp) (jit_chk_imm (is, CMPri(rs, is), CMPrr(rs, JIT_BIG)), jmp, MOVir(1, (d)), MOVir(0, (d))) +#define jit_boolr(d, s1, s2, jmp) ( CMPrr(s1, s2), jmp, MOVir(1, (d)), MOVir(0, (d))) + +/* Helper macros for division + * The architecture specifies that there must be 3 instructions between * + * a y register write and a use of it for correct results. */ +#define jit_prepare_y(rs, is) (SRArir(rs, 31, JIT_BIG), WRri(JIT_BIG, _y), NOP(), NOP(), NOP(), _jit.x.pc -= jit_immsize(is)) +#define jit_clr_y(rs, is) ( WRri(0, _y), NOP(), NOP(), NOP(), _jit.x.pc -= jit_immsize(is)) + +#define jit_mod(div, mul, d, s1, s2) ( \ + div (JIT_BIG2, s1, s2), \ + mul (JIT_BIG2, JIT_BIG2, s2), \ + jit_subr_i (d, s1, JIT_BIG2)) + +/* How many instruction are needed to put imm in a register. */ +#define jit_immsize(imm) (!(imm) ? 0 : \ + (!_siP((imm), 13) && ((imm) & 0x3ff) ? 2 : 1)) + + +/* branch instructions return the address of the *delay* instruction -- this + * is just a helper macro that makes jit_patch more readable. + */ +#define jit_patch_(jump_pc) \ + (*jump_pc &= ~_MASK(22), \ + *jump_pc |= ((_jit_UL(_jit.x.pc) - _jit_UL(jump_pc)) >> 2) & _MASK(22)) + + +#define jit_arg_c() (_jitl.nextarg_get++) +#define jit_arg_i() (_jitl.nextarg_get++) +#define jit_arg_l() (_jitl.nextarg_get++) +#define jit_arg_p() (_jitl.nextarg_get++) +#define jit_arg_s() (_jitl.nextarg_get++) +#define jit_arg_uc() (_jitl.nextarg_get++) +#define jit_arg_ui() (_jitl.nextarg_get++) +#define jit_arg_ul() (_jitl.nextarg_get++) +#define jit_arg_us() (_jitl.nextarg_get++) +#define jit_addi_i(d, rs, is) jit_chk_imm((is), ADDrir((rs), (is), (d)), ADDrrr((rs), JIT_BIG, (d))) +#define jit_addr_i(d, s1, s2) ADDrrr((s1), (s2), (d)) +#define jit_addci_i(d, rs, is) jit_chk_imm((is), ADDCCrir((rs), (is), (d)), ADDCCrrr((rs), JIT_BIG, (d))) +#define jit_addcr_i(d, s1, s2) ADDCCrrr((s1), (s2), (d)) +#define jit_addxi_i(d, rs, is) jit_chk_imm((is), ADDXCCrir((rs), (is), (d)), ADDXCCrrr((rs), JIT_BIG, (d))) +#define jit_addxr_i(d, s1, s2) ADDXCCrrr((s1), (s2), (d)) +#define jit_andi_i(d, rs, is) jit_chk_imm((is), ANDrir((rs), (is), (d)), ANDrrr((rs), JIT_BIG, (d))) +#define jit_andr_i(d, s1, s2) ANDrrr((s1), (s2), (d)) +#define jit_beqi_i(label, rs, is) jit_branchi((rs), (is), BEi((label)), NOP() ) +#define jit_beqr_i(label, s1, s2) jit_branchr((s1), (s2), BEi((label)), NOP() ) +#define jit_bgei_i(label, rs, is) jit_branchi((rs), (is), BGEi((label)), NOP() ) +#define jit_bgei_ui(label, rs, is) jit_branchi((rs), (is), BGEUi((label)), NOP() ) +#define jit_bger_i(label, s1, s2) jit_branchr((s1), (s2), BGEi((label)), NOP() ) +#define jit_bger_ui(label, s1, s2) jit_branchr((s1), (s2), BGEUi((label)), NOP() ) +#define jit_bgti_i(label, rs, is) jit_branchi((rs), (is), BGi((label)), NOP() ) +#define jit_bgti_ui(label, rs, is) jit_branchi((rs), (is), BGUi((label)), NOP() ) +#define jit_bgtr_i(label, s1, s2) jit_branchr((s1), (s2), BGi((label)), NOP() ) +#define jit_bgtr_ui(label, s1, s2) jit_branchr((s1), (s2), BGUi((label)), NOP() ) +#define jit_blei_i(label, rs, is) jit_branchi((rs), (is), BLEi((label)), NOP() ) +#define jit_blei_ui(label, rs, is) jit_branchi((rs), (is), BLEUi((label)), NOP() ) +#define jit_bler_i(label, s1, s2) jit_branchr((s1), (s2), BLEi((label)), NOP() ) +#define jit_bler_ui(label, s1, s2) jit_branchr((s1), (s2), BLEUi((label)), NOP() ) +#define jit_blti_i(label, rs, is) jit_branchi((rs), (is), BLi((label)), NOP() ) +#define jit_blti_ui(label, rs, is) jit_branchi((rs), (is), BLUi((label)), NOP() ) +#define jit_bltr_i(label, s1, s2) jit_branchr((s1), (s2), BLi((label)), NOP() ) +#define jit_bltr_ui(label, s1, s2) jit_branchr((s1), (s2), BLUi((label)), NOP() ) +#define jit_bnei_i(label, rs, is) jit_branchi((rs), (is), BNEi((label)), NOP() ) +#define jit_bner_i(label, s1, s2) jit_branchr((s1), (s2), BNEi((label)), NOP() ) +#define jit_bmsi_i(label, rs, is) (jit_chk_imm((is), BTSTir((is), (rs)), BTSTrr((rs), JIT_BIG)), BNEi((label)), NOP(), _jit.x.pc - 1) +#define jit_bmci_i(label, rs, is) (jit_chk_imm((is), BTSTir((is), (rs)), BTSTrr((rs), JIT_BIG)), BEi((label)), NOP(), _jit.x.pc - 1) +#define jit_bmsr_i(label, s1, s2) ( BTSTrr((s1), (s2)), BNEi((label)), NOP(), _jit.x.pc - 1) +#define jit_bmcr_i(label, s1, s2) ( BTSTrr((s1), (s2)), BEi((label)), NOP(), _jit.x.pc - 1) +#define jit_boaddi_i(label, rs, is) (jit_chk_imm((is), ADDCCrir((rs), (is), (rs)), ADDCCrrr((rs), JIT_BIG, (rs))), BVSi((label)), NOP(), _jit.x.pc - 1) +#define jit_bosubi_i(label, rs, is) (jit_chk_imm((is), SUBCCrir((rs), (is), (rs)), SUBCCrrr((rs), JIT_BIG, (rs))), BVSi((label)), NOP(), _jit.x.pc - 1) +#define jit_boaddr_i(label, s1, s2) ( ADDCCrrr((s1), (s2), (s1)), BVSi((label)), NOP(), _jit.x.pc - 1) +#define jit_bosubr_i(label, s1, s2) ( SUBCCrrr((s1), (s2), (s1)), BVSi((label)), NOP(), _jit.x.pc - 1) +#define jit_boaddi_ui(label, rs, is) (jit_chk_imm((is), ADDCCrir((rs), (is), (rs)), ADDCCrrr((rs), JIT_BIG, (rs))), BCSi((label)), NOP(), _jit.x.pc - 1) +#define jit_bosubi_ui(label, rs, is) (jit_chk_imm((is), SUBCCrir((rs), (is), (rs)), SUBCCrrr((rs), JIT_BIG, (rs))), BCSi((label)), NOP(), _jit.x.pc - 1) +#define jit_boaddr_ui(label, s1, s2) ( ADDCCrrr((s1), (s2), (s1)), BCSi((label)), NOP(), _jit.x.pc - 1) +#define jit_bosubr_ui(label, s1, s2) ( SUBCCrrr((s1), (s2), (s1)), BCSi((label)), NOP(), _jit.x.pc - 1) +#define jit_calli(label) (CALLi(label), NOP(), _jit.x.pc - 1) +#define jit_divi_i(d, rs, is) (jit_prepare_y((rs), 0x12345678), SETir((is), JIT_BIG), SDIVrrr((rs), JIT_BIG, (d)) ) +#define jit_divi_ui(d, rs, is) (jit_clr_y((rs)), 0x12345678), SETir((is), JIT_BIG), UDIVrrr((rs), JIT_BIG, (d)) ) +#define jit_divr_i(d, s1, s2) (jit_prepare_y((s1), 0), SDIVrrr((s1), (s2), (d))) +#define jit_divr_ui(d, s1, s2) (jit_clr_y((s1), 0), UDIVrrr((s1), (s2), (d))) +#define jit_eqi_i(d, rs, is) jit_chk_imm((is), \ + (SUBCCrir((rs), (is), (d)), ADDXCCrir((d), -1, JIT_BIG), SUBXrir(0,-1,(d))),\ + jit_eqr_i(d, rs, JIT_BIG)) +#define jit_eqr_i(d, s1, s2) (SUBCCrrr((s1), (s2), (d)), ADDXCCrir((d), -1, JIT_BIG), SUBXrir(0,-1,(d))) +#define jit_nei_i(d, rs, is) jit_chk_imm((is), \ + (SUBCCrir((rs), (is), (d)), ADDXCCrir((d), -1, JIT_BIG), ADDXrrr(0,0,(d))),\ + jit_ner_i(d, rs, JIT_BIG)) +#define jit_ner_i(d, s1, s2) (SUBCCrrr((s1), (s2), (d)), ADDXCCrir((d), -1, JIT_BIG), ADDXrrr(0,0,(d))) +#define jit_gei_i(d, rs, is) jit_booli ((d), (rs), (is), BGEi(_jit.x.pc + 3) ) +#define jit_gei_ui(d, rs, is) jit_booli ((d), (rs), (is), BGEUi(_jit.x.pc + 3)) +#define jit_ger_i(d, s1, s2) jit_boolr ((d), (s1), (s2), BGEi(_jit.x.pc + 3) ) +#define jit_ger_ui(d, s1, s2) jit_boolr ((d), (s1), (s2), BGEUi(_jit.x.pc + 3)) +#define jit_gti_i(d, rs, is) jit_booli ((d), (rs), (is), BGi(_jit.x.pc + 3) ) +#define jit_gti_ui(d, rs, is) jit_booli ((d), (rs), (is), BGUi(_jit.x.pc + 3) ) +#define jit_gtr_i(d, s1, s2) jit_boolr ((d), (s1), (s2), BGi(_jit.x.pc + 3) ) +#define jit_gtr_ui(d, s1, s2) jit_boolr ((d), (s1), (s2), BGUi(_jit.x.pc + 3) ) +#define jit_hmuli_i(d, rs, is) (jit_muli_i (JIT_BIG, (rs), (is)), RDir (_y, (d))) +#define jit_hmuli_ui(d, rs, is) (jit_muli_ui(JIT_BIG, (rs), (is)), RDir (_y, (d))) +#define jit_hmulr_i(d, s1, s2) (jit_mulr_i (JIT_BIG, (s1), (s2)), RDir (_y, (d))) +#define jit_hmulr_ui(d, s1, s2) (jit_mulr_ui(JIT_BIG, (s1), (s2)), RDir (_y, (d))) +#define jit_jmpi(label) (BA_Ai((label)), _jit.x.pc) +#define jit_jmpr(reg) (JMPx(JIT_RZERO, (reg)), NOP(), _jit.x.pc - 1) +#define jit_ldxi_c(d, rs, is) jit_chk_imm((is), LDSBmr((rs), (is), (d)), LDSBxr((rs), JIT_BIG, (d))) +#define jit_ldxi_i(d, rs, is) jit_chk_imm((is), LDSWmr((rs), (is), (d)), LDSWxr((rs), JIT_BIG, (d))) +#define jit_ldxi_s(d, rs, is) jit_chk_imm((is), LDSHmr((rs), (is), (d)), LDSHxr((rs), JIT_BIG, (d))) +#define jit_ldxi_uc(d, rs, is) jit_chk_imm((is), LDUBmr((rs), (is), (d)), LDUBxr((rs), JIT_BIG, (d))) +#define jit_ldxi_us(d, rs, is) jit_chk_imm((is), LDUHmr((rs), (is), (d)), LDUHxr((rs), JIT_BIG, (d))) +#define jit_ldxr_c(d, s1, s2) LDSBxr((s1), (s2), (d)) +#define jit_ldxr_i(d, s1, s2) LDSWxr((s1), (s2), (d)) +#define jit_ldxr_s(d, s1, s2) LDSHxr((s1), (s2), (d)) +#define jit_ldxr_uc(d, s1, s2) LDUBxr((s1), (s2), (d)) +#define jit_ldxr_us(d, s1, s2) LDUHxr((s1), (s2), (d)) +#define jit_lei_i(d, rs, is) jit_booli ((d), (rs), (is), BLEi(_jit.x.pc + 3) ) +#define jit_lei_ui(d, rs, is) jit_booli ((d), (rs), (is), BLEUi(_jit.x.pc + 3)) +#define jit_ler_i(d, s1, s2) jit_boolr ((d), (s1), (s2), BLEi(_jit.x.pc + 3) ) +#define jit_ler_ui(d, s1, s2) jit_boolr ((d), (s1), (s2), BLEUi(_jit.x.pc + 3)) +#define jit_lshi_i(d, rs, is) SLLrir((rs), (is), (d)) +#define jit_lshr_i(d, r1, r2) SLLrrr((r1), (r2), (d)) +#define jit_lti_i(d, rs, is) jit_booli ((d), (rs), (is), BLi(_jit.x.pc + 3) ) +#define jit_lti_ui(d, rs, is) jit_booli ((d), (rs), (is), BLUi(_jit.x.pc + 3) ) +#define jit_ltr_i(d, s1, s2) jit_boolr ((d), (s1), (s2), BLi(_jit.x.pc + 3) ) +#define jit_ltr_ui(d, s1, s2) jit_boolr ((d), (s1), (s2), BLUi(_jit.x.pc + 3) ) +#define jit_modi_i(d, rs, is) jit_modi(jit_divi_i, jit_muli_i, (d), (rs), (is)) +#define jit_modi_ui(d, rs, is) jit_modi(jit_divi_i, jit_muli_i, (d), (rs), (is)) +#define jit_modr_i(d, s1, s2) jit_modr(jit_divr_i, jit_mulr_i, (d), (s1), (s2)) +#define jit_modr_ui(d, s1, s2) jit_modr(jit_divr_i, jit_mulr_i, (d), (s1), (s2)) +#define jit_movi_i(d, is) SETir((is), (d)) +#define jit_movr_i(d, rs) MOVrr((rs), (d)) +#define jit_muli_i(d, rs, is) jit_chk_imm((is), SMULrir((rs), (is), (d)), SMULrrr((rs), JIT_BIG, (d))) +#define jit_muli_ui(d, rs, is) jit_chk_imm((is), UMULrir((rs), (is), (d)), UMULrrr((rs), JIT_BIG, (d))) +#define jit_mulr_i(d, s1, s2) SMULrrr((s1), (s2), (d)) +#define jit_mulr_ui(d, s1, s2) UMULrrr((s1), (s2), (d)) +#define jit_nop() NOP() +#define jit_ori_i(d, rs, is) jit_chk_imm((is), ORrir((rs), (is), (d)), ORrrr((rs), JIT_BIG, (d))) +#define jit_orr_i(d, s1, s2) ORrrr((s1), (s2), (d)) +#define jit_patch(delay_pc) jit_patch_ ( ((delay_pc) - 1) ) +#define jit_popr_i(rs) (LDmr(JIT_SP, 0, (rs)), ADDrir(JIT_SP, 8, JIT_SP)) +#define jitfp_prepare(numargs, nf, nd) (_jitl.nextarg_put = (numargs)) +#define jit_prolog(numargs) (SAVErir(JIT_SP, -96, JIT_SP), _jitl.nextarg_get = _Ri(0)) +#define jit_pushr_i(rs) (STrm((rs), JIT_SP, -8), SUBrir(JIT_SP, 8, JIT_SP)) +#define jit_pusharg_i(rs) (--_jitl.nextarg_put, MOVrr((rs), _Ro(_jitl.nextarg_put))) +#define jit_ret() (RET(), RESTORE()) +#define jit_retval(rd) MOVrr(_Ro(0), (rd)) +#define jit_rshi_i(d, rs, is) SRArir((rs), (is), (d)) +#define jit_rshi_ui(d, rs, is) SRLrir((rs), (is), (d)) +#define jit_rshr_i(d, r1, r2) SRArrr((r1), (r2), (d)) +#define jit_rshr_ui(d, r1, r2) SRLrrr((r1), (r2), (d)) +#define jit_stxi_c(id, rd, rs) jit_chk_imm((id), STBrm((rs), (rd), (id)), STBrx((rs), (rd), JIT_BIG)) +#define jit_stxi_i(id, rd, rs) jit_chk_imm((id), STWrm((rs), (rd), (id)), STWrx((rs), (rd), JIT_BIG)) +#define jit_stxi_s(id, rd, rs) jit_chk_imm((id), STHrm((rs), (rd), (id)), STHrx((rs), (rd), JIT_BIG)) +#define jit_stxr_c(d1, d2, rs) STBrx((rs), (d1), (d2)) +#define jit_stxr_i(d1, d2, rs) STWrx((rs), (d1), (d2)) +#define jit_stxr_s(d1, d2, rs) STHrx((rs), (d1), (d2)) +#define jit_subr_i(d, s1, s2) SUBrrr((s1), (s2), (d)) +#define jit_subcr_i(d, s1, s2) SUBCCrrr((s1), (s2), (d)) +#define jit_subxi_i(d, rs, is) jit_chk_imm((is), SUBXCCrir((rs), (is), (d)), SUBXCCrrr((rs), JIT_BIG, (d))) +#define jit_subxr_i(d, s1, s2) SUBXCCrrr((s1), (s2), (d)) +#define jit_xori_i(d, rs, is) jit_chk_imm((is), XORrir((rs), (is), (d)), XORrrr((rs), JIT_BIG, (d))) +#define jit_xorr_i(d, s1, s2) XORrrr((s1), (s2), (d)) + +#endif /* __lightning_core_h */ diff --git a/lightning/sparc/fp.h b/lightning/sparc/fp.h new file mode 100644 index 000000000..660af3de7 --- /dev/null +++ b/lightning/sparc/fp.h @@ -0,0 +1,163 @@ +/******************************** -*- C -*- **************************** + * + * Run-time assembler & support macros for the PowerPC math unit + * + ***********************************************************************/ + + +/*********************************************************************** + * + * 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 2.1, 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. + * + ***********************************************************************/ + + + + +#ifndef __lightning_asm_fp_h +#define __lightning_asm_fp_h + +#if 0 + +/* dummy for now */ + +#define _FP1(RD, RS1, OPF, RS2) _2f((RD), 52, (RS1), (OPF), (RS2)) +#define _FP2(RD, RS1, OPF, RS2) _2f((RD), 53, (RS1), (OPF), (RS2)) + +#define FITODrr(FRS, FRD) _FP1((FRD), 0, 200, (FRS)) +#define FDTOIrr(FRS, FRD) _FP1((FRD), 0, 210, (FRS)) +#define FSTODrr(FRS, FRD) _FP1((FRD), 0, 201, (FRS)) +#define FDTOSrr(FRS, FRD) _FP1((FRD), 0, 198, (FRS)) +#define FMOVSrr(FRS, FRD) _FP1((FRD), 0, 1, (FRS)) +#define FNEGSrr(FRS, FRD) _FP1((FRD), 0, 5, (FRS)) +#define FABSSrr(FRS, FRD) _FP1((FRD), 0, 9, (FRS)) +#define FSQRTDrr(FRS, FRD) _FP1((FRD), 0, 74, (FRS)) + +#define FADDDrrr(FRS1, FRS2, FRD) _FP1((FRD), (FRS1), 66, (FRS2)) +#define FSUBDrrr(FRS1, FRS2, FRD) _FP1((FRD), (FRS1), 70, (FRS2)) +#define FMULDrrr(FRS1, FRS2, FRD) _FP1((FRD), (FRS1), 82, (FRS2)) +#define FDIVDrrr(FRS1, FRS2, FRD) _FP1((FRD), (FRS1), 86, (FRS2)) + +#define FCMPDrr(FRS1, FRS2) _FP2(0, (FRS1), 82, (FRS2)) + +#define LDFxr(RS1, RS2, RD) _3 ((RD), 32, (RS1), 0, 0, (RS2)) +#define LDFmr(RS1, IMM, RD) _3i ((RD), 32, (RS1), 1, (IMM)) +#define LDDFxr(RS1, RS2, RD) _3 ((RD), 35, (RS1), 0, 0, (RS2)) +#define LDDFmr(RS1, IMM, RD) _3i ((RD), 35, (RS1), 1, (IMM)) +#define STFrx(RS, RD1, RD2) _3 ((RS), 36, (RD1), 0, 0, (RD2)) +#define STFrm(RS, RD1, IMM) _3i ((RS), 36, (RD1), 1, (IMM)) +#define STDFrx(RS, RD1, RD2) _3 ((RS), 39, (RD1), 0, 0, (RD2)) +#define STDFrm(RS, RD1, IMM) _3i ((RS), 39, (RD1), 1, (IMM)) + +#define FBNi(DISP) _0 (0, 0, 6, (DISP)) +#define FBN_Ai(DISP) _0 (1, 0, 6, (DISP)) +#define FBNEi(DISP) _0 (0, 1, 6, (DISP)) +#define FBNE_Ai(DISP) _0 (1, 1, 6, (DISP)) +#define FBLGi(DISP) _0 (0, 2, 6, (DISP)) +#define FBLG_Ai(DISP) _0 (1, 2, 6, (DISP)) +#define FBULi(DISP) _0 (0, 3, 6, (DISP)) +#define FBUL_Ai(DISP) _0 (1, 3, 6, (DISP)) +#define FBLi(DISP) _0 (0, 4, 6, (DISP)) +#define FBL_Ai(DISP) _0 (1, 4, 6, (DISP)) +#define FBUGi(DISP) _0 (0, 5, 6, (DISP)) +#define FBUG_Ai(DISP) _0 (1, 5, 6, (DISP)) +#define FBGi(DISP) _0 (0, 6, 6, (DISP)) +#define FBG_Ai(DISP) _0 (1, 6, 6, (DISP)) +#define FBUi(DISP) _0 (0, 7, 6, (DISP)) +#define FBU_Ai(DISP) _0 (1, 7, 6, (DISP)) +#define FBAi(DISP) _0 (0, 8, 6, (DISP)) +#define FBA_Ai(DISP) _0 (1, 8, 6, (DISP)) +#define FBEi(DISP) _0 (0, 9, 6, (DISP)) +#define FBE_Ai(DISP) _0 (1, 9, 6, (DISP)) +#define FBUEi(DISP) _0 (0, 10, 6, (DISP)) +#define FBUE_Ai(DISP) _0 (1, 10, 6, (DISP)) +#define FBGEi(DISP) _0 (0, 11, 6, (DISP)) +#define FBGE_Ai(DISP) _0 (1, 11, 6, (DISP)) +#define FBUGEi(DISP) _0 (0, 12, 6, (DISP)) +#define FBUGE_Ai(DISP) _0 (1, 12, 6, (DISP)) +#define FBLEi(DISP) _0 (0, 13, 6, (DISP)) +#define FBLE_Ai(DISP) _0 (1, 13, 6, (DISP)) +#define FBULEi(DISP) _0 (0, 14, 6, (DISP)) +#define FBULE_Ai(DISP) _0 (1, 14, 6, (DISP)) +#define FBOi(DISP) _0 (0, 15, 6, (DISP)) +#define FBO_Ai(DISP) _0 (1, 15, 6, (DISP)) + +#define FSKIPUG() _0d (1, 13, 6, 2) /* fble,a .+8 */ +#define FSKIPUL() _0d (1, 11, 6, 2) /* fbge,a .+8 */ + +#define jit_add_two(reg0) FADDDrrr(30 - (reg0) * 2, 28 - (reg0) * 2, 30 - (reg0) * 2) +#define jit_sub_two(reg0) FSUBDrrr(30 - (reg0) * 2, 28 - (reg0) * 2, 30 - (reg0) * 2) +#define jit_mul_two(reg0) FMULDrrr(30 - (reg0) * 2, 28 - (reg0) * 2, 30 - (reg0) * 2) +#define jit_div_two(reg0) FDIVDrrr(30 - (reg0) * 2, 28 - (reg0) * 2, 30 - (reg0) * 2) + +#define jit_abs(reg0) FABSSrr(30 - (reg0) * 2, 30 - (reg0) * 2) +#define jit_neg(reg0) FNEGSrr(30 - (reg0) * 2, 30 - (reg0) * 2) +#define jit_sqrt(reg0) FSQRTDrr(30 - (reg0) * 2, 30 - (reg0) * 2) + +#define jit_fpimm(reg0, first, second) \ + (_1(4), NOP(), _jit_L(first), _jit_L(second), \ + jit_ldxi_d((reg0), _Ro(7), 8)) + +#define jit_ldxi_f(reg0, rs, is) (jit_chk_imm((is), LDFmr((rs), (is), 30 - (reg0) * 2), LDFxr((rs), JIT_BIG, 30 - (reg0) * 2)), FSTODrr(30 - (reg0) * 2, 30 - (reg0) * 2)) +#define jit_ldxi_d(reg0, rs, is) jit_chk_imm((is), LDDFmr((rs), (is), 30 - (reg0) * 2), LDDFxr((rs), JIT_BIG, 30 - (reg0) * 2)) +#define jit_ldxr_f(reg0, s1, s2) (LDFxr((s1), (s2), 30 - (reg0) * 2), FSTODrr(30 - (reg0) * 2, 30 - (reg0) * 2)) +#define jit_ldxr_d(reg0, s1, s2) LDDFxr((s1), (s2), 30 - (reg0) * 2) +#define jit_stxi_f(id, rd, reg0) (FDTOSrr(30 - (reg0) * 2, 30 - (reg0) * 2), jit_chk_imm((id), STFrm(30 - (reg0) * 2, (rd), (id)), STFrx(30 - (reg0) * 2, (rd), JIT_BIG))) +#define jit_stxi_d(id, rd, reg0) jit_chk_imm((id), STDFrm(30 - (reg0) * 2, (rd), (id)), STDFrx(30 - (reg0) * 2, (rd), JIT_BIG)) +#define jit_stxr_f(d1, d2, reg0) (FDTOSrr(30 - (reg0) * 2, 30 - (reg0) * 2), STFrx (30 - (reg0) * 2, (d1), (d2))) +#define jit_stxr_d(d1, d2, reg0) STDFrx(30 - (reg0) * 2, (d1), (d2)) + + +#define jit_do_round(mode, rd, freg) ( \ + _1(3), \ + SETHIir(_HI(mode << 29), JIT_BIG), \ + NOP(), \ + STFSRm(_Ro(7), 8), /* store fsr */ \ + LDmr(_Ro(7), 8, rd), \ + XORrrr(rd, JIT_BIG, JIT_BIG), /* adjust mode */ \ + STrm(JIT_BIG, _Ro(7), 8), \ + LDFSRm(_Ro(7), 8), /* load fsr */ \ + FDTOIrr(freg, freg), /* truncate */ \ + STrm(rd, _Ro(7), 8), /* load old fsr */ \ + LDFSRm(_Ro(7), 8), \ + STFrm(freg, _Ro(7), 8), /* store truncated value */ \ + LDmr(_Ro(7), 8, rd)) /* load it into rd */ + + +/* call delay slot data ,--- call lands here */ +#define jit_exti_d(reg0, rs) (_1(3), NOP(), NOP(), STrm((rs), _Ro(7), 8), LDFmr(_Ro(7), 8, 30 - (reg0) * 2), FITODrr(30 - (reg0) * 2, 30 - (reg0) * 2)) +#define jit_round(rd, reg0) (_1(3), FDTOIrr(30 - (reg0) * 2, 30 - (reg0) * 2), NOP(), STFrm(30 - (reg0) * 2, _Ro(7), 8), LDmr(_Ro(7), 8, (rd))) +#define jit_floor(rd, reg0) jit_do_round(3, (rd), (30 - (reg0) * 2)) +#define jit_ceil(rd, reg0) jit_do_round(2, (rd), (30 - (reg0) * 2)) +#define jit_trunc(rd, reg0) jit_do_round(1, (rd), (30 - (reg0) * 2)) + +static double jit_zero = 0.0; + +#define jit_cmp(le, ge, reg0) (SETHIir(_HI(_jit_UL(&jit_zero)), (le)), \ + LDDFmr((le), _LO(_jit_UL(&jit_zero)), 28 - (reg0) * 2), \ + FCMPDrr(30 - (reg0) * 2, 28 - (reg0) * 2), \ + MOVir(0, (le)), MOVir(0, (ge)), \ + FSKIPUL(), MOVir(1, (ge)), \ + FSKIPUG(), MOVir(1, (le))) + +#endif + +#endif /* __lightning_asm_fp_h */ diff --git a/lightning/sparc/funcs.h b/lightning/sparc/funcs.h new file mode 100644 index 000000000..8fd9e1001 --- /dev/null +++ b/lightning/sparc/funcs.h @@ -0,0 +1,65 @@ +/******************************** -*- C -*- **************************** + * + * Platform-independent layer inline functions (Sparc) + * + ***********************************************************************/ + + +/*********************************************************************** + * + * 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 2.1, 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. + * + ***********************************************************************/ + + + +#ifndef __lightning_funcs_h +#define __lightning_funcs_h + +#if !defined(__GNUC__) && !defined(__GNUG__) +#error Go get GNU C, I do not know how to flush the cache +#error with this compiler. +#else +/* Why doesn't this compile?!? + * static void + * jit_flush_code(start, end) + * void *start; + * void *end; + */ + +static void +jit_flush_code(void* start, void* end) +{ +#ifndef LIGHTNING_CROSS + register char *dest; + + __asm__ __volatile__ ("stbar"); + for (dest = (char *)start; dest <= (char *)end; dest += 4) { + __asm__ __volatile__ ("flush %0"::"r"(dest)); + } + + /* [SPARC Architecture Manual v8, page 139, implementation note #5] */ + __asm__ __volatile__ ("nop; nop; nop; nop; nop"); +#endif +} +#endif + +#endif /* __lightning_core_h */ diff --git a/lightningize.in b/lightningize.in new file mode 100644 index 000000000..71d4ba364 --- /dev/null +++ b/lightningize.in @@ -0,0 +1,226 @@ +#! /bin/sh +# lightningize - Prepare a package to use lightning. +# Generated automatically from lightningize.in by configure. +# Copyright (C) 1996-2000 Free Software Foundation, Inc. +# Originally by Gordon Matzigkeit , 1996 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# 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 name of this program. +progname=`echo "$0" | sed 's%^.*/%%'` + +# Constants. +PROGRAM=lightningize +PACKAGE=@PACKAGE@ +VERSION=@VERSION@ + +# Directory names. +prefix=@prefix@ +datadir=@datadir@ +includedir=@includedir@ +pkgdatadir=${datadir}/lightning +pkgincludedir=${includedir}/lightning +aclocaldir=${datadir}/aclocal + +BACKENDS="@BACKENDS@" +file_base_names="asm core funcs fp" +macro_name=LIGHTNING_CONFIGURE_IF_NOT_FOUND +lightning_m4="$aclocaldir/lightning.m4" + +# Global variables. +automake= +copy= +force= +configure_ac= +status=0 +dry_run=no +help="Try \`$progname --help' for more information." +rm="rm -f" +ln_s="@LN_S@" +cp="cp -f" +mkdir="mkdir" + +for arg +do + case "$arg" in + --help) + cat <&2 + echo "$help" 1>&2 + exit 1 + ;; + + *) + echo "$progname: too many arguments" 1>&2 + echo "$help" 1>&2 + exit 1 + ;; + esac +done + +if test -f configure.ac; then + configure_ac=configure.ac +elif test -f configure.in; then + configure_ac=configure.in +else + echo "$progname: \`configure.ac' does not exist" 1>&2 + echo "$help" 1>&2 + exit 1 +fi + + +if test -z "$automake"; then + if egrep "^$macro_name" $configure_ac >/dev/null 2>&1; then : + else + echo "Remember to add \`$macro_name' to \`$configure_ac'." + fi + + if grep 'generated automatically by aclocal' aclocal.m4 >/dev/null 2>&1; then + updatemsg="update your \`aclocal.m4' by running aclocal" + else + updatemsg="add the contents of \`$lightning_m4' to \`aclocal.m4'" + fi + + if egrep '^AC_DEFUN\(\['$macro_name aclocal.m4 >/dev/null 2>&1; then + # Check the version number on lightning.m4 and the one used in aclocal.m4. + instserial=`grep '^# serial ' $lightning_m4 | grep $macro_name | sed -e 's/^# serial \([0-9][0-9]*\).*$/\1/; q'` + + if test -z "$instserial"; then + echo "$progname: warning: no serial number on \`$lightning_m4'" 1>&2 + else + # If the local macro has no serial number, we assume it's ancient. + localserial=`grep '^# serial ' aclocal.m4 | grep $macro_name | sed -e 's/^# serial \([0-9][0-9]*\).*$/\1/; q'` + + test -z "$localserial" && localserial=0 + + if test "$localserial" -lt "$instserial"; then + echo "You should $updatemsg." + elif test "$localserial" -gt "$instserial"; then + echo "$progname: \`$lightning_m4' is serial $instserial, less than $localserial in \`aclocal.m4'" 1>&2 + if test -z "$force"; then + echo "Use \`--force' to replace newer lightning files with this version." 1>&2 + exit 1 + fi + echo "To remain compatible, you should $updatemsg." + fi + fi + else + echo "You should $updatemsg." + fi +fi + +# Create the list of directories and files to be updated +# Syntax is DESTINATION-DIRECTORY:ABSOLUTE-SRC-PATH + +dirs="lightning" +files="lightning:$includedir/lightning.h lightning:$pkgdatadir/Makefile.am" +for i in $file_base_names; do + files="$files lightning:$pkgincludedir/$i-common.h" +done +for j in $BACKENDS; do + dirs="$dirs lightning/$j" + for i in $file_base_names; do + files="$files lightning/$j:$pkgincludedir/$j/$i.h" + done +done + +for dir in $dirs; do + if $mkdir $dir; then : + else + echo "$progname: cannot create \`$dir'" 1>&2 + status=1 + fi +done + +for file in $files; do + base=`echo $file | sed 's%^.*/%%' ` + src=`echo $file | sed 's/^.*://' ` + dest=`echo $file | sed 's/:.*//' `/$base + if test -f "$dest" && test -z "$force"; then + test -z "$automake" && echo "$progname: \`$dest' exists: use \`--force' to overwrite" 1>&2 + continue + fi + + $rm $dest + if test -n "$ln_s" && $ln_s $src $dest; then : + elif $cp $src $dest; then : + else + echo "$progname: cannot copy \`$src' to \`$dest'" 1>&2 + status=1 + fi +done + +exit $status + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/opcode/Makefile.am b/opcode/Makefile.am new file mode 100644 index 000000000..198480d4b --- /dev/null +++ b/opcode/Makefile.am @@ -0,0 +1,7 @@ +EXTRA_LIBRARIES = libdisass.a +noinst_LIBRARIES = @LIBDISASS@ + +libdisass_a_SOURCES = dis-buf.c i386-dis.c ppc-dis.c ppc-opc.c sparc-dis.c \ + sparc-opc.c disass.c + +noinst_HEADERS = ansidecl.h bfd.h dis-asm.h i386.h ppc.h sparc.h sysdep.h diff --git a/opcode/ansidecl.h b/opcode/ansidecl.h new file mode 100644 index 000000000..4944cb22b --- /dev/null +++ b/opcode/ansidecl.h @@ -0,0 +1,13 @@ +#ifndef __ANSIDECL_H_SEEN +#define __ANSIDECL_H_SEEN + +#ifdef __STDC__ +#define PARAMS(x) x +typedef void *PTR; +#else +#define CONST const +#define PARAMS(x) () +typedef char *PTR; +#endif + +#endif diff --git a/opcode/bfd.h b/opcode/bfd.h new file mode 100644 index 000000000..431021e2c --- /dev/null +++ b/opcode/bfd.h @@ -0,0 +1,185 @@ +/* Main header file for the bfd library -- portable access to object files. + Copyright 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of BFD, the Binary File Descriptor library. +(Simplified and modified for GNU lightning) + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* bfd.h -- The only header file required by users of the bfd library + +The bfd.h file is generated from bfd-in.h and various .c files; if you +change it, your changes will probably be lost. + +All the prototypes and definitions following the comment "THE FOLLOWING +IS EXTRACTED FROM THE SOURCE" are extracted from the source files for +BFD. If you change it, someone oneday will extract it from the source +again, and your changes will be lost. To save yourself from this bind, +change the definitions in the source in the bfd directory. Type "make +docs" and then "make headers" in that directory, and magically this file +will change to reflect your changes. + +If you don't have the tools to perform the extraction, then you are +safe from someone on your system trampling over your header files. +You should still maintain the equivalence between the source and this +file though; every change you make to the .c file should be reflected +here. */ + +#ifndef __BFD_H_SEEN__ +#define __BFD_H_SEEN__ + +#include "ansidecl.h" + +#ifndef INLINE +#if __GNUC__ >= 2 +#define INLINE __inline__ +#else +#define INLINE +#endif +#endif + +/* To squelch erroneous compiler warnings ("illegal pointer + combination") from the SVR3 compiler, we would like to typedef + boolean to int (it doesn't like functions which return boolean. + Making sure they are never implicitly declared to return int + doesn't seem to help). But this file is not configured based on + the host. */ +/* General rules: functions which are boolean return true on success + and false on failure (unless they're a predicate). -- bfd.doc */ +/* I'm sure this is going to break something and someone is going to + force me to change it. */ +/* typedef enum boolean {false, true} boolean; */ +/* Yup, SVR4 has a "typedef enum boolean" in -fnf */ +/* It gets worse if the host also defines a true/false enum... -sts */ +/* And even worse if your compiler has built-in boolean types... -law */ +#if defined (__GNUG__) && (__GNUC_MINOR__ > 5) +#define TRUE_FALSE_ALREADY_DEFINED +#endif +#ifdef MPW +/* Pre-emptive strike - get the file with the enum. */ +#include +#define TRUE_FALSE_ALREADY_DEFINED +#endif /* MPW */ +#ifndef TRUE_FALSE_ALREADY_DEFINED +typedef enum bfd_boolean {false, true} boolean; +#define BFD_TRUE_FALSE +#else +/* Use enum names that will appear nowhere else. */ +typedef enum bfd_boolean {bfd_fffalse, bfd_tttrue} boolean; +#endif + +/* A pointer to a position in a file. */ +/* FIXME: This should be using off_t from . + For now, try to avoid breaking stuff by not including here. + This will break on systems with 64-bit file offsets (e.g. 4.4BSD). + Probably the best long-term answer is to avoid using file_ptr AND off_t + in this header file, and to handle this in the BFD implementation + rather than in its interface. */ +/* typedef off_t file_ptr; */ +typedef long int file_ptr; + +/* Represent a target address. Also used as a generic unsigned type + which is guaranteed to be big enough to hold any arithmetic types + we need to deal with. */ +typedef unsigned long bfd_vma; + +/* A generic signed type which is guaranteed to be big enough to hold any + arithmetic types we need to deal with. Can be assumed to be compatible + with bfd_vma in the same way that signed and unsigned ints are compatible + (as parameters, in assignment, etc). */ +typedef long bfd_signed_vma; + +typedef unsigned long symvalue; +typedef unsigned long bfd_size_type; + +/* Print a bfd_vma x on stream s. */ +#define fprintf_vma(s,x) fprintf(s, "%08lx", x) +#define sprintf_vma(s,x) sprintf(s, "%08lx", x) +#define printf_vma(x) fprintf_vma(stdout,x) + +typedef unsigned int flagword; /* 32 bits of flags */ +typedef unsigned char bfd_byte; + +enum bfd_architecture +{ + bfd_arch_unknown, /* File arch not known */ + bfd_arch_obscure, /* Arch known, not one of these */ + bfd_arch_m68k, /* Motorola 68xxx */ + bfd_arch_vax, /* DEC Vax */ + bfd_arch_i960, /* Intel 960 */ + /* The order of the following is important. + lower number indicates a machine type that + only accepts a subset of the instructions + available to machines with higher numbers. + The exception is the "ca", which is + incompatible with all other machines except + "core". */ + +#define bfd_mach_i960_core 1 +#define bfd_mach_i960_ka_sa 2 +#define bfd_mach_i960_kb_sb 3 +#define bfd_mach_i960_mc 4 +#define bfd_mach_i960_xa 5 +#define bfd_mach_i960_ca 6 +#define bfd_mach_i960_jx 7 +#define bfd_mach_i960_hx 8 + + bfd_arch_a29k, /* AMD 29000 */ + bfd_arch_sparc, /* SPARC */ +#define bfd_mach_sparc 1 + /* The difference between v8plus and v9 is that v9 is a true 64 bit env. */ +#define bfd_mach_sparc_v8plus 2 +#define bfd_mach_sparc_v8plusa 3 /* with ultrasparc add'ns */ +#define bfd_mach_sparc_v9 4 +#define bfd_mach_sparc_v9a 5 /* with ultrasparc add'ns */ + /* Nonzero if MACH has the v9 instruction set. */ +#define bfd_mach_sparc_v9_p(mach) ((mach) != bfd_mach_sparc) + bfd_arch_mips, /* MIPS Rxxxx */ + bfd_arch_i386, /* Intel 386 */ + bfd_arch_we32k, /* AT&T WE32xxx */ + bfd_arch_tahoe, /* CCI/Harris Tahoe */ + bfd_arch_i860, /* Intel 860 */ + bfd_arch_romp, /* IBM ROMP PC/RT */ + bfd_arch_alliant, /* Alliant */ + bfd_arch_convex, /* Convex */ + bfd_arch_m88k, /* Motorola 88xxx */ + bfd_arch_pyramid, /* Pyramid Technology */ + bfd_arch_h8300, /* Hitachi H8/300 */ +#define bfd_mach_h8300 1 +#define bfd_mach_h8300h 2 + bfd_arch_powerpc, /* PowerPC */ + bfd_arch_rs6000, /* IBM RS/6000 */ + bfd_arch_hppa, /* HP PA RISC */ + bfd_arch_z8k, /* Zilog Z8000 */ +#define bfd_mach_z8001 1 +#define bfd_mach_z8002 2 + bfd_arch_h8500, /* Hitachi H8/500 */ + bfd_arch_sh, /* Hitachi SH */ + bfd_arch_alpha, /* Dec Alpha */ + bfd_arch_arm, /* Advanced Risc Machines ARM */ + bfd_arch_ns32k, /* National Semiconductors ns32000 */ + bfd_arch_w65, /* WDC 65816 */ + bfd_arch_last + }; + +enum bfd_endian { BFD_ENDIAN_UNKNOWN }; + +typedef struct bfd bfd; + +#define bfd_getb32(x) *((int *)(x)) +#define bfd_getl32(x) *((int *)(x)) + +#endif diff --git a/opcode/dis-asm.h b/opcode/dis-asm.h new file mode 100644 index 000000000..d70bd514e --- /dev/null +++ b/opcode/dis-asm.h @@ -0,0 +1,175 @@ +/* Interface between the opcode library and its callers. + Written by Cygnus Support, 1993. + + The opcode library (libopcodes.a) provides instruction decoders for + a large variety of instruction sets, callable with an identical + interface, for making instruction-processing programs more independent + of the instruction set being processed. */ + +#ifndef DIS_ASM_H +#define DIS_ASM_H + +#include +#include "bfd.h" + +typedef int (*fprintf_ftype) PARAMS((FILE*, const char*, ...)); + +enum dis_insn_type { + dis_noninsn, /* Not a valid instruction */ + dis_nonbranch, /* Not a branch instruction */ + dis_branch, /* Unconditional branch */ + dis_condbranch, /* Conditional branch */ + dis_jsr, /* Jump to subroutine */ + dis_condjsr, /* Conditional jump to subroutine */ + dis_dref, /* Data reference instruction */ + dis_dref2 /* Two data references in instruction */ +}; + +/* This struct is passed into the instruction decoding routine, + and is passed back out into each callback. The various fields are used + for conveying information from your main routine into your callbacks, + for passing information into the instruction decoders (such as the + addresses of the callback functions), or for passing information + back from the instruction decoders to their callers. + + It must be initialized before it is first passed; this can be done + by hand, or using one of the initialization macros below. */ + +typedef struct disassemble_info { + fprintf_ftype fprintf_func; + FILE *stream; + PTR application_data; + + /* Target description. We could replace this with a pointer to the bfd, + but that would require one. There currently isn't any such requirement + so to avoid introducing one we record these explicitly. */ + /* The bfd_arch value. */ + enum bfd_architecture arch; + /* The bfd_mach value. */ + unsigned long mach; + /* Endianness (for bi-endian cpus). Mono-endian cpus can ignore this. */ + enum bfd_endian endian; + + /* For use by the disassembler. + The top 16 bits are reserved for public use (and are documented here). + The bottom 16 bits are for the internal use of the disassembler. */ + unsigned long flags; + PTR private_data; + + /* Function used to get bytes to disassemble. MEMADDR is the + address of the stuff to be disassembled, MYADDR is the address to + put the bytes in, and LENGTH is the number of bytes to read. + INFO is a pointer to this struct. + Returns an errno value or 0 for success. */ + int (*read_memory_func) + PARAMS ((bfd_vma memaddr, bfd_byte *myaddr, int length, + struct disassemble_info *info)); + + /* Function which should be called if we get an error that we can't + recover from. STATUS is the errno value from read_memory_func and + MEMADDR is the address that we were trying to read. INFO is a + pointer to this struct. */ + void (*memory_error_func) + PARAMS ((int status, bfd_vma memaddr, struct disassemble_info *info)); + + /* Function called to print ADDR. */ + void (*print_address_func) + PARAMS ((bfd_vma addr, struct disassemble_info *info)); + + /* These are for buffer_read_memory. */ + bfd_byte *buffer; + bfd_vma buffer_vma; + int buffer_length; + + /* Results from instruction decoders. Not all decoders yet support + this information. This info is set each time an instruction is + decoded, and is only valid for the last such instruction. + + To determine whether this decoder supports this information, set + insn_info_valid to 0, decode an instruction, then check it. */ + + char insn_info_valid; /* Branch info has been set. */ + char branch_delay_insns; /* How many sequential insn's will run before + a branch takes effect. (0 = normal) */ + char data_size; /* Size of data reference in insn, in bytes */ + enum dis_insn_type insn_type; /* Type of instruction */ + bfd_vma target; /* Target address of branch or dref, if known; + zero if unknown. */ + bfd_vma target2; /* Second target address for dref2 */ + +} disassemble_info; + + +/* Standard disassemblers. Disassemble one instruction at the given + target address. Return number of bytes processed. */ +typedef int (*disassembler_ftype) + PARAMS((bfd_vma, disassemble_info *)); + +extern int print_insn_big_mips PARAMS ((bfd_vma, disassemble_info*)); +extern int print_insn_little_mips PARAMS ((bfd_vma, disassemble_info*)); +extern int print_insn_i386 PARAMS ((bfd_vma, disassemble_info*)); +extern int print_insn_m68k PARAMS ((bfd_vma, disassemble_info*)); +extern int print_insn_z8001 PARAMS ((bfd_vma, disassemble_info*)); +extern int print_insn_z8002 PARAMS ((bfd_vma, disassemble_info*)); +extern int print_insn_h8300 PARAMS ((bfd_vma, disassemble_info*)); +extern int print_insn_h8300h PARAMS ((bfd_vma, disassemble_info*)); +extern int print_insn_h8500 PARAMS ((bfd_vma, disassemble_info*)); +extern int print_insn_alpha PARAMS ((bfd_vma, disassemble_info*)); +extern int print_insn_big_arm PARAMS ((bfd_vma, disassemble_info*)); +extern int print_insn_little_arm PARAMS ((bfd_vma, disassemble_info*)); +extern int print_insn_sparc PARAMS ((bfd_vma, disassemble_info*)); +extern int print_insn_sparc64 PARAMS ((bfd_vma, disassemble_info*)); +extern int print_insn_big_a29k PARAMS ((bfd_vma, disassemble_info*)); +extern int print_insn_little_a29k PARAMS ((bfd_vma, disassemble_info*)); +extern int print_insn_i960 PARAMS ((bfd_vma, disassemble_info*)); +extern int print_insn_sh PARAMS ((bfd_vma, disassemble_info*)); +extern int print_insn_shl PARAMS ((bfd_vma, disassemble_info*)); +extern int print_insn_hppa PARAMS ((bfd_vma, disassemble_info*)); +extern int print_insn_m88k PARAMS ((bfd_vma, disassemble_info*)); +extern int print_insn_ns32k PARAMS ((bfd_vma, disassemble_info*)); +extern int print_insn_big_powerpc PARAMS ((bfd_vma, disassemble_info*)); +extern int print_insn_little_powerpc PARAMS ((bfd_vma, disassemble_info*)); +extern int print_insn_rs6000 PARAMS ((bfd_vma, disassemble_info*)); +extern int print_insn_w65 PARAMS ((bfd_vma, disassemble_info*)); + +/* Fetch the disassembler for a given BFD, if that support is available. */ +extern disassembler_ftype disassembler PARAMS ((bfd *)); + + +/* This block of definitions is for particular callers who read instructions + into a buffer before calling the instruction decoder. */ + +/* Here is a function which callers may wish to use for read_memory_func. + It gets bytes from a buffer. */ +extern int buffer_read_memory + PARAMS ((bfd_vma, bfd_byte *, int, struct disassemble_info *)); + +/* This function goes with buffer_read_memory. + It prints a message using info->fprintf_func and info->stream. */ +extern void perror_memory PARAMS ((int, bfd_vma, struct disassemble_info *)); + + +/* Just print the address in hex. This is included for completeness even + though both GDB and objdump provide their own (to print symbolic + addresses). */ +extern void generic_print_address + PARAMS ((bfd_vma, struct disassemble_info *)); + +/* Macro to initialize a disassemble_info struct. This should be called + by all applications creating such a struct. */ +#define INIT_DISASSEMBLE_INFO(INFO, STREAM, FPRINTF_FUNC) \ + (INFO).fprintf_func = (FPRINTF_FUNC), \ + (INFO).stream = (STREAM), \ + (INFO).buffer = NULL, \ + (INFO).buffer_vma = 0, \ + (INFO).buffer_length = 0, \ + (INFO).read_memory_func = buffer_read_memory, \ + (INFO).memory_error_func = perror_memory, \ + (INFO).print_address_func = generic_print_address, \ + (INFO).arch = bfd_arch_unknown, \ + (INFO).mach = 0, \ + (INFO).endian = BFD_ENDIAN_UNKNOWN, \ + (INFO).flags = 0, \ + (INFO).insn_info_valid = 0 + +#endif /* ! defined (DIS_ASM_H) */ diff --git a/opcode/dis-buf.c b/opcode/dis-buf.c new file mode 100644 index 000000000..47a2e33ef --- /dev/null +++ b/opcode/dis-buf.c @@ -0,0 +1,70 @@ +/* Disassemble from a buffer, for GNU. + Copyright (C) 1993, 1994 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "sysdep.h" +#include "dis-asm.h" +#include + +/* Get LENGTH bytes from info's buffer, at target address memaddr. + Transfer them to myaddr. */ +int +buffer_read_memory (memaddr, myaddr, length, info) + bfd_vma memaddr; + bfd_byte *myaddr; + int length; + struct disassemble_info *info; +{ + if (memaddr < info->buffer_vma + || memaddr + length > info->buffer_vma + info->buffer_length) + /* Out of bounds. Use EIO because GDB uses it. */ + return EIO; + memcpy (myaddr, info->buffer + (memaddr - info->buffer_vma), length); + return 0; +} + +/* Print an error message. We can assume that this is in response to + an error return from buffer_read_memory. */ +void +perror_memory (status, memaddr, info) + int status; + bfd_vma memaddr; + struct disassemble_info *info; +{ + if (status != EIO) + /* Can't happen. */ + (*info->fprintf_func) (info->stream, "Unknown error %d\n", status); + else + /* Actually, address between memaddr and memaddr + len was + out of bounds. */ + (*info->fprintf_func) (info->stream, + "Address 0x%x is out of bounds.\n", memaddr); +} + +/* This could be in a separate file, to save miniscule amounts of space + in statically linked executables. */ + +/* Just print the address is hex. This is included for completeness even + though both GDB and objdump provide their own (to print symbolic + addresses). */ + +void +generic_print_address (addr, info) + bfd_vma addr; + struct disassemble_info *info; +{ + (*info->fprintf_func) (info->stream, "0x%x", addr); +} diff --git a/opcode/disass.c b/opcode/disass.c new file mode 100644 index 000000000..71b1d1b4c --- /dev/null +++ b/opcode/disass.c @@ -0,0 +1,78 @@ +/******************************** -*- C -*- **************************** + * + * lightning disassembling support + * + ***********************************************************************/ + + +/*********************************************************************** + * + * Copyright 2000 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 2.1, 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. + * + ***********************************************************************/ + +#include +#include +#include "lightning.h" +#include "dis-asm.h" + +void disassemble(stream, from, to) + FILE *stream; + char *from, *to; +{ + disassemble_info info; + bfd_vma pc = (bfd_vma) from; + bfd_vma end = (bfd_vma) to; + + INIT_DISASSEMBLE_INFO(info, stream, fprintf); + info.buffer = NULL; + info.buffer_vma = 0; + info.buffer_length = end; + + while (pc < end) { + fprintf_vma(stream, pc); + putc('\t', stream); +#ifdef LIGHTNING_I386 + pc += print_insn_i386(pc, &info); +#endif +#ifdef LIGHTNING_PPC + pc += print_insn_big_powerpc(pc, &info); +#endif +#ifdef LIGHTNING_SPARC + pc += print_insn_sparc(pc, &info); +#endif + putc('\n', stream); + } +} + +/* Panic on failing malloc */ +PTR +xmalloc(size) + size_t size; +{ + PTR ret = malloc(size ? size : 1); + if (!ret) { + fprintf(stderr, "Couldn't allocate memory\n"); + exit(1); + } + return ret; +} + diff --git a/opcode/i386-dis.c b/opcode/i386-dis.c new file mode 100644 index 000000000..b781edc32 --- /dev/null +++ b/opcode/i386-dis.c @@ -0,0 +1,2031 @@ +/* Print i386 instructions for GDB, the GNU debugger. + Copyright (C) 1988, 89, 91, 93, 94, 95, 1996 Free Software Foundation, Inc. + +This file is part of GDB. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* + * 80386 instruction printer by Pace Willisson (pace@prep.ai.mit.edu) + * July 1988 + * modified by John Hassey (hassey@dg-rtp.dg.com) + */ + +/* + * The main tables describing the instructions is essentially a copy + * of the "Opcode Map" chapter (Appendix A) of the Intel 80386 + * Programmers Manual. Usually, there is a capital letter, followed + * by a small letter. The capital letter tell the addressing mode, + * and the small letter tells about the operand size. Refer to + * the Intel manual for details. + */ + +#include "dis-asm.h" +#include "sysdep.h" + +#define MAXLEN 20 + +#include + +struct dis_private +{ + /* Points to first byte not fetched. */ + bfd_byte *max_fetched; + bfd_byte the_buffer[MAXLEN]; + bfd_vma insn_start; + jmp_buf bailout; +}; + +/* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive) + to ADDR (exclusive) are valid. Returns 1 for success, longjmps + on error. */ +#define FETCH_DATA(info, addr) \ + ((addr) <= ((struct dis_private *)(info->private_data))->max_fetched \ + ? 1 : fetch_data ((info), (addr))) + +static int +fetch_data (info, addr) + struct disassemble_info *info; + bfd_byte *addr; +{ + int status; + struct dis_private *priv = (struct dis_private *)info->private_data; + bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer); + + status = (*info->read_memory_func) (start, + priv->max_fetched, + addr - priv->max_fetched, + info); + if (status != 0) + { + (*info->memory_error_func) (status, start, info); + longjmp (priv->bailout, 1); + } + else + priv->max_fetched = addr; + return 1; +} + +#define Eb OP_E, b_mode +#define indirEb OP_indirE, b_mode +#define Gb OP_G, b_mode +#define Ev OP_E, v_mode +#define indirEv OP_indirE, v_mode +#define Ew OP_E, w_mode +#define Ma OP_E, v_mode +#define M OP_E, 0 +#define Mp OP_E, 0 /* ? */ +#define Gv OP_G, v_mode +#define Gw OP_G, w_mode +#define Rw OP_rm, w_mode +#define Rd OP_rm, d_mode +#define Ib OP_I, b_mode +#define sIb OP_sI, b_mode /* sign extened byte */ +#define Iv OP_I, v_mode +#define Iw OP_I, w_mode +#define Jb OP_J, b_mode +#define Jv OP_J, v_mode +#define ONE OP_ONE, 0 +#define Cd OP_C, d_mode +#define Dd OP_D, d_mode +#define Td OP_T, d_mode + +#define eAX OP_REG, eAX_reg +#define eBX OP_REG, eBX_reg +#define eCX OP_REG, eCX_reg +#define eDX OP_REG, eDX_reg +#define eSP OP_REG, eSP_reg +#define eBP OP_REG, eBP_reg +#define eSI OP_REG, eSI_reg +#define eDI OP_REG, eDI_reg +#define AL OP_REG, al_reg +#define CL OP_REG, cl_reg +#define DL OP_REG, dl_reg +#define BL OP_REG, bl_reg +#define AH OP_REG, ah_reg +#define CH OP_REG, ch_reg +#define DH OP_REG, dh_reg +#define BH OP_REG, bh_reg +#define AX OP_REG, ax_reg +#define DX OP_REG, dx_reg +#define indirDX OP_REG, indir_dx_reg + +#define Sw OP_SEG, w_mode +#define Ap OP_DIR, lptr +#define Av OP_DIR, v_mode +#define Ob OP_OFF, b_mode +#define Ov OP_OFF, v_mode +#define Xb OP_DSSI, b_mode +#define Xv OP_DSSI, v_mode +#define Yb OP_ESDI, b_mode +#define Yv OP_ESDI, v_mode + +#define es OP_REG, es_reg +#define ss OP_REG, ss_reg +#define cs OP_REG, cs_reg +#define ds OP_REG, ds_reg +#define fs OP_REG, fs_reg +#define gs OP_REG, gs_reg + +int OP_E(), OP_indirE(), OP_G(), OP_I(), OP_sI(), OP_REG(); +int OP_J(), OP_SEG(); +int OP_DIR(), OP_OFF(), OP_DSSI(), OP_ESDI(), OP_ONE(), OP_C(); +int OP_D(), OP_T(), OP_rm(); + +static void dofloat (), putop (), append_prefix (), set_op (); +static int get16 (), get32 (); + +#define b_mode 1 +#define v_mode 2 +#define w_mode 3 +#define d_mode 4 + +#define es_reg 100 +#define cs_reg 101 +#define ss_reg 102 +#define ds_reg 103 +#define fs_reg 104 +#define gs_reg 105 +#define eAX_reg 107 +#define eCX_reg 108 +#define eDX_reg 109 +#define eBX_reg 110 +#define eSP_reg 111 +#define eBP_reg 112 +#define eSI_reg 113 +#define eDI_reg 114 + +#define lptr 115 + +#define al_reg 116 +#define cl_reg 117 +#define dl_reg 118 +#define bl_reg 119 +#define ah_reg 120 +#define ch_reg 121 +#define dh_reg 122 +#define bh_reg 123 + +#define ax_reg 124 +#define cx_reg 125 +#define dx_reg 126 +#define bx_reg 127 +#define sp_reg 128 +#define bp_reg 129 +#define si_reg 130 +#define di_reg 131 + +#define indir_dx_reg 150 + +#define GRP1b NULL, NULL, 0 +#define GRP1S NULL, NULL, 1 +#define GRP1Ss NULL, NULL, 2 +#define GRP2b NULL, NULL, 3 +#define GRP2S NULL, NULL, 4 +#define GRP2b_one NULL, NULL, 5 +#define GRP2S_one NULL, NULL, 6 +#define GRP2b_cl NULL, NULL, 7 +#define GRP2S_cl NULL, NULL, 8 +#define GRP3b NULL, NULL, 9 +#define GRP3S NULL, NULL, 10 +#define GRP4 NULL, NULL, 11 +#define GRP5 NULL, NULL, 12 +#define GRP6 NULL, NULL, 13 +#define GRP7 NULL, NULL, 14 +#define GRP8 NULL, NULL, 15 +#define GRP9 NULL, NULL, 16 + +#define FLOATCODE 50 +#define FLOAT NULL, NULL, FLOATCODE + +struct dis386 { + char *name; + int (*op1)(); + int bytemode1; + int (*op2)(); + int bytemode2; + int (*op3)(); + int bytemode3; +}; + +struct dis386 dis386[] = { + /* 00 */ + { "addb", Eb, Gb }, + { "addS", Ev, Gv }, + { "addb", Gb, Eb }, + { "addS", Gv, Ev }, + { "addb", AL, Ib }, + { "addS", eAX, Iv }, + { "pushl", es }, + { "popl", es }, + /* 08 */ + { "orb", Eb, Gb }, + { "orS", Ev, Gv }, + { "orb", Gb, Eb }, + { "orS", Gv, Ev }, + { "orb", AL, Ib }, + { "orS", eAX, Iv }, + { "pushl", cs }, + { "(bad)" }, /* 0x0f extended opcode escape */ + /* 10 */ + { "adcb", Eb, Gb }, + { "adcS", Ev, Gv }, + { "adcb", Gb, Eb }, + { "adcS", Gv, Ev }, + { "adcb", AL, Ib }, + { "adcS", eAX, Iv }, + { "pushl", ss }, + { "popl", ss }, + /* 18 */ + { "sbbb", Eb, Gb }, + { "sbbS", Ev, Gv }, + { "sbbb", Gb, Eb }, + { "sbbS", Gv, Ev }, + { "sbbb", AL, Ib }, + { "sbbS", eAX, Iv }, + { "pushl", ds }, + { "popl", ds }, + /* 20 */ + { "andb", Eb, Gb }, + { "andS", Ev, Gv }, + { "andb", Gb, Eb }, + { "andS", Gv, Ev }, + { "andb", AL, Ib }, + { "andS", eAX, Iv }, + { "(bad)" }, /* SEG ES prefix */ + { "daa" }, + /* 28 */ + { "subb", Eb, Gb }, + { "subS", Ev, Gv }, + { "subb", Gb, Eb }, + { "subS", Gv, Ev }, + { "subb", AL, Ib }, + { "subS", eAX, Iv }, + { "(bad)" }, /* SEG CS prefix */ + { "das" }, + /* 30 */ + { "xorb", Eb, Gb }, + { "xorS", Ev, Gv }, + { "xorb", Gb, Eb }, + { "xorS", Gv, Ev }, + { "xorb", AL, Ib }, + { "xorS", eAX, Iv }, + { "(bad)" }, /* SEG SS prefix */ + { "aaa" }, + /* 38 */ + { "cmpb", Eb, Gb }, + { "cmpS", Ev, Gv }, + { "cmpb", Gb, Eb }, + { "cmpS", Gv, Ev }, + { "cmpb", AL, Ib }, + { "cmpS", eAX, Iv }, + { "(bad)" }, /* SEG DS prefix */ + { "aas" }, + /* 40 */ + { "incS", eAX }, + { "incS", eCX }, + { "incS", eDX }, + { "incS", eBX }, + { "incS", eSP }, + { "incS", eBP }, + { "incS", eSI }, + { "incS", eDI }, + /* 48 */ + { "decS", eAX }, + { "decS", eCX }, + { "decS", eDX }, + { "decS", eBX }, + { "decS", eSP }, + { "decS", eBP }, + { "decS", eSI }, + { "decS", eDI }, + /* 50 */ + { "pushS", eAX }, + { "pushS", eCX }, + { "pushS", eDX }, + { "pushS", eBX }, + { "pushS", eSP }, + { "pushS", eBP }, + { "pushS", eSI }, + { "pushS", eDI }, + /* 58 */ + { "popS", eAX }, + { "popS", eCX }, + { "popS", eDX }, + { "popS", eBX }, + { "popS", eSP }, + { "popS", eBP }, + { "popS", eSI }, + { "popS", eDI }, + /* 60 */ + { "pusha" }, + { "popa" }, + { "boundS", Gv, Ma }, + { "arpl", Ew, Gw }, + { "(bad)" }, /* seg fs */ + { "(bad)" }, /* seg gs */ + { "(bad)" }, /* op size prefix */ + { "(bad)" }, /* adr size prefix */ + /* 68 */ + { "pushS", Iv }, /* 386 book wrong */ + { "imulS", Gv, Ev, Iv }, + { "pushl", sIb }, /* push of byte really pushes 4 bytes */ + { "imulS", Gv, Ev, Ib }, + { "insb", Yb, indirDX }, + { "insS", Yv, indirDX }, + { "outsb", indirDX, Xb }, + { "outsS", indirDX, Xv }, + /* 70 */ + { "jo", Jb }, + { "jno", Jb }, + { "jb", Jb }, + { "jae", Jb }, + { "je", Jb }, + { "jne", Jb }, + { "jbe", Jb }, + { "ja", Jb }, + /* 78 */ + { "js", Jb }, + { "jns", Jb }, + { "jp", Jb }, + { "jnp", Jb }, + { "jl", Jb }, + { "jnl", Jb }, + { "jle", Jb }, + { "jg", Jb }, + /* 80 */ + { GRP1b }, + { GRP1S }, + { "(bad)" }, + { GRP1Ss }, + { "testb", Eb, Gb }, + { "testS", Ev, Gv }, + { "xchgb", Eb, Gb }, + { "xchgS", Ev, Gv }, + /* 88 */ + { "movb", Eb, Gb }, + { "movS", Ev, Gv }, + { "movb", Gb, Eb }, + { "movS", Gv, Ev }, + { "movw", Ew, Sw }, + { "leaS", Gv, M }, + { "movw", Sw, Ew }, + { "popS", Ev }, + /* 90 */ + { "nop" }, + { "xchgS", eCX, eAX }, + { "xchgS", eDX, eAX }, + { "xchgS", eBX, eAX }, + { "xchgS", eSP, eAX }, + { "xchgS", eBP, eAX }, + { "xchgS", eSI, eAX }, + { "xchgS", eDI, eAX }, + /* 98 */ + { "cwtl" }, + { "cltd" }, + { "lcall", Ap }, + { "(bad)" }, /* fwait */ + { "pushf" }, + { "popf" }, + { "sahf" }, + { "lahf" }, + /* a0 */ + { "movb", AL, Ob }, + { "movS", eAX, Ov }, + { "movb", Ob, AL }, + { "movS", Ov, eAX }, + { "movsb", Yb, Xb }, + { "movsS", Yv, Xv }, + { "cmpsb", Yb, Xb }, + { "cmpsS", Yv, Xv }, + /* a8 */ + { "testb", AL, Ib }, + { "testS", eAX, Iv }, + { "stosb", Yb, AL }, + { "stosS", Yv, eAX }, + { "lodsb", AL, Xb }, + { "lodsS", eAX, Xv }, + { "scasb", AL, Yb }, + { "scasS", eAX, Yv }, + /* b0 */ + { "movb", AL, Ib }, + { "movb", CL, Ib }, + { "movb", DL, Ib }, + { "movb", BL, Ib }, + { "movb", AH, Ib }, + { "movb", CH, Ib }, + { "movb", DH, Ib }, + { "movb", BH, Ib }, + /* b8 */ + { "movS", eAX, Iv }, + { "movS", eCX, Iv }, + { "movS", eDX, Iv }, + { "movS", eBX, Iv }, + { "movS", eSP, Iv }, + { "movS", eBP, Iv }, + { "movS", eSI, Iv }, + { "movS", eDI, Iv }, + /* c0 */ + { GRP2b }, + { GRP2S }, + { "ret", Iw }, + { "ret" }, + { "lesS", Gv, Mp }, + { "ldsS", Gv, Mp }, + { "movb", Eb, Ib }, + { "movS", Ev, Iv }, + /* c8 */ + { "enter", Iw, Ib }, + { "leave" }, + { "lret", Iw }, + { "lret" }, + { "int3" }, + { "int", Ib }, + { "into" }, + { "iret" }, + /* d0 */ + { GRP2b_one }, + { GRP2S_one }, + { GRP2b_cl }, + { GRP2S_cl }, + { "aam", Ib }, + { "aad", Ib }, + { "(bad)" }, + { "xlat" }, + /* d8 */ + { FLOAT }, + { FLOAT }, + { FLOAT }, + { FLOAT }, + { FLOAT }, + { FLOAT }, + { FLOAT }, + { FLOAT }, + /* e0 */ + { "loopne", Jb }, + { "loope", Jb }, + { "loop", Jb }, + { "jCcxz", Jb }, + { "inb", AL, Ib }, + { "inS", eAX, Ib }, + { "outb", Ib, AL }, + { "outS", Ib, eAX }, + /* e8 */ + { "call", Av }, + { "jmp", Jv }, + { "ljmp", Ap }, + { "jmp", Jb }, + { "inb", AL, indirDX }, + { "inS", eAX, indirDX }, + { "outb", indirDX, AL }, + { "outS", indirDX, eAX }, + /* f0 */ + { "(bad)" }, /* lock prefix */ + { "(bad)" }, + { "(bad)" }, /* repne */ + { "(bad)" }, /* repz */ + { "hlt" }, + { "cmc" }, + { GRP3b }, + { GRP3S }, + /* f8 */ + { "clc" }, + { "stc" }, + { "cli" }, + { "sti" }, + { "cld" }, + { "std" }, + { GRP4 }, + { GRP5 }, +}; + +struct dis386 dis386_twobyte[] = { + /* 00 */ + { GRP6 }, + { GRP7 }, + { "larS", Gv, Ew }, + { "lslS", Gv, Ew }, + { "(bad)" }, + { "(bad)" }, + { "clts" }, + { "(bad)" }, + /* 08 */ + { "invd" }, + { "wbinvd" }, + { "(bad)" }, { "ud2a" }, + { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, + /* 10 */ + { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, + { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, + /* 18 */ + { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, + { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, + /* 20 */ + /* these are all backward in appendix A of the intel book */ + { "movl", Rd, Cd }, + { "movl", Rd, Dd }, + { "movl", Cd, Rd }, + { "movl", Dd, Rd }, + { "movl", Rd, Td }, + { "(bad)" }, + { "movl", Td, Rd }, + { "(bad)" }, + /* 28 */ + { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, + { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, + /* 30 */ + { "wrmsr" }, { "rdtsc" }, { "rdmsr" }, { "rdpmc" }, + { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, + /* 38 */ + { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, + { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, + /* 40 */ + { "cmovo", Gv,Ev }, { "cmovno", Gv,Ev }, { "cmovb", Gv,Ev }, { "cmovae", Gv,Ev }, + { "cmove", Gv,Ev }, { "cmovne", Gv,Ev }, { "cmovbe", Gv,Ev }, { "cmova", Gv,Ev }, + /* 48 */ + { "cmovs", Gv,Ev }, { "cmovns", Gv,Ev }, { "cmovp", Gv,Ev }, { "cmovnp", Gv,Ev }, + { "cmovl", Gv,Ev }, { "cmovge", Gv,Ev }, { "cmovle", Gv,Ev }, { "cmovg", Gv,Ev }, + /* 50 */ + { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, + { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, + /* 58 */ + { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, + { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, + /* 60 */ + { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, + { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, + /* 68 */ + { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, + { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, + /* 70 */ + { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, + { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, + /* 78 */ + { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, + { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, + /* 80 */ + { "jo", Jv }, + { "jno", Jv }, + { "jb", Jv }, + { "jae", Jv }, + { "je", Jv }, + { "jne", Jv }, + { "jbe", Jv }, + { "ja", Jv }, + /* 88 */ + { "js", Jv }, + { "jns", Jv }, + { "jp", Jv }, + { "jnp", Jv }, + { "jl", Jv }, + { "jge", Jv }, + { "jle", Jv }, + { "jg", Jv }, + /* 90 */ + { "seto", Eb }, + { "setno", Eb }, + { "setb", Eb }, + { "setae", Eb }, + { "sete", Eb }, + { "setne", Eb }, + { "setbe", Eb }, + { "seta", Eb }, + /* 98 */ + { "sets", Eb }, + { "setns", Eb }, + { "setp", Eb }, + { "setnp", Eb }, + { "setl", Eb }, + { "setge", Eb }, + { "setle", Eb }, + { "setg", Eb }, + /* a0 */ + { "pushl", fs }, + { "popl", fs }, + { "cpuid" }, + { "btS", Ev, Gv }, + { "shldS", Ev, Gv, Ib }, + { "shldS", Ev, Gv, CL }, + { "(bad)" }, + { "(bad)" }, + /* a8 */ + { "pushl", gs }, + { "popl", gs }, + { "rsm" }, + { "btsS", Ev, Gv }, + { "shrdS", Ev, Gv, Ib }, + { "shrdS", Ev, Gv, CL }, + { "(bad)" }, + { "imulS", Gv, Ev }, + /* b0 */ + { "cmpxchgb", Eb, Gb }, + { "cmpxchgS", Ev, Gv }, + { "lssS", Gv, Mp }, /* 386 lists only Mp */ + { "btrS", Ev, Gv }, + { "lfsS", Gv, Mp }, /* 386 lists only Mp */ + { "lgsS", Gv, Mp }, /* 386 lists only Mp */ + { "movzbS", Gv, Eb }, + { "movzwS", Gv, Ew }, + /* b8 */ + { "ud2b" }, + { "(bad)" }, + { GRP8 }, + { "btcS", Ev, Gv }, + { "bsfS", Gv, Ev }, + { "bsrS", Gv, Ev }, + { "movsbS", Gv, Eb }, + { "movswS", Gv, Ew }, + /* c0 */ + { "xaddb", Eb, Gb }, + { "xaddS", Ev, Gv }, + { "(bad)" }, + { "(bad)" }, + { "(bad)" }, + { "(bad)" }, + { "(bad)" }, + { GRP9 }, + /* c8 */ + { "bswap", eAX }, + { "bswap", eCX }, + { "bswap", eDX }, + { "bswap", eBX }, + { "bswap", eSP }, + { "bswap", eBP }, + { "bswap", eSI }, + { "bswap", eDI }, + /* d0 */ + { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, + { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, + /* d8 */ + { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, + { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, + /* e0 */ + { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, + { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, + /* e8 */ + { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, + { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, + /* f0 */ + { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, + { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, + /* f8 */ + { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, + { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, +}; + +static const unsigned char onebyte_has_modrm[256] = { + 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, + 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, + 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, + 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,1,1,0,0,0,0,0,1,0,1,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0, + 1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1 +}; + +static const unsigned char twobyte_has_modrm[256] = { + 1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,1,1,1,1,1,0,0,0,1,1,1,1,1, + 1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +}; + +static char obuf[100]; +static char *obufp; +static char scratchbuf[100]; +static unsigned char *start_codep; +static unsigned char *codep; +static disassemble_info *the_info; +static int mod; +static int rm; +static int reg; +static void oappend (); + +static char *names32[]={ + "%eax","%ecx","%edx","%ebx", "%esp","%ebp","%esi","%edi", +}; +static char *names16[] = { + "%ax","%cx","%dx","%bx","%sp","%bp","%si","%di", +}; +static char *names8[] = { + "%al","%cl","%dl","%bl","%ah","%ch","%dh","%bh", +}; +static char *names_seg[] = { + "%es","%cs","%ss","%ds","%fs","%gs","%?","%?", +}; +static char *index16[] = { + "bx+si","bx+di","bp+si","bp+di","si","di","bp","bx" +}; + +struct dis386 grps[][8] = { + /* GRP1b */ + { + { "addb", Eb, Ib }, + { "orb", Eb, Ib }, + { "adcb", Eb, Ib }, + { "sbbb", Eb, Ib }, + { "andb", Eb, Ib }, + { "subb", Eb, Ib }, + { "xorb", Eb, Ib }, + { "cmpb", Eb, Ib } + }, + /* GRP1S */ + { + { "addS", Ev, Iv }, + { "orS", Ev, Iv }, + { "adcS", Ev, Iv }, + { "sbbS", Ev, Iv }, + { "andS", Ev, Iv }, + { "subS", Ev, Iv }, + { "xorS", Ev, Iv }, + { "cmpS", Ev, Iv } + }, + /* GRP1Ss */ + { + { "addS", Ev, sIb }, + { "orS", Ev, sIb }, + { "adcS", Ev, sIb }, + { "sbbS", Ev, sIb }, + { "andS", Ev, sIb }, + { "subS", Ev, sIb }, + { "xorS", Ev, sIb }, + { "cmpS", Ev, sIb } + }, + /* GRP2b */ + { + { "rolb", Eb, Ib }, + { "rorb", Eb, Ib }, + { "rclb", Eb, Ib }, + { "rcrb", Eb, Ib }, + { "shlb", Eb, Ib }, + { "shrb", Eb, Ib }, + { "(bad)" }, + { "sarb", Eb, Ib }, + }, + /* GRP2S */ + { + { "rolS", Ev, Ib }, + { "rorS", Ev, Ib }, + { "rclS", Ev, Ib }, + { "rcrS", Ev, Ib }, + { "shlS", Ev, Ib }, + { "shrS", Ev, Ib }, + { "(bad)" }, + { "sarS", Ev, Ib }, + }, + /* GRP2b_one */ + { + { "rolb", Eb }, + { "rorb", Eb }, + { "rclb", Eb }, + { "rcrb", Eb }, + { "shlb", Eb }, + { "shrb", Eb }, + { "(bad)" }, + { "sarb", Eb }, + }, + /* GRP2S_one */ + { + { "rolS", Ev }, + { "rorS", Ev }, + { "rclS", Ev }, + { "rcrS", Ev }, + { "shlS", Ev }, + { "shrS", Ev }, + { "(bad)" }, + { "sarS", Ev }, + }, + /* GRP2b_cl */ + { + { "rolb", Eb, CL }, + { "rorb", Eb, CL }, + { "rclb", Eb, CL }, + { "rcrb", Eb, CL }, + { "shlb", Eb, CL }, + { "shrb", Eb, CL }, + { "(bad)" }, + { "sarb", Eb, CL }, + }, + /* GRP2S_cl */ + { + { "rolS", Ev, CL }, + { "rorS", Ev, CL }, + { "rclS", Ev, CL }, + { "rcrS", Ev, CL }, + { "shlS", Ev, CL }, + { "shrS", Ev, CL }, + { "(bad)" }, + { "sarS", Ev, CL } + }, + /* GRP3b */ + { + { "testb", Eb, Ib }, + { "(bad)", Eb }, + { "notb", Eb }, + { "negb", Eb }, + { "mulb", AL, Eb }, + { "imulb", AL, Eb }, + { "divb", AL, Eb }, + { "idivb", AL, Eb } + }, + /* GRP3S */ + { + { "testS", Ev, Iv }, + { "(bad)" }, + { "notS", Ev }, + { "negS", Ev }, + { "mulS", eAX, Ev }, + { "imulS", eAX, Ev }, + { "divS", eAX, Ev }, + { "idivS", eAX, Ev }, + }, + /* GRP4 */ + { + { "incb", Eb }, + { "decb", Eb }, + { "(bad)" }, + { "(bad)" }, + { "(bad)" }, + { "(bad)" }, + { "(bad)" }, + { "(bad)" }, + }, + /* GRP5 */ + { + { "incS", Ev }, + { "decS", Ev }, + { "call", indirEv }, + { "lcall", indirEv }, + { "jmp", indirEv }, + { "ljmp", indirEv }, + { "pushS", Ev }, + { "(bad)" }, + }, + /* GRP6 */ + { + { "sldt", Ew }, + { "str", Ew }, + { "lldt", Ew }, + { "ltr", Ew }, + { "verr", Ew }, + { "verw", Ew }, + { "(bad)" }, + { "(bad)" } + }, + /* GRP7 */ + { + { "sgdt", Ew }, + { "sidt", Ew }, + { "lgdt", Ew }, + { "lidt", Ew }, + { "smsw", Ew }, + { "(bad)" }, + { "lmsw", Ew }, + { "invlpg", Ew }, + }, + /* GRP8 */ + { + { "(bad)" }, + { "(bad)" }, + { "(bad)" }, + { "(bad)" }, + { "btS", Ev, Ib }, + { "btsS", Ev, Ib }, + { "btrS", Ev, Ib }, + { "btcS", Ev, Ib }, + }, + /* GRP9 */ + { + { "(bad)" }, + { "cmpxchg8b", Ev }, + { "(bad)" }, + { "(bad)" }, + { "(bad)" }, + { "(bad)" }, + { "(bad)" }, + { "(bad)" }, + } +}; + +#define PREFIX_REPZ 1 +#define PREFIX_REPNZ 2 +#define PREFIX_LOCK 4 +#define PREFIX_CS 8 +#define PREFIX_SS 0x10 +#define PREFIX_DS 0x20 +#define PREFIX_ES 0x40 +#define PREFIX_FS 0x80 +#define PREFIX_GS 0x100 +#define PREFIX_DATA 0x200 +#define PREFIX_ADR 0x400 +#define PREFIX_FWAIT 0x800 + +static int prefixes; + +static void +ckprefix () +{ + prefixes = 0; + while (1) + { + FETCH_DATA (the_info, codep + 1); + switch (*codep) + { + case 0xf3: + prefixes |= PREFIX_REPZ; + break; + case 0xf2: + prefixes |= PREFIX_REPNZ; + break; + case 0xf0: + prefixes |= PREFIX_LOCK; + break; + case 0x2e: + prefixes |= PREFIX_CS; + break; + case 0x36: + prefixes |= PREFIX_SS; + break; + case 0x3e: + prefixes |= PREFIX_DS; + break; + case 0x26: + prefixes |= PREFIX_ES; + break; + case 0x64: + prefixes |= PREFIX_FS; + break; + case 0x65: + prefixes |= PREFIX_GS; + break; + case 0x66: + prefixes |= PREFIX_DATA; + break; + case 0x67: + prefixes |= PREFIX_ADR; + break; + case 0x9b: + prefixes |= PREFIX_FWAIT; + break; + default: + return; + } + codep++; + } +} + +static int dflag; +static int aflag; + +static char op1out[100], op2out[100], op3out[100]; +static int op_address[3], op_ad, op_index[3]; +static int start_pc; + + +/* + * On the 386's of 1988, the maximum length of an instruction is 15 bytes. + * (see topic "Redundant prefixes" in the "Differences from 8086" + * section of the "Virtual 8086 Mode" chapter.) + * 'pc' should be the address of this instruction, it will + * be used to print the target address if this is a relative jump or call + * The function returns the length of this instruction in bytes. + */ + +int +print_insn_i386 (pc, info) + bfd_vma pc; + disassemble_info *info; +{ + struct dis386 *dp; + int i; + int enter_instruction; + char *first, *second, *third; + int needcomma; + unsigned char need_modrm; + + struct dis_private priv; + bfd_byte *inbuf = priv.the_buffer; + + info->private_data = (PTR) &priv; + priv.max_fetched = priv.the_buffer; + priv.insn_start = pc; + if (setjmp (priv.bailout) != 0) + /* Error return. */ + return -1; + + obuf[0] = 0; + op1out[0] = 0; + op2out[0] = 0; + op3out[0] = 0; + + op_index[0] = op_index[1] = op_index[2] = -1; + + the_info = info; + start_pc = pc; + start_codep = inbuf; + codep = inbuf; + + ckprefix (); + + FETCH_DATA (info, codep + 1); + if (*codep == 0xc8) + enter_instruction = 1; + else + enter_instruction = 0; + + obufp = obuf; + + if (prefixes & PREFIX_REPZ) + oappend ("repz "); + if (prefixes & PREFIX_REPNZ) + oappend ("repnz "); + if (prefixes & PREFIX_LOCK) + oappend ("lock "); + + if ((prefixes & PREFIX_FWAIT) + && ((*codep < 0xd8) || (*codep > 0xdf))) + { + /* fwait not followed by floating point instruction */ + (*info->fprintf_func) (info->stream, "fwait"); + return (1); + } + + /* these would be initialized to 0 if disassembling for 8086 or 286 */ + dflag = 1; + aflag = 1; + + if (prefixes & PREFIX_DATA) + dflag ^= 1; + + if (prefixes & PREFIX_ADR) + { + aflag ^= 1; + oappend ("addr16 "); + } + + if (*codep == 0x0f) + { + FETCH_DATA (info, codep + 2); + dp = &dis386_twobyte[*++codep]; + need_modrm = twobyte_has_modrm[*codep]; + } + else + { + dp = &dis386[*codep]; + need_modrm = onebyte_has_modrm[*codep]; + } + codep++; + + if (need_modrm) + { + FETCH_DATA (info, codep + 1); + mod = (*codep >> 6) & 3; + reg = (*codep >> 3) & 7; + rm = *codep & 7; + } + + if (dp->name == NULL && dp->bytemode1 == FLOATCODE) + { + dofloat (); + } + else + { + if (dp->name == NULL) + dp = &grps[dp->bytemode1][reg]; + + putop (dp->name); + + obufp = op1out; + op_ad = 2; + if (dp->op1) + (*dp->op1)(dp->bytemode1); + + obufp = op2out; + op_ad = 1; + if (dp->op2) + (*dp->op2)(dp->bytemode2); + + obufp = op3out; + op_ad = 0; + if (dp->op3) + (*dp->op3)(dp->bytemode3); + } + + obufp = obuf + strlen (obuf); + for (i = strlen (obuf); i < 6; i++) + oappend (" "); + oappend (" "); + (*info->fprintf_func) (info->stream, "%s", obuf); + + /* enter instruction is printed with operands in the + * same order as the intel book; everything else + * is printed in reverse order + */ + if (enter_instruction) + { + first = op1out; + second = op2out; + third = op3out; + op_ad = op_index[0]; + op_index[0] = op_index[2]; + op_index[2] = op_ad; + } + else + { + first = op3out; + second = op2out; + third = op1out; + } + needcomma = 0; + if (*first) + { + if (op_index[0] != -1) + (*info->print_address_func) (op_address[op_index[0]], info); + else + (*info->fprintf_func) (info->stream, "%s", first); + needcomma = 1; + } + if (*second) + { + if (needcomma) + (*info->fprintf_func) (info->stream, ","); + if (op_index[1] != -1) + (*info->print_address_func) (op_address[op_index[1]], info); + else + (*info->fprintf_func) (info->stream, "%s", second); + needcomma = 1; + } + if (*third) + { + if (needcomma) + (*info->fprintf_func) (info->stream, ","); + if (op_index[2] != -1) + (*info->print_address_func) (op_address[op_index[2]], info); + else + (*info->fprintf_func) (info->stream, "%s", third); + } + return (codep - inbuf); +} + +char *float_mem[] = { + /* d8 */ + "fadds", + "fmuls", + "fcoms", + "fcomps", + "fsubs", + "fsubrs", + "fdivs", + "fdivrs", + /* d9 */ + "flds", + "(bad)", + "fsts", + "fstps", + "fldenv", + "fldcw", + "fNstenv", + "fNstcw", + /* da */ + "fiaddl", + "fimull", + "ficoml", + "ficompl", + "fisubl", + "fisubrl", + "fidivl", + "fidivrl", + /* db */ + "fildl", + "(bad)", + "fistl", + "fistpl", + "(bad)", + "fldt", + "(bad)", + "fstpt", + /* dc */ + "faddl", + "fmull", + "fcoml", + "fcompl", + "fsubl", + "fsubrl", + "fdivl", + "fdivrl", + /* dd */ + "fldl", + "(bad)", + "fstl", + "fstpl", + "frstor", + "(bad)", + "fNsave", + "fNstsw", + /* de */ + "fiadd", + "fimul", + "ficom", + "ficomp", + "fisub", + "fisubr", + "fidiv", + "fidivr", + /* df */ + "fild", + "(bad)", + "fist", + "fistp", + "fbld", + "fildll", + "fbstp", + "fistpll", +}; + +#define ST OP_ST, 0 +#define STi OP_STi, 0 +int OP_ST(), OP_STi(); + +#define FGRPd9_2 NULL, NULL, 0 +#define FGRPd9_4 NULL, NULL, 1 +#define FGRPd9_5 NULL, NULL, 2 +#define FGRPd9_6 NULL, NULL, 3 +#define FGRPd9_7 NULL, NULL, 4 +#define FGRPda_5 NULL, NULL, 5 +#define FGRPdb_4 NULL, NULL, 6 +#define FGRPde_3 NULL, NULL, 7 +#define FGRPdf_4 NULL, NULL, 8 + +struct dis386 float_reg[][8] = { + /* d8 */ + { + { "fadd", ST, STi }, + { "fmul", ST, STi }, + { "fcom", STi }, + { "fcomp", STi }, + { "fsub", ST, STi }, + { "fsubr", ST, STi }, + { "fdiv", ST, STi }, + { "fdivr", ST, STi }, + }, + /* d9 */ + { + { "fld", STi }, + { "fxch", STi }, + { FGRPd9_2 }, + { "(bad)" }, + { FGRPd9_4 }, + { FGRPd9_5 }, + { FGRPd9_6 }, + { FGRPd9_7 }, + }, + /* da */ + { + { "fcmovb", ST, STi }, + { "fcmove", ST, STi }, + { "fcmovbe",ST, STi }, + { "fcmovu", ST, STi }, + { "(bad)" }, + { FGRPda_5 }, + { "(bad)" }, + { "(bad)" }, + }, + /* db */ + { + { "fcmovnb",ST, STi }, + { "fcmovne",ST, STi }, + { "fcmovnbe",ST, STi }, + { "fcmovnu",ST, STi }, + { FGRPdb_4 }, + { "fucomi", ST, STi }, + { "fcomi", ST, STi }, + { "(bad)" }, + }, + /* dc */ + { + { "fadd", STi, ST }, + { "fmul", STi, ST }, + { "(bad)" }, + { "(bad)" }, + { "fsub", STi, ST }, + { "fsubr", STi, ST }, + { "fdiv", STi, ST }, + { "fdivr", STi, ST }, + }, + /* dd */ + { + { "ffree", STi }, + { "(bad)" }, + { "fst", STi }, + { "fstp", STi }, + { "fucom", STi }, + { "fucomp", STi }, + { "(bad)" }, + { "(bad)" }, + }, + /* de */ + { + { "faddp", STi, ST }, + { "fmulp", STi, ST }, + { "(bad)" }, + { FGRPde_3 }, + { "fsubp", STi, ST }, + { "fsubrp", STi, ST }, + { "fdivp", STi, ST }, + { "fdivrp", STi, ST }, + }, + /* df */ + { + { "(bad)" }, + { "(bad)" }, + { "(bad)" }, + { "(bad)" }, + { FGRPdf_4 }, + { "fucomip",ST, STi }, + { "fcomip", ST, STi }, + { "(bad)" }, + }, +}; + + +char *fgrps[][8] = { + /* d9_2 0 */ + { + "fnop","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)", + }, + + /* d9_4 1 */ + { + "fchs","fabs","(bad)","(bad)","ftst","fxam","(bad)","(bad)", + }, + + /* d9_5 2 */ + { + "fld1","fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz","(bad)", + }, + + /* d9_6 3 */ + { + "f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp","fincstp", + }, + + /* d9_7 4 */ + { + "fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos", + }, + + /* da_5 5 */ + { + "(bad)","fucompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)", + }, + + /* db_4 6 */ + { + "feni(287 only)","fdisi(287 only)","fNclex","fNinit", + "fNsetpm(287 only)","(bad)","(bad)","(bad)", + }, + + /* de_3 7 */ + { + "(bad)","fcompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)", + }, + + /* df_4 8 */ + { + "fNstsw","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)", + }, +}; + +static void +dofloat () +{ + struct dis386 *dp; + unsigned char floatop; + + floatop = codep[-1]; + + if (mod != 3) + { + putop (float_mem[(floatop - 0xd8) * 8 + reg]); + obufp = op1out; + OP_E (v_mode); + return; + } + codep++; + + dp = &float_reg[floatop - 0xd8][reg]; + if (dp->name == NULL) + { + putop (fgrps[dp->bytemode1][rm]); + /* instruction fnstsw is only one with strange arg */ + if (floatop == 0xdf + && FETCH_DATA (the_info, codep + 1) + && *codep == 0xe0) + strcpy (op1out, "%eax"); + } + else + { + putop (dp->name); + obufp = op1out; + if (dp->op1) + (*dp->op1)(dp->bytemode1); + obufp = op2out; + if (dp->op2) + (*dp->op2)(dp->bytemode2); + } +} + +/* ARGSUSED */ +int +OP_ST (ignore) + int ignore; +{ + oappend ("%st"); + return (0); +} + +/* ARGSUSED */ +int +OP_STi (ignore) + int ignore; +{ + sprintf (scratchbuf, "%%st(%d)", rm); + oappend (scratchbuf); + return (0); +} + + +/* capital letters in template are macros */ +static void +putop (template) + char *template; +{ + char *p; + + for (p = template; *p; p++) + { + switch (*p) + { + default: + *obufp++ = *p; + break; + case 'C': /* For jcxz/jecxz */ + if (aflag) + *obufp++ = 'e'; + break; + case 'N': + if ((prefixes & PREFIX_FWAIT) == 0) + *obufp++ = 'n'; + break; + case 'S': + /* operand size flag */ + if (dflag) + *obufp++ = 'l'; + else + *obufp++ = 'w'; + break; + } + } + *obufp = 0; +} + +static void +oappend (s) + char *s; +{ + strcpy (obufp, s); + obufp += strlen (s); + *obufp = 0; +} + +static void +append_prefix () +{ + if (prefixes & PREFIX_CS) + oappend ("%cs:"); + if (prefixes & PREFIX_DS) + oappend ("%ds:"); + if (prefixes & PREFIX_SS) + oappend ("%ss:"); + if (prefixes & PREFIX_ES) + oappend ("%es:"); + if (prefixes & PREFIX_FS) + oappend ("%fs:"); + if (prefixes & PREFIX_GS) + oappend ("%gs:"); +} + +int +OP_indirE (bytemode) + int bytemode; +{ + oappend ("*"); + return OP_E (bytemode); +} + +int +OP_E (bytemode) + int bytemode; +{ + int disp; + + /* skip mod/rm byte */ + codep++; + + if (mod == 3) + { + switch (bytemode) + { + case b_mode: + oappend (names8[rm]); + break; + case w_mode: + oappend (names16[rm]); + break; + case v_mode: + if (dflag) + oappend (names32[rm]); + else + oappend (names16[rm]); + break; + default: + oappend (""); + break; + } + return 0; + } + + disp = 0; + append_prefix (); + + if (aflag) /* 32 bit address mode */ + { + int havesib; + int havebase; + int base; + int index; + int scale; + + havesib = 0; + havebase = 1; + base = rm; + + if (base == 4) + { + havesib = 1; + FETCH_DATA (the_info, codep + 1); + scale = (*codep >> 6) & 3; + index = (*codep >> 3) & 7; + base = *codep & 7; + codep++; + } + + switch (mod) + { + case 0: + if (base == 5) + { + havebase = 0; + disp = get32 (); + } + break; + case 1: + FETCH_DATA (the_info, codep + 1); + disp = *(char *)codep++; + break; + case 2: + disp = get32 (); + break; + } + + if (mod != 0 || base == 5) + { + sprintf (scratchbuf, "0x%x", disp); + oappend (scratchbuf); + } + + if (havebase || (havesib && (index != 4 || scale != 0))) + { + oappend ("("); + if (havebase) + oappend (names32[base]); + if (havesib) + { + if (index != 4) + { + sprintf (scratchbuf, ",%s", names32[index]); + oappend (scratchbuf); + } + sprintf (scratchbuf, ",%d", 1 << scale); + oappend (scratchbuf); + } + oappend (")"); + } + } + else + { /* 16 bit address mode */ + switch (mod) + { + case 0: + if (rm == 6) + disp = (short) get16 (); + break; + case 1: + FETCH_DATA (the_info, codep + 1); + disp = *(char *)codep++; + break; + case 2: + disp = (short) get16 (); + break; + } + + if (mod != 0 || rm == 6) + { + sprintf (scratchbuf, "0x%x", disp); + oappend (scratchbuf); + } + + if (mod != 0 || rm != 6) + { + oappend ("("); + oappend (index16[rm]); + oappend (")"); + } + } + return 0; +} + +int +OP_G (bytemode) + int bytemode; +{ + switch (bytemode) + { + case b_mode: + oappend (names8[reg]); + break; + case w_mode: + oappend (names16[reg]); + break; + case d_mode: + oappend (names32[reg]); + break; + case v_mode: + if (dflag) + oappend (names32[reg]); + else + oappend (names16[reg]); + break; + default: + oappend (""); + break; + } + return (0); +} + +static int +get32 () +{ + int x = 0; + + FETCH_DATA (the_info, codep + 4); + x = *codep++ & 0xff; + x |= (*codep++ & 0xff) << 8; + x |= (*codep++ & 0xff) << 16; + x |= (*codep++ & 0xff) << 24; + return (x); +} + +static int +get16 () +{ + int x = 0; + + FETCH_DATA (the_info, codep + 2); + x = *codep++ & 0xff; + x |= (*codep++ & 0xff) << 8; + return (x); +} + +static void +set_op (op) + int op; +{ + op_index[op_ad] = op_ad; + op_address[op_ad] = op; +} + +int +OP_REG (code) + int code; +{ + char *s; + + switch (code) + { + case indir_dx_reg: s = "(%dx)"; break; + case ax_reg: case cx_reg: case dx_reg: case bx_reg: + case sp_reg: case bp_reg: case si_reg: case di_reg: + s = names16[code - ax_reg]; + break; + case es_reg: case ss_reg: case cs_reg: + case ds_reg: case fs_reg: case gs_reg: + s = names_seg[code - es_reg]; + break; + case al_reg: case ah_reg: case cl_reg: case ch_reg: + case dl_reg: case dh_reg: case bl_reg: case bh_reg: + s = names8[code - al_reg]; + break; + case eAX_reg: case eCX_reg: case eDX_reg: case eBX_reg: + case eSP_reg: case eBP_reg: case eSI_reg: case eDI_reg: + if (dflag) + s = names32[code - eAX_reg]; + else + s = names16[code - eAX_reg]; + break; + default: + s = ""; + break; + } + oappend (s); + return (0); +} + +int +OP_I (bytemode) + int bytemode; +{ + int op; + + switch (bytemode) + { + case b_mode: + FETCH_DATA (the_info, codep + 1); + op = *codep++ & 0xff; + break; + case v_mode: + if (dflag) + op = get32 (); + else + op = get16 (); + break; + case w_mode: + op = get16 (); + break; + default: + oappend (""); + return (0); + } + sprintf (scratchbuf, "$0x%x", op); + oappend (scratchbuf); + return (0); +} + +int +OP_sI (bytemode) + int bytemode; +{ + int op; + + switch (bytemode) + { + case b_mode: + FETCH_DATA (the_info, codep + 1); + op = *(char *)codep++; + break; + case v_mode: + if (dflag) + op = get32 (); + else + op = (short)get16(); + break; + case w_mode: + op = (short)get16 (); + break; + default: + oappend (""); + return (0); + } + sprintf (scratchbuf, "$0x%x", op); + oappend (scratchbuf); + return (0); +} + +int +OP_J (bytemode) + int bytemode; +{ + int disp; + int mask = -1; + + switch (bytemode) + { + case b_mode: + FETCH_DATA (the_info, codep + 1); + disp = *(char *)codep++; + break; + case v_mode: + if (dflag) + disp = get32 (); + else + { + disp = (short)get16 (); + /* for some reason, a data16 prefix on a jump instruction + means that the pc is masked to 16 bits after the + displacement is added! */ + mask = 0xffff; + } + break; + default: + oappend (""); + return (0); + } + disp = (start_pc + codep - start_codep + disp) & mask; + set_op (disp); + sprintf (scratchbuf, "0x%x", disp); + oappend (scratchbuf); + return (0); +} + +/* ARGSUSED */ +int +OP_SEG (dummy) + int dummy; +{ + static char *sreg[] = { + "%es","%cs","%ss","%ds","%fs","%gs","%?","%?", + }; + + oappend (sreg[reg]); + return (0); +} + +int +OP_DIR (size) + int size; +{ + int seg, offset; + + switch (size) + { + case lptr: + if (aflag) + { + offset = get32 (); + seg = get16 (); + } + else + { + offset = get16 (); + seg = get16 (); + } + sprintf (scratchbuf, "0x%x,0x%x", seg, offset); + oappend (scratchbuf); + break; + case v_mode: + if (aflag) + offset = get32 (); + else + offset = (short)get16 (); + + offset = start_pc + codep - start_codep + offset; + set_op (offset); + sprintf (scratchbuf, "0x%x", offset); + oappend (scratchbuf); + break; + default: + oappend (""); + break; + } + return (0); +} + +/* ARGSUSED */ +int +OP_OFF (bytemode) + int bytemode; +{ + int off; + + if (aflag) + off = get32 (); + else + off = get16 (); + + sprintf (scratchbuf, "0x%x", off); + oappend (scratchbuf); + return (0); +} + +/* ARGSUSED */ +int +OP_ESDI (dummy) + int dummy; +{ + oappend ("%es:("); + oappend (aflag ? "%edi" : "%di"); + oappend (")"); + return (0); +} + +/* ARGSUSED */ +int +OP_DSSI (dummy) + int dummy; +{ + oappend ("%ds:("); + oappend (aflag ? "%esi" : "%si"); + oappend (")"); + return (0); +} + +/* ARGSUSED */ +int +OP_ONE (dummy) + int dummy; +{ + oappend ("1"); + return (0); +} + +/* ARGSUSED */ +int +OP_C (dummy) + int dummy; +{ + codep++; /* skip mod/rm */ + sprintf (scratchbuf, "%%cr%d", reg); + oappend (scratchbuf); + return (0); +} + +/* ARGSUSED */ +int +OP_D (dummy) + int dummy; +{ + codep++; /* skip mod/rm */ + sprintf (scratchbuf, "%%db%d", reg); + oappend (scratchbuf); + return (0); +} + +/* ARGSUSED */ +int +OP_T (dummy) + int dummy; +{ + codep++; /* skip mod/rm */ + sprintf (scratchbuf, "%%tr%d", reg); + oappend (scratchbuf); + return (0); +} + +int +OP_rm (bytemode) + int bytemode; +{ + switch (bytemode) + { + case d_mode: + oappend (names32[rm]); + break; + case w_mode: + oappend (names16[rm]); + break; + } + return (0); +} diff --git a/opcode/i386.h b/opcode/i386.h new file mode 100644 index 000000000..849a86fa7 --- /dev/null +++ b/opcode/i386.h @@ -0,0 +1,898 @@ +/* i386-opcode.h -- Intel 80386 opcode table + Copyright 1989, 1991, 1992, 1995 Free Software Foundation. + +This file is part of GAS, the GNU Assembler, and GDB, the GNU Debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +static const template i386_optab[] = { + +#define _ None +/* move instructions */ +#define MOV_AX_DISP32 0xa0 +{ "mov", 2, 0xa0, _, DW|NoModrm, { Disp32, Acc, 0 } }, +{ "mov", 2, 0x88, _, DW|Modrm, { Reg, Reg|Mem, 0 } }, +{ "mov", 2, 0xb0, _, ShortFormW, { Imm, Reg, 0 } }, +{ "mov", 2, 0xc6, _, W|Modrm, { Imm, Reg|Mem, 0 } }, +{ "mov", 2, 0x8c, _, D|Modrm, { SReg3|SReg2, Reg16|Mem, 0 } }, +/* move to/from control debug registers */ +{ "mov", 2, 0x0f20, _, D|Modrm, { Control, Reg32, 0} }, +{ "mov", 2, 0x0f21, _, D|Modrm, { Debug, Reg32, 0} }, +{ "mov", 2, 0x0f24, _, D|Modrm, { Test, Reg32, 0} }, + +/* move with sign extend */ +/* "movsbl" & "movsbw" must not be unified into "movsb" to avoid + conflict with the "movs" string move instruction. Thus, + {"movsb", 2, 0x0fbe, _, ReverseRegRegmem|Modrm, { Reg8|Mem, Reg16|Reg32, 0} }, + is not kosher; we must seperate the two instructions. */ +{"movsbl", 2, 0x0fbe, _, ReverseRegRegmem|Modrm|Data32, { Reg8|Mem, Reg32, 0} }, +{"movsbw", 2, 0x0fbe, _, ReverseRegRegmem|Modrm|Data16, { Reg8|Mem, Reg16, 0} }, +{"movswl", 2, 0x0fbf, _, ReverseRegRegmem|Modrm, { Reg16|Mem, Reg32, 0} }, + +/* move with zero extend */ +{"movzb", 2, 0x0fb6, _, ReverseRegRegmem|Modrm, { Reg8|Mem, Reg16|Reg32, 0} }, +{"movzwl", 2, 0x0fb7, _, ReverseRegRegmem|Modrm, { Reg16|Mem, Reg32, 0} }, + +/* push instructions */ +{"push", 1, 0x50, _, ShortForm, { WordReg,0,0 } }, +{"push", 1, 0xff, 0x6, Modrm, { WordReg|WordMem, 0, 0 } }, +{"push", 1, 0x6a, _, NoModrm, { Imm8S, 0, 0} }, +{"push", 1, 0x68, _, NoModrm, { Imm16|Imm32, 0, 0} }, +{"push", 1, 0x06, _, Seg2ShortForm, { SReg2,0,0 } }, +{"push", 1, 0x0fa0, _, Seg3ShortForm, { SReg3,0,0 } }, +/* push all */ +{"pusha", 0, 0x60, _, NoModrm, { 0, 0, 0 } }, + +/* pop instructions */ +{"pop", 1, 0x58, _, ShortForm, { WordReg,0,0 } }, +{"pop", 1, 0x8f, 0x0, Modrm, { WordReg|WordMem, 0, 0 } }, +#define POP_SEG_SHORT 0x7 +{"pop", 1, 0x07, _, Seg2ShortForm, { SReg2,0,0 } }, +{"pop", 1, 0x0fa1, _, Seg3ShortForm, { SReg3,0,0 } }, +/* pop all */ +{"popa", 0, 0x61, _, NoModrm, { 0, 0, 0 } }, + +/* xchg exchange instructions + xchg commutes: we allow both operand orders */ +{"xchg", 2, 0x90, _, ShortForm, { WordReg, Acc, 0 } }, +{"xchg", 2, 0x90, _, ShortForm, { Acc, WordReg, 0 } }, +{"xchg", 2, 0x86, _, W|Modrm, { Reg, Reg|Mem, 0 } }, +{"xchg", 2, 0x86, _, W|Modrm, { Reg|Mem, Reg, 0 } }, + +/* in/out from ports */ +{"in", 2, 0xe4, _, W|NoModrm, { Imm8, Acc, 0 } }, +{"in", 2, 0xec, _, W|NoModrm, { InOutPortReg, Acc, 0 } }, +{"in", 1, 0xe4, _, W|NoModrm, { Imm8, 0, 0 } }, +{"in", 1, 0xec, _, W|NoModrm, { InOutPortReg, 0, 0 } }, +{"out", 2, 0xe6, _, W|NoModrm, { Acc, Imm8, 0 } }, +{"out", 2, 0xee, _, W|NoModrm, { Acc, InOutPortReg, 0 } }, +{"out", 1, 0xe6, _, W|NoModrm, { Imm8, 0, 0 } }, +{"out", 1, 0xee, _, W|NoModrm, { InOutPortReg, 0, 0 } }, + +/* load effective address */ +{"lea", 2, 0x8d, _, Modrm, { WordMem, WordReg, 0 } }, + +/* load segment registers from memory */ +{"lds", 2, 0xc5, _, Modrm, { Mem, Reg32, 0} }, +{"les", 2, 0xc4, _, Modrm, { Mem, Reg32, 0} }, +{"lfs", 2, 0x0fb4, _, Modrm, { Mem, Reg32, 0} }, +{"lgs", 2, 0x0fb5, _, Modrm, { Mem, Reg32, 0} }, +{"lss", 2, 0x0fb2, _, Modrm, { Mem, Reg32, 0} }, + +/* flags register instructions */ +{"clc", 0, 0xf8, _, NoModrm, { 0, 0, 0} }, +{"cld", 0, 0xfc, _, NoModrm, { 0, 0, 0} }, +{"cli", 0, 0xfa, _, NoModrm, { 0, 0, 0} }, +{"clts", 0, 0x0f06, _, NoModrm, { 0, 0, 0} }, +{"cmc", 0, 0xf5, _, NoModrm, { 0, 0, 0} }, +{"lahf", 0, 0x9f, _, NoModrm, { 0, 0, 0} }, +{"sahf", 0, 0x9e, _, NoModrm, { 0, 0, 0} }, +{"pushfl", 0, 0x9c, _, NoModrm|Data32, { 0, 0, 0} }, +{"popfl", 0, 0x9d, _, NoModrm|Data32, { 0, 0, 0} }, +{"pushfw", 0, 0x9c, _, NoModrm|Data16, { 0, 0, 0} }, +{"popfw", 0, 0x9d, _, NoModrm|Data16, { 0, 0, 0} }, +{"pushf", 0, 0x9c, _, NoModrm, { 0, 0, 0} }, +{"popf", 0, 0x9d, _, NoModrm, { 0, 0, 0} }, +{"stc", 0, 0xf9, _, NoModrm, { 0, 0, 0} }, +{"std", 0, 0xfd, _, NoModrm, { 0, 0, 0} }, +{"sti", 0, 0xfb, _, NoModrm, { 0, 0, 0} }, + +{"add", 2, 0x0, _, DW|Modrm, { Reg, Reg|Mem, 0} }, +{"add", 2, 0x83, 0, Modrm, { Imm8S, WordReg|WordMem, 0} }, +{"add", 2, 0x4, _, W|NoModrm, { Imm, Acc, 0} }, +{"add", 2, 0x80, 0, W|Modrm, { Imm, Reg|Mem, 0} }, + +{"inc", 1, 0x40, _, ShortForm, { WordReg, 0, 0} }, +{"inc", 1, 0xfe, 0, W|Modrm, { Reg|Mem, 0, 0} }, + +{"sub", 2, 0x28, _, DW|Modrm, { Reg, Reg|Mem, 0} }, +{"sub", 2, 0x83, 5, Modrm, { Imm8S, WordReg|WordMem, 0} }, +{"sub", 2, 0x2c, _, W|NoModrm, { Imm, Acc, 0} }, +{"sub", 2, 0x80, 5, W|Modrm, { Imm, Reg|Mem, 0} }, + +{"dec", 1, 0x48, _, ShortForm, { WordReg, 0, 0} }, +{"dec", 1, 0xfe, 1, W|Modrm, { Reg|Mem, 0, 0} }, + +{"sbb", 2, 0x18, _, DW|Modrm, { Reg, Reg|Mem, 0} }, +{"sbb", 2, 0x83, 3, Modrm, { Imm8S, WordReg|WordMem, 0} }, +{"sbb", 2, 0x1c, _, W|NoModrm, { Imm, Acc, 0} }, +{"sbb", 2, 0x80, 3, W|Modrm, { Imm, Reg|Mem, 0} }, + +{"cmp", 2, 0x38, _, DW|Modrm, { Reg, Reg|Mem, 0} }, +{"cmp", 2, 0x83, 7, Modrm, { Imm8S, WordReg|WordMem, 0} }, +{"cmp", 2, 0x3c, _, W|NoModrm, { Imm, Acc, 0} }, +{"cmp", 2, 0x80, 7, W|Modrm, { Imm, Reg|Mem, 0} }, + +{"test", 2, 0x84, _, W|Modrm, { Reg|Mem, Reg, 0} }, +{"test", 2, 0x84, _, W|Modrm, { Reg, Reg|Mem, 0} }, +{"test", 2, 0xa8, _, W|NoModrm, { Imm, Acc, 0} }, +{"test", 2, 0xf6, 0, W|Modrm, { Imm, Reg|Mem, 0} }, + +{"and", 2, 0x20, _, DW|Modrm, { Reg, Reg|Mem, 0} }, +{"and", 2, 0x83, 4, Modrm, { Imm8S, WordReg|WordMem, 0} }, +{"and", 2, 0x24, _, W|NoModrm, { Imm, Acc, 0} }, +{"and", 2, 0x80, 4, W|Modrm, { Imm, Reg|Mem, 0} }, + +{"or", 2, 0x08, _, DW|Modrm, { Reg, Reg|Mem, 0} }, +{"or", 2, 0x83, 1, Modrm, { Imm8S, WordReg|WordMem, 0} }, +{"or", 2, 0x0c, _, W|NoModrm, { Imm, Acc, 0} }, +{"or", 2, 0x80, 1, W|Modrm, { Imm, Reg|Mem, 0} }, + +{"xor", 2, 0x30, _, DW|Modrm, { Reg, Reg|Mem, 0} }, +{"xor", 2, 0x83, 6, Modrm, { Imm8S, WordReg|WordMem, 0} }, +{"xor", 2, 0x34, _, W|NoModrm, { Imm, Acc, 0} }, +{"xor", 2, 0x80, 6, W|Modrm, { Imm, Reg|Mem, 0} }, + +{"adc", 2, 0x10, _, DW|Modrm, { Reg, Reg|Mem, 0} }, +{"adc", 2, 0x83, 2, Modrm, { Imm8S, WordReg|WordMem, 0} }, +{"adc", 2, 0x14, _, W|NoModrm, { Imm, Acc, 0} }, +{"adc", 2, 0x80, 2, W|Modrm, { Imm, Reg|Mem, 0} }, + +{"neg", 1, 0xf6, 3, W|Modrm, { Reg|Mem, 0, 0} }, +{"not", 1, 0xf6, 2, W|Modrm, { Reg|Mem, 0, 0} }, + +{"aaa", 0, 0x37, _, NoModrm, { 0, 0, 0} }, +{"aas", 0, 0x3f, _, NoModrm, { 0, 0, 0} }, +{"daa", 0, 0x27, _, NoModrm, { 0, 0, 0} }, +{"das", 0, 0x2f, _, NoModrm, { 0, 0, 0} }, +{"aad", 0, 0xd50a, _, NoModrm, { 0, 0, 0} }, +{"aam", 0, 0xd40a, _, NoModrm, { 0, 0, 0} }, + +/* conversion insns */ +/* conversion: intel naming */ +{"cbw", 0, 0x98, _, NoModrm|Data16, { 0, 0, 0} }, +{"cwd", 0, 0x99, _, NoModrm|Data16, { 0, 0, 0} }, +{"cwde", 0, 0x98, _, NoModrm|Data32, { 0, 0, 0} }, +{"cdq", 0, 0x99, _, NoModrm|Data32, { 0, 0, 0} }, +/* att naming */ +{"cbtw", 0, 0x98, _, NoModrm|Data16, { 0, 0, 0} }, +{"cwtl", 0, 0x98, _, NoModrm|Data32, { 0, 0, 0} }, +{"cwtd", 0, 0x99, _, NoModrm|Data16, { 0, 0, 0} }, +{"cltd", 0, 0x99, _, NoModrm|Data32, { 0, 0, 0} }, + +/* Warning! the mul/imul (opcode 0xf6) must only have 1 operand! They are + expanding 64-bit multiplies, and *cannot* be selected to accomplish + 'imul %ebx, %eax' (opcode 0x0faf must be used in this case) + These multiplies can only be selected with single operand forms. */ +{"mul", 1, 0xf6, 4, W|Modrm, { Reg|Mem, 0, 0} }, +{"imul", 1, 0xf6, 5, W|Modrm, { Reg|Mem, 0, 0} }, + + + + +/* imulKludge here is needed to reverse the i.rm.reg & i.rm.regmem fields. + These instructions are exceptions: 'imul $2, %eax, %ecx' would put + '%eax' in the reg field and '%ecx' in the regmem field if we did not + switch them. */ +{"imul", 2, 0x0faf, _, Modrm|ReverseRegRegmem, { WordReg|Mem, WordReg, 0} }, +{"imul", 3, 0x6b, _, Modrm|ReverseRegRegmem, { Imm8S, WordReg|Mem, WordReg} }, +{"imul", 3, 0x69, _, Modrm|ReverseRegRegmem, { Imm16|Imm32, WordReg|Mem, WordReg} }, +/* + imul with 2 operands mimicks imul with 3 by puting register both + in i.rm.reg & i.rm.regmem fields +*/ +{"imul", 2, 0x6b, _, Modrm|imulKludge, { Imm8S, WordReg, 0} }, +{"imul", 2, 0x69, _, Modrm|imulKludge, { Imm16|Imm32, WordReg, 0} }, +{"div", 1, 0xf6, 6, W|Modrm, { Reg|Mem, 0, 0} }, +{"div", 2, 0xf6, 6, W|Modrm, { Reg|Mem, Acc, 0} }, +{"idiv", 1, 0xf6, 7, W|Modrm, { Reg|Mem, 0, 0} }, +{"idiv", 2, 0xf6, 7, W|Modrm, { Reg|Mem, Acc, 0} }, + +{"rol", 2, 0xd0, 0, W|Modrm, { Imm1, Reg|Mem, 0} }, +{"rol", 2, 0xc0, 0, W|Modrm, { Imm8, Reg|Mem, 0} }, +{"rol", 2, 0xd2, 0, W|Modrm, { ShiftCount, Reg|Mem, 0} }, +{"rol", 1, 0xd0, 0, W|Modrm, { Reg|Mem, 0, 0} }, + +{"ror", 2, 0xd0, 1, W|Modrm, { Imm1, Reg|Mem, 0} }, +{"ror", 2, 0xc0, 1, W|Modrm, { Imm8, Reg|Mem, 0} }, +{"ror", 2, 0xd2, 1, W|Modrm, { ShiftCount, Reg|Mem, 0} }, +{"ror", 1, 0xd0, 1, W|Modrm, { Reg|Mem, 0, 0} }, + +{"rcl", 2, 0xd0, 2, W|Modrm, { Imm1, Reg|Mem, 0} }, +{"rcl", 2, 0xc0, 2, W|Modrm, { Imm8, Reg|Mem, 0} }, +{"rcl", 2, 0xd2, 2, W|Modrm, { ShiftCount, Reg|Mem, 0} }, +{"rcl", 1, 0xd0, 2, W|Modrm, { Reg|Mem, 0, 0} }, + +{"rcr", 2, 0xd0, 3, W|Modrm, { Imm1, Reg|Mem, 0} }, +{"rcr", 2, 0xc0, 3, W|Modrm, { Imm8, Reg|Mem, 0} }, +{"rcr", 2, 0xd2, 3, W|Modrm, { ShiftCount, Reg|Mem, 0} }, +{"rcr", 1, 0xd0, 3, W|Modrm, { Reg|Mem, 0, 0} }, + +{"sal", 2, 0xd0, 4, W|Modrm, { Imm1, Reg|Mem, 0} }, +{"sal", 2, 0xc0, 4, W|Modrm, { Imm8, Reg|Mem, 0} }, +{"sal", 2, 0xd2, 4, W|Modrm, { ShiftCount, Reg|Mem, 0} }, +{"sal", 1, 0xd0, 4, W|Modrm, { Reg|Mem, 0, 0} }, +{"shl", 2, 0xd0, 4, W|Modrm, { Imm1, Reg|Mem, 0} }, +{"shl", 2, 0xc0, 4, W|Modrm, { Imm8, Reg|Mem, 0} }, +{"shl", 2, 0xd2, 4, W|Modrm, { ShiftCount, Reg|Mem, 0} }, +{"shl", 1, 0xd0, 4, W|Modrm, { Reg|Mem, 0, 0} }, + +{"shld", 3, 0x0fa4, _, Modrm, { Imm8, WordReg, WordReg|Mem} }, +{"shld", 3, 0x0fa5, _, Modrm, { ShiftCount, WordReg, WordReg|Mem} }, +{"shld", 2, 0x0fa5, _, Modrm, { WordReg, WordReg|Mem, 0} }, + +{"shr", 2, 0xd0, 5, W|Modrm, { Imm1, Reg|Mem, 0} }, +{"shr", 2, 0xc0, 5, W|Modrm, { Imm8, Reg|Mem, 0} }, +{"shr", 2, 0xd2, 5, W|Modrm, { ShiftCount, Reg|Mem, 0} }, +{"shr", 1, 0xd0, 5, W|Modrm, { Reg|Mem, 0, 0} }, + +{"shrd", 3, 0x0fac, _, Modrm, { Imm8, WordReg, WordReg|Mem} }, +{"shrd", 3, 0x0fad, _, Modrm, { ShiftCount, WordReg, WordReg|Mem} }, +{"shrd", 2, 0x0fad, _, Modrm, { WordReg, WordReg|Mem, 0} }, + +{"sar", 2, 0xd0, 7, W|Modrm, { Imm1, Reg|Mem, 0} }, +{"sar", 2, 0xc0, 7, W|Modrm, { Imm8, Reg|Mem, 0} }, +{"sar", 2, 0xd2, 7, W|Modrm, { ShiftCount, Reg|Mem, 0} }, +{"sar", 1, 0xd0, 7, W|Modrm, { Reg|Mem, 0, 0} }, + +/* control transfer instructions */ +#define CALL_PC_RELATIVE 0xe8 +{"call", 1, 0xe8, _, JumpDword, { Disp32, 0, 0} }, +{"call", 1, 0xff, 2, Modrm|Data32, { Reg|Mem|JumpAbsolute, 0, 0} }, +{"callw", 1, 0xff, 2, Modrm|Data16, { Reg|Mem|JumpAbsolute, 0, 0} }, +#define CALL_FAR_IMMEDIATE 0x9a +{"lcall", 2, 0x9a, _, JumpInterSegment, { Imm16, Abs32|Imm32, 0} }, +{"lcall", 1, 0xff, 3, Modrm|Data32, { Mem, 0, 0} }, +{"lcallw", 1, 0xff, 3, Modrm|Data16, { Mem, 0, 0} }, + +#define JUMP_PC_RELATIVE 0xeb +{"jmp", 1, 0xeb, _, Jump, { Disp, 0, 0} }, +{"jmp", 1, 0xff, 4, Modrm, { Reg32|Mem|JumpAbsolute, 0, 0} }, +#define JUMP_FAR_IMMEDIATE 0xea +{"ljmp", 2, 0xea, _, JumpInterSegment, { Imm16, Imm32, 0} }, +{"ljmp", 1, 0xff, 5, Modrm|Data32, { Mem, 0, 0} }, + +{"ret", 0, 0xc3, _, NoModrm|Data32, { 0, 0, 0} }, +{"ret", 1, 0xc2, _, NoModrm|Data32, { Imm16, 0, 0} }, +{"retw", 0, 0xc3, _, NoModrm|Data16, { 0, 0, 0} }, +{"retw", 1, 0xc2, _, NoModrm|Data16, { Imm16, 0, 0} }, +{"lret", 0, 0xcb, _, NoModrm|Data32, { 0, 0, 0} }, +{"lret", 1, 0xca, _, NoModrm|Data32, { Imm16, 0, 0} }, +{"lretw", 0, 0xcb, _, NoModrm|Data16, { 0, 0, 0} }, +{"lretw", 1, 0xca, _, NoModrm|Data16, { Imm16, 0, 0} }, +{"enter", 2, 0xc8, _, NoModrm|Data32, { Imm16, Imm8, 0} }, +{"leave", 0, 0xc9, _, NoModrm|Data32, { 0, 0, 0} }, +{"enterw", 2, 0xc8, _, NoModrm|Data16, { Imm16, Imm8, 0} }, +{"leavew", 0, 0xc9, _, NoModrm|Data16, { 0, 0, 0} }, + +/* conditional jumps */ +{"jo", 1, 0x70, _, Jump, { Disp, 0, 0} }, + +{"jno", 1, 0x71, _, Jump, { Disp, 0, 0} }, + +{"jb", 1, 0x72, _, Jump, { Disp, 0, 0} }, +{"jc", 1, 0x72, _, Jump, { Disp, 0, 0} }, +{"jnae", 1, 0x72, _, Jump, { Disp, 0, 0} }, + +{"jnb", 1, 0x73, _, Jump, { Disp, 0, 0} }, +{"jnc", 1, 0x73, _, Jump, { Disp, 0, 0} }, +{"jae", 1, 0x73, _, Jump, { Disp, 0, 0} }, + +{"je", 1, 0x74, _, Jump, { Disp, 0, 0} }, +{"jz", 1, 0x74, _, Jump, { Disp, 0, 0} }, + +{"jne", 1, 0x75, _, Jump, { Disp, 0, 0} }, +{"jnz", 1, 0x75, _, Jump, { Disp, 0, 0} }, + +{"jbe", 1, 0x76, _, Jump, { Disp, 0, 0} }, +{"jna", 1, 0x76, _, Jump, { Disp, 0, 0} }, + +{"jnbe", 1, 0x77, _, Jump, { Disp, 0, 0} }, +{"ja", 1, 0x77, _, Jump, { Disp, 0, 0} }, + +{"js", 1, 0x78, _, Jump, { Disp, 0, 0} }, + +{"jns", 1, 0x79, _, Jump, { Disp, 0, 0} }, + +{"jp", 1, 0x7a, _, Jump, { Disp, 0, 0} }, +{"jpe", 1, 0x7a, _, Jump, { Disp, 0, 0} }, + +{"jnp", 1, 0x7b, _, Jump, { Disp, 0, 0} }, +{"jpo", 1, 0x7b, _, Jump, { Disp, 0, 0} }, + +{"jl", 1, 0x7c, _, Jump, { Disp, 0, 0} }, +{"jnge", 1, 0x7c, _, Jump, { Disp, 0, 0} }, + +{"jnl", 1, 0x7d, _, Jump, { Disp, 0, 0} }, +{"jge", 1, 0x7d, _, Jump, { Disp, 0, 0} }, + +{"jle", 1, 0x7e, _, Jump, { Disp, 0, 0} }, +{"jng", 1, 0x7e, _, Jump, { Disp, 0, 0} }, + +{"jnle", 1, 0x7f, _, Jump, { Disp, 0, 0} }, +{"jg", 1, 0x7f, _, Jump, { Disp, 0, 0} }, + +#if 0 /* XXX where are these macros used? + To get them working again, they need to take + an entire template as the parameter, + and check for Data16/Data32 flags. */ +/* these turn into pseudo operations when disp is larger than 8 bits */ +#define IS_JUMP_ON_CX_ZERO(o) \ + (o == 0x66e3) +#define IS_JUMP_ON_ECX_ZERO(o) \ + (o == 0xe3) +#endif + +{"jcxz", 1, 0xe3, _, JumpByte|Data16, { Disp, 0, 0} }, +{"jecxz", 1, 0xe3, _, JumpByte|Data32, { Disp, 0, 0} }, + +#define IS_LOOP_ECX_TIMES(o) \ + (o == 0xe2 || o == 0xe1 || o == 0xe0) + +{"loop", 1, 0xe2, _, JumpByte, { Disp, 0, 0} }, + +{"loopz", 1, 0xe1, _, JumpByte, { Disp, 0, 0} }, +{"loope", 1, 0xe1, _, JumpByte, { Disp, 0, 0} }, + +{"loopnz", 1, 0xe0, _, JumpByte, { Disp, 0, 0} }, +{"loopne", 1, 0xe0, _, JumpByte, { Disp, 0, 0} }, + +/* set byte on flag instructions */ +{"seto", 1, 0x0f90, 0, Modrm, { Reg8|Mem, 0, 0} }, + +{"setno", 1, 0x0f91, 0, Modrm, { Reg8|Mem, 0, 0} }, + +{"setb", 1, 0x0f92, 0, Modrm, { Reg8|Mem, 0, 0} }, +{"setc", 1, 0x0f92, 0, Modrm, { Reg8|Mem, 0, 0} }, +{"setnae", 1, 0x0f92, 0, Modrm, { Reg8|Mem, 0, 0} }, + +{"setnb", 1, 0x0f93, 0, Modrm, { Reg8|Mem, 0, 0} }, +{"setnc", 1, 0x0f93, 0, Modrm, { Reg8|Mem, 0, 0} }, +{"setae", 1, 0x0f93, 0, Modrm, { Reg8|Mem, 0, 0} }, + +{"sete", 1, 0x0f94, 0, Modrm, { Reg8|Mem, 0, 0} }, +{"setz", 1, 0x0f94, 0, Modrm, { Reg8|Mem, 0, 0} }, + +{"setne", 1, 0x0f95, 0, Modrm, { Reg8|Mem, 0, 0} }, +{"setnz", 1, 0x0f95, 0, Modrm, { Reg8|Mem, 0, 0} }, + +{"setbe", 1, 0x0f96, 0, Modrm, { Reg8|Mem, 0, 0} }, +{"setna", 1, 0x0f96, 0, Modrm, { Reg8|Mem, 0, 0} }, + +{"setnbe", 1, 0x0f97, 0, Modrm, { Reg8|Mem, 0, 0} }, +{"seta", 1, 0x0f97, 0, Modrm, { Reg8|Mem, 0, 0} }, + +{"sets", 1, 0x0f98, 0, Modrm, { Reg8|Mem, 0, 0} }, + +{"setns", 1, 0x0f99, 0, Modrm, { Reg8|Mem, 0, 0} }, + +{"setp", 1, 0x0f9a, 0, Modrm, { Reg8|Mem, 0, 0} }, +{"setpe", 1, 0x0f9a, 0, Modrm, { Reg8|Mem, 0, 0} }, + +{"setnp", 1, 0x0f9b, 0, Modrm, { Reg8|Mem, 0, 0} }, +{"setpo", 1, 0x0f9b, 0, Modrm, { Reg8|Mem, 0, 0} }, + +{"setl", 1, 0x0f9c, 0, Modrm, { Reg8|Mem, 0, 0} }, +{"setnge", 1, 0x0f9c, 0, Modrm, { Reg8|Mem, 0, 0} }, + +{"setnl", 1, 0x0f9d, 0, Modrm, { Reg8|Mem, 0, 0} }, +{"setge", 1, 0x0f9d, 0, Modrm, { Reg8|Mem, 0, 0} }, + +{"setle", 1, 0x0f9e, 0, Modrm, { Reg8|Mem, 0, 0} }, +{"setng", 1, 0x0f9e, 0, Modrm, { Reg8|Mem, 0, 0} }, + +{"setnle", 1, 0x0f9f, 0, Modrm, { Reg8|Mem, 0, 0} }, +{"setg", 1, 0x0f9f, 0, Modrm, { Reg8|Mem, 0, 0} }, + +#define IS_STRING_INSTRUCTION(o) \ + ((o) == 0xa6 || (o) == 0x6c || (o) == 0x6e || (o) == 0x6e || \ + (o) == 0xac || (o) == 0xa4 || (o) == 0xae || (o) == 0xaa || \ + (o) == 0xd7) + +/* string manipulation */ +{"cmps", 0, 0xa6, _, W|NoModrm, { 0, 0, 0} }, +{"scmp", 0, 0xa6, _, W|NoModrm, { 0, 0, 0} }, +{"ins", 0, 0x6c, _, W|NoModrm, { 0, 0, 0} }, +{"outs", 0, 0x6e, _, W|NoModrm, { 0, 0, 0} }, +{"lods", 0, 0xac, _, W|NoModrm, { 0, 0, 0} }, +{"slod", 0, 0xac, _, W|NoModrm, { 0, 0, 0} }, +{"movs", 0, 0xa4, _, W|NoModrm, { 0, 0, 0} }, +{"smov", 0, 0xa4, _, W|NoModrm, { 0, 0, 0} }, +{"scas", 0, 0xae, _, W|NoModrm, { 0, 0, 0} }, +{"ssca", 0, 0xae, _, W|NoModrm, { 0, 0, 0} }, +{"stos", 0, 0xaa, _, W|NoModrm, { 0, 0, 0} }, +{"ssto", 0, 0xaa, _, W|NoModrm, { 0, 0, 0} }, +{"xlat", 0, 0xd7, _, NoModrm, { 0, 0, 0} }, + +/* bit manipulation */ +{"bsf", 2, 0x0fbc, _, Modrm|ReverseRegRegmem, { Reg|Mem, Reg, 0} }, +{"bsr", 2, 0x0fbd, _, Modrm|ReverseRegRegmem, { Reg|Mem, Reg, 0} }, +{"bt", 2, 0x0fa3, _, Modrm, { Reg, Reg|Mem, 0} }, +{"bt", 2, 0x0fba, 4, Modrm, { Imm8, Reg|Mem, 0} }, +{"btc", 2, 0x0fbb, _, Modrm, { Reg, Reg|Mem, 0} }, +{"btc", 2, 0x0fba, 7, Modrm, { Imm8, Reg|Mem, 0} }, +{"btr", 2, 0x0fb3, _, Modrm, { Reg, Reg|Mem, 0} }, +{"btr", 2, 0x0fba, 6, Modrm, { Imm8, Reg|Mem, 0} }, +{"bts", 2, 0x0fab, _, Modrm, { Reg, Reg|Mem, 0} }, +{"bts", 2, 0x0fba, 5, Modrm, { Imm8, Reg|Mem, 0} }, + +/* interrupts & op. sys insns */ +/* See gas/config/tc-i386.c for conversion of 'int $3' into the special + int 3 insn. */ +#define INT_OPCODE 0xcd +#define INT3_OPCODE 0xcc +{"int", 1, 0xcd, _, NoModrm, { Imm8, 0, 0} }, +{"int3", 0, 0xcc, _, NoModrm, { 0, 0, 0} }, +{"into", 0, 0xce, _, NoModrm, { 0, 0, 0} }, +{"iret", 0, 0xcf, _, NoModrm|Data32, { 0, 0, 0} }, +{"iretw", 0, 0xcf, _, NoModrm|Data16, { 0, 0, 0} }, +/* i386sl, i486sl, later 486, and Pentium */ +{"rsm", 0, 0x0faa, _, NoModrm,{ 0, 0, 0} }, + +{"boundl", 2, 0x62, _, Modrm|Data32, { Reg32, Mem, 0} }, +{"boundw", 2, 0x62, _, Modrm|Data16, { Reg16, Mem, 0} }, + +{"hlt", 0, 0xf4, _, NoModrm, { 0, 0, 0} }, +{"wait", 0, 0x9b, _, NoModrm, { 0, 0, 0} }, +/* nop is actually 'xchgl %eax, %eax' */ +{"nop", 0, 0x90, _, NoModrm, { 0, 0, 0} }, + +/* protection control */ +{"arpl", 2, 0x63, _, Modrm, { Reg16, Reg16|Mem, 0} }, +{"lar", 2, 0x0f02, _, Modrm|ReverseRegRegmem, { WordReg|Mem, WordReg, 0} }, +{"lgdt", 1, 0x0f01, 2, Modrm, { Mem, 0, 0} }, +{"lidt", 1, 0x0f01, 3, Modrm, { Mem, 0, 0} }, +{"lldt", 1, 0x0f00, 2, Modrm, { WordReg|Mem, 0, 0} }, +{"lmsw", 1, 0x0f01, 6, Modrm, { WordReg|Mem, 0, 0} }, +{"lsl", 2, 0x0f03, _, Modrm|ReverseRegRegmem, { WordReg|Mem, WordReg, 0} }, +{"ltr", 1, 0x0f00, 3, Modrm, { WordReg|Mem, 0, 0} }, + +{"sgdt", 1, 0x0f01, 0, Modrm, { Mem, 0, 0} }, +{"sidt", 1, 0x0f01, 1, Modrm, { Mem, 0, 0} }, +{"sldt", 1, 0x0f00, 0, Modrm, { WordReg|Mem, 0, 0} }, +{"smsw", 1, 0x0f01, 4, Modrm, { WordReg|Mem, 0, 0} }, +{"str", 1, 0x0f00, 1, Modrm, { Reg16|Mem, 0, 0} }, + +{"verr", 1, 0x0f00, 4, Modrm, { WordReg|Mem, 0, 0} }, +{"verw", 1, 0x0f00, 5, Modrm, { WordReg|Mem, 0, 0} }, + +/* floating point instructions */ + +/* load */ +{"fld", 1, 0xd9c0, _, ShortForm, { FloatReg, 0, 0} }, /* register */ +{"flds", 1, 0xd9, 0, Modrm, { Mem, 0, 0} }, /* %st0 <-- mem float */ +{"fldl", 1, 0xdd, 0, Modrm, { Mem, 0, 0} }, /* %st0 <-- mem double */ +{"fldl", 1, 0xd9c0, _, ShortForm, { FloatReg, 0, 0} }, /* register */ +{"fild", 1, 0xdf, 0, Modrm, { Mem, 0, 0} }, /* %st0 <-- mem word (16) */ +{"fildl", 1, 0xdb, 0, Modrm, { Mem, 0, 0} }, /* %st0 <-- mem dword (32) */ +{"fildq",1, 0xdf, 5, Modrm, { Mem, 0, 0} }, /* %st0 <-- mem qword (64) */ +{"fildll",1, 0xdf, 5, Modrm, { Mem, 0, 0} }, /* %st0 <-- mem qword (64) */ +{"fldt", 1, 0xdb, 5, Modrm, { Mem, 0, 0} }, /* %st0 <-- mem efloat */ +{"fbld", 1, 0xdf, 4, Modrm, { Mem, 0, 0} }, /* %st0 <-- mem bcd */ + +/* store (no pop) */ +{"fst", 1, 0xddd0, _, ShortForm, { FloatReg, 0, 0} }, /* register */ +{"fsts", 1, 0xd9, 2, Modrm, { Mem, 0, 0} }, /* %st0 --> mem float */ +{"fstl", 1, 0xdd, 2, Modrm, { Mem, 0, 0} }, /* %st0 --> mem double */ +{"fstl", 1, 0xddd0, _, ShortForm, { FloatReg, 0, 0} }, /* register */ +{"fist", 1, 0xdf, 2, Modrm, { Mem, 0, 0} }, /* %st0 --> mem word (16) */ +{"fistl", 1, 0xdb, 2, Modrm, { Mem, 0, 0} }, /* %st0 --> mem dword (32) */ + +/* store (with pop) */ +{"fstp", 1, 0xddd8, _, ShortForm, { FloatReg, 0, 0} }, /* register */ +{"fstps", 1, 0xd9, 3, Modrm, { Mem, 0, 0} }, /* %st0 --> mem float */ +{"fstpl", 1, 0xdd, 3, Modrm, { Mem, 0, 0} }, /* %st0 --> mem double */ +{"fstpl", 1, 0xddd8, _, ShortForm, { FloatReg, 0, 0} }, /* register */ +{"fistp", 1, 0xdf, 3, Modrm, { Mem, 0, 0} }, /* %st0 --> mem word (16) */ +{"fistpl",1, 0xdb, 3, Modrm, { Mem, 0, 0} }, /* %st0 --> mem dword (32) */ +{"fistpq",1, 0xdf, 7, Modrm, { Mem, 0, 0} }, /* %st0 --> mem qword (64) */ +{"fistpll",1,0xdf, 7, Modrm, { Mem, 0, 0} }, /* %st0 --> mem qword (64) */ +{"fstpt", 1, 0xdb, 7, Modrm, { Mem, 0, 0} }, /* %st0 --> mem efloat */ +{"fbstp", 1, 0xdf, 6, Modrm, { Mem, 0, 0} }, /* %st0 --> mem bcd */ + +/* exchange %st with %st0 */ +{"fxch", 1, 0xd9c8, _, ShortForm, { FloatReg, 0, 0} }, +{"fxch", 0, 0xd9c9, _, NoModrm, { 0, 0, 0} }, /* alias for fxch %st, %st(1) */ + +/* comparison (without pop) */ +{"fcom", 1, 0xd8d0, _, ShortForm, { FloatReg, 0, 0} }, +{"fcoms", 1, 0xd8, 2, Modrm, { Mem, 0, 0} }, /* compare %st0, mem float */ +{"ficoml", 1, 0xda, 2, Modrm, { Mem, 0, 0} }, /* compare %st0, mem word */ +{"fcoml", 1, 0xdc, 2, Modrm, { Mem, 0, 0} }, /* compare %st0, mem double */ +{"fcoml", 1, 0xd8d0, _, ShortForm, { FloatReg, 0, 0} }, +{"ficoms", 1, 0xde, 2, Modrm, { Mem, 0, 0} }, /* compare %st0, mem dword */ + +/* comparison (with pop) */ +{"fcomp", 1, 0xd8d8, _, ShortForm, { FloatReg, 0, 0} }, +{"fcomps", 1, 0xd8, 3, Modrm, { Mem, 0, 0} }, /* compare %st0, mem float */ +{"ficompl", 1, 0xda, 3, Modrm, { Mem, 0, 0} }, /* compare %st0, mem word */ +{"fcompl", 1, 0xdc, 3, Modrm, { Mem, 0, 0} }, /* compare %st0, mem double */ +{"fcompl", 1, 0xd8d8, _, ShortForm, { FloatReg, 0, 0} }, +{"ficomps", 1, 0xde, 3, Modrm, { Mem, 0, 0} }, /* compare %st0, mem dword */ +{"fcompp", 0, 0xded9, _, NoModrm, { 0, 0, 0} }, /* compare %st0, %st1 & pop 2 */ + +/* unordered comparison (with pop) */ +{"fucom", 1, 0xdde0, _, ShortForm, { FloatReg, 0, 0} }, +{"fucomp", 1, 0xdde8, _, ShortForm, { FloatReg, 0, 0} }, +{"fucompp", 0, 0xdae9, _, NoModrm, { 0, 0, 0} }, /* ucompare %st0, %st1 & pop twice */ + +{"ftst", 0, 0xd9e4, _, NoModrm, { 0, 0, 0} }, /* test %st0 */ +{"fxam", 0, 0xd9e5, _, NoModrm, { 0, 0, 0} }, /* examine %st0 */ + +/* load constants into %st0 */ +{"fld1", 0, 0xd9e8, _, NoModrm, { 0, 0, 0} }, /* %st0 <-- 1.0 */ +{"fldl2t", 0, 0xd9e9, _, NoModrm, { 0, 0, 0} }, /* %st0 <-- log2(10) */ +{"fldl2e", 0, 0xd9ea, _, NoModrm, { 0, 0, 0} }, /* %st0 <-- log2(e) */ +{"fldpi", 0, 0xd9eb, _, NoModrm, { 0, 0, 0} }, /* %st0 <-- pi */ +{"fldlg2", 0, 0xd9ec, _, NoModrm, { 0, 0, 0} }, /* %st0 <-- log10(2) */ +{"fldln2", 0, 0xd9ed, _, NoModrm, { 0, 0, 0} }, /* %st0 <-- ln(2) */ +{"fldz", 0, 0xd9ee, _, NoModrm, { 0, 0, 0} }, /* %st0 <-- 0.0 */ + +/* arithmetic */ + +/* add */ +{"fadd", 1, 0xd8c0, _, ShortForm, { FloatReg, 0, 0} }, +{"fadd", 2, 0xd8c0, _, ShortForm|FloatD, { FloatReg, FloatAcc, 0} }, +{"fadd", 0, 0xdcc1, _, NoModrm, { 0, 0, 0} }, /* alias for fadd %st, %st(1) */ +{"faddp", 1, 0xdac0, _, ShortForm, { FloatReg, 0, 0} }, +{"faddp", 2, 0xdac0, _, ShortForm|FloatD, { FloatReg, FloatAcc, 0} }, +{"faddp", 0, 0xdec1, _, NoModrm, { 0, 0, 0} }, /* alias for faddp %st, %st(1) */ +{"fadds", 1, 0xd8, 0, Modrm, { Mem, 0, 0} }, +{"fiaddl", 1, 0xda, 0, Modrm, { Mem, 0, 0} }, +{"faddl", 1, 0xdc, 0, Modrm, { Mem, 0, 0} }, +{"fiadds", 1, 0xde, 0, Modrm, { Mem, 0, 0} }, + +/* sub */ +/* Note: intel has decided that certain of these operations are reversed + in assembler syntax. */ +{"fsub", 1, 0xd8e0, _, ShortForm, { FloatReg, 0, 0} }, +{"fsub", 2, 0xd8e0, _, ShortForm, { FloatReg, FloatAcc, 0} }, +#ifdef NON_BROKEN_OPCODES +{"fsub", 2, 0xdce8, _, ShortForm, { FloatAcc, FloatReg, 0} }, +#else +{"fsub", 2, 0xdce0, _, ShortForm, { FloatAcc, FloatReg, 0} }, +#endif +{"fsub", 0, 0xdce1, _, NoModrm, { 0, 0, 0} }, +{"fsubp", 1, 0xdae0, _, ShortForm, { FloatReg, 0, 0} }, +{"fsubp", 2, 0xdae0, _, ShortForm, { FloatReg, FloatAcc, 0} }, +#ifdef NON_BROKEN_OPCODES +{"fsubp", 2, 0xdee8, _, ShortForm, { FloatAcc, FloatReg, 0} }, +#else +{"fsubp", 2, 0xdee0, _, ShortForm, { FloatAcc, FloatReg, 0} }, +#endif +{"fsubp", 0, 0xdee1, _, NoModrm, { 0, 0, 0} }, +{"fsubs", 1, 0xd8, 4, Modrm, { Mem, 0, 0} }, +{"fisubl", 1, 0xda, 4, Modrm, { Mem, 0, 0} }, +{"fsubl", 1, 0xdc, 4, Modrm, { Mem, 0, 0} }, +{"fisubs", 1, 0xde, 4, Modrm, { Mem, 0, 0} }, + +/* sub reverse */ +{"fsubr", 1, 0xd8e8, _, ShortForm, { FloatReg, 0, 0} }, +{"fsubr", 2, 0xd8e8, _, ShortForm, { FloatReg, FloatAcc, 0} }, +#ifdef NON_BROKEN_OPCODES +{"fsubr", 2, 0xdce0, _, ShortForm, { FloatAcc, FloatReg, 0} }, +#else +{"fsubr", 2, 0xdce8, _, ShortForm, { FloatAcc, FloatReg, 0} }, +#endif +{"fsubr", 0, 0xdce9, _, NoModrm, { 0, 0, 0} }, +{"fsubrp", 1, 0xdae8, _, ShortForm, { FloatReg, 0, 0} }, +{"fsubrp", 2, 0xdae8, _, ShortForm, { FloatReg, FloatAcc, 0} }, +#ifdef NON_BROKEN_OPCODES +{"fsubrp", 2, 0xdee0, _, ShortForm, { FloatAcc, FloatReg, 0} }, +#else +{"fsubrp", 2, 0xdee8, _, ShortForm, { FloatAcc, FloatReg, 0} }, +#endif +{"fsubrp", 0, 0xdee9, _, NoModrm, { 0, 0, 0} }, +{"fsubrs", 1, 0xd8, 5, Modrm, { Mem, 0, 0} }, +{"fisubrl", 1, 0xda, 5, Modrm, { Mem, 0, 0} }, +{"fsubrl", 1, 0xdc, 5, Modrm, { Mem, 0, 0} }, +{"fisubrs", 1, 0xde, 5, Modrm, { Mem, 0, 0} }, + +/* mul */ +{"fmul", 1, 0xd8c8, _, ShortForm, { FloatReg, 0, 0} }, +{"fmul", 2, 0xd8c8, _, ShortForm|FloatD, { FloatReg, FloatAcc, 0} }, +{"fmul", 0, 0xdcc9, _, NoModrm, { 0, 0, 0} }, +{"fmulp", 1, 0xdac8, _, ShortForm, { FloatReg, 0, 0} }, +{"fmulp", 2, 0xdac8, _, ShortForm|FloatD, { FloatReg, FloatAcc, 0} }, +{"fmulp", 0, 0xdec9, _, NoModrm, { 0, 0, 0} }, +{"fmuls", 1, 0xd8, 1, Modrm, { Mem, 0, 0} }, +{"fimull", 1, 0xda, 1, Modrm, { Mem, 0, 0} }, +{"fmull", 1, 0xdc, 1, Modrm, { Mem, 0, 0} }, +{"fimuls", 1, 0xde, 1, Modrm, { Mem, 0, 0} }, + +/* div */ +/* Note: intel has decided that certain of these operations are reversed + in assembler syntax. */ +{"fdiv", 1, 0xd8f0, _, ShortForm, { FloatReg, 0, 0} }, +{"fdiv", 2, 0xd8f0, _, ShortForm, { FloatReg, FloatAcc, 0} }, +#ifdef NON_BROKEN_OPCODES +{"fdiv", 2, 0xdcf8, _, ShortForm, { FloatAcc, FloatReg, 0} }, +#else +{"fdiv", 2, 0xdcf0, _, ShortForm, { FloatAcc, FloatReg, 0} }, +#endif +{"fdiv", 0, 0xdcf1, _, NoModrm, { 0, 0, 0} }, +{"fdivp", 1, 0xdaf0, _, ShortForm, { FloatReg, 0, 0} }, +{"fdivp", 2, 0xdaf0, _, ShortForm, { FloatReg, FloatAcc, 0} }, +#ifdef NON_BROKEN_OPCODES +{"fdivp", 2, 0xdef8, _, ShortForm, { FloatAcc, FloatReg, 0} }, +#else +{"fdivp", 2, 0xdef0, _, ShortForm, { FloatAcc, FloatReg, 0} }, +#endif +{"fdivp", 0, 0xdef1, _, NoModrm, { 0, 0, 0} }, +{"fdivs", 1, 0xd8, 6, Modrm, { Mem, 0, 0} }, +{"fidivl", 1, 0xda, 6, Modrm, { Mem, 0, 0} }, +{"fdivl", 1, 0xdc, 6, Modrm, { Mem, 0, 0} }, +{"fidivs", 1, 0xde, 6, Modrm, { Mem, 0, 0} }, + +/* div reverse */ +{"fdivr", 1, 0xd8f8, _, ShortForm, { FloatReg, 0, 0} }, +{"fdivr", 2, 0xd8f8, _, ShortForm, { FloatReg, FloatAcc, 0} }, +#ifdef NON_BROKEN_OPCODES +{"fdivr", 2, 0xdcf0, _, ShortForm, { FloatAcc, FloatReg, 0} }, +#else +{"fdivr", 2, 0xdcf8, _, ShortForm, { FloatAcc, FloatReg, 0} }, +#endif +{"fdivr", 0, 0xdcf9, _, NoModrm, { 0, 0, 0} }, +{"fdivrp", 1, 0xdaf8, _, ShortForm, { FloatReg, 0, 0} }, +{"fdivrp", 2, 0xdaf8, _, ShortForm, { FloatReg, FloatAcc, 0} }, +#ifdef NON_BROKEN_OPCODES +{"fdivrp", 2, 0xdef0, _, ShortForm, { FloatAcc, FloatReg, 0} }, +#else +{"fdivrp", 2, 0xdef8, _, ShortForm, { FloatAcc, FloatReg, 0} }, +#endif +{"fdivrp", 0, 0xdef9, _, NoModrm, { 0, 0, 0} }, +{"fdivrs", 1, 0xd8, 7, Modrm, { Mem, 0, 0} }, +{"fidivrl", 1, 0xda, 7, Modrm, { Mem, 0, 0} }, +{"fdivrl", 1, 0xdc, 7, Modrm, { Mem, 0, 0} }, +{"fidivrs", 1, 0xde, 7, Modrm, { Mem, 0, 0} }, + +{"f2xm1", 0, 0xd9f0, _, NoModrm, { 0, 0, 0} }, +{"fyl2x", 0, 0xd9f1, _, NoModrm, { 0, 0, 0} }, +{"fptan", 0, 0xd9f2, _, NoModrm, { 0, 0, 0} }, +{"fpatan", 0, 0xd9f3, _, NoModrm, { 0, 0, 0} }, +{"fxtract", 0, 0xd9f4, _, NoModrm, { 0, 0, 0} }, +{"fprem1", 0, 0xd9f5, _, NoModrm, { 0, 0, 0} }, +{"fdecstp", 0, 0xd9f6, _, NoModrm, { 0, 0, 0} }, +{"fincstp", 0, 0xd9f7, _, NoModrm, { 0, 0, 0} }, +{"fprem", 0, 0xd9f8, _, NoModrm, { 0, 0, 0} }, +{"fyl2xp1", 0, 0xd9f9, _, NoModrm, { 0, 0, 0} }, +{"fsqrt", 0, 0xd9fa, _, NoModrm, { 0, 0, 0} }, +{"fsincos", 0, 0xd9fb, _, NoModrm, { 0, 0, 0} }, +{"frndint", 0, 0xd9fc, _, NoModrm, { 0, 0, 0} }, +{"fscale", 0, 0xd9fd, _, NoModrm, { 0, 0, 0} }, +{"fsin", 0, 0xd9fe, _, NoModrm, { 0, 0, 0} }, +{"fcos", 0, 0xd9ff, _, NoModrm, { 0, 0, 0} }, + +{"fchs", 0, 0xd9e0, _, NoModrm, { 0, 0, 0} }, +{"fabs", 0, 0xd9e1, _, NoModrm, { 0, 0, 0} }, + +/* processor control */ +{"fninit", 0, 0xdbe3, _, NoModrm, { 0, 0, 0} }, +{"finit", 0, 0x9bdbe3, _, NoModrm, { 0, 0, 0} }, +{"fldcw", 1, 0xd9, 5, Modrm, { Mem, 0, 0} }, +{"fnstcw", 1, 0xd9, 7, Modrm, { Mem, 0, 0} }, +{"fstcw", 1, 0x9bd9, 7, Modrm, { Mem, 0, 0} }, +{"fnstsw", 1, 0xdfe0, _, NoModrm, { Acc, 0, 0} }, +{"fnstsw", 1, 0xdd, 7, Modrm, { Mem, 0, 0} }, +{"fnstsw", 0, 0xdfe0, _, NoModrm, { 0, 0, 0} }, +{"fstsw", 1, 0x9bdfe0, _, NoModrm, { Acc, 0, 0} }, +{"fstsw", 1, 0x9bdd, 7, Modrm, { Mem, 0, 0} }, +{"fstsw", 0, 0x9bdfe0, _, NoModrm, { 0, 0, 0} }, +{"fnclex", 0, 0xdbe2, _, NoModrm, { 0, 0, 0} }, +{"fclex", 0, 0x9bdbe2, _, NoModrm, { 0, 0, 0} }, +/* + We ignore the short format (287) versions of fstenv/fldenv & fsave/frstor + instructions; i'm not sure how to add them or how they are different. + My 386/387 book offers no details about this. +*/ +{"fnstenv", 1, 0xd9, 6, Modrm, { Mem, 0, 0} }, +{"fstenv", 1, 0x9bd9, 6, Modrm, { Mem, 0, 0} }, +{"fldenv", 1, 0xd9, 4, Modrm, { Mem, 0, 0} }, +{"fnsave", 1, 0xdd, 6, Modrm, { Mem, 0, 0} }, +{"fsave", 1, 0x9bdd, 6, Modrm, { Mem, 0, 0} }, +{"frstor", 1, 0xdd, 4, Modrm, { Mem, 0, 0} }, + +{"ffree", 1, 0xddc0, _, ShortForm, { FloatReg, 0, 0} }, +{"fnop", 0, 0xd9d0, _, NoModrm, { 0, 0, 0} }, +{"fwait", 0, 0x9b, _, NoModrm, { 0, 0, 0} }, + +/* + opcode prefixes; we allow them as seperate insns too + (see prefix table below) +*/ +{"aword", 0, 0x67, _, NoModrm, { 0, 0, 0} }, +{"addr16", 0, 0x67, _, NoModrm, { 0, 0, 0} }, +{"word", 0, 0x66, _, NoModrm, { 0, 0, 0} }, +{"data16", 0, 0x66, _, NoModrm, { 0, 0, 0} }, +{"lock", 0, 0xf0, _, NoModrm, { 0, 0, 0} }, +{"cs", 0, 0x2e, _, NoModrm, { 0, 0, 0} }, +{"ds", 0, 0x3e, _, NoModrm, { 0, 0, 0} }, +{"es", 0, 0x26, _, NoModrm, { 0, 0, 0} }, +{"fs", 0, 0x64, _, NoModrm, { 0, 0, 0} }, +{"gs", 0, 0x65, _, NoModrm, { 0, 0, 0} }, +{"ss", 0, 0x36, _, NoModrm, { 0, 0, 0} }, +{"rep", 0, 0xf3, _, NoModrm, { 0, 0, 0} }, +{"repe", 0, 0xf3, _, NoModrm, { 0, 0, 0} }, +{"repz", 0, 0xf3, _, NoModrm, { 0, 0, 0} }, +{"repne", 0, 0xf2, _, NoModrm, { 0, 0, 0} }, +{"repnz", 0, 0xf2, _, NoModrm, { 0, 0, 0} }, + +/* 486 extensions */ + +{"bswap", 1, 0x0fc8, _, ShortForm, { Reg32,0,0 } }, +{"xadd", 2, 0x0fc0, _, DW|Modrm, { Reg, Reg|Mem, 0 } }, +{"cmpxchg", 2, 0x0fb0, _, DW|Modrm, { Reg, Reg|Mem, 0 } }, +{"invd", 0, 0x0f08, _, NoModrm, { 0, 0, 0} }, +{"wbinvd", 0, 0x0f09, _, NoModrm, { 0, 0, 0} }, +{"invlpg", 1, 0x0f01, 7, Modrm, { Mem, 0, 0} }, + +/* 586 and late 486 extensions */ +{"cpuid", 0, 0x0fa2, _, NoModrm, { 0, 0, 0} }, + +/* Pentium extensions */ +{"wrmsr", 0, 0x0f30, _, NoModrm, { 0, 0, 0} }, +{"rdtsc", 0, 0x0f31, _, NoModrm, { 0, 0, 0} }, +{"rdmsr", 0, 0x0f32, _, NoModrm, { 0, 0, 0} }, +{"cmpxchg8b", 1, 0x0fc7, 1, Modrm, { Mem, 0, 0} }, + +/* Pentium Pro extensions */ +{"rdpmc", 0, 0x0f33, _, NoModrm, { 0, 0, 0} }, + +{"cmovo", 2, 0x0f40, _, W|Modrm|ReverseRegRegmem, { WordReg|WordMem, WordReg, 0} }, +{"cmovno", 2, 0x0f41, _, W|Modrm|ReverseRegRegmem, { WordReg|WordMem, WordReg, 0} }, +{"cmovb", 2, 0x0f42, _, W|Modrm|ReverseRegRegmem, { WordReg|WordMem, WordReg, 0} }, +{"cmovae", 2, 0x0f43, _, W|Modrm|ReverseRegRegmem, { WordReg|WordMem, WordReg, 0} }, +{"cmove", 2, 0x0f44, _, W|Modrm|ReverseRegRegmem, { WordReg|WordMem, WordReg, 0} }, +{"cmovne", 2, 0x0f45, _, W|Modrm|ReverseRegRegmem, { WordReg|WordMem, WordReg, 0} }, +{"cmovbe", 2, 0x0f46, _, W|Modrm|ReverseRegRegmem, { WordReg|WordMem, WordReg, 0} }, +{"cmova", 2, 0x0f47, _, W|Modrm|ReverseRegRegmem, { WordReg|WordMem, WordReg, 0} }, +{"cmovs", 2, 0x0f48, _, W|Modrm|ReverseRegRegmem, { WordReg|WordMem, WordReg, 0} }, +{"cmovns", 2, 0x0f49, _, W|Modrm|ReverseRegRegmem, { WordReg|WordMem, WordReg, 0} }, +{"cmovp", 2, 0x0f4a, _, W|Modrm|ReverseRegRegmem, { WordReg|WordMem, WordReg, 0} }, +{"cmovnp", 2, 0x0f4b, _, W|Modrm|ReverseRegRegmem, { WordReg|WordMem, WordReg, 0} }, +{"cmovl", 2, 0x0f4c, _, W|Modrm|ReverseRegRegmem, { WordReg|WordMem, WordReg, 0} }, +{"cmovge", 2, 0x0f4d, _, W|Modrm|ReverseRegRegmem, { WordReg|WordMem, WordReg, 0} }, +{"cmovle", 2, 0x0f4e, _, W|Modrm|ReverseRegRegmem, { WordReg|WordMem, WordReg, 0} }, +{"cmovg", 2, 0x0f4f, _, W|Modrm|ReverseRegRegmem, { WordReg|WordMem, WordReg, 0} }, + +{"fcmovb", 2, 0xdac0, _, ShortForm, { FloatReg, FloatAcc, 0} }, +{"fcmove", 2, 0xdac8, _, ShortForm, { FloatReg, FloatAcc, 0} }, +{"fcmovbe",2, 0xdad0, _, ShortForm, { FloatReg, FloatAcc, 0} }, +{"fcmovu", 2, 0xdad8, _, ShortForm, { FloatReg, FloatAcc, 0} }, +{"fcmovnb", 2, 0xdbc0, _, ShortForm, { FloatReg, FloatAcc, 0} }, +{"fcmovne", 2, 0xdbc8, _, ShortForm, { FloatReg, FloatAcc, 0} }, +{"fcmovnbe",2, 0xdbd0, _, ShortForm, { FloatReg, FloatAcc, 0} }, +{"fcmovnu", 2, 0xdbd8, _, ShortForm, { FloatReg, FloatAcc, 0} }, + +{"fcomi", 2, 0xdbf0, _, ShortForm, { FloatReg, FloatAcc, 0} }, +{"fucomi", 2, 0xdbe8, _, ShortForm, { FloatReg, FloatAcc, 0} }, +{"fcomip", 2, 0xdff0, _, ShortForm, { FloatReg, FloatAcc, 0} }, +{"fucomip",2, 0xdfe8, _, ShortForm, { FloatReg, FloatAcc, 0} }, + +{"", 0, 0, 0, 0, { 0, 0, 0} } /* sentinel */ +}; +#undef _ + +static const template *const i386_optab_end + = i386_optab + sizeof (i386_optab)/sizeof(i386_optab[0]); + +/* 386 register table */ + +static const reg_entry i386_regtab[] = { + /* 8 bit regs */ + {"al", Reg8|Acc, 0}, {"cl", Reg8|ShiftCount, 1}, {"dl", Reg8, 2}, + {"bl", Reg8, 3}, + {"ah", Reg8, 4}, {"ch", Reg8, 5}, {"dh", Reg8, 6}, {"bh", Reg8, 7}, + /* 16 bit regs */ + {"ax", Reg16|Acc, 0}, {"cx", Reg16, 1}, {"dx", Reg16|InOutPortReg, 2}, {"bx", Reg16, 3}, + {"sp", Reg16, 4}, {"bp", Reg16, 5}, {"si", Reg16, 6}, {"di", Reg16, 7}, + /* 32 bit regs */ + {"eax", Reg32|Acc, 0}, {"ecx", Reg32, 1}, {"edx", Reg32, 2}, {"ebx", Reg32, 3}, + {"esp", Reg32, 4}, {"ebp", Reg32, 5}, {"esi", Reg32, 6}, {"edi", Reg32, 7}, + /* segment registers */ + {"es", SReg2, 0}, {"cs", SReg2, 1}, {"ss", SReg2, 2}, + {"ds", SReg2, 3}, {"fs", SReg3, 4}, {"gs", SReg3, 5}, + /* control registers */ + {"cr0", Control, 0}, {"cr2", Control, 2}, {"cr3", Control, 3}, + {"cr4", Control, 4}, + /* debug registers */ + {"db0", Debug, 0}, {"db1", Debug, 1}, {"db2", Debug, 2}, + {"db3", Debug, 3}, {"db6", Debug, 6}, {"db7", Debug, 7}, + {"dr0", Debug, 0}, {"dr1", Debug, 1}, {"dr2", Debug, 2}, + {"dr3", Debug, 3}, {"dr6", Debug, 6}, {"dr7", Debug, 7}, + /* test registers */ + {"tr3", Test, 3}, {"tr4", Test, 4}, {"tr5", Test, 5}, + {"tr6", Test, 6}, {"tr7", Test, 7}, + /* float registers */ + {"st(0)", FloatReg|FloatAcc, 0}, + {"st", FloatReg|FloatAcc, 0}, + {"st(1)", FloatReg, 1}, {"st(2)", FloatReg, 2}, + {"st(3)", FloatReg, 3}, {"st(4)", FloatReg, 4}, {"st(5)", FloatReg, 5}, + {"st(6)", FloatReg, 6}, {"st(7)", FloatReg, 7} +}; + +#define MAX_REG_NAME_SIZE 8 /* for parsing register names from input */ + +static const reg_entry *const i386_regtab_end + = i386_regtab + sizeof(i386_regtab)/sizeof(i386_regtab[0]); + +/* segment stuff */ +static const seg_entry cs = { "cs", 0x2e }; +static const seg_entry ds = { "ds", 0x3e }; +static const seg_entry ss = { "ss", 0x36 }; +static const seg_entry es = { "es", 0x26 }; +static const seg_entry fs = { "fs", 0x64 }; +static const seg_entry gs = { "gs", 0x65 }; +static const seg_entry null = { "", 0x0 }; + +/* + This table is used to store the default segment register implied by all + possible memory addressing modes. + It is indexed by the mode & modrm entries of the modrm byte as follows: + index = (mode<<3) | modrm; +*/ +static const seg_entry *const one_byte_segment_defaults[] = { + /* mode 0 */ + &ds, &ds, &ds, &ds, &null, &ds, &ds, &ds, + /* mode 1 */ + &ds, &ds, &ds, &ds, &null, &ss, &ds, &ds, + /* mode 2 */ + &ds, &ds, &ds, &ds, &null, &ss, &ds, &ds, + /* mode 3 --- not a memory reference; never referenced */ +}; + +static const seg_entry *const two_byte_segment_defaults[] = { + /* mode 0 */ + &ds, &ds, &ds, &ds, &ss, &ds, &ds, &ds, + /* mode 1 */ + &ds, &ds, &ds, &ds, &ss, &ds, &ds, &ds, + /* mode 2 */ + &ds, &ds, &ds, &ds, &ss, &ds, &ds, &ds, + /* mode 3 --- not a memory reference; never referenced */ +}; + +static const prefix_entry i386_prefixtab[] = { +#define ADDR_PREFIX_OPCODE 0x67 + { "addr16", 0x67 }, /* address size prefix ==> 16bit addressing + * (How is this useful?) */ +#define WORD_PREFIX_OPCODE 0x66 + { "data16", 0x66 }, /* operand size prefix */ + { "lock", 0xf0 }, /* bus lock prefix */ + { "wait", 0x9b }, /* wait for coprocessor */ + { "cs", 0x2e }, { "ds", 0x3e }, /* segment overrides ... */ + { "es", 0x26 }, { "fs", 0x64 }, + { "gs", 0x65 }, { "ss", 0x36 }, +/* REPE & REPNE used to detect rep/repne with a non-string instruction */ +#define REPNE 0xf2 +#define REPE 0xf3 + { "rep", 0xf3 }, /* repeat string instructions */ + { "repe", 0xf3 }, { "repz", 0xf3 }, + { "repne", 0xf2 }, { "repnz", 0xf2 } +}; + +static const prefix_entry *const i386_prefixtab_end + = i386_prefixtab + sizeof(i386_prefixtab)/sizeof(i386_prefixtab[0]); + +/* end of i386-opcode.h */ diff --git a/opcode/ppc-dis.c b/opcode/ppc-dis.c new file mode 100644 index 000000000..70716ea24 --- /dev/null +++ b/opcode/ppc-dis.c @@ -0,0 +1,238 @@ +/* ppc-dis.c -- Disassemble PowerPC instructions + Copyright 1994 Free Software Foundation, Inc. + Written by Ian Lance Taylor, Cygnus Support + +This file is part of GDB, GAS, and the GNU binutils. + +GDB, GAS, and the GNU binutils are free software; you can redistribute +them and/or modify them under the terms of the GNU General Public +License as published by the Free Software Foundation; either version +2, or (at your option) any later version. + +GDB, GAS, and the GNU binutils are distributed in the hope that they +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 file; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include +#include "ansidecl.h" +#include "sysdep.h" +#include "dis-asm.h" +#include "opcode/ppc.h" + +/* This file provides several disassembler functions, all of which use + the disassembler interface defined in dis-asm.h. Several functions + are provided because this file handles disassembly for the PowerPC + in both big and little endian mode and also for the POWER (RS/6000) + chip. */ + +static int print_insn_powerpc PARAMS ((bfd_vma, struct disassemble_info *, + int bigendian, int dialect)); + +/* Print a big endian PowerPC instruction. For convenience, also + disassemble instructions supported by the Motorola PowerPC 601. */ + +int +print_insn_big_powerpc (memaddr, info) + bfd_vma memaddr; + struct disassemble_info *info; +{ + return print_insn_powerpc (memaddr, info, 1, + PPC_OPCODE_PPC | PPC_OPCODE_601); +} + +/* Print a little endian PowerPC instruction. For convenience, also + disassemble instructions supported by the Motorola PowerPC 601. */ + +int +print_insn_little_powerpc (memaddr, info) + bfd_vma memaddr; + struct disassemble_info *info; +{ + return print_insn_powerpc (memaddr, info, 0, + PPC_OPCODE_PPC | PPC_OPCODE_601); +} + +/* Print a POWER (RS/6000) instruction. */ + +int +print_insn_rs6000 (memaddr, info) + bfd_vma memaddr; + struct disassemble_info *info; +{ + return print_insn_powerpc (memaddr, info, 1, PPC_OPCODE_POWER); +} + +/* Print a PowerPC or POWER instruction. */ + +static int +print_insn_powerpc (memaddr, info, bigendian, dialect) + bfd_vma memaddr; + struct disassemble_info *info; + int bigendian; + int dialect; +{ + bfd_byte buffer[4]; + int status; + unsigned long insn; + const struct powerpc_opcode *opcode; + const struct powerpc_opcode *opcode_end; + unsigned long op; + + status = (*info->read_memory_func) (memaddr, buffer, 4, info); + if (status != 0) + { + (*info->memory_error_func) (status, memaddr, info); + return -1; + } + + if (bigendian) + insn = bfd_getb32 (buffer); + else + insn = bfd_getl32 (buffer); + + /* Get the major opcode of the instruction. */ + op = PPC_OP (insn); + + /* Find the first match in the opcode table. We could speed this up + a bit by doing a binary search on the major opcode. */ + opcode_end = powerpc_opcodes + powerpc_num_opcodes; + for (opcode = powerpc_opcodes; opcode < opcode_end; opcode++) + { + unsigned long table_op; + const unsigned char *opindex; + const struct powerpc_operand *operand; + int invalid; + int need_comma; + int need_paren; + + table_op = PPC_OP (opcode->opcode); + if (op < table_op) + break; + if (op > table_op) + continue; + + if ((insn & opcode->mask) != opcode->opcode + || (opcode->flags & dialect) == 0) + continue; + + /* Make two passes over the operands. First see if any of them + have extraction functions, and, if they do, make sure the + instruction is valid. */ + invalid = 0; + for (opindex = opcode->operands; *opindex != 0; opindex++) + { + operand = powerpc_operands + *opindex; + if (operand->extract) + (*operand->extract) (insn, &invalid); + } + if (invalid) + continue; + + /* The instruction is valid. */ + (*info->fprintf_func) (info->stream, "%s", opcode->name); + if (opcode->operands[0] != 0) + (*info->fprintf_func) (info->stream, "\t"); + + /* Now extract and print the operands. */ + need_comma = 0; + need_paren = 0; + for (opindex = opcode->operands; *opindex != 0; opindex++) + { + long value; + + operand = powerpc_operands + *opindex; + + /* Operands that are marked FAKE are simply ignored. We + already made sure that the extract function considered + the instruction to be valid. */ + if ((operand->flags & PPC_OPERAND_FAKE) != 0) + continue; + + /* Extract the value from the instruction. */ + if (operand->extract) + value = (*operand->extract) (insn, (int *) NULL); + else + { + value = (insn >> operand->shift) & ((1 << operand->bits) - 1); + if ((operand->flags & PPC_OPERAND_SIGNED) != 0 + && (value & (1 << (operand->bits - 1))) != 0) + value -= 1 << operand->bits; + } + + /* If the operand is optional, and the value is zero, don't + print anything. */ + if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0 + && (operand->flags & PPC_OPERAND_NEXT) == 0 + && value == 0) + continue; + + if (need_comma) + { + (*info->fprintf_func) (info->stream, ","); + need_comma = 0; + } + + /* Print the operand as directed by the flags. */ + if ((operand->flags & PPC_OPERAND_GPR) != 0) + (*info->fprintf_func) (info->stream, "r%ld", value); + else if ((operand->flags & PPC_OPERAND_FPR) != 0) + (*info->fprintf_func) (info->stream, "f%ld", value); + else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0) + (*info->print_address_func) (memaddr + value, info); + else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0) + (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info); + else if ((operand->flags & PPC_OPERAND_CR) == 0 + || (dialect & PPC_OPCODE_PPC) == 0) + (*info->fprintf_func) (info->stream, "%ld", value); + else + { + if (operand->bits == 3) + (*info->fprintf_func) (info->stream, "cr%d", value); + else + { + static const char *cbnames[4] = { "lt", "gt", "eq", "so" }; + int cr; + int cc; + + cr = value >> 2; + if (cr != 0) + (*info->fprintf_func) (info->stream, "4*cr%d", cr); + cc = value & 3; + if (cc != 0) + { + if (cr != 0) + (*info->fprintf_func) (info->stream, "+"); + (*info->fprintf_func) (info->stream, "%s", cbnames[cc]); + } + } + } + + if (need_paren) + { + (*info->fprintf_func) (info->stream, ")"); + need_paren = 0; + } + + if ((operand->flags & PPC_OPERAND_PARENS) == 0) + need_comma = 1; + else + { + (*info->fprintf_func) (info->stream, "("); + need_paren = 1; + } + } + + /* We have found and printed an instruction; return. */ + return 4; + } + + /* We could not find a match. */ + (*info->fprintf_func) (info->stream, ".long 0x%lx", insn); + + return 4; +} diff --git a/opcode/ppc-opc.c b/opcode/ppc-opc.c new file mode 100644 index 000000000..3e11db9b4 --- /dev/null +++ b/opcode/ppc-opc.c @@ -0,0 +1,2830 @@ +/* ppc-opc.c -- PowerPC opcode list + Copyright 1994 Free Software Foundation, Inc. + Written by Ian Lance Taylor, Cygnus Support + +This file is part of GDB, GAS, and the GNU binutils. + +GDB, GAS, and the GNU binutils are free software; you can redistribute +them and/or modify them under the terms of the GNU General Public +License as published by the Free Software Foundation; either version +2, or (at your option) any later version. + +GDB, GAS, and the GNU binutils are distributed in the hope that they +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 file; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include +#include "ansidecl.h" +#include "opcode/ppc.h" + +/* This file holds the PowerPC opcode table. The opcode table + includes almost all of the extended instruction mnemonics. This + permits the disassembler to use them, and simplifies the assembler + logic, at the cost of increasing the table size. The table is + strictly constant data, so the compiler should be able to put it in + the .text section. + + This file also holds the operand table. All knowledge about + inserting operands into instructions and vice-versa is kept in this + file. */ + +/* Local insertion and extraction functions. */ + +static unsigned long insert_bat PARAMS ((unsigned long, long, const char **)); +static long extract_bat PARAMS ((unsigned long, int *)); +static unsigned long insert_bba PARAMS ((unsigned long, long, const char **)); +static long extract_bba PARAMS ((unsigned long, int *)); +static unsigned long insert_bd PARAMS ((unsigned long, long, const char **)); +static long extract_bd PARAMS ((unsigned long, int *)); +static unsigned long insert_bdm PARAMS ((unsigned long, long, const char **)); +static long extract_bdm PARAMS ((unsigned long, int *)); +static unsigned long insert_bdp PARAMS ((unsigned long, long, const char **)); +static long extract_bdp PARAMS ((unsigned long, int *)); +static unsigned long insert_bo PARAMS ((unsigned long, long, const char **)); +static long extract_bo PARAMS ((unsigned long, int *)); +static unsigned long insert_boe PARAMS ((unsigned long, long, const char **)); +static long extract_boe PARAMS ((unsigned long, int *)); +static unsigned long insert_ds PARAMS ((unsigned long, long, const char **)); +static long extract_ds PARAMS ((unsigned long, int *)); +static unsigned long insert_li PARAMS ((unsigned long, long, const char **)); +static long extract_li PARAMS ((unsigned long, int *)); +static unsigned long insert_mbe PARAMS ((unsigned long, long, const char **)); +static long extract_mbe PARAMS ((unsigned long, int *)); +static unsigned long insert_mb6 PARAMS ((unsigned long, long, const char **)); +static long extract_mb6 PARAMS ((unsigned long, int *)); +static unsigned long insert_nb PARAMS ((unsigned long, long, const char **)); +static long extract_nb PARAMS ((unsigned long, int *)); +static unsigned long insert_nsi PARAMS ((unsigned long, long, const char **)); +static long extract_nsi PARAMS ((unsigned long, int *)); +static unsigned long insert_ral PARAMS ((unsigned long, long, const char **)); +static unsigned long insert_ram PARAMS ((unsigned long, long, const char **)); +static unsigned long insert_ras PARAMS ((unsigned long, long, const char **)); +static unsigned long insert_rbs PARAMS ((unsigned long, long, const char **)); +static long extract_rbs PARAMS ((unsigned long, int *)); +static unsigned long insert_sh6 PARAMS ((unsigned long, long, const char **)); +static long extract_sh6 PARAMS ((unsigned long, int *)); +static unsigned long insert_spr PARAMS ((unsigned long, long, const char **)); +static long extract_spr PARAMS ((unsigned long, int *)); +static unsigned long insert_tbr PARAMS ((unsigned long, long, const char **)); +static long extract_tbr PARAMS ((unsigned long, int *)); + +/* The operands table. + + The fields are bits, shift, signed, insert, extract, flags. */ + +const struct powerpc_operand powerpc_operands[] = +{ + /* The zero index is used to indicate the end of the list of + operands. */ +#define UNUSED (0) + { 0, 0, 0, 0, 0 }, + + /* The BA field in an XL form instruction. */ +#define BA (UNUSED + 1) +#define BA_MASK (0x1f << 16) + { 5, 16, 0, 0, PPC_OPERAND_CR }, + + /* The BA field in an XL form instruction when it must be the same + as the BT field in the same instruction. */ +#define BAT (BA + 1) + { 5, 16, insert_bat, extract_bat, PPC_OPERAND_FAKE }, + + /* The BB field in an XL form instruction. */ +#define BB (BAT + 1) +#define BB_MASK (0x1f << 11) + { 5, 11, 0, 0, PPC_OPERAND_CR }, + + /* The BB field in an XL form instruction when it must be the same + as the BA field in the same instruction. */ +#define BBA (BB + 1) + { 5, 11, insert_bba, extract_bba, PPC_OPERAND_FAKE }, + + /* The BD field in a B form instruction. The lower two bits are + forced to zero. */ +#define BD (BBA + 1) + { 16, 0, insert_bd, extract_bd, PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED }, + + /* The BD field in a B form instruction when absolute addressing is + used. */ +#define BDA (BD + 1) + { 16, 0, insert_bd, extract_bd, PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED }, + + /* The BD field in a B form instruction when the - modifier is used. + This sets the y bit of the BO field appropriately. */ +#define BDM (BDA + 1) + { 16, 0, insert_bdm, extract_bdm, + PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED }, + + /* The BD field in a B form instruction when the - modifier is used + and absolute address is used. */ +#define BDMA (BDM + 1) + { 16, 0, insert_bdm, extract_bdm, + PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED }, + + /* The BD field in a B form instruction when the + modifier is used. + This sets the y bit of the BO field appropriately. */ +#define BDP (BDMA + 1) + { 16, 0, insert_bdp, extract_bdp, + PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED }, + + /* The BD field in a B form instruction when the + modifier is used + and absolute addressing is used. */ +#define BDPA (BDP + 1) + { 16, 0, insert_bdp, extract_bdp, + PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED }, + + /* The BF field in an X or XL form instruction. */ +#define BF (BDPA + 1) + { 3, 23, 0, 0, PPC_OPERAND_CR }, + + /* An optional BF field. This is used for comparison instructions, + in which an omitted BF field is taken as zero. */ +#define OBF (BF + 1) + { 3, 23, 0, 0, PPC_OPERAND_CR | PPC_OPERAND_OPTIONAL }, + + /* The BFA field in an X or XL form instruction. */ +#define BFA (OBF + 1) + { 3, 18, 0, 0, PPC_OPERAND_CR }, + + /* The BI field in a B form or XL form instruction. */ +#define BI (BFA + 1) +#define BI_MASK (0x1f << 16) + { 5, 16, 0, 0, PPC_OPERAND_CR }, + + /* The BO field in a B form instruction. Certain values are + illegal. */ +#define BO (BI + 1) +#define BO_MASK (0x1f << 21) + { 5, 21, insert_bo, extract_bo, 0 }, + + /* The BO field in a B form instruction when the + or - modifier is + used. This is like the BO field, but it must be even. */ +#define BOE (BO + 1) + { 5, 21, insert_boe, extract_boe, 0 }, + + /* The BT field in an X or XL form instruction. */ +#define BT (BOE + 1) + { 5, 21, 0, 0, PPC_OPERAND_CR }, + + /* The condition register number portion of the BI field in a B form + or XL form instruction. This is used for the extended + conditional branch mnemonics, which set the lower two bits of the + BI field. This field is optional. */ +#define CR (BT + 1) + { 3, 18, 0, 0, PPC_OPERAND_CR | PPC_OPERAND_OPTIONAL }, + + /* The D field in a D form instruction. This is a displacement off + a register, and implies that the next operand is a register in + parentheses. */ +#define D (CR + 1) + { 16, 0, 0, 0, PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED }, + + /* The DS field in a DS form instruction. This is like D, but the + lower two bits are forced to zero. */ +#define DS (D + 1) + { 16, 0, insert_ds, extract_ds, PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED }, + + /* The FL1 field in a POWER SC form instruction. */ +#define FL1 (DS + 1) + { 4, 12, 0, 0, 0 }, + + /* The FL2 field in a POWER SC form instruction. */ +#define FL2 (FL1 + 1) + { 3, 2, 0, 0, 0 }, + + /* The FLM field in an XFL form instruction. */ +#define FLM (FL2 + 1) + { 8, 17, 0, 0, 0 }, + + /* The FRA field in an X or A form instruction. */ +#define FRA (FLM + 1) +#define FRA_MASK (0x1f << 16) + { 5, 16, 0, 0, PPC_OPERAND_FPR }, + + /* The FRB field in an X or A form instruction. */ +#define FRB (FRA + 1) +#define FRB_MASK (0x1f << 11) + { 5, 11, 0, 0, PPC_OPERAND_FPR }, + + /* The FRC field in an A form instruction. */ +#define FRC (FRB + 1) +#define FRC_MASK (0x1f << 6) + { 5, 6, 0, 0, PPC_OPERAND_FPR }, + + /* The FRS field in an X form instruction or the FRT field in a D, X + or A form instruction. */ +#define FRS (FRC + 1) +#define FRT (FRS) + { 5, 21, 0, 0, PPC_OPERAND_FPR }, + + /* The FXM field in an XFX instruction. */ +#define FXM (FRS + 1) +#define FXM_MASK (0xff << 12) + { 8, 12, 0, 0, 0 }, + + /* The L field in a D or X form instruction. */ +#define L (FXM + 1) + { 1, 21, 0, 0, PPC_OPERAND_OPTIONAL }, + + /* The LEV field in a POWER SC form instruction. */ +#define LEV (L + 1) + { 7, 5, 0, 0, 0 }, + + /* The LI field in an I form instruction. The lower two bits are + forced to zero. */ +#define LI (LEV + 1) + { 26, 0, insert_li, extract_li, PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED }, + + /* The LI field in an I form instruction when used as an absolute + address. */ +#define LIA (LI + 1) + { 26, 0, insert_li, extract_li, PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED }, + + /* The MB field in an M form instruction. */ +#define MB (LIA + 1) +#define MB_MASK (0x1f << 6) + { 5, 6, 0, 0, 0 }, + + /* The ME field in an M form instruction. */ +#define ME (MB + 1) +#define ME_MASK (0x1f << 1) + { 5, 1, 0, 0, 0 }, + + /* The MB and ME fields in an M form instruction expressed a single + operand which is a bitmask indicating which bits to select. This + is a two operand form using PPC_OPERAND_NEXT. See the + description in opcode/ppc.h for what this means. */ +#define MBE (ME + 1) + { 5, 6, 0, 0, PPC_OPERAND_OPTIONAL | PPC_OPERAND_NEXT }, + { 32, 0, insert_mbe, extract_mbe, 0 }, + + /* The MB or ME field in an MD or MDS form instruction. The high + bit is wrapped to the low end. */ +#define MB6 (MBE + 2) +#define ME6 (MB6) +#define MB6_MASK (0x3f << 5) + { 6, 5, insert_mb6, extract_mb6, 0 }, + + /* The NB field in an X form instruction. The value 32 is stored as + 0. */ +#define NB (MB6 + 1) + { 6, 11, insert_nb, extract_nb, 0 }, + + /* The NSI field in a D form instruction. This is the same as the + SI field, only negated. */ +#define NSI (NB + 1) + { 16, 0, insert_nsi, extract_nsi, + PPC_OPERAND_NEGATIVE | PPC_OPERAND_SIGNED }, + + /* The RA field in an D, DS, X, XO, M, or MDS form instruction. */ +#define RA (NSI + 1) +#define RA_MASK (0x1f << 16) + { 5, 16, 0, 0, PPC_OPERAND_GPR }, + + /* The RA field in a D or X form instruction which is an updating + load, which means that the RA field may not be zero and may not + equal the RT field. */ +#define RAL (RA + 1) + { 5, 16, insert_ral, 0, PPC_OPERAND_GPR }, + + /* The RA field in an lmw instruction, which has special value + restrictions. */ +#define RAM (RAL + 1) + { 5, 16, insert_ram, 0, PPC_OPERAND_GPR }, + + /* The RA field in a D or X form instruction which is an updating + store or an updating floating point load, which means that the RA + field may not be zero. */ +#define RAS (RAM + 1) + { 5, 16, insert_ras, 0, PPC_OPERAND_GPR }, + + /* The RB field in an X, XO, M, or MDS form instruction. */ +#define RB (RAS + 1) +#define RB_MASK (0x1f << 11) + { 5, 11, 0, 0, PPC_OPERAND_GPR }, + + /* The RB field in an X form instruction when it must be the same as + the RS field in the instruction. This is used for extended + mnemonics like mr. */ +#define RBS (RB + 1) + { 5, 1, insert_rbs, extract_rbs, PPC_OPERAND_FAKE }, + + /* The RS field in a D, DS, X, XFX, XS, M, MD or MDS form + instruction or the RT field in a D, DS, X, XFX or XO form + instruction. */ +#define RS (RBS + 1) +#define RT (RS) +#define RT_MASK (0x1f << 21) + { 5, 21, 0, 0, PPC_OPERAND_GPR }, + + /* The SH field in an X or M form instruction. */ +#define SH (RS + 1) +#define SH_MASK (0x1f << 11) + { 5, 11, 0, 0, 0 }, + + /* The SH field in an MD form instruction. This is split. */ +#define SH6 (SH + 1) +#define SH6_MASK ((0x1f << 11) | (1 << 1)) + { 6, 1, insert_sh6, extract_sh6, 0 }, + + /* The SI field in a D form instruction. */ +#define SI (SH6 + 1) + { 16, 0, 0, 0, PPC_OPERAND_SIGNED }, + + /* The SI field in a D form instruction when we accept a wide range + of positive values. */ +#define SISIGNOPT (SI + 1) + { 16, 0, 0, 0, PPC_OPERAND_SIGNED | PPC_OPERAND_SIGNOPT }, + + /* The SPR field in an XFX form instruction. This is flipped--the + lower 5 bits are stored in the upper 5 and vice- versa. */ +#define SPR (SISIGNOPT + 1) +#define SPR_MASK (0x3ff << 11) + { 10, 11, insert_spr, extract_spr, 0 }, + + /* The BAT index number in an XFX form m[ft]ibat[lu] instruction. */ +#define SPRBAT (SPR + 1) +#define SPRBAT_MASK (0x3 << 17) + { 2, 17, 0, 0, 0 }, + + /* The SPRG register number in an XFX form m[ft]sprg instruction. */ +#define SPRG (SPRBAT + 1) +#define SPRG_MASK (0x3 << 16) + { 2, 16, 0, 0, 0 }, + + /* The SR field in an X form instruction. */ +#define SR (SPRG + 1) + { 4, 16, 0, 0, 0 }, + + /* The SV field in a POWER SC form instruction. */ +#define SV (SR + 1) + { 14, 2, 0, 0, 0 }, + + /* The TBR field in an XFX form instruction. This is like the SPR + field, but it is optional. */ +#define TBR (SV + 1) + { 10, 11, insert_tbr, extract_tbr, PPC_OPERAND_OPTIONAL }, + + /* The TO field in a D or X form instruction. */ +#define TO (TBR + 1) +#define TO_MASK (0x1f << 21) + { 5, 21, 0, 0, 0 }, + + /* The U field in an X form instruction. */ +#define U (TO + 1) + { 4, 12, 0, 0, 0 }, + + /* The UI field in a D form instruction. */ +#define UI (U + 1) + { 16, 0, 0, 0, 0 }, +}; + +/* The functions used to insert and extract complicated operands. */ + +/* The BA field in an XL form instruction when it must be the same as + the BT field in the same instruction. This operand is marked FAKE. + The insertion function just copies the BT field into the BA field, + and the extraction function just checks that the fields are the + same. */ + +/*ARGSUSED*/ +static unsigned long +insert_bat (insn, value, errmsg) + unsigned long insn; + long value; + const char **errmsg; +{ + return insn | (((insn >> 21) & 0x1f) << 16); +} + +static long +extract_bat (insn, invalid) + unsigned long insn; + int *invalid; +{ + if (invalid != (int *) NULL + && ((insn >> 21) & 0x1f) != ((insn >> 16) & 0x1f)) + *invalid = 1; + return 0; +} + +/* The BB field in an XL form instruction when it must be the same as + the BA field in the same instruction. This operand is marked FAKE. + The insertion function just copies the BA field into the BB field, + and the extraction function just checks that the fields are the + same. */ + +/*ARGSUSED*/ +static unsigned long +insert_bba (insn, value, errmsg) + unsigned long insn; + long value; + const char **errmsg; +{ + return insn | (((insn >> 16) & 0x1f) << 11); +} + +static long +extract_bba (insn, invalid) + unsigned long insn; + int *invalid; +{ + if (invalid != (int *) NULL + && ((insn >> 16) & 0x1f) != ((insn >> 11) & 0x1f)) + *invalid = 1; + return 0; +} + +/* The BD field in a B form instruction. The lower two bits are + forced to zero. */ + +/*ARGSUSED*/ +static unsigned long +insert_bd (insn, value, errmsg) + unsigned long insn; + long value; + const char **errmsg; +{ + return insn | (value & 0xfffc); +} + +/*ARGSUSED*/ +static long +extract_bd (insn, invalid) + unsigned long insn; + int *invalid; +{ + if ((insn & 0x8000) != 0) + return (insn & 0xfffc) - 0x10000; + else + return insn & 0xfffc; +} + +/* The BD field in a B form instruction when the - modifier is used. + This modifier means that the branch is not expected to be taken. + We must set the y bit of the BO field to 1 if the offset is + negative. When extracting, we require that the y bit be 1 and that + the offset be positive, since if the y bit is 0 we just want to + print the normal form of the instruction. */ + +/*ARGSUSED*/ +static unsigned long +insert_bdm (insn, value, errmsg) + unsigned long insn; + long value; + const char **errmsg; +{ + if ((value & 0x8000) != 0) + insn |= 1 << 21; + return insn | (value & 0xfffc); +} + +static long +extract_bdm (insn, invalid) + unsigned long insn; + int *invalid; +{ + if (invalid != (int *) NULL + && ((insn & (1 << 21)) == 0 + || (insn & (1 << 15)) == 0)) + *invalid = 1; + if ((insn & 0x8000) != 0) + return (insn & 0xfffc) - 0x10000; + else + return insn & 0xfffc; +} + +/* The BD field in a B form instruction when the + modifier is used. + This is like BDM, above, except that the branch is expected to be + taken. */ + +/*ARGSUSED*/ +static unsigned long +insert_bdp (insn, value, errmsg) + unsigned long insn; + long value; + const char **errmsg; +{ + if ((value & 0x8000) == 0) + insn |= 1 << 21; + return insn | (value & 0xfffc); +} + +static long +extract_bdp (insn, invalid) + unsigned long insn; + int *invalid; +{ + if (invalid != (int *) NULL + && ((insn & (1 << 21)) == 0 + || (insn & (1 << 15)) != 0)) + *invalid = 1; + if ((insn & 0x8000) != 0) + return (insn & 0xfffc) - 0x10000; + else + return insn & 0xfffc; +} + +/* Check for legal values of a BO field. */ + +static int +valid_bo (value) + long value; +{ + /* Certain encodings have bits that are required to be zero. These + are (z must be zero, y may be anything): + 001zy + 011zy + 1z00y + 1z01y + 1z1zz + */ + switch (value & 0x14) + { + default: + case 0: + return 1; + case 0x4: + return (value & 0x2) == 0; + case 0x10: + return (value & 0x8) == 0; + case 0x14: + return value == 0x14; + } +} + +/* The BO field in a B form instruction. Warn about attempts to set + the field to an illegal value. */ + +static unsigned long +insert_bo (insn, value, errmsg) + unsigned long insn; + long value; + const char **errmsg; +{ + if (errmsg != (const char **) NULL + && ! valid_bo (value)) + *errmsg = "invalid conditional option"; + return insn | ((value & 0x1f) << 21); +} + +static long +extract_bo (insn, invalid) + unsigned long insn; + int *invalid; +{ + long value; + + value = (insn >> 21) & 0x1f; + if (invalid != (int *) NULL + && ! valid_bo (value)) + *invalid = 1; + return value; +} + +/* The BO field in a B form instruction when the + or - modifier is + used. This is like the BO field, but it must be even. When + extracting it, we force it to be even. */ + +static unsigned long +insert_boe (insn, value, errmsg) + unsigned long insn; + long value; + const char **errmsg; +{ + if (errmsg != (const char **) NULL) + { + if (! valid_bo (value)) + *errmsg = "invalid conditional option"; + else if ((value & 1) != 0) + *errmsg = "attempt to set y bit when using + or - modifier"; + } + return insn | ((value & 0x1f) << 21); +} + +static long +extract_boe (insn, invalid) + unsigned long insn; + int *invalid; +{ + long value; + + value = (insn >> 21) & 0x1f; + if (invalid != (int *) NULL + && ! valid_bo (value)) + *invalid = 1; + return value & 0x1e; +} + +/* The DS field in a DS form instruction. This is like D, but the + lower two bits are forced to zero. */ + +/*ARGSUSED*/ +static unsigned long +insert_ds (insn, value, errmsg) + unsigned long insn; + long value; + const char **errmsg; +{ + return insn | (value & 0xfffc); +} + +/*ARGSUSED*/ +static long +extract_ds (insn, invalid) + unsigned long insn; + int *invalid; +{ + if ((insn & 0x8000) != 0) + return (insn & 0xfffc) - 0x10000; + else + return insn & 0xfffc; +} + +/* The LI field in an I form instruction. The lower two bits are + forced to zero. */ + +/*ARGSUSED*/ +static unsigned long +insert_li (insn, value, errmsg) + unsigned long insn; + long value; + const char **errmsg; +{ + return insn | (value & 0x3fffffc); +} + +/*ARGSUSED*/ +static long +extract_li (insn, invalid) + unsigned long insn; + int *invalid; +{ + if ((insn & 0x2000000) != 0) + return (insn & 0x3fffffc) - 0x4000000; + else + return insn & 0x3fffffc; +} + +/* The MB and ME fields in an M form instruction expressed as a single + operand which is itself a bitmask. The extraction function always + marks it as invalid, since we never want to recognize an + instruction which uses a field of this type. */ + +static unsigned long +insert_mbe (insn, value, errmsg) + unsigned long insn; + long value; + const char **errmsg; +{ + unsigned long uval; + int mb, me; + + uval = value; + + if (uval == 0) + { + if (errmsg != (const char **) NULL) + *errmsg = "illegal bitmask"; + return insn; + } + + me = 31; + while ((uval & 1) == 0) + { + uval >>= 1; + --me; + } + + mb = me; + uval >>= 1; + while ((uval & 1) != 0) + { + uval >>= 1; + --mb; + } + + if (uval != 0) + { + if (errmsg != (const char **) NULL) + *errmsg = "illegal bitmask"; + } + + return insn | (mb << 6) | (me << 1); +} + +static long +extract_mbe (insn, invalid) + unsigned long insn; + int *invalid; +{ + long ret; + int mb, me; + int i; + + if (invalid != (int *) NULL) + *invalid = 1; + + ret = 0; + mb = (insn >> 6) & 0x1f; + me = (insn >> 1) & 0x1f; + for (i = mb; i < me; i++) + ret |= 1 << (31 - i); + return ret; +} + +/* The MB or ME field in an MD or MDS form instruction. The high bit + is wrapped to the low end. */ + +/*ARGSUSED*/ +static unsigned long +insert_mb6 (insn, value, errmsg) + unsigned long insn; + long value; + const char **errmsg; +{ + return insn | ((value & 0x1f) << 6) | (value & 0x20); +} + +/*ARGSUSED*/ +static long +extract_mb6 (insn, invalid) + unsigned long insn; + int *invalid; +{ + return ((insn >> 6) & 0x1f) | (insn & 0x20); +} + +/* The NB field in an X form instruction. The value 32 is stored as + 0. */ + +static unsigned long +insert_nb (insn, value, errmsg) + unsigned long insn; + long value; + const char **errmsg; +{ + if (value < 0 || value > 32) + *errmsg = "value out of range"; + if (value == 32) + value = 0; + return insn | ((value & 0x1f) << 11); +} + +/*ARGSUSED*/ +static long +extract_nb (insn, invalid) + unsigned long insn; + int *invalid; +{ + long ret; + + ret = (insn >> 11) & 0x1f; + if (ret == 0) + ret = 32; + return ret; +} + +/* The NSI field in a D form instruction. This is the same as the SI + field, only negated. The extraction function always marks it as + invalid, since we never want to recognize an instruction which uses + a field of this type. */ + +/*ARGSUSED*/ +static unsigned long +insert_nsi (insn, value, errmsg) + unsigned long insn; + long value; + const char **errmsg; +{ + return insn | ((- value) & 0xffff); +} + +static long +extract_nsi (insn, invalid) + unsigned long insn; + int *invalid; +{ + if (invalid != (int *) NULL) + *invalid = 1; + if ((insn & 0x8000) != 0) + return - ((insn & 0xffff) - 0x10000); + else + return - (insn & 0xffff); +} + +/* The RA field in a D or X form instruction which is an updating + load, which means that the RA field may not be zero and may not + equal the RT field. */ + +static unsigned long +insert_ral (insn, value, errmsg) + unsigned long insn; + long value; + const char **errmsg; +{ + if (value == 0 + || value == ((insn >> 21) & 0x1f)) + *errmsg = "invalid register operand when updating"; + return insn | ((value & 0x1f) << 16); +} + +/* The RA field in an lmw instruction, which has special value + restrictions. */ + +static unsigned long +insert_ram (insn, value, errmsg) + unsigned long insn; + long value; + const char **errmsg; +{ + if (value >= ((insn >> 21) & 0x1f)) + *errmsg = "index register in load range"; + return insn | ((value & 0x1f) << 16); +} + +/* The RA field in a D or X form instruction which is an updating + store or an updating floating point load, which means that the RA + field may not be zero. */ + +static unsigned long +insert_ras (insn, value, errmsg) + unsigned long insn; + long value; + const char **errmsg; +{ + if (value == 0) + *errmsg = "invalid register operand when updating"; + return insn | ((value & 0x1f) << 16); +} + +/* The RB field in an X form instruction when it must be the same as + the RS field in the instruction. This is used for extended + mnemonics like mr. This operand is marked FAKE. The insertion + function just copies the BT field into the BA field, and the + extraction function just checks that the fields are the same. */ + +/*ARGSUSED*/ +static unsigned long +insert_rbs (insn, value, errmsg) + unsigned long insn; + long value; + const char **errmsg; +{ + return insn | (((insn >> 21) & 0x1f) << 11); +} + +static long +extract_rbs (insn, invalid) + unsigned long insn; + int *invalid; +{ + if (invalid != (int *) NULL + && ((insn >> 21) & 0x1f) != ((insn >> 11) & 0x1f)) + *invalid = 1; + return 0; +} + +/* The SH field in an MD form instruction. This is split. */ + +/*ARGSUSED*/ +static unsigned long +insert_sh6 (insn, value, errmsg) + unsigned long insn; + long value; + const char **errmsg; +{ + return insn | ((value & 0x1f) << 11) | ((value & 0x20) >> 4); +} + +/*ARGSUSED*/ +static long +extract_sh6 (insn, invalid) + unsigned long insn; + int *invalid; +{ + return ((insn >> 11) & 0x1f) | ((insn << 4) & 0x20); +} + +/* The SPR field in an XFX form instruction. This is flipped--the + lower 5 bits are stored in the upper 5 and vice- versa. */ + +static unsigned long +insert_spr (insn, value, errmsg) + unsigned long insn; + long value; + const char **errmsg; +{ + return insn | ((value & 0x1f) << 16) | ((value & 0x3e0) << 6); +} + +static long +extract_spr (insn, invalid) + unsigned long insn; + int *invalid; +{ + return ((insn >> 16) & 0x1f) | ((insn >> 6) & 0x3e0); +} + +/* The TBR field in an XFX instruction. This is just like SPR, but it + is optional. When TBR is omitted, it must be inserted as 268 (the + magic number of the TB register). These functions treat 0 + (indicating an omitted optional operand) as 268. This means that + ``mftb 4,0'' is not handled correctly. This does not matter very + much, since the architecture manual does not define mftb as + accepting any values other than 268 or 269. */ + +#define TB (268) + +static unsigned long +insert_tbr (insn, value, errmsg) + unsigned long insn; + long value; + const char **errmsg; +{ + if (value == 0) + value = TB; + return insn | ((value & 0x1f) << 16) | ((value & 0x3e0) << 6); +} + +static long +extract_tbr (insn, invalid) + unsigned long insn; + int *invalid; +{ + long ret; + + ret = ((insn >> 16) & 0x1f) | ((insn >> 6) & 0x3e0); + if (ret == TB) + ret = 0; + return ret; +} + +/* Macros used to form opcodes. */ + +/* The main opcode. */ +#define OP(x) (((x) & 0x3f) << 26) +#define OP_MASK OP (0x3f) + +/* The main opcode combined with a trap code in the TO field of a D + form instruction. Used for extended mnemonics for the trap + instructions. */ +#define OPTO(x,to) (OP (x) | (((to) & 0x1f) << 21)) +#define OPTO_MASK (OP_MASK | TO_MASK) + +/* The main opcode combined with a comparison size bit in the L field + of a D form or X form instruction. Used for extended mnemonics for + the comparison instructions. */ +#define OPL(x,l) (OP (x) | (((l) & 1) << 21)) +#define OPL_MASK OPL (0x3f,1) + +/* An A form instruction. */ +#define A(op, xop, rc) (OP (op) | (((xop) & 0x1f) << 1) | ((rc) & 1)) +#define A_MASK A (0x3f, 0x1f, 1) + +/* An A_MASK with the FRB field fixed. */ +#define AFRB_MASK (A_MASK | FRB_MASK) + +/* An A_MASK with the FRC field fixed. */ +#define AFRC_MASK (A_MASK | FRC_MASK) + +/* An A_MASK with the FRA and FRC fields fixed. */ +#define AFRAFRC_MASK (A_MASK | FRA_MASK | FRC_MASK) + +/* A B form instruction. */ +#define B(op, aa, lk) (OP (op) | (((aa) & 1) << 1) | ((lk) & 1)) +#define B_MASK B (0x3f, 1, 1) + +/* A B form instruction setting the BO field. */ +#define BBO(op, bo, aa, lk) (B ((op), (aa), (lk)) | (((bo) & 0x1f) << 21)) +#define BBO_MASK BBO (0x3f, 0x1f, 1, 1) + +/* A BBO_MASK with the y bit of the BO field removed. This permits + matching a conditional branch regardless of the setting of the y + bit. */ +#define Y_MASK (1 << 21) +#define BBOY_MASK (BBO_MASK &~ Y_MASK) + +/* A B form instruction setting the BO field and the condition bits of + the BI field. */ +#define BBOCB(op, bo, cb, aa, lk) \ + (BBO ((op), (bo), (aa), (lk)) | (((cb) & 0x3) << 16)) +#define BBOCB_MASK BBOCB (0x3f, 0x1f, 0x3, 1, 1) + +/* A BBOCB_MASK with the y bit of the BO field removed. */ +#define BBOYCB_MASK (BBOCB_MASK &~ Y_MASK) + +/* A BBOYCB_MASK in which the BI field is fixed. */ +#define BBOYBI_MASK (BBOYCB_MASK | BI_MASK) + +/* The main opcode mask with the RA field clear. */ +#define DRA_MASK (OP_MASK | RA_MASK) + +/* A DS form instruction. */ +#define DSO(op, xop) (OP (op) | ((xop) & 0x3)) +#define DS_MASK DSO (0x3f, 3) + +/* An M form instruction. */ +#define M(op, rc) (OP (op) | ((rc) & 1)) +#define M_MASK M (0x3f, 1) + +/* An M form instruction with the ME field specified. */ +#define MME(op, me, rc) (M ((op), (rc)) | (((me) & 0x1f) << 1)) + +/* An M_MASK with the MB and ME fields fixed. */ +#define MMBME_MASK (M_MASK | MB_MASK | ME_MASK) + +/* An M_MASK with the SH and ME fields fixed. */ +#define MSHME_MASK (M_MASK | SH_MASK | ME_MASK) + +/* An MD form instruction. */ +#define MD(op, xop, rc) (OP (op) | (((xop) & 0x7) << 2) | ((rc) & 1)) +#define MD_MASK MD (0x3f, 0x7, 1) + +/* An MD_MASK with the MB field fixed. */ +#define MDMB_MASK (MD_MASK | MB6_MASK) + +/* An MD_MASK with the SH field fixed. */ +#define MDSH_MASK (MD_MASK | SH6_MASK) + +/* An MDS form instruction. */ +#define MDS(op, xop, rc) (OP (op) | (((xop) & 0xf) << 1) | ((rc) & 1)) +#define MDS_MASK MDS (0x3f, 0xf, 1) + +/* An MDS_MASK with the MB field fixed. */ +#define MDSMB_MASK (MDS_MASK | MB6_MASK) + +/* An SC form instruction. */ +#define SC(op, sa, lk) (OP (op) | (((sa) & 1) << 1) | ((lk) & 1)) +#define SC_MASK (OP_MASK | (0x3ff << 16) | (1 << 1) | 1) + +/* An X form instruction. */ +#define X(op, xop) (OP (op) | (((xop) & 0x3ff) << 1)) + +/* An X form instruction with the RC bit specified. */ +#define XRC(op, xop, rc) (X ((op), (xop)) | ((rc) & 1)) + +/* The mask for an X form instruction. */ +#define X_MASK XRC (0x3f, 0x3ff, 1) + +/* An X_MASK with the RA field fixed. */ +#define XRA_MASK (X_MASK | RA_MASK) + +/* An X_MASK with the RB field fixed. */ +#define XRB_MASK (X_MASK | RB_MASK) + +/* An X_MASK with the RT field fixed. */ +#define XRT_MASK (X_MASK | RT_MASK) + +/* An X_MASK with the RA and RB fields fixed. */ +#define XRARB_MASK (X_MASK | RA_MASK | RB_MASK) + +/* An X_MASK with the RT and RA fields fixed. */ +#define XRTRA_MASK (X_MASK | RT_MASK | RA_MASK) + +/* An X form comparison instruction. */ +#define XCMPL(op, xop, l) (X ((op), (xop)) | (((l) & 1) << 21)) + +/* The mask for an X form comparison instruction. */ +#define XCMP_MASK (X_MASK | (1 << 22)) + +/* The mask for an X form comparison instruction with the L field + fixed. */ +#define XCMPL_MASK (XCMP_MASK | (1 << 21)) + +/* An X form trap instruction with the TO field specified. */ +#define XTO(op, xop, to) (X ((op), (xop)) | (((to) & 0x1f) << 21)) +#define XTO_MASK (X_MASK | TO_MASK) + +/* An XFL form instruction. */ +#define XFL(op, xop, rc) (OP (op) | (((xop) & 0x3ff) << 1) | ((rc) & 1)) +#define XFL_MASK (XFL (0x3f, 0x3ff, 1) | (1 << 25) | (1 << 16)) + +/* An XL form instruction with the LK field set to 0. */ +#define XL(op, xop) (OP (op) | (((xop) & 0x3ff) << 1)) + +/* An XL form instruction which uses the LK field. */ +#define XLLK(op, xop, lk) (XL ((op), (xop)) | ((lk) & 1)) + +/* The mask for an XL form instruction. */ +#define XL_MASK XLLK (0x3f, 0x3ff, 1) + +/* An XL form instruction which explicitly sets the BO field. */ +#define XLO(op, bo, xop, lk) \ + (XLLK ((op), (xop), (lk)) | (((bo) & 0x1f) << 21)) +#define XLO_MASK (XL_MASK | BO_MASK) + +/* An XL form instruction which explicitly sets the y bit of the BO + field. */ +#define XLYLK(op, xop, y, lk) (XLLK ((op), (xop), (lk)) | (((y) & 1) << 21)) +#define XLYLK_MASK (XL_MASK | Y_MASK) + +/* An XL form instruction which sets the BO field and the condition + bits of the BI field. */ +#define XLOCB(op, bo, cb, xop, lk) \ + (XLO ((op), (bo), (xop), (lk)) | (((cb) & 3) << 16)) +#define XLOCB_MASK XLOCB (0x3f, 0x1f, 0x3, 0x3ff, 1) + +/* An XL_MASK or XLYLK_MASK or XLOCB_MASK with the BB field fixed. */ +#define XLBB_MASK (XL_MASK | BB_MASK) +#define XLYBB_MASK (XLYLK_MASK | BB_MASK) +#define XLBOCBBB_MASK (XLOCB_MASK | BB_MASK) + +/* An XL_MASK with the BO and BB fields fixed. */ +#define XLBOBB_MASK (XL_MASK | BO_MASK | BB_MASK) + +/* An XL_MASK with the BO, BI and BB fields fixed. */ +#define XLBOBIBB_MASK (XL_MASK | BO_MASK | BI_MASK | BB_MASK) + +/* An XO form instruction. */ +#define XO(op, xop, oe, rc) \ + (OP (op) | (((xop) & 0x1ff) << 1) | (((oe) & 1) << 10) | ((rc) & 1)) +#define XO_MASK XO (0x3f, 0x1ff, 1, 1) + +/* An XO_MASK with the RB field fixed. */ +#define XORB_MASK (XO_MASK | RB_MASK) + +/* An XS form instruction. */ +#define XS(op, xop, rc) (OP (op) | (((xop) & 0x1ff) << 2) | ((rc) & 1)) +#define XS_MASK XS (0x3f, 0x1ff, 1) + +/* A mask for the FXM version of an XFX form instruction. */ +#define XFXFXM_MASK (X_MASK | (1 << 20) | (1 << 11)) + +/* An XFX form instruction with the FXM field filled in. */ +#define XFXM(op, xop, fxm) \ + (X ((op), (xop)) | (((fxm) & 0xff) << 12)) + +/* An XFX form instruction with the SPR field filled in. */ +#define XSPR(op, xop, spr) \ + (X ((op), (xop)) | (((spr) & 0x1f) << 16) | (((spr) & 0x3e0) << 6)) +#define XSPR_MASK (X_MASK | SPR_MASK) + +/* An XFX form instruction with the SPR field filled in except for the + SPRBAT field. */ +#define XSPRBAT_MASK (XSPR_MASK &~ SPRBAT_MASK) + +/* An XFX form instruction with the SPR field filled in except for the + SPRG field. */ +#define XSPRG_MASK (XSPR_MASK &~ SPRG_MASK) + +/* The BO encodings used in extended conditional branch mnemonics. */ +#define BODNZF (0x0) +#define BODNZFP (0x1) +#define BODZF (0x2) +#define BODZFP (0x3) +#define BOF (0x4) +#define BOFP (0x5) +#define BODNZT (0x8) +#define BODNZTP (0x9) +#define BODZT (0xa) +#define BODZTP (0xb) +#define BOT (0xc) +#define BOTP (0xd) +#define BODNZ (0x10) +#define BODNZP (0x11) +#define BODZ (0x12) +#define BODZP (0x13) +#define BOU (0x14) + +/* The BI condition bit encodings used in extended conditional branch + mnemonics. */ +#define CBLT (0) +#define CBGT (1) +#define CBEQ (2) +#define CBSO (3) + +/* The TO encodings used in extended trap mnemonics. */ +#define TOLGT (0x1) +#define TOLLT (0x2) +#define TOEQ (0x4) +#define TOLGE (0x5) +#define TOLNL (0x5) +#define TOLLE (0x6) +#define TOLNG (0x6) +#define TOGT (0x8) +#define TOGE (0xc) +#define TONL (0xc) +#define TOLT (0x10) +#define TOLE (0x14) +#define TONG (0x14) +#define TONE (0x18) +#define TOU (0x1f) + +/* Smaller names for the flags so each entry in the opcodes table will + fit on a single line. */ +#undef PPC +#define PPC PPC_OPCODE_PPC | PPC_OPCODE_ANY +#define PPCCOM PPC_OPCODE_PPC | PPC_OPCODE_COMMON | PPC_OPCODE_ANY +#define PPC32 PPC_OPCODE_PPC | PPC_OPCODE_32 | PPC_OPCODE_ANY +#define PPC64 PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_ANY +#define PPCONLY PPC_OPCODE_PPC +#define POWER PPC_OPCODE_POWER | PPC_OPCODE_ANY +#define POWER2 PPC_OPCODE_POWER | PPC_OPCODE_POWER2 | PPC_OPCODE_ANY +#define POWER32 PPC_OPCODE_POWER | PPC_OPCODE_ANY | PPC_OPCODE_32 +#define COM PPC_OPCODE_POWER | PPC_OPCODE_PPC | PPC_OPCODE_COMMON | PPC_OPCODE_ANY +#define COM32 PPC_OPCODE_POWER | PPC_OPCODE_PPC | PPC_OPCODE_COMMON | PPC_OPCODE_ANY | PPC_OPCODE_32 +#define M601 PPC_OPCODE_POWER | PPC_OPCODE_601 | PPC_OPCODE_ANY +#define PWRCOM PPC_OPCODE_POWER | PPC_OPCODE_601 | PPC_OPCODE_COMMON | PPC_OPCODE_ANY +#define MFDEC1 PPC_OPCODE_POWER +#define MFDEC2 PPC_OPCODE_PPC | PPC_OPCODE_601 + +/* The opcode table. + + The format of the opcode table is: + + NAME OPCODE MASK FLAGS { OPERANDS } + + NAME is the name of the instruction. + OPCODE is the instruction opcode. + MASK is the opcode mask; this is used to tell the disassembler + which bits in the actual opcode must match OPCODE. + FLAGS are flags indicated what processors support the instruction. + OPERANDS is the list of operands. + + The disassembler reads the table in order and prints the first + instruction which matches, so this table is sorted to put more + specific instructions before more general instructions. It is also + sorted by major opcode. */ + +const struct powerpc_opcode powerpc_opcodes[] = { +{ "tdlgti", OPTO(2,TOLGT), OPTO_MASK, PPC64, { RA, SI } }, +{ "tdllti", OPTO(2,TOLLT), OPTO_MASK, PPC64, { RA, SI } }, +{ "tdeqi", OPTO(2,TOEQ), OPTO_MASK, PPC64, { RA, SI } }, +{ "tdlgei", OPTO(2,TOLGE), OPTO_MASK, PPC64, { RA, SI } }, +{ "tdlnli", OPTO(2,TOLNL), OPTO_MASK, PPC64, { RA, SI } }, +{ "tdllei", OPTO(2,TOLLE), OPTO_MASK, PPC64, { RA, SI } }, +{ "tdlngi", OPTO(2,TOLNG), OPTO_MASK, PPC64, { RA, SI } }, +{ "tdgti", OPTO(2,TOGT), OPTO_MASK, PPC64, { RA, SI } }, +{ "tdgei", OPTO(2,TOGE), OPTO_MASK, PPC64, { RA, SI } }, +{ "tdnli", OPTO(2,TONL), OPTO_MASK, PPC64, { RA, SI } }, +{ "tdlti", OPTO(2,TOLT), OPTO_MASK, PPC64, { RA, SI } }, +{ "tdlei", OPTO(2,TOLE), OPTO_MASK, PPC64, { RA, SI } }, +{ "tdngi", OPTO(2,TONG), OPTO_MASK, PPC64, { RA, SI } }, +{ "tdnei", OPTO(2,TONE), OPTO_MASK, PPC64, { RA, SI } }, +{ "tdi", OP(2), OP_MASK, PPC64, { TO, RA, SI } }, + +{ "twlgti", OPTO(3,TOLGT), OPTO_MASK, PPCCOM, { RA, SI } }, +{ "tlgti", OPTO(3,TOLGT), OPTO_MASK, PWRCOM, { RA, SI } }, +{ "twllti", OPTO(3,TOLLT), OPTO_MASK, PPCCOM, { RA, SI } }, +{ "tllti", OPTO(3,TOLLT), OPTO_MASK, PWRCOM, { RA, SI } }, +{ "tweqi", OPTO(3,TOEQ), OPTO_MASK, PPCCOM, { RA, SI } }, +{ "teqi", OPTO(3,TOEQ), OPTO_MASK, PWRCOM, { RA, SI } }, +{ "twlgei", OPTO(3,TOLGE), OPTO_MASK, PPCCOM, { RA, SI } }, +{ "tlgei", OPTO(3,TOLGE), OPTO_MASK, PWRCOM, { RA, SI } }, +{ "twlnli", OPTO(3,TOLNL), OPTO_MASK, PPCCOM, { RA, SI } }, +{ "tlnli", OPTO(3,TOLNL), OPTO_MASK, PWRCOM, { RA, SI } }, +{ "twllei", OPTO(3,TOLLE), OPTO_MASK, PPCCOM, { RA, SI } }, +{ "tllei", OPTO(3,TOLLE), OPTO_MASK, PWRCOM, { RA, SI } }, +{ "twlngi", OPTO(3,TOLNG), OPTO_MASK, PPCCOM, { RA, SI } }, +{ "tlngi", OPTO(3,TOLNG), OPTO_MASK, PWRCOM, { RA, SI } }, +{ "twgti", OPTO(3,TOGT), OPTO_MASK, PPCCOM, { RA, SI } }, +{ "tgti", OPTO(3,TOGT), OPTO_MASK, PWRCOM, { RA, SI } }, +{ "twgei", OPTO(3,TOGE), OPTO_MASK, PPCCOM, { RA, SI } }, +{ "tgei", OPTO(3,TOGE), OPTO_MASK, PWRCOM, { RA, SI } }, +{ "twnli", OPTO(3,TONL), OPTO_MASK, PPCCOM, { RA, SI } }, +{ "tnli", OPTO(3,TONL), OPTO_MASK, PWRCOM, { RA, SI } }, +{ "twlti", OPTO(3,TOLT), OPTO_MASK, PPCCOM, { RA, SI } }, +{ "tlti", OPTO(3,TOLT), OPTO_MASK, PWRCOM, { RA, SI } }, +{ "twlei", OPTO(3,TOLE), OPTO_MASK, PPCCOM, { RA, SI } }, +{ "tlei", OPTO(3,TOLE), OPTO_MASK, PWRCOM, { RA, SI } }, +{ "twngi", OPTO(3,TONG), OPTO_MASK, PPCCOM, { RA, SI } }, +{ "tngi", OPTO(3,TONG), OPTO_MASK, PWRCOM, { RA, SI } }, +{ "twnei", OPTO(3,TONE), OPTO_MASK, PPCCOM, { RA, SI } }, +{ "tnei", OPTO(3,TONE), OPTO_MASK, PWRCOM, { RA, SI } }, +{ "twi", OP(3), OP_MASK, PPCCOM, { TO, RA, SI } }, +{ "ti", OP(3), OP_MASK, PWRCOM, { TO, RA, SI } }, + +{ "mulli", OP(7), OP_MASK, PPCCOM, { RT, RA, SI } }, +{ "muli", OP(7), OP_MASK, PWRCOM, { RT, RA, SI } }, + +{ "subfic", OP(8), OP_MASK, PPCCOM, { RT, RA, SI } }, +{ "sfi", OP(8), OP_MASK, PWRCOM, { RT, RA, SI } }, + +{ "dozi", OP(9), OP_MASK, M601, { RT, RA, SI } }, + +{ "cmplwi", OPL(10,0), OPL_MASK, PPCCOM, { OBF, RA, UI } }, +{ "cmpldi", OPL(10,1), OPL_MASK, PPC64, { OBF, RA, UI } }, +{ "cmpli", OP(10), OP_MASK, PPCONLY, { BF, L, RA, UI } }, +{ "cmpli", OP(10), OP_MASK, PWRCOM, { BF, RA, UI } }, + +{ "cmpwi", OPL(11,0), OPL_MASK, PPCCOM, { OBF, RA, SI } }, +{ "cmpdi", OPL(11,1), OPL_MASK, PPC64, { OBF, RA, SI } }, +{ "cmpi", OP(11), OP_MASK, PPCONLY, { BF, L, RA, SI } }, +{ "cmpi", OP(11), OP_MASK, PWRCOM, { BF, RA, SI } }, + +{ "addic", OP(12), OP_MASK, PPCCOM, { RT, RA, SI } }, +{ "ai", OP(12), OP_MASK, PWRCOM, { RT, RA, SI } }, +{ "subic", OP(12), OP_MASK, PPCCOM, { RT, RA, NSI } }, + +{ "addic.", OP(13), OP_MASK, PPCCOM, { RT, RA, SI } }, +{ "ai.", OP(13), OP_MASK, PWRCOM, { RT, RA, SI } }, +{ "subic.", OP(13), OP_MASK, PPCCOM, { RT, RA, NSI } }, + +{ "li", OP(14), DRA_MASK, PPCCOM, { RT, SI } }, +{ "lil", OP(14), DRA_MASK, PWRCOM, { RT, SI } }, +{ "addi", OP(14), OP_MASK, PPCCOM, { RT, RA, SI } }, +{ "cal", OP(14), OP_MASK, PWRCOM, { RT, D, RA } }, +{ "subi", OP(14), OP_MASK, PPCCOM, { RT, RA, NSI } }, +{ "la", OP(14), OP_MASK, PPCCOM, { RT, D, RA } }, + +{ "lis", OP(15), DRA_MASK, PPCCOM, { RT, SISIGNOPT } }, +{ "liu", OP(15), DRA_MASK, PWRCOM, { RT, SISIGNOPT } }, +{ "addis", OP(15), OP_MASK, PPCCOM, { RT,RA,SISIGNOPT } }, +{ "cau", OP(15), OP_MASK, PWRCOM, { RT,RA,SISIGNOPT } }, +{ "subis", OP(15), OP_MASK, PPCCOM, { RT, RA, NSI } }, + +{ "bdnz-", BBO(16,BODNZ,0,0), BBOYBI_MASK, PPC, { BDM } }, +{ "bdnz+", BBO(16,BODNZ,0,0), BBOYBI_MASK, PPC, { BDP } }, +{ "bdnz", BBO(16,BODNZ,0,0), BBOYBI_MASK, PPCCOM, { BD } }, +{ "bdn", BBO(16,BODNZ,0,0), BBOYBI_MASK, PWRCOM, { BD } }, +{ "bdnzl-", BBO(16,BODNZ,0,1), BBOYBI_MASK, PPC, { BDM } }, +{ "bdnzl+", BBO(16,BODNZ,0,1), BBOYBI_MASK, PPC, { BDP } }, +{ "bdnzl", BBO(16,BODNZ,0,1), BBOYBI_MASK, PPCCOM, { BD } }, +{ "bdnl", BBO(16,BODNZ,0,1), BBOYBI_MASK, PWRCOM, { BD } }, +{ "bdnza-", BBO(16,BODNZ,1,0), BBOYBI_MASK, PPC, { BDMA } }, +{ "bdnza+", BBO(16,BODNZ,1,0), BBOYBI_MASK, PPC, { BDPA } }, +{ "bdnza", BBO(16,BODNZ,1,0), BBOYBI_MASK, PPCCOM, { BDA } }, +{ "bdna", BBO(16,BODNZ,1,0), BBOYBI_MASK, PWRCOM, { BDA } }, +{ "bdnzla-", BBO(16,BODNZ,1,1), BBOYBI_MASK, PPC, { BDMA } }, +{ "bdnzla+", BBO(16,BODNZ,1,1), BBOYBI_MASK, PPC, { BDPA } }, +{ "bdnzla", BBO(16,BODNZ,1,1), BBOYBI_MASK, PPCCOM, { BDA } }, +{ "bdnla", BBO(16,BODNZ,1,1), BBOYBI_MASK, PWRCOM, { BDA } }, +{ "bdz-", BBO(16,BODZ,0,0), BBOYBI_MASK, PPC, { BDM } }, +{ "bdz+", BBO(16,BODZ,0,0), BBOYBI_MASK, PPC, { BDP } }, +{ "bdz", BBO(16,BODZ,0,0), BBOYBI_MASK, COM, { BD } }, +{ "bdzl-", BBO(16,BODZ,0,1), BBOYBI_MASK, PPC, { BDM } }, +{ "bdzl+", BBO(16,BODZ,0,1), BBOYBI_MASK, PPC, { BDP } }, +{ "bdzl", BBO(16,BODZ,0,1), BBOYBI_MASK, COM, { BD } }, +{ "bdza-", BBO(16,BODZ,1,0), BBOYBI_MASK, PPC, { BDMA } }, +{ "bdza+", BBO(16,BODZ,1,0), BBOYBI_MASK, PPC, { BDPA } }, +{ "bdza", BBO(16,BODZ,1,0), BBOYBI_MASK, COM, { BDA } }, +{ "bdzla-", BBO(16,BODZ,1,1), BBOYBI_MASK, PPC, { BDMA } }, +{ "bdzla+", BBO(16,BODZ,1,1), BBOYBI_MASK, PPC, { BDPA } }, +{ "bdzla", BBO(16,BODZ,1,1), BBOYBI_MASK, COM, { BDA } }, +{ "blt-", BBOCB(16,BOT,CBLT,0,0), BBOYCB_MASK, PPC, { CR, BDM } }, +{ "blt+", BBOCB(16,BOT,CBLT,0,0), BBOYCB_MASK, PPC, { CR, BDP } }, +{ "blt", BBOCB(16,BOT,CBLT,0,0), BBOYCB_MASK, COM, { CR, BD } }, +{ "bltl-", BBOCB(16,BOT,CBLT,0,1), BBOYCB_MASK, PPC, { CR, BDM } }, +{ "bltl+", BBOCB(16,BOT,CBLT,0,1), BBOYCB_MASK, PPC, { CR, BDP } }, +{ "bltl", BBOCB(16,BOT,CBLT,0,1), BBOYCB_MASK, COM, { CR, BD } }, +{ "blta-", BBOCB(16,BOT,CBLT,1,0), BBOYCB_MASK, PPC, { CR, BDMA } }, +{ "blta+", BBOCB(16,BOT,CBLT,1,0), BBOYCB_MASK, PPC, { CR, BDPA } }, +{ "blta", BBOCB(16,BOT,CBLT,1,0), BBOYCB_MASK, COM, { CR, BDA } }, +{ "bltla-", BBOCB(16,BOT,CBLT,1,1), BBOYCB_MASK, PPC, { CR, BDMA } }, +{ "bltla+", BBOCB(16,BOT,CBLT,1,1), BBOYCB_MASK, PPC, { CR, BDPA } }, +{ "bltla", BBOCB(16,BOT,CBLT,1,1), BBOYCB_MASK, COM, { CR, BDA } }, +{ "bgt-", BBOCB(16,BOT,CBGT,0,0), BBOYCB_MASK, PPC, { CR, BDM } }, +{ "bgt+", BBOCB(16,BOT,CBGT,0,0), BBOYCB_MASK, PPC, { CR, BDP } }, +{ "bgt", BBOCB(16,BOT,CBGT,0,0), BBOYCB_MASK, COM, { CR, BD } }, +{ "bgtl-", BBOCB(16,BOT,CBGT,0,1), BBOYCB_MASK, PPC, { CR, BDM } }, +{ "bgtl+", BBOCB(16,BOT,CBGT,0,1), BBOYCB_MASK, PPC, { CR, BDP } }, +{ "bgtl", BBOCB(16,BOT,CBGT,0,1), BBOYCB_MASK, COM, { CR, BD } }, +{ "bgta-", BBOCB(16,BOT,CBGT,1,0), BBOYCB_MASK, PPC, { CR, BDMA } }, +{ "bgta+", BBOCB(16,BOT,CBGT,1,0), BBOYCB_MASK, PPC, { CR, BDPA } }, +{ "bgta", BBOCB(16,BOT,CBGT,1,0), BBOYCB_MASK, COM, { CR, BDA } }, +{ "bgtla-", BBOCB(16,BOT,CBGT,1,1), BBOYCB_MASK, PPC, { CR, BDMA } }, +{ "bgtla+", BBOCB(16,BOT,CBGT,1,1), BBOYCB_MASK, PPC, { CR, BDPA } }, +{ "bgtla", BBOCB(16,BOT,CBGT,1,1), BBOYCB_MASK, COM, { CR, BDA } }, +{ "beq-", BBOCB(16,BOT,CBEQ,0,0), BBOYCB_MASK, PPC, { CR, BDM } }, +{ "beq+", BBOCB(16,BOT,CBEQ,0,0), BBOYCB_MASK, PPC, { CR, BDP } }, +{ "beq", BBOCB(16,BOT,CBEQ,0,0), BBOYCB_MASK, COM, { CR, BD } }, +{ "beql-", BBOCB(16,BOT,CBEQ,0,1), BBOYCB_MASK, PPC, { CR, BDM } }, +{ "beql+", BBOCB(16,BOT,CBEQ,0,1), BBOYCB_MASK, PPC, { CR, BDP } }, +{ "beql", BBOCB(16,BOT,CBEQ,0,1), BBOYCB_MASK, COM, { CR, BD } }, +{ "beqa-", BBOCB(16,BOT,CBEQ,1,0), BBOYCB_MASK, PPC, { CR, BDMA } }, +{ "beqa+", BBOCB(16,BOT,CBEQ,1,0), BBOYCB_MASK, PPC, { CR, BDPA } }, +{ "beqa", BBOCB(16,BOT,CBEQ,1,0), BBOYCB_MASK, COM, { CR, BDA } }, +{ "beqla-", BBOCB(16,BOT,CBEQ,1,1), BBOYCB_MASK, PPC, { CR, BDMA } }, +{ "beqla+", BBOCB(16,BOT,CBEQ,1,1), BBOYCB_MASK, PPC, { CR, BDPA } }, +{ "beqla", BBOCB(16,BOT,CBEQ,1,1), BBOYCB_MASK, COM, { CR, BDA } }, +{ "bso-", BBOCB(16,BOT,CBSO,0,0), BBOYCB_MASK, PPC, { CR, BDM } }, +{ "bso+", BBOCB(16,BOT,CBSO,0,0), BBOYCB_MASK, PPC, { CR, BDP } }, +{ "bso", BBOCB(16,BOT,CBSO,0,0), BBOYCB_MASK, COM, { CR, BD } }, +{ "bsol-", BBOCB(16,BOT,CBSO,0,1), BBOYCB_MASK, PPC, { CR, BDM } }, +{ "bsol+", BBOCB(16,BOT,CBSO,0,1), BBOYCB_MASK, PPC, { CR, BDP } }, +{ "bsol", BBOCB(16,BOT,CBSO,0,1), BBOYCB_MASK, COM, { CR, BD } }, +{ "bsoa-", BBOCB(16,BOT,CBSO,1,0), BBOYCB_MASK, PPC, { CR, BDMA } }, +{ "bsoa+", BBOCB(16,BOT,CBSO,1,0), BBOYCB_MASK, PPC, { CR, BDPA } }, +{ "bsoa", BBOCB(16,BOT,CBSO,1,0), BBOYCB_MASK, COM, { CR, BDA } }, +{ "bsola-", BBOCB(16,BOT,CBSO,1,1), BBOYCB_MASK, PPC, { CR, BDMA } }, +{ "bsola+", BBOCB(16,BOT,CBSO,1,1), BBOYCB_MASK, PPC, { CR, BDPA } }, +{ "bsola", BBOCB(16,BOT,CBSO,1,1), BBOYCB_MASK, COM, { CR, BDA } }, +{ "bun-", BBOCB(16,BOT,CBSO,0,0), BBOYCB_MASK, PPC, { CR, BDM } }, +{ "bun+", BBOCB(16,BOT,CBSO,0,0), BBOYCB_MASK, PPC, { CR, BDP } }, +{ "bun", BBOCB(16,BOT,CBSO,0,0), BBOYCB_MASK, PPCCOM, { CR, BD } }, +{ "bunl-", BBOCB(16,BOT,CBSO,0,1), BBOYCB_MASK, PPC, { CR, BDM } }, +{ "bunl+", BBOCB(16,BOT,CBSO,0,1), BBOYCB_MASK, PPC, { CR, BDP } }, +{ "bunl", BBOCB(16,BOT,CBSO,0,1), BBOYCB_MASK, PPCCOM, { CR, BD } }, +{ "buna-", BBOCB(16,BOT,CBSO,1,0), BBOYCB_MASK, PPC, { CR, BDMA } }, +{ "buna+", BBOCB(16,BOT,CBSO,1,0), BBOYCB_MASK, PPC, { CR, BDPA } }, +{ "buna", BBOCB(16,BOT,CBSO,1,0), BBOYCB_MASK, PPCCOM, { CR, BDA } }, +{ "bunla-", BBOCB(16,BOT,CBSO,1,1), BBOYCB_MASK, PPC, { CR, BDMA } }, +{ "bunla+", BBOCB(16,BOT,CBSO,1,1), BBOYCB_MASK, PPC, { CR, BDPA } }, +{ "bunla", BBOCB(16,BOT,CBSO,1,1), BBOYCB_MASK, PPCCOM, { CR, BDA } }, +{ "bge-", BBOCB(16,BOF,CBLT,0,0), BBOYCB_MASK, PPC, { CR, BDM } }, +{ "bge+", BBOCB(16,BOF,CBLT,0,0), BBOYCB_MASK, PPC, { CR, BDP } }, +{ "bge", BBOCB(16,BOF,CBLT,0,0), BBOYCB_MASK, COM, { CR, BD } }, +{ "bgel-", BBOCB(16,BOF,CBLT,0,1), BBOYCB_MASK, PPC, { CR, BDM } }, +{ "bgel+", BBOCB(16,BOF,CBLT,0,1), BBOYCB_MASK, PPC, { CR, BDP } }, +{ "bgel", BBOCB(16,BOF,CBLT,0,1), BBOYCB_MASK, COM, { CR, BD } }, +{ "bgea-", BBOCB(16,BOF,CBLT,1,0), BBOYCB_MASK, PPC, { CR, BDMA } }, +{ "bgea+", BBOCB(16,BOF,CBLT,1,0), BBOYCB_MASK, PPC, { CR, BDPA } }, +{ "bgea", BBOCB(16,BOF,CBLT,1,0), BBOYCB_MASK, COM, { CR, BDA } }, +{ "bgela-", BBOCB(16,BOF,CBLT,1,1), BBOYCB_MASK, PPC, { CR, BDMA } }, +{ "bgela+", BBOCB(16,BOF,CBLT,1,1), BBOYCB_MASK, PPC, { CR, BDPA } }, +{ "bgela", BBOCB(16,BOF,CBLT,1,1), BBOYCB_MASK, COM, { CR, BDA } }, +{ "bnl-", BBOCB(16,BOF,CBLT,0,0), BBOYCB_MASK, PPC, { CR, BDM } }, +{ "bnl+", BBOCB(16,BOF,CBLT,0,0), BBOYCB_MASK, PPC, { CR, BDP } }, +{ "bnl", BBOCB(16,BOF,CBLT,0,0), BBOYCB_MASK, COM, { CR, BD } }, +{ "bnll-", BBOCB(16,BOF,CBLT,0,1), BBOYCB_MASK, PPC, { CR, BDM } }, +{ "bnll+", BBOCB(16,BOF,CBLT,0,1), BBOYCB_MASK, PPC, { CR, BDP } }, +{ "bnll", BBOCB(16,BOF,CBLT,0,1), BBOYCB_MASK, COM, { CR, BD } }, +{ "bnla-", BBOCB(16,BOF,CBLT,1,0), BBOYCB_MASK, PPC, { CR, BDMA } }, +{ "bnla+", BBOCB(16,BOF,CBLT,1,0), BBOYCB_MASK, PPC, { CR, BDPA } }, +{ "bnla", BBOCB(16,BOF,CBLT,1,0), BBOYCB_MASK, COM, { CR, BDA } }, +{ "bnlla-", BBOCB(16,BOF,CBLT,1,1), BBOYCB_MASK, PPC, { CR, BDMA } }, +{ "bnlla+", BBOCB(16,BOF,CBLT,1,1), BBOYCB_MASK, PPC, { CR, BDPA } }, +{ "bnlla", BBOCB(16,BOF,CBLT,1,1), BBOYCB_MASK, COM, { CR, BDA } }, +{ "ble-", BBOCB(16,BOF,CBGT,0,0), BBOYCB_MASK, PPC, { CR, BDM } }, +{ "ble+", BBOCB(16,BOF,CBGT,0,0), BBOYCB_MASK, PPC, { CR, BDP } }, +{ "ble", BBOCB(16,BOF,CBGT,0,0), BBOYCB_MASK, COM, { CR, BD } }, +{ "blel-", BBOCB(16,BOF,CBGT,0,1), BBOYCB_MASK, PPC, { CR, BDM } }, +{ "blel+", BBOCB(16,BOF,CBGT,0,1), BBOYCB_MASK, PPC, { CR, BDP } }, +{ "blel", BBOCB(16,BOF,CBGT,0,1), BBOYCB_MASK, COM, { CR, BD } }, +{ "blea-", BBOCB(16,BOF,CBGT,1,0), BBOYCB_MASK, PPC, { CR, BDMA } }, +{ "blea+", BBOCB(16,BOF,CBGT,1,0), BBOYCB_MASK, PPC, { CR, BDPA } }, +{ "blea", BBOCB(16,BOF,CBGT,1,0), BBOYCB_MASK, COM, { CR, BDA } }, +{ "blela-", BBOCB(16,BOF,CBGT,1,1), BBOYCB_MASK, PPC, { CR, BDMA } }, +{ "blela+", BBOCB(16,BOF,CBGT,1,1), BBOYCB_MASK, PPC, { CR, BDPA } }, +{ "blela", BBOCB(16,BOF,CBGT,1,1), BBOYCB_MASK, COM, { CR, BDA } }, +{ "bng-", BBOCB(16,BOF,CBGT,0,0), BBOYCB_MASK, PPC, { CR, BDM } }, +{ "bng+", BBOCB(16,BOF,CBGT,0,0), BBOYCB_MASK, PPC, { CR, BDP } }, +{ "bng", BBOCB(16,BOF,CBGT,0,0), BBOYCB_MASK, COM, { CR, BD } }, +{ "bngl-", BBOCB(16,BOF,CBGT,0,1), BBOYCB_MASK, PPC, { CR, BDM } }, +{ "bngl+", BBOCB(16,BOF,CBGT,0,1), BBOYCB_MASK, PPC, { CR, BDP } }, +{ "bngl", BBOCB(16,BOF,CBGT,0,1), BBOYCB_MASK, COM, { CR, BD } }, +{ "bnga-", BBOCB(16,BOF,CBGT,1,0), BBOYCB_MASK, PPC, { CR, BDMA } }, +{ "bnga+", BBOCB(16,BOF,CBGT,1,0), BBOYCB_MASK, PPC, { CR, BDPA } }, +{ "bnga", BBOCB(16,BOF,CBGT,1,0), BBOYCB_MASK, COM, { CR, BDA } }, +{ "bngla-", BBOCB(16,BOF,CBGT,1,1), BBOYCB_MASK, PPC, { CR, BDMA } }, +{ "bngla+", BBOCB(16,BOF,CBGT,1,1), BBOYCB_MASK, PPC, { CR, BDPA } }, +{ "bngla", BBOCB(16,BOF,CBGT,1,1), BBOYCB_MASK, COM, { CR, BDA } }, +{ "bne-", BBOCB(16,BOF,CBEQ,0,0), BBOYCB_MASK, PPC, { CR, BDM } }, +{ "bne+", BBOCB(16,BOF,CBEQ,0,0), BBOYCB_MASK, PPC, { CR, BDP } }, +{ "bne", BBOCB(16,BOF,CBEQ,0,0), BBOYCB_MASK, COM, { CR, BD } }, +{ "bnel-", BBOCB(16,BOF,CBEQ,0,1), BBOYCB_MASK, PPC, { CR, BDM } }, +{ "bnel+", BBOCB(16,BOF,CBEQ,0,1), BBOYCB_MASK, PPC, { CR, BDP } }, +{ "bnel", BBOCB(16,BOF,CBEQ,0,1), BBOYCB_MASK, COM, { CR, BD } }, +{ "bnea-", BBOCB(16,BOF,CBEQ,1,0), BBOYCB_MASK, PPC, { CR, BDMA } }, +{ "bnea+", BBOCB(16,BOF,CBEQ,1,0), BBOYCB_MASK, PPC, { CR, BDPA } }, +{ "bnea", BBOCB(16,BOF,CBEQ,1,0), BBOYCB_MASK, COM, { CR, BDA } }, +{ "bnela-", BBOCB(16,BOF,CBEQ,1,1), BBOYCB_MASK, PPC, { CR, BDMA } }, +{ "bnela+", BBOCB(16,BOF,CBEQ,1,1), BBOYCB_MASK, PPC, { CR, BDPA } }, +{ "bnela", BBOCB(16,BOF,CBEQ,1,1), BBOYCB_MASK, COM, { CR, BDA } }, +{ "bns-", BBOCB(16,BOF,CBSO,0,0), BBOYCB_MASK, PPC, { CR, BDM } }, +{ "bns+", BBOCB(16,BOF,CBSO,0,0), BBOYCB_MASK, PPC, { CR, BDP } }, +{ "bns", BBOCB(16,BOF,CBSO,0,0), BBOYCB_MASK, COM, { CR, BD } }, +{ "bnsl-", BBOCB(16,BOF,CBSO,0,1), BBOYCB_MASK, PPC, { CR, BDM } }, +{ "bnsl+", BBOCB(16,BOF,CBSO,0,1), BBOYCB_MASK, PPC, { CR, BDP } }, +{ "bnsl", BBOCB(16,BOF,CBSO,0,1), BBOYCB_MASK, COM, { CR, BD } }, +{ "bnsa-", BBOCB(16,BOF,CBSO,1,0), BBOYCB_MASK, PPC, { CR, BDMA } }, +{ "bnsa+", BBOCB(16,BOF,CBSO,1,0), BBOYCB_MASK, PPC, { CR, BDPA } }, +{ "bnsa", BBOCB(16,BOF,CBSO,1,0), BBOYCB_MASK, COM, { CR, BDA } }, +{ "bnsla-", BBOCB(16,BOF,CBSO,1,1), BBOYCB_MASK, PPC, { CR, BDMA } }, +{ "bnsla+", BBOCB(16,BOF,CBSO,1,1), BBOYCB_MASK, PPC, { CR, BDPA } }, +{ "bnsla", BBOCB(16,BOF,CBSO,1,1), BBOYCB_MASK, COM, { CR, BDA } }, +{ "bnu-", BBOCB(16,BOF,CBSO,0,0), BBOYCB_MASK, PPC, { CR, BDM } }, +{ "bnu+", BBOCB(16,BOF,CBSO,0,0), BBOYCB_MASK, PPC, { CR, BDP } }, +{ "bnu", BBOCB(16,BOF,CBSO,0,0), BBOYCB_MASK, PPCCOM, { CR, BD } }, +{ "bnul-", BBOCB(16,BOF,CBSO,0,1), BBOYCB_MASK, PPC, { CR, BDM } }, +{ "bnul+", BBOCB(16,BOF,CBSO,0,1), BBOYCB_MASK, PPC, { CR, BDP } }, +{ "bnul", BBOCB(16,BOF,CBSO,0,1), BBOYCB_MASK, PPCCOM, { CR, BD } }, +{ "bnua-", BBOCB(16,BOF,CBSO,1,0), BBOYCB_MASK, PPC, { CR, BDMA } }, +{ "bnua+", BBOCB(16,BOF,CBSO,1,0), BBOYCB_MASK, PPC, { CR, BDPA } }, +{ "bnua", BBOCB(16,BOF,CBSO,1,0), BBOYCB_MASK, PPCCOM, { CR, BDA } }, +{ "bnula-", BBOCB(16,BOF,CBSO,1,1), BBOYCB_MASK, PPC, { CR, BDMA } }, +{ "bnula+", BBOCB(16,BOF,CBSO,1,1), BBOYCB_MASK, PPC, { CR, BDPA } }, +{ "bnula", BBOCB(16,BOF,CBSO,1,1), BBOYCB_MASK, PPCCOM, { CR, BDA } }, +{ "bdnzt-", BBO(16,BODNZT,0,0), BBOY_MASK, PPC, { BI, BDM } }, +{ "bdnzt+", BBO(16,BODNZT,0,0), BBOY_MASK, PPC, { BI, BDP } }, +{ "bdnzt", BBO(16,BODNZT,0,0), BBOY_MASK, PPCCOM, { BI, BD } }, +{ "bdnztl-", BBO(16,BODNZT,0,1), BBOY_MASK, PPC, { BI, BDM } }, +{ "bdnztl+", BBO(16,BODNZT,0,1), BBOY_MASK, PPC, { BI, BDP } }, +{ "bdnztl", BBO(16,BODNZT,0,1), BBOY_MASK, PPCCOM, { BI, BD } }, +{ "bdnzta-", BBO(16,BODNZT,1,0), BBOY_MASK, PPC, { BI, BDMA } }, +{ "bdnzta+", BBO(16,BODNZT,1,0), BBOY_MASK, PPC, { BI, BDPA } }, +{ "bdnzta", BBO(16,BODNZT,1,0), BBOY_MASK, PPCCOM, { BI, BDA } }, +{ "bdnztla-",BBO(16,BODNZT,1,1), BBOY_MASK, PPC, { BI, BDMA } }, +{ "bdnztla+",BBO(16,BODNZT,1,1), BBOY_MASK, PPC, { BI, BDPA } }, +{ "bdnztla", BBO(16,BODNZT,1,1), BBOY_MASK, PPCCOM, { BI, BDA } }, +{ "bdnzf-", BBO(16,BODNZF,0,0), BBOY_MASK, PPC, { BI, BDM } }, +{ "bdnzf+", BBO(16,BODNZF,0,0), BBOY_MASK, PPC, { BI, BDP } }, +{ "bdnzf", BBO(16,BODNZF,0,0), BBOY_MASK, PPCCOM, { BI, BD } }, +{ "bdnzfl-", BBO(16,BODNZF,0,1), BBOY_MASK, PPC, { BI, BDM } }, +{ "bdnzfl+", BBO(16,BODNZF,0,1), BBOY_MASK, PPC, { BI, BDP } }, +{ "bdnzfl", BBO(16,BODNZF,0,1), BBOY_MASK, PPCCOM, { BI, BD } }, +{ "bdnzfa-", BBO(16,BODNZF,1,0), BBOY_MASK, PPC, { BI, BDMA } }, +{ "bdnzfa+", BBO(16,BODNZF,1,0), BBOY_MASK, PPC, { BI, BDPA } }, +{ "bdnzfa", BBO(16,BODNZF,1,0), BBOY_MASK, PPCCOM, { BI, BDA } }, +{ "bdnzfla-",BBO(16,BODNZF,1,1), BBOY_MASK, PPC, { BI, BDMA } }, +{ "bdnzfla+",BBO(16,BODNZF,1,1), BBOY_MASK, PPC, { BI, BDPA } }, +{ "bdnzfla", BBO(16,BODNZF,1,1), BBOY_MASK, PPCCOM, { BI, BDA } }, +{ "bt-", BBO(16,BOT,0,0), BBOY_MASK, PPC, { BI, BDM } }, +{ "bt+", BBO(16,BOT,0,0), BBOY_MASK, PPC, { BI, BDP } }, +{ "bt", BBO(16,BOT,0,0), BBOY_MASK, PPCCOM, { BI, BD } }, +{ "bbt", BBO(16,BOT,0,0), BBOY_MASK, PWRCOM, { BI, BD } }, +{ "btl-", BBO(16,BOT,0,1), BBOY_MASK, PPC, { BI, BDM } }, +{ "btl+", BBO(16,BOT,0,1), BBOY_MASK, PPC, { BI, BDP } }, +{ "btl", BBO(16,BOT,0,1), BBOY_MASK, PPCCOM, { BI, BD } }, +{ "bbtl", BBO(16,BOT,0,1), BBOY_MASK, PWRCOM, { BI, BD } }, +{ "bta-", BBO(16,BOT,1,0), BBOY_MASK, PPC, { BI, BDMA } }, +{ "bta+", BBO(16,BOT,1,0), BBOY_MASK, PPC, { BI, BDPA } }, +{ "bta", BBO(16,BOT,1,0), BBOY_MASK, PPCCOM, { BI, BDA } }, +{ "bbta", BBO(16,BOT,1,0), BBOY_MASK, PWRCOM, { BI, BDA } }, +{ "btla-", BBO(16,BOT,1,1), BBOY_MASK, PPC, { BI, BDMA } }, +{ "btla+", BBO(16,BOT,1,1), BBOY_MASK, PPC, { BI, BDPA } }, +{ "btla", BBO(16,BOT,1,1), BBOY_MASK, PPCCOM, { BI, BDA } }, +{ "bbtla", BBO(16,BOT,1,1), BBOY_MASK, PWRCOM, { BI, BDA } }, +{ "bf-", BBO(16,BOF,0,0), BBOY_MASK, PPC, { BI, BDM } }, +{ "bf+", BBO(16,BOF,0,0), BBOY_MASK, PPC, { BI, BDP } }, +{ "bf", BBO(16,BOF,0,0), BBOY_MASK, PPCCOM, { BI, BD } }, +{ "bbf", BBO(16,BOF,0,0), BBOY_MASK, PWRCOM, { BI, BD } }, +{ "bfl-", BBO(16,BOF,0,1), BBOY_MASK, PPC, { BI, BDM } }, +{ "bfl+", BBO(16,BOF,0,1), BBOY_MASK, PPC, { BI, BDP } }, +{ "bfl", BBO(16,BOF,0,1), BBOY_MASK, PPCCOM, { BI, BD } }, +{ "bbfl", BBO(16,BOF,0,1), BBOY_MASK, PWRCOM, { BI, BD } }, +{ "bfa-", BBO(16,BOF,1,0), BBOY_MASK, PPC, { BI, BDMA } }, +{ "bfa+", BBO(16,BOF,1,0), BBOY_MASK, PPC, { BI, BDPA } }, +{ "bfa", BBO(16,BOF,1,0), BBOY_MASK, PPCCOM, { BI, BDA } }, +{ "bbfa", BBO(16,BOF,1,0), BBOY_MASK, PWRCOM, { BI, BDA } }, +{ "bfla-", BBO(16,BOF,1,1), BBOY_MASK, PPC, { BI, BDMA } }, +{ "bfla+", BBO(16,BOF,1,1), BBOY_MASK, PPC, { BI, BDPA } }, +{ "bfla", BBO(16,BOF,1,1), BBOY_MASK, PPCCOM, { BI, BDA } }, +{ "bbfla", BBO(16,BOF,1,1), BBOY_MASK, PWRCOM, { BI, BDA } }, +{ "bdzt-", BBO(16,BODZT,0,0), BBOY_MASK, PPC, { BI, BDM } }, +{ "bdzt+", BBO(16,BODZT,0,0), BBOY_MASK, PPC, { BI, BDP } }, +{ "bdzt", BBO(16,BODZT,0,0), BBOY_MASK, PPCCOM, { BI, BD } }, +{ "bdztl-", BBO(16,BODZT,0,1), BBOY_MASK, PPC, { BI, BDM } }, +{ "bdztl+", BBO(16,BODZT,0,1), BBOY_MASK, PPC, { BI, BDP } }, +{ "bdztl", BBO(16,BODZT,0,1), BBOY_MASK, PPCCOM, { BI, BD } }, +{ "bdzta-", BBO(16,BODZT,1,0), BBOY_MASK, PPC, { BI, BDMA } }, +{ "bdzta+", BBO(16,BODZT,1,0), BBOY_MASK, PPC, { BI, BDPA } }, +{ "bdzta", BBO(16,BODZT,1,0), BBOY_MASK, PPCCOM, { BI, BDA } }, +{ "bdztla-", BBO(16,BODZT,1,1), BBOY_MASK, PPC, { BI, BDMA } }, +{ "bdztla+", BBO(16,BODZT,1,1), BBOY_MASK, PPC, { BI, BDPA } }, +{ "bdztla", BBO(16,BODZT,1,1), BBOY_MASK, PPCCOM, { BI, BDA } }, +{ "bdzf-", BBO(16,BODZF,0,0), BBOY_MASK, PPC, { BI, BDM } }, +{ "bdzf+", BBO(16,BODZF,0,0), BBOY_MASK, PPC, { BI, BDP } }, +{ "bdzf", BBO(16,BODZF,0,0), BBOY_MASK, PPCCOM, { BI, BD } }, +{ "bdzfl-", BBO(16,BODZF,0,1), BBOY_MASK, PPC, { BI, BDM } }, +{ "bdzfl+", BBO(16,BODZF,0,1), BBOY_MASK, PPC, { BI, BDP } }, +{ "bdzfl", BBO(16,BODZF,0,1), BBOY_MASK, PPCCOM, { BI, BD } }, +{ "bdzfa-", BBO(16,BODZF,1,0), BBOY_MASK, PPC, { BI, BDMA } }, +{ "bdzfa+", BBO(16,BODZF,1,0), BBOY_MASK, PPC, { BI, BDPA } }, +{ "bdzfa", BBO(16,BODZF,1,0), BBOY_MASK, PPCCOM, { BI, BDA } }, +{ "bdzfla-", BBO(16,BODZF,1,1), BBOY_MASK, PPC, { BI, BDMA } }, +{ "bdzfla+", BBO(16,BODZF,1,1), BBOY_MASK, PPC, { BI, BDPA } }, +{ "bdzfla", BBO(16,BODZF,1,1), BBOY_MASK, PPCCOM, { BI, BDA } }, +{ "bc-", B(16,0,0), B_MASK, PPC, { BOE, BI, BDM } }, +{ "bc+", B(16,0,0), B_MASK, PPC, { BOE, BI, BDP } }, +{ "bc", B(16,0,0), B_MASK, COM, { BO, BI, BD } }, +{ "bcl-", B(16,0,1), B_MASK, PPC, { BOE, BI, BDM } }, +{ "bcl+", B(16,0,1), B_MASK, PPC, { BOE, BI, BDP } }, +{ "bcl", B(16,0,1), B_MASK, COM, { BO, BI, BD } }, +{ "bca-", B(16,1,0), B_MASK, PPC, { BOE, BI, BDMA } }, +{ "bca+", B(16,1,0), B_MASK, PPC, { BOE, BI, BDPA } }, +{ "bca", B(16,1,0), B_MASK, COM, { BO, BI, BDA } }, +{ "bcla-", B(16,1,1), B_MASK, PPC, { BOE, BI, BDMA } }, +{ "bcla+", B(16,1,1), B_MASK, PPC, { BOE, BI, BDPA } }, +{ "bcla", B(16,1,1), B_MASK, COM, { BO, BI, BDA } }, + +{ "sc", SC(17,1,0), 0xffffffff, PPC, { 0 } }, +{ "svc", SC(17,0,0), SC_MASK, POWER, { LEV, FL1, FL2 } }, +{ "svcl", SC(17,0,1), SC_MASK, POWER, { LEV, FL1, FL2 } }, +{ "svca", SC(17,1,0), SC_MASK, PWRCOM, { SV } }, +{ "svcla", SC(17,1,1), SC_MASK, POWER, { SV } }, + +{ "b", B(18,0,0), B_MASK, COM, { LI } }, +{ "bl", B(18,0,1), B_MASK, COM, { LI } }, +{ "ba", B(18,1,0), B_MASK, COM, { LIA } }, +{ "bla", B(18,1,1), B_MASK, COM, { LIA } }, + +{ "mcrf", XL(19,0), XLBB_MASK|(3<<21)|(3<<16), COM, { BF, BFA } }, + +{ "blr", XLO(19,BOU,16,0), XLBOBIBB_MASK, PPCCOM, { 0 } }, +{ "br", XLO(19,BOU,16,0), XLBOBIBB_MASK, PWRCOM, { 0 } }, +{ "blrl", XLO(19,BOU,16,1), XLBOBIBB_MASK, PPCCOM, { 0 } }, +{ "brl", XLO(19,BOU,16,1), XLBOBIBB_MASK, PWRCOM, { 0 } }, +{ "bdnzlr", XLO(19,BODNZ,16,0), XLBOBIBB_MASK, PPCCOM, { 0 } }, +{ "bdnzlr-", XLO(19,BODNZ,16,0), XLBOBIBB_MASK, PPC, { 0 } }, +{ "bdnzlr+", XLO(19,BODNZP,16,0), XLBOBIBB_MASK, PPC, { 0 } }, +{ "bdnzlrl", XLO(19,BODNZ,16,1), XLBOBIBB_MASK, PPCCOM, { 0 } }, +{ "bdnzlrl-",XLO(19,BODNZ,16,1), XLBOBIBB_MASK, PPC, { 0 } }, +{ "bdnzlrl+",XLO(19,BODNZP,16,1), XLBOBIBB_MASK, PPC, { 0 } }, +{ "bdzlr", XLO(19,BODZ,16,0), XLBOBIBB_MASK, PPCCOM, { 0 } }, +{ "bdzlr-", XLO(19,BODZ,16,0), XLBOBIBB_MASK, PPC, { 0 } }, +{ "bdzlr+", XLO(19,BODZP,16,0), XLBOBIBB_MASK, PPC, { 0 } }, +{ "bdzlrl", XLO(19,BODZ,16,1), XLBOBIBB_MASK, PPCCOM, { 0 } }, +{ "bdzlrl-", XLO(19,BODZ,16,1), XLBOBIBB_MASK, PPC, { 0 } }, +{ "bdzlrl+", XLO(19,BODZP,16,1), XLBOBIBB_MASK, PPC, { 0 } }, +{ "bltlr", XLOCB(19,BOT,CBLT,16,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bltlr-", XLOCB(19,BOT,CBLT,16,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bltlr+", XLOCB(19,BOTP,CBLT,16,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bltr", XLOCB(19,BOT,CBLT,16,0), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "bltlrl", XLOCB(19,BOT,CBLT,16,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bltlrl-", XLOCB(19,BOT,CBLT,16,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "bltlrl+", XLOCB(19,BOTP,CBLT,16,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "bltrl", XLOCB(19,BOT,CBLT,16,1), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "bgtlr", XLOCB(19,BOT,CBGT,16,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bgtlr-", XLOCB(19,BOT,CBGT,16,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bgtlr+", XLOCB(19,BOTP,CBGT,16,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bgtr", XLOCB(19,BOT,CBGT,16,0), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "bgtlrl", XLOCB(19,BOT,CBGT,16,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bgtlrl-", XLOCB(19,BOT,CBGT,16,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "bgtlrl+", XLOCB(19,BOTP,CBGT,16,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "bgtrl", XLOCB(19,BOT,CBGT,16,1), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "beqlr", XLOCB(19,BOT,CBEQ,16,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "beqlr-", XLOCB(19,BOT,CBEQ,16,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "beqlr+", XLOCB(19,BOTP,CBEQ,16,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "beqr", XLOCB(19,BOT,CBEQ,16,0), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "beqlrl", XLOCB(19,BOT,CBEQ,16,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "beqlrl-", XLOCB(19,BOT,CBEQ,16,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "beqlrl+", XLOCB(19,BOTP,CBEQ,16,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "beqrl", XLOCB(19,BOT,CBEQ,16,1), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "bsolr", XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bsolr-", XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bsolr+", XLOCB(19,BOTP,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bsor", XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "bsolrl", XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bsolrl-", XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "bsolrl+", XLOCB(19,BOTP,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "bsorl", XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "bunlr", XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bunlr-", XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bunlr+", XLOCB(19,BOTP,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bunlrl", XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bunlrl-", XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "bunlrl+", XLOCB(19,BOTP,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "bgelr", XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bgelr-", XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bgelr+", XLOCB(19,BOFP,CBLT,16,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bger", XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "bgelrl", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bgelrl-", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "bgelrl+", XLOCB(19,BOFP,CBLT,16,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "bgerl", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "bnllr", XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bnllr-", XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bnllr+", XLOCB(19,BOFP,CBLT,16,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bnlr", XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "bnllrl", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bnllrl-", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "bnllrl+", XLOCB(19,BOFP,CBLT,16,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "bnlrl", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "blelr", XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "blelr-", XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "blelr+", XLOCB(19,BOFP,CBGT,16,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bler", XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "blelrl", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "blelrl-", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "blelrl+", XLOCB(19,BOFP,CBGT,16,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "blerl", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "bnglr", XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bnglr-", XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bnglr+", XLOCB(19,BOFP,CBGT,16,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bngr", XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "bnglrl", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bnglrl-", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "bnglrl+", XLOCB(19,BOFP,CBGT,16,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "bngrl", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "bnelr", XLOCB(19,BOF,CBEQ,16,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bnelr-", XLOCB(19,BOF,CBEQ,16,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bnelr+", XLOCB(19,BOFP,CBEQ,16,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bner", XLOCB(19,BOF,CBEQ,16,0), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "bnelrl", XLOCB(19,BOF,CBEQ,16,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bnelrl-", XLOCB(19,BOF,CBEQ,16,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "bnelrl+", XLOCB(19,BOFP,CBEQ,16,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "bnerl", XLOCB(19,BOF,CBEQ,16,1), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "bnslr", XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bnslr-", XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bnslr+", XLOCB(19,BOFP,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bnsr", XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "bnslrl", XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bnslrl-", XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "bnslrl+", XLOCB(19,BOFP,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "bnsrl", XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "bnulr", XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bnulr-", XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bnulr+", XLOCB(19,BOFP,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bnulrl", XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bnulrl-", XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "bnulrl+", XLOCB(19,BOFP,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "btlr", XLO(19,BOT,16,0), XLBOBB_MASK, PPCCOM, { BI } }, +{ "btlr-", XLO(19,BOT,16,0), XLBOBB_MASK, PPC, { BI } }, +{ "btlr+", XLO(19,BOTP,16,0), XLBOBB_MASK, PPC, { BI } }, +{ "bbtr", XLO(19,BOT,16,0), XLBOBB_MASK, PWRCOM, { BI } }, +{ "btlrl", XLO(19,BOT,16,1), XLBOBB_MASK, PPCCOM, { BI } }, +{ "btlrl-", XLO(19,BOT,16,1), XLBOBB_MASK, PPC, { BI } }, +{ "btlrl+", XLO(19,BOTP,16,1), XLBOBB_MASK, PPC, { BI } }, +{ "bbtrl", XLO(19,BOT,16,1), XLBOBB_MASK, PWRCOM, { BI } }, +{ "bflr", XLO(19,BOF,16,0), XLBOBB_MASK, PPCCOM, { BI } }, +{ "bflr-", XLO(19,BOF,16,0), XLBOBB_MASK, PPC, { BI } }, +{ "bflr+", XLO(19,BOFP,16,0), XLBOBB_MASK, PPC, { BI } }, +{ "bbfr", XLO(19,BOF,16,0), XLBOBB_MASK, PWRCOM, { BI } }, +{ "bflrl", XLO(19,BOF,16,1), XLBOBB_MASK, PPCCOM, { BI } }, +{ "bflrl-", XLO(19,BOF,16,1), XLBOBB_MASK, PPC, { BI } }, +{ "bflrl+", XLO(19,BOFP,16,1), XLBOBB_MASK, PPC, { BI } }, +{ "bbfrl", XLO(19,BOF,16,1), XLBOBB_MASK, PWRCOM, { BI } }, +{ "bdnztlr", XLO(19,BODNZT,16,0), XLBOBB_MASK, PPCCOM, { BI } }, +{ "bdnztlr-",XLO(19,BODNZT,16,0), XLBOBB_MASK, PPC, { BI } }, +{ "bdnztlr+",XLO(19,BODNZTP,16,0), XLBOBB_MASK, PPC, { BI } }, +{ "bdnztlrl",XLO(19,BODNZT,16,1), XLBOBB_MASK, PPCCOM, { BI } }, +{ "bdnztlrl-",XLO(19,BODNZT,16,1), XLBOBB_MASK, PPC, { BI } }, +{ "bdnztlrl+",XLO(19,BODNZTP,16,1), XLBOBB_MASK, PPC, { BI } }, +{ "bdnzflr", XLO(19,BODNZF,16,0), XLBOBB_MASK, PPCCOM, { BI } }, +{ "bdnzflr-",XLO(19,BODNZF,16,0), XLBOBB_MASK, PPC, { BI } }, +{ "bdnzflr+",XLO(19,BODNZFP,16,0), XLBOBB_MASK, PPC, { BI } }, +{ "bdnzflrl",XLO(19,BODNZF,16,1), XLBOBB_MASK, PPCCOM, { BI } }, +{ "bdnzflrl-",XLO(19,BODNZF,16,1), XLBOBB_MASK, PPC, { BI } }, +{ "bdnzflrl+",XLO(19,BODNZFP,16,1), XLBOBB_MASK, PPC, { BI } }, +{ "bdztlr", XLO(19,BODZT,16,0), XLBOBB_MASK, PPCCOM, { BI } }, +{ "bdztlr-", XLO(19,BODZT,16,0), XLBOBB_MASK, PPC, { BI } }, +{ "bdztlr+", XLO(19,BODZTP,16,0), XLBOBB_MASK, PPC, { BI } }, +{ "bdztlrl", XLO(19,BODZT,16,1), XLBOBB_MASK, PPCCOM, { BI } }, +{ "bdztlrl-",XLO(19,BODZT,16,1), XLBOBB_MASK, PPC, { BI } }, +{ "bdztlrl+",XLO(19,BODZTP,16,1), XLBOBB_MASK, PPC, { BI } }, +{ "bdzflr", XLO(19,BODZF,16,0), XLBOBB_MASK, PPCCOM, { BI } }, +{ "bdzflr-", XLO(19,BODZF,16,0), XLBOBB_MASK, PPC, { BI } }, +{ "bdzflr+", XLO(19,BODZFP,16,0), XLBOBB_MASK, PPC, { BI } }, +{ "bdzflrl", XLO(19,BODZF,16,1), XLBOBB_MASK, PPCCOM, { BI } }, +{ "bdzflrl-",XLO(19,BODZF,16,1), XLBOBB_MASK, PPC, { BI } }, +{ "bdzflrl+",XLO(19,BODZFP,16,1), XLBOBB_MASK, PPC, { BI } }, +{ "bclr", XLLK(19,16,0), XLYBB_MASK, PPCCOM, { BO, BI } }, +{ "bclrl", XLLK(19,16,1), XLYBB_MASK, PPCCOM, { BO, BI } }, +{ "bclr+", XLYLK(19,16,1,0), XLYBB_MASK, PPC, { BOE, BI } }, +{ "bclrl+", XLYLK(19,16,1,1), XLYBB_MASK, PPC, { BOE, BI } }, +{ "bclr-", XLYLK(19,16,0,0), XLYBB_MASK, PPC, { BOE, BI } }, +{ "bclrl-", XLYLK(19,16,0,1), XLYBB_MASK, PPC, { BOE, BI } }, +{ "bcr", XLLK(19,16,0), XLBB_MASK, PWRCOM, { BO, BI } }, +{ "bcrl", XLLK(19,16,1), XLBB_MASK, PWRCOM, { BO, BI } }, + +{ "crnot", XL(19,33), XL_MASK, PPCCOM, { BT, BA, BBA } }, +{ "crnor", XL(19,33), XL_MASK, COM, { BT, BA, BB } }, + +{ "rfi", XL(19,50), 0xffffffff, COM, { 0 } }, +{ "rfci", XL(19,51), 0xffffffff, PPC, { 0 } }, + +{ "rfsvc", XL(19,82), 0xffffffff, POWER, { 0 } }, + +{ "crandc", XL(19,129), XL_MASK, COM, { BT, BA, BB } }, + +{ "isync", XL(19,150), 0xffffffff, PPCCOM, { 0 } }, +{ "ics", XL(19,150), 0xffffffff, PWRCOM, { 0 } }, + +{ "crclr", XL(19,193), XL_MASK, PPCCOM, { BT, BAT, BBA } }, +{ "crxor", XL(19,193), XL_MASK, COM, { BT, BA, BB } }, + +{ "crnand", XL(19,225), XL_MASK, COM, { BT, BA, BB } }, + +{ "crand", XL(19,257), XL_MASK, COM, { BT, BA, BB } }, + +{ "crset", XL(19,289), XL_MASK, PPCCOM, { BT, BAT, BBA } }, +{ "creqv", XL(19,289), XL_MASK, COM, { BT, BA, BB } }, + +{ "crorc", XL(19,417), XL_MASK, COM, { BT, BA, BB } }, + +{ "crmove", XL(19,449), XL_MASK, PPCCOM, { BT, BA, BBA } }, +{ "cror", XL(19,449), XL_MASK, COM, { BT, BA, BB } }, + +{ "bctr", XLO(19,BOU,528,0), XLBOBIBB_MASK, COM, { 0 } }, +{ "bctrl", XLO(19,BOU,528,1), XLBOBIBB_MASK, COM, { 0 } }, +{ "bltctr", XLOCB(19,BOT,CBLT,528,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bltctr-", XLOCB(19,BOT,CBLT,528,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bltctr+", XLOCB(19,BOTP,CBLT,528,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bltctrl", XLOCB(19,BOT,CBLT,528,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bltctrl-",XLOCB(19,BOT,CBLT,528,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "bltctrl+",XLOCB(19,BOTP,CBLT,528,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "bgtctr", XLOCB(19,BOT,CBGT,528,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bgtctr-", XLOCB(19,BOT,CBGT,528,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bgtctr+", XLOCB(19,BOTP,CBGT,528,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bgtctrl", XLOCB(19,BOT,CBGT,528,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bgtctrl-",XLOCB(19,BOT,CBGT,528,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "bgtctrl+",XLOCB(19,BOTP,CBGT,528,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "beqctr", XLOCB(19,BOT,CBEQ,528,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "beqctr-", XLOCB(19,BOT,CBEQ,528,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "beqctr+", XLOCB(19,BOTP,CBEQ,528,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "beqctrl", XLOCB(19,BOT,CBEQ,528,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "beqctrl-",XLOCB(19,BOT,CBEQ,528,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "beqctrl+",XLOCB(19,BOTP,CBEQ,528,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "bsoctr", XLOCB(19,BOT,CBSO,528,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bsoctr-", XLOCB(19,BOT,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bsoctr+", XLOCB(19,BOTP,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bsoctrl", XLOCB(19,BOT,CBSO,528,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bsoctrl-",XLOCB(19,BOT,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "bsoctrl+",XLOCB(19,BOTP,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "bunctr", XLOCB(19,BOT,CBSO,528,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bunctr-", XLOCB(19,BOT,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bunctr+", XLOCB(19,BOTP,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bunctrl", XLOCB(19,BOT,CBSO,528,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bunctrl-",XLOCB(19,BOT,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "bunctrl+",XLOCB(19,BOTP,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "bgectr", XLOCB(19,BOF,CBLT,528,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bgectr-", XLOCB(19,BOF,CBLT,528,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bgectr+", XLOCB(19,BOFP,CBLT,528,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bgectrl", XLOCB(19,BOF,CBLT,528,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bgectrl-",XLOCB(19,BOF,CBLT,528,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "bgectrl+",XLOCB(19,BOFP,CBLT,528,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "bnlctr", XLOCB(19,BOF,CBLT,528,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bnlctr-", XLOCB(19,BOF,CBLT,528,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bnlctr+", XLOCB(19,BOFP,CBLT,528,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bnlctrl", XLOCB(19,BOF,CBLT,528,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bnlctrl-",XLOCB(19,BOF,CBLT,528,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "bnlctrl+",XLOCB(19,BOFP,CBLT,528,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "blectr", XLOCB(19,BOF,CBGT,528,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "blectr-", XLOCB(19,BOF,CBGT,528,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "blectr+", XLOCB(19,BOFP,CBGT,528,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "blectrl", XLOCB(19,BOF,CBGT,528,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "blectrl-",XLOCB(19,BOF,CBGT,528,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "blectrl+",XLOCB(19,BOFP,CBGT,528,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "bngctr", XLOCB(19,BOF,CBGT,528,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bngctr-", XLOCB(19,BOF,CBGT,528,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bngctr+", XLOCB(19,BOFP,CBGT,528,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bngctrl", XLOCB(19,BOF,CBGT,528,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bngctrl-",XLOCB(19,BOF,CBGT,528,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "bngctrl+",XLOCB(19,BOFP,CBGT,528,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "bnectr", XLOCB(19,BOF,CBEQ,528,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bnectr-", XLOCB(19,BOF,CBEQ,528,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bnectr+", XLOCB(19,BOFP,CBEQ,528,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bnectrl", XLOCB(19,BOF,CBEQ,528,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bnectrl-",XLOCB(19,BOF,CBEQ,528,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "bnectrl+",XLOCB(19,BOFP,CBEQ,528,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "bnsctr", XLOCB(19,BOF,CBSO,528,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bnsctr-", XLOCB(19,BOF,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bnsctr+", XLOCB(19,BOFP,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bnsctrl", XLOCB(19,BOF,CBSO,528,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bnsctrl-",XLOCB(19,BOF,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "bnsctrl+",XLOCB(19,BOFP,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "bnuctr", XLOCB(19,BOF,CBSO,528,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bnuctr-", XLOCB(19,BOF,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bnuctr+", XLOCB(19,BOFP,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } }, +{ "bnuctrl", XLOCB(19,BOF,CBSO,528,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bnuctrl-",XLOCB(19,BOF,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "bnuctrl+",XLOCB(19,BOFP,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } }, +{ "btctr", XLO(19,BOT,528,0), XLBOBB_MASK, PPCCOM, { BI } }, +{ "btctr-", XLO(19,BOT,528,0), XLBOBB_MASK, PPC, { BI } }, +{ "btctr+", XLO(19,BOTP,528,0), XLBOBB_MASK, PPC, { BI } }, +{ "btctrl", XLO(19,BOT,528,1), XLBOBB_MASK, PPCCOM, { BI } }, +{ "btctrl-", XLO(19,BOT,528,1), XLBOBB_MASK, PPC, { BI } }, +{ "btctrl+", XLO(19,BOTP,528,1), XLBOBB_MASK, PPC, { BI } }, +{ "bfctr", XLO(19,BOF,528,0), XLBOBB_MASK, PPCCOM, { BI } }, +{ "bfctr-", XLO(19,BOF,528,0), XLBOBB_MASK, PPC, { BI } }, +{ "bfctr+", XLO(19,BOFP,528,0), XLBOBB_MASK, PPC, { BI } }, +{ "bfctrl", XLO(19,BOF,528,1), XLBOBB_MASK, PPCCOM, { BI } }, +{ "bfctrl-", XLO(19,BOF,528,1), XLBOBB_MASK, PPC, { BI } }, +{ "bfctrl+", XLO(19,BOFP,528,1), XLBOBB_MASK, PPC, { BI } }, +{ "bcctr", XLLK(19,528,0), XLYBB_MASK, PPCCOM, { BO, BI } }, +{ "bcctr-", XLYLK(19,528,0,0), XLYBB_MASK, PPC, { BOE, BI } }, +{ "bcctr+", XLYLK(19,528,1,0), XLYBB_MASK, PPC, { BOE, BI } }, +{ "bcctrl", XLLK(19,528,1), XLYBB_MASK, PPCCOM, { BO, BI } }, +{ "bcctrl-", XLYLK(19,528,0,1), XLYBB_MASK, PPC, { BOE, BI } }, +{ "bcctrl+", XLYLK(19,528,1,1), XLYBB_MASK, PPC, { BOE, BI } }, +{ "bcc", XLLK(19,528,0), XLBB_MASK, PWRCOM, { BO, BI } }, +{ "bccl", XLLK(19,528,1), XLBB_MASK, PWRCOM, { BO, BI } }, + +{ "rlwimi", M(20,0), M_MASK, PPCCOM, { RA,RS,SH,MBE,ME } }, +{ "rlimi", M(20,0), M_MASK, PWRCOM, { RA,RS,SH,MBE,ME } }, + +{ "rlwimi.", M(20,1), M_MASK, PPCCOM, { RA,RS,SH,MBE,ME } }, +{ "rlimi.", M(20,1), M_MASK, PWRCOM, { RA,RS,SH,MBE,ME } }, + +{ "rotlwi", MME(21,31,0), MMBME_MASK, PPCCOM, { RA, RS, SH } }, +{ "clrlwi", MME(21,31,0), MSHME_MASK, PPCCOM, { RA, RS, MB } }, +{ "rlwinm", M(21,0), M_MASK, PPCCOM, { RA,RS,SH,MBE,ME } }, +{ "rlinm", M(21,0), M_MASK, PWRCOM, { RA,RS,SH,MBE,ME } }, +{ "rotlwi.", MME(21,31,1), MMBME_MASK, PPCCOM, { RA,RS,SH } }, +{ "clrlwi.", MME(21,31,1), MSHME_MASK, PPCCOM, { RA, RS, MB } }, +{ "rlwinm.", M(21,1), M_MASK, PPCCOM, { RA,RS,SH,MBE,ME } }, +{ "rlinm.", M(21,1), M_MASK, PWRCOM, { RA,RS,SH,MBE,ME } }, + +{ "rlmi", M(22,0), M_MASK, M601, { RA,RS,RB,MBE,ME } }, +{ "rlmi.", M(22,1), M_MASK, M601, { RA,RS,RB,MBE,ME } }, + +{ "rotlw", MME(23,31,0), MMBME_MASK, PPCCOM, { RA, RS, RB } }, +{ "rlwnm", M(23,0), M_MASK, PPCCOM, { RA,RS,RB,MBE,ME } }, +{ "rlnm", M(23,0), M_MASK, PWRCOM, { RA,RS,RB,MBE,ME } }, +{ "rotlw.", MME(23,31,1), MMBME_MASK, PPCCOM, { RA, RS, RB } }, +{ "rlwnm.", M(23,1), M_MASK, PPCCOM, { RA,RS,RB,MBE,ME } }, +{ "rlnm.", M(23,1), M_MASK, PWRCOM, { RA,RS,RB,MBE,ME } }, + +{ "nop", OP(24), 0xffffffff, PPCCOM, { 0 } }, +{ "ori", OP(24), OP_MASK, PPCCOM, { RA, RS, UI } }, +{ "oril", OP(24), OP_MASK, PWRCOM, { RA, RS, UI } }, + +{ "oris", OP(25), OP_MASK, PPCCOM, { RA, RS, UI } }, +{ "oriu", OP(25), OP_MASK, PWRCOM, { RA, RS, UI } }, + +{ "xori", OP(26), OP_MASK, PPCCOM, { RA, RS, UI } }, +{ "xoril", OP(26), OP_MASK, PWRCOM, { RA, RS, UI } }, + +{ "xoris", OP(27), OP_MASK, PPCCOM, { RA, RS, UI } }, +{ "xoriu", OP(27), OP_MASK, PWRCOM, { RA, RS, UI } }, + +{ "andi.", OP(28), OP_MASK, PPCCOM, { RA, RS, UI } }, +{ "andil.", OP(28), OP_MASK, PWRCOM, { RA, RS, UI } }, + +{ "andis.", OP(29), OP_MASK, PPCCOM, { RA, RS, UI } }, +{ "andiu.", OP(29), OP_MASK, PWRCOM, { RA, RS, UI } }, + +{ "rotldi", MD(30,0,0), MDMB_MASK, PPC64, { RA, RS, SH6 } }, +{ "clrldi", MD(30,0,0), MDSH_MASK, PPC64, { RA, RS, MB6 } }, +{ "rldicl", MD(30,0,0), MD_MASK, PPC64, { RA, RS, SH6, MB6 } }, +{ "rotldi.", MD(30,0,1), MDMB_MASK, PPC64, { RA, RS, SH6 } }, +{ "clrldi.", MD(30,0,1), MDSH_MASK, PPC64, { RA, RS, MB6 } }, +{ "rldicl.", MD(30,0,1), MD_MASK, PPC64, { RA, RS, SH6, MB6 } }, + +{ "rldicr", MD(30,1,0), MD_MASK, PPC64, { RA, RS, SH6, ME6 } }, +{ "rldicr.", MD(30,1,1), MD_MASK, PPC64, { RA, RS, SH6, ME6 } }, + +{ "rldic", MD(30,2,0), MD_MASK, PPC64, { RA, RS, SH6, MB6 } }, +{ "rldic.", MD(30,2,1), MD_MASK, PPC64, { RA, RS, SH6, MB6 } }, + +{ "rldimi", MD(30,3,0), MD_MASK, PPC64, { RA, RS, SH6, MB6 } }, +{ "rldimi.", MD(30,3,1), MD_MASK, PPC64, { RA, RS, SH6, MB6 } }, + +{ "rotld", MDS(30,8,0), MDSMB_MASK, PPC64, { RA, RS, RB } }, +{ "rldcl", MDS(30,8,0), MDS_MASK, PPC64, { RA, RS, RB, MB6 } }, +{ "rotld.", MDS(30,8,1), MDSMB_MASK, PPC64, { RA, RS, RB } }, +{ "rldcl.", MDS(30,8,1), MDS_MASK, PPC64, { RA, RS, RB, MB6 } }, + +{ "rldcr", MDS(30,9,0), MDS_MASK, PPC64, { RA, RS, RB, ME6 } }, +{ "rldcr.", MDS(30,9,1), MDS_MASK, PPC64, { RA, RS, RB, ME6 } }, + +{ "cmpw", XCMPL(31,0,0), XCMPL_MASK, PPCCOM, { OBF, RA, RB } }, +{ "cmpd", XCMPL(31,0,1), XCMPL_MASK, PPC64, { OBF, RA, RB } }, +{ "cmp", X(31,0), XCMP_MASK, PPCONLY, { BF, L, RA, RB } }, +{ "cmp", X(31,0), XCMPL_MASK, PWRCOM, { BF, RA, RB } }, + +{ "twlgt", XTO(31,4,TOLGT), XTO_MASK, PPCCOM, { RA, RB } }, +{ "tlgt", XTO(31,4,TOLGT), XTO_MASK, PWRCOM, { RA, RB } }, +{ "twllt", XTO(31,4,TOLLT), XTO_MASK, PPCCOM, { RA, RB } }, +{ "tllt", XTO(31,4,TOLLT), XTO_MASK, PWRCOM, { RA, RB } }, +{ "tweq", XTO(31,4,TOEQ), XTO_MASK, PPCCOM, { RA, RB } }, +{ "teq", XTO(31,4,TOEQ), XTO_MASK, PWRCOM, { RA, RB } }, +{ "twlge", XTO(31,4,TOLGE), XTO_MASK, PPCCOM, { RA, RB } }, +{ "tlge", XTO(31,4,TOLGE), XTO_MASK, PWRCOM, { RA, RB } }, +{ "twlnl", XTO(31,4,TOLNL), XTO_MASK, PPCCOM, { RA, RB } }, +{ "tlnl", XTO(31,4,TOLNL), XTO_MASK, PWRCOM, { RA, RB } }, +{ "twlle", XTO(31,4,TOLLE), XTO_MASK, PPCCOM, { RA, RB } }, +{ "tlle", XTO(31,4,TOLLE), XTO_MASK, PWRCOM, { RA, RB } }, +{ "twlng", XTO(31,4,TOLNG), XTO_MASK, PPCCOM, { RA, RB } }, +{ "tlng", XTO(31,4,TOLNG), XTO_MASK, PWRCOM, { RA, RB } }, +{ "twgt", XTO(31,4,TOGT), XTO_MASK, PPCCOM, { RA, RB } }, +{ "tgt", XTO(31,4,TOGT), XTO_MASK, PWRCOM, { RA, RB } }, +{ "twge", XTO(31,4,TOGE), XTO_MASK, PPCCOM, { RA, RB } }, +{ "tge", XTO(31,4,TOGE), XTO_MASK, PWRCOM, { RA, RB } }, +{ "twnl", XTO(31,4,TONL), XTO_MASK, PPCCOM, { RA, RB } }, +{ "tnl", XTO(31,4,TONL), XTO_MASK, PWRCOM, { RA, RB } }, +{ "twlt", XTO(31,4,TOLT), XTO_MASK, PPCCOM, { RA, RB } }, +{ "tlt", XTO(31,4,TOLT), XTO_MASK, PWRCOM, { RA, RB } }, +{ "twle", XTO(31,4,TOLE), XTO_MASK, PPCCOM, { RA, RB } }, +{ "tle", XTO(31,4,TOLE), XTO_MASK, PWRCOM, { RA, RB } }, +{ "twng", XTO(31,4,TONG), XTO_MASK, PPCCOM, { RA, RB } }, +{ "tng", XTO(31,4,TONG), XTO_MASK, PWRCOM, { RA, RB } }, +{ "twne", XTO(31,4,TONE), XTO_MASK, PPCCOM, { RA, RB } }, +{ "tne", XTO(31,4,TONE), XTO_MASK, PWRCOM, { RA, RB } }, +{ "trap", XTO(31,4,TOU), 0xffffffff, PPCCOM, { 0 } }, +{ "tw", X(31,4), X_MASK, PPCCOM, { TO, RA, RB } }, +{ "t", X(31,4), X_MASK, PWRCOM, { TO, RA, RB } }, + +{ "subfc", XO(31,8,0,0), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "sf", XO(31,8,0,0), XO_MASK, PWRCOM, { RT, RA, RB } }, +{ "subc", XO(31,8,0,0), XO_MASK, PPC, { RT, RB, RA } }, +{ "subfc.", XO(31,8,0,1), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "sf.", XO(31,8,0,1), XO_MASK, PWRCOM, { RT, RA, RB } }, +{ "subc.", XO(31,8,0,1), XO_MASK, PPCCOM, { RT, RB, RA } }, +{ "subfco", XO(31,8,1,0), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "sfo", XO(31,8,1,0), XO_MASK, PWRCOM, { RT, RA, RB } }, +{ "subco", XO(31,8,1,0), XO_MASK, PPC, { RT, RB, RA } }, +{ "subfco.", XO(31,8,1,1), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "sfo.", XO(31,8,1,1), XO_MASK, PWRCOM, { RT, RA, RB } }, +{ "subco.", XO(31,8,1,1), XO_MASK, PPC, { RT, RB, RA } }, + +{ "mulhdu", XO(31,9,0,0), XO_MASK, PPC64, { RT, RA, RB } }, +{ "mulhdu.", XO(31,9,0,1), XO_MASK, PPC64, { RT, RA, RB } }, + +{ "addc", XO(31,10,0,0), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "a", XO(31,10,0,0), XO_MASK, PWRCOM, { RT, RA, RB } }, +{ "addc.", XO(31,10,0,1), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "a.", XO(31,10,0,1), XO_MASK, PWRCOM, { RT, RA, RB } }, +{ "addco", XO(31,10,1,0), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "ao", XO(31,10,1,0), XO_MASK, PWRCOM, { RT, RA, RB } }, +{ "addco.", XO(31,10,1,1), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "ao.", XO(31,10,1,1), XO_MASK, PWRCOM, { RT, RA, RB } }, + +{ "mulhwu", XO(31,11,0,0), XO_MASK, PPC, { RT, RA, RB } }, +{ "mulhwu.", XO(31,11,0,1), XO_MASK, PPC, { RT, RA, RB } }, + +{ "mfcr", X(31,19), XRARB_MASK, COM, { RT } }, + +{ "lwarx", X(31,20), X_MASK, PPC, { RT, RA, RB } }, + +{ "ldx", X(31,21), X_MASK, PPC64, { RT, RA, RB } }, + +{ "lwzx", X(31,23), X_MASK, PPCCOM, { RT, RA, RB } }, +{ "lx", X(31,23), X_MASK, PWRCOM, { RT, RA, RB } }, + +{ "slw", XRC(31,24,0), X_MASK, PPCCOM, { RA, RS, RB } }, +{ "sl", XRC(31,24,0), X_MASK, PWRCOM, { RA, RS, RB } }, +{ "slw.", XRC(31,24,1), X_MASK, PPCCOM, { RA, RS, RB } }, +{ "sl.", XRC(31,24,1), X_MASK, PWRCOM, { RA, RS, RB } }, + +{ "cntlzw", XRC(31,26,0), XRB_MASK, PPCCOM, { RA, RS } }, +{ "cntlz", XRC(31,26,0), XRB_MASK, PWRCOM, { RA, RS } }, +{ "cntlzw.", XRC(31,26,1), XRB_MASK, PPCCOM, { RA, RS } }, +{ "cntlz.", XRC(31,26,1), XRB_MASK, PWRCOM, { RA, RS } }, + +{ "sld", XRC(31,27,0), X_MASK, PPC64, { RA, RS, RB } }, +{ "sld.", XRC(31,27,1), X_MASK, PPC64, { RA, RS, RB } }, + +{ "and", XRC(31,28,0), X_MASK, COM, { RA, RS, RB } }, +{ "and.", XRC(31,28,1), X_MASK, COM, { RA, RS, RB } }, + +{ "maskg", XRC(31,29,0), X_MASK, M601, { RA, RS, RB } }, +{ "maskg.", XRC(31,29,1), X_MASK, M601, { RA, RS, RB } }, + +{ "cmplw", XCMPL(31,32,0), XCMPL_MASK, PPCCOM, { OBF, RA, RB } }, +{ "cmpld", XCMPL(31,32,1), XCMPL_MASK, PPC64, { OBF, RA, RB } }, +{ "cmpl", X(31,32), XCMP_MASK, PPCONLY, { BF, L, RA, RB } }, +{ "cmpl", X(31,32), XCMPL_MASK, PWRCOM, { BF, RA, RB } }, + +{ "subf", XO(31,40,0,0), XO_MASK, PPC, { RT, RA, RB } }, +{ "sub", XO(31,40,0,0), XO_MASK, PPC, { RT, RB, RA } }, +{ "subf.", XO(31,40,0,1), XO_MASK, PPC, { RT, RA, RB } }, +{ "sub.", XO(31,40,0,1), XO_MASK, PPC, { RT, RB, RA } }, +{ "subfo", XO(31,40,1,0), XO_MASK, PPC, { RT, RA, RB } }, +{ "subo", XO(31,40,1,0), XO_MASK, PPC, { RT, RB, RA } }, +{ "subfo.", XO(31,40,1,1), XO_MASK, PPC, { RT, RA, RB } }, +{ "subo.", XO(31,40,1,1), XO_MASK, PPC, { RT, RB, RA } }, + +{ "ldux", X(31,53), X_MASK, PPC64, { RT, RAL, RB } }, + +{ "dcbst", X(31,54), XRT_MASK, PPC, { RA, RB } }, + +{ "lwzux", X(31,55), X_MASK, PPCCOM, { RT, RAL, RB } }, +{ "lux", X(31,55), X_MASK, PWRCOM, { RT, RA, RB } }, + +{ "cntlzd", XRC(31,58,0), XRB_MASK, PPC64, { RA, RS } }, +{ "cntlzd.", XRC(31,58,1), XRB_MASK, PPC64, { RA, RS } }, + +{ "andc", XRC(31,60,0), X_MASK, COM, { RA, RS, RB } }, +{ "andc.", XRC(31,60,1), X_MASK, COM, { RA, RS, RB } }, + +{ "tdlgt", XTO(31,68,TOLGT), XTO_MASK, PPC64, { RA, RB } }, +{ "tdllt", XTO(31,68,TOLLT), XTO_MASK, PPC64, { RA, RB } }, +{ "tdeq", XTO(31,68,TOEQ), XTO_MASK, PPC64, { RA, RB } }, +{ "tdlge", XTO(31,68,TOLGE), XTO_MASK, PPC64, { RA, RB } }, +{ "tdlnl", XTO(31,68,TOLNL), XTO_MASK, PPC64, { RA, RB } }, +{ "tdlle", XTO(31,68,TOLLE), XTO_MASK, PPC64, { RA, RB } }, +{ "tdlng", XTO(31,68,TOLNG), XTO_MASK, PPC64, { RA, RB } }, +{ "tdgt", XTO(31,68,TOGT), XTO_MASK, PPC64, { RA, RB } }, +{ "tdge", XTO(31,68,TOGE), XTO_MASK, PPC64, { RA, RB } }, +{ "tdnl", XTO(31,68,TONL), XTO_MASK, PPC64, { RA, RB } }, +{ "tdlt", XTO(31,68,TOLT), XTO_MASK, PPC64, { RA, RB } }, +{ "tdle", XTO(31,68,TOLE), XTO_MASK, PPC64, { RA, RB } }, +{ "tdng", XTO(31,68,TONG), XTO_MASK, PPC64, { RA, RB } }, +{ "tdne", XTO(31,68,TONE), XTO_MASK, PPC64, { RA, RB } }, +{ "td", X(31,68), X_MASK, PPC64, { TO, RA, RB } }, + +{ "mulhd", XO(31,73,0,0), XO_MASK, PPC64, { RT, RA, RB } }, +{ "mulhd.", XO(31,73,0,1), XO_MASK, PPC64, { RT, RA, RB } }, + +{ "mulhw", XO(31,75,0,0), XO_MASK, PPC, { RT, RA, RB } }, +{ "mulhw.", XO(31,75,0,1), XO_MASK, PPC, { RT, RA, RB } }, + +{ "mfmsr", X(31,83), XRARB_MASK, COM, { RT } }, + +{ "ldarx", X(31,84), X_MASK, PPC64, { RT, RA, RB } }, + +{ "dcbf", X(31,86), XRT_MASK, PPC, { RA, RB } }, + +{ "lbzx", X(31,87), X_MASK, COM, { RT, RA, RB } }, + +{ "neg", XO(31,104,0,0), XORB_MASK, COM, { RT, RA } }, +{ "neg.", XO(31,104,0,1), XORB_MASK, COM, { RT, RA } }, +{ "nego", XO(31,104,1,0), XORB_MASK, COM, { RT, RA } }, +{ "nego.", XO(31,104,1,1), XORB_MASK, COM, { RT, RA } }, + +{ "mul", XO(31,107,0,0), XO_MASK, M601, { RT, RA, RB } }, +{ "mul.", XO(31,107,0,1), XO_MASK, M601, { RT, RA, RB } }, +{ "mulo", XO(31,107,1,0), XO_MASK, M601, { RT, RA, RB } }, +{ "mulo.", XO(31,107,1,1), XO_MASK, M601, { RT, RA, RB } }, + +{ "clf", X(31,118), XRB_MASK, POWER, { RT, RA } }, + +{ "lbzux", X(31,119), X_MASK, COM, { RT, RAL, RB } }, + +{ "not", XRC(31,124,0), X_MASK, COM, { RA, RS, RBS } }, +{ "nor", XRC(31,124,0), X_MASK, COM, { RA, RS, RB } }, +{ "not.", XRC(31,124,1), X_MASK, COM, { RA, RS, RBS } }, +{ "nor.", XRC(31,124,1), X_MASK, COM, { RA, RS, RB } }, + +{ "subfe", XO(31,136,0,0), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "sfe", XO(31,136,0,0), XO_MASK, PWRCOM, { RT, RA, RB } }, +{ "subfe.", XO(31,136,0,1), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "sfe.", XO(31,136,0,1), XO_MASK, PWRCOM, { RT, RA, RB } }, +{ "subfeo", XO(31,136,1,0), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "sfeo", XO(31,136,1,0), XO_MASK, PWRCOM, { RT, RA, RB } }, +{ "subfeo.", XO(31,136,1,1), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "sfeo.", XO(31,136,1,1), XO_MASK, PWRCOM, { RT, RA, RB } }, + +{ "adde", XO(31,138,0,0), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "ae", XO(31,138,0,0), XO_MASK, PWRCOM, { RT, RA, RB } }, +{ "adde.", XO(31,138,0,1), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "ae.", XO(31,138,0,1), XO_MASK, PWRCOM, { RT, RA, RB } }, +{ "addeo", XO(31,138,1,0), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "aeo", XO(31,138,1,0), XO_MASK, PWRCOM, { RT, RA, RB } }, +{ "addeo.", XO(31,138,1,1), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "aeo.", XO(31,138,1,1), XO_MASK, PWRCOM, { RT, RA, RB } }, + +{ "mtcr", XFXM(31,144,0xff), XFXFXM_MASK|FXM_MASK, COM, { RS }}, +{ "mtcrf", X(31,144), XFXFXM_MASK, COM, { FXM, RS } }, + +{ "mtmsr", X(31,146), XRARB_MASK, COM, { RS } }, + +{ "stdx", X(31,149), X_MASK, PPC64, { RS, RA, RB } }, + +{ "stwcx.", XRC(31,150,1), X_MASK, PPC, { RS, RA, RB } }, + +{ "stwx", X(31,151), X_MASK, PPCCOM, { RS, RA, RB } }, +{ "stx", X(31,151), X_MASK, PWRCOM, { RS, RA, RB } }, + +{ "slq", XRC(31,152,0), X_MASK, M601, { RA, RS, RB } }, +{ "slq.", XRC(31,152,1), X_MASK, M601, { RA, RS, RB } }, + +{ "sle", XRC(31,153,0), X_MASK, M601, { RA, RS, RB } }, +{ "sle.", XRC(31,153,1), X_MASK, M601, { RA, RS, RB } }, + +{ "stdux", X(31,181), X_MASK, PPC64, { RS, RAS, RB } }, + +{ "stwux", X(31,183), X_MASK, PPCCOM, { RS, RAS, RB } }, +{ "stux", X(31,183), X_MASK, PWRCOM, { RS, RA, RB } }, + +{ "sliq", XRC(31,184,0), X_MASK, M601, { RA, RS, SH } }, +{ "sliq.", XRC(31,184,1), X_MASK, M601, { RA, RS, SH } }, + +{ "subfze", XO(31,200,0,0), XORB_MASK, PPCCOM, { RT, RA } }, +{ "sfze", XO(31,200,0,0), XORB_MASK, PWRCOM, { RT, RA } }, +{ "subfze.", XO(31,200,0,1), XORB_MASK, PPCCOM, { RT, RA } }, +{ "sfze.", XO(31,200,0,1), XORB_MASK, PWRCOM, { RT, RA } }, +{ "subfzeo", XO(31,200,1,0), XORB_MASK, PPCCOM, { RT, RA } }, +{ "sfzeo", XO(31,200,1,0), XORB_MASK, PWRCOM, { RT, RA } }, +{ "subfzeo.",XO(31,200,1,1), XORB_MASK, PPCCOM, { RT, RA } }, +{ "sfzeo.", XO(31,200,1,1), XORB_MASK, PWRCOM, { RT, RA } }, + +{ "addze", XO(31,202,0,0), XORB_MASK, PPCCOM, { RT, RA } }, +{ "aze", XO(31,202,0,0), XORB_MASK, PWRCOM, { RT, RA } }, +{ "addze.", XO(31,202,0,1), XORB_MASK, PPCCOM, { RT, RA } }, +{ "aze.", XO(31,202,0,1), XORB_MASK, PWRCOM, { RT, RA } }, +{ "addzeo", XO(31,202,1,0), XORB_MASK, PPCCOM, { RT, RA } }, +{ "azeo", XO(31,202,1,0), XORB_MASK, PWRCOM, { RT, RA } }, +{ "addzeo.", XO(31,202,1,1), XORB_MASK, PPCCOM, { RT, RA } }, +{ "azeo.", XO(31,202,1,1), XORB_MASK, PWRCOM, { RT, RA } }, + +{ "mtsr", X(31,210), XRB_MASK|(1<<20), COM32, { SR, RS } }, + +{ "stdcx.", XRC(31,214,1), X_MASK, PPC64, { RS, RA, RB } }, + +{ "stbx", X(31,215), X_MASK, COM, { RS, RA, RB } }, + +{ "sllq", XRC(31,216,0), X_MASK, M601, { RA, RS, RB } }, +{ "sllq.", XRC(31,216,1), X_MASK, M601, { RA, RS, RB } }, + +{ "sleq", XRC(31,217,0), X_MASK, M601, { RA, RS, RB } }, +{ "sleq.", XRC(31,217,1), X_MASK, M601, { RA, RS, RB } }, + +{ "subfme", XO(31,232,0,0), XORB_MASK, PPCCOM, { RT, RA } }, +{ "sfme", XO(31,232,0,0), XORB_MASK, PWRCOM, { RT, RA } }, +{ "subfme.", XO(31,232,0,1), XORB_MASK, PPCCOM, { RT, RA } }, +{ "sfme.", XO(31,232,0,1), XORB_MASK, PWRCOM, { RT, RA } }, +{ "subfmeo", XO(31,232,1,0), XORB_MASK, PPCCOM, { RT, RA } }, +{ "sfmeo", XO(31,232,1,0), XORB_MASK, PWRCOM, { RT, RA } }, +{ "subfmeo.",XO(31,232,1,1), XORB_MASK, PPCCOM, { RT, RA } }, +{ "sfmeo.", XO(31,232,1,1), XORB_MASK, PWRCOM, { RT, RA } }, + +{ "mulld", XO(31,233,0,0), XO_MASK, PPC64, { RT, RA, RB } }, +{ "mulld.", XO(31,233,0,1), XO_MASK, PPC64, { RT, RA, RB } }, +{ "mulldo", XO(31,233,1,0), XO_MASK, PPC64, { RT, RA, RB } }, +{ "mulldo.", XO(31,233,1,1), XO_MASK, PPC64, { RT, RA, RB } }, + +{ "addme", XO(31,234,0,0), XORB_MASK, PPCCOM, { RT, RA } }, +{ "ame", XO(31,234,0,0), XORB_MASK, PWRCOM, { RT, RA } }, +{ "addme.", XO(31,234,0,1), XORB_MASK, PPCCOM, { RT, RA } }, +{ "ame.", XO(31,234,0,1), XORB_MASK, PWRCOM, { RT, RA } }, +{ "addmeo", XO(31,234,1,0), XORB_MASK, PPCCOM, { RT, RA } }, +{ "ameo", XO(31,234,1,0), XORB_MASK, PWRCOM, { RT, RA } }, +{ "addmeo.", XO(31,234,1,1), XORB_MASK, PPCCOM, { RT, RA } }, +{ "ameo.", XO(31,234,1,1), XORB_MASK, PWRCOM, { RT, RA } }, + +{ "mullw", XO(31,235,0,0), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "muls", XO(31,235,0,0), XO_MASK, PWRCOM, { RT, RA, RB } }, +{ "mullw.", XO(31,235,0,1), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "muls.", XO(31,235,0,1), XO_MASK, PWRCOM, { RT, RA, RB } }, +{ "mullwo", XO(31,235,1,0), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "mulso", XO(31,235,1,0), XO_MASK, PWRCOM, { RT, RA, RB } }, +{ "mullwo.", XO(31,235,1,1), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "mulso.", XO(31,235,1,1), XO_MASK, PWRCOM, { RT, RA, RB } }, + +{ "mtsrin", X(31,242), XRA_MASK, PPC32, { RS, RB } }, +{ "mtsri", X(31,242), XRA_MASK, POWER32, { RS, RB } }, + +{ "dcbtst", X(31,246), XRT_MASK, PPC, { RA, RB } }, + +{ "stbux", X(31,247), X_MASK, COM, { RS, RAS, RB } }, + +{ "slliq", XRC(31,248,0), X_MASK, M601, { RA, RS, SH } }, +{ "slliq.", XRC(31,248,1), X_MASK, M601, { RA, RS, SH } }, + +{ "doz", XO(31,264,0,0), XO_MASK, M601, { RT, RA, RB } }, +{ "doz.", XO(31,264,0,1), XO_MASK, M601, { RT, RA, RB } }, +{ "dozo", XO(31,264,1,0), XO_MASK, M601, { RT, RA, RB } }, +{ "dozo.", XO(31,264,1,1), XO_MASK, M601, { RT, RA, RB } }, + +{ "add", XO(31,266,0,0), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "cax", XO(31,266,0,0), XO_MASK, PWRCOM, { RT, RA, RB } }, +{ "add.", XO(31,266,0,1), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "cax.", XO(31,266,0,1), XO_MASK, PWRCOM, { RT, RA, RB } }, +{ "addo", XO(31,266,1,0), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "caxo", XO(31,266,1,0), XO_MASK, PWRCOM, { RT, RA, RB } }, +{ "addo.", XO(31,266,1,1), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "caxo.", XO(31,266,1,1), XO_MASK, PWRCOM, { RT, RA, RB } }, + +{ "lscbx", XRC(31,277,0), X_MASK, M601, { RT, RA, RB } }, +{ "lscbx.", XRC(31,277,1), X_MASK, M601, { RT, RA, RB } }, + +{ "dcbt", X(31,278), XRT_MASK, PPC, { RA, RB } }, + +{ "lhzx", X(31,279), X_MASK, COM, { RT, RA, RB } }, + +{ "icbt", X(31,262), XRT_MASK, PPC, { RA, RB } }, + +{ "eqv", XRC(31,284,0), X_MASK, COM, { RA, RS, RB } }, +{ "eqv.", XRC(31,284,1), X_MASK, COM, { RA, RS, RB } }, + +{ "tlbie", X(31,306), XRTRA_MASK, PPC, { RB } }, +{ "tlbi", X(31,306), XRT_MASK, POWER, { RA, RB } }, + +{ "eciwx", X(31,310), X_MASK, PPC, { RT, RA, RB } }, + +{ "lhzux", X(31,311), X_MASK, COM, { RT, RAL, RB } }, + +{ "xor", XRC(31,316,0), X_MASK, COM, { RA, RS, RB } }, +{ "xor.", XRC(31,316,1), X_MASK, COM, { RA, RS, RB } }, + +{ "mfdcr", X(31,323), X_MASK, PPC, { RT, SPR } }, + +{ "div", XO(31,331,0,0), XO_MASK, M601, { RT, RA, RB } }, +{ "div.", XO(31,331,0,1), XO_MASK, M601, { RT, RA, RB } }, +{ "divo", XO(31,331,1,0), XO_MASK, M601, { RT, RA, RB } }, +{ "divo.", XO(31,331,1,1), XO_MASK, M601, { RT, RA, RB } }, + +{ "mfmq", XSPR(31,339,0), XSPR_MASK, M601, { RT } }, +{ "mfxer", XSPR(31,339,1), XSPR_MASK, COM, { RT } }, +{ "mfrtcu", XSPR(31,339,4), XSPR_MASK, COM, { RT } }, +{ "mfrtcl", XSPR(31,339,5), XSPR_MASK, COM, { RT } }, +{ "mfdec", XSPR(31,339,6), XSPR_MASK, MFDEC1, { RT } }, +{ "mflr", XSPR(31,339,8), XSPR_MASK, COM, { RT } }, +{ "mfctr", XSPR(31,339,9), XSPR_MASK, COM, { RT } }, +{ "mftid", XSPR(31,339,17), XSPR_MASK, POWER, { RT } }, +{ "mfdsisr", XSPR(31,339,18), XSPR_MASK, COM, { RT } }, +{ "mfdar", XSPR(31,339,19), XSPR_MASK, COM, { RT } }, +{ "mfdec", XSPR(31,339,22), XSPR_MASK, MFDEC2, { RT } }, +{ "mfsdr0", XSPR(31,339,24), XSPR_MASK, POWER, { RT } }, +{ "mfsdr1", XSPR(31,339,25), XSPR_MASK, COM, { RT } }, +{ "mfsrr0", XSPR(31,339,26), XSPR_MASK, COM, { RT } }, +{ "mfsrr1", XSPR(31,339,27), XSPR_MASK, COM, { RT } }, +{ "mfsprg", XSPR(31,339,272), XSPRG_MASK, PPC, { RT, SPRG } }, +{ "mfasr", XSPR(31,339,280), XSPR_MASK, PPC64, { RT } }, +{ "mfear", XSPR(31,339,282), XSPR_MASK, PPC, { RT } }, +{ "mfpvr", XSPR(31,339,287), XSPR_MASK, PPC, { RT } }, +{ "mfibatu", XSPR(31,339,528), XSPRBAT_MASK, PPC, { RT, SPRBAT } }, +{ "mfibatl", XSPR(31,339,529), XSPRBAT_MASK, PPC, { RT, SPRBAT } }, +{ "mfdbatu", XSPR(31,339,536), XSPRBAT_MASK, PPC, { RT, SPRBAT } }, +{ "mfdbatl", XSPR(31,339,537), XSPRBAT_MASK, PPC, { RT, SPRBAT } }, +{ "mfspr", X(31,339), X_MASK, COM, { RT, SPR } }, + +{ "lwax", X(31,341), X_MASK, PPC64, { RT, RA, RB } }, + +{ "lhax", X(31,343), X_MASK, COM, { RT, RA, RB } }, + +{ "dccci", X(31,454), XRT_MASK, PPC, { RA, RB } }, + +{ "abs", XO(31,360,0,0), XORB_MASK, M601, { RT, RA } }, +{ "abs.", XO(31,360,0,1), XORB_MASK, M601, { RT, RA } }, +{ "abso", XO(31,360,1,0), XORB_MASK, M601, { RT, RA } }, +{ "abso.", XO(31,360,1,1), XORB_MASK, M601, { RT, RA } }, + +{ "divs", XO(31,363,0,0), XO_MASK, M601, { RT, RA, RB } }, +{ "divs.", XO(31,363,0,1), XO_MASK, M601, { RT, RA, RB } }, +{ "divso", XO(31,363,1,0), XO_MASK, M601, { RT, RA, RB } }, +{ "divso.", XO(31,363,1,1), XO_MASK, M601, { RT, RA, RB } }, + +{ "tlbia", X(31,370), 0xffffffff, PPC, { 0 } }, + +{ "mftbu", XSPR(31,371,269), XSPR_MASK, PPC, { RT } }, +{ "mftb", X(31,371), X_MASK, PPC, { RT, TBR } }, + +{ "lwaux", X(31,373), X_MASK, PPC64, { RT, RAL, RB } }, + +{ "lhaux", X(31,375), X_MASK, COM, { RT, RAL, RB } }, + +{ "sthx", X(31,407), X_MASK, COM, { RS, RA, RB } }, + +{ "lfqx", X(31,791), X_MASK, POWER2, { FRT, RA, RB } }, + +{ "lfqux", X(31,823), X_MASK, POWER2, { FRT, RA, RB } }, + +{ "stfqx", X(31,919), X_MASK, POWER2, { FRS, RA, RB } }, + +{ "stfqux", X(31,951), X_MASK, POWER2, { FRS, RA, RB } }, + +{ "orc", XRC(31,412,0), X_MASK, COM, { RA, RS, RB } }, +{ "orc.", XRC(31,412,1), X_MASK, COM, { RA, RS, RB } }, + +{ "sradi", XS(31,413,0), XS_MASK, PPC64, { RA, RS, SH6 } }, +{ "sradi.", XS(31,413,1), XS_MASK, PPC64, { RA, RS, SH6 } }, + +{ "slbie", X(31,434), XRTRA_MASK, PPC64, { RB } }, + +{ "ecowx", X(31,438), X_MASK, PPC, { RT, RA, RB } }, + +{ "sthux", X(31,439), X_MASK, COM, { RS, RAS, RB } }, + +{ "mr", XRC(31,444,0), X_MASK, COM, { RA, RS, RBS } }, +{ "or", XRC(31,444,0), X_MASK, COM, { RA, RS, RB } }, +{ "mr.", XRC(31,444,1), X_MASK, COM, { RA, RS, RBS } }, +{ "or.", XRC(31,444,1), X_MASK, COM, { RA, RS, RB } }, + +{ "mtdcr", X(31,451), X_MASK, PPC, { SPR, RS } }, + +{ "divdu", XO(31,457,0,0), XO_MASK, PPC64, { RT, RA, RB } }, +{ "divdu.", XO(31,457,0,1), XO_MASK, PPC64, { RT, RA, RB } }, +{ "divduo", XO(31,457,1,0), XO_MASK, PPC64, { RT, RA, RB } }, +{ "divduo.", XO(31,457,1,1), XO_MASK, PPC64, { RT, RA, RB } }, + +{ "divwu", XO(31,459,0,0), XO_MASK, PPC, { RT, RA, RB } }, +{ "divwu.", XO(31,459,0,1), XO_MASK, PPC, { RT, RA, RB } }, +{ "divwuo", XO(31,459,1,0), XO_MASK, PPC, { RT, RA, RB } }, +{ "divwuo.", XO(31,459,1,1), XO_MASK, PPC, { RT, RA, RB } }, + +{ "mtmq", XSPR(31,467,0), XSPR_MASK, M601, { RS } }, +{ "mtxer", XSPR(31,467,1), XSPR_MASK, COM, { RS } }, +{ "mtlr", XSPR(31,467,8), XSPR_MASK, COM, { RS } }, +{ "mtctr", XSPR(31,467,9), XSPR_MASK, COM, { RS } }, +{ "mttid", XSPR(31,467,17), XSPR_MASK, POWER, { RS } }, +{ "mtdsisr", XSPR(31,467,18), XSPR_MASK, COM, { RS } }, +{ "mtdar", XSPR(31,467,19), XSPR_MASK, COM, { RS } }, +{ "mtrtcu", XSPR(31,467,20), XSPR_MASK, COM, { RS } }, +{ "mtrtcl", XSPR(31,467,21), XSPR_MASK, COM, { RS } }, +{ "mtdec", XSPR(31,467,22), XSPR_MASK, COM, { RS } }, +{ "mtsdr0", XSPR(31,467,24), XSPR_MASK, POWER, { RS } }, +{ "mtsdr1", XSPR(31,467,25), XSPR_MASK, COM, { RS } }, +{ "mtsrr0", XSPR(31,467,26), XSPR_MASK, COM, { RS } }, +{ "mtsrr1", XSPR(31,467,27), XSPR_MASK, COM, { RS } }, +{ "mtsprg", XSPR(31,467,272), XSPRG_MASK, PPC, { SPRG, RS } }, +{ "mtasr", XSPR(31,467,280), XSPR_MASK, PPC64, { RS } }, +{ "mtear", XSPR(31,467,282), XSPR_MASK, PPC, { RS } }, +{ "mttbl", XSPR(31,467,284), XSPR_MASK, PPC, { RS } }, +{ "mttbu", XSPR(31,467,285), XSPR_MASK, PPC, { RS } }, +{ "mtibatu", XSPR(31,467,528), XSPRBAT_MASK, PPC, { SPRBAT, RS } }, +{ "mtibatl", XSPR(31,467,529), XSPRBAT_MASK, PPC, { SPRBAT, RS } }, +{ "mtdbatu", XSPR(31,467,536), XSPRBAT_MASK, PPC, { SPRBAT, RS } }, +{ "mtdbatl", XSPR(31,467,537), XSPRBAT_MASK, PPC, { SPRBAT, RS } }, +{ "mtspr", X(31,467), X_MASK, COM, { SPR, RS } }, + +{ "dcbi", X(31,470), XRT_MASK, PPC, { RA, RB } }, + +{ "nand", XRC(31,476,0), X_MASK, COM, { RA, RS, RB } }, +{ "nand.", XRC(31,476,1), X_MASK, COM, { RA, RS, RB } }, + +{ "nabs", XO(31,488,0,0), XORB_MASK, M601, { RT, RA } }, +{ "nabs.", XO(31,488,0,1), XORB_MASK, M601, { RT, RA } }, +{ "nabso", XO(31,488,1,0), XORB_MASK, M601, { RT, RA } }, +{ "nabso.", XO(31,488,1,1), XORB_MASK, M601, { RT, RA } }, + +{ "divd", XO(31,489,0,0), XO_MASK, PPC64, { RT, RA, RB } }, +{ "divd.", XO(31,489,0,1), XO_MASK, PPC64, { RT, RA, RB } }, +{ "divdo", XO(31,489,1,0), XO_MASK, PPC64, { RT, RA, RB } }, +{ "divdo.", XO(31,489,1,1), XO_MASK, PPC64, { RT, RA, RB } }, + +{ "divw", XO(31,491,0,0), XO_MASK, PPC, { RT, RA, RB } }, +{ "divw.", XO(31,491,0,1), XO_MASK, PPC, { RT, RA, RB } }, +{ "divwo", XO(31,491,1,0), XO_MASK, PPC, { RT, RA, RB } }, +{ "divwo.", XO(31,491,1,1), XO_MASK, PPC, { RT, RA, RB } }, + +{ "slbia", X(31,498), 0xffffffff, PPC64, { 0 } }, + +{ "cli", X(31,502), XRB_MASK, POWER, { RT, RA } }, + +{ "mcrxr", X(31,512), XRARB_MASK|(3<<21), COM, { BF } }, + +{ "clcs", X(31,531), XRB_MASK, M601, { RT, RA } }, + +{ "lswx", X(31,533), X_MASK, PPCCOM, { RT, RA, RB } }, +{ "lsx", X(31,533), X_MASK, PWRCOM, { RT, RA, RB } }, + +{ "lwbrx", X(31,534), X_MASK, PPCCOM, { RT, RA, RB } }, +{ "lbrx", X(31,534), X_MASK, PWRCOM, { RT, RA, RB } }, + +{ "lfsx", X(31,535), X_MASK, COM, { FRT, RA, RB } }, + +{ "srw", XRC(31,536,0), X_MASK, PPCCOM, { RA, RS, RB } }, +{ "sr", XRC(31,536,0), X_MASK, PWRCOM, { RA, RS, RB } }, +{ "srw.", XRC(31,536,1), X_MASK, PPCCOM, { RA, RS, RB } }, +{ "sr.", XRC(31,536,1), X_MASK, PWRCOM, { RA, RS, RB } }, + +{ "rrib", XRC(31,537,0), X_MASK, M601, { RA, RS, RB } }, +{ "rrib.", XRC(31,537,1), X_MASK, M601, { RA, RS, RB } }, + +{ "srd", XRC(31,539,0), X_MASK, PPC64, { RA, RS, RB } }, +{ "srd.", XRC(31,539,1), X_MASK, PPC64, { RA, RS, RB } }, + +{ "maskir", XRC(31,541,0), X_MASK, M601, { RA, RS, RB } }, +{ "maskir.", XRC(31,541,1), X_MASK, M601, { RA, RS, RB } }, + +{ "tlbsync", X(31,566), 0xffffffff, PPC, { 0 } }, + +{ "lfsux", X(31,567), X_MASK, COM, { FRT, RAS, RB } }, + +{ "mfsr", X(31,595), XRB_MASK|(1<<20), COM32, { RT, SR } }, + +{ "lswi", X(31,597), X_MASK, PPCCOM, { RT, RA, NB } }, +{ "lsi", X(31,597), X_MASK, PWRCOM, { RT, RA, NB } }, + +{ "sync", X(31,598), 0xffffffff, PPCCOM, { 0 } }, +{ "dcs", X(31,598), 0xffffffff, PWRCOM, { 0 } }, + +{ "lfdx", X(31,599), X_MASK, COM, { FRT, RA, RB } }, + +{ "mfsri", X(31,627), X_MASK, PWRCOM, { RT, RA, RB } }, + +{ "dclst", X(31,630), XRB_MASK, PWRCOM, { RS, RA } }, + +{ "lfdux", X(31,631), X_MASK, COM, { FRT, RAS, RB } }, + +{ "mfsrin", X(31,659), XRA_MASK, PPC32, { RT, RB } }, + +{ "stswx", X(31,661), X_MASK, PPCCOM, { RS, RA, RB } }, +{ "stsx", X(31,661), X_MASK, PWRCOM, { RS, RA, RB } }, + +{ "stwbrx", X(31,662), X_MASK, PPCCOM, { RS, RA, RB } }, +{ "stbrx", X(31,662), X_MASK, PWRCOM, { RS, RA, RB } }, + +{ "stfsx", X(31,663), X_MASK, COM, { FRS, RA, RB } }, + +{ "srq", XRC(31,664,0), X_MASK, M601, { RA, RS, RB } }, +{ "srq.", XRC(31,664,1), X_MASK, M601, { RA, RS, RB } }, + +{ "sre", XRC(31,665,0), X_MASK, M601, { RA, RS, RB } }, +{ "sre.", XRC(31,665,1), X_MASK, M601, { RA, RS, RB } }, + +{ "stfsux", X(31,695), X_MASK, COM, { FRS, RAS, RB } }, + +{ "sriq", XRC(31,696,0), X_MASK, M601, { RA, RS, SH } }, +{ "sriq.", XRC(31,696,1), X_MASK, M601, { RA, RS, SH } }, + +{ "stswi", X(31,725), X_MASK, PPCCOM, { RS, RA, NB } }, +{ "stsi", X(31,725), X_MASK, PWRCOM, { RS, RA, NB } }, + +{ "stfdx", X(31,727), X_MASK, COM, { FRS, RA, RB } }, + +{ "srlq", XRC(31,728,0), X_MASK, M601, { RA, RS, RB } }, +{ "srlq.", XRC(31,728,1), X_MASK, M601, { RA, RS, RB } }, + +{ "sreq", XRC(31,729,0), X_MASK, M601, { RA, RS, RB } }, +{ "sreq.", XRC(31,729,1), X_MASK, M601, { RA, RS, RB } }, + +{ "stfdux", X(31,759), X_MASK, COM, { FRS, RAS, RB } }, + +{ "srliq", XRC(31,760,0), X_MASK, M601, { RA, RS, SH } }, +{ "srliq.", XRC(31,760,1), X_MASK, M601, { RA, RS, SH } }, + +{ "lhbrx", X(31,790), X_MASK, COM, { RT, RA, RB } }, + +{ "sraw", XRC(31,792,0), X_MASK, PPCCOM, { RA, RS, RB } }, +{ "sra", XRC(31,792,0), X_MASK, PWRCOM, { RA, RS, RB } }, +{ "sraw.", XRC(31,792,1), X_MASK, PPCCOM, { RA, RS, RB } }, +{ "sra.", XRC(31,792,1), X_MASK, PWRCOM, { RA, RS, RB } }, + +{ "srad", XRC(31,794,0), X_MASK, PPC64, { RA, RS, RB } }, +{ "srad.", XRC(31,794,1), X_MASK, PPC64, { RA, RS, RB } }, + +{ "rac", X(31,818), X_MASK, PWRCOM, { RT, RA, RB } }, + +{ "srawi", XRC(31,824,0), X_MASK, PPCCOM, { RA, RS, SH } }, +{ "srai", XRC(31,824,0), X_MASK, PWRCOM, { RA, RS, SH } }, +{ "srawi.", XRC(31,824,1), X_MASK, PPCCOM, { RA, RS, SH } }, +{ "srai.", XRC(31,824,1), X_MASK, PWRCOM, { RA, RS, SH } }, + +{ "eieio", X(31,854), 0xffffffff, PPC, { 0 } }, + +{ "sthbrx", X(31,918), X_MASK, COM, { RS, RA, RB } }, + +{ "sraq", XRC(31,920,0), X_MASK, M601, { RA, RS, RB } }, +{ "sraq.", XRC(31,920,1), X_MASK, M601, { RA, RS, RB } }, + +{ "srea", XRC(31,921,0), X_MASK, M601, { RA, RS, RB } }, +{ "srea.", XRC(31,921,1), X_MASK, M601, { RA, RS, RB } }, + +{ "extsh", XRC(31,922,0), XRB_MASK, PPCCOM, { RA, RS } }, +{ "exts", XRC(31,922,0), XRB_MASK, PWRCOM, { RA, RS } }, +{ "extsh.", XRC(31,922,1), XRB_MASK, PPCCOM, { RA, RS } }, +{ "exts.", XRC(31,922,1), XRB_MASK, PWRCOM, { RA, RS } }, + +{ "sraiq", XRC(31,952,0), X_MASK, M601, { RA, RS, SH } }, +{ "sraiq.", XRC(31,952,1), X_MASK, M601, { RA, RS, SH } }, + +{ "extsb", XRC(31,954,0), XRB_MASK, PPC, { RA, RS} }, +{ "extsb.", XRC(31,954,1), XRB_MASK, PPC, { RA, RS} }, + +{ "iccci", X(31,966), XRT_MASK, PPC, { RA, RB } }, + +{ "tlbld", X(31,978), XRTRA_MASK, PPC, { RB } }, + +{ "icbi", X(31,982), XRT_MASK, PPC, { RA, RB } }, + +{ "stfiwx", X(31,983), X_MASK, PPC, { FRS, RA, RB } }, + +{ "extsw", XRC(31,986,0), XRB_MASK, PPC, { RA, RS } }, +{ "extsw.", XRC(31,986,1), XRB_MASK, PPC, { RA, RS } }, + +{ "tlbli", X(31,1010), XRTRA_MASK, PPC, { RB } }, + +{ "dcbz", X(31,1014), XRT_MASK, PPC, { RA, RB } }, +{ "dclz", X(31,1014), XRT_MASK, PPC, { RA, RB } }, + +{ "lwz", OP(32), OP_MASK, PPCCOM, { RT, D, RA } }, +{ "l", OP(32), OP_MASK, PWRCOM, { RT, D, RA } }, + +{ "lwzu", OP(33), OP_MASK, PPCCOM, { RT, D, RAL } }, +{ "lu", OP(33), OP_MASK, PWRCOM, { RT, D, RA } }, + +{ "lbz", OP(34), OP_MASK, COM, { RT, D, RA } }, + +{ "lbzu", OP(35), OP_MASK, COM, { RT, D, RAL } }, + +{ "stw", OP(36), OP_MASK, PPCCOM, { RS, D, RA } }, +{ "st", OP(36), OP_MASK, PWRCOM, { RS, D, RA } }, + +{ "stwu", OP(37), OP_MASK, PPCCOM, { RS, D, RAS } }, +{ "stu", OP(37), OP_MASK, PWRCOM, { RS, D, RA } }, + +{ "stb", OP(38), OP_MASK, COM, { RS, D, RA } }, + +{ "stbu", OP(39), OP_MASK, COM, { RS, D, RAS } }, + +{ "lhz", OP(40), OP_MASK, COM, { RT, D, RA } }, + +{ "lhzu", OP(41), OP_MASK, COM, { RT, D, RAL } }, + +{ "lha", OP(42), OP_MASK, COM, { RT, D, RA } }, + +{ "lhau", OP(43), OP_MASK, COM, { RT, D, RAL } }, + +{ "sth", OP(44), OP_MASK, COM, { RS, D, RA } }, + +{ "sthu", OP(45), OP_MASK, COM, { RS, D, RAS } }, + +{ "lmw", OP(46), OP_MASK, PPCCOM, { RT, D, RAM } }, +{ "lm", OP(46), OP_MASK, PWRCOM, { RT, D, RA } }, + +{ "stmw", OP(47), OP_MASK, PPCCOM, { RS, D, RA } }, +{ "stm", OP(47), OP_MASK, PWRCOM, { RS, D, RA } }, + +{ "lfs", OP(48), OP_MASK, COM, { FRT, D, RA } }, + +{ "lfsu", OP(49), OP_MASK, COM, { FRT, D, RAS } }, + +{ "lfd", OP(50), OP_MASK, COM, { FRT, D, RA } }, + +{ "lfdu", OP(51), OP_MASK, COM, { FRT, D, RAS } }, + +{ "stfs", OP(52), OP_MASK, COM, { FRS, D, RA } }, + +{ "stfsu", OP(53), OP_MASK, COM, { FRS, D, RAS } }, + +{ "stfd", OP(54), OP_MASK, COM, { FRS, D, RA } }, + +{ "stfdu", OP(55), OP_MASK, COM, { FRS, D, RAS } }, + +{ "lfq", OP(56), OP_MASK, POWER2, { FRT, D, RA } }, + +{ "lfqu", OP(57), OP_MASK, POWER2, { FRT, D, RA } }, + +{ "ld", DSO(58,0), DS_MASK, PPC64, { RT, DS, RA } }, + +{ "ldu", DSO(58,1), DS_MASK, PPC64, { RT, DS, RAL } }, + +{ "lwa", DSO(58,2), DS_MASK, PPC64, { RT, DS, RA } }, + +{ "fdivs", A(59,18,0), AFRC_MASK, PPC, { FRT, FRA, FRB } }, +{ "fdivs.", A(59,18,1), AFRC_MASK, PPC, { FRT, FRA, FRB } }, + +{ "fsubs", A(59,20,0), AFRC_MASK, PPC, { FRT, FRA, FRB } }, +{ "fsubs.", A(59,20,1), AFRC_MASK, PPC, { FRT, FRA, FRB } }, + +{ "fadds", A(59,21,0), AFRC_MASK, PPC, { FRT, FRA, FRB } }, +{ "fadds.", A(59,21,1), AFRC_MASK, PPC, { FRT, FRA, FRB } }, + +{ "fsqrts", A(59,22,0), AFRAFRC_MASK, PPC, { FRT, FRB } }, +{ "fsqrts.", A(59,22,1), AFRAFRC_MASK, PPC, { FRT, FRB } }, + +{ "fres", A(59,24,0), AFRAFRC_MASK, PPC, { FRT, FRB } }, +{ "fres.", A(59,24,1), AFRAFRC_MASK, PPC, { FRT, FRB } }, + +{ "fmuls", A(59,25,0), AFRB_MASK, PPC, { FRT, FRA, FRC } }, +{ "fmuls.", A(59,25,1), AFRB_MASK, PPC, { FRT, FRA, FRC } }, + +{ "fmsubs", A(59,28,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, +{ "fmsubs.", A(59,28,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, + +{ "fmadds", A(59,29,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, +{ "fmadds.", A(59,29,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, + +{ "fnmsubs", A(59,30,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, +{ "fnmsubs.",A(59,30,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, + +{ "fnmadds", A(59,31,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, +{ "fnmadds.",A(59,31,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, + +{ "stfq", OP(60), OP_MASK, POWER2, { FRS, D, RA } }, + +{ "stfqu", OP(61), OP_MASK, POWER2, { FRS, D, RA } }, + +{ "std", DSO(62,0), DS_MASK, PPC64, { RS, DS, RA } }, + +{ "stdu", DSO(62,1), DS_MASK, PPC64, { RS, DS, RAS } }, + +{ "fcmpu", X(63,0), X_MASK|(3<<21), COM, { BF, FRA, FRB } }, + +{ "frsp", XRC(63,12,0), XRA_MASK, COM, { FRT, FRB } }, +{ "frsp.", XRC(63,12,1), XRA_MASK, COM, { FRT, FRB } }, + +{ "fctiw", XRC(63,14,0), XRA_MASK, PPCCOM, { FRT, FRB } }, +{ "fcir", XRC(63,14,0), XRA_MASK, POWER2, { FRT, FRB } }, +{ "fctiw.", XRC(63,14,1), XRA_MASK, PPCCOM, { FRT, FRB } }, +{ "fcir.", XRC(63,14,1), XRA_MASK, POWER2, { FRT, FRB } }, + +{ "fctiwz", XRC(63,15,0), XRA_MASK, PPCCOM, { FRT, FRB } }, +{ "fcirz", XRC(63,15,0), XRA_MASK, POWER2, { FRT, FRB } }, +{ "fctiwz.", XRC(63,15,1), XRA_MASK, PPCCOM, { FRT, FRB } }, +{ "fcirz.", XRC(63,15,1), XRA_MASK, POWER2, { FRT, FRB } }, + +{ "fdiv", A(63,18,0), AFRC_MASK, PPCCOM, { FRT, FRA, FRB } }, +{ "fd", A(63,18,0), AFRC_MASK, PWRCOM, { FRT, FRA, FRB } }, +{ "fdiv.", A(63,18,1), AFRC_MASK, PPCCOM, { FRT, FRA, FRB } }, +{ "fd.", A(63,18,1), AFRC_MASK, PWRCOM, { FRT, FRA, FRB } }, + +{ "fsub", A(63,20,0), AFRC_MASK, PPCCOM, { FRT, FRA, FRB } }, +{ "fs", A(63,20,0), AFRC_MASK, PWRCOM, { FRT, FRA, FRB } }, +{ "fsub.", A(63,20,1), AFRC_MASK, PPCCOM, { FRT, FRA, FRB } }, +{ "fs.", A(63,20,1), AFRC_MASK, PWRCOM, { FRT, FRA, FRB } }, + +{ "fadd", A(63,21,0), AFRC_MASK, PPCCOM, { FRT, FRA, FRB } }, +{ "fa", A(63,21,0), AFRC_MASK, PWRCOM, { FRT, FRA, FRB } }, +{ "fadd.", A(63,21,1), AFRC_MASK, PPCCOM, { FRT, FRA, FRB } }, +{ "fa.", A(63,21,1), AFRC_MASK, PWRCOM, { FRT, FRA, FRB } }, + +{ "fsqrt", A(63,22,0), AFRAFRC_MASK, POWER2, { FRT, FRB } }, +{ "fsqrt.", A(63,22,1), AFRAFRC_MASK, POWER2, { FRT, FRB } }, +{ "fsqrt", A(63,22,0), AFRAFRC_MASK, PPC, { FRT, FRB } }, +{ "fsqrt.", A(63,22,1), AFRAFRC_MASK, PPC, { FRT, FRB } }, + +{ "fsel", A(63,23,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, +{ "fsel.", A(63,23,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, + +{ "fmul", A(63,25,0), AFRB_MASK, PPCCOM, { FRT, FRA, FRC } }, +{ "fm", A(63,25,0), AFRB_MASK, PWRCOM, { FRT, FRA, FRC } }, +{ "fmul.", A(63,25,1), AFRB_MASK, PPCCOM, { FRT, FRA, FRC } }, +{ "fm.", A(63,25,1), AFRB_MASK, PWRCOM, { FRT, FRA, FRC } }, + +{ "frsqrte", A(63,26,0), AFRAFRC_MASK, PPC, { FRT, FRB } }, +{ "frsqrte.",A(63,26,1), AFRAFRC_MASK, PPC, { FRT, FRB } }, + +{ "fmsub", A(63,28,0), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } }, +{ "fms", A(63,28,0), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } }, +{ "fmsub.", A(63,28,1), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } }, +{ "fms.", A(63,28,1), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } }, + +{ "fmadd", A(63,29,0), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } }, +{ "fma", A(63,29,0), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } }, +{ "fmadd.", A(63,29,1), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } }, +{ "fma.", A(63,29,1), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } }, + +{ "fnmsub", A(63,30,0), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } }, +{ "fnms", A(63,30,0), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } }, +{ "fnmsub.", A(63,30,1), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } }, +{ "fnms.", A(63,30,1), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } }, + +{ "fnmadd", A(63,31,0), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } }, +{ "fnma", A(63,31,0), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } }, +{ "fnmadd.", A(63,31,1), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } }, +{ "fnma.", A(63,31,1), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } }, + +{ "fcmpo", X(63,30), X_MASK|(3<<21), COM, { BF, FRA, FRB } }, + +{ "mtfsb1", XRC(63,38,0), XRARB_MASK, COM, { BT } }, +{ "mtfsb1.", XRC(63,38,1), XRARB_MASK, COM, { BT } }, + +{ "fneg", XRC(63,40,0), XRA_MASK, COM, { FRT, FRB } }, +{ "fneg.", XRC(63,40,1), XRA_MASK, COM, { FRT, FRB } }, + +{ "mcrfs", X(63,64), XRB_MASK|(3<<21)|(3<<16), COM, { BF, BFA } }, + +{ "mtfsb0", XRC(63,70,0), XRARB_MASK, COM, { BT } }, +{ "mtfsb0.", XRC(63,70,1), XRARB_MASK, COM, { BT } }, + +{ "fmr", XRC(63,72,0), XRA_MASK, COM, { FRT, FRB } }, +{ "fmr.", XRC(63,72,1), XRA_MASK, COM, { FRT, FRB } }, + +{ "mtfsfi", XRC(63,134,0), XRA_MASK|(3<<21)|(1<<11), COM, { BF, U } }, +{ "mtfsfi.", XRC(63,134,1), XRA_MASK|(3<<21)|(1<<11), COM, { BF, U } }, + +{ "fnabs", XRC(63,136,0), XRA_MASK, COM, { FRT, FRB } }, +{ "fnabs.", XRC(63,136,1), XRA_MASK, COM, { FRT, FRB } }, + +{ "fabs", XRC(63,264,0), XRA_MASK, COM, { FRT, FRB } }, +{ "fabs.", XRC(63,264,1), XRA_MASK, COM, { FRT, FRB } }, + +{ "mffs", XRC(63,583,0), XRARB_MASK, COM, { FRT } }, +{ "mffs.", XRC(63,583,1), XRARB_MASK, COM, { FRT } }, + +{ "mtfsf", XFL(63,711,0), XFL_MASK, COM, { FLM, FRB } }, +{ "mtfsf.", XFL(63,711,1), XFL_MASK, COM, { FLM, FRB } }, + +{ "fctid", XRC(63,814,0), XRA_MASK, PPC64, { FRT, FRB } }, +{ "fctid.", XRC(63,814,1), XRA_MASK, PPC64, { FRT, FRB } }, + +{ "fctidz", XRC(63,815,0), XRA_MASK, PPC64, { FRT, FRB } }, +{ "fctidz.", XRC(63,815,1), XRA_MASK, PPC64, { FRT, FRB } }, + +{ "fcfid", XRC(63,846,0), XRA_MASK, PPC64, { FRT, FRB } }, +{ "fcfid.", XRC(63,846,1), XRA_MASK, PPC64, { FRT, FRB } }, + +}; + +const int powerpc_num_opcodes = + sizeof (powerpc_opcodes) / sizeof (powerpc_opcodes[0]); + +/* The macro table. This is only used by the assembler. */ + +const struct powerpc_macro powerpc_macros[] = { +{ "extldi", 4, PPC64, "rldicr %0,%1,%3,(%2)-1" }, +{ "extldi.", 4, PPC64, "rldicr. %0,%1,%3,(%2)-1" }, +{ "extrdi", 4, PPC64, "rldicl %0,%1,(%2)+(%3),64-(%2)" }, +{ "extrdi.", 4, PPC64, "rldicl. %0,%1,(%2)+(%3),64-(%2)" }, +{ "insrdi", 4, PPC64, "rldimi %0,%1,64-((%2)+(%3)),%3" }, +{ "insrdi.", 4, PPC64, "rldimi. %0,%1,64-((%2)+(%3)),%3" }, +{ "rotrdi", 3, PPC64, "rldicl %0,%1,64-(%2),0" }, +{ "rotrdi.", 3, PPC64, "rldicl. %0,%1,64-(%2),0" }, +{ "sldi", 3, PPC64, "rldicr %0,%1,%2,63-(%2)" }, +{ "sldi.", 3, PPC64, "rldicr. %0,%1,%2,63-(%2)" }, +{ "srdi", 3, PPC64, "rldicl %0,%1,64-(%2),%2" }, +{ "srdi.", 3, PPC64, "rldicl. %0,%1,64-(%2),%2" }, +{ "clrrdi", 3, PPC64, "rldicr %0,%1,0,63-(%2)" }, +{ "clrrdi.", 3, PPC64, "rldicr. %0,%1,0,63-(%2)" }, +{ "clrlsldi",4, PPC64, "rldic %0,%1,%3,(%2)-(%3)" }, +{ "clrlsldi.",4, PPC64, "rldic. %0,%1,%3,(%2)-(%3)" }, + +{ "extlwi", 4, PPCCOM, "rlwinm %0,%1,%3,0,(%2)-1" }, +{ "extlwi.", 4, PPCCOM, "rlwinm. %0,%1,%3,0,(%2)-1" }, +{ "extrwi", 4, PPCCOM, "rlwinm %0,%1,(%2)+(%3),32-(%2),31" }, +{ "extrwi.", 4, PPCCOM, "rlwinm. %0,%1,(%2)+(%3),32-(%2),31" }, +{ "inslwi", 4, PPCCOM, "rlwimi %0,%1,32-(%3),%3,(%2)+(%3)-1" }, +{ "inslwi.", 4, PPCCOM, "rlwimi. %0,%1,32-(%3),%3,(%2)+(%3)-1" }, +{ "insrwi", 4, PPCCOM, "rlwimi %0,%1,32-((%2)+(%3)),%3,(%2)+(%3)-1" }, +{ "insrwi.", 4, PPCCOM, "rlwimi. %0,%1,32-((%2)+(%3)),%3,(%2)+(%3)-1"}, +{ "rotrwi", 3, PPCCOM, "rlwinm %0,%1,32-(%2),0,31" }, +{ "rotrwi.", 3, PPCCOM, "rlwinm. %0,%1,32-(%2),0,31" }, +{ "slwi", 3, PPCCOM, "rlwinm %0,%1,%2,0,31-(%2)" }, +{ "sli", 3, PWRCOM, "rlinm %0,%1,%2,0,31-(%2)" }, +{ "slwi.", 3, PPCCOM, "rlwinm. %0,%1,%2,0,31-(%2)" }, +{ "sli.", 3, PWRCOM, "rlinm. %0,%1,%2,0,31-(%2)" }, +{ "srwi", 3, PPCCOM, "rlwinm %0,%1,32-(%2),%2,31" }, +{ "sri", 3, PWRCOM, "rlinm %0,%1,32-(%2),%2,31" }, +{ "srwi.", 3, PPCCOM, "rlwinm. %0,%1,32-(%2),%2,31" }, +{ "sri.", 3, PWRCOM, "rlinm. %0,%1,32-(%2),%2,31" }, +{ "clrrwi", 3, PPCCOM, "rlwinm %0,%1,0,0,31-(%2)" }, +{ "clrrwi.", 3, PPCCOM, "rlwinm. %0,%1,0,0,31-(%2)" }, +{ "clrlslwi",4, PPCCOM, "rlwinm %0,%1,%3,(%2)-(%3),31-(%3)" }, +{ "clrlslwi.",4, PPCCOM, "rlwinm. %0,%1,%3,(%2)-(%3),31-(%3)" }, + +}; + +const int powerpc_num_macros = + sizeof (powerpc_macros) / sizeof (powerpc_macros[0]); diff --git a/opcode/ppc.h b/opcode/ppc.h new file mode 100644 index 000000000..a9e3b24ab --- /dev/null +++ b/opcode/ppc.h @@ -0,0 +1,248 @@ +/* ppc.h -- Header file for PowerPC opcode table + Copyright 1994, 1995 Free Software Foundation, Inc. + Written by Ian Lance Taylor, Cygnus Support + +This file is part of GDB, GAS, and the GNU binutils. + +GDB, GAS, and the GNU binutils are free software; you can redistribute +them and/or modify them under the terms of the GNU General Public +License as published by the Free Software Foundation; either version +1, or (at your option) any later version. + +GDB, GAS, and the GNU binutils are distributed in the hope that they +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 file; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef PPC_H +#define PPC_H + +/* The opcode table is an array of struct powerpc_opcode. */ + +struct powerpc_opcode +{ + /* The opcode name. */ + const char *name; + + /* The opcode itself. Those bits which will be filled in with + operands are zeroes. */ + unsigned long opcode; + + /* The opcode mask. This is used by the disassembler. This is a + mask containing ones indicating those bits which must match the + opcode field, and zeroes indicating those bits which need not + match (and are presumably filled in by operands). */ + unsigned long mask; + + /* One bit flags for the opcode. These are used to indicate which + specific processors support the instructions. The defined values + are listed below. */ + unsigned long flags; + + /* An array of operand codes. Each code is an index into the + operand table. They appear in the order which the operands must + appear in assembly code, and are terminated by a zero. */ + unsigned char operands[8]; +}; + +/* The table itself is sorted by major opcode number, and is otherwise + in the order in which the disassembler should consider + instructions. */ +extern const struct powerpc_opcode powerpc_opcodes[]; +extern const int powerpc_num_opcodes; + +/* Values defined for the flags field of a struct powerpc_opcode. */ + +/* Opcode is defined for the PowerPC architecture. */ +#define PPC_OPCODE_PPC (01) + +/* Opcode is defined for the POWER (RS/6000) architecture. */ +#define PPC_OPCODE_POWER (02) + +/* Opcode is defined for the POWER2 (Rios 2) architecture. */ +#define PPC_OPCODE_POWER2 (04) + +/* Opcode is only defined on 32 bit architectures. */ +#define PPC_OPCODE_32 (010) + +/* Opcode is only defined on 64 bit architectures. */ +#define PPC_OPCODE_64 (020) + +/* Opcode is supported by the Motorola PowerPC 601 processor. The 601 + is assumed to support all PowerPC (PPC_OPCODE_PPC) instructions, + but it also supports many additional POWER instructions. */ +#define PPC_OPCODE_601 (040) + +/* Opcode is supported in both the Power and PowerPC architectures + (ie, compiler's -mcpu=common or assembler's -mcom). */ +#define PPC_OPCODE_COMMON (0100) + +/* Opcode is supported for any Power or PowerPC platform (this is + for the assembler's -many option, and it eliminates duplicates). */ +#define PPC_OPCODE_ANY (0200) + +/* A macro to extract the major opcode from an instruction. */ +#define PPC_OP(i) (((i) >> 26) & 0x3f) + +/* The operands table is an array of struct powerpc_operand. */ + +struct powerpc_operand +{ + /* The number of bits in the operand. */ + int bits; + + /* How far the operand is left shifted in the instruction. */ + int shift; + + /* Insertion function. This is used by the assembler. To insert an + operand value into an instruction, check this field. + + If it is NULL, execute + i |= (op & ((1 << o->bits) - 1)) << o->shift; + (i is the instruction which we are filling in, o is a pointer to + this structure, and op is the opcode value; this assumes twos + complement arithmetic). + + If this field is not NULL, then simply call it with the + instruction and the operand value. It will return the new value + of the instruction. If the ERRMSG argument is not NULL, then if + the operand value is illegal, *ERRMSG will be set to a warning + string (the operand will be inserted in any case). If the + operand value is legal, *ERRMSG will be unchanged (most operands + can accept any value). */ + unsigned long (*insert) PARAMS ((unsigned long instruction, long op, + const char **errmsg)); + + /* Extraction function. This is used by the disassembler. To + extract this operand type from an instruction, check this field. + + If it is NULL, compute + op = ((i) >> o->shift) & ((1 << o->bits) - 1); + if ((o->flags & PPC_OPERAND_SIGNED) != 0 + && (op & (1 << (o->bits - 1))) != 0) + op -= 1 << o->bits; + (i is the instruction, o is a pointer to this structure, and op + is the result; this assumes twos complement arithmetic). + + If this field is not NULL, then simply call it with the + instruction value. It will return the value of the operand. If + the INVALID argument is not NULL, *INVALID will be set to + non-zero if this operand type can not actually be extracted from + this operand (i.e., the instruction does not match). If the + operand is valid, *INVALID will not be changed. */ + long (*extract) PARAMS ((unsigned long instruction, int *invalid)); + + /* One bit syntax flags. */ + unsigned long flags; +}; + +/* Elements in the table are retrieved by indexing with values from + the operands field of the powerpc_opcodes table. */ + +extern const struct powerpc_operand powerpc_operands[]; + +/* Values defined for the flags field of a struct powerpc_operand. */ + +/* This operand takes signed values. */ +#define PPC_OPERAND_SIGNED (01) + +/* This operand takes signed values, but also accepts a full positive + range of values when running in 32 bit mode. That is, if bits is + 16, it takes any value from -0x8000 to 0xffff. In 64 bit mode, + this flag is ignored. */ +#define PPC_OPERAND_SIGNOPT (02) + +/* This operand does not actually exist in the assembler input. This + is used to support extended mnemonics such as mr, for which two + operands fields are identical. The assembler should call the + insert function with any op value. The disassembler should call + the extract function, ignore the return value, and check the value + placed in the valid argument. */ +#define PPC_OPERAND_FAKE (04) + +/* The next operand should be wrapped in parentheses rather than + separated from this one by a comma. This is used for the load and + store instructions which want their operands to look like + reg,displacement(reg) + */ +#define PPC_OPERAND_PARENS (010) + +/* This operand may use the symbolic names for the CR fields, which + are + lt 0 gt 1 eq 2 so 3 un 3 + cr0 0 cr1 1 cr2 2 cr3 3 + cr4 4 cr5 5 cr6 6 cr7 7 + These may be combined arithmetically, as in cr2*4+gt. These are + only supported on the PowerPC, not the POWER. */ +#define PPC_OPERAND_CR (020) + +/* This operand names a register. The disassembler uses this to print + register names with a leading 'r'. */ +#define PPC_OPERAND_GPR (040) + +/* This operand names a floating point register. The disassembler + prints these with a leading 'f'. */ +#define PPC_OPERAND_FPR (0100) + +/* This operand is a relative branch displacement. The disassembler + prints these symbolically if possible. */ +#define PPC_OPERAND_RELATIVE (0200) + +/* This operand is an absolute branch address. The disassembler + prints these symbolically if possible. */ +#define PPC_OPERAND_ABSOLUTE (0400) + +/* This operand is optional, and is zero if omitted. This is used for + the optional BF and L fields in the comparison instructions. The + assembler must count the number of operands remaining on the line, + and the number of operands remaining for the opcode, and decide + whether this operand is present or not. The disassembler should + print this operand out only if it is not zero. */ +#define PPC_OPERAND_OPTIONAL (01000) + +/* This flag is only used with PPC_OPERAND_OPTIONAL. If this operand + is omitted, then for the next operand use this operand value plus + 1, ignoring the next operand field for the opcode. This wretched + hack is needed because the Power rotate instructions can take + either 4 or 5 operands. The disassembler should print this operand + out regardless of the PPC_OPERAND_OPTIONAL field. */ +#define PPC_OPERAND_NEXT (02000) + +/* This operand should be regarded as a negative number for the + purposes of overflow checking (i.e., the normal most negative + number is disallowed and one more than the normal most positive + number is allowed). This flag will only be set for a signed + operand. */ +#define PPC_OPERAND_NEGATIVE (04000) + +/* The POWER and PowerPC assemblers use a few macros. We keep them + with the operands table for simplicity. The macro table is an + array of struct powerpc_macro. */ + +struct powerpc_macro +{ + /* The macro name. */ + const char *name; + + /* The number of operands the macro takes. */ + unsigned int operands; + + /* One bit flags for the opcode. These are used to indicate which + specific processors support the instructions. The values are the + same as those for the struct powerpc_opcode flags field. */ + unsigned long flags; + + /* A format string to turn the macro into a normal instruction. + Each %N in the string is replaced with operand number N (zero + based). */ + const char *format; +}; + +extern const struct powerpc_macro powerpc_macros[]; +extern const int powerpc_num_macros; + +#endif /* PPC_H */ diff --git a/opcode/sparc-dis.c b/opcode/sparc-dis.c new file mode 100644 index 000000000..42388aef9 --- /dev/null +++ b/opcode/sparc-dis.c @@ -0,0 +1,868 @@ +/* Print SPARC instructions. + Copyright (C) 1989, 91-93, 1995, 1996 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "ansidecl.h" +#include "opcode/sparc.h" +#include "dis-asm.h" + +#include + +/* Bitmask of v9 architectures. */ +#define MASK_V9 ((1 << SPARC_OPCODE_ARCH_V9) \ + | (1 << SPARC_OPCODE_ARCH_V9A)) +/* 1 if INSN is for v9 only. */ +#define V9_ONLY_P(insn) (! ((insn)->architecture & ~MASK_V9)) +/* 1 if INSN is for v9. */ +#define V9_P(insn) (((insn)->architecture & MASK_V9) != 0) + +/* For faster lookup, after insns are sorted they are hashed. */ +/* ??? I think there is room for even more improvement. */ + +#define HASH_SIZE 256 +/* It is important that we only look at insn code bits as that is how the + opcode table is hashed. OPCODE_BITS is a table of valid bits for each + of the main types (0,1,2,3). */ +static int opcode_bits[4] = { 0x01c00000, 0x0, 0x01f80000, 0x01f80000 }; +#define HASH_INSN(INSN) \ + ((((INSN) >> 24) & 0xc0) | (((INSN) & opcode_bits[((INSN) >> 30) & 3]) >> 19)) +struct opcode_hash { + struct opcode_hash *next; + struct sparc_opcode *opcode; +}; +static struct opcode_hash *opcode_hash_table[HASH_SIZE]; +static void build_hash_table (); + +/* Sign-extend a value which is N bits long. */ +#define SEX(value, bits) \ + ((((int)(value)) << ((8 * sizeof (int)) - bits)) \ + >> ((8 * sizeof (int)) - bits) ) + +static char *reg_names[] = +{ "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", + "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7", + "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", + "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7", + "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", + "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", + "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", + "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", + "f32", "f33", "f34", "f35", "f36", "f37", "f38", "f39", + "f40", "f41", "f42", "f43", "f44", "f45", "f46", "f47", + "f48", "f49", "f50", "f51", "f52", "f53", "f54", "f55", + "f56", "f57", "f58", "f59", "f60", "f61", "f62", "f63", +/* psr, wim, tbr, fpsr, cpsr are v8 only. */ + "y", "psr", "wim", "tbr", "pc", "npc", "fpsr", "cpsr" +}; + +#define freg_names (®_names[4 * 8]) + +/* These are ordered according to there register number in + rdpr and wrpr insns. */ +static char *v9_priv_reg_names[] = +{ + "tpc", "tnpc", "tstate", "tt", "tick", "tba", "pstate", "tl", + "pil", "cwp", "cansave", "canrestore", "cleanwin", "otherwin", + "wstate", "fq" + /* "ver" - special cased */ +}; + +/* Macros used to extract instruction fields. Not all fields have + macros defined here, only those which are actually used. */ + +#define X_RD(i) (((i) >> 25) & 0x1f) +#define X_RS1(i) (((i) >> 14) & 0x1f) +#define X_LDST_I(i) (((i) >> 13) & 1) +#define X_ASI(i) (((i) >> 5) & 0xff) +#define X_RS2(i) (((i) >> 0) & 0x1f) +#define X_IMM13(i) (((i) >> 0) & 0x1fff) +#define X_DISP22(i) (((i) >> 0) & 0x3fffff) +#define X_IMM22(i) X_DISP22 (i) +#define X_DISP30(i) (((i) >> 0) & 0x3fffffff) + +/* These are for v9. */ +#define X_DISP16(i) (((((i) >> 20) & 3) << 14) | (((i) >> 0) & 0x3fff)) +#define X_DISP19(i) (((i) >> 0) & 0x7ffff) +#define X_MEMBAR(i) ((i) & 0x7f) + +/* Here is the union which was used to extract instruction fields + before the shift and mask macros were written. + + union sparc_insn + { + unsigned long int code; + struct + { + unsigned int anop:2; + #define op ldst.anop + unsigned int anrd:5; + #define rd ldst.anrd + unsigned int op3:6; + unsigned int anrs1:5; + #define rs1 ldst.anrs1 + unsigned int i:1; + unsigned int anasi:8; + #define asi ldst.anasi + unsigned int anrs2:5; + #define rs2 ldst.anrs2 + #define shcnt rs2 + } ldst; + struct + { + unsigned int anop:2, anrd:5, op3:6, anrs1:5, i:1; + unsigned int IMM13:13; + #define imm13 IMM13.IMM13 + } IMM13; + struct + { + unsigned int anop:2; + unsigned int a:1; + unsigned int cond:4; + unsigned int op2:3; + unsigned int DISP22:22; + #define disp22 branch.DISP22 + #define imm22 disp22 + } branch; + struct + { + unsigned int anop:2; + unsigned int a:1; + unsigned int z:1; + unsigned int rcond:3; + unsigned int op2:3; + unsigned int DISP16HI:2; + unsigned int p:1; + unsigned int _rs1:5; + unsigned int DISP16LO:14; + } branch16; + struct + { + unsigned int anop:2; + unsigned int adisp30:30; + #define disp30 call.adisp30 + } call; + }; + + */ + +/* Nonzero if INSN is the opcode for a delayed branch. */ +static int +is_delayed_branch (insn) + unsigned long insn; +{ + struct opcode_hash *op; + + for (op = opcode_hash_table[HASH_INSN (insn)]; op; op = op->next) + { + const struct sparc_opcode *opcode = op->opcode; + if ((opcode->match & insn) == opcode->match + && (opcode->lose & insn) == 0) + return (opcode->flags & F_DELAYED); + } + return 0; +} + +/* Nonzero of opcode table has been initialized. */ +static int opcodes_initialized = 0; + +/* extern void qsort (); */ +static int compare_opcodes (); + +/* Print one instruction from MEMADDR on INFO->STREAM. + + We suffix the instruction with a comment that gives the absolute + address involved, as well as its symbolic form, if the instruction + is preceded by a findable `sethi' and it either adds an immediate + displacement to that register, or it is an `add' or `or' instruction + on that register. */ + +int +print_insn_sparc (memaddr, info) + bfd_vma memaddr; + disassemble_info *info; +{ + FILE *stream = info->stream; + bfd_byte buffer[4]; + unsigned long insn; + register unsigned int i; + register struct opcode_hash *op; + int sparc_v9_p = bfd_mach_sparc_v9_p (info->mach); + + if (!opcodes_initialized) + { + qsort ((char *) sparc_opcodes, sparc_num_opcodes, + sizeof (sparc_opcodes[0]), compare_opcodes); + build_hash_table (sparc_opcodes, opcode_hash_table, sparc_num_opcodes); + opcodes_initialized = 1; + } + + { + int status = + (*info->read_memory_func) (memaddr, buffer, sizeof (buffer), info); + if (status != 0) + { + (*info->memory_error_func) (status, memaddr, info); + return -1; + } + } + + insn = bfd_getb32 (buffer); + + info->insn_info_valid = 1; /* We do return this info */ + info->insn_type = dis_nonbranch; /* Assume non branch insn */ + info->branch_delay_insns = 0; /* Assume no delay */ + info->target = 0; /* Assume no target known */ + + for (op = opcode_hash_table[HASH_INSN (insn)]; op; op = op->next) + { + const struct sparc_opcode *opcode = op->opcode; + + /* ??? These architecture tests need to be more selective. */ + + /* If the current architecture isn't sparc64, skip sparc64 insns. */ + if (!sparc_v9_p + && V9_ONLY_P (opcode)) + continue; + + /* If the current architecture is sparc64, skip sparc32 only insns. */ + if (sparc_v9_p + && ! V9_P (opcode)) + continue; + + if ((opcode->match & insn) == opcode->match + && (opcode->lose & insn) == 0) + { + /* Nonzero means that we have found an instruction which has + the effect of adding or or'ing the imm13 field to rs1. */ + int imm_added_to_rs1 = 0; + + /* Nonzero means that we have found a plus sign in the args + field of the opcode table. */ + int found_plus = 0; + + /* Nonzero means we have an annulled branch. */ + int is_annulled = 0; + + /* Do we have an `add' or `or' instruction where rs1 is the same + as rsd, and which has the i bit set? */ + if ((opcode->match == 0x80102000 || opcode->match == 0x80002000) + /* (or) (add) */ + && X_RS1 (insn) == X_RD (insn)) + imm_added_to_rs1 = 1; + + if (X_RS1 (insn) != X_RD (insn) + && strchr (opcode->args, 'r') != 0) + /* Can't do simple format if source and dest are different. */ + continue; + if (X_RS2 (insn) != X_RD (insn) + && strchr (opcode->args, 'O') != 0) + /* Can't do simple format if source and dest are different. */ + continue; + + (*info->fprintf_func) (stream, opcode->name); + + { + register const char *s; + + if (opcode->args[0] != ',') + (*info->fprintf_func) (stream, " "); + for (s = opcode->args; *s != '\0'; ++s) + { + while (*s == ',') + { + (*info->fprintf_func) (stream, ","); + ++s; + switch (*s) { + case 'a': + (*info->fprintf_func) (stream, "a"); + is_annulled = 1; + ++s; + continue; + case 'N': + (*info->fprintf_func) (stream, "pn"); + ++s; + continue; + + case 'T': + (*info->fprintf_func) (stream, "pt"); + ++s; + continue; + + default: + break; + } /* switch on arg */ + } /* while there are comma started args */ + + (*info->fprintf_func) (stream, " "); + + switch (*s) + { + case '+': + found_plus = 1; + + /* note fall-through */ + default: + (*info->fprintf_func) (stream, "%c", *s); + break; + + case '#': + (*info->fprintf_func) (stream, "0"); + break; + +#define reg(n) (*info->fprintf_func) (stream, "%%%s", reg_names[n]) + case '1': + case 'r': + reg (X_RS1 (insn)); + break; + + case '2': + case 'O': + reg (X_RS2 (insn)); + break; + + case 'd': + reg (X_RD (insn)); + break; +#undef reg + +#define freg(n) (*info->fprintf_func) (stream, "%%%s", freg_names[n]) +#define fregx(n) (*info->fprintf_func) (stream, "%%%s", freg_names[((n) & ~1) | (((n) & 1) << 5)]) + case 'e': + freg (X_RS1 (insn)); + break; + case 'v': /* double/even */ + case 'V': /* quad/multiple of 4 */ + fregx (X_RS1 (insn)); + break; + + case 'f': + freg (X_RS2 (insn)); + break; + case 'B': /* double/even */ + case 'R': /* quad/multiple of 4 */ + fregx (X_RS2 (insn)); + break; + + case 'g': + freg (X_RD (insn)); + break; + case 'H': /* double/even */ + case 'J': /* quad/multiple of 4 */ + fregx (X_RD (insn)); + break; +#undef freg +#undef fregx + +#define creg(n) (*info->fprintf_func) (stream, "%%c%u", (unsigned int) (n)) + case 'b': + creg (X_RS1 (insn)); + break; + + case 'c': + creg (X_RS2 (insn)); + break; + + case 'D': + creg (X_RD (insn)); + break; +#undef creg + + case 'h': + (*info->fprintf_func) (stream, "%%hi(%#x)", + (0xFFFFFFFF + & ((int) X_IMM22 (insn) << 10))); + break; + + case 'i': + { + int imm = SEX (X_IMM13 (insn), 13); + + /* Check to see whether we have a 1+i, and take + note of that fact. + + Note: because of the way we sort the table, + we will be matching 1+i rather than i+1, + so it is OK to assume that i is after +, + not before it. */ + if (found_plus) + imm_added_to_rs1 = 1; + + if (imm <= 9) + (*info->fprintf_func) (stream, "%d", imm); + else + (*info->fprintf_func) (stream, "%#x", imm); + } + break; + + case 'I': /* 11 bit immediate. */ + case 'j': /* 10 bit immediate. */ + { + int imm; + + if (*s == 'I') + imm = SEX (X_IMM13 (insn), 11); + else + imm = SEX (X_IMM13 (insn), 10); + + /* Check to see whether we have a 1+i, and take + note of that fact. + + Note: because of the way we sort the table, + we will be matching 1+i rather than i+1, + so it is OK to assume that i is after +, + not before it. */ + if (found_plus) + imm_added_to_rs1 = 1; + + if (imm <= 9) + (info->fprintf_func) (stream, "%d", imm); + else + (info->fprintf_func) (stream, "%#x", (unsigned) imm); + } + break; + + case 'K': + { + int mask = X_MEMBAR (insn); + int bit = 0x40, printed_one = 0; + char *name; + + if (mask == 0) + (info->fprintf_func) (stream, "0"); + else + while (bit) + { + if (mask & bit) + { + if (printed_one) + (info->fprintf_func) (stream, "|"); + name = sparc_decode_membar (bit); + (info->fprintf_func) (stream, "%s", name); + printed_one = 1; + } + bit >>= 1; + } + break; + } + + case 'k': + info->target = memaddr + SEX (X_DISP16 (insn), 16) * 4; + (*info->print_address_func) (info->target, info); + break; + + case 'G': + info->target = memaddr + SEX (X_DISP19 (insn), 19) * 4; + (*info->print_address_func) (info->target, info); + break; + + case '6': + case '7': + case '8': + case '9': + (*info->fprintf_func) (stream, "%%fcc%c", *s - '6' + '0'); + break; + + case 'z': + (*info->fprintf_func) (stream, "%%icc"); + break; + + case 'Z': + (*info->fprintf_func) (stream, "%%xcc"); + break; + + case 'E': + (*info->fprintf_func) (stream, "%%ccr"); + break; + + case 's': + (*info->fprintf_func) (stream, "%%fprs"); + break; + + case 'o': + (*info->fprintf_func) (stream, "%%asi"); + break; + + case 'W': + (*info->fprintf_func) (stream, "%%tick"); + break; + + case 'P': + (*info->fprintf_func) (stream, "%%pc"); + break; + + case '?': + if (X_RS1 (insn) == 31) + (*info->fprintf_func) (stream, "%%ver"); + else if ((unsigned) X_RS1 (insn) < 16) + (*info->fprintf_func) (stream, "%%%s", + v9_priv_reg_names[X_RS1 (insn)]); + else + (*info->fprintf_func) (stream, "%%reserved"); + break; + + case '!': + if ((unsigned) X_RD (insn) < 15) + (*info->fprintf_func) (stream, "%%%s", + v9_priv_reg_names[X_RD (insn)]); + else + (*info->fprintf_func) (stream, "%%reserved"); + break; + + case '*': + { + char *name = sparc_decode_prefetch (X_RD (insn)); + + if (name) + (*info->fprintf_func) (stream, "%s", name); + else + (*info->fprintf_func) (stream, "%d", X_RD (insn)); + break; + } + + case 'M': + (*info->fprintf_func) (stream, "%%asr%d", X_RS1 (insn)); + break; + + case 'm': + (*info->fprintf_func) (stream, "%%asr%d", X_RD (insn)); + break; + + case 'L': + info->target = memaddr + SEX (X_DISP30 (insn), 30) * 4; + (*info->print_address_func) (info->target, info); + break; + + case 'n': + (*info->fprintf_func) + (stream, "%#x", SEX (X_DISP22 (insn), 22)); + break; + + case 'l': + info->target = memaddr + SEX (X_DISP22 (insn), 22) * 4; + (*info->print_address_func) (info->target, info); + break; + + case 'A': + { + char *name = sparc_decode_asi (X_ASI (insn)); + + if (name) + (*info->fprintf_func) (stream, "%s", name); + else + (*info->fprintf_func) (stream, "(%d)", X_ASI (insn)); + break; + } + + case 'C': + (*info->fprintf_func) (stream, "%%csr"); + break; + + case 'F': + (*info->fprintf_func) (stream, "%%fsr"); + break; + + case 'p': + (*info->fprintf_func) (stream, "%%psr"); + break; + + case 'q': + (*info->fprintf_func) (stream, "%%fq"); + break; + + case 'Q': + (*info->fprintf_func) (stream, "%%cq"); + break; + + case 't': + (*info->fprintf_func) (stream, "%%tbr"); + break; + + case 'w': + (*info->fprintf_func) (stream, "%%wim"); + break; + + case 'x': + (*info->fprintf_func) (stream, "%d", + ((X_LDST_I (insn) << 8) + + X_ASI (insn))); + break; + + case 'y': + (*info->fprintf_func) (stream, "%%y"); + break; + + case 'u': + case 'U': + { + int val = *s == 'U' ? X_RS1 (insn) : X_RD (insn); + char *name = sparc_decode_sparclet_cpreg (val); + + if (name) + (*info->fprintf_func) (stream, "%s", name); + else + (*info->fprintf_func) (stream, "%%cpreg(%d)", val); + break; + } + } + } + } + + /* If we are adding or or'ing something to rs1, then + check to see whether the previous instruction was + a sethi to the same register as in the sethi. + If so, attempt to print the result of the add or + or (in this context add and or do the same thing) + and its symbolic value. */ + if (imm_added_to_rs1) + { + unsigned long prev_insn; + int errcode; + + errcode = + (*info->read_memory_func) + (memaddr - 4, buffer, sizeof (buffer), info); + prev_insn = bfd_getb32 (buffer); + + if (errcode == 0) + { + /* If it is a delayed branch, we need to look at the + instruction before the delayed branch. This handles + sequences such as + + sethi %o1, %hi(_foo), %o1 + call _printf + or %o1, %lo(_foo), %o1 + */ + + if (is_delayed_branch (prev_insn)) + { + errcode = (*info->read_memory_func) + (memaddr - 8, buffer, sizeof (buffer), info); + prev_insn = bfd_getb32 (buffer); + } + } + + /* If there was a problem reading memory, then assume + the previous instruction was not sethi. */ + if (errcode == 0) + { + /* Is it sethi to the same register? */ + if ((prev_insn & 0xc1c00000) == 0x01000000 + && X_RD (prev_insn) == X_RS1 (insn)) + { + (*info->fprintf_func) (stream, "\t! "); + info->target = + (0xFFFFFFFF & (int) X_IMM22 (prev_insn) << 10) + | SEX (X_IMM13 (insn), 13); + (*info->print_address_func) (info->target, info); + info->insn_type = dis_dref; + info->data_size = 4; /* FIXME!!! */ + } + } + } + + if (opcode->flags & (F_UNBR|F_CONDBR|F_JSR)) + { + /* FIXME -- check is_annulled flag */ + if (opcode->flags & F_UNBR) + info->insn_type = dis_branch; + if (opcode->flags & F_CONDBR) + info->insn_type = dis_condbranch; + if (opcode->flags & F_JSR) + info->insn_type = dis_jsr; + if (opcode->flags & F_DELAYED) + info->branch_delay_insns = 1; + } + + return sizeof (buffer); + } + } + + info->insn_type = dis_noninsn; /* Mark as non-valid instruction */ + (*info->fprintf_func) (stream, "unknown"); + return sizeof (buffer); +} + +/* Compare opcodes A and B. */ + +static int +compare_opcodes (a, b) + char *a, *b; +{ + struct sparc_opcode *op0 = (struct sparc_opcode *) a; + struct sparc_opcode *op1 = (struct sparc_opcode *) b; + unsigned long int match0 = op0->match, match1 = op1->match; + unsigned long int lose0 = op0->lose, lose1 = op1->lose; + register unsigned int i; + + /* If a bit is set in both match and lose, there is something + wrong with the opcode table. */ + if (match0 & lose0) + { + fprintf (stderr, "Internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n", + op0->name, match0, lose0); + op0->lose &= ~op0->match; + lose0 = op0->lose; + } + + if (match1 & lose1) + { + fprintf (stderr, "Internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n", + op1->name, match1, lose1); + op1->lose &= ~op1->match; + lose1 = op1->lose; + } + + /* Because the bits that are variable in one opcode are constant in + another, it is important to order the opcodes in the right order. */ + for (i = 0; i < 32; ++i) + { + unsigned long int x = 1 << i; + int x0 = (match0 & x) != 0; + int x1 = (match1 & x) != 0; + + if (x0 != x1) + return x1 - x0; + } + + for (i = 0; i < 32; ++i) + { + unsigned long int x = 1 << i; + int x0 = (lose0 & x) != 0; + int x1 = (lose1 & x) != 0; + + if (x0 != x1) + return x1 - x0; + } + + /* Put non-sparc64 insns ahead of sparc64 ones. */ + if (V9_ONLY_P (op0) != V9_ONLY_P (op1)) + return V9_ONLY_P (op0) - V9_ONLY_P (op1); + + /* They are functionally equal. So as long as the opcode table is + valid, we can put whichever one first we want, on aesthetic grounds. */ + + /* Our first aesthetic ground is that aliases defer to real insns. */ + { + int alias_diff = (op0->flags & F_ALIAS) - (op1->flags & F_ALIAS); + if (alias_diff != 0) + /* Put the one that isn't an alias first. */ + return alias_diff; + } + + /* Except for aliases, two "identical" instructions had + better have the same opcode. This is a sanity check on the table. */ + i = strcmp (op0->name, op1->name); + if (i) + if (op0->flags & F_ALIAS) /* If they're both aliases, be arbitrary. */ + return i; + else + fprintf (stderr, + "Internal error: bad sparc-opcode.h: \"%s\" == \"%s\"\n", + op0->name, op1->name); + + /* Fewer arguments are preferred. */ + { + int length_diff = strlen (op0->args) - strlen (op1->args); + if (length_diff != 0) + /* Put the one with fewer arguments first. */ + return length_diff; + } + + /* Put 1+i before i+1. */ + { + char *p0 = (char *) strchr(op0->args, '+'); + char *p1 = (char *) strchr(op1->args, '+'); + + if (p0 && p1) + { + /* There is a plus in both operands. Note that a plus + sign cannot be the first character in args, + so the following [-1]'s are valid. */ + if (p0[-1] == 'i' && p1[1] == 'i') + /* op0 is i+1 and op1 is 1+i, so op1 goes first. */ + return 1; + if (p0[1] == 'i' && p1[-1] == 'i') + /* op0 is 1+i and op1 is i+1, so op0 goes first. */ + return -1; + } + } + + /* Put 1,i before i,1. */ + { + int i0 = strncmp (op0->args, "i,1", 3) == 0; + int i1 = strncmp (op1->args, "i,1", 3) == 0; + + if (i0 ^ i1) + return i0 - i1; + } + + /* They are, as far as we can tell, identical. + Since qsort may have rearranged the table partially, there is + no way to tell which one was first in the opcode table as + written, so just say there are equal. */ + return 0; +} + +/* Build a hash table from the opcode table. */ + +static void +build_hash_table (table, hash_table, num_opcodes) + struct sparc_opcode *table; + struct opcode_hash **hash_table; + int num_opcodes; +{ + register int i; + int hash_count[HASH_SIZE]; + static struct opcode_hash *hash_buf = NULL; + + /* Start at the end of the table and work backwards so that each + chain is sorted. */ + + memset (hash_table, 0, HASH_SIZE * sizeof (hash_table[0])); + memset (hash_count, 0, HASH_SIZE * sizeof (hash_count[0])); + if (hash_buf != NULL) + free (hash_buf); + hash_buf = (struct opcode_hash *) xmalloc (sizeof (struct opcode_hash) * num_opcodes); + for (i = num_opcodes - 1; i >= 0; --i) + { + register int hash = HASH_INSN (sparc_opcodes[i].match); + register struct opcode_hash *h = &hash_buf[i]; + h->next = hash_table[hash]; + h->opcode = &sparc_opcodes[i]; + hash_table[hash] = h; + ++hash_count[hash]; + } + +#if 0 /* for debugging */ + { + int min_count = num_opcodes, max_count = 0; + int total; + + for (i = 0; i < HASH_SIZE; ++i) + { + if (hash_count[i] < min_count) + min_count = hash_count[i]; + if (hash_count[i] > max_count) + max_count = hash_count[i]; + total += hash_count[i]; + } + + printf ("Opcode hash table stats: min %d, max %d, ave %f\n", + min_count, max_count, (double) total / HASH_SIZE); + } +#endif +} diff --git a/opcode/sparc-opc.c b/opcode/sparc-opc.c new file mode 100644 index 000000000..4e91227c1 --- /dev/null +++ b/opcode/sparc-opc.c @@ -0,0 +1,1757 @@ +/* Table of opcodes for the sparc. + Copyright (C) 1989, 1991, 1992, 1995, 1996 Free Software Foundation, Inc. + +This file is part of the BFD library. + +BFD is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 2, or (at your option) any later +version. + +BFD 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 software; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* FIXME-someday: perhaps the ,a's and such should be embedded in the + instruction's name rather than the args. This would make gas faster, pinsn + slower, but would mess up some macros a bit. xoxorich. */ + +/* v9 FIXME: Doesn't accept `setsw', `setx' synthetic instructions for v9. */ + +#include +#include "ansidecl.h" +#include "opcode/sparc.h" + +/* Some defines to make life easy. */ +#define MASK_V6 (1 << SPARC_OPCODE_ARCH_V6) +#define MASK_V7 (1 << SPARC_OPCODE_ARCH_V7) +#define MASK_V8 (1 << SPARC_OPCODE_ARCH_V8) +#define MASK_SPARCLET (1 << SPARC_OPCODE_ARCH_SPARCLET) +#define MASK_SPARCLITE (1 << SPARC_OPCODE_ARCH_SPARCLITE) +#define MASK_V9 (1 << SPARC_OPCODE_ARCH_V9) +#define MASK_V9A (1 << SPARC_OPCODE_ARCH_V9A) + +/* Bit masks of architectures supporting the insn. */ + +#define v6 (MASK_V6 | MASK_V7 | MASK_V8 | MASK_SPARCLET \ + | MASK_SPARCLITE | MASK_V9 | MASK_V9A) +#define v7 (MASK_V7 | MASK_V8 | MASK_SPARCLET \ + | MASK_SPARCLITE | MASK_V9 | MASK_V9A) +/* Although not all insns are implemented in hardware, sparclite is defined + to be a superset of v8. Unimplemented insns trap and are then theoretically + implemented in software. + It's not clear that the same is true for sparclet, although the docs + suggest it is. Rather than complicating things, the sparclet assembler + recognizes all v8 insns. */ +#define v8 (MASK_V8 | MASK_SPARCLET | MASK_SPARCLITE | MASK_V9 | MASK_V9A) +#define sparclet (MASK_SPARCLET) +#define sparclite (MASK_SPARCLITE) +#define v9 (MASK_V9 | MASK_V9A) +#define v9a (MASK_V9A) +/* v6 insns not supported by v9 */ +#define v6notv9 (MASK_V6 | MASK_V7 | MASK_V8 \ + | MASK_SPARCLET | MASK_SPARCLITE) + +/* Table of opcode architectures. + The order is defined in opcode/sparc.h. */ +const struct sparc_opcode_arch sparc_opcode_archs[] = { + { "v6", MASK_V6 }, + { "v7", MASK_V6 | MASK_V7 }, + { "v8", MASK_V6 | MASK_V7 | MASK_V8 }, + { "sparclet", MASK_V6 | MASK_V7 | MASK_V8 | MASK_SPARCLET }, + { "sparclite", MASK_V6 | MASK_V7 | MASK_V8 | MASK_SPARCLITE }, + /* ??? Don't some v8 priviledged insns conflict with v9? */ + { "v9", MASK_V6 | MASK_V7 | MASK_V8 | MASK_V9 }, + /* v9 with ultrasparc additions */ + { "v9a", MASK_V6 | MASK_V7 | MASK_V8 | MASK_V9 | MASK_V9A }, + { NULL, 0 } +}; + +/* Given NAME, return it's architecture entry. */ + +enum sparc_opcode_arch_val +sparc_opcode_lookup_arch (name) + const char *name; +{ + const struct sparc_opcode_arch *p; + + for (p = &sparc_opcode_archs[0]; p->name; ++p) + { + if (strcmp (name, p->name) == 0) + return (enum sparc_opcode_arch_val) (p - &sparc_opcode_archs[0]); + } + + return SPARC_OPCODE_ARCH_BAD; +} + +/* Branch condition field. */ +#define COND(x) (((x)&0xf)<<25) + +/* v9: Move (MOVcc and FMOVcc) condition field. */ +#define MCOND(x,i_or_f) ((((i_or_f)&1)<<18)|(((x)>>11)&(0xf<<14))) /* v9 */ + +/* v9: Move register (MOVRcc and FMOVRcc) condition field. */ +#define RCOND(x) (((x)&0x7)<<10) /* v9 */ + +#define CONDA (COND(0x8)) +#define CONDCC (COND(0xd)) +#define CONDCS (COND(0x5)) +#define CONDE (COND(0x1)) +#define CONDG (COND(0xa)) +#define CONDGE (COND(0xb)) +#define CONDGU (COND(0xc)) +#define CONDL (COND(0x3)) +#define CONDLE (COND(0x2)) +#define CONDLEU (COND(0x4)) +#define CONDN (COND(0x0)) +#define CONDNE (COND(0x9)) +#define CONDNEG (COND(0x6)) +#define CONDPOS (COND(0xe)) +#define CONDVC (COND(0xf)) +#define CONDVS (COND(0x7)) + +#define CONDNZ CONDNE +#define CONDZ CONDE +#define CONDGEU CONDCC +#define CONDLU CONDCS + +#define FCONDA (COND(0x8)) +#define FCONDE (COND(0x9)) +#define FCONDG (COND(0x6)) +#define FCONDGE (COND(0xb)) +#define FCONDL (COND(0x4)) +#define FCONDLE (COND(0xd)) +#define FCONDLG (COND(0x2)) +#define FCONDN (COND(0x0)) +#define FCONDNE (COND(0x1)) +#define FCONDO (COND(0xf)) +#define FCONDU (COND(0x7)) +#define FCONDUE (COND(0xa)) +#define FCONDUG (COND(0x5)) +#define FCONDUGE (COND(0xc)) +#define FCONDUL (COND(0x3)) +#define FCONDULE (COND(0xe)) + +#define FCONDNZ FCONDNE +#define FCONDZ FCONDE + +#define ICC (0) /* v9 */ +#define XCC (1<<12) /* v9 */ +#define FCC(x) (((x)&0x3)<<11) /* v9 */ +#define FBFCC(x) (((x)&0x3)<<20) /* v9 */ + +/* The order of the opcodes in the table is significant: + + * The assembler requires that all instances of the same mnemonic must + be consecutive. If they aren't, the assembler will bomb at runtime. + + * The disassembler should not care about the order of the opcodes. + +*/ + +/* Entries for commutative arithmetic operations. */ +/* ??? More entries can make use of this. */ +#define commuteop(opcode, op3, arch_mask) \ +{ opcode, F3(2, op3, 0), F3(~2, ~op3, ~0)|ASI(~0), "1,2,d", 0, arch_mask }, \ +{ opcode, F3(2, op3, 1), F3(~2, ~op3, ~1), "1,i,d", 0, arch_mask }, \ +{ opcode, F3(2, op3, 1), F3(~2, ~op3, ~1), "i,1,d", 0, arch_mask } + +struct sparc_opcode sparc_opcodes[] = { + +{ "ld", F3(3, 0x00, 0), F3(~3, ~0x00, ~0), "[1+2],d", 0, v6 }, +{ "ld", F3(3, 0x00, 0), F3(~3, ~0x00, ~0)|RS2_G0, "[1],d", 0, v6 }, /* ld [rs1+%g0],d */ +{ "ld", F3(3, 0x00, 1), F3(~3, ~0x00, ~1), "[1+i],d", 0, v6 }, +{ "ld", F3(3, 0x00, 1), F3(~3, ~0x00, ~1), "[i+1],d", 0, v6 }, +{ "ld", F3(3, 0x00, 1), F3(~3, ~0x00, ~1)|RS1_G0, "[i],d", 0, v6 }, +{ "ld", F3(3, 0x00, 1), F3(~3, ~0x00, ~1)|SIMM13(~0), "[1],d", 0, v6 }, /* ld [rs1+0],d */ +{ "ld", F3(3, 0x20, 0), F3(~3, ~0x20, ~0), "[1+2],g", 0, v6 }, +{ "ld", F3(3, 0x20, 0), F3(~3, ~0x20, ~0)|RS2_G0, "[1],g", 0, v6 }, /* ld [rs1+%g0],d */ +{ "ld", F3(3, 0x20, 1), F3(~3, ~0x20, ~1), "[1+i],g", 0, v6 }, +{ "ld", F3(3, 0x20, 1), F3(~3, ~0x20, ~1), "[i+1],g", 0, v6 }, +{ "ld", F3(3, 0x20, 1), F3(~3, ~0x20, ~1)|RS1_G0, "[i],g", 0, v6 }, +{ "ld", F3(3, 0x20, 1), F3(~3, ~0x20, ~1)|SIMM13(~0), "[1],g", 0, v6 }, /* ld [rs1+0],d */ + +{ "ld", F3(3, 0x21, 0), F3(~3, ~0x21, ~0)|RD(~0), "[1+2],F", 0, v6 }, +{ "ld", F3(3, 0x21, 0), F3(~3, ~0x21, ~0)|RS2_G0|RD(~0),"[1],F", 0, v6 }, /* ld [rs1+%g0],d */ +{ "ld", F3(3, 0x21, 1), F3(~3, ~0x21, ~1)|RD(~0), "[1+i],F", 0, v6 }, +{ "ld", F3(3, 0x21, 1), F3(~3, ~0x21, ~1)|RD(~0), "[i+1],F", 0, v6 }, +{ "ld", F3(3, 0x21, 1), F3(~3, ~0x21, ~1)|RS1_G0|RD(~0),"[i],F", 0, v6 }, +{ "ld", F3(3, 0x21, 1), F3(~3, ~0x21, ~1)|SIMM13(~0)|RD(~0),"[1],F", 0, v6 }, /* ld [rs1+0],d */ + +{ "ld", F3(3, 0x30, 0), F3(~3, ~0x30, ~0), "[1+2],D", 0, v6notv9 }, +{ "ld", F3(3, 0x30, 0), F3(~3, ~0x30, ~0)|RS2_G0, "[1],D", 0, v6notv9 }, /* ld [rs1+%g0],d */ +{ "ld", F3(3, 0x30, 1), F3(~3, ~0x30, ~1), "[1+i],D", 0, v6notv9 }, +{ "ld", F3(3, 0x30, 1), F3(~3, ~0x30, ~1), "[i+1],D", 0, v6notv9 }, +{ "ld", F3(3, 0x30, 1), F3(~3, ~0x30, ~1)|RS1_G0, "[i],D", 0, v6notv9 }, +{ "ld", F3(3, 0x30, 1), F3(~3, ~0x30, ~1)|SIMM13(~0), "[1],D", 0, v6notv9 }, /* ld [rs1+0],d */ +{ "ld", F3(3, 0x31, 0), F3(~3, ~0x31, ~0), "[1+2],C", 0, v6notv9 }, +{ "ld", F3(3, 0x31, 0), F3(~3, ~0x31, ~0)|RS2_G0, "[1],C", 0, v6notv9 }, /* ld [rs1+%g0],d */ +{ "ld", F3(3, 0x31, 1), F3(~3, ~0x31, ~1), "[1+i],C", 0, v6notv9 }, +{ "ld", F3(3, 0x31, 1), F3(~3, ~0x31, ~1), "[i+1],C", 0, v6notv9 }, +{ "ld", F3(3, 0x31, 1), F3(~3, ~0x31, ~1)|RS1_G0, "[i],C", 0, v6notv9 }, +{ "ld", F3(3, 0x31, 1), F3(~3, ~0x31, ~1)|SIMM13(~0), "[1],C", 0, v6notv9 }, /* ld [rs1+0],d */ + +/* The v9 LDUW is the same as the old 'ld' opcode, it is not the same as the + 'ld' pseudo-op in v9. */ +{ "lduw", F3(3, 0x00, 0), F3(~3, ~0x00, ~0), "[1+2],d", F_ALIAS, v9 }, +{ "lduw", F3(3, 0x00, 0), F3(~3, ~0x00, ~0)|RS2_G0, "[1],d", F_ALIAS, v9 }, /* ld [rs1+%g0],d */ +{ "lduw", F3(3, 0x00, 1), F3(~3, ~0x00, ~1), "[1+i],d", F_ALIAS, v9 }, +{ "lduw", F3(3, 0x00, 1), F3(~3, ~0x00, ~1), "[i+1],d", F_ALIAS, v9 }, +{ "lduw", F3(3, 0x00, 1), F3(~3, ~0x00, ~1)|RS1_G0, "[i],d", F_ALIAS, v9 }, +{ "lduw", F3(3, 0x00, 1), F3(~3, ~0x00, ~1)|SIMM13(~0), "[1],d", F_ALIAS, v9 }, /* ld [rs1+0],d */ + +{ "ldd", F3(3, 0x03, 0), F3(~3, ~0x03, ~0)|ASI(~0), "[1+2],d", 0, v6 }, +{ "ldd", F3(3, 0x03, 0), F3(~3, ~0x03, ~0)|ASI_RS2(~0), "[1],d", 0, v6 }, /* ldd [rs1+%g0],d */ +{ "ldd", F3(3, 0x03, 1), F3(~3, ~0x03, ~1), "[1+i],d", 0, v6 }, +{ "ldd", F3(3, 0x03, 1), F3(~3, ~0x03, ~1), "[i+1],d", 0, v6 }, +{ "ldd", F3(3, 0x03, 1), F3(~3, ~0x03, ~1)|RS1_G0, "[i],d", 0, v6 }, +{ "ldd", F3(3, 0x03, 1), F3(~3, ~0x03, ~1)|SIMM13(~0), "[1],d", 0, v6 }, /* ldd [rs1+0],d */ +{ "ldd", F3(3, 0x23, 0), F3(~3, ~0x23, ~0)|ASI(~0), "[1+2],H", 0, v6 }, +{ "ldd", F3(3, 0x23, 0), F3(~3, ~0x23, ~0)|ASI_RS2(~0), "[1],H", 0, v6 }, /* ldd [rs1+%g0],d */ +{ "ldd", F3(3, 0x23, 1), F3(~3, ~0x23, ~1), "[1+i],H", 0, v6 }, +{ "ldd", F3(3, 0x23, 1), F3(~3, ~0x23, ~1), "[i+1],H", 0, v6 }, +{ "ldd", F3(3, 0x23, 1), F3(~3, ~0x23, ~1)|RS1_G0, "[i],H", 0, v6 }, +{ "ldd", F3(3, 0x23, 1), F3(~3, ~0x23, ~1)|SIMM13(~0), "[1],H", 0, v6 }, /* ldd [rs1+0],d */ + +{ "ldd", F3(3, 0x33, 0), F3(~3, ~0x33, ~0)|ASI(~0), "[1+2],D", 0, v6notv9 }, +{ "ldd", F3(3, 0x33, 0), F3(~3, ~0x33, ~0)|ASI_RS2(~0), "[1],D", 0, v6notv9 }, /* ldd [rs1+%g0],d */ +{ "ldd", F3(3, 0x33, 1), F3(~3, ~0x33, ~1), "[1+i],D", 0, v6notv9 }, +{ "ldd", F3(3, 0x33, 1), F3(~3, ~0x33, ~1), "[i+1],D", 0, v6notv9 }, +{ "ldd", F3(3, 0x33, 1), F3(~3, ~0x33, ~1)|RS1_G0, "[i],D", 0, v6notv9 }, +{ "ldd", F3(3, 0x33, 1), F3(~3, ~0x33, ~1)|SIMM13(~0), "[1],D", 0, v6notv9 }, /* ldd [rs1+0],d */ + +{ "ldq", F3(3, 0x22, 0), F3(~3, ~0x22, ~0)|ASI(~0), "[1+2],J", 0, v9 }, +{ "ldq", F3(3, 0x22, 0), F3(~3, ~0x22, ~0)|ASI_RS2(~0), "[1],J", 0, v9 }, /* ldd [rs1+%g0],d */ +{ "ldq", F3(3, 0x22, 1), F3(~3, ~0x22, ~1), "[1+i],J", 0, v9 }, +{ "ldq", F3(3, 0x22, 1), F3(~3, ~0x22, ~1), "[i+1],J", 0, v9 }, +{ "ldq", F3(3, 0x22, 1), F3(~3, ~0x22, ~1)|RS1_G0, "[i],J", 0, v9 }, +{ "ldq", F3(3, 0x22, 1), F3(~3, ~0x22, ~1)|SIMM13(~0), "[1],J", 0, v9 }, /* ldd [rs1+0],d */ + +{ "ldsb", F3(3, 0x09, 0), F3(~3, ~0x09, ~0)|ASI(~0), "[1+2],d", 0, v6 }, +{ "ldsb", F3(3, 0x09, 0), F3(~3, ~0x09, ~0)|ASI_RS2(~0), "[1],d", 0, v6 }, /* ldsb [rs1+%g0],d */ +{ "ldsb", F3(3, 0x09, 1), F3(~3, ~0x09, ~1), "[1+i],d", 0, v6 }, +{ "ldsb", F3(3, 0x09, 1), F3(~3, ~0x09, ~1), "[i+1],d", 0, v6 }, +{ "ldsb", F3(3, 0x09, 1), F3(~3, ~0x09, ~1)|RS1_G0, "[i],d", 0, v6 }, +{ "ldsb", F3(3, 0x09, 1), F3(~3, ~0x09, ~1)|SIMM13(~0), "[1],d", 0, v6 }, /* ldsb [rs1+0],d */ + +{ "ldsh", F3(3, 0x0a, 0), F3(~3, ~0x0a, ~0)|ASI_RS2(~0), "[1],d", 0, v6 }, /* ldsh [rs1+%g0],d */ +{ "ldsh", F3(3, 0x0a, 0), F3(~3, ~0x0a, ~0)|ASI(~0), "[1+2],d", 0, v6 }, +{ "ldsh", F3(3, 0x0a, 1), F3(~3, ~0x0a, ~1), "[1+i],d", 0, v6 }, +{ "ldsh", F3(3, 0x0a, 1), F3(~3, ~0x0a, ~1), "[i+1],d", 0, v6 }, +{ "ldsh", F3(3, 0x0a, 1), F3(~3, ~0x0a, ~1)|RS1_G0, "[i],d", 0, v6 }, +{ "ldsh", F3(3, 0x0a, 1), F3(~3, ~0x0a, ~1)|SIMM13(~0), "[1],d", 0, v6 }, /* ldsh [rs1+0],d */ + +{ "ldstub", F3(3, 0x0d, 0), F3(~3, ~0x0d, ~0)|ASI(~0), "[1+2],d", 0, v6 }, +{ "ldstub", F3(3, 0x0d, 0), F3(~3, ~0x0d, ~0)|ASI_RS2(~0), "[1],d", 0, v6 }, /* ldstub [rs1+%g0],d */ +{ "ldstub", F3(3, 0x0d, 1), F3(~3, ~0x0d, ~1), "[1+i],d", 0, v6 }, +{ "ldstub", F3(3, 0x0d, 1), F3(~3, ~0x0d, ~1), "[i+1],d", 0, v6 }, +{ "ldstub", F3(3, 0x0d, 1), F3(~3, ~0x0d, ~1)|RS1_G0, "[i],d", 0, v6 }, +{ "ldstub", F3(3, 0x0d, 1), F3(~3, ~0x0d, ~1)|SIMM13(~0), "[1],d", 0, v6 }, /* ldstub [rs1+0],d */ + +{ "ldsw", F3(3, 0x08, 0), F3(~3, ~0x08, ~0)|ASI(~0), "[1+2],d", 0, v9 }, +{ "ldsw", F3(3, 0x08, 0), F3(~3, ~0x08, ~0)|ASI_RS2(~0), "[1],d", 0, v9 }, /* ldsw [rs1+%g0],d */ +{ "ldsw", F3(3, 0x08, 1), F3(~3, ~0x08, ~1), "[1+i],d", 0, v9 }, +{ "ldsw", F3(3, 0x08, 1), F3(~3, ~0x08, ~1), "[i+1],d", 0, v9 }, +{ "ldsw", F3(3, 0x08, 1), F3(~3, ~0x08, ~1)|RS1_G0, "[i],d", 0, v9 }, +{ "ldsw", F3(3, 0x08, 1), F3(~3, ~0x08, ~1)|SIMM13(~0), "[1],d", 0, v9 }, /* ldsw [rs1+0],d */ + +{ "ldub", F3(3, 0x01, 0), F3(~3, ~0x01, ~0)|ASI(~0), "[1+2],d", 0, v6 }, +{ "ldub", F3(3, 0x01, 0), F3(~3, ~0x01, ~0)|ASI_RS2(~0), "[1],d", 0, v6 }, /* ldub [rs1+%g0],d */ +{ "ldub", F3(3, 0x01, 1), F3(~3, ~0x01, ~1), "[1+i],d", 0, v6 }, +{ "ldub", F3(3, 0x01, 1), F3(~3, ~0x01, ~1), "[i+1],d", 0, v6 }, +{ "ldub", F3(3, 0x01, 1), F3(~3, ~0x01, ~1)|RS1_G0, "[i],d", 0, v6 }, +{ "ldub", F3(3, 0x01, 1), F3(~3, ~0x01, ~1)|SIMM13(~0), "[1],d", 0, v6 }, /* ldub [rs1+0],d */ + +{ "lduh", F3(3, 0x02, 0), F3(~3, ~0x02, ~0)|ASI(~0), "[1+2],d", 0, v6 }, +{ "lduh", F3(3, 0x02, 0), F3(~3, ~0x02, ~0)|ASI_RS2(~0), "[1],d", 0, v6 }, /* lduh [rs1+%g0],d */ +{ "lduh", F3(3, 0x02, 1), F3(~3, ~0x02, ~1), "[1+i],d", 0, v6 }, +{ "lduh", F3(3, 0x02, 1), F3(~3, ~0x02, ~1), "[i+1],d", 0, v6 }, +{ "lduh", F3(3, 0x02, 1), F3(~3, ~0x02, ~1)|RS1_G0, "[i],d", 0, v6 }, +{ "lduh", F3(3, 0x02, 1), F3(~3, ~0x02, ~1)|SIMM13(~0), "[1],d", 0, v6 }, /* lduh [rs1+0],d */ + +{ "ldx", F3(3, 0x0b, 0), F3(~3, ~0x0b, ~0)|ASI(~0), "[1+2],d", 0, v9 }, +{ "ldx", F3(3, 0x0b, 0), F3(~3, ~0x0b, ~0)|ASI_RS2(~0), "[1],d", 0, v9 }, /* ldx [rs1+%g0],d */ +{ "ldx", F3(3, 0x0b, 1), F3(~3, ~0x0b, ~1), "[1+i],d", 0, v9 }, +{ "ldx", F3(3, 0x0b, 1), F3(~3, ~0x0b, ~1), "[i+1],d", 0, v9 }, +{ "ldx", F3(3, 0x0b, 1), F3(~3, ~0x0b, ~1)|RS1_G0, "[i],d", 0, v9 }, +{ "ldx", F3(3, 0x0b, 1), F3(~3, ~0x0b, ~1)|SIMM13(~0), "[1],d", 0, v9 }, /* ldx [rs1+0],d */ + +{ "ldx", F3(3, 0x21, 0)|RD(1), F3(~3, ~0x21, ~0)|RD(~1), "[1+2],F", 0, v9 }, +{ "ldx", F3(3, 0x21, 0)|RD(1), F3(~3, ~0x21, ~0)|RS2_G0|RD(~1), "[1],F", 0, v9 }, /* ld [rs1+%g0],d */ +{ "ldx", F3(3, 0x21, 1)|RD(1), F3(~3, ~0x21, ~1)|RD(~1), "[1+i],F", 0, v9 }, +{ "ldx", F3(3, 0x21, 1)|RD(1), F3(~3, ~0x21, ~1)|RD(~1), "[i+1],F", 0, v9 }, +{ "ldx", F3(3, 0x21, 1)|RD(1), F3(~3, ~0x21, ~1)|RS1_G0|RD(~1), "[i],F", 0, v9 }, +{ "ldx", F3(3, 0x21, 1)|RD(1), F3(~3, ~0x21, ~1)|SIMM13(~0)|RD(~1),"[1],F", 0, v9 }, /* ld [rs1+0],d */ + +{ "lda", F3(3, 0x10, 0), F3(~3, ~0x10, ~0), "[1+2]A,d", 0, v6 }, +{ "lda", F3(3, 0x10, 0), F3(~3, ~0x10, ~0)|RS2_G0, "[1]A,d", 0, v6 }, /* lda [rs1+%g0],d */ +{ "lda", F3(3, 0x10, 1), F3(~3, ~0x10, ~1), "[1+i]o,d", 0, v9 }, +{ "lda", F3(3, 0x10, 1), F3(~3, ~0x10, ~1), "[i+1]o,d", 0, v9 }, +{ "lda", F3(3, 0x10, 1), F3(~3, ~0x10, ~1)|RS1_G0, "[i]o,d", 0, v9 }, +{ "lda", F3(3, 0x10, 1), F3(~3, ~0x10, ~1)|SIMM13(~0), "[1]o,d", 0, v9 }, /* ld [rs1+0],d */ +{ "lda", F3(3, 0x30, 0), F3(~3, ~0x30, ~0), "[1+2]A,g", 0, v9 }, +{ "lda", F3(3, 0x30, 0), F3(~3, ~0x30, ~0)|RS2_G0, "[1]A,g", 0, v9 }, /* lda [rs1+%g0],d */ +{ "lda", F3(3, 0x30, 1), F3(~3, ~0x30, ~1), "[1+i]o,g", 0, v9 }, +{ "lda", F3(3, 0x30, 1), F3(~3, ~0x30, ~1), "[i+1]o,g", 0, v9 }, +{ "lda", F3(3, 0x30, 1), F3(~3, ~0x30, ~1)|RS1_G0, "[i]o,g", 0, v9 }, +{ "lda", F3(3, 0x30, 1), F3(~3, ~0x30, ~1)|SIMM13(~0), "[1]o,g", 0, v9 }, /* ld [rs1+0],d */ + +{ "ldda", F3(3, 0x13, 0), F3(~3, ~0x13, ~0), "[1+2]A,d", 0, v6 }, +{ "ldda", F3(3, 0x13, 0), F3(~3, ~0x13, ~0)|RS2_G0, "[1]A,d", 0, v6 }, /* ldda [rs1+%g0],d */ +{ "ldda", F3(3, 0x13, 1), F3(~3, ~0x13, ~1), "[1+i]o,d", 0, v9 }, +{ "ldda", F3(3, 0x13, 1), F3(~3, ~0x13, ~1), "[i+1]o,d", 0, v9 }, +{ "ldda", F3(3, 0x13, 1), F3(~3, ~0x13, ~1)|RS1_G0, "[i]o,d", 0, v9 }, +{ "ldda", F3(3, 0x13, 1), F3(~3, ~0x13, ~1)|SIMM13(~0), "[1]o,d", 0, v9 }, /* ld [rs1+0],d */ + +{ "ldda", F3(3, 0x33, 0), F3(~3, ~0x33, ~0), "[1+2]A,H", 0, v9 }, +{ "ldda", F3(3, 0x33, 0), F3(~3, ~0x33, ~0)|RS2_G0, "[1]A,H", 0, v9 }, /* ldda [rs1+%g0],d */ +{ "ldda", F3(3, 0x33, 1), F3(~3, ~0x33, ~1), "[1+i]o,H", 0, v9 }, +{ "ldda", F3(3, 0x33, 1), F3(~3, ~0x33, ~1), "[i+1]o,H", 0, v9 }, +{ "ldda", F3(3, 0x33, 1), F3(~3, ~0x33, ~1)|RS1_G0, "[i]o,H", 0, v9 }, +{ "ldda", F3(3, 0x33, 1), F3(~3, ~0x33, ~1)|SIMM13(~0), "[1]o,H", 0, v9 }, /* ld [rs1+0],d */ + +{ "ldqa", F3(3, 0x32, 0), F3(~3, ~0x32, ~0), "[1+2]A,J", 0, v9 }, +{ "ldqa", F3(3, 0x32, 0), F3(~3, ~0x32, ~0)|RS2_G0, "[1]A,J", 0, v9 }, /* ldd [rs1+%g0],d */ +{ "ldqa", F3(3, 0x32, 1), F3(~3, ~0x32, ~1), "[1+i]o,J", 0, v9 }, +{ "ldqa", F3(3, 0x32, 1), F3(~3, ~0x32, ~1), "[i+1]o,J", 0, v9 }, +{ "ldqa", F3(3, 0x32, 1), F3(~3, ~0x32, ~1)|RS1_G0, "[i]o,J", 0, v9 }, +{ "ldqa", F3(3, 0x32, 1), F3(~3, ~0x32, ~1)|SIMM13(~0), "[1]o,J", 0, v9 }, /* ldd [rs1+0],d */ + +{ "ldsba", F3(3, 0x19, 0), F3(~3, ~0x19, ~0), "[1+2]A,d", 0, v6 }, +{ "ldsba", F3(3, 0x19, 0), F3(~3, ~0x19, ~0)|RS2_G0, "[1]A,d", 0, v6 }, /* ldsba [rs1+%g0],d */ +{ "ldsba", F3(3, 0x19, 1), F3(~3, ~0x19, ~1), "[1+i]o,d", 0, v9 }, +{ "ldsba", F3(3, 0x19, 1), F3(~3, ~0x19, ~1), "[i+1]o,d", 0, v9 }, +{ "ldsba", F3(3, 0x19, 1), F3(~3, ~0x19, ~1)|RS1_G0, "[i]o,d", 0, v9 }, +{ "ldsba", F3(3, 0x19, 1), F3(~3, ~0x19, ~1)|SIMM13(~0), "[1]o,d", 0, v9 }, /* ld [rs1+0],d */ + +{ "ldsha", F3(3, 0x1a, 0), F3(~3, ~0x1a, ~0), "[1+2]A,d", 0, v6 }, +{ "ldsha", F3(3, 0x1a, 0), F3(~3, ~0x1a, ~0)|RS2_G0, "[1]A,d", 0, v6 }, /* ldsha [rs1+%g0],d */ +{ "ldsha", F3(3, 0x1a, 1), F3(~3, ~0x1a, ~1), "[1+i]o,d", 0, v9 }, +{ "ldsha", F3(3, 0x1a, 1), F3(~3, ~0x1a, ~1), "[i+1]o,d", 0, v9 }, +{ "ldsha", F3(3, 0x1a, 1), F3(~3, ~0x1a, ~1)|RS1_G0, "[i]o,d", 0, v9 }, +{ "ldsha", F3(3, 0x1a, 1), F3(~3, ~0x1a, ~1)|SIMM13(~0), "[1]o,d", 0, v9 }, /* ld [rs1+0],d */ + +{ "ldstuba", F3(3, 0x1d, 0), F3(~3, ~0x1d, ~0), "[1+2]A,d", 0, v6 }, +{ "ldstuba", F3(3, 0x1d, 0), F3(~3, ~0x1d, ~0)|RS2_G0, "[1]A,d", 0, v6 }, /* ldstuba [rs1+%g0],d */ +{ "ldstuba", F3(3, 0x1d, 1), F3(~3, ~0x1d, ~1), "[1+i]o,d", 0, v9 }, +{ "ldstuba", F3(3, 0x1d, 1), F3(~3, ~0x1d, ~1), "[i+1]o,d", 0, v9 }, +{ "ldstuba", F3(3, 0x1d, 1), F3(~3, ~0x1d, ~1)|RS1_G0, "[i]o,d", 0, v9 }, +{ "ldstuba", F3(3, 0x1d, 1), F3(~3, ~0x1d, ~1)|SIMM13(~0), "[1]o,d", 0, v9 }, /* ld [rs1+0],d */ + +{ "ldswa", F3(3, 0x18, 0), F3(~3, ~0x18, ~0), "[1+2]A,d", 0, v9 }, +{ "ldswa", F3(3, 0x18, 0), F3(~3, ~0x18, ~0)|RS2_G0, "[1]A,d", 0, v9 }, /* lda [rs1+%g0],d */ +{ "ldswa", F3(3, 0x18, 1), F3(~3, ~0x18, ~1), "[1+i]o,d", 0, v9 }, +{ "ldswa", F3(3, 0x18, 1), F3(~3, ~0x18, ~1), "[i+1]o,d", 0, v9 }, +{ "ldswa", F3(3, 0x18, 1), F3(~3, ~0x18, ~1)|RS1_G0, "[i]o,d", 0, v9 }, +{ "ldswa", F3(3, 0x18, 1), F3(~3, ~0x18, ~1)|SIMM13(~0), "[1]o,d", 0, v9 }, /* ld [rs1+0],d */ + +{ "lduba", F3(3, 0x11, 0), F3(~3, ~0x11, ~0), "[1+2]A,d", 0, v6 }, +{ "lduba", F3(3, 0x11, 0), F3(~3, ~0x11, ~0)|RS2_G0, "[1]A,d", 0, v6 }, /* lduba [rs1+%g0],d */ +{ "lduba", F3(3, 0x11, 1), F3(~3, ~0x11, ~1), "[1+i]o,d", 0, v9 }, +{ "lduba", F3(3, 0x11, 1), F3(~3, ~0x11, ~1), "[i+1]o,d", 0, v9 }, +{ "lduba", F3(3, 0x11, 1), F3(~3, ~0x11, ~1)|RS1_G0, "[i]o,d", 0, v9 }, +{ "lduba", F3(3, 0x11, 1), F3(~3, ~0x11, ~1)|SIMM13(~0), "[1]o,d", 0, v9 }, /* ld [rs1+0],d */ + +{ "lduha", F3(3, 0x12, 0), F3(~3, ~0x12, ~0), "[1+2]A,d", 0, v6 }, +{ "lduha", F3(3, 0x12, 0), F3(~3, ~0x12, ~0)|RS2_G0, "[1]A,d", 0, v6 }, /* lduha [rs1+%g0],d */ +{ "lduha", F3(3, 0x12, 1), F3(~3, ~0x12, ~1), "[1+i]o,d", 0, v9 }, +{ "lduha", F3(3, 0x12, 1), F3(~3, ~0x12, ~1), "[i+1]o,d", 0, v9 }, +{ "lduha", F3(3, 0x12, 1), F3(~3, ~0x12, ~1)|RS1_G0, "[i]o,d", 0, v9 }, +{ "lduha", F3(3, 0x12, 1), F3(~3, ~0x12, ~1)|SIMM13(~0), "[1]o,d", 0, v9 }, /* ld [rs1+0],d */ + +{ "lduwa", F3(3, 0x10, 0), F3(~3, ~0x10, ~0), "[1+2]A,d", F_ALIAS, v9 }, /* lduwa === lda */ +{ "lduwa", F3(3, 0x10, 0), F3(~3, ~0x10, ~0)|RS2_G0, "[1]A,d", F_ALIAS, v9 }, /* lda [rs1+%g0],d */ +{ "lduwa", F3(3, 0x10, 1), F3(~3, ~0x10, ~1), "[1+i]o,d", F_ALIAS, v9 }, +{ "lduwa", F3(3, 0x10, 1), F3(~3, ~0x10, ~1), "[i+1]o,d", F_ALIAS, v9 }, +{ "lduwa", F3(3, 0x10, 1), F3(~3, ~0x10, ~1)|RS1_G0, "[i]o,d", F_ALIAS, v9 }, +{ "lduwa", F3(3, 0x10, 1), F3(~3, ~0x10, ~1)|SIMM13(~0), "[1]o,d", F_ALIAS, v9 }, /* ld [rs1+0],d */ + +{ "ldxa", F3(3, 0x1b, 0), F3(~3, ~0x1b, ~0), "[1+2]A,d", 0, v9 }, /* lduwa === lda */ +{ "ldxa", F3(3, 0x1b, 0), F3(~3, ~0x1b, ~0)|RS2_G0, "[1]A,d", 0, v9 }, /* lda [rs1+%g0],d */ +{ "ldxa", F3(3, 0x1b, 1), F3(~3, ~0x1b, ~1), "[1+i]o,d", 0, v9 }, +{ "ldxa", F3(3, 0x1b, 1), F3(~3, ~0x1b, ~1), "[i+1]o,d", 0, v9 }, +{ "ldxa", F3(3, 0x1b, 1), F3(~3, ~0x1b, ~1)|RS1_G0, "[i]o,d", 0, v9 }, +{ "ldxa", F3(3, 0x1b, 1), F3(~3, ~0x1b, ~1)|SIMM13(~0), "[1]o,d", 0, v9 }, /* ld [rs1+0],d */ + +{ "st", F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|ASI(~0), "d,[1+2]", 0, v6 }, +{ "st", F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|ASI_RS2(~0), "d,[1]", 0, v6 }, /* st d,[rs1+%g0] */ +{ "st", F3(3, 0x04, 1), F3(~3, ~0x04, ~1), "d,[1+i]", 0, v6 }, +{ "st", F3(3, 0x04, 1), F3(~3, ~0x04, ~1), "d,[i+1]", 0, v6 }, +{ "st", F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|RS1_G0, "d,[i]", 0, v6 }, +{ "st", F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|SIMM13(~0), "d,[1]", 0, v6 }, /* st d,[rs1+0] */ +{ "st", F3(3, 0x24, 0), F3(~3, ~0x24, ~0)|ASI(~0), "g,[1+2]", 0, v6 }, +{ "st", F3(3, 0x24, 0), F3(~3, ~0x24, ~0)|ASI_RS2(~0), "g,[1]", 0, v6 }, /* st d[rs1+%g0] */ +{ "st", F3(3, 0x24, 1), F3(~3, ~0x24, ~1), "g,[1+i]", 0, v6 }, +{ "st", F3(3, 0x24, 1), F3(~3, ~0x24, ~1), "g,[i+1]", 0, v6 }, +{ "st", F3(3, 0x24, 1), F3(~3, ~0x24, ~1)|RS1_G0, "g,[i]", 0, v6 }, +{ "st", F3(3, 0x24, 1), F3(~3, ~0x24, ~1)|SIMM13(~0), "g,[1]", 0, v6 }, /* st d,[rs1+0] */ + +{ "st", F3(3, 0x34, 0), F3(~3, ~0x34, ~0)|ASI(~0), "D,[1+2]", 0, v6notv9 }, +{ "st", F3(3, 0x34, 0), F3(~3, ~0x34, ~0)|ASI_RS2(~0), "D,[1]", 0, v6notv9 }, /* st d,[rs1+%g0] */ +{ "st", F3(3, 0x34, 1), F3(~3, ~0x34, ~1), "D,[1+i]", 0, v6notv9 }, +{ "st", F3(3, 0x34, 1), F3(~3, ~0x34, ~1), "D,[i+1]", 0, v6notv9 }, +{ "st", F3(3, 0x34, 1), F3(~3, ~0x34, ~1)|RS1_G0, "D,[i]", 0, v6notv9 }, +{ "st", F3(3, 0x34, 1), F3(~3, ~0x34, ~1)|SIMM13(~0), "D,[1]", 0, v6notv9 }, /* st d,[rs1+0] */ +{ "st", F3(3, 0x35, 0), F3(~3, ~0x35, ~0)|ASI(~0), "C,[1+2]", 0, v6notv9 }, +{ "st", F3(3, 0x35, 0), F3(~3, ~0x35, ~0)|ASI_RS2(~0), "C,[1]", 0, v6notv9 }, /* st d,[rs1+%g0] */ +{ "st", F3(3, 0x35, 1), F3(~3, ~0x35, ~1), "C,[1+i]", 0, v6notv9 }, +{ "st", F3(3, 0x35, 1), F3(~3, ~0x35, ~1), "C,[i+1]", 0, v6notv9 }, +{ "st", F3(3, 0x35, 1), F3(~3, ~0x35, ~1)|RS1_G0, "C,[i]", 0, v6notv9 }, +{ "st", F3(3, 0x35, 1), F3(~3, ~0x35, ~1)|SIMM13(~0), "C,[1]", 0, v6notv9 }, /* st d,[rs1+0] */ + +{ "st", F3(3, 0x25, 0), F3(~3, ~0x25, ~0)|RD_G0|ASI(~0), "F,[1+2]", 0, v6 }, +{ "st", F3(3, 0x25, 0), F3(~3, ~0x25, ~0)|RD_G0|ASI_RS2(~0), "F,[1]", 0, v6 }, /* st d,[rs1+%g0] */ +{ "st", F3(3, 0x25, 1), F3(~3, ~0x25, ~1)|RD_G0, "F,[1+i]", 0, v6 }, +{ "st", F3(3, 0x25, 1), F3(~3, ~0x25, ~1)|RD_G0, "F,[i+1]", 0, v6 }, +{ "st", F3(3, 0x25, 1), F3(~3, ~0x25, ~1)|RD_G0|RS1_G0, "F,[i]", 0, v6 }, +{ "st", F3(3, 0x25, 1), F3(~3, ~0x25, ~1)|RD_G0|SIMM13(~0), "F,[1]", 0, v6 }, /* st d,[rs1+0] */ + +{ "stw", F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|ASI(~0), "d,[1+2]", F_ALIAS, v9 }, +{ "stw", F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|ASI_RS2(~0), "d,[1]", F_ALIAS, v9 }, /* st d,[rs1+%g0] */ +{ "stw", F3(3, 0x04, 1), F3(~3, ~0x04, ~1), "d,[1+i]", F_ALIAS, v9 }, +{ "stw", F3(3, 0x04, 1), F3(~3, ~0x04, ~1), "d,[i+1]", F_ALIAS, v9 }, +{ "stw", F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|RS1_G0, "d,[i]", F_ALIAS, v9 }, +{ "stw", F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|SIMM13(~0), "d,[1]", F_ALIAS, v9 }, /* st d,[rs1+0] */ + +{ "sta", F3(3, 0x14, 0), F3(~3, ~0x14, ~0), "d,[1+2]A", 0, v6 }, +{ "sta", F3(3, 0x14, 0), F3(~3, ~0x14, ~0)|RS2(~0), "d,[1]A", 0, v6 }, /* sta d,[rs1+%g0] */ +{ "sta", F3(3, 0x14, 1), F3(~3, ~0x14, ~1), "d,[1+i]o", 0, v9 }, +{ "sta", F3(3, 0x14, 1), F3(~3, ~0x14, ~1), "d,[i+1]o", 0, v9 }, +{ "sta", F3(3, 0x14, 1), F3(~3, ~0x14, ~1)|RS1_G0, "d,[i]o", 0, v9 }, +{ "sta", F3(3, 0x14, 1), F3(~3, ~0x14, ~1)|SIMM13(~0), "d,[1]o", 0, v9 }, /* st d,[rs1+0] */ + +{ "sta", F3(3, 0x34, 0), F3(~3, ~0x34, ~0), "g,[1+2]A", 0, v9 }, +{ "sta", F3(3, 0x34, 0), F3(~3, ~0x34, ~0)|RS2(~0), "g,[1]A", 0, v9 }, /* sta d,[rs1+%g0] */ +{ "sta", F3(3, 0x34, 1), F3(~3, ~0x34, ~1), "g,[1+i]o", 0, v9 }, +{ "sta", F3(3, 0x34, 1), F3(~3, ~0x34, ~1), "g,[i+1]o", 0, v9 }, +{ "sta", F3(3, 0x34, 1), F3(~3, ~0x34, ~1)|RS1_G0, "g,[i]o", 0, v9 }, +{ "sta", F3(3, 0x34, 1), F3(~3, ~0x34, ~1)|SIMM13(~0), "g,[1]o", 0, v9 }, /* st d,[rs1+0] */ + +{ "stwa", F3(3, 0x14, 0), F3(~3, ~0x14, ~0), "d,[1+2]A", F_ALIAS, v9 }, +{ "stwa", F3(3, 0x14, 0), F3(~3, ~0x14, ~0)|RS2(~0), "d,[1]A", F_ALIAS, v9 }, /* sta d,[rs1+%g0] */ +{ "stwa", F3(3, 0x14, 1), F3(~3, ~0x14, ~1), "d,[1+i]o", F_ALIAS, v9 }, +{ "stwa", F3(3, 0x14, 1), F3(~3, ~0x14, ~1), "d,[i+1]o", F_ALIAS, v9 }, +{ "stwa", F3(3, 0x14, 1), F3(~3, ~0x14, ~1)|RS1_G0, "d,[i]o", F_ALIAS, v9 }, +{ "stwa", F3(3, 0x14, 1), F3(~3, ~0x14, ~1)|SIMM13(~0), "d,[1]o", F_ALIAS, v9 }, /* st d,[rs1+0] */ + +{ "stb", F3(3, 0x05, 0), F3(~3, ~0x05, ~0)|ASI(~0), "d,[1+2]", 0, v6 }, +{ "stb", F3(3, 0x05, 0), F3(~3, ~0x05, ~0)|ASI_RS2(~0), "d,[1]", 0, v6 }, /* stb d,[rs1+%g0] */ +{ "stb", F3(3, 0x05, 1), F3(~3, ~0x05, ~1), "d,[1+i]", 0, v6 }, +{ "stb", F3(3, 0x05, 1), F3(~3, ~0x05, ~1), "d,[i+1]", 0, v6 }, +{ "stb", F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|RS1_G0, "d,[i]", 0, v6 }, +{ "stb", F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|SIMM13(~0), "d,[1]", 0, v6 }, /* stb d,[rs1+0] */ + +{ "stba", F3(3, 0x15, 0), F3(~3, ~0x15, ~0), "d,[1+2]A", 0, v6 }, +{ "stba", F3(3, 0x15, 0), F3(~3, ~0x15, ~0)|RS2(~0), "d,[1]A", 0, v6 }, /* stba d,[rs1+%g0] */ +{ "stba", F3(3, 0x15, 1), F3(~3, ~0x15, ~1), "d,[1+i]o", 0, v9 }, +{ "stba", F3(3, 0x15, 1), F3(~3, ~0x15, ~1), "d,[i+1]o", 0, v9 }, +{ "stba", F3(3, 0x15, 1), F3(~3, ~0x15, ~1)|RS1_G0, "d,[i]o", 0, v9 }, +{ "stba", F3(3, 0x15, 1), F3(~3, ~0x15, ~1)|SIMM13(~0), "d,[1]o", 0, v9 }, /* stb d,[rs1+0] */ + +{ "std", F3(3, 0x07, 0), F3(~3, ~0x07, ~0)|ASI(~0), "d,[1+2]", 0, v6 }, +{ "std", F3(3, 0x07, 0), F3(~3, ~0x07, ~0)|ASI_RS2(~0), "d,[1]", 0, v6 }, /* std d,[rs1+%g0] */ +{ "std", F3(3, 0x07, 1), F3(~3, ~0x07, ~1), "d,[1+i]", 0, v6 }, +{ "std", F3(3, 0x07, 1), F3(~3, ~0x07, ~1), "d,[i+1]", 0, v6 }, +{ "std", F3(3, 0x07, 1), F3(~3, ~0x07, ~1)|RS1_G0, "d,[i]", 0, v6 }, +{ "std", F3(3, 0x07, 1), F3(~3, ~0x07, ~1)|SIMM13(~0), "d,[1]", 0, v6 }, /* std d,[rs1+0] */ + +{ "std", F3(3, 0x26, 0), F3(~3, ~0x26, ~0)|ASI(~0), "q,[1+2]", 0, v6notv9 }, +{ "std", F3(3, 0x26, 0), F3(~3, ~0x26, ~0)|ASI_RS2(~0), "q,[1]", 0, v6notv9 }, /* std d,[rs1+%g0] */ +{ "std", F3(3, 0x26, 1), F3(~3, ~0x26, ~1), "q,[1+i]", 0, v6notv9 }, +{ "std", F3(3, 0x26, 1), F3(~3, ~0x26, ~1), "q,[i+1]", 0, v6notv9 }, +{ "std", F3(3, 0x26, 1), F3(~3, ~0x26, ~1)|RS1_G0, "q,[i]", 0, v6notv9 }, +{ "std", F3(3, 0x26, 1), F3(~3, ~0x26, ~1)|SIMM13(~0), "q,[1]", 0, v6notv9 }, /* std d,[rs1+0] */ +{ "std", F3(3, 0x27, 0), F3(~3, ~0x27, ~0)|ASI(~0), "H,[1+2]", 0, v6 }, +{ "std", F3(3, 0x27, 0), F3(~3, ~0x27, ~0)|ASI_RS2(~0), "H,[1]", 0, v6 }, /* std d,[rs1+%g0] */ +{ "std", F3(3, 0x27, 1), F3(~3, ~0x27, ~1), "H,[1+i]", 0, v6 }, +{ "std", F3(3, 0x27, 1), F3(~3, ~0x27, ~1), "H,[i+1]", 0, v6 }, +{ "std", F3(3, 0x27, 1), F3(~3, ~0x27, ~1)|RS1_G0, "H,[i]", 0, v6 }, +{ "std", F3(3, 0x27, 1), F3(~3, ~0x27, ~1)|SIMM13(~0), "H,[1]", 0, v6 }, /* std d,[rs1+0] */ + +{ "std", F3(3, 0x36, 0), F3(~3, ~0x36, ~0)|ASI(~0), "Q,[1+2]", 0, v6notv9 }, +{ "std", F3(3, 0x36, 0), F3(~3, ~0x36, ~0)|ASI_RS2(~0), "Q,[1]", 0, v6notv9 }, /* std d,[rs1+%g0] */ +{ "std", F3(3, 0x36, 1), F3(~3, ~0x36, ~1), "Q,[1+i]", 0, v6notv9 }, +{ "std", F3(3, 0x36, 1), F3(~3, ~0x36, ~1), "Q,[i+1]", 0, v6notv9 }, +{ "std", F3(3, 0x36, 1), F3(~3, ~0x36, ~1)|RS1_G0, "Q,[i]", 0, v6notv9 }, +{ "std", F3(3, 0x36, 1), F3(~3, ~0x36, ~1)|SIMM13(~0), "Q,[1]", 0, v6notv9 }, /* std d,[rs1+0] */ +{ "std", F3(3, 0x37, 0), F3(~3, ~0x37, ~0)|ASI(~0), "D,[1+2]", 0, v6notv9 }, +{ "std", F3(3, 0x37, 0), F3(~3, ~0x37, ~0)|ASI_RS2(~0), "D,[1]", 0, v6notv9 }, /* std d,[rs1+%g0] */ +{ "std", F3(3, 0x37, 1), F3(~3, ~0x37, ~1), "D,[1+i]", 0, v6notv9 }, +{ "std", F3(3, 0x37, 1), F3(~3, ~0x37, ~1), "D,[i+1]", 0, v6notv9 }, +{ "std", F3(3, 0x37, 1), F3(~3, ~0x37, ~1)|RS1_G0, "D,[i]", 0, v6notv9 }, +{ "std", F3(3, 0x37, 1), F3(~3, ~0x37, ~1)|SIMM13(~0), "D,[1]", 0, v6notv9 }, /* std d,[rs1+0] */ + +{ "stda", F3(3, 0x17, 0), F3(~3, ~0x17, ~0), "d,[1+2]A", 0, v6 }, +{ "stda", F3(3, 0x17, 0), F3(~3, ~0x17, ~0)|RS2(~0), "d,[1]A", 0, v6 }, /* stda d,[rs1+%g0] */ +{ "stda", F3(3, 0x17, 1), F3(~3, ~0x17, ~1), "d,[1+i]o", 0, v9 }, +{ "stda", F3(3, 0x17, 1), F3(~3, ~0x17, ~1), "d,[i+1]o", 0, v9 }, +{ "stda", F3(3, 0x17, 1), F3(~3, ~0x17, ~1)|RS1_G0, "d,[i]o", 0, v9 }, +{ "stda", F3(3, 0x17, 1), F3(~3, ~0x17, ~1)|SIMM13(~0), "d,[1]o", 0, v9 }, /* std d,[rs1+0] */ +{ "stda", F3(3, 0x37, 0), F3(~3, ~0x37, ~0), "H,[1+2]A", 0, v9 }, +{ "stda", F3(3, 0x37, 0), F3(~3, ~0x37, ~0)|RS2(~0), "H,[1]A", 0, v9 }, /* stda d,[rs1+%g0] */ +{ "stda", F3(3, 0x37, 1), F3(~3, ~0x37, ~1), "H,[1+i]o", 0, v9 }, +{ "stda", F3(3, 0x37, 1), F3(~3, ~0x37, ~1), "H,[i+1]o", 0, v9 }, +{ "stda", F3(3, 0x37, 1), F3(~3, ~0x37, ~1)|RS1_G0, "H,[i]o", 0, v9 }, +{ "stda", F3(3, 0x37, 1), F3(~3, ~0x37, ~1)|SIMM13(~0), "H,[1]o", 0, v9 }, /* std d,[rs1+0] */ + +{ "sth", F3(3, 0x06, 0), F3(~3, ~0x06, ~0)|ASI(~0), "d,[1+2]", 0, v6 }, +{ "sth", F3(3, 0x06, 0), F3(~3, ~0x06, ~0)|ASI_RS2(~0), "d,[1]", 0, v6 }, /* sth d,[rs1+%g0] */ +{ "sth", F3(3, 0x06, 1), F3(~3, ~0x06, ~1), "d,[1+i]", 0, v6 }, +{ "sth", F3(3, 0x06, 1), F3(~3, ~0x06, ~1), "d,[i+1]", 0, v6 }, +{ "sth", F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|RS1_G0, "d,[i]", 0, v6 }, +{ "sth", F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|SIMM13(~0), "d,[1]", 0, v6 }, /* sth d,[rs1+0] */ + +{ "stha", F3(3, 0x16, 0), F3(~3, ~0x16, ~0), "d,[1+2]A", 0, v6 }, +{ "stha", F3(3, 0x16, 0), F3(~3, ~0x16, ~0)|RS2(~0), "d,[1]A", 0, v6 }, /* stha ,[rs1+%g0] */ +{ "stha", F3(3, 0x16, 1), F3(~3, ~0x16, ~1), "d,[1+i]o", 0, v9 }, +{ "stha", F3(3, 0x16, 1), F3(~3, ~0x16, ~1), "d,[i+1]o", 0, v9 }, +{ "stha", F3(3, 0x16, 1), F3(~3, ~0x16, ~1)|RS1_G0, "d,[i]o", 0, v9 }, +{ "stha", F3(3, 0x16, 1), F3(~3, ~0x16, ~1)|SIMM13(~0), "d,[1]o", 0, v9 }, /* sth d,[rs1+0] */ + +{ "stx", F3(3, 0x0e, 0), F3(~3, ~0x0e, ~0)|ASI(~0), "d,[1+2]", 0, v9 }, +{ "stx", F3(3, 0x0e, 0), F3(~3, ~0x0e, ~0)|ASI_RS2(~0), "d,[1]", 0, v9 }, /* stx d,[rs1+%g0] */ +{ "stx", F3(3, 0x0e, 1), F3(~3, ~0x0e, ~1), "d,[1+i]", 0, v9 }, +{ "stx", F3(3, 0x0e, 1), F3(~3, ~0x0e, ~1), "d,[i+1]", 0, v9 }, +{ "stx", F3(3, 0x0e, 1), F3(~3, ~0x0e, ~1)|RS1_G0, "d,[i]", 0, v9 }, +{ "stx", F3(3, 0x0e, 1), F3(~3, ~0x0e, ~1)|SIMM13(~0), "d,[1]", 0, v9 }, /* stx d,[rs1+0] */ + +{ "stx", F3(3, 0x25, 0)|RD(1), F3(~3, ~0x25, ~0)|ASI(~0)|RD(~1), "F,[1+2]", 0, v9 }, +{ "stx", F3(3, 0x25, 0)|RD(1), F3(~3, ~0x25, ~0)|ASI_RS2(~0)|RD(~1),"F,[1]", 0, v9 }, /* stx d,[rs1+%g0] */ +{ "stx", F3(3, 0x25, 1)|RD(1), F3(~3, ~0x25, ~1)|RD(~1), "F,[1+i]", 0, v9 }, +{ "stx", F3(3, 0x25, 1)|RD(1), F3(~3, ~0x25, ~1)|RD(~1), "F,[i+1]", 0, v9 }, +{ "stx", F3(3, 0x25, 1)|RD(1), F3(~3, ~0x25, ~1)|RS1_G0|RD(~1), "F,[i]", 0, v9 }, +{ "stx", F3(3, 0x25, 1)|RD(1), F3(~3, ~0x25, ~1)|SIMM13(~0)|RD(~1),"F,[1]", 0, v9 }, /* stx d,[rs1+0] */ + +{ "stxa", F3(3, 0x1e, 0), F3(~3, ~0x1e, ~0), "d,[1+2]A", 0, v9 }, +{ "stxa", F3(3, 0x1e, 0), F3(~3, ~0x1e, ~0)|RS2(~0), "d,[1]A", 0, v9 }, /* stxa d,[rs1+%g0] */ +{ "stxa", F3(3, 0x1e, 1), F3(~3, ~0x1e, ~1), "d,[1+i]o", 0, v9 }, +{ "stxa", F3(3, 0x1e, 1), F3(~3, ~0x1e, ~1), "d,[i+1]o", 0, v9 }, +{ "stxa", F3(3, 0x1e, 1), F3(~3, ~0x1e, ~1)|RS1_G0, "d,[i]o", 0, v9 }, +{ "stxa", F3(3, 0x1e, 1), F3(~3, ~0x1e, ~1)|SIMM13(~0), "d,[1]o", 0, v9 }, /* stx d,[rs1+0] */ + +{ "stq", F3(3, 0x26, 0), F3(~3, ~0x26, ~0)|ASI(~0), "J,[1+2]", 0, v9 }, +{ "stq", F3(3, 0x26, 0), F3(~3, ~0x26, ~0)|ASI_RS2(~0), "J,[1]", 0, v9 }, /* stq [rs1+%g0] */ +{ "stq", F3(3, 0x26, 1), F3(~3, ~0x26, ~1), "J,[1+i]", 0, v9 }, +{ "stq", F3(3, 0x26, 1), F3(~3, ~0x26, ~1), "J,[i+1]", 0, v9 }, +{ "stq", F3(3, 0x26, 1), F3(~3, ~0x26, ~1)|RS1_G0, "J,[i]", 0, v9 }, +{ "stq", F3(3, 0x26, 1), F3(~3, ~0x26, ~1)|SIMM13(~0), "J,[1]", 0, v9 }, /* stq [rs1+0] */ + +{ "stqa", F3(3, 0x36, 0), F3(~3, ~0x36, ~0)|ASI(~0), "J,[1+2]A", 0, v9 }, +{ "stqa", F3(3, 0x36, 0), F3(~3, ~0x36, ~0)|ASI_RS2(~0), "J,[1]A", 0, v9 }, /* stqa [rs1+%g0] */ +{ "stqa", F3(3, 0x36, 1), F3(~3, ~0x36, ~1), "J,[1+i]o", 0, v9 }, +{ "stqa", F3(3, 0x36, 1), F3(~3, ~0x36, ~1), "J,[i+1]o", 0, v9 }, +{ "stqa", F3(3, 0x36, 1), F3(~3, ~0x36, ~1)|RS1_G0, "J,[i]o", 0, v9 }, +{ "stqa", F3(3, 0x36, 1), F3(~3, ~0x36, ~1)|SIMM13(~0), "J,[1]o", 0, v9 }, /* stqa [rs1+0] */ + +{ "swap", F3(3, 0x0f, 0), F3(~3, ~0x0f, ~0)|ASI(~0), "[1+2],d", 0, v7 }, +{ "swap", F3(3, 0x0f, 0), F3(~3, ~0x0f, ~0)|ASI_RS2(~0), "[1],d", 0, v7 }, /* swap [rs1+%g0],d */ +{ "swap", F3(3, 0x0f, 1), F3(~3, ~0x0f, ~1), "[1+i],d", 0, v7 }, +{ "swap", F3(3, 0x0f, 1), F3(~3, ~0x0f, ~1), "[i+1],d", 0, v7 }, +{ "swap", F3(3, 0x0f, 1), F3(~3, ~0x0f, ~1)|RS1_G0, "[i],d", 0, v7 }, +{ "swap", F3(3, 0x0f, 1), F3(~3, ~0x0f, ~1)|SIMM13(~0), "[1],d", 0, v7 }, /* swap [rs1+0],d */ + +{ "swapa", F3(3, 0x1f, 0), F3(~3, ~0x1f, ~0), "[1+2]A,d", 0, v7 }, +{ "swapa", F3(3, 0x1f, 0), F3(~3, ~0x1f, ~0)|RS2(~0), "[1]A,d", 0, v7 }, /* swapa [rs1+%g0],d */ +{ "swapa", F3(3, 0x1f, 1), F3(~3, ~0x1f, ~1), "[1+i]o,d", 0, v9 }, +{ "swapa", F3(3, 0x1f, 1), F3(~3, ~0x1f, ~1), "[i+1]o,d", 0, v9 }, +{ "swapa", F3(3, 0x1f, 1), F3(~3, ~0x1f, ~1)|RS1_G0, "[i]o,d", 0, v9 }, +{ "swapa", F3(3, 0x1f, 1), F3(~3, ~0x1f, ~1)|SIMM13(~0), "[1]o,d", 0, v9 }, /* swap [rs1+0],d */ + +{ "restore", F3(2, 0x3d, 0), F3(~2, ~0x3d, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "restore", F3(2, 0x3d, 0), F3(~2, ~0x3d, ~0)|RD_G0|RS1_G0|ASI_RS2(~0), "", 0, v6 }, /* restore %g0,%g0,%g0 */ +{ "restore", F3(2, 0x3d, 1), F3(~2, ~0x3d, ~1), "1,i,d", 0, v6 }, +{ "restore", F3(2, 0x3d, 1), F3(~2, ~0x3d, ~1)|RD_G0|RS1_G0|SIMM13(~0), "", 0, v6 }, /* restore %g0,0,%g0 */ + +{ "rett", F3(2, 0x39, 0), F3(~2, ~0x39, ~0)|RD_G0|ASI(~0), "1+2", F_UNBR|F_DELAYED, v6 }, /* rett rs1+rs2 */ +{ "rett", F3(2, 0x39, 0), F3(~2, ~0x39, ~0)|RD_G0|ASI_RS2(~0), "1", F_UNBR|F_DELAYED, v6 }, /* rett rs1,%g0 */ +{ "rett", F3(2, 0x39, 1), F3(~2, ~0x39, ~1)|RD_G0, "1+i", F_UNBR|F_DELAYED, v6 }, /* rett rs1+X */ +{ "rett", F3(2, 0x39, 1), F3(~2, ~0x39, ~1)|RD_G0, "i+1", F_UNBR|F_DELAYED, v6 }, /* rett X+rs1 */ +{ "rett", F3(2, 0x39, 1), F3(~2, ~0x39, ~1)|RD_G0|RS1_G0, "i", F_UNBR|F_DELAYED, v6 }, /* rett X+rs1 */ +{ "rett", F3(2, 0x39, 1), F3(~2, ~0x39, ~1)|RD_G0|RS1_G0, "i", F_UNBR|F_DELAYED, v6 }, /* rett X */ +{ "rett", F3(2, 0x39, 1), F3(~2, ~0x39, ~1)|RD_G0|SIMM13(~0), "1", F_UNBR|F_DELAYED, v6 }, /* rett rs1+0 */ + +{ "save", F3(2, 0x3c, 0), F3(~2, ~0x3c, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "save", F3(2, 0x3c, 1), F3(~2, ~0x3c, ~1), "1,i,d", 0, v6 }, +{ "save", 0x81e00000, ~0x81e00000, "", F_ALIAS, v6 }, + +{ "ret", F3(2, 0x38, 1)|RS1(0x1f)|SIMM13(8), F3(~2, ~0x38, ~1)|SIMM13(~8), "", F_UNBR|F_DELAYED, v6 }, /* jmpl %i7+8,%g0 */ +{ "retl", F3(2, 0x38, 1)|RS1(0x0f)|SIMM13(8), F3(~2, ~0x38, ~1)|RS1(~0x0f)|SIMM13(~8), "", F_UNBR|F_DELAYED, v6 }, /* jmpl %o7+8,%g0 */ + +{ "jmpl", F3(2, 0x38, 0), F3(~2, ~0x38, ~0)|ASI(~0), "1+2,d", F_JSR|F_DELAYED, v6 }, +{ "jmpl", F3(2, 0x38, 0), F3(~2, ~0x38, ~0)|ASI_RS2(~0), "1,d", F_JSR|F_DELAYED, v6 }, /* jmpl rs1+%g0,d */ +{ "jmpl", F3(2, 0x38, 1), F3(~2, ~0x38, ~1)|SIMM13(~0), "1,d", F_JSR|F_DELAYED, v6 }, /* jmpl rs1+0,d */ +{ "jmpl", F3(2, 0x38, 1), F3(~2, ~0x38, ~1)|RS1_G0, "i,d", F_JSR|F_DELAYED, v6 }, /* jmpl %g0+i,d */ +{ "jmpl", F3(2, 0x38, 1), F3(~2, ~0x38, ~1), "1+i,d", F_JSR|F_DELAYED, v6 }, +{ "jmpl", F3(2, 0x38, 1), F3(~2, ~0x38, ~1), "i+1,d", F_JSR|F_DELAYED, v6 }, + +{ "done", F3(2, 0x3e, 0)|RD(0), F3(~2, ~0x3e, ~0)|RD(~0)|RS1_G0|SIMM13(~0), "", 0, v9 }, +{ "retry", F3(2, 0x3e, 0)|RD(1), F3(~2, ~0x3e, ~0)|RD(~1)|RS1_G0|SIMM13(~0), "", 0, v9 }, +{ "saved", F3(2, 0x31, 0)|RD(0), F3(~2, ~0x31, ~0)|RD(~0)|RS1_G0|SIMM13(~0), "", 0, v9 }, +{ "restored", F3(2, 0x31, 0)|RD(1), F3(~2, ~0x31, ~0)|RD(~1)|RS1_G0|SIMM13(~0), "", 0, v9 }, +{ "sir", F3(2, 0x30, 1)|RD(0xf), F3(~2, ~0x30, ~1)|RD(~0xf)|RS1_G0, "i", 0, v9 }, + +{ "flush", F3(2, 0x3b, 0), F3(~2, ~0x3b, ~0)|ASI(~0), "1+2", 0, v8 }, +{ "flush", F3(2, 0x3b, 0), F3(~2, ~0x3b, ~0)|ASI_RS2(~0), "1", 0, v8 }, /* flush rs1+%g0 */ +{ "flush", F3(2, 0x3b, 1), F3(~2, ~0x3b, ~1)|SIMM13(~0), "1", 0, v8 }, /* flush rs1+0 */ +{ "flush", F3(2, 0x3b, 1), F3(~2, ~0x3b, ~1)|RS1_G0, "i", 0, v8 }, /* flush %g0+i */ +{ "flush", F3(2, 0x3b, 1), F3(~2, ~0x3b, ~1), "1+i", 0, v8 }, +{ "flush", F3(2, 0x3b, 1), F3(~2, ~0x3b, ~1), "i+1", 0, v8 }, + +/* IFLUSH was renamed to FLUSH in v8. */ +{ "iflush", F3(2, 0x3b, 0), F3(~2, ~0x3b, ~0)|ASI(~0), "1+2", F_ALIAS, v6 }, +{ "iflush", F3(2, 0x3b, 0), F3(~2, ~0x3b, ~0)|ASI_RS2(~0), "1", F_ALIAS, v6 }, /* flush rs1+%g0 */ +{ "iflush", F3(2, 0x3b, 1), F3(~2, ~0x3b, ~1)|SIMM13(~0), "1", F_ALIAS, v6 }, /* flush rs1+0 */ +{ "iflush", F3(2, 0x3b, 1), F3(~2, ~0x3b, ~1)|RS1_G0, "i", F_ALIAS, v6 }, +{ "iflush", F3(2, 0x3b, 1), F3(~2, ~0x3b, ~1), "1+i", F_ALIAS, v6 }, +{ "iflush", F3(2, 0x3b, 1), F3(~2, ~0x3b, ~1), "i+1", F_ALIAS, v6 }, + +{ "return", F3(2, 0x39, 0), F3(~2, ~0x39, ~0)|ASI(~0), "1+2", 0, v9 }, +{ "return", F3(2, 0x39, 0), F3(~2, ~0x39, ~0)|ASI_RS2(~0), "1", 0, v9 }, /* return rs1+%g0 */ +{ "return", F3(2, 0x39, 1), F3(~2, ~0x39, ~1)|SIMM13(~0), "1", 0, v9 }, /* return rs1+0 */ +{ "return", F3(2, 0x39, 1), F3(~2, ~0x39, ~1)|RS1_G0, "i", 0, v9 }, /* return %g0+i */ +{ "return", F3(2, 0x39, 1), F3(~2, ~0x39, ~1), "1+i", 0, v9 }, +{ "return", F3(2, 0x39, 1), F3(~2, ~0x39, ~1), "i+1", 0, v9 }, + +{ "flushw", F3(2, 0x2b, 0), F3(~2, ~0x2b, ~0)|RD_G0|RS1_G0|ASI_RS2(~0), "", 0, v9 }, + +{ "membar", F3(2, 0x28, 1)|RS1(0xf), F3(~2, ~0x28, ~1)|RD_G0|RS1(~0xf)|SIMM13(~127), "K", 0, v9 }, +{ "stbar", F3(2, 0x28, 0)|RS1(0xf), F3(~2, ~0x28, ~0)|RD_G0|RS1(~0xf)|SIMM13(~0), "", 0, v8 }, + +{ "prefetch", F3(3, 0x2d, 0), F3(~3, ~0x2d, ~0), "[1+2],*", 0, v9 }, +{ "prefetch", F3(3, 0x2d, 0), F3(~3, ~0x2d, ~0)|RS2_G0, "[1],*", 0, v9 }, /* prefetch [rs1+%g0],prefetch_fcn */ +{ "prefetch", F3(3, 0x2d, 1), F3(~3, ~0x2d, ~1), "[1+i],*", 0, v9 }, +{ "prefetch", F3(3, 0x2d, 1), F3(~3, ~0x2d, ~1), "[i+1],*", 0, v9 }, +{ "prefetch", F3(3, 0x2d, 1), F3(~3, ~0x2d, ~1)|RS1_G0, "[i],*", 0, v9 }, +{ "prefetch", F3(3, 0x2d, 1), F3(~3, ~0x2d, ~1)|SIMM13(~0), "[1],*", 0, v9 }, /* prefetch [rs1+0],prefetch_fcn */ +{ "prefetcha", F3(3, 0x3d, 0), F3(~3, ~0x3d, ~0), "[1+2]A,*", 0, v9 }, +{ "prefetcha", F3(3, 0x3d, 0), F3(~3, ~0x3d, ~0)|RS2_G0, "[1]A,*", 0, v9 }, /* prefetcha [rs1+%g0],prefetch_fcn */ +{ "prefetcha", F3(3, 0x3d, 1), F3(~3, ~0x3d, ~1), "[1+i]o,*", 0, v9 }, +{ "prefetcha", F3(3, 0x3d, 1), F3(~3, ~0x3d, ~1), "[i+1]o,*", 0, v9 }, +{ "prefetcha", F3(3, 0x3d, 1), F3(~3, ~0x3d, ~1)|RS1_G0, "[i]o,*", 0, v9 }, +{ "prefetcha", F3(3, 0x3d, 1), F3(~3, ~0x3d, ~1)|SIMM13(~0), "[1]o,*", 0, v9 }, /* prefetcha [rs1+0],d */ + + /* The 1<<12 is a long story. It is necessary. For more info, please contact rich@cygnus.com */ + /* FIXME: 'i' is wrong, need new letter for 5 bit unsigned constants. */ +{ "sll", F3(2, 0x25, 0), F3(~2, ~0x25, ~0)|(1<<12)|ASI(~0), "1,2,d", 0, v6 }, +{ "sll", F3(2, 0x25, 1), F3(~2, ~0x25, ~1)|(1<<12), "1,i,d", 0, v6 }, +{ "sra", F3(2, 0x27, 0), F3(~2, ~0x27, ~0)|(1<<12)|ASI(~0), "1,2,d", 0, v6 }, +{ "sra", F3(2, 0x27, 1), F3(~2, ~0x27, ~1)|(1<<12), "1,i,d", 0, v6 }, +{ "srl", F3(2, 0x26, 0), F3(~2, ~0x26, ~0)|(1<<12)|ASI(~0), "1,2,d", 0, v6 }, +{ "srl", F3(2, 0x26, 1), F3(~2, ~0x26, ~1)|(1<<12), "1,i,d", 0, v6 }, + + /* FIXME: 'j' is wrong, need new letter for 6 bit unsigned constants. */ +{ "sllx", F3(2, 0x25, 0)|(1<<12), F3(~2, ~0x25, ~0)|(ASI(~0)^(1<<12)), "1,2,d", 0, v9 }, +{ "sllx", F3(2, 0x25, 1)|(1<<12), F3(~2, ~0x25, ~1)|(0x3f<<6), "1,j,d", 0, v9 }, +{ "srax", F3(2, 0x27, 0)|(1<<12), F3(~2, ~0x27, ~0)|(ASI(~0)^(1<<12)), "1,2,d", 0, v9 }, +{ "srax", F3(2, 0x27, 1)|(1<<12), F3(~2, ~0x27, ~1)|(0x3f<<6), "1,j,d", 0, v9 }, +{ "srlx", F3(2, 0x26, 0)|(1<<12), F3(~2, ~0x26, ~0)|(ASI(~0)^(1<<12)), "1,2,d", 0, v9 }, +{ "srlx", F3(2, 0x26, 1)|(1<<12), F3(~2, ~0x26, ~1)|(0x3f<<6), "1,j,d", 0, v9 }, + +{ "mulscc", F3(2, 0x24, 0), F3(~2, ~0x24, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "mulscc", F3(2, 0x24, 1), F3(~2, ~0x24, ~1), "1,i,d", 0, v6 }, + +{ "divscc", F3(2, 0x1d, 0), F3(~2, ~0x1d, ~0)|ASI(~0), "1,2,d", 0, sparclite }, +{ "divscc", F3(2, 0x1d, 1), F3(~2, ~0x1d, ~1), "1,i,d", 0, sparclite }, + +{ "scan", F3(2, 0x2c, 0), F3(~2, ~0x2c, ~0)|ASI(~0), "1,2,d", 0, sparclet|sparclite }, +{ "scan", F3(2, 0x2c, 1), F3(~2, ~0x2c, ~1), "1,i,d", 0, sparclet|sparclite }, + +{ "popc", F3(2, 0x2e, 0), F3(~2, ~0x2e, ~0)|RS2_G0|ASI(~0),"2,d", 0, v9 }, +{ "popc", F3(2, 0x2e, 1), F3(~2, ~0x2e, ~1)|RS2_G0, "i,d", 0, v9 }, + +{ "clr", F3(2, 0x02, 0), F3(~2, ~0x02, ~0)|RD_G0|RS1_G0|ASI_RS2(~0), "d", F_ALIAS, v6 }, /* or %g0,%g0,d */ +{ "clr", F3(2, 0x02, 1), F3(~2, ~0x02, ~1)|RS1_G0|SIMM13(~0), "d", F_ALIAS, v6 }, /* or %g0,0,d */ +{ "clr", F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|RD_G0|ASI(~0), "[1+2]", F_ALIAS, v6 }, +{ "clr", F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|RD_G0|ASI_RS2(~0), "[1]", F_ALIAS, v6 }, /* st %g0,[rs1+%g0] */ +{ "clr", F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|RD_G0, "[1+i]", F_ALIAS, v6 }, +{ "clr", F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|RD_G0, "[i+1]", F_ALIAS, v6 }, +{ "clr", F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|RD_G0|RS1_G0, "[i]", F_ALIAS, v6 }, +{ "clr", F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|RD_G0|SIMM13(~0), "[1]", F_ALIAS, v6 }, /* st %g0,[rs1+0] */ + +{ "clrb", F3(3, 0x05, 0), F3(~3, ~0x05, ~0)|RD_G0|ASI(~0), "[1+2]", F_ALIAS, v6 }, +{ "clrb", F3(3, 0x05, 0), F3(~3, ~0x05, ~0)|RD_G0|ASI_RS2(~0), "[1]", F_ALIAS, v6 }, /* stb %g0,[rs1+%g0] */ +{ "clrb", F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|RD_G0, "[1+i]", F_ALIAS, v6 }, +{ "clrb", F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|RD_G0, "[i+1]", F_ALIAS, v6 }, +{ "clrb", F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|RD_G0|RS1_G0, "[i]", F_ALIAS, v6 }, +{ "clrb", F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|RD_G0|SIMM13(~0), "[1]", F_ALIAS, v6 }, /* stb %g0,[rs1+0] */ + +{ "clrh", F3(3, 0x06, 0), F3(~3, ~0x06, ~0)|RD_G0|ASI(~0), "[1+2]", F_ALIAS, v6 }, +{ "clrh", F3(3, 0x06, 0), F3(~3, ~0x06, ~0)|RD_G0|ASI_RS2(~0), "[1]", F_ALIAS, v6 }, /* sth %g0,[rs1+%g0] */ +{ "clrh", F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|RD_G0, "[1+i]", F_ALIAS, v6 }, +{ "clrh", F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|RD_G0, "[i+1]", F_ALIAS, v6 }, +{ "clrh", F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|RD_G0|RS1_G0, "[i]", F_ALIAS, v6 }, +{ "clrh", F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|RD_G0|SIMM13(~0), "[1]", F_ALIAS, v6 }, /* sth %g0,[rs1+0] */ + +{ "clrx", F3(3, 0x0e, 0), F3(~3, ~0x0e, ~0)|RD_G0|ASI(~0), "[1+2]", F_ALIAS, v9 }, +{ "clrx", F3(3, 0x0e, 0), F3(~3, ~0x0e, ~0)|RD_G0|ASI_RS2(~0), "[1]", F_ALIAS, v9 }, /* stx %g0,[rs1+%g0] */ +{ "clrx", F3(3, 0x0e, 1), F3(~3, ~0x0e, ~1)|RD_G0, "[1+i]", F_ALIAS, v9 }, +{ "clrx", F3(3, 0x0e, 1), F3(~3, ~0x0e, ~1)|RD_G0, "[i+1]", F_ALIAS, v9 }, +{ "clrx", F3(3, 0x0e, 1), F3(~3, ~0x0e, ~1)|RD_G0|RS1_G0, "[i]", F_ALIAS, v9 }, +{ "clrx", F3(3, 0x0e, 1), F3(~3, ~0x0e, ~1)|RD_G0|SIMM13(~0), "[1]", F_ALIAS, v9 }, /* stx %g0,[rs1+0] */ + +{ "orcc", F3(2, 0x12, 0), F3(~2, ~0x12, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "orcc", F3(2, 0x12, 1), F3(~2, ~0x12, ~1), "1,i,d", 0, v6 }, +{ "orcc", F3(2, 0x12, 1), F3(~2, ~0x12, ~1), "i,1,d", 0, v6 }, + +/* This is not a commutative instruction. */ +{ "orncc", F3(2, 0x16, 0), F3(~2, ~0x16, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "orncc", F3(2, 0x16, 1), F3(~2, ~0x16, ~1), "1,i,d", 0, v6 }, + +/* This is not a commutative instruction. */ +{ "orn", F3(2, 0x06, 0), F3(~2, ~0x06, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "orn", F3(2, 0x06, 1), F3(~2, ~0x06, ~1), "1,i,d", 0, v6 }, + +{ "tst", F3(2, 0x12, 0), F3(~2, ~0x12, ~0)|RD_G0|ASI_RS2(~0), "1", 0, v6 }, /* orcc rs1, %g0, %g0 */ +{ "tst", F3(2, 0x12, 0), F3(~2, ~0x12, ~0)|RD_G0|RS1_G0|ASI(~0), "2", 0, v6 }, /* orcc %g0, rs2, %g0 */ +{ "tst", F3(2, 0x12, 1), F3(~2, ~0x12, ~1)|RD_G0|SIMM13(~0), "1", 0, v6 }, /* orcc rs1, 0, %g0 */ + +{ "wr", F3(2, 0x30, 0), F3(~2, ~0x30, ~0)|ASI(~0), "1,2,m", 0, v8 }, /* wr r,r,%asrX */ +{ "wr", F3(2, 0x30, 0), F3(~2, ~0x30, ~0)|RD_G0|ASI(~0), "1,2,y", 0, v6 }, /* wr r,r,%y */ +{ "wr", F3(2, 0x30, 1), F3(~2, ~0x30, ~1), "1,i,m", 0, v8 }, /* wr r,i,%asrX */ +{ "wr", F3(2, 0x30, 1), F3(~2, ~0x30, ~1)|RD_G0, "1,i,y", 0, v6 }, /* wr r,i,%y */ +{ "wr", F3(2, 0x31, 0), F3(~2, ~0x31, ~0)|RD_G0|ASI(~0), "1,2,p", 0, v6notv9 }, /* wr r,r,%psr */ +{ "wr", F3(2, 0x31, 1), F3(~2, ~0x31, ~1)|RD_G0, "1,i,p", 0, v6notv9 }, /* wr r,i,%psr */ +{ "wr", F3(2, 0x32, 0), F3(~2, ~0x32, ~0)|RD_G0|ASI(~0), "1,2,w", 0, v6notv9 }, /* wr r,r,%wim */ +{ "wr", F3(2, 0x32, 1), F3(~2, ~0x32, ~1)|RD_G0, "1,i,w", 0, v6notv9 }, /* wr r,i,%wim */ +{ "wr", F3(2, 0x33, 0), F3(~2, ~0x33, ~0)|RD_G0|ASI(~0), "1,2,t", 0, v6notv9 }, /* wr r,r,%tbr */ +{ "wr", F3(2, 0x33, 1), F3(~2, ~0x33, ~1)|RD_G0, "1,i,t", 0, v6notv9 }, /* wr r,i,%tbr */ + +{ "wr", F3(2, 0x30, 0)|RD(2), F3(~2, ~0x30, ~0)|RD(~2)|ASI(~0), "1,2,E", 0, v9 }, /* wr r,r,%ccr */ +{ "wr", F3(2, 0x30, 1)|RD(2), F3(~2, ~0x30, ~1)|RD(~2), "1,i,E", 0, v9 }, /* wr r,i,%ccr */ +{ "wr", F3(2, 0x30, 0)|RD(3), F3(~2, ~0x30, ~0)|RD(~3)|ASI(~0), "1,2,o", 0, v9 }, /* wr r,r,%asi */ +{ "wr", F3(2, 0x30, 1)|RD(3), F3(~2, ~0x30, ~1)|RD(~3), "1,i,o", 0, v9 }, /* wr r,i,%asi */ +{ "wr", F3(2, 0x30, 0)|RD(6), F3(~2, ~0x30, ~0)|RD(~6)|ASI(~0), "1,2,s", 0, v9 }, /* wr r,i,%fprs */ +{ "wr", F3(2, 0x30, 1)|RD(6), F3(~2, ~0x30, ~1)|RD(~6), "1,i,s", 0, v9 }, /* wr r,i,%fprs */ + +{ "rd", F3(2, 0x28, 0), F3(~2, ~0x28, ~0)|SIMM13(~0), "M,d", 0, v8 }, /* rd %asrX,r */ +{ "rd", F3(2, 0x28, 0), F3(~2, ~0x28, ~0)|RS1_G0|SIMM13(~0), "y,d", 0, v6 }, /* rd %y,r */ +{ "rd", F3(2, 0x29, 0), F3(~2, ~0x29, ~0)|RS1_G0|SIMM13(~0), "p,d", 0, v6notv9 }, /* rd %psr,r */ +{ "rd", F3(2, 0x2a, 0), F3(~2, ~0x2a, ~0)|RS1_G0|SIMM13(~0), "w,d", 0, v6notv9 }, /* rd %wim,r */ +{ "rd", F3(2, 0x2b, 0), F3(~2, ~0x2b, ~0)|RS1_G0|SIMM13(~0), "t,d", 0, v6notv9 }, /* rd %tbr,r */ + +{ "rd", F3(2, 0x28, 0)|RS1(2), F3(~2, ~0x28, ~0)|RS1(~2)|SIMM13(~0), "E,d", 0, v9 }, /* rd %ccr,r */ +{ "rd", F3(2, 0x28, 0)|RS1(3), F3(~2, ~0x28, ~0)|RS1(~3)|SIMM13(~0), "o,d", 0, v9 }, /* rd %asi,r */ +{ "rd", F3(2, 0x28, 0)|RS1(4), F3(~2, ~0x28, ~0)|RS1(~4)|SIMM13(~0), "W,d", 0, v9 }, /* rd %tick,r */ +{ "rd", F3(2, 0x28, 0)|RS1(5), F3(~2, ~0x28, ~0)|RS1(~5)|SIMM13(~0), "P,d", 0, v9 }, /* rd %pc,r */ +{ "rd", F3(2, 0x28, 0)|RS1(6), F3(~2, ~0x28, ~0)|RS1(~6)|SIMM13(~0), "s,d", 0, v9 }, /* rd %fprs,r */ + +{ "rdpr", F3(2, 0x2a, 0), F3(~2, ~0x2a, ~0)|SIMM13(~0), "?,d", 0, v9 }, /* rdpr %priv,r */ +{ "wrpr", F3(2, 0x32, 0), F3(~2, ~0x32, ~0), "1,2,!", 0, v9 }, /* wrpr r1,r2,%priv */ +{ "wrpr", F3(2, 0x32, 0), F3(~2, ~0x32, ~0)|SIMM13(~0), "1,!", 0, v9 }, /* wrpr r1,%priv */ +{ "wrpr", F3(2, 0x32, 1), F3(~2, ~0x32, ~1), "1,i,!", 0, v9 }, /* wrpr r1,i,%priv */ +{ "wrpr", F3(2, 0x32, 1), F3(~2, ~0x32, ~1), "i,1,!", F_ALIAS, v9 }, /* wrpr i,r1,%priv */ +{ "wrpr", F3(2, 0x32, 1), F3(~2, ~0x32, ~1)|RS1(~0), "i,!", 0, v9 }, /* wrpr i,%priv */ + +{ "mov", F3(2, 0x30, 0), F3(~2, ~0x30, ~0)|ASI(~0), "1,2,m", F_ALIAS, v8 }, /* wr r,r,%asrX */ +{ "mov", F3(2, 0x30, 0), F3(~2, ~0x30, ~0)|RD_G0|ASI(~0), "1,2,y", F_ALIAS, v6 }, /* wr r,r,%y */ +{ "mov", F3(2, 0x30, 1), F3(~2, ~0x30, ~1), "1,i,m", F_ALIAS, v8 }, /* wr r,i,%asrX */ +{ "mov", F3(2, 0x30, 1), F3(~2, ~0x30, ~1)|RD_G0, "1,i,y", F_ALIAS, v6 }, /* wr r,i,%y */ +{ "mov", F3(2, 0x31, 0), F3(~2, ~0x31, ~0)|RD_G0|ASI(~0), "1,2,p", F_ALIAS, v6notv9 }, /* wr r,r,%psr */ +{ "mov", F3(2, 0x31, 1), F3(~2, ~0x31, ~1)|RD_G0, "1,i,p", F_ALIAS, v6notv9 }, /* wr r,i,%psr */ +{ "mov", F3(2, 0x32, 0), F3(~2, ~0x32, ~0)|RD_G0|ASI(~0), "1,2,w", F_ALIAS, v6notv9 }, /* wr r,r,%wim */ +{ "mov", F3(2, 0x32, 1), F3(~2, ~0x32, ~1)|RD_G0, "1,i,w", F_ALIAS, v6notv9 }, /* wr r,i,%wim */ +{ "mov", F3(2, 0x33, 0), F3(~2, ~0x33, ~0)|RD_G0|ASI(~0), "1,2,t", F_ALIAS, v6notv9 }, /* wr r,r,%tbr */ +{ "mov", F3(2, 0x33, 1), F3(~2, ~0x33, ~1)|RD_G0, "1,i,t", F_ALIAS, v6notv9 }, /* wr r,i,%tbr */ + +{ "mov", F3(2, 0x28, 0), F3(~2, ~0x28, ~0)|SIMM13(~0), "M,d", F_ALIAS, v8 }, /* rd %asr1,r */ +{ "mov", F3(2, 0x28, 0), F3(~2, ~0x28, ~0)|RS1_G0|SIMM13(~0), "y,d", F_ALIAS, v6 }, /* rd %y,r */ +{ "mov", F3(2, 0x29, 0), F3(~2, ~0x29, ~0)|RS1_G0|SIMM13(~0), "p,d", F_ALIAS, v6notv9 }, /* rd %psr,r */ +{ "mov", F3(2, 0x2a, 0), F3(~2, ~0x2a, ~0)|RS1_G0|SIMM13(~0), "w,d", F_ALIAS, v6notv9 }, /* rd %wim,r */ +{ "mov", F3(2, 0x2b, 0), F3(~2, ~0x2b, ~0)|RS1_G0|SIMM13(~0), "t,d", F_ALIAS, v6notv9 }, /* rd %tbr,r */ + +{ "mov", F3(2, 0x30, 0), F3(~2, ~0x30, ~0)|ASI_RS2(~0), "1,y", F_ALIAS, v6 }, /* wr rs1,%g0,%y */ +{ "mov", F3(2, 0x30, 1), F3(~2, ~0x30, ~1), "i,y", F_ALIAS, v6 }, /* wr %g0,i,%y */ +{ "mov", F3(2, 0x30, 1), F3(~2, ~0x30, ~1)|SIMM13(~0), "1,y", F_ALIAS, v6 }, /* wr rs1,0,%y */ +{ "mov", F3(2, 0x31, 0), F3(~2, ~0x31, ~0)|ASI_RS2(~0), "1,p", F_ALIAS, v6notv9 }, /* wr rs1,%g0,%psr */ +{ "mov", F3(2, 0x31, 1), F3(~2, ~0x31, ~1), "i,p", F_ALIAS, v6notv9 }, /* wr %g0,i,%psr */ +{ "mov", F3(2, 0x31, 1), F3(~2, ~0x31, ~1)|SIMM13(~0), "1,p", F_ALIAS, v6notv9 }, /* wr rs1,0,%psr */ +{ "mov", F3(2, 0x32, 0), F3(~2, ~0x32, ~0)|ASI_RS2(~0), "1,w", F_ALIAS, v6notv9 }, /* wr rs1,%g0,%wim */ +{ "mov", F3(2, 0x32, 1), F3(~2, ~0x32, ~1), "i,w", F_ALIAS, v6notv9 }, /* wr %g0,i,%wim */ +{ "mov", F3(2, 0x32, 1), F3(~2, ~0x32, ~1)|SIMM13(~0), "1,w", F_ALIAS, v6notv9 }, /* wr rs1,0,%wim */ +{ "mov", F3(2, 0x33, 0), F3(~2, ~0x33, ~0)|ASI_RS2(~0), "1,t", F_ALIAS, v6notv9 }, /* wr rs1,%g0,%tbr */ +{ "mov", F3(2, 0x33, 1), F3(~2, ~0x33, ~1), "i,t", F_ALIAS, v6notv9 }, /* wr %g0,i,%tbr */ +{ "mov", F3(2, 0x33, 1), F3(~2, ~0x33, ~1)|SIMM13(~0), "1,t", F_ALIAS, v6notv9 }, /* wr rs1,0,%tbr */ + +{ "mov", F3(2, 0x02, 0), F3(~2, ~0x02, ~0)|RS1_G0|ASI(~0), "2,d", 0, v6 }, /* or %g0,rs2,d */ +{ "mov", F3(2, 0x02, 1), F3(~2, ~0x02, ~1)|RS1_G0, "i,d", 0, v6 }, /* or %g0,i,d */ +{ "mov", F3(2, 0x02, 0), F3(~2, ~0x02, ~0)|ASI_RS2(~0), "1,d", 0, v6 }, /* or rs1,%g0,d */ +{ "mov", F3(2, 0x02, 1), F3(~2, ~0x02, ~1)|SIMM13(~0), "1,d", 0, v6 }, /* or rs1,0,d */ + +{ "or", F3(2, 0x02, 0), F3(~2, ~0x02, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "or", F3(2, 0x02, 1), F3(~2, ~0x02, ~1), "1,i,d", 0, v6 }, +{ "or", F3(2, 0x02, 1), F3(~2, ~0x02, ~1), "i,1,d", 0, v6 }, + +{ "bset", F3(2, 0x02, 0), F3(~2, ~0x02, ~0)|ASI(~0), "2,r", F_ALIAS, v6 }, /* or rd,rs2,rd */ +{ "bset", F3(2, 0x02, 1), F3(~2, ~0x02, ~1), "i,r", F_ALIAS, v6 }, /* or rd,i,rd */ + +/* This is not a commutative instruction. */ +{ "andn", F3(2, 0x05, 0), F3(~2, ~0x05, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "andn", F3(2, 0x05, 1), F3(~2, ~0x05, ~1), "1,i,d", 0, v6 }, + +/* This is not a commutative instruction. */ +{ "andncc", F3(2, 0x15, 0), F3(~2, ~0x15, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "andncc", F3(2, 0x15, 1), F3(~2, ~0x15, ~1), "1,i,d", 0, v6 }, + +{ "bclr", F3(2, 0x05, 0), F3(~2, ~0x05, ~0)|ASI(~0), "2,r", F_ALIAS, v6 }, /* andn rd,rs2,rd */ +{ "bclr", F3(2, 0x05, 1), F3(~2, ~0x05, ~1), "i,r", F_ALIAS, v6 }, /* andn rd,i,rd */ + +{ "cmp", F3(2, 0x14, 0), F3(~2, ~0x14, ~0)|RD_G0|ASI(~0), "1,2", 0, v6 }, /* subcc rs1,rs2,%g0 */ +{ "cmp", F3(2, 0x14, 1), F3(~2, ~0x14, ~1)|RD_G0, "1,i", 0, v6 }, /* subcc rs1,i,%g0 */ + +{ "sub", F3(2, 0x04, 0), F3(~2, ~0x04, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "sub", F3(2, 0x04, 1), F3(~2, ~0x04, ~1), "1,i,d", 0, v6 }, + +{ "subcc", F3(2, 0x14, 0), F3(~2, ~0x14, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "subcc", F3(2, 0x14, 1), F3(~2, ~0x14, ~1), "1,i,d", 0, v6 }, + +{ "subx", F3(2, 0x0c, 0), F3(~2, ~0x0c, ~0)|ASI(~0), "1,2,d", 0, v6notv9 }, +{ "subx", F3(2, 0x0c, 1), F3(~2, ~0x0c, ~1), "1,i,d", 0, v6notv9 }, +{ "subc", F3(2, 0x0c, 0), F3(~2, ~0x0c, ~0)|ASI(~0), "1,2,d", 0, v9 }, +{ "subc", F3(2, 0x0c, 1), F3(~2, ~0x0c, ~1), "1,i,d", 0, v9 }, + +{ "subxcc", F3(2, 0x1c, 0), F3(~2, ~0x1c, ~0)|ASI(~0), "1,2,d", 0, v6notv9 }, +{ "subxcc", F3(2, 0x1c, 1), F3(~2, ~0x1c, ~1), "1,i,d", 0, v6notv9 }, +{ "subccc", F3(2, 0x1c, 0), F3(~2, ~0x1c, ~0)|ASI(~0), "1,2,d", 0, v9 }, +{ "subccc", F3(2, 0x1c, 1), F3(~2, ~0x1c, ~1), "1,i,d", 0, v9 }, + +{ "and", F3(2, 0x01, 0), F3(~2, ~0x01, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "and", F3(2, 0x01, 1), F3(~2, ~0x01, ~1), "1,i,d", 0, v6 }, +{ "and", F3(2, 0x01, 1), F3(~2, ~0x01, ~1), "i,1,d", 0, v6 }, + +{ "andcc", F3(2, 0x11, 0), F3(~2, ~0x11, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "andcc", F3(2, 0x11, 1), F3(~2, ~0x11, ~1), "1,i,d", 0, v6 }, +{ "andcc", F3(2, 0x11, 1), F3(~2, ~0x11, ~1), "i,1,d", 0, v6 }, + +{ "dec", F3(2, 0x04, 1)|SIMM13(0x1), F3(~2, ~0x04, ~1)|SIMM13(~0x0001), "r", F_ALIAS, v6 }, /* sub rd,1,rd */ +{ "dec", F3(2, 0x04, 1), F3(~2, ~0x04, ~1), "i,r", F_ALIAS, v8 }, /* sub rd,imm,rd */ +{ "deccc", F3(2, 0x14, 1)|SIMM13(0x1), F3(~2, ~0x14, ~1)|SIMM13(~0x0001), "r", F_ALIAS, v6 }, /* subcc rd,1,rd */ +{ "deccc", F3(2, 0x14, 1), F3(~2, ~0x14, ~1), "i,r", F_ALIAS, v8 }, /* subcc rd,imm,rd */ +{ "inc", F3(2, 0x00, 1)|SIMM13(0x1), F3(~2, ~0x00, ~1)|SIMM13(~0x0001), "r", F_ALIAS, v6 }, /* add rd,1,rd */ +{ "inc", F3(2, 0x00, 1), F3(~2, ~0x00, ~1), "i,r", F_ALIAS, v8 }, /* add rd,imm,rd */ +{ "inccc", F3(2, 0x10, 1)|SIMM13(0x1), F3(~2, ~0x10, ~1)|SIMM13(~0x0001), "r", F_ALIAS, v6 }, /* addcc rd,1,rd */ +{ "inccc", F3(2, 0x10, 1), F3(~2, ~0x10, ~1), "i,r", F_ALIAS, v8 }, /* addcc rd,imm,rd */ + +{ "btst", F3(2, 0x11, 0), F3(~2, ~0x11, ~0)|RD_G0|ASI(~0), "1,2", F_ALIAS, v6 }, /* andcc rs1,rs2,%g0 */ +{ "btst", F3(2, 0x11, 1), F3(~2, ~0x11, ~1)|RD_G0, "i,1", F_ALIAS, v6 }, /* andcc rs1,i,%g0 */ + +{ "neg", F3(2, 0x04, 0), F3(~2, ~0x04, ~0)|RS1_G0|ASI(~0), "2,d", F_ALIAS, v6 }, /* sub %g0,rs2,rd */ +{ "neg", F3(2, 0x04, 0), F3(~2, ~0x04, ~0)|RS1_G0|ASI(~0), "O", F_ALIAS, v6 }, /* sub %g0,rd,rd */ + +{ "add", F3(2, 0x00, 0), F3(~2, ~0x00, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "add", F3(2, 0x00, 1), F3(~2, ~0x00, ~1), "1,i,d", 0, v6 }, +{ "add", F3(2, 0x00, 1), F3(~2, ~0x00, ~1), "i,1,d", 0, v6 }, +{ "addcc", F3(2, 0x10, 0), F3(~2, ~0x10, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "addcc", F3(2, 0x10, 1), F3(~2, ~0x10, ~1), "1,i,d", 0, v6 }, +{ "addcc", F3(2, 0x10, 1), F3(~2, ~0x10, ~1), "i,1,d", 0, v6 }, + +{ "addx", F3(2, 0x08, 0), F3(~2, ~0x08, ~0)|ASI(~0), "1,2,d", 0, v6notv9 }, +{ "addx", F3(2, 0x08, 1), F3(~2, ~0x08, ~1), "1,i,d", 0, v6notv9 }, +{ "addx", F3(2, 0x08, 1), F3(~2, ~0x08, ~1), "i,1,d", 0, v6notv9 }, +{ "addc", F3(2, 0x08, 0), F3(~2, ~0x08, ~0)|ASI(~0), "1,2,d", 0, v9 }, +{ "addc", F3(2, 0x08, 1), F3(~2, ~0x08, ~1), "1,i,d", 0, v9 }, +{ "addc", F3(2, 0x08, 1), F3(~2, ~0x08, ~1), "i,1,d", 0, v9 }, + +{ "addxcc", F3(2, 0x18, 0), F3(~2, ~0x18, ~0)|ASI(~0), "1,2,d", 0, v6notv9 }, +{ "addxcc", F3(2, 0x18, 1), F3(~2, ~0x18, ~1), "1,i,d", 0, v6notv9 }, +{ "addxcc", F3(2, 0x18, 1), F3(~2, ~0x18, ~1), "i,1,d", 0, v6notv9 }, +{ "addccc", F3(2, 0x18, 0), F3(~2, ~0x18, ~0)|ASI(~0), "1,2,d", 0, v9 }, +{ "addccc", F3(2, 0x18, 1), F3(~2, ~0x18, ~1), "1,i,d", 0, v9 }, +{ "addccc", F3(2, 0x18, 1), F3(~2, ~0x18, ~1), "i,1,d", 0, v9 }, + +{ "smul", F3(2, 0x0b, 0), F3(~2, ~0x0b, ~0)|ASI(~0), "1,2,d", 0, v8 }, +{ "smul", F3(2, 0x0b, 1), F3(~2, ~0x0b, ~1), "1,i,d", 0, v8 }, +{ "smul", F3(2, 0x0b, 1), F3(~2, ~0x0b, ~1), "i,1,d", 0, v8 }, +{ "smulcc", F3(2, 0x1b, 0), F3(~2, ~0x1b, ~0)|ASI(~0), "1,2,d", 0, v8 }, +{ "smulcc", F3(2, 0x1b, 1), F3(~2, ~0x1b, ~1), "1,i,d", 0, v8 }, +{ "smulcc", F3(2, 0x1b, 1), F3(~2, ~0x1b, ~1), "i,1,d", 0, v8 }, +{ "umul", F3(2, 0x0a, 0), F3(~2, ~0x0a, ~0)|ASI(~0), "1,2,d", 0, v8 }, +{ "umul", F3(2, 0x0a, 1), F3(~2, ~0x0a, ~1), "1,i,d", 0, v8 }, +{ "umul", F3(2, 0x0a, 1), F3(~2, ~0x0a, ~1), "i,1,d", 0, v8 }, +{ "umulcc", F3(2, 0x1a, 0), F3(~2, ~0x1a, ~0)|ASI(~0), "1,2,d", 0, v8 }, +{ "umulcc", F3(2, 0x1a, 1), F3(~2, ~0x1a, ~1), "1,i,d", 0, v8 }, +{ "umulcc", F3(2, 0x1a, 1), F3(~2, ~0x1a, ~1), "i,1,d", 0, v8 }, +{ "sdiv", F3(2, 0x0f, 0), F3(~2, ~0x0f, ~0)|ASI(~0), "1,2,d", 0, v8 }, +{ "sdiv", F3(2, 0x0f, 1), F3(~2, ~0x0f, ~1), "1,i,d", 0, v8 }, +{ "sdiv", F3(2, 0x0f, 1), F3(~2, ~0x0f, ~1), "i,1,d", 0, v8 }, +{ "sdivcc", F3(2, 0x1f, 0), F3(~2, ~0x1f, ~0)|ASI(~0), "1,2,d", 0, v8 }, +{ "sdivcc", F3(2, 0x1f, 1), F3(~2, ~0x1f, ~1), "1,i,d", 0, v8 }, +{ "sdivcc", F3(2, 0x1f, 1), F3(~2, ~0x1f, ~1), "i,1,d", 0, v8 }, +{ "udiv", F3(2, 0x0e, 0), F3(~2, ~0x0e, ~0)|ASI(~0), "1,2,d", 0, v8 }, +{ "udiv", F3(2, 0x0e, 1), F3(~2, ~0x0e, ~1), "1,i,d", 0, v8 }, +{ "udiv", F3(2, 0x0e, 1), F3(~2, ~0x0e, ~1), "i,1,d", 0, v8 }, +{ "udivcc", F3(2, 0x1e, 0), F3(~2, ~0x1e, ~0)|ASI(~0), "1,2,d", 0, v8 }, +{ "udivcc", F3(2, 0x1e, 1), F3(~2, ~0x1e, ~1), "1,i,d", 0, v8 }, +{ "udivcc", F3(2, 0x1e, 1), F3(~2, ~0x1e, ~1), "i,1,d", 0, v8 }, + +{ "mulx", F3(2, 0x09, 0), F3(~2, ~0x09, ~0)|ASI(~0), "1,2,d", 0, v9 }, +{ "mulx", F3(2, 0x09, 1), F3(~2, ~0x09, ~1), "1,i,d", 0, v9 }, +{ "sdivx", F3(2, 0x2d, 0), F3(~2, ~0x2d, ~0)|ASI(~0), "1,2,d", 0, v9 }, +{ "sdivx", F3(2, 0x2d, 1), F3(~2, ~0x2d, ~1), "1,i,d", 0, v9 }, +{ "udivx", F3(2, 0x0d, 0), F3(~2, ~0x0d, ~0)|ASI(~0), "1,2,d", 0, v9 }, +{ "udivx", F3(2, 0x0d, 1), F3(~2, ~0x0d, ~1), "1,i,d", 0, v9 }, + +{ "call", F1(0x1), F1(~0x1), "L", F_JSR|F_DELAYED, v6 }, +{ "call", F1(0x1), F1(~0x1), "L,#", F_JSR|F_DELAYED, v6 }, + +{ "call", F3(2, 0x38, 0)|RD(0xf), F3(~2, ~0x38, ~0)|RD(~0xf)|ASI(~0), "1+2", F_JSR|F_DELAYED, v6 }, /* jmpl rs1+rs2,%o7 */ +{ "call", F3(2, 0x38, 0)|RD(0xf), F3(~2, ~0x38, ~0)|RD(~0xf)|ASI(~0), "1+2,#", F_JSR|F_DELAYED, v6 }, +{ "call", F3(2, 0x38, 0)|RD(0xf), F3(~2, ~0x38, ~0)|RD(~0xf)|ASI_RS2(~0), "1", F_JSR|F_DELAYED, v6 }, /* jmpl rs1+%g0,%o7 */ +{ "call", F3(2, 0x38, 0)|RD(0xf), F3(~2, ~0x38, ~0)|RD(~0xf)|ASI_RS2(~0), "1,#", F_JSR|F_DELAYED, v6 }, +{ "call", F3(2, 0x38, 1)|RD(0xf), F3(~2, ~0x38, ~1)|RD(~0xf), "1+i", F_JSR|F_DELAYED, v6 }, /* jmpl rs1+i,%o7 */ +{ "call", F3(2, 0x38, 1)|RD(0xf), F3(~2, ~0x38, ~1)|RD(~0xf), "1+i,#", F_JSR|F_DELAYED, v6 }, +{ "call", F3(2, 0x38, 1)|RD(0xf), F3(~2, ~0x38, ~1)|RD(~0xf), "i+1", F_JSR|F_DELAYED, v6 }, /* jmpl i+rs1,%o7 */ +{ "call", F3(2, 0x38, 1)|RD(0xf), F3(~2, ~0x38, ~1)|RD(~0xf), "i+1,#", F_JSR|F_DELAYED, v6 }, +{ "call", F3(2, 0x38, 1)|RD(0xf), F3(~2, ~0x38, ~1)|RD(~0xf)|RS1_G0, "i", F_JSR|F_DELAYED, v6 }, /* jmpl %g0+i,%o7 */ +{ "call", F3(2, 0x38, 1)|RD(0xf), F3(~2, ~0x38, ~1)|RD(~0xf)|RS1_G0, "i,#", F_JSR|F_DELAYED, v6 }, +{ "call", F3(2, 0x38, 1)|RD(0xf), F3(~2, ~0x38, ~1)|RD(~0xf)|SIMM13(~0), "1", F_JSR|F_DELAYED, v6 }, /* jmpl rs1+0,%o7 */ +{ "call", F3(2, 0x38, 1)|RD(0xf), F3(~2, ~0x38, ~1)|RD(~0xf)|SIMM13(~0), "1,#", F_JSR|F_DELAYED, v6 }, + + +/* Conditional instructions. + + Because this part of the table was such a mess earlier, I have + macrofied it so that all the branches and traps are generated from + a single-line description of each condition value. John Gilmore. */ + +/* Define branches -- one annulled, one without, etc. */ +#define br(opcode, mask, lose, flags) \ + { opcode, (mask)|ANNUL, (lose), ",a l", (flags), v6 }, \ + { opcode, (mask) , (lose)|ANNUL, "l", (flags), v6 } + +#define brx(opcode, mask, lose, flags) /* v9 */ \ + { opcode, (mask)|(2<<20)|BPRED, ANNUL|(lose), "Z,G", (flags), v9 }, \ + { opcode, (mask)|(2<<20)|BPRED, ANNUL|(lose), ",T Z,G", (flags), v9 }, \ + { opcode, (mask)|(2<<20)|BPRED|ANNUL, (lose), ",a Z,G", (flags), v9 }, \ + { opcode, (mask)|(2<<20)|BPRED|ANNUL, (lose), ",a,T Z,G", (flags), v9 }, \ + { opcode, (mask)|(2<<20), ANNUL|BPRED|(lose), ",N Z,G", (flags), v9 }, \ + { opcode, (mask)|(2<<20)|ANNUL, BPRED|(lose), ",a,N Z,G", (flags), v9 }, \ + { opcode, (mask)|BPRED, ANNUL|(lose)|(2<<20), "z,G", (flags), v9 }, \ + { opcode, (mask)|BPRED, ANNUL|(lose)|(2<<20), ",T z,G", (flags), v9 }, \ + { opcode, (mask)|BPRED|ANNUL, (lose)|(2<<20), ",a z,G", (flags), v9 }, \ + { opcode, (mask)|BPRED|ANNUL, (lose)|(2<<20), ",a,T z,G", (flags), v9 }, \ + { opcode, (mask), ANNUL|BPRED|(lose)|(2<<20), ",N z,G", (flags), v9 }, \ + { opcode, (mask)|ANNUL, BPRED|(lose)|(2<<20), ",a,N z,G", (flags), v9 } + +/* Define four traps: reg+reg, reg + immediate, immediate alone, reg alone. */ +#define tr(opcode, mask, lose, flags) \ + { opcode, (mask)|(2<<11)|IMMED, (lose)|RS1_G0, "Z,i", (flags), v9 }, /* %g0 + imm */ \ + { opcode, (mask)|(2<<11)|IMMED, (lose), "Z,1+i", (flags), v9 }, /* rs1 + imm */ \ + { opcode, (mask)|(2<<11), IMMED|(lose), "Z,1+2", (flags), v9 }, /* rs1 + rs2 */ \ + { opcode, (mask)|(2<<11), IMMED|(lose)|RS2_G0, "Z,1", (flags), v9 }, /* rs1 + %g0 */ \ + { opcode, (mask)|IMMED, (lose)|RS1_G0, "z,i", (flags)|F_ALIAS, v9 }, /* %g0 + imm */ \ + { opcode, (mask)|IMMED, (lose), "z,1+i", (flags)|F_ALIAS, v9 }, /* rs1 + imm */ \ + { opcode, (mask), IMMED|(lose), "z,1+2", (flags)|F_ALIAS, v9 }, /* rs1 + rs2 */ \ + { opcode, (mask), IMMED|(lose)|RS2_G0, "z,1", (flags)|F_ALIAS, v9 }, /* rs1 + %g0 */ \ + { opcode, (mask)|IMMED, (lose)|RS1_G0, "i", (flags), v6 }, /* %g0 + imm */ \ + { opcode, (mask)|IMMED, (lose), "1+i", (flags), v6 }, /* rs1 + imm */ \ + { opcode, (mask), IMMED|(lose), "1+2", (flags), v6 }, /* rs1 + rs2 */ \ + { opcode, (mask), IMMED|(lose)|RS2_G0, "1", (flags), v6 } /* rs1 + %g0 */ + +/* v9: We must put `brx' before `br', to ensure that we never match something + v9: against an expression unless it is an expression. Otherwise, we end + v9: up with undefined symbol tables entries, because they get added, but + v9: are not deleted if the pattern fails to match. */ + +/* Define both branches and traps based on condition mask */ +#define cond(bop, top, mask, flags) \ + brx(bop, F2(0, 1)|(mask), F2(~0, ~1)|((~mask)&COND(~0)), F_DELAYED|(flags)), /* v9 */ \ + br(bop, F2(0, 2)|(mask), F2(~0, ~2)|((~mask)&COND(~0)), F_DELAYED|(flags)), \ + tr(top, F3(2, 0x3a, 0)|(mask), F3(~2, ~0x3a, 0)|((~mask)&COND(~0)), ((flags) & ~(F_UNBR|F_CONDBR))) + +/* Define all the conditions, all the branches, all the traps. */ + +/* Standard branch, trap mnemonics */ +cond ("b", "ta", CONDA, F_UNBR), +/* Alternative form (just for assembly, not for disassembly) */ +cond ("ba", "t", CONDA, F_UNBR|F_ALIAS), + +cond ("bcc", "tcc", CONDCC, F_CONDBR), +cond ("bcs", "tcs", CONDCS, F_CONDBR), +cond ("be", "te", CONDE, F_CONDBR), +cond ("bg", "tg", CONDG, F_CONDBR), +cond ("bgt", "tgt", CONDG, F_CONDBR|F_ALIAS), +cond ("bge", "tge", CONDGE, F_CONDBR), +cond ("bgeu", "tgeu", CONDGEU, F_CONDBR|F_ALIAS), /* for cc */ +cond ("bgu", "tgu", CONDGU, F_CONDBR), +cond ("bl", "tl", CONDL, F_CONDBR), +cond ("blt", "tlt", CONDL, F_CONDBR|F_ALIAS), +cond ("ble", "tle", CONDLE, F_CONDBR), +cond ("bleu", "tleu", CONDLEU, F_CONDBR), +cond ("blu", "tlu", CONDLU, F_CONDBR|F_ALIAS), /* for cs */ +cond ("bn", "tn", CONDN, F_CONDBR), +cond ("bne", "tne", CONDNE, F_CONDBR), +cond ("bneg", "tneg", CONDNEG, F_CONDBR), +cond ("bnz", "tnz", CONDNZ, F_CONDBR|F_ALIAS), /* for ne */ +cond ("bpos", "tpos", CONDPOS, F_CONDBR), +cond ("bvc", "tvc", CONDVC, F_CONDBR), +cond ("bvs", "tvs", CONDVS, F_CONDBR), +cond ("bz", "tz", CONDZ, F_CONDBR|F_ALIAS), /* for e */ + +#undef cond +#undef br +#undef brr /* v9 */ +#undef tr + +#define brr(opcode, mask, lose, flags) /* v9 */ \ + { opcode, (mask)|BPRED, ANNUL|(lose), "1,k", F_DELAYED|(flags), v9 }, \ + { opcode, (mask)|BPRED, ANNUL|(lose), ",T 1,k", F_DELAYED|(flags), v9 }, \ + { opcode, (mask)|BPRED|ANNUL, (lose), ",a 1,k", F_DELAYED|(flags), v9 }, \ + { opcode, (mask)|BPRED|ANNUL, (lose), ",a,T 1,k", F_DELAYED|(flags), v9 }, \ + { opcode, (mask), ANNUL|BPRED|(lose), ",N 1,k", F_DELAYED|(flags), v9 }, \ + { opcode, (mask)|ANNUL, BPRED|(lose), ",a,N 1,k", F_DELAYED|(flags), v9 } + +#define condr(bop, mask, flags) /* v9 */ \ + brr(bop, F2(0, 3)|COND(mask), F2(~0, ~3)|COND(~(mask)), (flags)) /* v9 */ + +/* v9 */ condr("brnz", 0x5, F_CONDBR), +/* v9 */ condr("brz", 0x1, F_CONDBR), +/* v9 */ condr("brgez", 0x7, F_CONDBR), +/* v9 */ condr("brlz", 0x3, F_CONDBR), +/* v9 */ condr("brlez", 0x2, F_CONDBR), +/* v9 */ condr("brgz", 0x6, F_CONDBR), + +#undef condr /* v9 */ +#undef brr /* v9 */ + +#define movr(opcode, mask, flags) /* v9 */ \ + { opcode, F3(2, 0x2f, 0)|RCOND(mask), F3(~2, ~0x2f, ~0)|RCOND(~(mask)), "1,2,d", (flags), v9 }, \ + { opcode, F3(2, 0x2f, 1)|RCOND(mask), F3(~2, ~0x2f, ~1)|RCOND(~(mask)), "1,j,d", (flags), v9 } + +#define fmrrs(opcode, mask, lose, flags) /* v9 */ \ + { opcode, (mask), (lose), "1,f,g", (flags), v9 } +#define fmrrd(opcode, mask, lose, flags) /* v9 */ \ + { opcode, (mask), (lose), "1,B,H", (flags), v9 } +#define fmrrq(opcode, mask, lose, flags) /* v9 */ \ + { opcode, (mask), (lose), "1,R,J", (flags), v9 } + +#define fmovrs(mop, mask, flags) /* v9 */ \ + fmrrs(mop, F3(2, 0x35, 0)|OPF_LOW5(5)|RCOND(mask), F3(~2, ~0x35, 0)|OPF_LOW5(~5)|RCOND(~(mask)), (flags)) /* v9 */ +#define fmovrd(mop, mask, flags) /* v9 */ \ + fmrrd(mop, F3(2, 0x35, 0)|OPF_LOW5(6)|RCOND(mask), F3(~2, ~0x35, 0)|OPF_LOW5(~6)|RCOND(~(mask)), (flags)) /* v9 */ +#define fmovrq(mop, mask, flags) /* v9 */ \ + fmrrq(mop, F3(2, 0x35, 0)|OPF_LOW5(7)|RCOND(mask), F3(~2, ~0x35, 0)|OPF_LOW5(~7)|RCOND(~(mask)), (flags)) /* v9 */ + +/* v9 */ movr("movrne", 0x5, 0), +/* v9 */ movr("movre", 0x1, 0), +/* v9 */ movr("movrgez", 0x7, 0), +/* v9 */ movr("movrlz", 0x3, 0), +/* v9 */ movr("movrlez", 0x2, 0), +/* v9 */ movr("movrgz", 0x6, 0), +/* v9 */ movr("movrnz", 0x5, F_ALIAS), +/* v9 */ movr("movrz", 0x1, F_ALIAS), + +/* v9 */ fmovrs("fmovrsne", 0x5, 0), +/* v9 */ fmovrs("fmovrse", 0x1, 0), +/* v9 */ fmovrs("fmovrsgez", 0x7, 0), +/* v9 */ fmovrs("fmovrslz", 0x3, 0), +/* v9 */ fmovrs("fmovrslez", 0x2, 0), +/* v9 */ fmovrs("fmovrsgz", 0x6, 0), +/* v9 */ fmovrs("fmovrsnz", 0x5, F_ALIAS), +/* v9 */ fmovrs("fmovrsz", 0x1, F_ALIAS), + +/* v9 */ fmovrd("fmovrdne", 0x5, 0), +/* v9 */ fmovrd("fmovrde", 0x1, 0), +/* v9 */ fmovrd("fmovrdgez", 0x7, 0), +/* v9 */ fmovrd("fmovrdlz", 0x3, 0), +/* v9 */ fmovrd("fmovrdlez", 0x2, 0), +/* v9 */ fmovrd("fmovrdgz", 0x6, 0), +/* v9 */ fmovrd("fmovrdnz", 0x5, F_ALIAS), +/* v9 */ fmovrd("fmovrdz", 0x1, F_ALIAS), + +/* v9 */ fmovrq("fmovrqne", 0x5, 0), +/* v9 */ fmovrq("fmovrqe", 0x1, 0), +/* v9 */ fmovrq("fmovrqgez", 0x7, 0), +/* v9 */ fmovrq("fmovrqlz", 0x3, 0), +/* v9 */ fmovrq("fmovrqlez", 0x2, 0), +/* v9 */ fmovrq("fmovrqgz", 0x6, 0), +/* v9 */ fmovrq("fmovrqnz", 0x5, F_ALIAS), +/* v9 */ fmovrq("fmovrqz", 0x1, F_ALIAS), + +#undef movr /* v9 */ +#undef fmovr /* v9 */ +#undef fmrr /* v9 */ + +#define movicc(opcode, cond, flags) /* v9 */ \ + { opcode, F3(2, 0x2c, 0)|MCOND(cond,1)|ICC, F3(~2, ~0x2c, ~0)|MCOND(~cond,~1)|XCC|(1<<11), "z,2,d", flags, v9 }, \ + { opcode, F3(2, 0x2c, 1)|MCOND(cond,1)|ICC, F3(~2, ~0x2c, ~1)|MCOND(~cond,~1)|XCC|(1<<11), "z,I,d", flags, v9 }, \ + { opcode, F3(2, 0x2c, 0)|MCOND(cond,1)|XCC, F3(~2, ~0x2c, ~0)|MCOND(~cond,~1)|(1<<11), "Z,2,d", flags, v9 }, \ + { opcode, F3(2, 0x2c, 1)|MCOND(cond,1)|XCC, F3(~2, ~0x2c, ~1)|MCOND(~cond,~1)|(1<<11), "Z,I,d", flags, v9 } + +#define movfcc(opcode, fcond, flags) /* v9 */ \ + { opcode, F3(2, 0x2c, 0)|FCC(0)|MCOND(fcond,0), MCOND(~fcond,~0)|FCC(~0)|F3(~2, ~0x2c, ~0), "6,2,d", flags, v9 }, \ + { opcode, F3(2, 0x2c, 1)|FCC(0)|MCOND(fcond,0), MCOND(~fcond,~0)|FCC(~0)|F3(~2, ~0x2c, ~1), "6,I,d", flags, v9 }, \ + { opcode, F3(2, 0x2c, 0)|FCC(1)|MCOND(fcond,0), MCOND(~fcond,~0)|FCC(~1)|F3(~2, ~0x2c, ~0), "7,2,d", flags, v9 }, \ + { opcode, F3(2, 0x2c, 1)|FCC(1)|MCOND(fcond,0), MCOND(~fcond,~0)|FCC(~1)|F3(~2, ~0x2c, ~1), "7,I,d", flags, v9 }, \ + { opcode, F3(2, 0x2c, 0)|FCC(2)|MCOND(fcond,0), MCOND(~fcond,~0)|FCC(~2)|F3(~2, ~0x2c, ~0), "8,2,d", flags, v9 }, \ + { opcode, F3(2, 0x2c, 1)|FCC(2)|MCOND(fcond,0), MCOND(~fcond,~0)|FCC(~2)|F3(~2, ~0x2c, ~1), "8,I,d", flags, v9 }, \ + { opcode, F3(2, 0x2c, 0)|FCC(3)|MCOND(fcond,0), MCOND(~fcond,~0)|FCC(~3)|F3(~2, ~0x2c, ~0), "9,2,d", flags, v9 }, \ + { opcode, F3(2, 0x2c, 1)|FCC(3)|MCOND(fcond,0), MCOND(~fcond,~0)|FCC(~3)|F3(~2, ~0x2c, ~1), "9,I,d", flags, v9 } + +#define movcc(opcode, cond, fcond, flags) /* v9 */ \ + movfcc (opcode, fcond, flags), /* v9 */ \ + movicc (opcode, cond, flags) /* v9 */ + +/* v9 */ movcc ("mova", CONDA, FCONDA, 0), +/* v9 */ movicc ("movcc", CONDCC, 0), +/* v9 */ movicc ("movgeu", CONDGEU, F_ALIAS), +/* v9 */ movicc ("movcs", CONDCS, 0), +/* v9 */ movicc ("movlu", CONDLU, F_ALIAS), +/* v9 */ movcc ("move", CONDE, FCONDE, 0), +/* v9 */ movcc ("movg", CONDG, FCONDG, 0), +/* v9 */ movcc ("movge", CONDGE, FCONDGE, 0), +/* v9 */ movicc ("movgu", CONDGU, 0), +/* v9 */ movcc ("movl", CONDL, FCONDL, 0), +/* v9 */ movcc ("movle", CONDLE, FCONDLE, 0), +/* v9 */ movicc ("movleu", CONDLEU, 0), +/* v9 */ movfcc ("movlg", FCONDLG, 0), +/* v9 */ movcc ("movn", CONDN, FCONDN, 0), +/* v9 */ movcc ("movne", CONDNE, FCONDNE, 0), +/* v9 */ movicc ("movneg", CONDNEG, 0), +/* v9 */ movcc ("movnz", CONDNZ, FCONDNZ, F_ALIAS), +/* v9 */ movfcc ("movo", FCONDO, 0), +/* v9 */ movicc ("movpos", CONDPOS, 0), +/* v9 */ movfcc ("movu", FCONDU, 0), +/* v9 */ movfcc ("movue", FCONDUE, 0), +/* v9 */ movfcc ("movug", FCONDUG, 0), +/* v9 */ movfcc ("movuge", FCONDUGE, 0), +/* v9 */ movfcc ("movul", FCONDUL, 0), +/* v9 */ movfcc ("movule", FCONDULE, 0), +/* v9 */ movicc ("movvc", CONDVC, 0), +/* v9 */ movicc ("movvs", CONDVS, 0), +/* v9 */ movcc ("movz", CONDZ, FCONDZ, F_ALIAS), + +#undef movicc /* v9 */ +#undef movfcc /* v9 */ +#undef movcc /* v9 */ + +#define FM_SF 1 /* v9 - values for fpsize */ +#define FM_DF 2 /* v9 */ +#define FM_QF 3 /* v9 */ + +#define fmovicc(opcode, fpsize, cond, flags) /* v9 */ \ +{ opcode, F3F(2, 0x35, 0x100+fpsize)|MCOND(cond,0), F3F(~2, ~0x35, ~(0x100+fpsize))|MCOND(~cond,~0), "z,f,g", flags, v9 }, \ +{ opcode, F3F(2, 0x35, 0x180+fpsize)|MCOND(cond,0), F3F(~2, ~0x35, ~(0x180+fpsize))|MCOND(~cond,~0), "Z,f,g", flags, v9 } + +#define fmovfcc(opcode, fpsize, fcond, flags) /* v9 */ \ +{ opcode, F3F(2, 0x35, 0x000+fpsize)|MCOND(fcond,0), F3F(~2, ~0x35, ~(0x000+fpsize))|MCOND(~fcond,~0), "6,f,g", flags, v9 }, \ +{ opcode, F3F(2, 0x35, 0x040+fpsize)|MCOND(fcond,0), F3F(~2, ~0x35, ~(0x040+fpsize))|MCOND(~fcond,~0), "7,f,g", flags, v9 }, \ +{ opcode, F3F(2, 0x35, 0x080+fpsize)|MCOND(fcond,0), F3F(~2, ~0x35, ~(0x080+fpsize))|MCOND(~fcond,~0), "8,f,g", flags, v9 }, \ +{ opcode, F3F(2, 0x35, 0x0c0+fpsize)|MCOND(fcond,0), F3F(~2, ~0x35, ~(0x0c0+fpsize))|MCOND(~fcond,~0), "9,f,g", flags, v9 } + +/* FIXME: use fmovicc/fmovfcc? */ /* v9 */ +#define fmovcc(opcode, fpsize, cond, fcond, flags) /* v9 */ \ +{ opcode, F3F(2, 0x35, 0x100+fpsize)|MCOND(cond,0), F3F(~2, ~0x35, ~(0x100+fpsize))|MCOND(~cond,~0), "z,f,g", flags, v9 }, \ +{ opcode, F3F(2, 0x35, 0x000+fpsize)|MCOND(fcond,0), F3F(~2, ~0x35, ~(0x000+fpsize))|MCOND(~fcond,~0), "6,f,g", flags, v9 }, \ +{ opcode, F3F(2, 0x35, 0x180+fpsize)|MCOND(cond,0), F3F(~2, ~0x35, ~(0x180+fpsize))|MCOND(~cond,~0), "Z,f,g", flags, v9 }, \ +{ opcode, F3F(2, 0x35, 0x040+fpsize)|MCOND(fcond,0), F3F(~2, ~0x35, ~(0x040+fpsize))|MCOND(~fcond,~0), "7,f,g", flags, v9 }, \ +{ opcode, F3F(2, 0x35, 0x080+fpsize)|MCOND(fcond,0), F3F(~2, ~0x35, ~(0x080+fpsize))|MCOND(~fcond,~0), "8,f,g", flags, v9 }, \ +{ opcode, F3F(2, 0x35, 0x0c0+fpsize)|MCOND(fcond,0), F3F(~2, ~0x35, ~(0x0c0+fpsize))|MCOND(~fcond,~0), "9,f,g", flags, v9 } + +/* v9 */ fmovcc ("fmovda", FM_DF, CONDA, FCONDA, 0), +/* v9 */ fmovcc ("fmovqa", FM_QF, CONDA, FCONDA, 0), +/* v9 */ fmovcc ("fmovsa", FM_SF, CONDA, FCONDA, 0), +/* v9 */ fmovicc ("fmovdcc", FM_DF, CONDCC, 0), +/* v9 */ fmovicc ("fmovqcc", FM_QF, CONDCC, 0), +/* v9 */ fmovicc ("fmovscc", FM_SF, CONDCC, 0), +/* v9 */ fmovicc ("fmovdcs", FM_DF, CONDCS, 0), +/* v9 */ fmovicc ("fmovqcs", FM_QF, CONDCS, 0), +/* v9 */ fmovicc ("fmovscs", FM_SF, CONDCS, 0), +/* v9 */ fmovcc ("fmovde", FM_DF, CONDE, FCONDE, 0), +/* v9 */ fmovcc ("fmovqe", FM_QF, CONDE, FCONDE, 0), +/* v9 */ fmovcc ("fmovse", FM_SF, CONDE, FCONDE, 0), +/* v9 */ fmovcc ("fmovdg", FM_DF, CONDG, FCONDG, 0), +/* v9 */ fmovcc ("fmovqg", FM_QF, CONDG, FCONDG, 0), +/* v9 */ fmovcc ("fmovsg", FM_SF, CONDG, FCONDG, 0), +/* v9 */ fmovcc ("fmovdge", FM_DF, CONDGE, FCONDGE, 0), +/* v9 */ fmovcc ("fmovqge", FM_QF, CONDGE, FCONDGE, 0), +/* v9 */ fmovcc ("fmovsge", FM_SF, CONDGE, FCONDGE, 0), +/* v9 */ fmovicc ("fmovdgeu", FM_DF, CONDGEU, F_ALIAS), +/* v9 */ fmovicc ("fmovqgeu", FM_QF, CONDGEU, F_ALIAS), +/* v9 */ fmovicc ("fmovsgeu", FM_SF, CONDGEU, F_ALIAS), +/* v9 */ fmovicc ("fmovdgu", FM_DF, CONDGU, 0), +/* v9 */ fmovicc ("fmovqgu", FM_QF, CONDGU, 0), +/* v9 */ fmovicc ("fmovsgu", FM_SF, CONDGU, 0), +/* v9 */ fmovcc ("fmovdl", FM_DF, CONDL, FCONDL, 0), +/* v9 */ fmovcc ("fmovql", FM_QF, CONDL, FCONDL, 0), +/* v9 */ fmovcc ("fmovsl", FM_SF, CONDL, FCONDL, 0), +/* v9 */ fmovcc ("fmovdle", FM_DF, CONDLE, FCONDLE, 0), +/* v9 */ fmovcc ("fmovqle", FM_QF, CONDLE, FCONDLE, 0), +/* v9 */ fmovcc ("fmovsle", FM_SF, CONDLE, FCONDLE, 0), +/* v9 */ fmovicc ("fmovdleu", FM_DF, CONDLEU, 0), +/* v9 */ fmovicc ("fmovqleu", FM_QF, CONDLEU, 0), +/* v9 */ fmovicc ("fmovsleu", FM_SF, CONDLEU, 0), +/* v9 */ fmovfcc ("fmovdlg", FM_DF, FCONDLG, 0), +/* v9 */ fmovfcc ("fmovqlg", FM_QF, FCONDLG, 0), +/* v9 */ fmovfcc ("fmovslg", FM_SF, FCONDLG, 0), +/* v9 */ fmovicc ("fmovdlu", FM_DF, CONDLU, F_ALIAS), +/* v9 */ fmovicc ("fmovqlu", FM_QF, CONDLU, F_ALIAS), +/* v9 */ fmovicc ("fmovslu", FM_SF, CONDLU, F_ALIAS), +/* v9 */ fmovcc ("fmovdn", FM_DF, CONDN, FCONDN, 0), +/* v9 */ fmovcc ("fmovqn", FM_QF, CONDN, FCONDN, 0), +/* v9 */ fmovcc ("fmovsn", FM_SF, CONDN, FCONDN, 0), +/* v9 */ fmovcc ("fmovdne", FM_DF, CONDNE, FCONDNE, 0), +/* v9 */ fmovcc ("fmovqne", FM_QF, CONDNE, FCONDNE, 0), +/* v9 */ fmovcc ("fmovsne", FM_SF, CONDNE, FCONDNE, 0), +/* v9 */ fmovicc ("fmovdneg", FM_DF, CONDNEG, 0), +/* v9 */ fmovicc ("fmovqneg", FM_QF, CONDNEG, 0), +/* v9 */ fmovicc ("fmovsneg", FM_SF, CONDNEG, 0), +/* v9 */ fmovcc ("fmovdnz", FM_DF, CONDNZ, FCONDNZ, F_ALIAS), +/* v9 */ fmovcc ("fmovqnz", FM_QF, CONDNZ, FCONDNZ, F_ALIAS), +/* v9 */ fmovcc ("fmovsnz", FM_SF, CONDNZ, FCONDNZ, F_ALIAS), +/* v9 */ fmovfcc ("fmovdo", FM_DF, FCONDO, 0), +/* v9 */ fmovfcc ("fmovqo", FM_QF, FCONDO, 0), +/* v9 */ fmovfcc ("fmovso", FM_SF, FCONDO, 0), +/* v9 */ fmovicc ("fmovdpos", FM_DF, CONDPOS, 0), +/* v9 */ fmovicc ("fmovqpos", FM_QF, CONDPOS, 0), +/* v9 */ fmovicc ("fmovspos", FM_SF, CONDPOS, 0), +/* v9 */ fmovfcc ("fmovdu", FM_DF, FCONDU, 0), +/* v9 */ fmovfcc ("fmovqu", FM_QF, FCONDU, 0), +/* v9 */ fmovfcc ("fmovsu", FM_SF, FCONDU, 0), +/* v9 */ fmovfcc ("fmovdue", FM_DF, FCONDUE, 0), +/* v9 */ fmovfcc ("fmovque", FM_QF, FCONDUE, 0), +/* v9 */ fmovfcc ("fmovsue", FM_SF, FCONDUE, 0), +/* v9 */ fmovfcc ("fmovdug", FM_DF, FCONDUG, 0), +/* v9 */ fmovfcc ("fmovqug", FM_QF, FCONDUG, 0), +/* v9 */ fmovfcc ("fmovsug", FM_SF, FCONDUG, 0), +/* v9 */ fmovfcc ("fmovduge", FM_DF, FCONDUGE, 0), +/* v9 */ fmovfcc ("fmovquge", FM_QF, FCONDUGE, 0), +/* v9 */ fmovfcc ("fmovsuge", FM_SF, FCONDUGE, 0), +/* v9 */ fmovfcc ("fmovdul", FM_DF, FCONDUL, 0), +/* v9 */ fmovfcc ("fmovqul", FM_QF, FCONDUL, 0), +/* v9 */ fmovfcc ("fmovsul", FM_SF, FCONDUL, 0), +/* v9 */ fmovfcc ("fmovdule", FM_DF, FCONDULE, 0), +/* v9 */ fmovfcc ("fmovqule", FM_QF, FCONDULE, 0), +/* v9 */ fmovfcc ("fmovsule", FM_SF, FCONDULE, 0), +/* v9 */ fmovicc ("fmovdvc", FM_DF, CONDVC, 0), +/* v9 */ fmovicc ("fmovqvc", FM_QF, CONDVC, 0), +/* v9 */ fmovicc ("fmovsvc", FM_SF, CONDVC, 0), +/* v9 */ fmovicc ("fmovdvs", FM_DF, CONDVS, 0), +/* v9 */ fmovicc ("fmovqvs", FM_QF, CONDVS, 0), +/* v9 */ fmovicc ("fmovsvs", FM_SF, CONDVS, 0), +/* v9 */ fmovcc ("fmovdz", FM_DF, CONDZ, FCONDZ, F_ALIAS), +/* v9 */ fmovcc ("fmovqz", FM_QF, CONDZ, FCONDZ, F_ALIAS), +/* v9 */ fmovcc ("fmovsz", FM_SF, CONDZ, FCONDZ, F_ALIAS), + +#undef fmovicc /* v9 */ +#undef fmovfcc /* v9 */ +#undef fmovcc /* v9 */ +#undef FM_DF /* v9 */ +#undef FM_QF /* v9 */ +#undef FM_SF /* v9 */ + +#define brfc(opcode, mask, lose, flags) \ + { opcode, (mask), ANNUL|(lose), "l", flags|F_DELAYED, v6 }, \ + { opcode, (mask)|ANNUL, (lose), ",a l", flags|F_DELAYED, v6 } + +#define brfcx(opcode, mask, lose, flags) /* v9 */ \ + { opcode, FBFCC(0)|(mask)|BPRED, ANNUL|FBFCC(~0)|(lose), "6,G", flags|F_DELAYED, v9 }, \ + { opcode, FBFCC(0)|(mask)|BPRED, ANNUL|FBFCC(~0)|(lose), ",T 6,G", flags|F_DELAYED, v9 }, \ + { opcode, FBFCC(0)|(mask)|BPRED|ANNUL, FBFCC(~0)|(lose), ",a 6,G", flags|F_DELAYED, v9 }, \ + { opcode, FBFCC(0)|(mask)|BPRED|ANNUL, FBFCC(~0)|(lose), ",a,T 6,G", flags|F_DELAYED, v9 }, \ + { opcode, FBFCC(0)|(mask), ANNUL|BPRED|FBFCC(~0)|(lose), ",N 6,G", flags|F_DELAYED, v9 }, \ + { opcode, FBFCC(0)|(mask)|ANNUL, BPRED|FBFCC(~0)|(lose), ",a,N 6,G", flags|F_DELAYED, v9 }, \ + { opcode, FBFCC(1)|(mask)|BPRED, ANNUL|FBFCC(~1)|(lose), "7,G", flags|F_DELAYED, v9 }, \ + { opcode, FBFCC(1)|(mask)|BPRED, ANNUL|FBFCC(~1)|(lose), ",T 7,G", flags|F_DELAYED, v9 }, \ + { opcode, FBFCC(1)|(mask)|BPRED|ANNUL, FBFCC(~1)|(lose), ",a 7,G", flags|F_DELAYED, v9 }, \ + { opcode, FBFCC(1)|(mask)|BPRED|ANNUL, FBFCC(~1)|(lose), ",a,T 7,G", flags|F_DELAYED, v9 }, \ + { opcode, FBFCC(1)|(mask), ANNUL|BPRED|FBFCC(~1)|(lose), ",N 7,G", flags|F_DELAYED, v9 }, \ + { opcode, FBFCC(1)|(mask)|ANNUL, BPRED|FBFCC(~1)|(lose), ",a,N 7,G", flags|F_DELAYED, v9 }, \ + { opcode, FBFCC(2)|(mask)|BPRED, ANNUL|FBFCC(~2)|(lose), "8,G", flags|F_DELAYED, v9 }, \ + { opcode, FBFCC(2)|(mask)|BPRED, ANNUL|FBFCC(~2)|(lose), ",T 8,G", flags|F_DELAYED, v9 }, \ + { opcode, FBFCC(2)|(mask)|BPRED|ANNUL, FBFCC(~2)|(lose), ",a 8,G", flags|F_DELAYED, v9 }, \ + { opcode, FBFCC(2)|(mask)|BPRED|ANNUL, FBFCC(~2)|(lose), ",a,T 8,G", flags|F_DELAYED, v9 }, \ + { opcode, FBFCC(2)|(mask), ANNUL|BPRED|FBFCC(~2)|(lose), ",N 8,G", flags|F_DELAYED, v9 }, \ + { opcode, FBFCC(2)|(mask)|ANNUL, BPRED|FBFCC(~2)|(lose), ",a,N 8,G", flags|F_DELAYED, v9 }, \ + { opcode, FBFCC(3)|(mask)|BPRED, ANNUL|FBFCC(~3)|(lose), "9,G", flags|F_DELAYED, v9 }, \ + { opcode, FBFCC(3)|(mask)|BPRED, ANNUL|FBFCC(~3)|(lose), ",T 9,G", flags|F_DELAYED, v9 }, \ + { opcode, FBFCC(3)|(mask)|BPRED|ANNUL, FBFCC(~3)|(lose), ",a 9,G", flags|F_DELAYED, v9 }, \ + { opcode, FBFCC(3)|(mask)|BPRED|ANNUL, FBFCC(~3)|(lose), ",a,T 9,G", flags|F_DELAYED, v9 }, \ + { opcode, FBFCC(3)|(mask), ANNUL|BPRED|FBFCC(~3)|(lose), ",N 9,G", flags|F_DELAYED, v9 }, \ + { opcode, FBFCC(3)|(mask)|ANNUL, BPRED|FBFCC(~3)|(lose), ",a,N 9,G", flags|F_DELAYED, v9 } + +/* v9: We must put `brfcx' before `brfc', to ensure that we never match + v9: something against an expression unless it is an expression. Otherwise, + v9: we end up with undefined symbol tables entries, because they get added, + v9: but are not deleted if the pattern fails to match. */ + +#define condfc(fop, cop, mask, flags) \ + brfcx(fop, F2(0, 5)|COND(mask), F2(~0, ~5)|COND(~(mask)), flags), /* v9 */ \ + brfc(fop, F2(0, 6)|COND(mask), F2(~0, ~6)|COND(~(mask)), flags), \ + brfc(cop, F2(0, 7)|COND(mask), F2(~0, ~7)|COND(~(mask)), flags) + +#define condf(fop, mask, flags) \ + brfcx(fop, F2(0, 5)|COND(mask), F2(~0, ~5)|COND(~(mask)), flags), /* v9 */ \ + brfc(fop, F2(0, 6)|COND(mask), F2(~0, ~6)|COND(~(mask)), flags) + +condfc("fb", "cb", 0x8, 0), +condfc("fba", "cba", 0x8, F_ALIAS), +condfc("fbe", "cb0", 0x9, 0), +condf("fbz", 0x9, F_ALIAS), +condfc("fbg", "cb2", 0x6, 0), +condfc("fbge", "cb02", 0xb, 0), +condfc("fbl", "cb1", 0x4, 0), +condfc("fble", "cb01", 0xd, 0), +condfc("fblg", "cb12", 0x2, 0), +condfc("fbn", "cbn", 0x0, 0), +condfc("fbne", "cb123", 0x1, 0), +condf("fbnz", 0x1, F_ALIAS), +condfc("fbo", "cb012", 0xf, 0), +condfc("fbu", "cb3", 0x7, 0), +condfc("fbue", "cb03", 0xa, 0), +condfc("fbug", "cb23", 0x5, 0), +condfc("fbuge", "cb023", 0xc, 0), +condfc("fbul", "cb13", 0x3, 0), +condfc("fbule", "cb013", 0xe, 0), + +#undef condfc +#undef brfc +#undef brfcx /* v9 */ + +{ "jmp", F3(2, 0x38, 0), F3(~2, ~0x38, ~0)|RD_G0|ASI(~0), "1+2", F_UNBR|F_DELAYED, v6 }, /* jmpl rs1+rs2,%g0 */ +{ "jmp", F3(2, 0x38, 0), F3(~2, ~0x38, ~0)|RD_G0|ASI_RS2(~0), "1", F_UNBR|F_DELAYED, v6 }, /* jmpl rs1+%g0,%g0 */ +{ "jmp", F3(2, 0x38, 1), F3(~2, ~0x38, ~1)|RD_G0, "1+i", F_UNBR|F_DELAYED, v6 }, /* jmpl rs1+i,%g0 */ +{ "jmp", F3(2, 0x38, 1), F3(~2, ~0x38, ~1)|RD_G0, "i+1", F_UNBR|F_DELAYED, v6 }, /* jmpl i+rs1,%g0 */ +{ "jmp", F3(2, 0x38, 1), F3(~2, ~0x38, ~1)|RD_G0|RS1_G0, "i", F_UNBR|F_DELAYED, v6 }, /* jmpl %g0+i,%g0 */ +{ "jmp", F3(2, 0x38, 1), F3(~2, ~0x38, ~1)|RD_G0|SIMM13(~0), "1", F_UNBR|F_DELAYED, v6 }, /* jmpl rs1+0,%g0 */ + +{ "nop", F2(0, 4), 0xfeffffff, "", 0, v6 }, /* sethi 0, %g0 */ + +{ "set", F2(0x0, 0x4), F2(~0x0, ~0x4), "Sh,d", F_ALIAS, v6 }, + +{ "sethi", F2(0x0, 0x4), F2(~0x0, ~0x4), "h,d", 0, v6 }, + +{ "taddcc", F3(2, 0x20, 0), F3(~2, ~0x20, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "taddcc", F3(2, 0x20, 1), F3(~2, ~0x20, ~1), "1,i,d", 0, v6 }, +{ "taddcc", F3(2, 0x20, 1), F3(~2, ~0x20, ~1), "i,1,d", 0, v6 }, +{ "taddcctv", F3(2, 0x22, 0), F3(~2, ~0x22, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "taddcctv", F3(2, 0x22, 1), F3(~2, ~0x22, ~1), "1,i,d", 0, v6 }, +{ "taddcctv", F3(2, 0x22, 1), F3(~2, ~0x22, ~1), "i,1,d", 0, v6 }, + +{ "tsubcc", F3(2, 0x21, 0), F3(~2, ~0x21, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "tsubcc", F3(2, 0x21, 1), F3(~2, ~0x21, ~1), "1,i,d", 0, v6 }, +{ "tsubcctv", F3(2, 0x23, 0), F3(~2, ~0x23, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "tsubcctv", F3(2, 0x23, 1), F3(~2, ~0x23, ~1), "1,i,d", 0, v6 }, + +{ "unimp", F2(0x0, 0x0), 0xffc00000, "n", 0, v6notv9 }, +{ "illtrap", F2(0, 0), F2(~0, ~0)|RD_G0, "n", 0, v9 }, + +/* This *is* a commutative instruction. */ +{ "xnor", F3(2, 0x07, 0), F3(~2, ~0x07, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "xnor", F3(2, 0x07, 1), F3(~2, ~0x07, ~1), "1,i,d", 0, v6 }, +{ "xnor", F3(2, 0x07, 1), F3(~2, ~0x07, ~1), "i,1,d", 0, v6 }, +/* This *is* a commutative instruction. */ +{ "xnorcc", F3(2, 0x17, 0), F3(~2, ~0x17, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "xnorcc", F3(2, 0x17, 1), F3(~2, ~0x17, ~1), "1,i,d", 0, v6 }, +{ "xnorcc", F3(2, 0x17, 1), F3(~2, ~0x17, ~1), "i,1,d", 0, v6 }, +{ "xor", F3(2, 0x03, 0), F3(~2, ~0x03, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "xor", F3(2, 0x03, 1), F3(~2, ~0x03, ~1), "1,i,d", 0, v6 }, +{ "xor", F3(2, 0x03, 1), F3(~2, ~0x03, ~1), "i,1,d", 0, v6 }, +{ "xorcc", F3(2, 0x13, 0), F3(~2, ~0x13, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "xorcc", F3(2, 0x13, 1), F3(~2, ~0x13, ~1), "1,i,d", 0, v6 }, +{ "xorcc", F3(2, 0x13, 1), F3(~2, ~0x13, ~1), "i,1,d", 0, v6 }, + +{ "not", F3(2, 0x07, 0), F3(~2, ~0x07, ~0)|ASI(~0), "1,d", F_ALIAS, v6 }, /* xnor rs1,%0,rd */ +{ "not", F3(2, 0x07, 0), F3(~2, ~0x07, ~0)|ASI(~0), "r", F_ALIAS, v6 }, /* xnor rd,%0,rd */ + +{ "btog", F3(2, 0x03, 0), F3(~2, ~0x03, ~0)|ASI(~0), "2,r", F_ALIAS, v6 }, /* xor rd,rs2,rd */ +{ "btog", F3(2, 0x03, 1), F3(~2, ~0x03, ~1), "i,r", F_ALIAS, v6 }, /* xor rd,i,rd */ + +/* FPop1 and FPop2 are not instructions. Don't accept them. */ + +{ "fdtoi", F3F(2, 0x34, 0x0d2), F3F(~2, ~0x34, ~0x0d2)|RS1_G0, "B,g", 0, v6 }, +{ "fstoi", F3F(2, 0x34, 0x0d1), F3F(~2, ~0x34, ~0x0d1)|RS1_G0, "f,g", 0, v6 }, +{ "fqtoi", F3F(2, 0x34, 0x0d3), F3F(~2, ~0x34, ~0x0d3)|RS1_G0, "R,g", 0, v8 }, + +{ "fdtox", F3F(2, 0x34, 0x082), F3F(~2, ~0x34, ~0x082)|RS1_G0, "B,g", 0, v9 }, +{ "fstox", F3F(2, 0x34, 0x081), F3F(~2, ~0x34, ~0x081)|RS1_G0, "f,g", 0, v9 }, +{ "fqtox", F3F(2, 0x34, 0x083), F3F(~2, ~0x34, ~0x083)|RS1_G0, "R,g", 0, v9 }, + +{ "fitod", F3F(2, 0x34, 0x0c8), F3F(~2, ~0x34, ~0x0c8)|RS1_G0, "f,H", 0, v6 }, +{ "fitos", F3F(2, 0x34, 0x0c4), F3F(~2, ~0x34, ~0x0c4)|RS1_G0, "f,g", 0, v6 }, +{ "fitoq", F3F(2, 0x34, 0x0cc), F3F(~2, ~0x34, ~0x0cc)|RS1_G0, "f,J", 0, v8 }, + +{ "fxtod", F3F(2, 0x34, 0x088), F3F(~2, ~0x34, ~0x088)|RS1_G0, "f,H", 0, v9 }, +{ "fxtos", F3F(2, 0x34, 0x084), F3F(~2, ~0x34, ~0x084)|RS1_G0, "f,g", 0, v9 }, +{ "fxtoq", F3F(2, 0x34, 0x08c), F3F(~2, ~0x34, ~0x08c)|RS1_G0, "f,J", 0, v9 }, + +{ "fdtoq", F3F(2, 0x34, 0x0ce), F3F(~2, ~0x34, ~0x0ce)|RS1_G0, "B,J", 0, v8 }, +{ "fdtos", F3F(2, 0x34, 0x0c6), F3F(~2, ~0x34, ~0x0c6)|RS1_G0, "B,g", 0, v6 }, +{ "fqtod", F3F(2, 0x34, 0x0cb), F3F(~2, ~0x34, ~0x0cb)|RS1_G0, "R,H", 0, v8 }, +{ "fqtos", F3F(2, 0x34, 0x0c7), F3F(~2, ~0x34, ~0x0c7)|RS1_G0, "R,g", 0, v8 }, +{ "fstod", F3F(2, 0x34, 0x0c9), F3F(~2, ~0x34, ~0x0c9)|RS1_G0, "f,H", 0, v6 }, +{ "fstoq", F3F(2, 0x34, 0x0cd), F3F(~2, ~0x34, ~0x0cd)|RS1_G0, "f,J", 0, v8 }, + +{ "fdivd", F3F(2, 0x34, 0x04e), F3F(~2, ~0x34, ~0x04e), "v,B,H", 0, v6 }, +{ "fdivq", F3F(2, 0x34, 0x04f), F3F(~2, ~0x34, ~0x04f), "V,R,J", 0, v8 }, +{ "fdivs", F3F(2, 0x34, 0x04d), F3F(~2, ~0x34, ~0x04d), "e,f,g", 0, v6 }, +{ "fmuld", F3F(2, 0x34, 0x04a), F3F(~2, ~0x34, ~0x04a), "v,B,H", 0, v6 }, +{ "fmulq", F3F(2, 0x34, 0x04b), F3F(~2, ~0x34, ~0x04b), "V,R,J", 0, v8 }, +{ "fmuls", F3F(2, 0x34, 0x049), F3F(~2, ~0x34, ~0x049), "e,f,g", 0, v6 }, + +{ "fdmulq", F3F(2, 0x34, 0x06e), F3F(~2, ~0x34, ~0x06e), "v,B,J", 0, v8 }, +{ "fsmuld", F3F(2, 0x34, 0x069), F3F(~2, ~0x34, ~0x069), "e,f,H", 0, v8 }, + +{ "fsqrtd", F3F(2, 0x34, 0x02a), F3F(~2, ~0x34, ~0x02a)|RS1_G0, "B,H", 0, v7 }, +{ "fsqrtq", F3F(2, 0x34, 0x02b), F3F(~2, ~0x34, ~0x02b)|RS1_G0, "R,J", 0, v8 }, +{ "fsqrts", F3F(2, 0x34, 0x029), F3F(~2, ~0x34, ~0x029)|RS1_G0, "f,g", 0, v7 }, + +{ "fabsd", F3F(2, 0x34, 0x00a), F3F(~2, ~0x34, ~0x00a)|RS1_G0, "B,H", 0, v9 }, +{ "fabsq", F3F(2, 0x34, 0x00b), F3F(~2, ~0x34, ~0x00b)|RS1_G0, "R,J", 0, v9 }, +{ "fabss", F3F(2, 0x34, 0x009), F3F(~2, ~0x34, ~0x009)|RS1_G0, "f,g", 0, v6 }, +{ "fmovd", F3F(2, 0x34, 0x002), F3F(~2, ~0x34, ~0x002)|RS1_G0, "B,H", 0, v9 }, +{ "fmovq", F3F(2, 0x34, 0x003), F3F(~2, ~0x34, ~0x003)|RS1_G0, "R,J", 0, v9 }, +{ "fmovs", F3F(2, 0x34, 0x001), F3F(~2, ~0x34, ~0x001)|RS1_G0, "f,g", 0, v6 }, +{ "fnegd", F3F(2, 0x34, 0x006), F3F(~2, ~0x34, ~0x006)|RS1_G0, "B,H", 0, v9 }, +{ "fnegq", F3F(2, 0x34, 0x007), F3F(~2, ~0x34, ~0x007)|RS1_G0, "R,J", 0, v9 }, +{ "fnegs", F3F(2, 0x34, 0x005), F3F(~2, ~0x34, ~0x005)|RS1_G0, "f,g", 0, v6 }, + +{ "faddd", F3F(2, 0x34, 0x042), F3F(~2, ~0x34, ~0x042), "v,B,H", 0, v6 }, +{ "faddq", F3F(2, 0x34, 0x043), F3F(~2, ~0x34, ~0x043), "V,R,J", 0, v8 }, +{ "fadds", F3F(2, 0x34, 0x041), F3F(~2, ~0x34, ~0x041), "e,f,g", 0, v6 }, +{ "fsubd", F3F(2, 0x34, 0x046), F3F(~2, ~0x34, ~0x046), "v,B,H", 0, v6 }, +{ "fsubq", F3F(2, 0x34, 0x047), F3F(~2, ~0x34, ~0x047), "V,R,J", 0, v8 }, +{ "fsubs", F3F(2, 0x34, 0x045), F3F(~2, ~0x34, ~0x045), "e,f,g", 0, v6 }, + +#define CMPFCC(x) (((x)&0x3)<<25) + +{ "fcmpd", F3F(2, 0x35, 0x052), F3F(~2, ~0x35, ~0x052)|RD_G0, "v,B", 0, v6 }, +{ "fcmpd", CMPFCC(0)|F3F(2, 0x35, 0x052), CMPFCC(~0)|F3F(~2, ~0x35, ~0x052), "6,v,B", 0, v9 }, +{ "fcmpd", CMPFCC(1)|F3F(2, 0x35, 0x052), CMPFCC(~1)|F3F(~2, ~0x35, ~0x052), "7,v,B", 0, v9 }, +{ "fcmpd", CMPFCC(2)|F3F(2, 0x35, 0x052), CMPFCC(~2)|F3F(~2, ~0x35, ~0x052), "8,v,B", 0, v9 }, +{ "fcmpd", CMPFCC(3)|F3F(2, 0x35, 0x052), CMPFCC(~3)|F3F(~2, ~0x35, ~0x052), "9,v,B", 0, v9 }, +{ "fcmped", F3F(2, 0x35, 0x056), F3F(~2, ~0x35, ~0x056)|RD_G0, "v,B", 0, v6 }, +{ "fcmped", CMPFCC(0)|F3F(2, 0x35, 0x056), CMPFCC(~0)|F3F(~2, ~0x35, ~0x056), "6,v,B", 0, v9 }, +{ "fcmped", CMPFCC(1)|F3F(2, 0x35, 0x056), CMPFCC(~1)|F3F(~2, ~0x35, ~0x056), "7,v,B", 0, v9 }, +{ "fcmped", CMPFCC(2)|F3F(2, 0x35, 0x056), CMPFCC(~2)|F3F(~2, ~0x35, ~0x056), "8,v,B", 0, v9 }, +{ "fcmped", CMPFCC(3)|F3F(2, 0x35, 0x056), CMPFCC(~3)|F3F(~2, ~0x35, ~0x056), "9,v,B", 0, v9 }, +{ "fcmpq", F3F(2, 0x34, 0x053), F3F(~2, ~0x34, ~0x053)|RD_G0, "V,R", 0, v8 }, +{ "fcmpq", CMPFCC(0)|F3F(2, 0x35, 0x053), CMPFCC(~0)|F3F(~2, ~0x35, ~0x053), "6,V,R", 0, v9 }, +{ "fcmpq", CMPFCC(1)|F3F(2, 0x35, 0x053), CMPFCC(~1)|F3F(~2, ~0x35, ~0x053), "7,V,R", 0, v9 }, +{ "fcmpq", CMPFCC(2)|F3F(2, 0x35, 0x053), CMPFCC(~2)|F3F(~2, ~0x35, ~0x053), "8,V,R", 0, v9 }, +{ "fcmpq", CMPFCC(3)|F3F(2, 0x35, 0x053), CMPFCC(~3)|F3F(~2, ~0x35, ~0x053), "9,V,R", 0, v9 }, +{ "fcmpeq", F3F(2, 0x34, 0x057), F3F(~2, ~0x34, ~0x057)|RD_G0, "V,R", 0, v8 }, +{ "fcmpeq", CMPFCC(0)|F3F(2, 0x35, 0x057), CMPFCC(~0)|F3F(~2, ~0x35, ~0x057), "6,V,R", 0, v9 }, +{ "fcmpeq", CMPFCC(1)|F3F(2, 0x35, 0x057), CMPFCC(~1)|F3F(~2, ~0x35, ~0x057), "7,V,R", 0, v9 }, +{ "fcmpeq", CMPFCC(2)|F3F(2, 0x35, 0x057), CMPFCC(~2)|F3F(~2, ~0x35, ~0x057), "8,V,R", 0, v9 }, +{ "fcmpeq", CMPFCC(3)|F3F(2, 0x35, 0x057), CMPFCC(~3)|F3F(~2, ~0x35, ~0x057), "9,V,R", 0, v9 }, +{ "fcmps", F3F(2, 0x35, 0x051), F3F(~2, ~0x35, ~0x051)|RD_G0, "e,f", 0, v6 }, +{ "fcmps", CMPFCC(0)|F3F(2, 0x35, 0x051), CMPFCC(~0)|F3F(~2, ~0x35, ~0x051), "6,e,f", 0, v9 }, +{ "fcmps", CMPFCC(1)|F3F(2, 0x35, 0x051), CMPFCC(~1)|F3F(~2, ~0x35, ~0x051), "7,e,f", 0, v9 }, +{ "fcmps", CMPFCC(2)|F3F(2, 0x35, 0x051), CMPFCC(~2)|F3F(~2, ~0x35, ~0x051), "8,e,f", 0, v9 }, +{ "fcmps", CMPFCC(3)|F3F(2, 0x35, 0x051), CMPFCC(~3)|F3F(~2, ~0x35, ~0x051), "9,e,f", 0, v9 }, +{ "fcmpes", F3F(2, 0x35, 0x055), F3F(~2, ~0x35, ~0x055)|RD_G0, "e,f", 0, v6 }, +{ "fcmpes", CMPFCC(0)|F3F(2, 0x35, 0x055), CMPFCC(~0)|F3F(~2, ~0x35, ~0x055), "6,e,f", 0, v9 }, +{ "fcmpes", CMPFCC(1)|F3F(2, 0x35, 0x055), CMPFCC(~1)|F3F(~2, ~0x35, ~0x055), "7,e,f", 0, v9 }, +{ "fcmpes", CMPFCC(2)|F3F(2, 0x35, 0x055), CMPFCC(~2)|F3F(~2, ~0x35, ~0x055), "8,e,f", 0, v9 }, +{ "fcmpes", CMPFCC(3)|F3F(2, 0x35, 0x055), CMPFCC(~3)|F3F(~2, ~0x35, ~0x055), "9,e,f", 0, v9 }, + +/* These Extended FPop (FIFO) instructions are new in the Fujitsu + MB86934, replacing the CPop instructions from v6 and later + processors. */ + +#define EFPOP1_2(name, op, args) { name, F3F(2, 0x36, op), F3F(~2, ~0x36, ~op)|RS1_G0, args, 0, sparclite } +#define EFPOP1_3(name, op, args) { name, F3F(2, 0x36, op), F3F(~2, ~0x36, ~op), args, 0, sparclite } +#define EFPOP2_2(name, op, args) { name, F3F(2, 0x37, op), F3F(~2, ~0x37, ~op)|RD_G0, args, 0, sparclite } + +EFPOP1_2 ("efitod", 0x0c8, "f,H"), +EFPOP1_2 ("efitos", 0x0c4, "f,g"), +EFPOP1_2 ("efdtoi", 0x0d2, "B,g"), +EFPOP1_2 ("efstoi", 0x0d1, "f,g"), +EFPOP1_2 ("efstod", 0x0c9, "f,H"), +EFPOP1_2 ("efdtos", 0x0c6, "B,g"), +EFPOP1_2 ("efmovs", 0x001, "f,g"), +EFPOP1_2 ("efnegs", 0x005, "f,g"), +EFPOP1_2 ("efabss", 0x009, "f,g"), +EFPOP1_2 ("efsqrtd", 0x02a, "B,H"), +EFPOP1_2 ("efsqrts", 0x029, "f,g"), +EFPOP1_3 ("efaddd", 0x042, "v,B,H"), +EFPOP1_3 ("efadds", 0x041, "e,f,g"), +EFPOP1_3 ("efsubd", 0x046, "v,B,H"), +EFPOP1_3 ("efsubs", 0x045, "e,f,g"), +EFPOP1_3 ("efdivd", 0x04e, "v,B,H"), +EFPOP1_3 ("efdivs", 0x04d, "e,f,g"), +EFPOP1_3 ("efmuld", 0x04a, "v,B,H"), +EFPOP1_3 ("efmuls", 0x049, "e,f,g"), +EFPOP1_3 ("efsmuld", 0x069, "e,f,H"), +EFPOP2_2 ("efcmpd", 0x052, "v,B"), +EFPOP2_2 ("efcmped", 0x056, "v,B"), +EFPOP2_2 ("efcmps", 0x051, "e,f"), +EFPOP2_2 ("efcmpes", 0x055, "e,f"), + +#undef EFPOP1_2 +#undef EFPOP1_3 +#undef EFPOP2_2 + +/* These are marked F_ALIAS, so that they won't conflict with sparclite insns + present. Otherwise, the F_ALIAS flag is ignored. */ +{ "cpop1", F3(2, 0x36, 0), F3(~2, ~0x36, ~1), "[1+2],d", F_ALIAS, v6notv9 }, +{ "cpop2", F3(2, 0x37, 0), F3(~2, ~0x37, ~1), "[1+2],d", F_ALIAS, v6notv9 }, + +/* sparclet specific insns */ + +commuteop ("umac", 0x3e, sparclet), +commuteop ("smac", 0x3f, sparclet), +commuteop ("umacd", 0x2e, sparclet), +commuteop ("smacd", 0x2f, sparclet), +commuteop ("umuld", 0x09, sparclet), +commuteop ("smuld", 0x0d, sparclet), + +{ "shuffle", F3(2, 0x2d, 0), F3(~2, ~0x2d, ~0)|ASI(~0), "1,2,d", 0, sparclet }, +{ "shuffle", F3(2, 0x2d, 1), F3(~2, ~0x2d, ~1), "1,i,d", 0, sparclet }, + +{ "crdcxt", F3(2, 0x36, 0)|ASI(4), F3(~2, ~0x36, ~0)|ASI(~4)|RS2(~0), "U,d", 0, sparclet }, +{ "cwrcxt", F3(2, 0x36, 0)|ASI(3), F3(~2, ~0x36, ~0)|ASI(~3)|RS2(~0), "1,u", 0, sparclet }, +{ "cpush", F3(2, 0x36, 0)|ASI(0), F3(~2, ~0x36, ~0)|ASI(~0)|RD(~0), "1,2", 0, sparclet }, +{ "cpusha", F3(2, 0x36, 0)|ASI(1), F3(~2, ~0x36, ~0)|ASI(~1)|RD(~0), "1,2", 0, sparclet }, +{ "cpull", F3(2, 0x36, 0)|ASI(2), F3(~2, ~0x36, ~0)|ASI(~2)|RS1(~0)|RS2(~0), "d", 0, sparclet }, + +/* sparclet coprocessor branch insns */ +/* FIXME: We have to mark these as aliases until we can sort opcodes based + on selected cpu. */ +#define slcbcc2(opcode, mask, lose) \ + { opcode, (mask), ANNUL|(lose), "l", F_DELAYED|F_CONDBR|F_ALIAS, sparclet }, \ + { opcode, (mask)|ANNUL, (lose), ",a l", F_DELAYED|F_CONDBR|F_ALIAS, sparclet } +#define slcbcc(opcode, mask) \ + slcbcc2(opcode, F2(0, 7)|COND(mask), F2(~0, ~7)|COND(~(mask))) + +/*slcbcc("cbn", 0), - already defined */ +slcbcc("cbe", 1), +slcbcc("cbf", 2), +slcbcc("cbef", 3), +slcbcc("cbr", 4), +slcbcc("cber", 5), +slcbcc("cbfr", 6), +slcbcc("cbefr", 7), +/*slcbcc("cba", 8), - already defined */ +slcbcc("cbne", 9), +slcbcc("cbnf", 10), +slcbcc("cbnef", 11), +slcbcc("cbnr", 12), +slcbcc("cbner", 13), +slcbcc("cbnfr", 14), +slcbcc("cbnefr", 15), + +#undef slcbcc2 +#undef slcbcc + +/* More v9 specific insns */ + +#define IMPDEP(name, code) \ +{ name, F3(2, code, 0), F3(~2, ~code, ~0)|ASI(~0), "1,2,d", 0, v9 }, \ +{ name, F3(2, code, 1), F3(~2, ~code, ~1), "1,i,d", 0, v9 }, \ +{ name, F3(2, code, 0), F3(~2, ~code, ~0), "x,1,2,d", 0, v9 }, \ +{ name, F3(2, code, 0), F3(~2, ~code, ~0), "x,e,f,g", 0, v9 } + +IMPDEP ("impdep1", 0x36), +IMPDEP ("impdep2", 0x37), + +#undef IMPDEP + +{ "casa", F3(3, 0x3c, 0), F3(~3, ~0x3c, ~0), "[1]A,2,d", 0, v9 }, +{ "casa", F3(3, 0x3c, 1), F3(~3, ~0x3c, ~1), "[1]o,2,d", 0, v9 }, +{ "casxa", F3(3, 0x3e, 0), F3(~3, ~0x3e, ~0), "[1]A,2,d", 0, v9 }, +{ "casxa", F3(3, 0x3e, 1), F3(~3, ~0x3e, ~1), "[1]o,2,d", 0, v9 }, + +/* v9 synthetic insns */ +/* FIXME: still missing "signx d", and "clruw d". Can't be done here. */ +{ "iprefetch", F2(0, 1)|(2<<20)|BPRED, F2(~0, ~1)|(1<<20)|ANNUL|COND(~0), "G", 0, v9 }, /* bn,a,pt %xcc,label */ +{ "signx", F3(2, 0x27, 0), F3(~2, ~0x27, ~0)|(1<<12)|ASI(~0)|RS2_G0, "1,d", F_ALIAS, v9 }, /* sra rs1,%g0,rd */ +{ "clruw", F3(2, 0x26, 0), F3(~2, ~0x26, ~0)|(1<<12)|ASI(~0)|RS2_G0, "1,d", F_ALIAS, v9 }, /* srl rs1,%g0,rd */ +{ "cas", F3(3, 0x3c, 0)|ASI(0x80), F3(~3, ~0x3c, ~0)|ASI(~0x80), "[1],2,d", F_ALIAS, v9 }, /* casa [rs1]ASI_P,rs2,rd */ +{ "casl", F3(3, 0x3c, 0)|ASI(0x88), F3(~3, ~0x3c, ~0)|ASI(~0x88), "[1],2,d", F_ALIAS, v9 }, /* casa [rs1]ASI_P_L,rs2,rd */ +{ "casx", F3(3, 0x3e, 0)|ASI(0x80), F3(~3, ~0x3e, ~0)|ASI(~0x80), "[1],2,d", F_ALIAS, v9 }, /* casxa [rs1]ASI_P,rs2,rd */ +{ "casxl", F3(3, 0x3e, 0)|ASI(0x88), F3(~3, ~0x3e, ~0)|ASI(~0x88), "[1],2,d", F_ALIAS, v9 }, /* casxa [rs1]ASI_P_L,rs2,rd */ + +/* Ultrasparc extensions */ +/* FIXME: lots more to go */ +{ "shutdown", F3F(2, 0x36, 0x80), F3(~2, ~0x36, ~0x80)|RD_G0|RS1_G0|RS2_G0, "", 0, v9a }, + +}; + +const int sparc_num_opcodes = ((sizeof sparc_opcodes)/(sizeof sparc_opcodes[0])); + +/* Utilities for argument parsing. */ + +typedef struct +{ + int value; + char *name; +} arg; + +/* Look up NAME in TABLE. */ + +static int +lookup_name (table, name) + arg *table; + char *name; +{ + arg *p; + + for (p = table; p->name; ++p) + if (strcmp (name, p->name) == 0) + return p->value; + + return -1; +} + +/* Look up VALUE in TABLE. */ + +static char * +lookup_value (table, value) + arg *table; + int value; +{ + arg *p; + + for (p = table; p->name; ++p) + if (value == p->value) + return p->name; + + return (char *) 0; +} + +/* Handle ASI's. */ + +static arg asi_table[] = +{ + { 0x10, "#ASI_AIUP" }, + { 0x11, "#ASI_AIUS" }, + { 0x18, "#ASI_AIUP_L" }, + { 0x19, "#ASI_AIUS_L" }, + { 0x80, "#ASI_P" }, + { 0x81, "#ASI_S" }, + { 0x82, "#ASI_PNF" }, + { 0x83, "#ASI_SNF" }, + { 0x88, "#ASI_P_L" }, + { 0x89, "#ASI_S_L" }, + { 0x8a, "#ASI_PNF_L" }, + { 0x8b, "#ASI_SNF_L" }, + { 0x10, "#ASI_AS_IF_USER_PRIMARY" }, + { 0x11, "#ASI_AS_IF_USER_SECONDARY" }, + { 0x18, "#ASI_AS_IF_USER_PRIMARY_L" }, + { 0x19, "#ASI_AS_IF_USER_SECONDARY_L" }, + { 0x80, "#ASI_PRIMARY" }, + { 0x81, "#ASI_SECONDARY" }, + { 0x82, "#ASI_PRIMARY_NOFAULT" }, + { 0x83, "#ASI_SECONDARY_NOFAULT" }, + { 0x88, "#ASI_PRIMARY_LITTLE" }, + { 0x89, "#ASI_SECONDARY_LITTLE" }, + { 0x8a, "#ASI_PRIMARY_NOFAULT_LITTLE" }, + { 0x8b, "#ASI_SECONDARY_NOFAULT_LITTLE" }, + { 0, 0 } +}; + +/* Return the value for ASI NAME, or -1 if not found. */ + +int +sparc_encode_asi (name) + char *name; +{ + return lookup_name (asi_table, name); +} + +/* Return the name for ASI value VALUE or NULL if not found. */ + +char * +sparc_decode_asi (value) + int value; +{ + return lookup_value (asi_table, value); +} + +/* Handle membar masks. */ + +static arg membar_table[] = +{ + { 0x40, "#Sync" }, + { 0x20, "#MemIssue" }, + { 0x10, "#Lookaside" }, + { 0x08, "#StoreStore" }, + { 0x04, "#LoadStore" }, + { 0x02, "#StoreLoad" }, + { 0x01, "#LoadLoad" }, + { 0, 0 } +}; + +/* Return the value for membar arg NAME, or -1 if not found. */ + +int +sparc_encode_membar (name) + char *name; +{ + return lookup_name (membar_table, name); +} + +/* Return the name for membar value VALUE or NULL if not found. */ + +char * +sparc_decode_membar (value) + int value; +{ + return lookup_value (membar_table, value); +} + +/* Handle prefetch args. */ + +static arg prefetch_table[] = +{ + { 0, "#n_reads" }, + { 1, "#one_read" }, + { 2, "#n_writes" }, + { 3, "#one_write" }, + { 4, "#page" }, + { 0, 0 } +}; + +/* Return the value for prefetch arg NAME, or -1 if not found. */ + +int +sparc_encode_prefetch (name) + char *name; +{ + return lookup_name (prefetch_table, name); +} + +/* Return the name for prefetch value VALUE or NULL if not found. */ + +char * +sparc_decode_prefetch (value) + int value; +{ + return lookup_value (prefetch_table, value); +} + +/* Handle sparclet coprocessor registers. */ + +static arg sparclet_cpreg_table[] = +{ + { 0, "%ccsr" }, + { 1, "%ccfr" }, + { 2, "%cccrcr" }, + { 3, "%ccpr" }, + { 0, 0 } +}; + +/* Return the value for sparclet cpreg arg NAME, or -1 if not found. */ + +int +sparc_encode_sparclet_cpreg (name) + char *name; +{ + return lookup_name (sparclet_cpreg_table, name); +} + +/* Return the name for sparclet cpreg value VALUE or NULL if not found. */ + +char * +sparc_decode_sparclet_cpreg (value) + int value; +{ + return lookup_value (sparclet_cpreg_table, value); +} diff --git a/opcode/sparc.h b/opcode/sparc.h new file mode 100644 index 000000000..b9281e607 --- /dev/null +++ b/opcode/sparc.h @@ -0,0 +1,220 @@ +/* Definitions for opcode table for the sparc. + Copyright (C) 1989, 1991, 1992, 1995, 1996 Free Software Foundation, Inc. + +This file is part of GAS, the GNU Assembler, GDB, the GNU debugger, and +the GNU Binutils. + +GAS/GDB is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GAS/GDB 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 GAS or GDB; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* The SPARC opcode table (and other related data) is defined in + the opcodes library in sparc-opc.c. If you change anything here, make + sure you fix up that file, and vice versa. */ + + /* FIXME-someday: perhaps the ,a's and such should be embedded in the + instruction's name rather than the args. This would make gas faster, pinsn + slower, but would mess up some macros a bit. xoxorich. */ + +/* List of instruction sets variations. + These values are such that each element is either a superset of a + preceding each one or they conflict in which case SPARC_OPCODE_CONFLICT_P + returns non-zero. + The values are indices into `sparc_opcode_archs' defined in sparc-opc.c. + Don't change this without updating sparc-opc.c. */ + +enum sparc_opcode_arch_val { + SPARC_OPCODE_ARCH_V6 = 0, + SPARC_OPCODE_ARCH_V7, + SPARC_OPCODE_ARCH_V8, + SPARC_OPCODE_ARCH_SPARCLET, + SPARC_OPCODE_ARCH_SPARCLITE, + /* v9 variants must appear last */ + SPARC_OPCODE_ARCH_V9, + SPARC_OPCODE_ARCH_V9A, /* v9 with ultrasparc additions */ + SPARC_OPCODE_ARCH_BAD /* error return from sparc_opcode_lookup_arch */ +}; + +/* The highest architecture in the table. */ +#define SPARC_OPCODE_ARCH_MAX (SPARC_OPCODE_ARCH_BAD - 1) + +/* Table of cpu variants. */ + +struct sparc_opcode_arch { + const char *name; + /* Mask of sparc_opcode_arch_val's supported. + EG: For v7 this would be ((1 << v6) | (1 << v7)). */ + /* These are short's because sparc_opcode.architecture is. */ + short supported; +}; + +extern const struct sparc_opcode_arch sparc_opcode_archs[]; + +/* Given architecture name, look up it's sparc_opcode_arch_val value. */ +extern enum sparc_opcode_arch_val sparc_opcode_lookup_arch (); + +/* Return the bitmask of supported architectures for ARCH. */ +#define SPARC_OPCODE_SUPPORTED(ARCH) (sparc_opcode_archs[ARCH].supported) + +/* Non-zero if ARCH1 conflicts with ARCH2. + IE: ARCH1 as a supported bit set that ARCH2 doesn't, and vice versa. */ +#define SPARC_OPCODE_CONFLICT_P(ARCH1, ARCH2) \ +(((SPARC_OPCODE_SUPPORTED (ARCH1) & SPARC_OPCODE_SUPPORTED (ARCH2)) \ + != SPARC_OPCODE_SUPPORTED (ARCH1)) \ + && ((SPARC_OPCODE_SUPPORTED (ARCH1) & SPARC_OPCODE_SUPPORTED (ARCH2)) \ + != SPARC_OPCODE_SUPPORTED (ARCH2))) + +/* Structure of an opcode table entry. */ + +struct sparc_opcode { + const char *name; + unsigned long match; /* Bits that must be set. */ + unsigned long lose; /* Bits that must not be set. */ + const char *args; + /* This was called "delayed" in versions before the flags. */ + char flags; + short architecture; /* Bitmask of sparc_opcode_arch_val's. */ +}; + +#define F_DELAYED 1 /* Delayed branch */ +#define F_ALIAS 2 /* Alias for a "real" instruction */ +#define F_UNBR 4 /* Unconditional branch */ +#define F_CONDBR 8 /* Conditional branch */ +#define F_JSR 16 /* Subroutine call */ +/* FIXME: Add F_ANACHRONISTIC flag for v9. */ + +/* + +All sparc opcodes are 32 bits, except for the `set' instruction (really a +macro), which is 64 bits. It is handled as a special case. + +The match component is a mask saying which bits must match a particular +opcode in order for an instruction to be an instance of that opcode. + +The args component is a string containing one character for each operand of the +instruction. + +Kinds of operands: + # Number used by optimizer. It is ignored. + 1 rs1 register. + 2 rs2 register. + d rd register. + e frs1 floating point register. + v frs1 floating point register (double/even). + V frs1 floating point register (quad/multiple of 4). + f frs2 floating point register. + B frs2 floating point register (double/even). + R frs2 floating point register (quad/multiple of 4). + g frsd floating point register. + H frsd floating point register (double/even). + J frsd floating point register (quad/multiple of 4). + b crs1 coprocessor register + c crs2 coprocessor register + D crsd coprocessor register + m alternate space register (asr) in rd + M alternate space register (asr) in rs1 + h 22 high bits. + K MEMBAR mask (7 bits). (v9) + j 10 bit Immediate. (v9) + I 11 bit Immediate. (v9) + i 13 bit Immediate. + n 22 bit immediate. + k 2+14 bit PC relative immediate. (v9) + G 19 bit PC relative immediate. (v9) + l 22 bit PC relative immediate. + L 30 bit PC relative immediate. + a Annul. The annul bit is set. + A Alternate address space. Stored as 8 bits. + C Coprocessor state register. + F floating point state register. + p Processor state register. + N Branch predict clear ",pn" (v9) + T Branch predict set ",pt" (v9) + z %icc. (v9) + Z %xcc. (v9) + q Floating point queue. + r Single register that is both rs1 and rd. + O Single register that is both rs2 and rd. + Q Coprocessor queue. + S Special case. + t Trap base register. + w Window invalid mask register. + y Y register. + u sparclet coprocessor registers in rd position + U sparclet coprocessor registers in rs1 position + E %ccr. (v9) + s %fprs. (v9) + P %pc. (v9) + W %tick. (v9) + o %asi. (v9) + 6 %fcc0. (v9) + 7 %fcc1. (v9) + 8 %fcc2. (v9) + 9 %fcc3. (v9) + ! Privileged Register in rd (v9) + ? Privileged Register in rs1 (v9) + * Prefetch function constant. (v9) + x OPF field (v9 impdep). + +The following chars are unused: (note: ,[] are used as punctuation) +[XY3450] + +*/ + +#define OP2(x) (((x)&0x7) << 22) /* op2 field of format2 insns */ +#define OP3(x) (((x)&0x3f) << 19) /* op3 field of format3 insns */ +#define OP(x) ((unsigned)((x)&0x3) << 30) /* op field of all insns */ +#define OPF(x) (((x)&0x1ff) << 5) /* opf field of float insns */ +#define OPF_LOW5(x) OPF((x)&0x1f) /* v9 */ +#define F3F(x, y, z) (OP(x) | OP3(y) | OPF(z)) /* format3 float insns */ +#define F3I(x) (((x)&0x1) << 13) /* immediate field of format 3 insns */ +#define F2(x, y) (OP(x) | OP2(y)) /* format 2 insns */ +#define F3(x, y, z) (OP(x) | OP3(y) | F3I(z)) /* format3 insns */ +#define F1(x) (OP(x)) +#define DISP30(x) ((x)&0x3fffffff) +#define ASI(x) (((x)&0xff) << 5) /* asi field of format3 insns */ +#define RS2(x) ((x)&0x1f) /* rs2 field */ +#define SIMM13(x) ((x)&0x1fff) /* simm13 field */ +#define RD(x) (((x)&0x1f) << 25) /* destination register field */ +#define RS1(x) (((x)&0x1f) << 14) /* rs1 field */ +#define ASI_RS2(x) (SIMM13(x)) +#define MEMBAR(x) ((x)&0x7f) + +#define ANNUL (1<<29) +#define BPRED (1<<19) /* v9 */ +#define IMMED F3I(1) +#define RD_G0 RD(~0) +#define RS1_G0 RS1(~0) +#define RS2_G0 RS2(~0) + +extern struct sparc_opcode sparc_opcodes[]; +extern const int sparc_num_opcodes; + +int sparc_encode_asi (); +char *sparc_decode_asi (); +int sparc_encode_membar (); +char *sparc_decode_membar (); +int sparc_encode_prefetch (); +char *sparc_decode_prefetch (); +int sparc_encode_sparclet_cpreg (); +char *sparc_decode_sparclet_cpreg (); + +/* + * Local Variables: + * fill-column: 131 + * comment-column: 0 + * End: + */ + +/* end of sparc.h */ diff --git a/opcode/sysdep.h b/opcode/sysdep.h new file mode 100644 index 000000000..db31dc6aa --- /dev/null +++ b/opcode/sysdep.h @@ -0,0 +1,10 @@ +#ifndef __SYSDEP_H_SEEN +#define __SYSDEP_H_SEEN + +#include "lightning.h" + +#ifndef HAVE_MEMCPY +#define memcpy(d, s, n) bcopy((s),(d),(n)) +#endif + +#endif diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 000000000..04abed31f --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,16 @@ +AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir) + +EXTRA_PROGRAMS = testfp funcfp rpnfp +noinst_PROGRAMS = fibit incr printf printf2 rpn fib fibdelay add +noinst_DATA = fibit.ok incr.ok printf.ok printf2.ok rpn.ok fib.ok fibdelay.ok testfp.ok funcfp.ok rpnfp.ok add.ok +EXTRA_DIST = $(noinst_DATA) run-test + +if DISASS +LDADD = $(top_builddir)/opcode/libdisass.a +endif + +if REGRESSION_TESTING +TESTS = fib fibit fibdelay incr printf printf2 rpn add \ + #testfp funcfp rpnfp +TESTS_ENVIRONMENT=$(srcdir)/run-test +endif diff --git a/tests/add.c b/tests/add.c new file mode 100644 index 000000000..0d3661805 --- /dev/null +++ b/tests/add.c @@ -0,0 +1,61 @@ +/******************************** -*- C -*- **************************** + * + * Sample call for using arguments in GNU lightning + * + ***********************************************************************/ + + +/*********************************************************************** + * + * Copyright 2000 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 2.1, 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. + * + ***********************************************************************/ + +#include +#include "lightning.h" + +static char codeBuffer[1024]; + +typedef int (*pifii)(int, int); /* Pointer to Int Function of Int, Int */ + +int main() +{ + pifii myFunction= (pifii) (jit_set_ip(codeBuffer).iptr); + int ofs; /* offset of the argument */ + + jit_leaf(2); + ofs = jit_arg_i(); + jit_getarg_i(JIT_R0, ofs); + ofs = jit_arg_i(); + jit_getarg_i(JIT_R1, ofs); + jit_addr_i(JIT_RET, JIT_R0, JIT_R1); + jit_ret(); + jit_flush_code(codeBuffer, jit_get_ip().ptr); + + /* call the generated code, passing its size as argument */ +#ifdef LIGHTNING_DISASSEMBLE + disassemble(stderr, codeBuffer, jit_get_ip().ptr); +#endif +#ifndef LIGHTNING_CROSS + printf("%d + %d = %d\n", 5, 4, myFunction(5, 4)); +#endif + return 0; +} diff --git a/tests/add.ok b/tests/add.ok new file mode 100644 index 000000000..f5f322c5f --- /dev/null +++ b/tests/add.ok @@ -0,0 +1 @@ +5 + 4 = 9 diff --git a/tests/fib.c b/tests/fib.c new file mode 100644 index 000000000..647ec8d63 --- /dev/null +++ b/tests/fib.c @@ -0,0 +1,77 @@ +/******************************** -*- C -*- **************************** + * + * Sample example of recursion and forward references + * + ***********************************************************************/ + + +/*********************************************************************** + * + * Copyright 2000 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 2.1, 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. + * + ***********************************************************************/ + +#include +#include "lightning.h" + +static jit_insn codeBuffer[1024]; + +typedef int (*pifi)(int); /* Pointer to Int Function of Int */ + +int main() +{ + pifi nfibs = (pifi) (jit_set_ip(codeBuffer).iptr); + int in; /* offset of the argument */ + jit_insn *ref; /* to patch the forward reference */ + + jit_prolog (1); + in = jit_arg_ui (); + jit_getarg_ui(JIT_V0, in); /* V0 = n */ + ref = jit_blti_ui (jit_forward(), JIT_V0, 2); + jit_subi_ui (JIT_V1, JIT_V0, 1); /* V1 = n-1 */ + jit_subi_ui (JIT_V2, JIT_V0, 2); /* V2 = n-2 */ + jit_prepare (1); + jit_pusharg_ui(JIT_V1); + jit_finish(nfibs); + jit_retval(JIT_V1); /* V1 = nfibs(n-1) */ + jit_prepare(1); + jit_pusharg_ui(JIT_V2); + jit_finish(nfibs); + jit_retval(JIT_V2); /* V2 = nfibs(n-2) */ + jit_addi_ui(JIT_V1, JIT_V1, 1); + jit_addr_ui(JIT_RET, JIT_V1, JIT_V2); /* RET = V1 + V2 + 1 */ + jit_ret(); + + jit_patch(ref); /* patch jump */ + jit_movi_i(JIT_RET, 1); /* RET = 1 */ + jit_ret(); + + /* call the generated code, passing 32 as an argument */ + jit_flush_code(codeBuffer, jit_get_ip().ptr); + +#ifdef LIGHTNING_DISASSEMBLE + disassemble(stderr, codeBuffer, jit_get_ip().ptr); +#endif +#ifndef LIGHTNING_CROSS + printf("nfibs(%d) = %d\n", 32, nfibs(32)); +#endif + return 0; +} diff --git a/tests/fib.ok b/tests/fib.ok new file mode 100644 index 000000000..ce73f6e2e --- /dev/null +++ b/tests/fib.ok @@ -0,0 +1 @@ +nfibs(32) = 7049155 diff --git a/tests/fibdelay.c b/tests/fibdelay.c new file mode 100644 index 000000000..313208c8e --- /dev/null +++ b/tests/fibdelay.c @@ -0,0 +1,77 @@ +/******************************** -*- C -*- **************************** + * + * Sample example of branches + * + ***********************************************************************/ + + +/*********************************************************************** + * + * Copyright 2000 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 2.1, 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. + * + ***********************************************************************/ + +#include +#include "lightning.h" + +static jit_insn codeBuffer[1024]; + +typedef int (*pifi)(int); /* Pointer to Int Function of Int */ + +int main() +{ + pifi nfibs = (pifi) (jit_set_ip(codeBuffer).iptr); + int in; /* offset of the argument */ + jit_insn *ref; /* to patch the forward reference */ + jit_insn *loop; /* start of the loop */ + + jit_prolog (1); + in = jit_arg_ui (); + jit_getarg_ui(JIT_R2, in); /* V0 = n */ + jit_delay( + jit_movi_ui (JIT_R1, 1), + ref = jit_blti_ui (jit_forward(), JIT_R2, 2)); + jit_subi_ui (JIT_R2, JIT_R2, 1); + jit_movi_ui (JIT_R0, 1); + + loop= jit_get_label(); + jit_subi_ui (JIT_R2, JIT_R2, 1); /* decr. counter */ + jit_addr_ui (JIT_V0, JIT_R0, JIT_R1); /* V0 = R0 + R1 */ + jit_movr_ui (JIT_R0, JIT_R1); /* R0 = R1 */ + jit_delay( + jit_addi_ui (JIT_R1, JIT_V0, 1), /* R1 = V0 + 1 */ + jit_bnei_ui (loop, JIT_R2, 0)); /* if (R2) goto loop; */ + + jit_patch(ref); /* patch forward jump */ + jit_movr_ui (JIT_RET, JIT_R1); /* RET = R1 */ + jit_ret(); + + jit_flush_code(codeBuffer, jit_get_ip().ptr); + +#ifdef LIGHTNING_DISASSEMBLE + disassemble(stderr, codeBuffer, jit_get_ip().ptr); +#endif +#ifndef LIGHTNING_CROSS + /* call the generated code, passing 36 as an argument */ + printf("nfibs(%d) = %d\n", 36, nfibs(36)); +#endif + return 0; +} diff --git a/tests/fibdelay.ok b/tests/fibdelay.ok new file mode 100644 index 000000000..334ce3f98 --- /dev/null +++ b/tests/fibdelay.ok @@ -0,0 +1 @@ +nfibs(36) = 48315633 diff --git a/tests/fibit.c b/tests/fibit.c new file mode 100644 index 000000000..4281b19e4 --- /dev/null +++ b/tests/fibit.c @@ -0,0 +1,75 @@ +/******************************** -*- C -*- **************************** + * + * Sample example of branches + * + ***********************************************************************/ + + +/*********************************************************************** + * + * Copyright 2000 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 2.1, 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. + * + ***********************************************************************/ + +#include +#include "lightning.h" + +static jit_insn codeBuffer[1024]; + +typedef int (*pifi)(int); /* Pointer to Int Function of Int */ + +int main() +{ + pifi nfibs = (pifi) (jit_set_ip(codeBuffer).iptr); + int in; /* offset of the argument */ + jit_insn *ref; /* to patch the forward reference */ + jit_insn *loop; /* start of the loop */ + + jit_prolog (1); + in = jit_arg_ui (); + jit_getarg_ui(JIT_R2, in); /* V0 = n */ + jit_movi_ui (JIT_R1, 1); + ref = jit_blti_ui (jit_forward(), JIT_R2, 2); + jit_subi_ui (JIT_R2, JIT_R2, 1); + jit_movi_ui (JIT_R0, 1); + + loop= jit_get_label(); + jit_subi_ui (JIT_R2, JIT_R2, 1); /* we'll calculate one more */ + jit_addr_ui (JIT_V0, JIT_R0, JIT_R1); /* V0 = R0 + R1 */ + jit_movr_ui (JIT_R0, JIT_R1); /* R0 = R1 */ + jit_addi_ui (JIT_R1, JIT_V0, 1); /* R1 = V0 + 1 */ + jit_bnei_ui (loop, JIT_R2, 0); /* if (R2) goto loop; */ + + jit_patch(ref); /* patch forward jump */ + jit_movr_ui (JIT_RET, JIT_R1); /* RET = R1 */ + jit_ret(); + + jit_flush_code(codeBuffer, jit_get_ip().ptr); + +#ifdef LIGHTNING_DISASSEMBLE + disassemble(stderr, codeBuffer, jit_get_ip().ptr); +#endif +#ifndef LIGHTNING_CROSS + /* call the generated code, passing 36 as an argument */ + printf("nfibs(%d) = %d\n", 36, nfibs(36)); +#endif + return 0; +} diff --git a/tests/fibit.ok b/tests/fibit.ok new file mode 100644 index 000000000..334ce3f98 --- /dev/null +++ b/tests/fibit.ok @@ -0,0 +1 @@ +nfibs(36) = 48315633 diff --git a/tests/funcfp.c b/tests/funcfp.c new file mode 100644 index 000000000..a95f3f530 --- /dev/null +++ b/tests/funcfp.c @@ -0,0 +1,173 @@ +/******************************** -*- C -*- **************************** + * + * Floating-point function invocation using GNU lightning + * + ***********************************************************************/ + + +/*********************************************************************** + * + * Copyright 2000 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 2.1, 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. + * + ***********************************************************************/ + + +#include +#include "lightning.h" + +static jit_insn codeBuffer[300]; +static struct jit_fp buffer[300]; + + +typedef int (*intFunc)(int,int); +typedef double (*dblFunc)(double,double); +typedef float (*floatFunc)(float,float); + + +dblFunc makeDblFunc() + /* Generate a function that computes and returns the sum of + its two double arguments (return an int) + i.e., double foo(double x,double y) { return x + y;} + */ +{ + dblFunc retVal; + int dbl1,dbl2; + jit_set_ip(codeBuffer); + retVal = (dblFunc)jit_get_ip().iptr; + jit_prolog(2); + jitfp_begin(buffer); + dbl1 = jit_arg_d(); + dbl2 = jit_arg_d(); + + + jitfp_retval(jitfp_add(jitfp_getarg_d(dbl1), + jitfp_getarg_d(dbl2))); + + jit_ret(); + jit_flush_code((char*)retVal,jit_get_ip().ptr); + +#ifdef LIGHTNING_DISASSEMBLE + disassemble(stderr, retVal, jit_get_ip().ptr); +#endif + + return retVal; +} + + +floatFunc makeFloatFunc() + /* Generate a function that computes and returns the sum of + its two double arguments (return an int) + i.e., double foo(double x,double y) { return x + y;} + */ +{ + floatFunc retVal; + int dbl1,dbl2; + //jit_set_ip(codeBuffer); + retVal = (floatFunc)jit_get_ip().iptr; + jit_prolog(2); + jitfp_begin(buffer); + dbl1 = jit_arg_f(); + dbl2 = jit_arg_f(); + + + jitfp_retval(jitfp_add(jitfp_getarg_f(dbl1), + jitfp_getarg_f(dbl2))); + + jit_ret(); + jit_flush_code((char*)retVal,jit_get_ip().ptr); + +#ifdef LIGHTNING_DISASSEMBLE + disassemble(stderr, retVal, jit_get_ip().ptr); +#endif + + return retVal; +} + +dblFunc makeCallFunc(dblFunc theFunc) +{ + dblFunc retVal; + int dbl1,dbl2; + //jit_set_ip(codeBuffer); + retVal = (dblFunc)jit_get_ip().iptr; + jit_prolog(2); + jitfp_begin(buffer); + dbl1 = jit_arg_d(); + dbl2 = jit_arg_d(); + + jitfp_prepare(0,0,2); + jitfp_pusharg_d(jitfp_mul(jitfp_getarg_d(dbl1), + jitfp_getarg_d(dbl2))); + jitfp_pusharg_d(jitfp_getarg_d(dbl1)); + jit_finish((void*)theFunc); + jit_ret(); + jit_flush_code((char*)retVal,jit_get_ip().ptr); + +#ifdef LIGHTNING_DISASSEMBLE + disassemble(stderr, retVal, jit_get_ip().ptr); +#endif + + return retVal; +} + +floatFunc makeCallFloatFunc(floatFunc theFunc) +{ + floatFunc retVal; + int dbl1,dbl2; + //jit_set_ip(codeBuffer); + retVal = (floatFunc)jit_get_ip().iptr; + jit_prolog(2); + jitfp_begin(buffer); + dbl1 = jit_arg_f(); + dbl2 = jit_arg_f(); + + jitfp_prepare(0,2,0); + jitfp_pusharg_f(jitfp_mul(jitfp_getarg_f(dbl1), + jitfp_getarg_f(dbl2))); + jitfp_pusharg_f(jitfp_getarg_f(dbl1)); + jit_finish((void*)theFunc); + jit_ret(); + jit_flush_code((char*)retVal,jit_get_ip().ptr); + +#ifdef LIGHTNING_DISASSEMBLE + disassemble(stderr, retVal, jit_get_ip().ptr); +#endif + + return retVal; +} + + +int main(int argc,char* argv[]) +{ + dblFunc myFunc2 = makeDblFunc(); + floatFunc myFunc3 = makeFloatFunc(); + dblFunc callIt1 = makeCallFunc(myFunc2); + floatFunc callIt2 = makeCallFloatFunc(myFunc3); + +#ifndef LIGHTNING_CROSS + double y = callIt1(10.5,15.3); + float a = 1.5; + float b = 10.5; + float z = callIt2(a,b); + printf("result is %f\t %f\n",y,z); +#endif + + return 0; +} diff --git a/tests/funcfp.ok b/tests/funcfp.ok new file mode 100644 index 000000000..5077368ec --- /dev/null +++ b/tests/funcfp.ok @@ -0,0 +1 @@ +result is 171.150000 17.250000 diff --git a/tests/incr.c b/tests/incr.c new file mode 100644 index 000000000..7a0a51660 --- /dev/null +++ b/tests/incr.c @@ -0,0 +1,59 @@ +/******************************** -*- C -*- **************************** + * + * Sample call for using arguments in GNU lightning + * + ***********************************************************************/ + + +/*********************************************************************** + * + * Copyright 2000 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 2.1, 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. + * + ***********************************************************************/ + +#include +#include "lightning.h" + +static char codeBuffer[1024]; + +typedef int (*pifi)(int); /* Pointer to Int Function of Int */ + +int main() +{ + pifi myFunction= (pifi) (jit_set_ip(codeBuffer).iptr); + int ofs; /* offset of the argument */ + + jit_leaf(1); + ofs = jit_arg_i(); + jit_getarg_i(JIT_R0, ofs); + jit_addi_i(JIT_RET, JIT_R0, 1); + jit_ret(); + jit_flush_code(codeBuffer, jit_get_ip().ptr); + + /* call the generated code, passing its size as argument */ +#ifdef LIGHTNING_DISASSEMBLE + disassemble(stderr, codeBuffer, jit_get_ip().ptr); +#endif +#ifndef LIGHTNING_CROSS + printf("%d + 1 = %d\n", 5, myFunction(5)); +#endif + return 0; +} diff --git a/tests/incr.ok b/tests/incr.ok new file mode 100644 index 000000000..0c3e5c8bb --- /dev/null +++ b/tests/incr.ok @@ -0,0 +1 @@ +5 + 1 = 6 diff --git a/tests/printf.c b/tests/printf.c new file mode 100644 index 000000000..ec27a2f65 --- /dev/null +++ b/tests/printf.c @@ -0,0 +1,68 @@ +/******************************** -*- C -*- **************************** + * + * Sample call to printf using GNU lightning + * + ***********************************************************************/ + + +/*********************************************************************** + * + * Copyright 2000 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 2.1, 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. + * + ***********************************************************************/ + +#include +#include "lightning.h" + +static char codeBuffer[1024]; + +typedef void (*pvfi)(int); /* Pointer to Void Function of Int */ + +int main() +{ + pvfi myFunction; /* ptr to generated code */ + char *start, *end; /* a couple of labels */ + int ofs; /* to get the argument */ + + myFunction = (pvfi) (jit_set_ip(codeBuffer).vptr); + start = jit_get_ip().ptr; + jit_prolog(1); + ofs = jit_arg_i(); + jit_movi_p(JIT_R0, "looks like %d bytes sufficed\n"); + jit_getarg_i(JIT_R1, ofs); + jit_prepare(2); + jit_pusharg_i(JIT_R1); /* push in reverse order */ + jit_pusharg_p(JIT_R0); + jit_finish(printf); + jit_ret(); + end = jit_get_ip().ptr; + + jit_flush_code(codeBuffer, end); + +#ifdef LIGHTNING_DISASSEMBLE + disassemble(stderr, codeBuffer, end); +#endif +#ifndef LIGHTNING_CROSS + /* call the generated code, passing its size as argument */ + myFunction(sizeof(codeBuffer)); +#endif + return 0; +} diff --git a/tests/printf.ok b/tests/printf.ok new file mode 100644 index 000000000..efa266343 --- /dev/null +++ b/tests/printf.ok @@ -0,0 +1 @@ +looks like 1024 bytes sufficed diff --git a/tests/printf2.c b/tests/printf2.c new file mode 100644 index 000000000..d4a297d45 --- /dev/null +++ b/tests/printf2.c @@ -0,0 +1,2409 @@ + +#include +#include +#include "lightning.h" + +typedef int (*pifi)(int); + /* Pointer to Int Function of Int */ + +void test(void); + +int main(void) +{ + jit_insn *codeBuffer = calloc(1, 1024); + pifi incr = (pifi) (jit_set_ip(codeBuffer).iptr); + int in; + + jit_leaf(1); + in = jit_arg_i(); + jit_getarg_i(JIT_R0, in); + jit_addi_i(JIT_R0, JIT_R0, 1); + jit_movr_i(JIT_RET, JIT_R0); + jit_ret(); + + jit_flush_code(codeBuffer, jit_get_ip().ptr); + + /* call the generated code, passing 5 as an argument */ + printf("%d + 1 = %d\n", 5, incr(5)); + test(); + return 0; +} + +void test(void) +{ + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); + printf("this is a test\n"); +} diff --git a/tests/printf2.ok b/tests/printf2.ok new file mode 100644 index 000000000..1c2f0b7b5 --- /dev/null +++ b/tests/printf2.ok @@ -0,0 +1,2376 @@ +5 + 1 = 6 +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test +this is a test diff --git a/tests/rpn.c b/tests/rpn.c new file mode 100644 index 000000000..a7549eba2 --- /dev/null +++ b/tests/rpn.c @@ -0,0 +1,445 @@ +/******************************** -*- C -*- **************************** + * + * Sample RPN calculator using GNU lightning + * Binary operators: + - * / % & | ^ < <= > >= = != << >> >>> + * Unary operators: _ (unary minus) and ~ (unary NOT) + * + ***********************************************************************/ + + +/*********************************************************************** + * + * Copyright 2000, 2004 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 2.1, 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. + * + ***********************************************************************/ + + +#include +#include +#include + +#include "lightning.h" + +static jit_insn codeBuffer[1024]; + +typedef int (*pifi) (int); /* Pointer to Int Function of Int */ + + +enum stack_kind { IMM, EXPR, ARG }; +enum operator { LE, GE, NE, LSH, RSHU, RSH }; + +struct stack_element +{ + enum stack_kind kind; + int imm; +}; + +/* Return a new operator TOK2 such that A TOK B = B TOK2 A, + or 0 if there is none. */ +int +swap_op (int tok) +{ + switch (tok) + { + case '<': + case '>': + /* Swap < and >. */ + return '<' ^ '>' ^ tok; + + case LE: + case GE: + /* Swap <= and >=. */ + return LE ^ GE ^ tok; + + case '+': + case '*': + case '&': + case '|': + case '^': + case '=': + case NE: + /* These are commutative. */ + return tok; + + default: + return 0; + } +} + +/* Perform constant folding on the two operands X and Y, + passing them through the operator TOK. */ +int +fold (int x, int y, int tok) +{ + switch (tok) + { + case '+': return x + y; + case '-': return x - y; + case '*': return x * y; + case '/': return x / y; + case '%': return x % y; + case '=': return x == y; + case '<': return x < y; + case '>': return x > y; + case '&': return x & y; + case '|': return x | y; + case '^': return x ^ y; + case LE: return x <= y; + case GE: return x >= y; + case NE: return x != y; + case LSH: return x << y; + case RSH: return x >> y; + case RSHU: return ((unsigned) x) >> y; + default: abort (); + } +} + +/* Store in R0 the result of evaluating the operator TOK with + a register operand SRC and an immediate operand IMM. */ +void +gen_reg_imm (int src, int imm, int tok) +{ + switch (tok) + { + case '+': jit_addi_i (JIT_R0, src, imm); break; + case '-': jit_subi_i (JIT_R0, src, imm); break; + case '*': jit_muli_i (JIT_R0, src, imm); break; + case '/': jit_divi_i (JIT_R0, src, imm); break; + case '%': jit_modi_i (JIT_R0, src, imm); break; + case '&': jit_andi_i (JIT_R0, src, imm); break; + case '|': jit_ori_i (JIT_R0, src, imm); break; + case '^': jit_xori_i (JIT_R0, src, imm); break; + case '=': jit_eqi_i (JIT_R0, src, imm); break; + case '<': jit_lti_i (JIT_R0, src, imm); break; + case '>': jit_gti_i (JIT_R0, src, imm); break; + case LE: jit_lei_i (JIT_R0, src, imm); break; + case GE: jit_gei_i (JIT_R0, src, imm); break; + case NE: jit_nei_i (JIT_R0, src, imm); break; + case LSH: jit_lshi_i (JIT_R0, src, imm); break; + case RSH: jit_rshi_i (JIT_R0, src, imm); break; + case RSHU: jit_rshi_ui (JIT_R0, src, imm); break; + default: abort (); + } +} + +/* Store in R0 the result of evaluating the operator TOK with + two register operands SRC1 and SRC2. */ +void +gen_reg_reg (int src1, int src2, int tok) +{ + switch (tok) + { + case '+': jit_addr_i (JIT_R0, src1, src2); break; + case '-': jit_subr_i (JIT_R0, src1, src2); break; + case '*': jit_mulr_i (JIT_R0, src1, src2); break; + case '/': jit_divr_i (JIT_R0, src1, src2); break; + case '%': jit_modr_i (JIT_R0, src1, src2); break; + case '&': jit_andr_i (JIT_R0, src1, src2); break; + case '|': jit_orr_i (JIT_R0, src1, src2); break; + case '^': jit_xorr_i (JIT_R0, src1, src2); break; + case '=': jit_eqr_i (JIT_R0, src1, src2); break; + case '<': jit_ltr_i (JIT_R0, src1, src2); break; + case '>': jit_gtr_i (JIT_R0, src1, src2); break; + case LE: jit_ler_i (JIT_R0, src1, src2); break; + case GE: jit_ger_i (JIT_R0, src1, src2); break; + case NE: jit_ner_i (JIT_R0, src1, src2); break; + case LSH: jit_lshr_i (JIT_R0, src1, src2); break; + case RSH: jit_rshr_i (JIT_R0, src1, src2); break; + case RSHU: jit_rshr_ui (JIT_R0, src1, src2); break; + default: abort (); + } +} + +/* This function does all of lexing, parsing, and picking a good + order of evaluation... Needless to say, this is not the best + possible design, but it avoids cluttering everything with globals. */ +pifi +compile_rpn (char *expr) +{ + struct stack_element stack[32]; + int sp = 0; + int curr_tos = -1; /* stack element currently in R0 */ + + pifi fn; + int ofs; + fn = (pifi) (jit_get_ip ().iptr); + jit_leaf (1); + ofs = jit_arg_i (); + + while (*expr) + { + int with_imm; + int imm; + int tok; + int src1, src2; + + /* This is the lexer. */ + switch (*expr) + { + case ' ': case '\t': + expr++; + continue; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + stack[sp].kind = IMM; + stack[sp++].imm = strtol (expr, &expr, 0); + continue; + + case 'x': + expr++; + stack[sp++].kind = ARG; + continue; + + case '~': + /* NOT. Implemented as a XOR with -1. */ + stack[sp].kind = IMM; + stack[sp++].imm = ~0; + tok = '^'; + break; + + case '_': + /* Unary minus. Transform to 0 - X and go on. + Also used to enter negative constants (32_ = -32). */ + expr++; + stack[sp] = stack[sp - 1]; + + /* Ensure CURR_TOS is correct. */ + if (curr_tos == sp - 1) + curr_tos = sp; + + stack[sp - 1].kind = IMM; + stack[sp - 1].imm = 0; + sp++; + tok = '-'; + break; + + case '+': + case '-': + case '*': + case '/': + case '%': + case '&': + case '|': + case '^': + case '=': + tok = *expr++; + break; + + case '!': + /* Get != */ + expr++; + assert (*expr == '='); + tok = NE; + break; + + case '<': + /* Get <, <<, <= */ + if (expr[1] == '=') + expr += 2, tok = LE; + else if (expr[1] == '<') + expr += 2, tok = LSH; + else + expr++, tok = '<'; + break; + + case '>': + /* Get >, >>, >>>, >= */ + if (expr[1] == '=') + expr += 2, tok = GE; + else if (expr[1] == '>' && expr[2] == '>') + expr += 3, tok = RSHU; + else if (expr[1] == '>') + expr += 2, tok = RSH; + else + expr++, tok = '>'; + break; + + default: + abort (); + } + + assert (sp >= 2); + + /* Constant folding. */ + if (stack[sp - 1].kind == IMM && stack[sp - 2].kind == IMM) + { + stack[sp - 2].imm = + fold (stack[sp - 2].imm, stack[sp - 1].imm, tok); + sp--; + continue; + } + + /* If possible, ensure that the constant is the RHS, possibly + by changing TOK (if it is a comparison). */ + if (stack[sp - 2].kind == IMM) + { + int swapped_operation = swap_op (tok); + if (swapped_operation) + { + tok = swapped_operation; + stack[sp - 2].kind = stack[sp - 1].kind; + stack[sp - 1].kind = IMM; + stack[sp - 1].imm = stack[sp - 2].imm; + + /* Ensure CURR_TOS is correct. */ + if (curr_tos == sp - 1) + curr_tos = sp - 2; + } + } + + /* Get the second argument into a register, if not an immediate. + Also decide which argument will be prepared into JIT_R0 and + which will be prepared into JIT_V0. */ + with_imm = 0; + src1 = JIT_R0; + src2 = JIT_V0; + switch (stack[sp - 1].kind) + { + case IMM: + /* RHS is an immediate, use an immediate instruction. */ + with_imm = 1; + imm = stack[sp - 1].imm; + break; + + case EXPR: + /* RHS is an expression, check if it is already in JIT_R0. */ + if (curr_tos == sp - 1) + { + /* Invert the two sources. */ + src1 = JIT_V0; + src2 = JIT_R0; + } + else + jit_popr_i (JIT_V0); + + curr_tos = -1; + break; + + case ARG: + jit_getarg_i (JIT_V0, ofs); + break; + } + + /* Get the first argument into a register indicated by SRC1. */ + switch (stack[sp - 2].kind) + { + case IMM: + /* LHS is an immediate, check if we must spill the top of stack. */ + if (curr_tos != -1) + { + jit_pushr_i (JIT_R0); + curr_tos = -1; + } + + jit_movi_i (src1, stack[sp - 2].imm); + break; + + case EXPR: + /* LHS is an expression, check if it is already in JIT_R0. */ + if (curr_tos != sp - 2) + { + jit_popr_i (src1); + curr_tos = -1; + } + else + assert (src1 == JIT_R0); + break; + + case ARG: + if (curr_tos != -1) + { + jit_pushr_i (JIT_R0); + curr_tos = -1; + } + + jit_getarg_i (src1, ofs); + break; + } + + /* Set up the new stack entry, which is cached in R0. */ + sp -= 2; + curr_tos = sp; + stack[sp++].kind = EXPR; + + /* Perform the computation. */ + if (with_imm) + gen_reg_imm (src1, imm, tok); + else + gen_reg_reg (src1, src2, tok); + } + + assert (sp == 1); + switch (stack[0].kind) + { + case IMM: + jit_movi_i (JIT_RET, stack[0].imm); + break; + + case EXPR: + assert (curr_tos == 0); + jit_movr_i (JIT_RET, JIT_R0); + break; + + case ARG: + jit_getarg_i (JIT_V0, ofs); + break; + } + + jit_ret (); + jit_flush_code ((char *) fn, jit_get_ip ().ptr); + +#ifdef LIGHTNING_DISASSEMBLE + disassemble (stderr, (char *) fn, jit_get_ip ().ptr); +#endif + return fn; +} + + +int +main () +{ + pifi c2f, f2c; + int i; + + jit_set_ip (codeBuffer); + c2f = compile_rpn ("32 x 9 * 5 / +"); + f2c = compile_rpn ("5 x 32_ + * 9 /"); + +#ifndef LIGHTNING_CROSS + printf ("\nC:"); + for (i = 0; i <= 100; i += 10) + printf ("%3d ", i); + printf ("\nF:"); + for (i = 0; i <= 100; i += 10) + printf ("%3d ", c2f (i)); + printf ("\n"); + + printf ("\nF:"); + for (i = 32; i <= 212; i += 10) + printf ("%3d ", i); + printf ("\nC:"); + for (i = 32; i <= 212; i += 10) + printf ("%3d ", f2c (i)); + printf ("\n"); +#endif + return 0; +} diff --git a/tests/rpn.ok b/tests/rpn.ok new file mode 100644 index 000000000..a1a2c4f0a --- /dev/null +++ b/tests/rpn.ok @@ -0,0 +1,6 @@ + +C: 0 10 20 30 40 50 60 70 80 90 100 +F: 32 50 68 86 104 122 140 158 176 194 212 + +F: 32 42 52 62 72 82 92 102 112 122 132 142 152 162 172 182 192 202 212 +C: 0 5 11 16 22 27 33 38 44 50 55 61 66 72 77 83 88 94 100 diff --git a/tests/rpnfp.c b/tests/rpnfp.c new file mode 100644 index 000000000..85b10af0a --- /dev/null +++ b/tests/rpnfp.c @@ -0,0 +1,134 @@ +/******************************** -*- C -*- **************************** + * + * Sample RPN calculator using GNU lightning and floating-point + * + ***********************************************************************/ + + +/*********************************************************************** + * + * Copyright 2000, 2004 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 2.1, 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. + * + ***********************************************************************/ + + +#include +#include +#include "lightning.h" + +static jit_insn codeBuffer[1024]; + +typedef double (*pdfd) (double); /* Pointer to Double Function of Double */ + + +pdfd +compile_rpn (char *expr) +{ + pdfd fn; + int ofs, sp = 1; + struct jit_fp buffer[300], *stack[10]; + + jitfp_begin (buffer); + fn = (pdfd) (jit_get_ip ().dptr); + jit_leaf (1); + ofs = jit_arg_d (); + stack[0] = jitfp_getarg_d (ofs); + + while (*expr) + { + char buf[32]; + int n; + + /* This scanner is much less advanced than the one in rpn.c. */ + if (sscanf (expr, "%[0-9]%n", buf, &n)) + { + double d = strtod (buf, NULL); + expr += n - 1; + stack[sp++] = jitfp_imm (d); + } + else if (*expr == '+') + { + stack[sp - 2] = jitfp_add (stack[sp - 2], stack[sp - 1]); + sp--; + } + else if (*expr == '-') + { + stack[sp - 2] = jitfp_sub (stack[sp - 2], stack[sp - 1]); + sp--; + } + else if (*expr == '*') + { + stack[sp - 2] = jitfp_mul (stack[sp - 2], stack[sp - 1]); + sp--; + } + else if (*expr == '/') + { + stack[sp - 2] = jitfp_div (stack[sp - 2], stack[sp - 1]); + sp--; + } + else + { + fprintf (stderr, "cannot compile: %s\n", expr); + abort (); + } + ++expr; + } + jitfp_retval (stack[0]); + jit_ret (); + + jit_flush_code ((char *) fn, jit_get_ip ().ptr); + +#ifdef LIGHTNING_DISASSEMBLE + disassemble (stderr, (char *) fn, jit_get_ip ().ptr); +#endif + return fn; +} + + +int +main () +{ + pdfd c2f, f2c; + double i; + + jit_set_ip (codeBuffer); + c2f = compile_rpn ("9*5/32+"); + f2c = compile_rpn ("32-5*9/"); + +#ifndef LIGHTNING_CROSS + printf ("\nC:"); + for (i = 0; i <= 100; i += 10) + printf ("%6.1f", i); + printf ("\nF:"); + for (i = 0; i <= 100; i += 10) + printf ("%6.1f", c2f (i)); + printf ("\n"); + + printf ("\nF:"); + for (i = 32; i <= 212; i += 10) + printf ("%6.1f", i); + printf ("\nC:"); + for (i = 32; i <= 212; i += 10) + printf ("%6.1f", f2c (i)); + printf ("\n"); +#endif + return 0; +} diff --git a/tests/rpnfp.ok b/tests/rpnfp.ok new file mode 100644 index 000000000..b803f5959 --- /dev/null +++ b/tests/rpnfp.ok @@ -0,0 +1,6 @@ + +C: 0.0 10.0 20.0 30.0 40.0 50.0 60.0 70.0 80.0 90.0 100.0 +F: 32.0 50.0 68.0 86.0 104.0 122.0 140.0 158.0 176.0 194.0 212.0 + +F: 32.0 42.0 52.0 62.0 72.0 82.0 92.0 102.0 112.0 122.0 132.0 142.0 152.0 162.0 172.0 182.0 192.0 202.0 212.0 +C: 0.0 5.6 11.1 16.7 22.2 27.8 33.3 38.9 44.4 50.0 55.6 61.1 66.7 72.2 77.8 83.3 88.9 94.4 100.0 diff --git a/tests/run-test b/tests/run-test new file mode 100755 index 000000000..ae3dfc7e6 --- /dev/null +++ b/tests/run-test @@ -0,0 +1,9 @@ +#! /bin/sh + +./$1 > $1.log +if cmp -s $srcdir/$1.ok $1.log; then + rm $1.log +else + diff $srcdir/$1.ok $1.log + exit 1 +fi diff --git a/tests/testfp.c b/tests/testfp.c new file mode 100644 index 000000000..83d3edfc3 --- /dev/null +++ b/tests/testfp.c @@ -0,0 +1,186 @@ +/******************************** -*- C -*- **************************** + * + * Floating-point miscellanea using GNU lightning + * + ***********************************************************************/ + + +/*********************************************************************** + * + * Copyright 2000, 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 2.1, 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. + * + ***********************************************************************/ + + +#include +#include "lightning.h" + +static jit_insn codeBuffer[300]; +static struct jit_fp buffer[300]; +static double a; + +void +int_test(what, code) + char *what; + jit_code code; +{ + a = -2.6; printf("%s\t\t%d ", what, code.iptr()); + a = -2.4; printf("%d ", code.iptr()); + a = 0.0; printf("%d ", code.iptr()); + a = 2.4; printf("%d ", code.iptr()); + a = 2.6; printf("%d\n", code.iptr()); +} + +int +main() +{ + jit_code code; + code.ptr = (char *) codeBuffer; + + jit_set_ip(codeBuffer); + jit_leaf(0); + jitfp_begin(buffer); + jitfp_cmp(JIT_R1, JIT_R0, + jitfp_ldi_d(&a) + ); + jit_subr_i(JIT_RET, JIT_R0, JIT_R1); /* [greater] - [less] = -1/0/1 */ + jit_ret(); + + jit_flush_code(codeBuffer, jit_get_ip().ptr); +#ifdef LIGHTNING_DISASSEMBLE + disassemble(stderr, codeBuffer, jit_get_ip().ptr); +#endif +#ifndef LIGHTNING_CROSS + int_test("compare", code); +#endif + + jit_set_ip(codeBuffer); + jit_leaf(0); + jitfp_begin(buffer); + jitfp_trunc(JIT_RET, + jitfp_ldi_d(&a) + ); + jit_ret(); +#ifdef LIGHTNING_DISASSEMBLE + disassemble(stderr, codeBuffer, jit_get_ip().ptr); +#endif +#ifndef LIGHTNING_CROSS + int_test("trunc", code); +#endif + + jit_set_ip(codeBuffer); + jit_leaf(0); + jitfp_begin(buffer); + jitfp_ceil(JIT_RET, + jitfp_ldi_d(&a) + ); + jit_ret(); +#ifdef LIGHTNING_DISASSEMBLE + disassemble(stderr, codeBuffer, jit_get_ip().ptr); +#endif +#ifndef LIGHTNING_CROSS + int_test("ceil", code); +#endif + + jit_set_ip(codeBuffer); + jit_leaf(0); + jitfp_begin(buffer); + jitfp_floor(JIT_RET, + jitfp_ldi_d(&a) + ); + jit_ret(); +#ifdef LIGHTNING_DISASSEMBLE + disassemble(stderr, codeBuffer, jit_get_ip().ptr); +#endif +#ifndef LIGHTNING_CROSS + int_test("floor", code); +#endif + + jit_set_ip(codeBuffer); + jit_leaf(0); + jitfp_begin(buffer); + jitfp_round(JIT_RET, + jitfp_ldi_d(&a) + ); + jit_ret(); +#ifdef LIGHTNING_DISASSEMBLE + disassemble(stderr, codeBuffer, jit_get_ip().ptr); +#endif +#ifndef LIGHTNING_CROSS + int_test("round", code); +#endif + +#if 0 && defined JIT_TRANSCENDENTAL + jit_set_ip(codeBuffer); + jit_leaf(0); + jitfp_begin(buffer); + jitfp_sti_d(&a, + jitfp_log( + jitfp_exp(jitfp_imm(1.0)) + ) + ); + jit_ret(); + code.vptr(); +#ifdef LIGHTNING_DISASSEMBLE + disassemble(stderr, codeBuffer, jit_get_ip().ptr); +#endif +#ifndef LIGHTNING_CROSS + printf("log e = \t%f\n", a); +#endif + + jit_set_ip(codeBuffer); + jit_leaf(0); + jitfp_begin(buffer); + jitfp_sti_d(&a, + jitfp_atn( + jitfp_imm(1.732050807657) + ) + ); + jit_ret(); + code.vptr(); +#ifdef LIGHTNING_DISASSEMBLE + disassemble(stderr, codeBuffer, jit_get_ip().ptr); +#endif +#ifndef LIGHTNING_CROSS + printf("pi = \t%f\n", a*3); +#endif + + jit_set_ip(codeBuffer); + jit_leaf(0); + jitfp_begin(buffer); + jitfp_sti_d(&a, + jitfp_tan( + jitfp_ldi_d(&a) + ) + ); + jit_ret(); + code.vptr(); +#ifdef LIGHTNING_DISASSEMBLE + disassemble(stderr, codeBuffer, jit_get_ip().ptr); +#endif +#ifndef LIGHTNING_CROSS + printf("tan^2 pi/3 = \t%f\n", a*a); +#endif + +#endif /* JIT_TRANSCEDENTAL */ + + return (0); +} diff --git a/tests/testfp.ok b/tests/testfp.ok new file mode 100644 index 000000000..8822deee0 --- /dev/null +++ b/tests/testfp.ok @@ -0,0 +1,5 @@ +compare 1 1 0 1 1 +trunc -2 -2 0 2 2 +ceil -2 -2 0 3 3 +floor -3 -3 0 2 2 +round -3 -2 0 2 3