commit 3b4c0619133a7a6e829d2d2db267f5b0f4e8c93d Author: Paolo Bonzini Date: Sun Oct 10 21:18:38 2004 +0000 initial import (automatically generated log message) git-archimport-id: bonzini@gnu.org--2004b/lightning--stable--1.2--base-0 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