diff options
42 files changed, 1849 insertions, 538 deletions
diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 962e13d..907820d 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,8 +1,29 @@ +# 0.2A + +* Implement Thumb: + * ldr Rd, [Rn, Immediate5] + * ldr Rd, [Rn, Rm] + * ldr Rd, [pc, Immediate8] + * ldr Rd, [sp, Immediate8] + * lsl Rd, Rm, Immediate5 + * svc Immediate8 + * push Registers + * pop Registers + * strh Rd, [Rn, Immediate5] + * lsr Rd, Rm, Immediate5 +* Update readme +* Rework instruction functions +* Improve comments +* Attach license file +* Initialise SP +* Optimise sign-extensions +* Bump dependency versions + # 0.29 * Implement Thumb: * mov Rd, Rm; - * movs Rd, immediate_8; + * movs Rd, immediate8; * movs Rd, Rm; * Update readme; * Rename condition method to check_condition; @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + 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. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +<https://www.gnu.org/licenses/>. @@ -1,6 +1,6 @@ [package] name = "luma" -version = "0.41.0" +version = "0.42.0" authors = ["Gabriel Jensen"] edition = "2021" description = "AGB emulator." @@ -20,4 +20,4 @@ lto = true toml = "0.7.5" libc = "0.2.147" sdl2 = "0.35.2" -serde = { version = "1.0.164", features = ["derive"] } +serde = { version = "1.0.166", features = ["derive"] } @@ -2,18 +2,18 @@ Copyright 2021-2023 Gabriel Jensen. -This program is free software: you can redistribute it and/or modify it under -the terms of the GNU Affero General Public License as published by the Free -Software Foundation, either version 3 of the License, or (at your option) any +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU Affero General Public License as published by the Free +Software Foundation, either version 3 of the License, or (at your option) any later version. -This program is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +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 Affero General Public License for more details. -You should have received a copy of the GNU Affero General Public License along -with this program. If not, see <https://www.gnu.org/licenses/>. +You should have received a copy of the GNU Affero General Public License along +with this program. If not, see <https://www.gnu.org/licenses/>. - ABOUT @@ -27,7 +27,7 @@ Invoke the emulator via the 'luma' command. - CONFIGURATION -The emulator tries to read the configuration file at '${HOME}/.luma.toml'. If +The emulator tries to read the configuration file at '${HOME}/.luma.toml'. If this file is found, the following fields are read (if present): luma: @@ -44,30 +44,42 @@ These settings are overwritten by terminal parameters (see USAGE). - COMPATIBILITY -Currently, the emulator supports the following ARM instructions only. Others +Currently, the emulator supports the following ARM instructions only. Others will be skipped. - * b{cond}{l} +/-offset_24 - * bx Rm - * ldr{cond} Rn, +/-offset_12 + * b{cond}{l} Immediate24 + * bx{cond} Rm + * ldr{cond} Rd, [Rn, Immediate12] * mov{cond} Rd, Rn - * mov{cond} Rd, immediate_8 + * mov{cond} Rd, #Immediate8 * mov{cons}s r15, Rn - * str{cond} Rn, +/-offset_12 + * str{cond} Rd, [Rn, Immediate12] Moreover, the following Thumb instructions are supported: - * b +/-offset_11 - * b{cond} +/-offset_8 + * b Immediate11 + * b{cond} Immediate8 + * bl Immediate24 * bx Rm + * ldr Rd, [Rn, Immediate5] + * ldr Rd, [Rn, Rm] + * ldr Rd, [r13, Immediate8] + * ldr Rd, [r15, Immediate8] + * lsl Rd, Rm, Immediate5 + * lsr Rd, Rm, Immediate5 * mov Rd, Rn - * movs Rd, immediate_8 + * movs Rd, Immediate8 * movs Rd, Rn + * pop Registers + * push Registers + * strh Rd, [Rn, Immediate5] + * svc Immediate8 -When the virtual processor boots, the default mode is the sys mode. As no -supported instruction can change this mode, this is also the only mode for now. +When the virtual processor boots, the default mode is the sys mode. This can be +changed using the 'svc Immediate8' (Thumb) or 'svc Immediate24' (ARM) +instructions, which changes this to the svc mode. -The entire memory space (0x00000000 to 0x0E010000, exclusive) is available, +The entire memory space (0x00000000 to 0x0E010000, exclusive) is available, however, no I/O-mapped addresses are currently functional. Improved support is, of course, planned. diff --git a/src/luma.rs b/src/luma.rs index 16c1941..6830045 100644 --- a/src/luma.rs +++ b/src/luma.rs @@ -3,22 +3,22 @@ This file is part of Luma. - Luma is free software: you can redistribute it - and/or modify it under the terms of the GNU + Luma is free software: you can redistribute it + and/or modify it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 - of the License, or (at your option) any later + the Free Software Foundation, either version 3 + of the License, or (at your option) any later version. - Luma 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 + Luma 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 Affero General Public License for more details. - You should have received a copy of the GNU - Affero General Public License along with Luma. If not, - see <https://www.gnu.org/licenses/>. + You should have received a copy of the GNU + Affero General Public License along with Luma. + If not, see <https://www.gnu.org/licenses/>. */ pub mod application; @@ -32,9 +32,14 @@ pub struct VersionType<T> { pub const VERSION: VersionType::<u32> = VersionType::<u32> { major: 0x0, - minor: 0x29, + minor: 0x2A, }; +pub struct WidthHeight<T> { + width: T, + height: T, +} + pub const CONFIGURATION_VERSION: u32 = 0x0; pub const MEMORY_SIZE: usize = 0x0E010000; @@ -42,5 +47,7 @@ pub const MEMORY_SIZE: usize = 0x0E010000; pub const BOOTLOADER_SIZE: usize = 0x00004000; pub const IMAGE_SIZE: usize = 0x02000000; -pub const SCREEN_WIDTH: u8 = 0xF0; -pub const SCREEN_HEIGHT: u8 = 0xA0; +pub const SCREEN_SIZE: WidthHeight::<u8> = WidthHeight::<u8> { + width: 0xF0, + height: 0xA0, +}; diff --git a/src/luma/application.rs b/src/luma/application.rs index e41f75f..7894b29 100644 --- a/src/luma/application.rs +++ b/src/luma/application.rs @@ -3,22 +3,22 @@ This file is part of Luma. - Luma is free software: you can redistribute it - and/or modify it under the terms of the GNU + Luma is free software: you can redistribute it + and/or modify it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 - of the License, or (at your option) any later + the Free Software Foundation, either version 3 + of the License, or (at your option) any later version. - Luma 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 + Luma 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 Affero General Public License for more details. - You should have received a copy of the GNU - Affero General Public License along with Luma. If not, - see <https://www.gnu.org/licenses/>. + You should have received a copy of the GNU + Affero General Public License along with Luma. + If not, see <https://www.gnu.org/licenses/>. */ use crate::luma::configuration::Configuration; diff --git a/src/luma/application/drop.rs b/src/luma/application/drop.rs index 9bef2c4..a5ad544 100644 --- a/src/luma/application/drop.rs +++ b/src/luma/application/drop.rs @@ -3,22 +3,22 @@ This file is part of Luma. - Luma is free software: you can redistribute it - and/or modify it under the terms of the GNU + Luma is free software: you can redistribute it + and/or modify it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 - of the License, or (at your option) any later + the Free Software Foundation, either version 3 + of the License, or (at your option) any later version. - Luma 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 + Luma 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 Affero General Public License for more details. - You should have received a copy of the GNU - Affero General Public License along with Luma. If not, - see <https://www.gnu.org/licenses/>. + You should have received a copy of the GNU + Affero General Public License along with Luma. + If not, see <https://www.gnu.org/licenses/>. */ use crate::luma::application::Application; diff --git a/src/luma/application/initialise.rs b/src/luma/application/initialise.rs index 8bf40b8..02b05bf 100644 --- a/src/luma/application/initialise.rs +++ b/src/luma/application/initialise.rs @@ -3,25 +3,25 @@ This file is part of Luma. - Luma is free software: you can redistribute it - and/or modify it under the terms of the GNU + Luma is free software: you can redistribute it + and/or modify it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 - of the License, or (at your option) any later + the Free Software Foundation, either version 3 + of the License, or (at your option) any later version. - Luma 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 + Luma 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 Affero General Public License for more details. - You should have received a copy of the GNU - Affero General Public License along with Luma. If not, - see <https://www.gnu.org/licenses/>. + You should have received a copy of the GNU + Affero General Public License along with Luma. + If not, see <https://www.gnu.org/licenses/>. */ -use crate::luma::{SCREEN_HEIGHT, SCREEN_WIDTH}; +use crate::luma::{SCREEN_SIZE}; use crate::luma::application::{Application, GOT_SIGNAL}; use crate::luma::configuration::Configuration; use crate::luma::device::Device; @@ -53,7 +53,7 @@ impl Application { let sdl = sdl2::init().expect("unable to initialise sdl2"); let sdl_video = sdl.video().expect("unable to initialise sdl2"); - let window = sdl_video.window("luma", SCREEN_WIDTH as u32 * configuration.scale, SCREEN_HEIGHT as u32 * configuration.scale).position_centered().build().unwrap(); + let window = sdl_video.window("luma", SCREEN_SIZE.width as u32 * configuration.scale, SCREEN_SIZE.height as u32 * configuration.scale).position_centered().build().unwrap(); return Application { configuration: configuration.clone(), diff --git a/src/luma/application/load.rs b/src/luma/application/load.rs index c3000ea..338f120 100644 --- a/src/luma/application/load.rs +++ b/src/luma/application/load.rs @@ -3,22 +3,22 @@ This file is part of Luma. - Luma is free software: you can redistribute it - and/or modify it under the terms of the GNU + Luma is free software: you can redistribute it + and/or modify it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 - of the License, or (at your option) any later + the Free Software Foundation, either version 3 + of the License, or (at your option) any later version. - Luma 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 + Luma 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 Affero General Public License for more details. - You should have received a copy of the GNU - Affero General Public License along with Luma. If not, - see <https://www.gnu.org/licenses/>. + You should have received a copy of the GNU + Affero General Public License along with Luma. + If not, see <https://www.gnu.org/licenses/>. */ use crate::luma::application::Application; diff --git a/src/luma/application/run.rs b/src/luma/application/run.rs index 9cba12c..2e47712 100644 --- a/src/luma/application/run.rs +++ b/src/luma/application/run.rs @@ -3,22 +3,22 @@ This file is part of Luma. - Luma is free software: you can redistribute it - and/or modify it under the terms of the GNU + Luma is free software: you can redistribute it + and/or modify it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 - of the License, or (at your option) any later + the Free Software Foundation, either version 3 + of the License, or (at your option) any later version. - Luma 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 + Luma 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 Affero General Public License for more details. - You should have received a copy of the GNU - Affero General Public License along with Luma. If not, - see <https://www.gnu.org/licenses/>. + You should have received a copy of the GNU + Affero General Public License along with Luma. + If not, see <https://www.gnu.org/licenses/>. */ use crate::luma::VERSION; @@ -59,7 +59,7 @@ impl Application { (self.device.decode)(&mut self.device); - sleep(Duration::from_secs(0x1)); + sleep(Duration::from_millis(250)); } } } diff --git a/src/luma/configuration.rs b/src/luma/configuration.rs index 20a858f..17e7221 100644 --- a/src/luma/configuration.rs +++ b/src/luma/configuration.rs @@ -3,22 +3,22 @@ This file is part of Luma. - Luma is free software: you can redistribute it - and/or modify it under the terms of the GNU + Luma is free software: you can redistribute it + and/or modify it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 - of the License, or (at your option) any later + the Free Software Foundation, either version 3 + of the License, or (at your option) any later version. - Luma 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 + Luma 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 Affero General Public License for more details. - You should have received a copy of the GNU - Affero General Public License along with Luma. If not, - see <https://www.gnu.org/licenses/>. + You should have received a copy of the GNU + Affero General Public License along with Luma. + If not, see <https://www.gnu.org/licenses/>. */ pub mod create; diff --git a/src/luma/configuration/create.rs b/src/luma/configuration/create.rs index 96fb25d..143fbac 100644 --- a/src/luma/configuration/create.rs +++ b/src/luma/configuration/create.rs @@ -1,4 +1,25 @@ -// Copyright 2021-2023 Gabriel Jensen. +/* + Copyright 2021-2023 Gabriel Jensen. + + This file is part of Luma. + + Luma is free software: you can redistribute it + and/or modify it under the terms of the GNU + Affero General Public License as published by + the Free Software Foundation, either version 3 + of the License, or (at your option) any later + version. + + Luma 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 + Affero General Public License for more details. + + You should have received a copy of the GNU + Affero General Public License along with Luma. + If not, see <https://www.gnu.org/licenses/>. +*/ use crate::luma::CONFIGURATION_VERSION; use crate::luma::configuration::Configuration; diff --git a/src/luma/configuration/load.rs b/src/luma/configuration/load.rs index dac8570..d08bcd5 100644 --- a/src/luma/configuration/load.rs +++ b/src/luma/configuration/load.rs @@ -3,22 +3,22 @@ This file is part of Luma. - Luma is free software: you can redistribute it - and/or modify it under the terms of the GNU + Luma is free software: you can redistribute it + and/or modify it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 - of the License, or (at your option) any later + the Free Software Foundation, either version 3 + of the License, or (at your option) any later version. - Luma 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 + Luma 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 Affero General Public License for more details. - You should have received a copy of the GNU - Affero General Public License along with Luma. If not, - see <https://www.gnu.org/licenses/>. + You should have received a copy of the GNU + Affero General Public License along with Luma. + If not, see <https://www.gnu.org/licenses/>. */ use crate::luma::CONFIGURATION_VERSION; @@ -64,7 +64,7 @@ impl Configuration { Ok( contents) => contents, Err(_) => { eprintln!("unable to read configuration file"); - return self.create(); + return self.create(); }, }; diff --git a/src/luma/configuration/new.rs b/src/luma/configuration/new.rs index eea03a9..7875d64 100644 --- a/src/luma/configuration/new.rs +++ b/src/luma/configuration/new.rs @@ -3,22 +3,22 @@ This file is part of Luma. - Luma is free software: you can redistribute it - and/or modify it under the terms of the GNU + Luma is free software: you can redistribute it + and/or modify it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 - of the License, or (at your option) any later + the Free Software Foundation, either version 3 + of the License, or (at your option) any later version. - Luma 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 + Luma 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 Affero General Public License for more details. - You should have received a copy of the GNU - Affero General Public License along with Luma. If not, - see <https://www.gnu.org/licenses/>. + You should have received a copy of the GNU + Affero General Public License along with Luma. + If not, see <https://www.gnu.org/licenses/>. */ use crate::luma::configuration::Configuration; diff --git a/src/luma/configuration/overwrite.rs b/src/luma/configuration/overwrite.rs index 3c06259..2d37c55 100644 --- a/src/luma/configuration/overwrite.rs +++ b/src/luma/configuration/overwrite.rs @@ -3,22 +3,22 @@ This file is part of Luma. - Luma is free software: you can redistribute it - and/or modify it under the terms of the GNU + Luma is free software: you can redistribute it + and/or modify it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 - of the License, or (at your option) any later + the Free Software Foundation, either version 3 + of the License, or (at your option) any later version. - Luma 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 + Luma 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 Affero General Public License for more details. - You should have received a copy of the GNU - Affero General Public License along with Luma. If not, - see <https://www.gnu.org/licenses/>. + You should have received a copy of the GNU + Affero General Public License along with Luma. + If not, see <https://www.gnu.org/licenses/>. */ use crate::luma::configuration::Configuration; diff --git a/src/luma/configuration/path.rs b/src/luma/configuration/path.rs index 63b3ccd..19d8145 100644 --- a/src/luma/configuration/path.rs +++ b/src/luma/configuration/path.rs @@ -3,22 +3,22 @@ This file is part of Luma. - Luma is free software: you can redistribute it - and/or modify it under the terms of the GNU + Luma is free software: you can redistribute it + and/or modify it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 - of the License, or (at your option) any later + the Free Software Foundation, either version 3 + of the License, or (at your option) any later version. - Luma 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 + Luma 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 Affero General Public License for more details. - You should have received a copy of the GNU - Affero General Public License along with Luma. If not, - see <https://www.gnu.org/licenses/>. + You should have received a copy of the GNU + Affero General Public License along with Luma. + If not, see <https://www.gnu.org/licenses/>. */ use crate::luma::configuration::Configuration; diff --git a/src/luma/device.rs b/src/luma/device.rs index c3d5092..30f1bb1 100644 --- a/src/luma/device.rs +++ b/src/luma/device.rs @@ -3,22 +3,22 @@ This file is part of Luma. - Luma is free software: you can redistribute it - and/or modify it under the terms of the GNU + Luma is free software: you can redistribute it + and/or modify it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 - of the License, or (at your option) any later + the Free Software Foundation, either version 3 + of the License, or (at your option) any later version. - Luma 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 + Luma 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 Affero General Public License for more details. - You should have received a copy of the GNU - Affero General Public License along with Luma. If not, - see <https://www.gnu.org/licenses/>. + You should have received a copy of the GNU + Affero General Public License along with Luma. + If not, see <https://www.gnu.org/licenses/>. */ pub mod bootloader; @@ -30,11 +30,17 @@ pub mod decode_thumb; pub mod drop; pub mod exchange; pub mod image; +pub mod interrupt; +pub mod link; +pub mod load; pub mod log; pub mod memory; pub mod r#move; pub mod new; +pub mod pop; +pub mod push; pub mod read; +pub mod shift; pub mod store; pub mod thumb; pub mod trap; @@ -47,9 +53,18 @@ pub enum Trap { OutOfBounds( u32), } -pub enum Branch { - Offset( i32, bool), - Register(u8), +pub enum Log { + Branch, + Continue, + Exchange, + Interrupt, + Link, + Load, + Move, + Pop, + Push, + Shift, + Store, } pub enum Move { @@ -58,8 +73,8 @@ pub enum Move { } pub struct Device { - pub decode: fn(&mut Device), - + pub decode: fn(&mut Device), + memory: *mut u8, registers: [u32; 0x10], cpsr: u32, diff --git a/src/luma/device/bootloader.rs b/src/luma/device/bootloader.rs index 4af66fd..2f84f70 100644 --- a/src/luma/device/bootloader.rs +++ b/src/luma/device/bootloader.rs @@ -3,22 +3,22 @@ This file is part of Luma. - Luma is free software: you can redistribute it - and/or modify it under the terms of the GNU + Luma is free software: you can redistribute it + and/or modify it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 - of the License, or (at your option) any later + the Free Software Foundation, either version 3 + of the License, or (at your option) any later version. - Luma 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 + Luma 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 Affero General Public License for more details. - You should have received a copy of the GNU - Affero General Public License along with Luma. If not, - see <https://www.gnu.org/licenses/>. + You should have received a copy of the GNU + Affero General Public License along with Luma. + If not, see <https://www.gnu.org/licenses/>. */ use crate::luma::device::Device; diff --git a/src/luma/device/branch.rs b/src/luma/device/branch.rs index 6bc2320..0bed178 100644 --- a/src/luma/device/branch.rs +++ b/src/luma/device/branch.rs @@ -3,83 +3,107 @@ This file is part of Luma. - Luma is free software: you can redistribute it - and/or modify it under the terms of the GNU + Luma is free software: you can redistribute it + and/or modify it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 - of the License, or (at your option) any later + the Free Software Foundation, either version 3 + of the License, or (at your option) any later version. - Luma 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 + Luma 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 Affero General Public License for more details. - You should have received a copy of the GNU - Affero General Public License along with Luma. If not, - see <https://www.gnu.org/licenses/>. + You should have received a copy of the GNU + Affero General Public License along with Luma. + If not, see <https://www.gnu.org/licenses/>. */ -use crate::luma::device::{Branch, Device}; +use crate::luma::device::{Device, Log}; impl Device { - pub fn branch(&mut self, kind: Branch) { - match kind { - Branch::Offset(offset, l) => { - if l { // Check the l flag. - // Store the address of the following instruction - // in r14 (lr). - - let pc_offset: u32 = match self.thumb() { - false => 0x4, - true => 0x2, - }; - - self.registers[0xE] = self.registers[0xF] - pc_offset; - - self.log("link", format!("r14 => r15-{pc_offset}={:#010X}", self.registers[0xE])); - } - - // Add the offset to r15 (pc). - - let (address, _) = self.registers[0xF].overflowing_add_signed(offset); - - // Add extra offset to move to the new fetch - // instruction. - let pc_offset = match self.thumb() { - false => 0x8, - true => 0x4, - }; - - self.registers[0xF] = address + pc_offset; - - self.log("branch", format!("r15 => r15{offset:+}+{pc_offset} ({:#010X})", self.registers[0xF])); - }, - Branch::Register(register) => { - // Use the address stored in 'register' as the new - // value in r15 (pc). - - let value = self.registers[register as usize]; - - let t = value & 0b00000000000000000000000000000001 != 0x0; - - self.cpsr = self.cpsr & 0b11111111111111111111111111011111 | (t as u32) << 0x5; - self.exchange(t); - - let address = value & 0b11111111111111111111111111111110; - - // Add extra offset to move to the new fetch - // instruction. - let pc_offset: u32 = match t { - false => 0x8, - true => 0x4, - }; - - self.registers[0xF] = address + pc_offset; - - self.log("branch", format!("r15 => r{register}{pc_offset:+} ({:#010X})", self.registers[0xF])); - }, - } + pub fn arm_branch(&mut self, offset: i32, l: bool) { + // Add the offset to r15 (pc). Conditionally link. + + if l { self.arm_link() } + + let (address, _) = self.registers[0xF].overflowing_add_signed(offset); + + // Add extra offset to move to the new fetch + // instruction. + self.registers[0xF] = address + 0x8; + + self.log(Log::Branch, format!("pc => pc{offset:+}+8 ({:#010X})", self.registers[0xF])); + } + + pub fn arm_branch_exchange(&mut self, register: u8) { + // Use the address stored in 'register' as the new + // value in r15 (pc). + + let value = self.registers[register as usize]; + + let t = value & 0b00000000000000000000000000000001 != 0x0; + + self.cpsr = self.cpsr & 0b11111111111111111111111111011111 | (t as u32) << 0x5; + self.exchange(t); + + // Add extra offset to move to the new fetch + // instruction. + let pc_offset: u32 = match t { + false => 0x8, + true => 0x4, + }; + + self.registers[0xF] = (value & 0b11111111111111111111111111111110) + pc_offset; + + self.log(Log::Branch, format!("pc => r{register}{pc_offset:+} ({:#010X})", self.registers[0xF])); + } + + pub fn thumb_branch(&mut self, offset: i32) { + let (address, _) = self.registers[0xF].overflowing_add_signed(offset); + + self.registers[0xF] = address + 0x4; + + self.log(Log::Branch, format!("pc => pc{offset:+}+4 ({:#010X})", self.registers[0xF])); } + + pub fn thumb_branch_exchange(&mut self, register: u8) { + let value = self.registers[register as usize]; + + let t = value & 0b00000000000000000000000000000001 != 0x0; + + self.cpsr = self.cpsr & 0b11111111111111111111111111011111 | (t as u32) << 0x5; + self.exchange(t); + + // Add extra offset to move to the new fetch + // instruction. + let pc_offset: u32 = match t { + false => 0x8, + true => 0x4, + }; + + self.registers[0xF] = (value & 0b11111111111111111111111111111110) + pc_offset; + + self.log(Log::Branch, format!("pc => r{register}{pc_offset:+} ({:#010X})", self.registers[0xF])); + } + + pub fn thumb_branch_link0(&mut self, offset: i32) { + let (address, _) = self.registers[0xF].overflowing_add_signed(offset); + self.registers[0xE] = address; + + self.log(Log::Branch, format!("lr => pc{offset:+}+4 ({:#010X})", self.registers[0xF])); + } + + pub fn thumb_branch_link1(&mut self, offset: i32) { + let (address, _) = self.registers[0xE].overflowing_add_signed(offset); + + self.thumb_link(); + + (self.registers[0xF], _) = address.overflowing_add(0x4); + + self.log(Log::Branch, format!("pc => pc{offset:+}+4 ({:#010X})", self.registers[0xF])); + } + } diff --git a/src/luma/device/check_condition.rs b/src/luma/device/check_condition.rs index b202448..7b84d8a 100644 --- a/src/luma/device/check_condition.rs +++ b/src/luma/device/check_condition.rs @@ -3,28 +3,46 @@ This file is part of Luma. - Luma is free software: you can redistribute it - and/or modify it under the terms of the GNU + Luma is free software: you can redistribute it + and/or modify it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 - of the License, or (at your option) any later + the Free Software Foundation, either version 3 + of the License, or (at your option) any later version. - Luma 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 + Luma 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 Affero General Public License for more details. - You should have received a copy of the GNU - Affero General Public License along with Luma. If not, - see <https://www.gnu.org/licenses/>. + You should have received a copy of the GNU + Affero General Public License along with Luma. + If not, see <https://www.gnu.org/licenses/>. */ use crate::luma::device::Device; impl Device { pub fn check_condition(&self, condition: u8) -> bool { + // Code Id. Predicates + // 0 eq Z==1 + // 1 ne Z==0 + // 2 cs, hs C==1 + // 3 cc, lo C==0 + // 4 mi N==1 + // 5 pl N==0 + // 6 vs V==1 + // 7 vc V==0 + // 8 hi C==1 && Z==0 + // 9 ls C==0 && Z==1 + // A ge N==V + // B lt N!=V + // C gt Z==0 && N==V + // D le Z==1 && N!=V + // E al true + // F nv false + return match condition { 0x0 => self.cpsr & 0b01000000000000000000000000000000 != 0x00, 0x1 => self.cpsr & 0b01000000000000000000000000000000 == 0x00, @@ -41,7 +59,7 @@ impl Device { 0xC => self.cpsr & 0b01000000000000000000000000000000 == 0x00 && self.cpsr & 0b00010000000000000000000000000000 >> 0x1C == self.cpsr & 0b10000000000000000000000000000000 >> 0x1F, 0xD => self.cpsr & 0b01000000000000000000000000000000 != 0x00 || self.cpsr & 0b00010000000000000000000000000000 >> 0x1C != self.cpsr & 0b10000000000000000000000000000000 >> 0x1F, 0xE => true, - 0xF => false, // Unpredictable, but we ignore it. + 0xF => false, _ => unreachable!(), } } diff --git a/src/luma/device/continue.rs b/src/luma/device/continue.rs index e1f43ec..519cf81 100644 --- a/src/luma/device/continue.rs +++ b/src/luma/device/continue.rs @@ -3,36 +3,42 @@ This file is part of Luma. - Luma is free software: you can redistribute it - and/or modify it under the terms of the GNU + Luma is free software: you can redistribute it + and/or modify it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 - of the License, or (at your option) any later + the Free Software Foundation, either version 3 + of the License, or (at your option) any later version. - Luma 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 + Luma 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 Affero General Public License for more details. - You should have received a copy of the GNU - Affero General Public License along with Luma. If not, - see <https://www.gnu.org/licenses/>. + You should have received a copy of the GNU + Affero General Public License along with Luma. + If not, see <https://www.gnu.org/licenses/>. */ -use crate::luma::device::Device; +use crate::luma::device::{Device, Log}; impl Device { - pub fn r#continue(&mut self) { - let offset = if self.thumb() { - 0x2 - } else { - 0x4 - }; + pub fn arm_continue(&mut self) { + // Increment the program counter by one + // instruction. - self.registers[0xF] += offset; + (self.registers[0xF], _) = self.registers[0xF].overflowing_add(0x4); - self.log("continue", format!("r15 => r15{offset:+}={:#010X}", self.registers[0xF])); + self.log(Log::Continue, format!("pc => pc+4={:#010X}", self.registers[0xF])); + } + + pub fn thumb_continue(&mut self) { + // Increment the program counter by one + // instruction. + + (self.registers[0xF], _) = self.registers[0xF].overflowing_add(0x2); + + self.log(Log::Continue, format!("pc => pc+2={:#010X}", self.registers[0xF])); } } diff --git a/src/luma/device/decode_arm.rs b/src/luma/device/decode_arm.rs index 4aa3216..3cd0ed9 100644 --- a/src/luma/device/decode_arm.rs +++ b/src/luma/device/decode_arm.rs @@ -3,94 +3,105 @@ This file is part of Luma. - Luma is free software: you can redistribute it - and/or modify it under the terms of the GNU + Luma is free software: you can redistribute it + and/or modify it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 - of the License, or (at your option) any later + the Free Software Foundation, either version 3 + of the License, or (at your option) any later version. - Luma 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 + Luma 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 Affero General Public License for more details. - You should have received a copy of the GNU - Affero General Public License along with Luma. If not, - see <https://www.gnu.org/licenses/>. + You should have received a copy of the GNU + Affero General Public License along with Luma. + If not, see <https://www.gnu.org/licenses/>. */ -use crate::luma::device::{Branch, Device, Move, Trap}; +use crate::luma::device::{Device, Move, Trap}; impl Device { pub fn decode_arm(&mut self) { debug_assert!(!self.thumb()); - let address = self.registers[0xF] - 0x8; + let (address, _) = self.registers[0xF].overflowing_sub(0x8); let opcode = self.read_word(address); if cfg!(debug_assertions) { eprintln!("{opcode:#034b} @ {address:#010X}") } - let condition = ((opcode & 0b11110000000000000000000000000000) >> 0x1C) as u8; - if !self.check_condition(condition) { return self.r#continue() } - - // b{cond}{l} +/-offset_24 + // b{cond}{l} Offset24 if opcode & 0b00001110000000000000000000000000 == 0b00001010000000000000000000000000 { - let link = opcode & 0b00000001000000000000000000000000 != 0x0; - - let offset = { - let mut offset = opcode & 0b00000000111111111111111111111111; + let condition = ((opcode & 0b11110000000000000000000000000000) >> 0x1C) as u8; + if !self.check_condition(condition) { return self.arm_continue() } - if offset & 0b00000000100000000000000000000000 != 0x0 { offset |= 0b00111111000000000000000000000000 } // Sign-extend. + let immediate = opcode & 0b00000000111111111111111111111111; - offset <<= 0x2; + let l = opcode & 0b00000001000000000000000000000000 != 0x0; - offset as i32 - }; + let offset = ((immediate << 0x8) as i32) >> 0x6; - return self.branch(Branch::Offset(offset, link)); + return self.arm_branch(offset, l); } // bx{cond} Rm if opcode & 0b00001111111111111111111111110000 == 0b00000001001011111111111100010000 { + let condition = ((opcode & 0b11110000000000000000000000000000) >> 0x1C) as u8; + if !self.check_condition(condition) { return self.arm_continue() } + let register = (opcode & 0b00000000000000000000000000001111) as u8; - return self.branch(Branch::Register(register)); + return self.arm_branch_exchange(register); } - // ldr|str{cond}{b} Rn, +/-offset_12 + // ldr|str{cond}{b} Rd, [Rn, Offset12] if opcode & 0b00001111001000000000000000000000 == 0b00000101000000000000000000000000 { - let register = ((opcode & 0b00000000000000001111000000000000) >> 0xC) as u8; - - let base = ((opcode & 0b00000000000011110000000000000000) >> 0x10) as u8; + let condition = ((opcode & 0b11110000000000000000000000000000) >> 0x1C) as u8; + if !self.check_condition(condition) { return self.arm_continue() } let immediate = (opcode & 0b00000000000000000000111111111111) as u16; - let u = opcode & 0b00000000100000000000000000000000 != 0x0; - let b = opcode & 0b00000000010000000000000000000000 != 0x0; + let register = ((opcode & 0b00000000000000001111000000000000) >> 0xC) as u8; + + let base = ((opcode & 0b00000000000011110000000000000000) >> 0x10) as u8; + let l = opcode & 0b00000000000100000000000000000000 != 0x0; + let b = opcode & 0b00000000010000000000000000000000 != 0x0; + let u = opcode & 0b00000000100000000000000000000000 != 0x0; - self.store(register, base, immediate, u, b, l); - return self.r#continue(); + self.arm_store(register, base, immediate, u, b, l); + return self.arm_continue(); } // mov{cond}{s} Rd, Rn if opcode & 0b00001101111111100000111111110000 == 0b00000001101000000000000000000000 { - let destination = ((opcode & 0b00000000000000001111000000000000) >> 0xC) as u8; - let source = (opcode & 0b00000000000000000000000000001111) as u8; + let condition = ((opcode & 0b11110000000000000000000000000000) >> 0x1C) as u8; + if !self.check_condition(condition) { return self.arm_continue() } - let value = self.registers[source as usize]; - self.registers[destination as usize] = value; + let source = (opcode & 0b00000000000000000000000000001111) as u8; + + let destination = ((opcode & 0b00000000000000001111000000000000) >> 0xC) as u8; let s = opcode & 0b00000000000100000000000000000000 != 0x0; - - self.r#move(destination, Move::Register(source), s); - return self.r#continue(); + + self.arm_move(destination, Move::Register(source), s); + return self.arm_continue(); + } + + // svc{cond} Immediate24 + if opcode & 0b00001111000000000000000000000000 == 0b00001111000000000000000000000000 { + let condition = ((opcode & 0b11110000000000000000000000000000) >> 0x1C) as u8; + if !self.check_condition(condition) { return self.arm_continue() } + + let immediate = opcode & 0b00000000111111111111111111111111; + + return self.interrupt(immediate); } self.trap(Trap::InvalidArmOpcode(self.registers[0xF] - 0x8, opcode)); - self.r#continue(); + self.arm_continue(); } } diff --git a/src/luma/device/decode_thumb.rs b/src/luma/device/decode_thumb.rs index 5ccd9ee..deafdfa 100644 --- a/src/luma/device/decode_thumb.rs +++ b/src/luma/device/decode_thumb.rs @@ -3,70 +3,155 @@ This file is part of Luma. - Luma is free software: you can redistribute it - and/or modify it under the terms of the GNU + Luma is free software: you can redistribute it + and/or modify it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 - of the License, or (at your option) any later + the Free Software Foundation, either version 3 + of the License, or (at your option) any later version. - Luma 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 + Luma 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 Affero General Public License for more details. - You should have received a copy of the GNU - Affero General Public License along with Luma. If not, - see <https://www.gnu.org/licenses/>. + You should have received a copy of the GNU + Affero General Public License along with Luma. + If not, see <https://www.gnu.org/licenses/>. */ -use crate::luma::device::{Branch, Device, Move, Trap}; +use crate::luma::device::{Device, Trap}; impl Device { pub fn decode_thumb(&mut self) { debug_assert!(self.thumb()); - let address = self.registers[0xF] - 0x4; + let (address, _) = self.registers[0xF].overflowing_sub(0x4); let opcode = self.read_halfword(address); if cfg!(debug_assertions) { eprintln!("{opcode:#018b} @ {address:#010X}") } // b if opcode & 0b1111100000000000 == 0b1110000000000000 { - let offset = { - let mut offset = (opcode & 0b0000011111111111) as u32; + let immediate = opcode & 0b0000011111111111; - offset <<= 0x1; + let offset = (((immediate as u32) << 0x15) as i32) >> 0x14; - if offset & 0b00000000000000000000100000000000 != 0x0 { offset |= 0b11111111111111111111000000000000 } + return self.thumb_branch(offset); + } + + // b{cond}, svc Immediate8 + if opcode & 0b1111000000000000 == 0b1101000000000000 { + let condition = ((opcode & 0b0000111100000000) >> 0x8) as u8; + + if condition == 0xF { + let immediate = (opcode & 0b0000000011111111) as u8; - offset as i32 - }; + return self.interrupt(immediate as u32); + } - return self.branch(Branch::Offset(offset, false)); + if !self.check_condition(condition) { return self.thumb_continue() } + + let immediate = opcode & 0b0000000011111111; + + let offset = (((immediate as u32) << 0x18) as i32) >> 0x17; + + return self.thumb_branch(offset); } - // b{cond} - if opcode & 0b1111000000000000 == 0b1101000000000000 { - let offset = { - let mut offset = (opcode & 0b0000000011111111) as u32; + // bl Offset11 + if opcode & 0b1111100000000000 == 0b1111000000000000 { + let immediate = opcode & 0b0000011111111111; - offset <<= 0x1; + let offset = (((immediate as u32) << 0x15) as i32) >> 0x9; - if offset & 0b00000000000000000000000100000000 != 0x0 { offset |= 0b11111111111111111111111000000000 } + self.thumb_branch_link0(offset); + return self.thumb_continue(); + } + + // bl Offset11 + if opcode & 0b1111100000000000 == 0b1111100000000000 { + let immediate = opcode & 0b0000011111111111; - offset as i32 - }; + let offset = ((immediate as u32) << 0x1) as i32; - return self.branch(Branch::Offset(offset, false)); + return self.thumb_branch_link1(offset); } - // bx + // bx Rm if opcode & 0b1111111110000111 == 0b0100011100000000 { let register = ((opcode & 0b0000000001111000) >> 0x3) as u8; - return self.branch(Branch::Register(register)); + return self.thumb_branch_exchange(register); + } + + // ldr Rd, [Rn, Immediate5] + if opcode & 0b1111100000000000 == 0b0110100000000000 { + let destination = (opcode & 0b0000000000000111) as u8; + + let base = ((opcode & 0b0000000000111000) >> 0x3) as u8; + + let immediate = ((opcode & 0b0000011111000000) >> 0x5) as u8; + + self.thumb_load_immediate(destination, base, immediate); + return self.thumb_continue(); + } + + // ldr Rd, [Rn, Rm] + if opcode & 0b1111111000000000 == 0b0101100000000000 { + let destination = (opcode & 0b0000000000000111) as u8; + + let base = ((opcode & 0b0000000000111000) >> 0x3) as u8; + + let offset = ((opcode & 0b0000000111000000) >> 0x5) as u8; + + self.thumb_load_register(destination, base, offset); + return self.thumb_continue(); + } + + // ldr Rd, [r13, Immediate8] + if opcode & 0b1111100000000000 == 0b1001100000000000 { + let destination = ((opcode & 0b0000011100000000) >> 0x8) as u8; + + let immediate = (opcode & 0b0000000011111111) as u8; + + self.thumb_load_sp(destination, immediate); + return self.thumb_continue(); + } + + // ldr Rd, [r15, Immediate8] + if opcode & 0b1111100000000000 == 0b0100100000000000 { + let destination = ((opcode & 0b0000011100000000) >> 0x8) as u8; + + let immediate = (opcode & 0b0000000011111111) as u8; + + self.thumb_load_pc(destination, immediate); + return self.thumb_continue(); + } + + // lsl Rd, Rm, Immediate5 + if opcode & 0b1111100000000000 == 0b0000000000000000 { + let destination = (opcode & 0b0000000000000111) as u8; + + let source = ((opcode & 0b0000000000111000) >> 0x3) as u8; + + let immediate = ((opcode & 0b0000011111000000) >> 0x5) as u8; + + self.thumb_shift_left(destination, source, immediate); + return self.thumb_continue(); + } + + // lsr Rd, Rm, Immediate5 + if opcode & 0b1111100000000000 == 0b0000100000000000 { + let destination = (opcode & 0b0000000000000111) as u8; + + let source = ((opcode & 0b0000000000111000) >> 0x3) as u8; + + let immediate = ((opcode & 0b0000011111000000) >> 0x5) as u8; + + self.thumb_shift_right(destination, source, immediate); + return self.thumb_continue(); } // mov Rd, Rm @@ -75,18 +160,18 @@ impl Device { let source = ((opcode & 0b0000000001111000) >> 0x3) as u8; - self.r#move(destination, Move::Register(source), false); - return self.r#continue(); + self.thumb_move_high(destination, source); + return self.thumb_continue(); } - // movs Rd, immediate_8 + // movs Rd, Immediate8 if opcode & 0b1111100000000000 == 0b0010000000000000 { let destination = ((opcode & 0b0000011100000000) >> 0x8) as u8; let immediate = (opcode & 0b0000000011111111) as u8; - self.r#move(destination, Move::Immediate(immediate), true); - return self.r#continue(); + self.thumb_move_immediate(destination, immediate); + return self.thumb_continue(); } // movs Rd, Rn @@ -95,12 +180,44 @@ impl Device { let source = ((opcode & 0b0000000000111000) >> 0x3) as u8; - self.r#move(destination, Move::Register(source), true); - return self.r#continue(); + self.thumb_move(destination, source); + return self.thumb_continue(); + } + + // pop Registers + if opcode & 0b1111111000000000 == 0b1011110000000000 { + let list = (opcode & 0b0000000011111111) as u8; + + let r = opcode & 0b0000000100000000 != 0x0; + + self.thumb_pop(list, r); + if !r { return self.thumb_continue() } + } + + // push Registers + if opcode & 0b1111111000000000 == 0b1011010000000000 { + let list = (opcode & 0b0000000011111111) as u8; + + let r = opcode & 0b0000000100000000 != 0x0; + + self.thumb_push(list, r); + return self.thumb_continue(); + } + + // strh Rd, [Rn, Immediate5] + if opcode & 0b1111100000000000 == 0b1000000000000000 { + let source = (opcode & 0b0000000000000111) as u8; + + let base = ((opcode & 0b0000000000000111) >> 0x3) as u8; + + let immediate = ((opcode & 0b0000011111000000) >> 0x6) as u8; + + self.thumb_store_halfword_immediate(source, base, immediate); + return self.thumb_continue(); } self.trap(Trap::InvalidThumbOpcode(address, opcode)); - self.r#continue(); + self.thumb_continue(); } } diff --git a/src/luma/device/drop.rs b/src/luma/device/drop.rs index 6bb694b..da5c727 100644 --- a/src/luma/device/drop.rs +++ b/src/luma/device/drop.rs @@ -3,22 +3,22 @@ This file is part of Luma. - Luma is free software: you can redistribute it - and/or modify it under the terms of the GNU + Luma is free software: you can redistribute it + and/or modify it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 - of the License, or (at your option) any later + the Free Software Foundation, either version 3 + of the License, or (at your option) any later version. - Luma 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 + Luma 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 Affero General Public License for more details. - You should have received a copy of the GNU - Affero General Public License along with Luma. If not, - see <https://www.gnu.org/licenses/>. + You should have received a copy of the GNU + Affero General Public License along with Luma. + If not, see <https://www.gnu.org/licenses/>. */ use crate::luma::device::Device; diff --git a/src/luma/device/exchange.rs b/src/luma/device/exchange.rs index 32a2f8a..7248792 100644 --- a/src/luma/device/exchange.rs +++ b/src/luma/device/exchange.rs @@ -3,35 +3,38 @@ This file is part of Luma. - Luma is free software: you can redistribute it - and/or modify it under the terms of the GNU + Luma is free software: you can redistribute it + and/or modify it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 - of the License, or (at your option) any later + the Free Software Foundation, either version 3 + of the License, or (at your option) any later version. - Luma 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 + Luma 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 Affero General Public License for more details. - You should have received a copy of the GNU - Affero General Public License along with Luma. If not, - see <https://www.gnu.org/licenses/>. + You should have received a copy of the GNU + Affero General Public License along with Luma. + If not, see <https://www.gnu.org/licenses/>. */ -use crate::luma::device::Device; +use crate::luma::device::{Device, Log}; impl Device { pub fn exchange(&mut self, thumb: bool) { + // Conditionally exchanges the instruction set. + // cpsr is set by the caller. + + self.log(Log::Exchange, format!("T => {thumb}")); + let decoders = [ Device::decode_arm, Device::decode_thumb, ]; self.decode = decoders[thumb as usize]; - - self.log("exchange", format!("T => {thumb}")); } } diff --git a/src/luma/device/image.rs b/src/luma/device/image.rs index 5fbb0be..2bb2230 100644 --- a/src/luma/device/image.rs +++ b/src/luma/device/image.rs @@ -3,22 +3,22 @@ This file is part of Luma. - Luma is free software: you can redistribute it - and/or modify it under the terms of the GNU + Luma is free software: you can redistribute it + and/or modify it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 - of the License, or (at your option) any later + the Free Software Foundation, either version 3 + of the License, or (at your option) any later version. - Luma 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 + Luma 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 Affero General Public License for more details. - You should have received a copy of the GNU - Affero General Public License along with Luma. If not, - see <https://www.gnu.org/licenses/>. + You should have received a copy of the GNU + Affero General Public License along with Luma. + If not, see <https://www.gnu.org/licenses/>. */ use crate::luma::device::Device; diff --git a/src/luma/device/interrupt.rs b/src/luma/device/interrupt.rs new file mode 100644 index 0000000..61fd7bf --- /dev/null +++ b/src/luma/device/interrupt.rs @@ -0,0 +1,44 @@ +/* + Copyright 2021-2023 Gabriel Jensen. + + This file is part of Luma. + + Luma is free software: you can redistribute it + and/or modify it under the terms of the GNU + Affero General Public License as published by + the Free Software Foundation, either version 3 + of the License, or (at your option) any later + version. + + Luma 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 + Affero General Public License for more details. + + You should have received a copy of the GNU + Affero General Public License along with Luma. + If not, see <https://www.gnu.org/licenses/>. +*/ + +use crate::luma::device::{Device, Log}; + +impl Device { + pub fn interrupt(&mut self, immediate: u32) { + self.log(Log::Interrupt, format!("{immediate:#010X}")); + + self.spsr[0b0011] = self.cpsr; + self.log(Log::Interrupt, format!("spsr_svc => cpsr ({:#034b})", self.spsr[0b0011])); + + // Enter svc mode. + // Enter ARM state. + // Disable IRQ exceptions. + self.cpsr = self.cpsr & 0b11111111111111111111111101000000 | 0b00000000000000000000000010010011; + self.log(Log::Interrupt, format!("cpsr => {:#034b}", self.cpsr)); + + self.exchange(false); + + self.registers[0xF] = 0x00000008; + self.log(Log::Interrupt, format!("pc => {:#010X}", self.registers[0xF])); + } +} diff --git a/src/luma/device/link.rs b/src/luma/device/link.rs new file mode 100644 index 0000000..24975d4 --- /dev/null +++ b/src/luma/device/link.rs @@ -0,0 +1,44 @@ +/* + Copyright 2021-2023 Gabriel Jensen. + + This file is part of Luma. + + Luma is free software: you can redistribute it + and/or modify it under the terms of the GNU + Affero General Public License as published by + the Free Software Foundation, either version 3 + of the License, or (at your option) any later + version. + + Luma 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 + Affero General Public License for more details. + + You should have received a copy of the GNU + Affero General Public License along with Luma. + If not, see <https://www.gnu.org/licenses/>. +*/ + +use crate::luma::device::{Device, Log}; + +impl Device { + pub fn arm_link(&mut self) { + // Store the address of the following instruction + // in the link register. + + (self.registers[0xE], _) = self.registers[0xF].overflowing_sub(0x4); + + self.log(Log::Link, format!("lr => pc-4 ({:#010X})", self.registers[0xE])); + } + + pub fn thumb_link(&mut self) { + // Store the address of the following instruction + // in the link register. + + (self.registers[0xE], _) = self.registers[0xF].overflowing_sub(0x2); + + self.log(Log::Link, format!("lr => pc ({:#010X})", self.registers[0xE])); + } +} diff --git a/src/luma/device/load.rs b/src/luma/device/load.rs new file mode 100644 index 0000000..7769300 --- /dev/null +++ b/src/luma/device/load.rs @@ -0,0 +1,87 @@ +/* + Copyright 2021-2023 Gabriel Jensen. + + This file is part of Luma. + + Luma is free software: you can redistribute it + and/or modify it under the terms of the GNU + Affero General Public License as published by + the Free Software Foundation, either version 3 + of the License, or (at your option) any later + version. + + Luma 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 + Affero General Public License for more details. + + You should have received a copy of the GNU + Affero General Public License along with Luma. + If not, see <https://www.gnu.org/licenses/>. +*/ + +use crate::luma::device::{Device, Log}; + +impl Device { + pub fn thumb_load_immediate(&mut self, destination: u8, base: u8, immediate: u8) { + // Load word from memory using immediate offset. + + let base_value = self.registers[base as usize]; + + let offset = (immediate as u32) << 0x2; + + let address = base_value + offset; + + let value = self.read_word(address); + self.registers[destination as usize] = value; + + self.log(Log::Load, format!("r{destination} => r{base}{offset:+}={address:#010X} ({value:#010X})")); + } + + pub fn thumb_load_register(&mut self, destination: u8, base: u8, offset: u8) { + // Load word from memory using register offset. + + let base_value = self.registers[base as usize]; + let offset_value = self.registers[offset as usize] as i32; + + let (address, _) = base_value.overflowing_add_signed(offset_value); + + let value = self.read_word(address); + self.registers[destination as usize] = value; + + self.log(Log::Load, format!("r{destination} => r{base}+r{offset}={address:#010X} ({value:#010X})")); + } + + pub fn thumb_load_pc(&mut self, destination: u8, immediate: u8) { + // Load word from memory using offset relative to + // the program counter. + + let offset = (immediate as u32) << 0x2; + + let base = self.registers[0xF] & 0b11111111111111111111111111111100; + + let address = base + offset; + + let value = self.read_word(address); + self.registers[destination as usize] = value; + + self.log(Log::Load, format!("r{destination} => pc{offset:+}={address:#010X} ({value:#010X})")); + } + + pub fn thumb_load_sp(&mut self, destination: u8, immediate: u8) { + // Load word from memory using offset relative to + // the stack pointer. + + let offset = (immediate as u32) << 0x2; + + let base = self.registers[0xD]; + + let address = base + offset; + + let value = self.read_word(address); + self.registers[destination as usize] = value; + + self.log(Log::Load, format!("r{destination} => sp{offset:+}={address:#010X} ({value:#010X})")); + } +} diff --git a/src/luma/device/log.rs b/src/luma/device/log.rs index e0ace5d..bc7369c 100644 --- a/src/luma/device/log.rs +++ b/src/luma/device/log.rs @@ -3,33 +3,42 @@ This file is part of Luma. - Luma is free software: you can redistribute it - and/or modify it under the terms of the GNU + Luma is free software: you can redistribute it + and/or modify it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 - of the License, or (at your option) any later + the Free Software Foundation, either version 3 + of the License, or (at your option) any later version. - Luma 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 + Luma 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 Affero General Public License for more details. - You should have received a copy of the GNU - Affero General Public License along with Luma. If not, - see <https://www.gnu.org/licenses/>. + You should have received a copy of the GNU + Affero General Public License along with Luma. + If not, see <https://www.gnu.org/licenses/>. */ -use crate::luma::device::Device; +use crate::luma::device::{Device, Log}; impl Device { - pub fn log(&mut self, keyword: &str, message: String) { + pub fn log(&mut self, kind: Log, message: String) { if cfg!(debug_assertions) { // This optimises the function away. - let padding: usize = 0x8; - - assert!(keyword.len() <= padding); - let keyword = keyword.to_string() + &" ".to_string().repeat(padding - keyword.len()); + let keyword = match kind { + Log::Branch => "branch ", + Log::Continue => "continue ", + Log::Exchange => "exchange ", + Log::Interrupt => "interrupt", + Log::Link => "link ", + Log::Load => "load ", + Log::Move => "move ", + Log::Pop => "pop ", + Log::Push => "push ", + Log::Shift => "shift ", + Log::Store => "store ", + }; eprintln!("{keyword} : {message}"); } diff --git a/src/luma/device/memory.rs b/src/luma/device/memory.rs index 652b133..0398a41 100644 --- a/src/luma/device/memory.rs +++ b/src/luma/device/memory.rs @@ -3,22 +3,22 @@ This file is part of Luma. - Luma is free software: you can redistribute it - and/or modify it under the terms of the GNU + Luma is free software: you can redistribute it + and/or modify it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 - of the License, or (at your option) any later + the Free Software Foundation, either version 3 + of the License, or (at your option) any later version. - Luma 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 + Luma 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 Affero General Public License for more details. - You should have received a copy of the GNU - Affero General Public License along with Luma. If not, - see <https://www.gnu.org/licenses/>. + You should have received a copy of the GNU + Affero General Public License along with Luma. + If not, see <https://www.gnu.org/licenses/>. */ use crate::luma::MEMORY_SIZE; diff --git a/src/luma/device/move.rs b/src/luma/device/move.rs index 9818f68..2952266 100644 --- a/src/luma/device/move.rs +++ b/src/luma/device/move.rs @@ -3,28 +3,28 @@ This file is part of Luma. - Luma is free software: you can redistribute it - and/or modify it under the terms of the GNU + Luma is free software: you can redistribute it + and/or modify it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 - of the License, or (at your option) any later + the Free Software Foundation, either version 3 + of the License, or (at your option) any later version. - Luma 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 + Luma 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 Affero General Public License for more details. - You should have received a copy of the GNU - Affero General Public License along with Luma. If not, - see <https://www.gnu.org/licenses/>. + You should have received a copy of the GNU + Affero General Public License along with Luma. + If not, see <https://www.gnu.org/licenses/>. */ -use crate::luma::device::{Device, Move}; +use crate::luma::device::{Device, Log, Move}; impl Device { - pub fn r#move(&mut self, destination: u8, kind: Move, s: bool) { + pub fn arm_move(&mut self, destination: u8, kind: Move, s: bool) { let value = match kind { Move::Immediate(immediate) => immediate as u32, Move::Register( source) => self.registers[source as usize], @@ -37,12 +37,47 @@ impl Device { self.cpsr = self.spsr[(self.cpsr & 0b00000000000000000000000000001111) as usize]; // We ignore the fifth bit, as this is always set. } else { // TO-DO + todo!(); } } - self.log("move", match kind { + self.log(Log::Move, match kind { Move::Immediate(..) => format!("r{destination} => {value:#04X}"), Move::Register( source) => format!("r{destination} => r{source} ({value:#010X})"), }); } + + pub fn thumb_move(&mut self, destination: u8, source: u8) { + // Move between high and low registers. Condition + // flags are set. + + let value = self.registers[source as usize]; + self.registers[destination as usize] = value; + + // TO-DO: Conditions. + + self.log(Log::Move, format!("r{destination} => r{source} ({value:#010X})")); + } + + pub fn thumb_move_high(&mut self, destination: u8, source: u8) { + // Move between registers. One or both registers + // are a high register. Condition flags are not + // set. + + let value = self.registers[source as usize]; + self.registers[destination as usize] = value; + + self.log(Log::Move, format!("r{destination} => r{source} ({value:#010X})")); + } + + pub fn thumb_move_immediate(&mut self, destination: u8, immediate: u8) { + // Move immediate to low register. Condition flags + // are set. + + self.registers[destination as usize] = immediate as u32; + + // TO-DO: Conditions. + + self.log(Log::Move, format!("r{destination} => {immediate:#04X}")); + } }
\ No newline at end of file diff --git a/src/luma/device/new.rs b/src/luma/device/new.rs index c3aec4f..d11e0f8 100644 --- a/src/luma/device/new.rs +++ b/src/luma/device/new.rs @@ -3,22 +3,22 @@ This file is part of Luma. - Luma is free software: you can redistribute it - and/or modify it under the terms of the GNU + Luma is free software: you can redistribute it + and/or modify it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 - of the License, or (at your option) any later + the Free Software Foundation, either version 3 + of the License, or (at your option) any later version. - Luma 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 + Luma 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 Affero General Public License for more details. - You should have received a copy of the GNU - Affero General Public License along with Luma. If not, - see <https://www.gnu.org/licenses/>. + You should have received a copy of the GNU + Affero General Public License along with Luma. + If not, see <https://www.gnu.org/licenses/>. */ use crate::luma::MEMORY_SIZE; @@ -57,7 +57,7 @@ impl Device { 0x00000000, 0x00000000, 0x00000000, - 0x00000000, + 0x03007F00, start, ], cpsr: 0b00000000000000000000000000001111, diff --git a/src/luma/device/pop.rs b/src/luma/device/pop.rs new file mode 100644 index 0000000..cdf08ce --- /dev/null +++ b/src/luma/device/pop.rs @@ -0,0 +1,58 @@ +/* + Copyright 2021-2023 Gabriel Jensen. + + This file is part of Luma. + + Luma is free software: you can redistribute it + and/or modify it under the terms of the GNU + Affero General Public License as published by + the Free Software Foundation, either version 3 + of the License, or (at your option) any later + version. + + Luma 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 + Affero General Public License for more details. + + You should have received a copy of the GNU + Affero General Public License along with Luma. + If not, see <https://www.gnu.org/licenses/>. +*/ + +use crate::luma::device::{Device, Log}; + +impl Device { + pub fn thumb_pop(&mut self, list: u8, r: bool) { + // Return true if branching. + + let ammount = list.count_ones() as u8 + r as u8; + + let mut address = self.registers[0xE]; + + for index in 0x0..0x7 { + let pop = (list >> index) & 0b00000001 != 0x0; + + if pop { + let value = self.read_word(address); + + self.registers[index as usize] = value; + self.log(Log::Pop, format!("r{index} => {address:#010X} ({value:#010X})")); + + address += 0x4; + } + } + + if r { + let value = self.read_word(address); + + // We ignore the T flag. + (self.registers[0xF], _) = (value & 0b11111111111111111111111111111110).overflowing_add(0x4); + self.log(Log::Pop, format!("pc => {address:#010X}+4 ({value:#010X})")); + } + + self.registers[0xE] = address - 0x4; + self.log(Log::Pop, format!("sp => sp{:+} ({:#010X})", ammount * 0x4, self.registers[0xE])); + } +} diff --git a/src/luma/device/push.rs b/src/luma/device/push.rs new file mode 100644 index 0000000..65ca3d9 --- /dev/null +++ b/src/luma/device/push.rs @@ -0,0 +1,58 @@ +/* + Copyright 2021-2023 Gabriel Jensen. + + This file is part of Luma. + + Luma is free software: you can redistribute it + and/or modify it under the terms of the GNU + Affero General Public License as published by + the Free Software Foundation, either version 3 + of the License, or (at your option) any later + version. + + Luma 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 + Affero General Public License for more details. + + You should have received a copy of the GNU + Affero General Public License along with Luma. + If not, see <https://www.gnu.org/licenses/>. +*/ + +use crate::luma::device::{Device, Log}; + +impl Device { + pub fn thumb_push(&mut self, list: u8, r: bool) { + let ammount = list.count_ones() as u8 + r as u8; + + let (start, _) = self.registers[0xE].overflowing_sub(ammount as u32 * 0x4); + + let mut address = start; + + for index in 0x0..0x7 { + let push = (list >> index) & 0b00000001 != 0x0; + + if push { + let value = self.registers[index as usize]; + + self.write_word(address, value); + self.log(Log::Push, format!("{address:#010X} => r{index} ({value:#010X})")); + + address += 0x4; + } + } + + if r { + let value = self.registers[0xD]; + + self.write_word(address, value); + self.log(Log::Push, format!("{address:#010X} = lr ({value:#010X})")); + } + + self.registers[0xE] = start; + + self.log(Log::Push, format!("sp => sp-{} ({start:#010X})", ammount * 0x4)); + } +} diff --git a/src/luma/device/read.rs b/src/luma/device/read.rs index 5622136..f0ea176 100644 --- a/src/luma/device/read.rs +++ b/src/luma/device/read.rs @@ -3,36 +3,34 @@ This file is part of Luma. - Luma is free software: you can redistribute it - and/or modify it under the terms of the GNU + Luma is free software: you can redistribute it + and/or modify it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 - of the License, or (at your option) any later + the Free Software Foundation, either version 3 + of the License, or (at your option) any later version. - Luma 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 + Luma 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 Affero General Public License for more details. - You should have received a copy of the GNU - Affero General Public License along with Luma. If not, - see <https://www.gnu.org/licenses/>. + You should have received a copy of the GNU + Affero General Public License along with Luma. + If not, see <https://www.gnu.org/licenses/>. */ use crate::luma::device::{Device, Trap}; use crate::luma::MEMORY_SIZE; impl Device { - #[allow(dead_code)] pub fn read_byte(&mut self, address: u32) -> u8 { if address >= MEMORY_SIZE as u32 { self.trap(Trap::OutOfBounds(address)) } return unsafe { *(self.memory.offset(address as isize) as *mut u8) }; } - #[allow(dead_code)] pub fn read_halfword(&mut self, address: u32) -> u16 { if address >= MEMORY_SIZE as u32 { self.trap(Trap::OutOfBounds(address)) } if address % 0x2 != 0x0 { self.trap(Trap::BadAlignment(address, 0x2)) } @@ -40,7 +38,6 @@ impl Device { return unsafe { *(self.memory.offset(address as isize) as *mut u16) }; } - #[allow(dead_code)] pub fn read_word(&mut self, address: u32) -> u32 { if address >= MEMORY_SIZE as u32 { self.trap(Trap::OutOfBounds(address)) } if address % 0x4 != 0x0 { self.trap(Trap::BadAlignment(address, 0x4)) } diff --git a/src/luma/device/shift.rs b/src/luma/device/shift.rs new file mode 100644 index 0000000..5b19a92 --- /dev/null +++ b/src/luma/device/shift.rs @@ -0,0 +1,50 @@ +/* + Copyright 2021-2023 Gabriel Jensen. + + This file is part of Luma. + + Luma is free software: you can redistribute it + and/or modify it under the terms of the GNU + Affero General Public License as published by + the Free Software Foundation, either version 3 + of the License, or (at your option) any later + version. + + Luma 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 + Affero General Public License for more details. + + You should have received a copy of the GNU + Affero General Public License along with Luma. + If not, see <https://www.gnu.org/licenses/>. +*/ + +use crate::luma::device::{Device, Log}; + +impl Device { + pub fn thumb_shift_left(&mut self, destination: u8, source: u8, immediate: u8) { + let source_value = self.registers[source as usize]; + + let (value, _) = source_value.overflowing_shl(immediate as u32); + + self.registers[destination as usize] = value; + + // TO-DO: Set condition flags. + + self.log(Log::Shift, format!("r{destination} => r{source} << {immediate} ({value:#010X})")); + } + + pub fn thumb_shift_right(&mut self, destination: u8, source: u8, immediate: u8) { + let source_value = self.registers[source as usize]; + + let (value, _) = source_value.overflowing_shr(immediate as u32); + + self.registers[destination as usize] = value; + + // TO-DO: Set condition flags. + + self.log(Log::Shift, format!("r{destination} => r{source} << {immediate} ({value:#010X})")); + } +} diff --git a/src/luma/device/store.rs b/src/luma/device/store.rs index e1df1a0..981b502 100644 --- a/src/luma/device/store.rs +++ b/src/luma/device/store.rs @@ -3,30 +3,30 @@ This file is part of Luma. - Luma is free software: you can redistribute it - and/or modify it under the terms of the GNU + Luma is free software: you can redistribute it + and/or modify it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 - of the License, or (at your option) any later + the Free Software Foundation, either version 3 + of the License, or (at your option) any later version. - Luma 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 + Luma 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 Affero General Public License for more details. - You should have received a copy of the GNU - Affero General Public License along with Luma. If not, - see <https://www.gnu.org/licenses/>. + You should have received a copy of the GNU + Affero General Public License along with Luma. + If not, see <https://www.gnu.org/licenses/>. */ -use crate::luma::device::Device; +use crate::luma::device::{Device, Log}; impl Device { - pub fn store(&mut self, register: u8, base: u8, immediate: u16, u: bool, _b: bool, l: bool) { + pub fn arm_store(&mut self, destination: u8, base: u8, immediate: u16, u: bool, _b: bool, l: bool) { // TO-DO: Byte loads/stores. - + // The U flag determins the sign of the offset // (set = unsigned). let offset = if u { @@ -39,20 +39,36 @@ impl Device { if l { // Check the L flag. // If the L flag is set, we perform a memory-to- - // register load instead. + // destination load instead. let value = self.read_word(address); - self.registers[register as usize] = value; + self.registers[destination as usize] = value; - self.log("load", format!("r{register} => r{base}{offset:+}={address:#010X} ({value:#010X})")); + self.log(Log::Load, format!("r{destination} => r{base}{offset:+}={address:#010X} ({value:#010X})")); } else { - // Otherwise, we perform a register-to-memory + // Otherwise, we perform a destination-to-memory // store. - let value = self.registers[register as usize]; + let value = self.registers[destination as usize]; self.write_word(address, value); - self.log("store", format!("r{base}{offset:+}={address:#010X} => r{register} ({value:#010X})")); + self.log(Log::Store, format!("r{base}{offset:+}={address:#010X} => r{destination} ({value:#010X})")); } } + + pub fn thumb_store_halfword_immediate(&mut self, source: u8, base: u8, immediate: u8) { + // Load halfword from memory using immediate offset. + + let base_value = self.registers[base as usize]; + + let offset = (immediate as u32) << 0x1; + + let (address, _) = base_value.overflowing_add(offset); + + let value = (self.registers[source as usize] & 0b00000000000000001111111111111111) as u16; + self.write_halfword(address, value); + + self.log(Log::Store, format!("r{source} => r{base}{immediate:+} ({value:#06X})")); + } + } diff --git a/src/luma/device/thumb.rs b/src/luma/device/thumb.rs index 130a164..aeb7059 100644 --- a/src/luma/device/thumb.rs +++ b/src/luma/device/thumb.rs @@ -3,22 +3,22 @@ This file is part of Luma. - Luma is free software: you can redistribute it - and/or modify it under the terms of the GNU + Luma is free software: you can redistribute it + and/or modify it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 - of the License, or (at your option) any later + the Free Software Foundation, either version 3 + of the License, or (at your option) any later version. - Luma 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 + Luma 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 Affero General Public License for more details. - You should have received a copy of the GNU - Affero General Public License along with Luma. If not, - see <https://www.gnu.org/licenses/>. + You should have received a copy of the GNU + Affero General Public License along with Luma. + If not, see <https://www.gnu.org/licenses/>. */ use crate::luma::device::Device; diff --git a/src/luma/device/trap.rs b/src/luma/device/trap.rs index 11e3343..9e5f003 100644 --- a/src/luma/device/trap.rs +++ b/src/luma/device/trap.rs @@ -3,22 +3,22 @@ This file is part of Luma. - Luma is free software: you can redistribute it - and/or modify it under the terms of the GNU + Luma is free software: you can redistribute it + and/or modify it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 - of the License, or (at your option) any later + the Free Software Foundation, either version 3 + of the License, or (at your option) any later version. - Luma 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 + Luma 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 Affero General Public License for more details. - You should have received a copy of the GNU - Affero General Public License along with Luma. If not, - see <https://www.gnu.org/licenses/>. + You should have received a copy of the GNU + Affero General Public License along with Luma. + If not, see <https://www.gnu.org/licenses/>. */ use crate::luma::MEMORY_SIZE; @@ -27,10 +27,10 @@ use crate::luma::device::{Device, Trap}; impl Device { pub fn trap(&mut self, kind: Trap) { let message = match kind { - Trap::BadAlignment( address, alignment) => format!("bad alignment of address {address:#010X} (should be {alignment}-byte aligned)"), - Trap::InvalidArmOpcode( address, opcode) => format!("invalid opcode {opcode:#034b} at {address:#010X}"), - Trap::InvalidThumbOpcode(address, opcode) => format!("invalid opcode {opcode:#018b} at {address:#010X}"), - Trap::OutOfBounds( address) => format!("out-of-bounds address {address:#010X} (limit is {MEMORY_SIZE:#010X})"), + Trap::BadAlignment( address, alignment) => format!("bad alignment of address {address:#010X} (should be {alignment}-byte aligned)"), + Trap::InvalidArmOpcode( address, opcode) => format!("invalid opcode {opcode:#034b} at {address:#010X}"), + Trap::InvalidThumbOpcode(address, opcode) => format!("invalid opcode {opcode:#018b} at {address:#010X}"), + Trap::OutOfBounds( address) => format!("out-of-bounds address {address:#010X} (limit is {MEMORY_SIZE:#010X})"), }; eprintln!("{message}"); diff --git a/src/luma/device/write.rs b/src/luma/device/write.rs index 1d29cbf..05a8901 100644 --- a/src/luma/device/write.rs +++ b/src/luma/device/write.rs @@ -3,36 +3,34 @@ This file is part of Luma. - Luma is free software: you can redistribute it - and/or modify it under the terms of the GNU + Luma is free software: you can redistribute it + and/or modify it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 - of the License, or (at your option) any later + the Free Software Foundation, either version 3 + of the License, or (at your option) any later version. - Luma 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 + Luma 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 Affero General Public License for more details. - You should have received a copy of the GNU - Affero General Public License along with Luma. If not, - see <https://www.gnu.org/licenses/>. + You should have received a copy of the GNU + Affero General Public License along with Luma. + If not, see <https://www.gnu.org/licenses/>. */ use crate::luma::device::{Device, Trap}; use crate::luma::MEMORY_SIZE; impl Device { - #[allow(dead_code)] pub fn write_byte(&mut self, address: u32, value: u8) { if address >= MEMORY_SIZE as u32 { self.trap(Trap::OutOfBounds(address)) } return unsafe { *(self.memory.offset(address as isize) as *mut u8) = value }; } - #[allow(dead_code)] pub fn write_halfword(&mut self, address: u32, value: u16) { if address >= MEMORY_SIZE as u32 { self.trap(Trap::OutOfBounds(address)) } if address % 0x2 != 0x0 { self.trap(Trap::BadAlignment(address, 0x2)) } @@ -40,7 +38,6 @@ impl Device { return unsafe { *(self.memory.offset(address as isize) as *mut u16) = value }; } - #[allow(dead_code)] pub fn write_word(&mut self, address: u32, value: u32) { if address >= MEMORY_SIZE as u32 { self.trap(Trap::OutOfBounds(address)) } if address % 0x4 != 0x0 { self.trap(Trap::BadAlignment(address, 0x4)) } diff --git a/src/main.rs b/src/main.rs index 1d45ca3..564e193 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,22 +3,22 @@ This file is part of Luma. - Luma is free software: you can redistribute it - and/or modify it under the terms of the GNU + Luma is free software: you can redistribute it + and/or modify it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 - of the License, or (at your option) any later + the Free Software Foundation, either version 3 + of the License, or (at your option) any later version. - Luma 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 + Luma 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 Affero General Public License for more details. - You should have received a copy of the GNU - Affero General Public License along with Luma. If not, - see <https://www.gnu.org/licenses/>. + You should have received a copy of the GNU + Affero General Public License along with Luma. + If not, see <https://www.gnu.org/licenses/>. */ mod luma; |