├── LICENSE ├── Proteus ├── Backup Of avr-x86.pdsbak ├── Last Loaded avr-x86.pdsbak ├── OS.FLP └── avr-x86.pdsprj ├── README.md └── avr-x86 ├── avr-x86.ino ├── config.h ├── cpu.cpp ├── cpu.h ├── outputserial.cpp ├── ram.cpp └── ram.h /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /Proteus/Backup Of avr-x86.pdsbak: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspiduino/avr-x86/4cc09e1c0dd89142bc7e9415d23532ead2b50372/Proteus/Backup Of avr-x86.pdsbak -------------------------------------------------------------------------------- /Proteus/Last Loaded avr-x86.pdsbak: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspiduino/avr-x86/4cc09e1c0dd89142bc7e9415d23532ead2b50372/Proteus/Last Loaded avr-x86.pdsbak -------------------------------------------------------------------------------- /Proteus/OS.FLP: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspiduino/avr-x86/4cc09e1c0dd89142bc7e9415d23532ead2b50372/Proteus/OS.FLP -------------------------------------------------------------------------------- /Proteus/avr-x86.pdsprj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspiduino/avr-x86/4cc09e1c0dd89142bc7e9415d23532ead2b50372/Proteus/avr-x86.pdsprj -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # avr-x86 2 | ## What is this? 3 | *AVR-x86* is a 8086+ emulator running on AVR Arduino. This project is originally forked from https://github.com/corax89/Arduino_8086_emulator 4 | ![Proteus simulation](https://user-images.githubusercontent.com/68118236/112129528-1415f400-8bfa-11eb-93f2-7bdf84fe7214.png) 5 |
As you can see in the image, AVR-x86 is running [*Brainfuck*](https://en.wikipedia.org/wiki/Brainfuck) written in 8086 assembly, 6 | 7 | ## How? 8 | AVR-x86 is based on [*Fake86*](http://fake86.rubbermallet.org/)'s core, ported to AVR by *corax89*. In the original version, binary is stored in a RAM array, then boot up and execute it. But AVR-x86 load the binary stored in a SD card to a *virtual RAM file* on the SD card. So you can have more RAM for the emulator than the AVR hardware's. That also means AVR-x86 can execute larger binary file! 9 |
It takes about one minute to load a 200K file. 10 | 11 | ## Why? 12 | For fun. It just a toy. 13 | 14 | From [dmitry.gr](http://dmitry.gr/?r=05.Projects&proj=07.%20Linux%20on%208bit): 15 | > It is common to see newbies asking in microcontroller forums if they can run Linux on their puny little 8-bit micro. The results are usually laughter. 16 | 17 | ## Todo 18 | - Write an bootloader for floppy disk files on SD card, not just executing one file at a time. 19 | - Reduce the sketch file 20 | - Boot more things 21 | - ... 22 | 23 | If you have any ideas, you can open an issue and tell me! 24 | 25 | ## Some other projects releated to this 26 | - [Linux on 8-bit AVR by *Dmitry.GR*](http://dmitry.gr/?r=05.Projects&proj=07.%20Linux%20on%208bit) 27 | - [CP/M on an AVR by *Spritesmods.com*](https://spritesmods.com/?art=avrcpm) 28 | - [Launch .COM file on Arduino by *corax89* (the repo where this repo forked)](https://github.com/corax89/Arduino_8086_emulator) 29 | - [8086 emulator on Arduino DUE by *miker00lz*](https://forum.arduino.cc/index.php?topic=605391.0) 30 | - [8086 emulator on ESP8266 (include video)](https://www.hackster.io/janost/ibm-pc-xt-emulator-on-an-esp8266-42abcc) 31 | - [emu86 by *murray1978*](https://github.com/murray1978/emu86) 32 | 33 | # Configs 34 | There are configs macro inside *config.h*. You can follow the instructions in that file. 35 |
Notes: You can enable more feature if you has more flash and RAM, but for Arduino UNO, you can only enable `ONE_USE` for now (autoload the file when boot, no bootprompt!). 36 | -------------------------------------------------------------------------------- /avr-x86/avr-x86.ino: -------------------------------------------------------------------------------- 1 | /* 2 | avr-x86 - x86 emulator running on AVR Arduino! 3 | Copyright (C) 2021 @raspiduino 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | /* ------------------------ Include libraries ------------------------ */ 20 | /* Fake86 */ 21 | #include "cpu.h" 22 | 23 | /* ------------------------ setup() function ------------------------- */ 24 | void setup() { 25 | Serial.begin(9600); // Open serial port with baud 9600 bps 26 | 27 | /* Display welcome messages */ 28 | Serial.println(F("avr-x86 - Copyright (C) 2021 @raspiduino")); 29 | Serial.println(F("Github repo: https://github.com/raspiduino/avr-x86")); 30 | Serial.println(F("Under GPL-v3")); 31 | 32 | /* Init SD card */ 33 | sdinit(); 34 | 35 | /* Copy data from virtual disk to virtual ram */ 36 | ramload(); 37 | 38 | /* Init the fake86 */ 39 | Serial.print(F("Init Fake86")); 40 | init86(); 41 | Serial.println(F(". Done! Starting emulator...")); 42 | } 43 | 44 | /* ------------------------ loop() function -------------------------- */ 45 | void loop() { 46 | exec86(100); // Execute fake86 47 | } 48 | -------------------------------------------------------------------------------- /avr-x86/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | avr-x86 - x86 emulator running on AVR Arduino! 3 | Copyright (C) 2021 @raspiduino 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #define RAM_LENGTH 512 // Set the amount of RAM - in byte. You must set it to fit your vram file 20 | #define RAM_BUFFER 64 // Set the RAM buffer size when load disk image to virtual RAM. 21 | #define RAM_FILE "RAM.BIN" // Set the virtual RAM File location 22 | 23 | // Boot file settings 24 | //#define BOOT_PROMPT // Comment this to disable boot prompt 25 | 26 | #ifndef BOOT_PROMPT 27 | #define BOOT_FILE "BF.COM" // If you disable boot prompt, you must set a boot file 28 | #endif 29 | 30 | //#define ONE_USE // Don't use this. This is basicly use the input file as ram file (direct RAM) 31 | 32 | #define CHIP_SELECT 10 // Chip select pin for SD card 33 | -------------------------------------------------------------------------------- /avr-x86/cpu.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Fake86: A portable, open-source 8086 PC emulator. 3 | Copyright (C)2010-2013 Mike Chambers 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | /* 21 | The author of the port for Arduino Corax (Rabetsky Igor) 22 | Copyright (C) 2017 corax89 23 | 24 | Some of the code are edited by @raspiduino 25 | Copyright (C) 2021 @raspiduino 26 | */ 27 | 28 | #include 29 | #include 30 | #include "cpu.h" 31 | 32 | //#define DEBUG 33 | #define CPU_8086 34 | #define STACK_LENGTH 32 35 | 36 | #define regax 0 37 | #define regcx 1 38 | #define regdx 2 39 | #define regbx 3 40 | #define regsp 4 41 | #define regbp 5 42 | #define regsi 6 43 | #define regdi 7 44 | #define reges 0 45 | #define regcs 1 46 | #define regss 2 47 | #define regds 3 48 | 49 | #define regal 0 50 | #define regah 1 51 | #define regcl 2 52 | #define regch 3 53 | #define regdl 4 54 | #define regdh 5 55 | #define regbl 6 56 | #define regbh 7 57 | 58 | #define StepIP(x) ip += x 59 | #define getmem8(x, y) read86(segbase(x) + y) 60 | #define getmem16(x, y) readw86(segbase(x) + y) 61 | #define putmem8(x, y, z) write86(segbase(x) + y, z) 62 | #define putmem16(x, y, z) writew86(segbase(x) + y, z) 63 | #define signext(value) (int16_t)(int8_t)(value) 64 | #define signext32(value) (int32_t)(int16_t)(value) 65 | #define getreg16(regid) regs.wordregs[regid] 66 | #define getreg8(regid) regs.byteregs[byteregtable[regid]] 67 | #define putreg16(regid, writeval) regs.wordregs[regid] = writeval 68 | #define putreg8(regid, writeval) regs.byteregs[byteregtable[regid]] = writeval 69 | #define getsegreg(regid) segregs[regid] 70 | #define putsegreg(regid, writeval) segregs[regid] = writeval 71 | #define segbase(x) ((uint32_t) x << 4) 72 | 73 | #define makeflagsword() \ 74 | ( \ 75 | 2 | (word) cf | ((word) pf << 2) | ((word) af << 4) | ((word) zf << 6) | ((word) sf << 7) | \ 76 | ((word) tf << 8) | ((word) ifl << 9) | ((word) df << 10) | ((word) of << 11) \ 77 | ) 78 | 79 | union _bytewordregs_ { 80 | word wordregs[8]; 81 | byte byteregs[8]; 82 | }; 83 | 84 | byte byteregtable[8] = { regal, regcl, regdl, regbl, regah, regch, regdh, regbh }; 85 | 86 | static const byte parity[0x100] = { 87 | 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 88 | 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 89 | 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 90 | 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 91 | 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 92 | 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 93 | 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 94 | 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1 95 | }; 96 | 97 | byte STACK[STACK_LENGTH]; 98 | 99 | byte opcode, segoverride, reptype, bootdrive = 0, hdcount = 0, hltstate = 0; 100 | word segregs[4], savecs, saveip, ip, useseg, oldsp; 101 | byte tempcf, oldcf, cf, pf, af, zf, sf, tf, ifl, df, of, mode, reg, rm; 102 | word oper1, oper2, res16, disp16, temp16, dummy, stacksize, frametemp; 103 | byte oper1b, oper2b, res8, disp8, temp8, nestlev, addrbyte; 104 | uint32_t temp1, temp2, temp3, temp4, temp5, temp32, tempaddr32, ea; 105 | int32_t result; 106 | uint64_t totalexec; 107 | 108 | union _bytewordregs_ regs; 109 | 110 | byte running = 0, didbootstrap = 0; 111 | 112 | byte vidmode; 113 | 114 | // Interupts 115 | 116 | void videoBIOSinterupt(){ 117 | switch(regs.byteregs[regah]){ 118 | case 0x9: 119 | /*09H писать символ/атрибут в текущей позиции курсора 120 | вход: BH = номер видео страницы 121 | AL = записываемый символ 122 | CX = счетчик (сколько экземпляров символа записать) 123 | BL = видео атрибут (текст) или цвет (графика) 124 | (графические режимы: +80H означает XOR с символом на экране)*/ 125 | case 0xA: 126 | /*0aH писать символ в текущей позиции курсора 127 | вход: BH = номер видео страницы 128 | AL = записываемый символ 129 | CX = счетчик (сколько экземпляров символа записать)*/ 130 | for(uint16_t j=0;jread86(adrs) || length>255) 214 | break; 215 | } 216 | write86(adrs+1,length);//записываем действительную длину данных 217 | write86(adrs+length+3,'$'); 218 | break; 219 | #ifdef DEBUG 220 | default: 221 | Serial.print("undefined DOS interupt "); 222 | Serial.print(regs.byteregs[regah],HEX); 223 | #endif 224 | } 225 | } 226 | 227 | void decodeflagsword( word x) { 228 | temp16 = x; 229 | cf = temp16 & 1; 230 | pf = (temp16 >> 2) & 1; 231 | af = (temp16 >> 4) & 1; 232 | zf = (temp16 >> 6) & 1; 233 | sf = (temp16 >> 7) & 1; 234 | tf = (temp16 >> 8) & 1; 235 | ifl = (temp16 >> 9) & 1; 236 | df = (temp16 >> 10) & 1; 237 | of = (temp16 >> 11) & 1; 238 | } 239 | 240 | 241 | void modregrm() { 242 | addrbyte = getmem8(segregs[regcs], ip); 243 | StepIP(1); 244 | mode = addrbyte >> 6; 245 | reg = (addrbyte >> 3) & 7; 246 | rm = addrbyte & 7; 247 | switch(mode){ 248 | case 0: 249 | if(rm == 6) { 250 | disp16 = getmem16(segregs[regcs], ip); 251 | StepIP(2); 252 | } 253 | if(((rm == 2) || (rm == 3)) && !segoverride) { 254 | useseg = segregs[regss]; 255 | } 256 | break; 257 | case 1: 258 | disp16 = signext(getmem8(segregs[regcs], ip)); 259 | StepIP(1); 260 | if(((rm == 2) || (rm == 3) || (rm == 6)) && !segoverride) { 261 | useseg = segregs[regss]; 262 | } 263 | break; 264 | case 2: 265 | disp16 = getmem16(segregs[regcs], ip); 266 | StepIP(2); 267 | if(((rm == 2) || (rm == 3) || (rm == 6)) && !segoverride) { 268 | useseg = segregs[regss]; 269 | } 270 | break; 271 | default: 272 | disp8 = 0; 273 | disp16 = 0; 274 | } 275 | } 276 | 277 | void write86 (uint32_t addr32, byte value) { 278 | if(addr32 > 0xFFFF - STACK_LENGTH){ 279 | STACK[tempaddr32] = value; 280 | } 281 | else if(addr32 >= 0x7100 && addr32 < RAM_LENGTH + 0x7100){ 282 | tempaddr32 = (addr32 & 0xFFFFF) - 0x7100; 283 | //RAM[tempaddr32] = value; 284 | ramwrite(tempaddr32, value); // Write to virtual RAM 285 | } 286 | } 287 | 288 | void writew86 (uint32_t addr32, word value) { 289 | write86 (addr32, (byte) value); 290 | write86 (addr32 + 1, (byte) (value >> 8) ); 291 | } 292 | 293 | byte read86 (uint32_t addr32) { 294 | if(addr32 > 0xFFFF - STACK_LENGTH){ 295 | return STACK[tempaddr32]; 296 | } 297 | else if(addr32 >= 0x7100 && addr32 < RAM_LENGTH + 0x7100){ 298 | addr32 &= 0xFFFFF; 299 | addr32 -= 0x7100; 300 | return (ramread(addr32)); 301 | } 302 | return 0x90; 303 | } 304 | 305 | word readw86 (uint32_t addr32) { 306 | return ( (word) read86 (addr32) | (word) (read86 (addr32 + 1) << 8) ); 307 | } 308 | 309 | void flag_szp8 (byte value) { 310 | if (!value) { 311 | zf = 1; 312 | } 313 | else { 314 | zf = 0; /* set or clear zero flag */ 315 | } 316 | 317 | if (value & 0x80) { 318 | sf = 1; 319 | } 320 | else { 321 | sf = 0; /* set or clear sign flag */ 322 | } 323 | 324 | pf = parity[value]; /* retrieve parity state from lookup table */ 325 | } 326 | 327 | void flag_szp16 (word value) { 328 | if (!value) { 329 | zf = 1; 330 | } 331 | else { 332 | zf = 0; /* set or clear zero flag */ 333 | } 334 | 335 | if (value & 0x8000) { 336 | sf = 1; 337 | } 338 | else { 339 | sf = 0; /* set or clear sign flag */ 340 | } 341 | 342 | pf = parity[value & 255]; /* retrieve parity state from lookup table */ 343 | } 344 | 345 | void flag_log8 (byte value) { 346 | flag_szp8 (value); 347 | cf = 0; 348 | of = 0; /* bitwise logic ops always clear carry and overflow */ 349 | } 350 | 351 | void flag_log16 (word value) { 352 | flag_szp16 (value); 353 | cf = 0; 354 | of = 0; /* bitwise logic ops always clear carry and overflow */ 355 | } 356 | 357 | void flag_adc8 (byte v1, byte v2, byte v3) { 358 | 359 | /* v1 = destination operand, v2 = source operand, v3 = carry flag */ 360 | word dst; 361 | 362 | dst = (word) v1 + (word) v2 + (word) v3; 363 | flag_szp8 ( (byte) dst); 364 | if ( ( (dst ^ v1) & (dst ^ v2) & 0x80) == 0x80) { 365 | of = 1; 366 | } 367 | else { 368 | of = 0; /* set or clear overflow flag */ 369 | } 370 | 371 | if (dst & 0xFF00) { 372 | cf = 1; 373 | } 374 | else { 375 | cf = 0; /* set or clear carry flag */ 376 | } 377 | 378 | if ( ( (v1 ^ v2 ^ dst) & 0x10) == 0x10) { 379 | af = 1; 380 | } 381 | else { 382 | af = 0; /* set or clear auxilliary flag */ 383 | } 384 | } 385 | 386 | void flag_adc16 (word v1, word v2, word v3) { 387 | 388 | uint32_t dst; 389 | 390 | dst = (uint32_t) v1 + (uint32_t) v2 + (uint32_t) v3; 391 | flag_szp16 ( (word) dst); 392 | if ( ( ( (dst ^ v1) & (dst ^ v2) ) & 0x8000) == 0x8000) { 393 | of = 1; 394 | } 395 | else { 396 | of = 0; 397 | } 398 | 399 | if (dst & 0xFFFF0000) { 400 | cf = 1; 401 | } 402 | else { 403 | cf = 0; 404 | } 405 | 406 | if ( ( (v1 ^ v2 ^ dst) & 0x10) == 0x10) { 407 | af = 1; 408 | } 409 | else { 410 | af = 0; 411 | } 412 | } 413 | 414 | void flag_add8 (byte v1, byte v2) { 415 | /* v1 = destination operand, v2 = source operand */ 416 | word dst; 417 | 418 | dst = (word) v1 + (word) v2; 419 | flag_szp8 ( (byte) dst); 420 | if (dst & 0xFF00) { 421 | cf = 1; 422 | } 423 | else { 424 | cf = 0; 425 | } 426 | 427 | if ( ( (dst ^ v1) & (dst ^ v2) & 0x80) == 0x80) { 428 | of = 1; 429 | } 430 | else { 431 | of = 0; 432 | } 433 | 434 | if ( ( (v1 ^ v2 ^ dst) & 0x10) == 0x10) { 435 | af = 1; 436 | } 437 | else { 438 | af = 0; 439 | } 440 | } 441 | 442 | void flag_add16 (word v1, word v2) { 443 | /* v1 = destination operand, v2 = source operand */ 444 | uint32_t dst; 445 | 446 | dst = (uint32_t) v1 + (uint32_t) v2; 447 | flag_szp16 ( (word) dst); 448 | if (dst & 0xFFFF0000) { 449 | cf = 1; 450 | } 451 | else { 452 | cf = 0; 453 | } 454 | 455 | if ( ( (dst ^ v1) & (dst ^ v2) & 0x8000) == 0x8000) { 456 | of = 1; 457 | } 458 | else { 459 | of = 0; 460 | } 461 | 462 | if ( ( (v1 ^ v2 ^ dst) & 0x10) == 0x10) { 463 | af = 1; 464 | } 465 | else { 466 | af = 0; 467 | } 468 | } 469 | 470 | void flag_sbb8 (byte v1, byte v2, byte v3) { 471 | 472 | /* v1 = destination operand, v2 = source operand, v3 = carry flag */ 473 | word dst; 474 | 475 | v2 += v3; 476 | dst = (word) v1 - (word) v2; 477 | flag_szp8 ( (byte) dst); 478 | if (dst & 0xFF00) { 479 | cf = 1; 480 | } 481 | else { 482 | cf = 0; 483 | } 484 | 485 | if ( (dst ^ v1) & (v1 ^ v2) & 0x80) { 486 | of = 1; 487 | } 488 | else { 489 | of = 0; 490 | } 491 | 492 | if ( (v1 ^ v2 ^ dst) & 0x10) { 493 | af = 1; 494 | } 495 | else { 496 | af = 0; 497 | } 498 | } 499 | 500 | void flag_sbb16 (word v1, word v2, word v3) { 501 | 502 | /* v1 = destination operand, v2 = source operand, v3 = carry flag */ 503 | uint32_t dst; 504 | 505 | v2 += v3; 506 | dst = (uint32_t) v1 - (uint32_t) v2; 507 | flag_szp16 ( (word) dst); 508 | if (dst & 0xFFFF0000) { 509 | cf = 1; 510 | } 511 | else { 512 | cf = 0; 513 | } 514 | 515 | if ( (dst ^ v1) & (v1 ^ v2) & 0x8000) { 516 | of = 1; 517 | } 518 | else { 519 | of = 0; 520 | } 521 | 522 | if ( (v1 ^ v2 ^ dst) & 0x10) { 523 | af = 1; 524 | } 525 | else { 526 | af = 0; 527 | } 528 | } 529 | 530 | void flag_sub8 (byte v1, byte v2) { 531 | 532 | /* v1 = destination operand, v2 = source operand */ 533 | word dst; 534 | 535 | dst = (word) v1 - (word) v2; 536 | flag_szp8 ( (byte) dst); 537 | if (dst & 0xFF00) { 538 | cf = 1; 539 | } 540 | else { 541 | cf = 0; 542 | } 543 | 544 | if ( (dst ^ v1) & (v1 ^ v2) & 0x80) { 545 | of = 1; 546 | } 547 | else { 548 | of = 0; 549 | } 550 | 551 | if ( (v1 ^ v2 ^ dst) & 0x10) { 552 | af = 1; 553 | } 554 | else { 555 | af = 0; 556 | } 557 | } 558 | 559 | void flag_sub16 (word v1, word v2) { 560 | 561 | /* v1 = destination operand, v2 = source operand */ 562 | uint32_t dst; 563 | 564 | dst = (uint32_t) v1 - (uint32_t) v2; 565 | flag_szp16 ( (word) dst); 566 | if (dst & 0xFFFF0000) { 567 | cf = 1; 568 | } 569 | else { 570 | cf = 0; 571 | } 572 | 573 | if ( (dst ^ v1) & (v1 ^ v2) & 0x8000) { 574 | of = 1; 575 | } 576 | else { 577 | of = 0; 578 | } 579 | 580 | if ( (v1 ^ v2 ^ dst) & 0x10) { 581 | af = 1; 582 | } 583 | else { 584 | af = 0; 585 | } 586 | } 587 | 588 | void op_adc8() { 589 | res8 = oper1b + oper2b + cf; 590 | flag_adc8 (oper1b, oper2b, cf); 591 | } 592 | 593 | void op_adc16() { 594 | res16 = oper1 + oper2 + cf; 595 | flag_adc16 (oper1, oper2, cf); 596 | } 597 | 598 | void op_add8() { 599 | res8 = oper1b + oper2b; 600 | flag_add8 (oper1b, oper2b); 601 | } 602 | 603 | void op_add16() { 604 | res16 = oper1 + oper2; 605 | flag_add16 (oper1, oper2); 606 | } 607 | 608 | void op_and8() { 609 | res8 = oper1b & oper2b; 610 | flag_log8 (res8); 611 | } 612 | 613 | void op_and16() { 614 | res16 = oper1 & oper2; 615 | flag_log16 (res16); 616 | } 617 | 618 | void op_or8() { 619 | res8 = oper1b | oper2b; 620 | flag_log8 (res8); 621 | } 622 | 623 | void op_or16() { 624 | res16 = oper1 | oper2; 625 | flag_log16 (res16); 626 | } 627 | 628 | void op_xor8() { 629 | res8 = oper1b ^ oper2b; 630 | flag_log8 (res8); 631 | } 632 | 633 | void op_xor16() { 634 | res16 = oper1 ^ oper2; 635 | flag_log16 (res16); 636 | } 637 | 638 | void op_sub8() { 639 | res8 = oper1b - oper2b; 640 | flag_sub8 (oper1b, oper2b); 641 | } 642 | 643 | void op_sub16() { 644 | res16 = oper1 - oper2; 645 | flag_sub16 (oper1, oper2); 646 | } 647 | 648 | void op_sbb8() { 649 | res8 = oper1b - (oper2b + cf); 650 | flag_sbb8 (oper1b, oper2b, cf); 651 | } 652 | 653 | void op_sbb16() { 654 | res16 = oper1 - (oper2 + cf); 655 | flag_sbb16 (oper1, oper2, cf); 656 | } 657 | 658 | void getea (byte rmval) { 659 | uint32_t tempea; 660 | 661 | tempea = 0; 662 | switch (mode) { 663 | case 0: 664 | switch (rmval) { 665 | case 0: 666 | tempea = regs.wordregs[regbx] + regs.wordregs[regsi]; 667 | break; 668 | case 1: 669 | tempea = regs.wordregs[regbx] + regs.wordregs[regdi]; 670 | break; 671 | case 2: 672 | tempea = regs.wordregs[regbp] + regs.wordregs[regsi]; 673 | break; 674 | case 3: 675 | tempea = regs.wordregs[regbp] + regs.wordregs[regdi]; 676 | break; 677 | case 4: 678 | tempea = regs.wordregs[regsi]; 679 | break; 680 | case 5: 681 | tempea = regs.wordregs[regdi]; 682 | break; 683 | case 6: 684 | tempea = disp16; 685 | break; 686 | case 7: 687 | tempea = regs.wordregs[regbx]; 688 | break; 689 | } 690 | break; 691 | 692 | case 1: 693 | case 2: 694 | switch (rmval) { 695 | case 0: 696 | tempea = regs.wordregs[regbx] + regs.wordregs[regsi] + disp16; 697 | break; 698 | case 1: 699 | tempea = regs.wordregs[regbx] + regs.wordregs[regdi] + disp16; 700 | break; 701 | case 2: 702 | tempea = regs.wordregs[regbp] + regs.wordregs[regsi] + disp16; 703 | break; 704 | case 3: 705 | tempea = regs.wordregs[regbp] + regs.wordregs[regdi] + disp16; 706 | break; 707 | case 4: 708 | tempea = regs.wordregs[regsi] + disp16; 709 | break; 710 | case 5: 711 | tempea = regs.wordregs[regdi] + disp16; 712 | break; 713 | case 6: 714 | tempea = regs.wordregs[regbp] + disp16; 715 | break; 716 | case 7: 717 | tempea = regs.wordregs[regbx] + disp16; 718 | break; 719 | } 720 | break; 721 | } 722 | 723 | ea = (tempea & 0xFFFF) + (useseg << 4); 724 | } 725 | 726 | void push (word pushval) { 727 | regs.wordregs[regsp] = regs.wordregs[regsp] - 2; 728 | putmem16 (segregs[regss], regs.wordregs[regsp], pushval); 729 | } 730 | 731 | word pop() { 732 | 733 | word tempval; 734 | 735 | tempval = getmem16 (segregs[regss], regs.wordregs[regsp]); 736 | regs.wordregs[regsp] = regs.wordregs[regsp] + 2; 737 | return tempval; 738 | } 739 | 740 | void reset86() { 741 | segregs[regcs] = 0xFFFF; 742 | ip = 0x0100; 743 | hltstate = 0; 744 | } 745 | 746 | word readrm16 (byte rmval) { 747 | if (mode < 3) { 748 | getea (rmval); 749 | return read86 (ea) | ( (word) read86 (ea + 1) << 8); 750 | } 751 | else { 752 | return getreg16 (rmval); 753 | } 754 | } 755 | 756 | byte readrm8 (byte rmval) { 757 | if (mode < 3) { 758 | getea (rmval); 759 | return read86 (ea); 760 | } 761 | else { 762 | return getreg8 (rmval); 763 | } 764 | } 765 | 766 | void writerm16 (byte rmval, word value) { 767 | if (mode < 3) { 768 | getea (rmval); 769 | write86 (ea, value & 0xFF); 770 | write86 (ea + 1, value >> 8); 771 | } 772 | else { 773 | putreg16 (rmval, value); 774 | } 775 | } 776 | 777 | void writerm8 (byte rmval, byte value) { 778 | if (mode < 3) { 779 | getea (rmval); 780 | write86 (ea, value); 781 | } 782 | else { 783 | putreg8 (rmval, value); 784 | } 785 | } 786 | 787 | 788 | void intcall86 (byte intnum) { 789 | static word lastint10ax; 790 | word oldregax; 791 | 792 | if (intnum == 0x19) didbootstrap = 1; 793 | 794 | switch (intnum) { 795 | case 0x10: 796 | videoBIOSinterupt(); 797 | break; 798 | case 0x16: 799 | keyBIOSinterupt(); 800 | break; 801 | case 0x21: 802 | DOSinterupt(); 803 | break; 804 | default: 805 | push (makeflagsword() ); 806 | push (segregs[regcs]); 807 | push (ip); 808 | segregs[regcs] = getmem16 (0, (word) intnum * 4 + 2); 809 | ip = getmem16 (0, (word) intnum * 4); 810 | ifl = 0; 811 | tf = 0; 812 | } 813 | } 814 | 815 | 816 | byte op_grp2_8 (byte cnt) { 817 | 818 | word s; 819 | word shift; 820 | word oldcf; 821 | word msb; 822 | 823 | s = oper1b; 824 | oldcf = cf; 825 | switch (reg) { 826 | case 0: /* ROL r/m8 */ 827 | for (shift = 1; shift <= cnt; shift++) { 828 | if (s & 0x80) { 829 | cf = 1; 830 | } 831 | else { 832 | cf = 0; 833 | } 834 | 835 | s = s << 1; 836 | s = s | cf; 837 | } 838 | 839 | if (cnt == 1) { 840 | //of = cf ^ ( (s >> 7) & 1); 841 | if ((s & 0x80) && cf) of = 1; else of = 0; 842 | } else of = 0; 843 | break; 844 | 845 | case 1: /* ROR r/m8 */ 846 | for (shift = 1; shift <= cnt; shift++) { 847 | cf = s & 1; 848 | s = (s >> 1) | (cf << 7); 849 | } 850 | 851 | if (cnt == 1) { 852 | of = (s >> 7) ^ ( (s >> 6) & 1); 853 | } 854 | break; 855 | 856 | case 2: /* RCL r/m8 */ 857 | for (shift = 1; shift <= cnt; shift++) { 858 | oldcf = cf; 859 | if (s & 0x80) { 860 | cf = 1; 861 | } 862 | else { 863 | cf = 0; 864 | } 865 | 866 | s = s << 1; 867 | s = s | oldcf; 868 | } 869 | 870 | if (cnt == 1) { 871 | of = cf ^ ( (s >> 7) & 1); 872 | } 873 | break; 874 | 875 | case 3: /* RCR r/m8 */ 876 | for (shift = 1; shift <= cnt; shift++) { 877 | oldcf = cf; 878 | cf = s & 1; 879 | s = (s >> 1) | (oldcf << 7); 880 | } 881 | 882 | if (cnt == 1) { 883 | of = (s >> 7) ^ ( (s >> 6) & 1); 884 | } 885 | break; 886 | 887 | case 4: 888 | case 6: /* SHL r/m8 */ 889 | for (shift = 1; shift <= cnt; shift++) { 890 | if (s & 0x80) { 891 | cf = 1; 892 | } 893 | else { 894 | cf = 0; 895 | } 896 | 897 | s = (s << 1) & 0xFF; 898 | } 899 | 900 | if ( (cnt == 1) && (cf == (s >> 7) ) ) { 901 | of = 0; 902 | } 903 | else { 904 | of = 1; 905 | } 906 | 907 | flag_szp8 ( (byte) s); 908 | break; 909 | 910 | case 5: /* SHR r/m8 */ 911 | if ( (cnt == 1) && (s & 0x80) ) { 912 | of = 1; 913 | } 914 | else { 915 | of = 0; 916 | } 917 | 918 | for (shift = 1; shift <= cnt; shift++) { 919 | cf = s & 1; 920 | s = s >> 1; 921 | } 922 | 923 | flag_szp8 ( (byte) s); 924 | break; 925 | 926 | case 7: /* SAR r/m8 */ 927 | for (shift = 1; shift <= cnt; shift++) { 928 | msb = s & 0x80; 929 | cf = s & 1; 930 | s = (s >> 1) | msb; 931 | } 932 | 933 | of = 0; 934 | flag_szp8 ( (byte) s); 935 | break; 936 | } 937 | 938 | return s & 0xFF; 939 | } 940 | 941 | word op_grp2_16 (byte cnt) { 942 | 943 | uint32_t s; 944 | uint32_t shift; 945 | uint32_t oldcf; 946 | uint32_t msb; 947 | 948 | s = oper1; 949 | oldcf = cf; 950 | switch (reg) { 951 | case 0: /* ROL r/m8 */ 952 | for (shift = 1; shift <= cnt; shift++) { 953 | if (s & 0x8000) { 954 | cf = 1; 955 | } 956 | else { 957 | cf = 0; 958 | } 959 | 960 | s = s << 1; 961 | s = s | cf; 962 | } 963 | 964 | if (cnt == 1) { 965 | of = cf ^ ( (s >> 15) & 1); 966 | } 967 | break; 968 | 969 | case 1: /* ROR r/m8 */ 970 | for (shift = 1; shift <= cnt; shift++) { 971 | cf = s & 1; 972 | s = (s >> 1) | (cf << 15); 973 | } 974 | 975 | if (cnt == 1) { 976 | of = (s >> 15) ^ ( (s >> 14) & 1); 977 | } 978 | break; 979 | 980 | case 2: /* RCL r/m8 */ 981 | for (shift = 1; shift <= cnt; shift++) { 982 | oldcf = cf; 983 | if (s & 0x8000) { 984 | cf = 1; 985 | } 986 | else { 987 | cf = 0; 988 | } 989 | 990 | s = s << 1; 991 | s = s | oldcf; 992 | } 993 | 994 | if (cnt == 1) { 995 | of = cf ^ ( (s >> 15) & 1); 996 | } 997 | break; 998 | 999 | case 3: /* RCR r/m8 */ 1000 | for (shift = 1; shift <= cnt; shift++) { 1001 | oldcf = cf; 1002 | cf = s & 1; 1003 | s = (s >> 1) | (oldcf << 15); 1004 | } 1005 | 1006 | if (cnt == 1) { 1007 | of = (s >> 15) ^ ( (s >> 14) & 1); 1008 | } 1009 | break; 1010 | 1011 | case 4: 1012 | case 6: /* SHL r/m8 */ 1013 | for (shift = 1; shift <= cnt; shift++) { 1014 | if (s & 0x8000) { 1015 | cf = 1; 1016 | } 1017 | else { 1018 | cf = 0; 1019 | } 1020 | 1021 | s = (s << 1) & 0xFFFF; 1022 | } 1023 | 1024 | if ( (cnt == 1) && (cf == (s >> 15) ) ) { 1025 | of = 0; 1026 | } 1027 | else { 1028 | of = 1; 1029 | } 1030 | 1031 | flag_szp16 ( (word) s); 1032 | break; 1033 | 1034 | case 5: /* SHR r/m8 */ 1035 | if ( (cnt == 1) && (s & 0x8000) ) { 1036 | of = 1; 1037 | } 1038 | else { 1039 | of = 0; 1040 | } 1041 | 1042 | for (shift = 1; shift <= cnt; shift++) { 1043 | cf = s & 1; 1044 | s = s >> 1; 1045 | } 1046 | 1047 | flag_szp16 ( (word) s); 1048 | break; 1049 | 1050 | case 7: /* SAR r/m8 */ 1051 | for (shift = 1; shift <= cnt; shift++) { 1052 | msb = s & 0x8000; 1053 | cf = s & 1; 1054 | s = (s >> 1) | msb; 1055 | } 1056 | 1057 | of = 0; 1058 | flag_szp16 ( (word) s); 1059 | break; 1060 | } 1061 | 1062 | return (word) s & 0xFFFF; 1063 | } 1064 | 1065 | void op_div8 (word valdiv, byte divisor) { 1066 | if (divisor == 0) { 1067 | intcall86 (0); 1068 | return; 1069 | } 1070 | 1071 | if ( (valdiv / (word) divisor) > 0xFF) { 1072 | intcall86 (0); 1073 | return; 1074 | } 1075 | 1076 | regs.byteregs[regah] = valdiv % (word) divisor; 1077 | regs.byteregs[regal] = valdiv / (word) divisor; 1078 | } 1079 | 1080 | void op_idiv8 (word valdiv, byte divisor) { 1081 | 1082 | word s1; 1083 | word s2; 1084 | word d1; 1085 | word d2; 1086 | int sign; 1087 | 1088 | if (divisor == 0) { 1089 | intcall86 (0); 1090 | return; 1091 | } 1092 | 1093 | s1 = valdiv; 1094 | s2 = divisor; 1095 | sign = ( ( (s1 ^ s2) & 0x8000) != 0); 1096 | s1 = (s1 < 0x8000) ? s1 : ( (~s1 + 1) & 0xffff); 1097 | s2 = (s2 < 0x8000) ? s2 : ( (~s2 + 1) & 0xffff); 1098 | d1 = s1 / s2; 1099 | d2 = s1 % s2; 1100 | if (d1 & 0xFF00) { 1101 | intcall86 (0); 1102 | return; 1103 | } 1104 | 1105 | if (sign) { 1106 | d1 = (~d1 + 1) & 0xff; 1107 | d2 = (~d2 + 1) & 0xff; 1108 | } 1109 | 1110 | regs.byteregs[regah] = (byte) d2; 1111 | regs.byteregs[regal] = (byte) d1; 1112 | } 1113 | 1114 | void op_grp3_8() { 1115 | oper1 = signext (oper1b); 1116 | oper2 = signext (oper2b); 1117 | switch (reg) { 1118 | case 0: 1119 | case 1: /* TEST */ 1120 | flag_log8 (oper1b & getmem8 (segregs[regcs], ip) ); 1121 | StepIP (1); 1122 | break; 1123 | 1124 | case 2: /* NOT */ 1125 | res8 = ~oper1b; 1126 | break; 1127 | 1128 | case 3: /* NEG */ 1129 | res8 = (~oper1b) + 1; 1130 | flag_sub8 (0, oper1b); 1131 | if (res8 == 0) { 1132 | cf = 0; 1133 | } 1134 | else { 1135 | cf = 1; 1136 | } 1137 | break; 1138 | 1139 | case 4: /* MUL */ 1140 | temp1 = (uint32_t) oper1b * (uint32_t) regs.byteregs[regal]; 1141 | regs.wordregs[regax] = temp1 & 0xFFFF; 1142 | flag_szp8 ( (byte) temp1); 1143 | if (regs.byteregs[regah]) { 1144 | cf = 1; 1145 | of = 1; 1146 | } 1147 | else { 1148 | cf = 0; 1149 | of = 0; 1150 | } 1151 | break; 1152 | 1153 | case 5: /* IMUL */ 1154 | oper1 = signext (oper1b); 1155 | temp1 = signext (regs.byteregs[regal]); 1156 | temp2 = oper1; 1157 | if ( (temp1 & 0x80) == 0x80) { 1158 | temp1 = temp1 | 0xFFFFFF00; 1159 | } 1160 | 1161 | if ( (temp2 & 0x80) == 0x80) { 1162 | temp2 = temp2 | 0xFFFFFF00; 1163 | } 1164 | 1165 | temp3 = (temp1 * temp2) & 0xFFFF; 1166 | regs.wordregs[regax] = temp3 & 0xFFFF; 1167 | if (regs.byteregs[regah]) { 1168 | cf = 1; 1169 | of = 1; 1170 | } 1171 | else { 1172 | cf = 0; 1173 | of = 0; 1174 | } 1175 | break; 1176 | 1177 | case 6: /* DIV */ 1178 | op_div8 (regs.wordregs[regax], oper1b); 1179 | break; 1180 | 1181 | case 7: /* IDIV */ 1182 | op_idiv8 (regs.wordregs[regax], oper1b); 1183 | break; 1184 | } 1185 | } 1186 | 1187 | void op_div16 (uint32_t valdiv, word divisor) { 1188 | if (divisor == 0) { 1189 | intcall86 (0); 1190 | return; 1191 | } 1192 | 1193 | if ( (valdiv / (uint32_t) divisor) > 0xFFFF) { 1194 | intcall86 (0); 1195 | return; 1196 | } 1197 | 1198 | regs.wordregs[regdx] = valdiv % (uint32_t) divisor; 1199 | regs.wordregs[regax] = valdiv / (uint32_t) divisor; 1200 | } 1201 | 1202 | void op_idiv16 (uint32_t valdiv, word divisor) { 1203 | 1204 | uint32_t d1; 1205 | uint32_t d2; 1206 | uint32_t s1; 1207 | uint32_t s2; 1208 | int sign; 1209 | 1210 | if (divisor == 0) { 1211 | intcall86 (0); 1212 | return; 1213 | } 1214 | 1215 | s1 = valdiv; 1216 | s2 = divisor; 1217 | s2 = (s2 & 0x8000) ? (s2 | 0xffff0000) : s2; 1218 | sign = ( ( (s1 ^ s2) & 0x80000000) != 0); 1219 | s1 = (s1 < 0x80000000) ? s1 : ( (~s1 + 1) & 0xffffffff); 1220 | s2 = (s2 < 0x80000000) ? s2 : ( (~s2 + 1) & 0xffffffff); 1221 | d1 = s1 / s2; 1222 | d2 = s1 % s2; 1223 | if (d1 & 0xFFFF0000) { 1224 | intcall86 (0); 1225 | return; 1226 | } 1227 | 1228 | if (sign) { 1229 | d1 = (~d1 + 1) & 0xffff; 1230 | d2 = (~d2 + 1) & 0xffff; 1231 | } 1232 | 1233 | regs.wordregs[regax] = d1; 1234 | regs.wordregs[regdx] = d2; 1235 | } 1236 | 1237 | void op_grp3_16() { 1238 | switch (reg) { 1239 | case 0: 1240 | case 1: /* TEST */ 1241 | flag_log16 (oper1 & getmem16 (segregs[regcs], ip) ); 1242 | StepIP (2); 1243 | break; 1244 | 1245 | case 2: /* NOT */ 1246 | res16 = ~oper1; 1247 | break; 1248 | 1249 | case 3: /* NEG */ 1250 | res16 = (~oper1) + 1; 1251 | flag_sub16 (0, oper1); 1252 | if (res16) { 1253 | cf = 1; 1254 | } 1255 | else { 1256 | cf = 0; 1257 | } 1258 | break; 1259 | 1260 | case 4: /* MUL */ 1261 | temp1 = (uint32_t) oper1 * (uint32_t) regs.wordregs[regax]; 1262 | regs.wordregs[regax] = temp1 & 0xFFFF; 1263 | regs.wordregs[regdx] = temp1 >> 16; 1264 | flag_szp16 ( (word) temp1); 1265 | if (regs.wordregs[regdx]) { 1266 | cf = 1; 1267 | of = 1; 1268 | } 1269 | else { 1270 | cf = 0; 1271 | of = 0; 1272 | } 1273 | break; 1274 | 1275 | case 5: /* IMUL */ 1276 | temp1 = regs.wordregs[regax]; 1277 | temp2 = oper1; 1278 | if (temp1 & 0x8000) { 1279 | temp1 |= 0xFFFF0000; 1280 | } 1281 | 1282 | if (temp2 & 0x8000) { 1283 | temp2 |= 0xFFFF0000; 1284 | } 1285 | 1286 | temp3 = temp1 * temp2; 1287 | regs.wordregs[regax] = temp3 & 0xFFFF; /* into register ax */ 1288 | regs.wordregs[regdx] = temp3 >> 16; /* into register dx */ 1289 | if (regs.wordregs[regdx]) { 1290 | cf = 1; 1291 | of = 1; 1292 | } 1293 | else { 1294 | cf = 0; 1295 | of = 0; 1296 | } 1297 | break; 1298 | 1299 | case 6: /* DIV */ 1300 | op_div16 ( ( (uint32_t) regs.wordregs[regdx] << 16) + regs.wordregs[regax], oper1); 1301 | break; 1302 | 1303 | case 7: /* DIV */ 1304 | op_idiv16 ( ( (uint32_t) regs.wordregs[regdx] << 16) + regs.wordregs[regax], oper1); 1305 | break; 1306 | } 1307 | } 1308 | 1309 | void op_grp5() { 1310 | switch (reg) { 1311 | case 0: /* INC Ev */ 1312 | oper2 = 1; 1313 | tempcf = cf; 1314 | op_add16(); 1315 | cf = tempcf; 1316 | writerm16 (rm, res16); 1317 | break; 1318 | 1319 | case 1: /* DEC Ev */ 1320 | oper2 = 1; 1321 | tempcf = cf; 1322 | op_sub16(); 1323 | cf = tempcf; 1324 | writerm16 (rm, res16); 1325 | break; 1326 | 1327 | case 2: /* CALL Ev */ 1328 | push (ip); 1329 | ip = oper1; 1330 | break; 1331 | 1332 | case 3: /* CALL Mp */ 1333 | push (segregs[regcs]); 1334 | push (ip); 1335 | getea (rm); 1336 | ip = (word) read86 (ea) + (word) read86 (ea + 1) * 256; 1337 | segregs[regcs] = (word) read86 (ea + 2) + (word) read86 (ea + 3) * 256; 1338 | break; 1339 | 1340 | case 4: /* JMP Ev */ 1341 | ip = oper1; 1342 | break; 1343 | 1344 | case 5: /* JMP Mp */ 1345 | getea (rm); 1346 | ip = (word) read86 (ea) + (word) read86 (ea + 1) * 256; 1347 | segregs[regcs] = (word) read86 (ea + 2) + (word) read86 (ea + 3) * 256; 1348 | break; 1349 | 1350 | case 6: /* PUSH Ev */ 1351 | push (oper1); 1352 | break; 1353 | } 1354 | } 1355 | 1356 | void init86 (){ 1357 | regs.wordregs[regax] = 0; 1358 | regs.wordregs[regbx] = 0; 1359 | regs.wordregs[regcx] = 0x001E; 1360 | regs.wordregs[regdx] = 0; 1361 | segregs[regcs]= 0x0700 ; 1362 | ip = 0x100; 1363 | segregs[regss] = 0x0700; 1364 | regs.wordregs[regsp] = 0xFFFE; 1365 | regs.wordregs[regbp] = 0; 1366 | regs.wordregs[regsi] = 0; 1367 | regs.wordregs[regdi] = 0; 1368 | segregs[regds] = 0x0700; 1369 | segregs[reges] = 0x0700; 1370 | } 1371 | 1372 | void exec86 (uint32_t execloops) { 1373 | 1374 | uint32_t loopcount; 1375 | byte docontinue; 1376 | static word firstip; 1377 | static word trap_toggle = 0; 1378 | 1379 | //counterticks = (uint64_t) ( (double) timerfreq / (double) 65536.0); 1380 | 1381 | for (loopcount = 0; loopcount < execloops; loopcount++) { 1382 | 1383 | if (tf) { 1384 | trap_toggle = 1; 1385 | } 1386 | else { 1387 | trap_toggle = 0; 1388 | } 1389 | 1390 | if (hltstate) goto skipexecution; 1391 | 1392 | reptype = 0; 1393 | segoverride = 0; 1394 | useseg = segregs[regds]; 1395 | docontinue = 0; 1396 | firstip = ip; 1397 | 1398 | if ( (segregs[regcs] == 0xF000) && (ip == 0xE066) ) didbootstrap = 0; //detect if we hit the BIOS entry point to clear didbootstrap because we've rebooted 1399 | 1400 | while (!docontinue) { 1401 | segregs[regcs] = segregs[regcs] & 0xFFFF; 1402 | ip = ip & 0xFFFF; 1403 | savecs = segregs[regcs]; 1404 | saveip = ip; 1405 | opcode = getmem8 (segregs[regcs], ip); 1406 | StepIP (1); 1407 | 1408 | #ifdef DEBUG 1409 | Serial.print("op:"); 1410 | Serial.print(opcode, HEX); 1411 | Serial.print(" ip:"); 1412 | Serial.print(ip, HEX); 1413 | Serial.print(" ax:"); 1414 | Serial.print(regs.wordregs[regax], HEX); 1415 | Serial.print(" bx:"); 1416 | Serial.print(regs.wordregs[regbx], HEX); 1417 | Serial.print(" cx:"); 1418 | Serial.print(regs.wordregs[regcx], HEX); 1419 | Serial.print(" dx:"); 1420 | Serial.println(regs.wordregs[regdx], HEX); 1421 | #endif 1422 | 1423 | switch (opcode) { 1424 | /* segment prefix check */ 1425 | case 0x2E: /* segment segregs[regcs] */ 1426 | useseg = segregs[regcs]; 1427 | segoverride = 1; 1428 | break; 1429 | 1430 | case 0x3E: /* segment segregs[regds] */ 1431 | useseg = segregs[regds]; 1432 | segoverride = 1; 1433 | break; 1434 | 1435 | case 0x26: /* segment segregs[reges] */ 1436 | useseg = segregs[reges]; 1437 | segoverride = 1; 1438 | break; 1439 | 1440 | case 0x36: /* segment segregs[regss] */ 1441 | useseg = segregs[regss]; 1442 | segoverride = 1; 1443 | break; 1444 | 1445 | /* repetition prefix check */ 1446 | case 0xF3: /* REP/REPE/REPZ */ 1447 | reptype = 1; 1448 | break; 1449 | 1450 | case 0xF2: /* REPNE/REPNZ */ 1451 | reptype = 2; 1452 | break; 1453 | 1454 | default: 1455 | docontinue = 1; 1456 | break; 1457 | } 1458 | } 1459 | 1460 | totalexec++; 1461 | 1462 | switch (opcode) { 1463 | case 0x0: /* 00 ADD Eb Gb */ 1464 | modregrm(); 1465 | oper1b = readrm8 (rm); 1466 | oper2b = getreg8 (reg); 1467 | op_add8(); 1468 | writerm8 (rm, res8); 1469 | break; 1470 | 1471 | case 0x1: /* 01 ADD Ev Gv */ 1472 | modregrm(); 1473 | oper1 = readrm16 (rm); 1474 | oper2 = getreg16 (reg); 1475 | op_add16(); 1476 | writerm16 (rm, res16); 1477 | break; 1478 | 1479 | case 0x2: /* 02 ADD Gb Eb */ 1480 | modregrm(); 1481 | oper1b = getreg8 (reg); 1482 | oper2b = readrm8 (rm); 1483 | op_add8(); 1484 | putreg8 (reg, res8); 1485 | break; 1486 | 1487 | case 0x3: /* 03 ADD Gv Ev */ 1488 | modregrm(); 1489 | oper1 = getreg16 (reg); 1490 | oper2 = readrm16 (rm); 1491 | op_add16(); 1492 | putreg16 (reg, res16); 1493 | break; 1494 | 1495 | case 0x4: /* 04 ADD regs.byteregs[regal] Ib */ 1496 | oper1b = regs.byteregs[regal]; 1497 | oper2b = getmem8 (segregs[regcs], ip); 1498 | StepIP (1); 1499 | op_add8(); 1500 | regs.byteregs[regal] = res8; 1501 | break; 1502 | 1503 | case 0x5: /* 05 ADD eAX Iv */ 1504 | oper1 = regs.wordregs[regax]; 1505 | oper2 = getmem16 (segregs[regcs], ip); 1506 | StepIP (2); 1507 | op_add16(); 1508 | regs.wordregs[regax] = res16; 1509 | break; 1510 | 1511 | case 0x6: /* 06 PUSH segregs[reges] */ 1512 | push (segregs[reges]); 1513 | break; 1514 | 1515 | case 0x7: /* 07 POP segregs[reges] */ 1516 | segregs[reges] = pop(); 1517 | break; 1518 | 1519 | case 0x8: /* 08 OR Eb Gb */ 1520 | modregrm(); 1521 | oper1b = readrm8 (rm); 1522 | oper2b = getreg8 (reg); 1523 | op_or8(); 1524 | writerm8 (rm, res8); 1525 | break; 1526 | 1527 | case 0x9: /* 09 OR Ev Gv */ 1528 | modregrm(); 1529 | oper1 = readrm16 (rm); 1530 | oper2 = getreg16 (reg); 1531 | op_or16(); 1532 | writerm16 (rm, res16); 1533 | break; 1534 | 1535 | case 0xA: /* 0A OR Gb Eb */ 1536 | modregrm(); 1537 | oper1b = getreg8 (reg); 1538 | oper2b = readrm8 (rm); 1539 | op_or8(); 1540 | putreg8 (reg, res8); 1541 | break; 1542 | 1543 | case 0xB: /* 0B OR Gv Ev */ 1544 | modregrm(); 1545 | oper1 = getreg16 (reg); 1546 | oper2 = readrm16 (rm); 1547 | op_or16(); 1548 | if ( (oper1 == 0xF802) && (oper2 == 0xF802) ) { 1549 | sf = 0; /* cheap hack to make Wolf 3D think we're a 286 so it plays */ 1550 | } 1551 | 1552 | putreg16 (reg, res16); 1553 | break; 1554 | 1555 | case 0xC: /* 0C OR regs.byteregs[regal] Ib */ 1556 | oper1b = regs.byteregs[regal]; 1557 | oper2b = getmem8 (segregs[regcs], ip); 1558 | StepIP (1); 1559 | op_or8(); 1560 | regs.byteregs[regal] = res8; 1561 | break; 1562 | 1563 | case 0xD: /* 0D OR eAX Iv */ 1564 | oper1 = regs.wordregs[regax]; 1565 | oper2 = getmem16 (segregs[regcs], ip); 1566 | StepIP (2); 1567 | op_or16(); 1568 | regs.wordregs[regax] = res16; 1569 | break; 1570 | 1571 | case 0xE: /* 0E PUSH segregs[regcs] */ 1572 | push (segregs[regcs]); 1573 | break; 1574 | 1575 | case 0xF: //0F POP CS only the 8086/8088 does this. 1576 | segregs[regcs] = pop(); 1577 | break; 1578 | 1579 | case 0x10: /* 10 ADC Eb Gb */ 1580 | modregrm(); 1581 | oper1b = readrm8 (rm); 1582 | oper2b = getreg8 (reg); 1583 | op_adc8(); 1584 | writerm8 (rm, res8); 1585 | break; 1586 | 1587 | case 0x11: /* 11 ADC Ev Gv */ 1588 | modregrm(); 1589 | oper1 = readrm16 (rm); 1590 | oper2 = getreg16 (reg); 1591 | op_adc16(); 1592 | writerm16 (rm, res16); 1593 | break; 1594 | 1595 | case 0x12: /* 12 ADC Gb Eb */ 1596 | modregrm(); 1597 | oper1b = getreg8 (reg); 1598 | oper2b = readrm8 (rm); 1599 | op_adc8(); 1600 | putreg8 (reg, res8); 1601 | break; 1602 | 1603 | case 0x13: /* 13 ADC Gv Ev */ 1604 | modregrm(); 1605 | oper1 = getreg16 (reg); 1606 | oper2 = readrm16 (rm); 1607 | op_adc16(); 1608 | putreg16 (reg, res16); 1609 | break; 1610 | 1611 | case 0x14: /* 14 ADC regs.byteregs[regal] Ib */ 1612 | oper1b = regs.byteregs[regal]; 1613 | oper2b = getmem8 (segregs[regcs], ip); 1614 | StepIP (1); 1615 | op_adc8(); 1616 | regs.byteregs[regal] = res8; 1617 | break; 1618 | 1619 | case 0x15: /* 15 ADC eAX Iv */ 1620 | oper1 = regs.wordregs[regax]; 1621 | oper2 = getmem16 (segregs[regcs], ip); 1622 | StepIP (2); 1623 | op_adc16(); 1624 | regs.wordregs[regax] = res16; 1625 | break; 1626 | 1627 | case 0x16: /* 16 PUSH segregs[regss] */ 1628 | push (segregs[regss]); 1629 | break; 1630 | 1631 | case 0x17: /* 17 POP segregs[regss] */ 1632 | segregs[regss] = pop(); 1633 | break; 1634 | 1635 | case 0x18: /* 18 SBB Eb Gb */ 1636 | modregrm(); 1637 | oper1b = readrm8 (rm); 1638 | oper2b = getreg8 (reg); 1639 | op_sbb8(); 1640 | writerm8 (rm, res8); 1641 | break; 1642 | 1643 | case 0x19: /* 19 SBB Ev Gv */ 1644 | modregrm(); 1645 | oper1 = readrm16 (rm); 1646 | oper2 = getreg16 (reg); 1647 | op_sbb16(); 1648 | writerm16 (rm, res16); 1649 | break; 1650 | 1651 | case 0x1A: /* 1A SBB Gb Eb */ 1652 | modregrm(); 1653 | oper1b = getreg8 (reg); 1654 | oper2b = readrm8 (rm); 1655 | op_sbb8(); 1656 | putreg8 (reg, res8); 1657 | break; 1658 | 1659 | case 0x1B: /* 1B SBB Gv Ev */ 1660 | modregrm(); 1661 | oper1 = getreg16 (reg); 1662 | oper2 = readrm16 (rm); 1663 | op_sbb16(); 1664 | putreg16 (reg, res16); 1665 | break; 1666 | 1667 | case 0x1C: /* 1C SBB regs.byteregs[regal] Ib */ 1668 | oper1b = regs.byteregs[regal]; 1669 | oper2b = getmem8 (segregs[regcs], ip); 1670 | StepIP (1); 1671 | op_sbb8(); 1672 | regs.byteregs[regal] = res8; 1673 | break; 1674 | 1675 | case 0x1D: /* 1D SBB eAX Iv */ 1676 | oper1 = regs.wordregs[regax]; 1677 | oper2 = getmem16 (segregs[regcs], ip); 1678 | StepIP (2); 1679 | op_sbb16(); 1680 | regs.wordregs[regax] = res16; 1681 | break; 1682 | 1683 | case 0x1E: /* 1E PUSH segregs[regds] */ 1684 | push (segregs[regds]); 1685 | break; 1686 | 1687 | case 0x1F: /* 1F POP segregs[regds] */ 1688 | segregs[regds] = pop(); 1689 | break; 1690 | 1691 | case 0x20: /* 20 AND Eb Gb */ 1692 | modregrm(); 1693 | oper1b = readrm8 (rm); 1694 | oper2b = getreg8 (reg); 1695 | op_and8(); 1696 | writerm8 (rm, res8); 1697 | break; 1698 | 1699 | case 0x21: /* 21 AND Ev Gv */ 1700 | modregrm(); 1701 | oper1 = readrm16 (rm); 1702 | oper2 = getreg16 (reg); 1703 | op_and16(); 1704 | writerm16 (rm, res16); 1705 | break; 1706 | 1707 | case 0x22: /* 22 AND Gb Eb */ 1708 | modregrm(); 1709 | oper1b = getreg8 (reg); 1710 | oper2b = readrm8 (rm); 1711 | op_and8(); 1712 | putreg8 (reg, res8); 1713 | break; 1714 | 1715 | case 0x23: /* 23 AND Gv Ev */ 1716 | modregrm(); 1717 | oper1 = getreg16 (reg); 1718 | oper2 = readrm16 (rm); 1719 | op_and16(); 1720 | putreg16 (reg, res16); 1721 | break; 1722 | 1723 | case 0x24: /* 24 AND regs.byteregs[regal] Ib */ 1724 | oper1b = regs.byteregs[regal]; 1725 | oper2b = getmem8 (segregs[regcs], ip); 1726 | StepIP (1); 1727 | op_and8(); 1728 | regs.byteregs[regal] = res8; 1729 | break; 1730 | 1731 | case 0x25: /* 25 AND eAX Iv */ 1732 | oper1 = regs.wordregs[regax]; 1733 | oper2 = getmem16 (segregs[regcs], ip); 1734 | StepIP (2); 1735 | op_and16(); 1736 | regs.wordregs[regax] = res16; 1737 | break; 1738 | 1739 | case 0x27: /* 27 DAA */ 1740 | if ( ( (regs.byteregs[regal] & 0xF) > 9) || (af == 1) ) { 1741 | oper1 = regs.byteregs[regal] + 6; 1742 | regs.byteregs[regal] = oper1 & 255; 1743 | if (oper1 & 0xFF00) { 1744 | cf = 1; 1745 | } 1746 | else { 1747 | cf = 0; 1748 | } 1749 | 1750 | af = 1; 1751 | } 1752 | else { 1753 | //af = 0; 1754 | } 1755 | 1756 | if ( (regs.byteregs[regal] > 0x9F) || (cf == 1) ) { 1757 | regs.byteregs[regal] = regs.byteregs[regal] + 0x60; 1758 | cf = 1; 1759 | } 1760 | else { 1761 | //cf = 0; 1762 | } 1763 | 1764 | regs.byteregs[regal] = regs.byteregs[regal] & 255; 1765 | flag_szp8 (regs.byteregs[regal]); 1766 | break; 1767 | 1768 | case 0x28: /* 28 SUB Eb Gb */ 1769 | modregrm(); 1770 | oper1b = readrm8 (rm); 1771 | oper2b = getreg8 (reg); 1772 | op_sub8(); 1773 | writerm8 (rm, res8); 1774 | break; 1775 | 1776 | case 0x29: /* 29 SUB Ev Gv */ 1777 | modregrm(); 1778 | oper1 = readrm16 (rm); 1779 | oper2 = getreg16 (reg); 1780 | op_sub16(); 1781 | writerm16 (rm, res16); 1782 | break; 1783 | 1784 | case 0x2A: /* 2A SUB Gb Eb */ 1785 | modregrm(); 1786 | oper1b = getreg8 (reg); 1787 | oper2b = readrm8 (rm); 1788 | op_sub8(); 1789 | putreg8 (reg, res8); 1790 | break; 1791 | 1792 | case 0x2B: /* 2B SUB Gv Ev */ 1793 | modregrm(); 1794 | oper1 = getreg16 (reg); 1795 | oper2 = readrm16 (rm); 1796 | op_sub16(); 1797 | putreg16 (reg, res16); 1798 | break; 1799 | 1800 | case 0x2C: /* 2C SUB regs.byteregs[regal] Ib */ 1801 | oper1b = regs.byteregs[regal]; 1802 | oper2b = getmem8 (segregs[regcs], ip); 1803 | StepIP (1); 1804 | op_sub8(); 1805 | regs.byteregs[regal] = res8; 1806 | break; 1807 | 1808 | case 0x2D: /* 2D SUB eAX Iv */ 1809 | oper1 = regs.wordregs[regax]; 1810 | oper2 = getmem16 (segregs[regcs], ip); 1811 | StepIP (2); 1812 | op_sub16(); 1813 | regs.wordregs[regax] = res16; 1814 | break; 1815 | 1816 | case 0x2F: /* 2F DAS */ 1817 | if ( ( (regs.byteregs[regal] & 15) > 9) || (af == 1) ) { 1818 | oper1 = regs.byteregs[regal] - 6; 1819 | regs.byteregs[regal] = oper1 & 255; 1820 | if (oper1 & 0xFF00) { 1821 | cf = 1; 1822 | } 1823 | else { 1824 | cf = 0; 1825 | } 1826 | 1827 | af = 1; 1828 | } 1829 | else { 1830 | af = 0; 1831 | } 1832 | 1833 | if ( ( (regs.byteregs[regal] & 0xF0) > 0x90) || (cf == 1) ) { 1834 | regs.byteregs[regal] = regs.byteregs[regal] - 0x60; 1835 | cf = 1; 1836 | } 1837 | else { 1838 | cf = 0; 1839 | } 1840 | 1841 | flag_szp8 (regs.byteregs[regal]); 1842 | break; 1843 | 1844 | case 0x30: /* 30 XOR Eb Gb */ 1845 | modregrm(); 1846 | oper1b = readrm8 (rm); 1847 | oper2b = getreg8 (reg); 1848 | op_xor8(); 1849 | writerm8 (rm, res8); 1850 | break; 1851 | 1852 | case 0x31: /* 31 XOR Ev Gv */ 1853 | modregrm(); 1854 | oper1 = readrm16 (rm); 1855 | oper2 = getreg16 (reg); 1856 | op_xor16(); 1857 | writerm16 (rm, res16); 1858 | break; 1859 | 1860 | case 0x32: /* 32 XOR Gb Eb */ 1861 | modregrm(); 1862 | oper1b = getreg8 (reg); 1863 | oper2b = readrm8 (rm); 1864 | op_xor8(); 1865 | putreg8 (reg, res8); 1866 | break; 1867 | 1868 | case 0x33: /* 33 XOR Gv Ev */ 1869 | modregrm(); 1870 | oper1 = getreg16 (reg); 1871 | oper2 = readrm16 (rm); 1872 | op_xor16(); 1873 | putreg16 (reg, res16); 1874 | break; 1875 | 1876 | case 0x34: /* 34 XOR regs.byteregs[regal] Ib */ 1877 | oper1b = regs.byteregs[regal]; 1878 | oper2b = getmem8 (segregs[regcs], ip); 1879 | StepIP (1); 1880 | op_xor8(); 1881 | regs.byteregs[regal] = res8; 1882 | break; 1883 | 1884 | case 0x35: /* 35 XOR eAX Iv */ 1885 | oper1 = regs.wordregs[regax]; 1886 | oper2 = getmem16 (segregs[regcs], ip); 1887 | StepIP (2); 1888 | op_xor16(); 1889 | regs.wordregs[regax] = res16; 1890 | break; 1891 | 1892 | case 0x37: /* 37 AAA ASCII */ 1893 | if ( ( (regs.byteregs[regal] & 0xF) > 9) || (af == 1) ) { 1894 | regs.byteregs[regal] = regs.byteregs[regal] + 6; 1895 | regs.byteregs[regah] = regs.byteregs[regah] + 1; 1896 | af = 1; 1897 | cf = 1; 1898 | } 1899 | else { 1900 | af = 0; 1901 | cf = 0; 1902 | } 1903 | 1904 | regs.byteregs[regal] = regs.byteregs[regal] & 0xF; 1905 | break; 1906 | 1907 | case 0x38: /* 38 CMP Eb Gb */ 1908 | modregrm(); 1909 | oper1b = readrm8 (rm); 1910 | oper2b = getreg8 (reg); 1911 | flag_sub8 (oper1b, oper2b); 1912 | break; 1913 | 1914 | case 0x39: /* 39 CMP Ev Gv */ 1915 | modregrm(); 1916 | oper1 = readrm16 (rm); 1917 | oper2 = getreg16 (reg); 1918 | flag_sub16 (oper1, oper2); 1919 | break; 1920 | 1921 | case 0x3A: /* 3A CMP Gb Eb */ 1922 | modregrm(); 1923 | oper1b = getreg8 (reg); 1924 | oper2b = readrm8 (rm); 1925 | flag_sub8 (oper1b, oper2b); 1926 | break; 1927 | 1928 | case 0x3B: /* 3B CMP Gv Ev */ 1929 | modregrm(); 1930 | oper1 = getreg16 (reg); 1931 | oper2 = readrm16 (rm); 1932 | flag_sub16 (oper1, oper2); 1933 | break; 1934 | 1935 | case 0x3C: /* 3C CMP regs.byteregs[regal] Ib */ 1936 | oper1b = regs.byteregs[regal]; 1937 | oper2b = getmem8 (segregs[regcs], ip); 1938 | StepIP (1); 1939 | flag_sub8 (oper1b, oper2b); 1940 | break; 1941 | 1942 | case 0x3D: /* 3D CMP eAX Iv */ 1943 | oper1 = regs.wordregs[regax]; 1944 | oper2 = getmem16 (segregs[regcs], ip); 1945 | StepIP (2); 1946 | flag_sub16 (oper1, oper2); 1947 | break; 1948 | 1949 | case 0x3F: /* 3F AAS ASCII */ 1950 | if ( ( (regs.byteregs[regal] & 0xF) > 9) || (af == 1) ) { 1951 | regs.byteregs[regal] = regs.byteregs[regal] - 6; 1952 | regs.byteregs[regah] = regs.byteregs[regah] - 1; 1953 | af = 1; 1954 | cf = 1; 1955 | } 1956 | else { 1957 | af = 0; 1958 | cf = 0; 1959 | } 1960 | 1961 | regs.byteregs[regal] = regs.byteregs[regal] & 0xF; 1962 | break; 1963 | 1964 | case 0x40: /* 40 INC eAX */ 1965 | oldcf = cf; 1966 | oper1 = regs.wordregs[regax]; 1967 | oper2 = 1; 1968 | op_add16(); 1969 | cf = oldcf; 1970 | regs.wordregs[regax] = res16; 1971 | break; 1972 | 1973 | case 0x41: /* 41 INC eCX */ 1974 | oldcf = cf; 1975 | oper1 = regs.wordregs[regcx]; 1976 | oper2 = 1; 1977 | op_add16(); 1978 | cf = oldcf; 1979 | regs.wordregs[regcx] = res16; 1980 | break; 1981 | 1982 | case 0x42: /* 42 INC eDX */ 1983 | oldcf = cf; 1984 | oper1 = regs.wordregs[regdx]; 1985 | oper2 = 1; 1986 | op_add16(); 1987 | cf = oldcf; 1988 | regs.wordregs[regdx] = res16; 1989 | break; 1990 | 1991 | case 0x43: /* 43 INC eBX */ 1992 | oldcf = cf; 1993 | oper1 = regs.wordregs[regbx]; 1994 | oper2 = 1; 1995 | op_add16(); 1996 | cf = oldcf; 1997 | regs.wordregs[regbx] = res16; 1998 | break; 1999 | 2000 | case 0x44: /* 44 INC eSP */ 2001 | oldcf = cf; 2002 | oper1 = regs.wordregs[regsp]; 2003 | oper2 = 1; 2004 | op_add16(); 2005 | cf = oldcf; 2006 | regs.wordregs[regsp] = res16; 2007 | break; 2008 | 2009 | case 0x45: /* 45 INC eBP */ 2010 | oldcf = cf; 2011 | oper1 = regs.wordregs[regbp]; 2012 | oper2 = 1; 2013 | op_add16(); 2014 | cf = oldcf; 2015 | regs.wordregs[regbp] = res16; 2016 | break; 2017 | 2018 | case 0x46: /* 46 INC eSI */ 2019 | oldcf = cf; 2020 | oper1 = regs.wordregs[regsi]; 2021 | oper2 = 1; 2022 | op_add16(); 2023 | cf = oldcf; 2024 | regs.wordregs[regsi] = res16; 2025 | break; 2026 | 2027 | case 0x47: /* 47 INC eDI */ 2028 | oldcf = cf; 2029 | oper1 = regs.wordregs[regdi]; 2030 | oper2 = 1; 2031 | op_add16(); 2032 | cf = oldcf; 2033 | regs.wordregs[regdi] = res16; 2034 | break; 2035 | 2036 | case 0x48: /* 48 DEC eAX */ 2037 | oldcf = cf; 2038 | oper1 = regs.wordregs[regax]; 2039 | oper2 = 1; 2040 | op_sub16(); 2041 | cf = oldcf; 2042 | regs.wordregs[regax] = res16; 2043 | break; 2044 | 2045 | case 0x49: /* 49 DEC eCX */ 2046 | oldcf = cf; 2047 | oper1 = regs.wordregs[regcx]; 2048 | oper2 = 1; 2049 | op_sub16(); 2050 | cf = oldcf; 2051 | regs.wordregs[regcx] = res16; 2052 | break; 2053 | 2054 | case 0x4A: /* 4A DEC eDX */ 2055 | oldcf = cf; 2056 | oper1 = regs.wordregs[regdx]; 2057 | oper2 = 1; 2058 | op_sub16(); 2059 | cf = oldcf; 2060 | regs.wordregs[regdx] = res16; 2061 | break; 2062 | 2063 | case 0x4B: /* 4B DEC eBX */ 2064 | oldcf = cf; 2065 | oper1 = regs.wordregs[regbx]; 2066 | oper2 = 1; 2067 | op_sub16(); 2068 | cf = oldcf; 2069 | regs.wordregs[regbx] = res16; 2070 | break; 2071 | 2072 | case 0x4C: /* 4C DEC eSP */ 2073 | oldcf = cf; 2074 | oper1 = regs.wordregs[regsp]; 2075 | oper2 = 1; 2076 | op_sub16(); 2077 | cf = oldcf; 2078 | regs.wordregs[regsp] = res16; 2079 | break; 2080 | 2081 | case 0x4D: /* 4D DEC eBP */ 2082 | oldcf = cf; 2083 | oper1 = regs.wordregs[regbp]; 2084 | oper2 = 1; 2085 | op_sub16(); 2086 | cf = oldcf; 2087 | regs.wordregs[regbp] = res16; 2088 | break; 2089 | 2090 | case 0x4E: /* 4E DEC eSI */ 2091 | oldcf = cf; 2092 | oper1 = regs.wordregs[regsi]; 2093 | oper2 = 1; 2094 | op_sub16(); 2095 | cf = oldcf; 2096 | regs.wordregs[regsi] = res16; 2097 | break; 2098 | 2099 | case 0x4F: /* 4F DEC eDI */ 2100 | oldcf = cf; 2101 | oper1 = regs.wordregs[regdi]; 2102 | oper2 = 1; 2103 | op_sub16(); 2104 | cf = oldcf; 2105 | regs.wordregs[regdi] = res16; 2106 | break; 2107 | 2108 | case 0x50: /* 50 PUSH eAX */ 2109 | push (regs.wordregs[regax]); 2110 | break; 2111 | 2112 | case 0x51: /* 51 PUSH eCX */ 2113 | push (regs.wordregs[regcx]); 2114 | break; 2115 | 2116 | case 0x52: /* 52 PUSH eDX */ 2117 | push (regs.wordregs[regdx]); 2118 | break; 2119 | 2120 | case 0x53: /* 53 PUSH eBX */ 2121 | push (regs.wordregs[regbx]); 2122 | break; 2123 | 2124 | case 0x54: /* 54 PUSH eSP */ 2125 | push (regs.wordregs[regsp] - 2); 2126 | break; 2127 | 2128 | case 0x55: /* 55 PUSH eBP */ 2129 | push (regs.wordregs[regbp]); 2130 | break; 2131 | 2132 | case 0x56: /* 56 PUSH eSI */ 2133 | push (regs.wordregs[regsi]); 2134 | break; 2135 | 2136 | case 0x57: /* 57 PUSH eDI */ 2137 | push (regs.wordregs[regdi]); 2138 | break; 2139 | 2140 | case 0x58: /* 58 POP eAX */ 2141 | regs.wordregs[regax] = pop(); 2142 | break; 2143 | 2144 | case 0x59: /* 59 POP eCX */ 2145 | regs.wordregs[regcx] = pop(); 2146 | break; 2147 | 2148 | case 0x5A: /* 5A POP eDX */ 2149 | regs.wordregs[regdx] = pop(); 2150 | break; 2151 | 2152 | case 0x5B: /* 5B POP eBX */ 2153 | regs.wordregs[regbx] = pop(); 2154 | break; 2155 | 2156 | case 0x5C: /* 5C POP eSP */ 2157 | regs.wordregs[regsp] = pop(); 2158 | break; 2159 | 2160 | case 0x5D: /* 5D POP eBP */ 2161 | regs.wordregs[regbp] = pop(); 2162 | break; 2163 | 2164 | case 0x5E: /* 5E POP eSI */ 2165 | regs.wordregs[regsi] = pop(); 2166 | break; 2167 | 2168 | case 0x5F: /* 5F POP eDI */ 2169 | regs.wordregs[regdi] = pop(); 2170 | break; 2171 | 2172 | #ifndef CPU_8086 2173 | case 0x60: /* 60 PUSHA (80186+) */ 2174 | oldsp = regs.wordregs[regsp]; 2175 | push (regs.wordregs[regax]); 2176 | push (regs.wordregs[regcx]); 2177 | push (regs.wordregs[regdx]); 2178 | push (regs.wordregs[regbx]); 2179 | push (oldsp); 2180 | push (regs.wordregs[regbp]); 2181 | push (regs.wordregs[regsi]); 2182 | push (regs.wordregs[regdi]); 2183 | break; 2184 | 2185 | case 0x61: /* 61 POPA (80186+) */ 2186 | regs.wordregs[regdi] = pop(); 2187 | regs.wordregs[regsi] = pop(); 2188 | regs.wordregs[regbp] = pop(); 2189 | dummy = pop(); 2190 | regs.wordregs[regbx] = pop(); 2191 | regs.wordregs[regdx] = pop(); 2192 | regs.wordregs[regcx] = pop(); 2193 | regs.wordregs[regax] = pop(); 2194 | break; 2195 | 2196 | case 0x62: /* 62 BOUND Gv, Ev (80186+) */ 2197 | modregrm(); 2198 | getea (rm); 2199 | if (signext32 (getreg16 (reg) ) < signext32 ( getmem16 (ea >> 4, ea & 15) ) ) { 2200 | intcall86 (5); //bounds check exception 2201 | } 2202 | else { 2203 | ea += 2; 2204 | if (signext32 (getreg16 (reg) ) > signext32 ( getmem16 (ea >> 4, ea & 15) ) ) { 2205 | intcall86(5); //bounds check exception 2206 | } 2207 | } 2208 | break; 2209 | 2210 | case 0x68: /* 68 PUSH Iv (80186+) */ 2211 | push (getmem16 (segregs[regcs], ip) ); 2212 | StepIP (2); 2213 | break; 2214 | 2215 | case 0x69: /* 69 IMUL Gv Ev Iv (80186+) */ 2216 | modregrm(); 2217 | temp1 = readrm16 (rm); 2218 | temp2 = getmem16 (segregs[regcs], ip); 2219 | StepIP (2); 2220 | if ( (temp1 & 0x8000L) == 0x8000L) { 2221 | temp1 = temp1 | 0xFFFF0000L; 2222 | } 2223 | 2224 | if ( (temp2 & 0x8000L) == 0x8000L) { 2225 | temp2 = temp2 | 0xFFFF0000L; 2226 | } 2227 | 2228 | temp3 = temp1 * temp2; 2229 | putreg16 (reg, temp3 & 0xFFFFL); 2230 | if (temp3 & 0xFFFF0000L) { 2231 | cf = 1; 2232 | of = 1; 2233 | } 2234 | else { 2235 | cf = 0; 2236 | of = 0; 2237 | } 2238 | break; 2239 | 2240 | case 0x6A: /* 6A PUSH Ib (80186+) */ 2241 | push (getmem8 (segregs[regcs], ip) ); 2242 | StepIP (1); 2243 | break; 2244 | 2245 | case 0x6B: /* 6B IMUL Gv Eb Ib (80186+) */ 2246 | modregrm(); 2247 | temp1 = readrm16 (rm); 2248 | temp2 = signext (getmem8 (segregs[regcs], ip) ); 2249 | StepIP (1); 2250 | if ( (temp1 & 0x8000L) == 0x8000L) { 2251 | temp1 = temp1 | 0xFFFF0000L; 2252 | } 2253 | 2254 | if ( (temp2 & 0x8000L) == 0x8000L) { 2255 | temp2 = temp2 | 0xFFFF0000L; 2256 | } 2257 | 2258 | temp3 = temp1 * temp2; 2259 | putreg16 (reg, temp3 & 0xFFFFL); 2260 | if (temp3 & 0xFFFF0000L) { 2261 | cf = 1; 2262 | of = 1; 2263 | } 2264 | else { 2265 | cf = 0; 2266 | of = 0; 2267 | } 2268 | break; 2269 | 2270 | case 0x6C: /* 6E INSB */ 2271 | if (reptype && (regs.wordregs[regcx] == 0) ) { 2272 | break; 2273 | } 2274 | 2275 | //putmem8 (useseg, regs.wordregs[regsi], portin (regs.wordregs[regdx]) ); 2276 | if (df) { 2277 | regs.wordregs[regsi] = regs.wordregs[regsi] - 1; 2278 | regs.wordregs[regdi] = regs.wordregs[regdi] - 1; 2279 | } 2280 | else { 2281 | regs.wordregs[regsi] = regs.wordregs[regsi] + 1; 2282 | regs.wordregs[regdi] = regs.wordregs[regdi] + 1; 2283 | } 2284 | 2285 | if (reptype) { 2286 | regs.wordregs[regcx] = regs.wordregs[regcx] - 1; 2287 | } 2288 | 2289 | totalexec++; 2290 | loopcount++; 2291 | if (!reptype) { 2292 | break; 2293 | } 2294 | 2295 | ip = firstip; 2296 | break; 2297 | 2298 | case 0x6D: /* 6F INSW */ 2299 | if (reptype && (regs.wordregs[regcx] == 0) ) { 2300 | break; 2301 | } 2302 | 2303 | //putmem16 (useseg, regs.wordregs[regsi], portin16 (regs.wordregs[regdx]) ); 2304 | if (df) { 2305 | regs.wordregs[regsi] = regs.wordregs[regsi] - 2; 2306 | regs.wordregs[regdi] = regs.wordregs[regdi] - 2; 2307 | } 2308 | else { 2309 | regs.wordregs[regsi] = regs.wordregs[regsi] + 2; 2310 | regs.wordregs[regdi] = regs.wordregs[regdi] + 2; 2311 | } 2312 | 2313 | if (reptype) { 2314 | regs.wordregs[regcx] = regs.wordregs[regcx] - 1; 2315 | } 2316 | 2317 | totalexec++; 2318 | loopcount++; 2319 | if (!reptype) { 2320 | break; 2321 | } 2322 | 2323 | ip = firstip; 2324 | break; 2325 | 2326 | case 0x6E: /* 6E OUTSB */ 2327 | if (reptype && (regs.wordregs[regcx] == 0) ) { 2328 | break; 2329 | } 2330 | 2331 | //portout (regs.wordregs[regdx], getmem8 (useseg, regs.wordregs[regsi]) ); 2332 | if (df) { 2333 | regs.wordregs[regsi] = regs.wordregs[regsi] - 1; 2334 | regs.wordregs[regdi] = regs.wordregs[regdi] - 1; 2335 | } 2336 | else { 2337 | regs.wordregs[regsi] = regs.wordregs[regsi] + 1; 2338 | regs.wordregs[regdi] = regs.wordregs[regdi] + 1; 2339 | } 2340 | 2341 | if (reptype) { 2342 | regs.wordregs[regcx] = regs.wordregs[regcx] - 1; 2343 | } 2344 | 2345 | totalexec++; 2346 | loopcount++; 2347 | if (!reptype) { 2348 | break; 2349 | } 2350 | 2351 | ip = firstip; 2352 | break; 2353 | 2354 | case 0x6F: /* 6F OUTSW */ 2355 | if (reptype && (regs.wordregs[regcx] == 0) ) { 2356 | break; 2357 | } 2358 | 2359 | //portout16 (regs.wordregs[regdx], getmem16 (useseg, regs.wordregs[regsi]) ); 2360 | if (df) { 2361 | regs.wordregs[regsi] = regs.wordregs[regsi] - 2; 2362 | regs.wordregs[regdi] = regs.wordregs[regdi] - 2; 2363 | } 2364 | else { 2365 | regs.wordregs[regsi] = regs.wordregs[regsi] + 2; 2366 | regs.wordregs[regdi] = regs.wordregs[regdi] + 2; 2367 | } 2368 | 2369 | if (reptype) { 2370 | regs.wordregs[regcx] = regs.wordregs[regcx] - 1; 2371 | } 2372 | 2373 | totalexec++; 2374 | loopcount++; 2375 | if (!reptype) { 2376 | break; 2377 | } 2378 | 2379 | ip = firstip; 2380 | break; 2381 | #endif 2382 | case 0x70: /* 70 JO Jb */ 2383 | temp16 = signext (getmem8 (segregs[regcs], ip) ); 2384 | StepIP (1); 2385 | if (of) { 2386 | ip = ip + temp16; 2387 | } 2388 | break; 2389 | 2390 | case 0x71: /* 71 JNO Jb */ 2391 | temp16 = signext (getmem8 (segregs[regcs], ip) ); 2392 | StepIP (1); 2393 | if (!of) { 2394 | ip = ip + temp16; 2395 | } 2396 | break; 2397 | 2398 | case 0x72: /* 72 JB Jb */ 2399 | temp16 = signext (getmem8 (segregs[regcs], ip) ); 2400 | StepIP (1); 2401 | if (cf) { 2402 | ip = ip + temp16; 2403 | } 2404 | break; 2405 | 2406 | case 0x73: /* 73 JNB Jb */ 2407 | temp16 = signext (getmem8 (segregs[regcs], ip) ); 2408 | StepIP (1); 2409 | if (!cf) { 2410 | ip = ip + temp16; 2411 | } 2412 | break; 2413 | 2414 | case 0x74: /* 74 JZ Jb */ 2415 | temp16 = signext (getmem8 (segregs[regcs], ip) ); 2416 | StepIP (1); 2417 | if (zf) { 2418 | ip = ip + temp16; 2419 | } 2420 | break; 2421 | 2422 | case 0x75: /* 75 JNZ Jb */ 2423 | temp16 = signext (getmem8 (segregs[regcs], ip) ); 2424 | StepIP (1); 2425 | if (!zf) { 2426 | ip = ip + temp16; 2427 | } 2428 | break; 2429 | 2430 | case 0x76: /* 76 JBE Jb */ 2431 | temp16 = signext (getmem8 (segregs[regcs], ip) ); 2432 | StepIP (1); 2433 | if (cf || zf) { 2434 | ip = ip + temp16; 2435 | } 2436 | break; 2437 | 2438 | case 0x77: /* 77 JA Jb */ 2439 | temp16 = signext (getmem8 (segregs[regcs], ip) ); 2440 | StepIP (1); 2441 | if (!cf && !zf) { 2442 | ip = ip + temp16; 2443 | } 2444 | break; 2445 | 2446 | case 0x78: /* 78 JS Jb */ 2447 | temp16 = signext (getmem8 (segregs[regcs], ip) ); 2448 | StepIP (1); 2449 | if (sf) { 2450 | ip = ip + temp16; 2451 | } 2452 | break; 2453 | 2454 | case 0x79: /* 79 JNS Jb */ 2455 | temp16 = signext (getmem8 (segregs[regcs], ip) ); 2456 | StepIP (1); 2457 | if (!sf) { 2458 | ip = ip + temp16; 2459 | } 2460 | break; 2461 | 2462 | case 0x7A: /* 7A JPE Jb */ 2463 | temp16 = signext (getmem8 (segregs[regcs], ip) ); 2464 | StepIP (1); 2465 | if (pf) { 2466 | ip = ip + temp16; 2467 | } 2468 | break; 2469 | 2470 | case 0x7B: /* 7B JPO Jb */ 2471 | temp16 = signext (getmem8 (segregs[regcs], ip) ); 2472 | StepIP (1); 2473 | if (!pf) { 2474 | ip = ip + temp16; 2475 | } 2476 | break; 2477 | 2478 | case 0x7C: /* 7C JL Jb */ 2479 | temp16 = signext (getmem8 (segregs[regcs], ip) ); 2480 | StepIP (1); 2481 | if (sf != of) { 2482 | ip = ip + temp16; 2483 | } 2484 | break; 2485 | 2486 | case 0x7D: /* 7D JGE Jb */ 2487 | temp16 = signext (getmem8 (segregs[regcs], ip) ); 2488 | StepIP (1); 2489 | if (sf == of) { 2490 | ip = ip + temp16; 2491 | } 2492 | break; 2493 | 2494 | case 0x7E: /* 7E JLE Jb */ 2495 | temp16 = signext (getmem8 (segregs[regcs], ip) ); 2496 | StepIP (1); 2497 | if ( (sf != of) || zf) { 2498 | ip = ip + temp16; 2499 | } 2500 | break; 2501 | 2502 | case 0x7F: /* 7F JG Jb */ 2503 | temp16 = signext (getmem8 (segregs[regcs], ip) ); 2504 | StepIP (1); 2505 | if (!zf && (sf == of) ) { 2506 | ip = ip + temp16; 2507 | } 2508 | break; 2509 | 2510 | case 0x80: 2511 | case 0x82: /* 80/82 GRP1 Eb Ib */ 2512 | modregrm(); 2513 | oper1b = readrm8 (rm); 2514 | oper2b = getmem8 (segregs[regcs], ip); 2515 | StepIP (1); 2516 | switch (reg) { 2517 | case 0: 2518 | op_add8(); 2519 | break; 2520 | case 1: 2521 | op_or8(); 2522 | break; 2523 | case 2: 2524 | op_adc8(); 2525 | break; 2526 | case 3: 2527 | op_sbb8(); 2528 | break; 2529 | case 4: 2530 | op_and8(); 2531 | break; 2532 | case 5: 2533 | op_sub8(); 2534 | break; 2535 | case 6: 2536 | op_xor8(); 2537 | break; 2538 | case 7: 2539 | flag_sub8 (oper1b, oper2b); 2540 | break; 2541 | default: 2542 | break; /* to avoid compiler warnings */ 2543 | } 2544 | 2545 | if (reg < 7) { 2546 | writerm8 (rm, res8); 2547 | } 2548 | break; 2549 | 2550 | case 0x81: /* 81 GRP1 Ev Iv */ 2551 | case 0x83: /* 83 GRP1 Ev Ib */ 2552 | modregrm(); 2553 | oper1 = readrm16 (rm); 2554 | if (opcode == 0x81) { 2555 | oper2 = getmem16 (segregs[regcs], ip); 2556 | StepIP (2); 2557 | } 2558 | else { 2559 | oper2 = signext (getmem8 (segregs[regcs], ip) ); 2560 | StepIP (1); 2561 | } 2562 | 2563 | switch (reg) { 2564 | case 0: 2565 | op_add16(); 2566 | break; 2567 | case 1: 2568 | op_or16(); 2569 | break; 2570 | case 2: 2571 | op_adc16(); 2572 | break; 2573 | case 3: 2574 | op_sbb16(); 2575 | break; 2576 | case 4: 2577 | op_and16(); 2578 | break; 2579 | case 5: 2580 | op_sub16(); 2581 | break; 2582 | case 6: 2583 | op_xor16(); 2584 | break; 2585 | case 7: 2586 | flag_sub16 (oper1, oper2); 2587 | break; 2588 | default: 2589 | break; /* to avoid compiler warnings */ 2590 | } 2591 | 2592 | if (reg < 7) { 2593 | writerm16 (rm, res16); 2594 | } 2595 | break; 2596 | 2597 | case 0x84: /* 84 TEST Gb Eb */ 2598 | modregrm(); 2599 | oper1b = getreg8 (reg); 2600 | oper2b = readrm8 (rm); 2601 | flag_log8 (oper1b & oper2b); 2602 | break; 2603 | 2604 | case 0x85: /* 85 TEST Gv Ev */ 2605 | modregrm(); 2606 | oper1 = getreg16 (reg); 2607 | oper2 = readrm16 (rm); 2608 | flag_log16 (oper1 & oper2); 2609 | break; 2610 | 2611 | case 0x86: /* 86 XCHG Gb Eb */ 2612 | modregrm(); 2613 | oper1b = getreg8 (reg); 2614 | putreg8 (reg, readrm8 (rm) ); 2615 | writerm8 (rm, oper1b); 2616 | break; 2617 | 2618 | case 0x87: /* 87 XCHG Gv Ev */ 2619 | modregrm(); 2620 | oper1 = getreg16 (reg); 2621 | putreg16 (reg, readrm16 (rm) ); 2622 | writerm16 (rm, oper1); 2623 | break; 2624 | 2625 | case 0x88: /* 88 MOV Eb Gb */ 2626 | modregrm(); 2627 | writerm8 (rm, getreg8 (reg) ); 2628 | break; 2629 | 2630 | case 0x89: /* 89 MOV Ev Gv */ 2631 | modregrm(); 2632 | writerm16 (rm, getreg16 (reg) ); 2633 | break; 2634 | 2635 | case 0x8A: /* 8A MOV Gb Eb */ 2636 | modregrm(); 2637 | putreg8 (reg, readrm8 (rm) ); 2638 | break; 2639 | 2640 | case 0x8B: /* 8B MOV Gv Ev */ 2641 | modregrm(); 2642 | putreg16 (reg, readrm16 (rm) ); 2643 | break; 2644 | 2645 | case 0x8C: /* 8C MOV Ew Sw */ 2646 | modregrm(); 2647 | writerm16 (rm, getsegreg (reg) ); 2648 | break; 2649 | 2650 | case 0x8D: /* 8D LEA Gv M */ 2651 | modregrm(); 2652 | getea (rm); 2653 | putreg16 (reg, ea - segbase (useseg) ); 2654 | break; 2655 | 2656 | case 0x8E: /* 8E MOV Sw Ew */ 2657 | modregrm(); 2658 | putsegreg (reg, readrm16 (rm) ); 2659 | break; 2660 | 2661 | case 0x8F: /* 8F POP Ev */ 2662 | modregrm(); 2663 | writerm16 (rm, pop() ); 2664 | break; 2665 | 2666 | case 0x90: /* 90 NOP */ 2667 | break; 2668 | 2669 | case 0x91: /* 91 XCHG eCX eAX */ 2670 | oper1 = regs.wordregs[regcx]; 2671 | regs.wordregs[regcx] = regs.wordregs[regax]; 2672 | regs.wordregs[regax] = oper1; 2673 | break; 2674 | 2675 | case 0x92: /* 92 XCHG eDX eAX */ 2676 | oper1 = regs.wordregs[regdx]; 2677 | regs.wordregs[regdx] = regs.wordregs[regax]; 2678 | regs.wordregs[regax] = oper1; 2679 | break; 2680 | 2681 | case 0x93: /* 93 XCHG eBX eAX */ 2682 | oper1 = regs.wordregs[regbx]; 2683 | regs.wordregs[regbx] = regs.wordregs[regax]; 2684 | regs.wordregs[regax] = oper1; 2685 | break; 2686 | 2687 | case 0x94: /* 94 XCHG eSP eAX */ 2688 | oper1 = regs.wordregs[regsp]; 2689 | regs.wordregs[regsp] = regs.wordregs[regax]; 2690 | regs.wordregs[regax] = oper1; 2691 | break; 2692 | 2693 | case 0x95: /* 95 XCHG eBP eAX */ 2694 | oper1 = regs.wordregs[regbp]; 2695 | regs.wordregs[regbp] = regs.wordregs[regax]; 2696 | regs.wordregs[regax] = oper1; 2697 | break; 2698 | 2699 | case 0x96: /* 96 XCHG eSI eAX */ 2700 | oper1 = regs.wordregs[regsi]; 2701 | regs.wordregs[regsi] = regs.wordregs[regax]; 2702 | regs.wordregs[regax] = oper1; 2703 | break; 2704 | 2705 | case 0x97: /* 97 XCHG eDI eAX */ 2706 | oper1 = regs.wordregs[regdi]; 2707 | regs.wordregs[regdi] = regs.wordregs[regax]; 2708 | regs.wordregs[regax] = oper1; 2709 | break; 2710 | 2711 | case 0x98: /* 98 CBW */ 2712 | if ( (regs.byteregs[regal] & 0x80) == 0x80) { 2713 | regs.byteregs[regah] = 0xFF; 2714 | } 2715 | else { 2716 | regs.byteregs[regah] = 0; 2717 | } 2718 | break; 2719 | 2720 | case 0x99: /* 99 CWD */ 2721 | if ( (regs.byteregs[regah] & 0x80) == 0x80) { 2722 | regs.wordregs[regdx] = 0xFFFF; 2723 | } 2724 | else { 2725 | regs.wordregs[regdx] = 0; 2726 | } 2727 | break; 2728 | 2729 | case 0x9A: /* 9A CALL Ap */ 2730 | oper1 = getmem16 (segregs[regcs], ip); 2731 | StepIP (2); 2732 | oper2 = getmem16 (segregs[regcs], ip); 2733 | StepIP (2); 2734 | push (segregs[regcs]); 2735 | push (ip); 2736 | ip = oper1; 2737 | segregs[regcs] = oper2; 2738 | break; 2739 | 2740 | case 0x9B: /* 9B WAIT */ 2741 | break; 2742 | 2743 | case 0x9C: /* 9C PUSHF */ 2744 | push (makeflagsword() | 0x0800); 2745 | break; 2746 | 2747 | case 0x9D: /* 9D POPF */ 2748 | temp16 = pop(); 2749 | decodeflagsword (temp16); 2750 | break; 2751 | 2752 | case 0x9E: /* 9E SAHF */ 2753 | decodeflagsword ( (makeflagsword() & 0xFF00) | regs.byteregs[regah]); 2754 | break; 2755 | 2756 | case 0x9F: /* 9F LAHF */ 2757 | regs.byteregs[regah] = makeflagsword() & 0xFF; 2758 | break; 2759 | 2760 | case 0xA0: /* A0 MOV regs.byteregs[regal] Ob */ 2761 | regs.byteregs[regal] = getmem8 (useseg, getmem16 (segregs[regcs], ip) ); 2762 | StepIP (2); 2763 | break; 2764 | 2765 | case 0xA1: /* A1 MOV eAX Ov */ 2766 | oper1 = getmem16 (useseg, getmem16 (segregs[regcs], ip) ); 2767 | StepIP (2); 2768 | regs.wordregs[regax] = oper1; 2769 | break; 2770 | 2771 | case 0xA2: /* A2 MOV Ob regs.byteregs[regal] */ 2772 | putmem8 (useseg, getmem16 (segregs[regcs], ip), regs.byteregs[regal]); 2773 | StepIP (2); 2774 | break; 2775 | 2776 | case 0xA3: /* A3 MOV Ov eAX */ 2777 | putmem16 (useseg, getmem16 (segregs[regcs], ip), regs.wordregs[regax]); 2778 | StepIP (2); 2779 | break; 2780 | 2781 | case 0xA4: /* A4 MOVSB */ 2782 | if (reptype && (regs.wordregs[regcx] == 0) ) { 2783 | break; 2784 | } 2785 | 2786 | putmem8 (segregs[reges], regs.wordregs[regdi], getmem8 (useseg, regs.wordregs[regsi]) ); 2787 | if (df) { 2788 | regs.wordregs[regsi] = regs.wordregs[regsi] - 1; 2789 | regs.wordregs[regdi] = regs.wordregs[regdi] - 1; 2790 | } 2791 | else { 2792 | regs.wordregs[regsi] = regs.wordregs[regsi] + 1; 2793 | regs.wordregs[regdi] = regs.wordregs[regdi] + 1; 2794 | } 2795 | 2796 | if (reptype) { 2797 | regs.wordregs[regcx] = regs.wordregs[regcx] - 1; 2798 | } 2799 | 2800 | totalexec++; 2801 | loopcount++; 2802 | if (!reptype) { 2803 | break; 2804 | } 2805 | 2806 | ip = firstip; 2807 | break; 2808 | 2809 | case 0xA5: /* A5 MOVSW */ 2810 | if (reptype && (regs.wordregs[regcx] == 0) ) { 2811 | break; 2812 | } 2813 | 2814 | putmem16 (segregs[reges], regs.wordregs[regdi], getmem16 (useseg, regs.wordregs[regsi]) ); 2815 | if (df) { 2816 | regs.wordregs[regsi] = regs.wordregs[regsi] - 2; 2817 | regs.wordregs[regdi] = regs.wordregs[regdi] - 2; 2818 | } 2819 | else { 2820 | regs.wordregs[regsi] = regs.wordregs[regsi] + 2; 2821 | regs.wordregs[regdi] = regs.wordregs[regdi] + 2; 2822 | } 2823 | 2824 | if (reptype) { 2825 | regs.wordregs[regcx] = regs.wordregs[regcx] - 1; 2826 | } 2827 | 2828 | totalexec++; 2829 | loopcount++; 2830 | if (!reptype) { 2831 | break; 2832 | } 2833 | 2834 | ip = firstip; 2835 | break; 2836 | 2837 | case 0xA6: /* A6 CMPSB */ 2838 | if (reptype && (regs.wordregs[regcx] == 0) ) { 2839 | break; 2840 | } 2841 | 2842 | oper1b = getmem8 (useseg, regs.wordregs[regsi]); 2843 | oper2b = getmem8 (segregs[reges], regs.wordregs[regdi]); 2844 | if (df) { 2845 | regs.wordregs[regsi] = regs.wordregs[regsi] - 1; 2846 | regs.wordregs[regdi] = regs.wordregs[regdi] - 1; 2847 | } 2848 | else { 2849 | regs.wordregs[regsi] = regs.wordregs[regsi] + 1; 2850 | regs.wordregs[regdi] = regs.wordregs[regdi] + 1; 2851 | } 2852 | 2853 | flag_sub8 (oper1b, oper2b); 2854 | if (reptype) { 2855 | regs.wordregs[regcx] = regs.wordregs[regcx] - 1; 2856 | } 2857 | 2858 | if ( (reptype == 1) && !zf) { 2859 | break; 2860 | } 2861 | else if ( (reptype == 2) && (zf == 1) ) { 2862 | break; 2863 | } 2864 | 2865 | totalexec++; 2866 | loopcount++; 2867 | if (!reptype) { 2868 | break; 2869 | } 2870 | 2871 | ip = firstip; 2872 | break; 2873 | 2874 | case 0xA7: /* A7 CMPSW */ 2875 | if (reptype && (regs.wordregs[regcx] == 0) ) { 2876 | break; 2877 | } 2878 | 2879 | oper1 = getmem16 (useseg,regs.wordregs[regsi]); 2880 | oper2 = getmem16 (segregs[reges], regs.wordregs[regdi]); 2881 | if (df) { 2882 | regs.wordregs[regsi] = regs.wordregs[regsi] - 2; 2883 | regs.wordregs[regdi] = regs.wordregs[regdi] - 2; 2884 | } 2885 | else { 2886 | regs.wordregs[regsi] = regs.wordregs[regsi] + 2; 2887 | regs.wordregs[regdi] = regs.wordregs[regdi] + 2; 2888 | } 2889 | 2890 | flag_sub16 (oper1, oper2); 2891 | if (reptype) { 2892 | regs.wordregs[regcx] = regs.wordregs[regcx] - 1; 2893 | } 2894 | 2895 | if ( (reptype == 1) && !zf) { 2896 | break; 2897 | } 2898 | 2899 | if ( (reptype == 2) && (zf == 1) ) { 2900 | break; 2901 | } 2902 | 2903 | totalexec++; 2904 | loopcount++; 2905 | if (!reptype) { 2906 | break; 2907 | } 2908 | 2909 | ip = firstip; 2910 | break; 2911 | 2912 | case 0xA8: /* A8 TEST regs.byteregs[regal] Ib */ 2913 | oper1b = regs.byteregs[regal]; 2914 | oper2b = getmem8 (segregs[regcs], ip); 2915 | StepIP (1); 2916 | flag_log8 (oper1b & oper2b); 2917 | break; 2918 | 2919 | case 0xA9: /* A9 TEST eAX Iv */ 2920 | oper1 = regs.wordregs[regax]; 2921 | oper2 = getmem16 (segregs[regcs], ip); 2922 | StepIP (2); 2923 | flag_log16 (oper1 & oper2); 2924 | break; 2925 | 2926 | case 0xAA: /* AA STOSB */ 2927 | if (reptype && (regs.wordregs[regcx] == 0) ) { 2928 | break; 2929 | } 2930 | 2931 | putmem8 (segregs[reges], regs.wordregs[regdi], regs.byteregs[regal]); 2932 | if (df) { 2933 | regs.wordregs[regdi] = regs.wordregs[regdi] - 1; 2934 | } 2935 | else { 2936 | regs.wordregs[regdi] = regs.wordregs[regdi] + 1; 2937 | } 2938 | 2939 | if (reptype) { 2940 | regs.wordregs[regcx] = regs.wordregs[regcx] - 1; 2941 | } 2942 | 2943 | totalexec++; 2944 | loopcount++; 2945 | if (!reptype) { 2946 | break; 2947 | } 2948 | 2949 | ip = firstip; 2950 | break; 2951 | 2952 | case 0xAB: /* AB STOSW */ 2953 | if (reptype && (regs.wordregs[regcx] == 0) ) { 2954 | break; 2955 | } 2956 | 2957 | putmem16 (segregs[reges], regs.wordregs[regdi], regs.wordregs[regax]); 2958 | if (df) { 2959 | regs.wordregs[regdi] = regs.wordregs[regdi] - 2; 2960 | } 2961 | else { 2962 | regs.wordregs[regdi] = regs.wordregs[regdi] + 2; 2963 | } 2964 | 2965 | if (reptype) { 2966 | regs.wordregs[regcx] = regs.wordregs[regcx] - 1; 2967 | } 2968 | 2969 | totalexec++; 2970 | loopcount++; 2971 | if (!reptype) { 2972 | break; 2973 | } 2974 | 2975 | ip = firstip; 2976 | break; 2977 | 2978 | case 0xAC: /* AC LODSB */ 2979 | if (reptype && (regs.wordregs[regcx] == 0) ) { 2980 | break; 2981 | } 2982 | 2983 | regs.byteregs[regal] = getmem8 (useseg, regs.wordregs[regsi]); 2984 | if (df) { 2985 | regs.wordregs[regsi] = regs.wordregs[regsi] - 1; 2986 | } 2987 | else { 2988 | regs.wordregs[regsi] = regs.wordregs[regsi] + 1; 2989 | } 2990 | 2991 | if (reptype) { 2992 | regs.wordregs[regcx] = regs.wordregs[regcx] - 1; 2993 | } 2994 | 2995 | totalexec++; 2996 | loopcount++; 2997 | if (!reptype) { 2998 | break; 2999 | } 3000 | 3001 | ip = firstip; 3002 | break; 3003 | 3004 | case 0xAD: /* AD LODSW */ 3005 | if (reptype && (regs.wordregs[regcx] == 0) ) { 3006 | break; 3007 | } 3008 | 3009 | oper1 = getmem16 (useseg, regs.wordregs[regsi]); 3010 | regs.wordregs[regax] = oper1; 3011 | if (df) { 3012 | regs.wordregs[regsi] = regs.wordregs[regsi] - 2; 3013 | } 3014 | else { 3015 | regs.wordregs[regsi] = regs.wordregs[regsi] + 2; 3016 | } 3017 | 3018 | if (reptype) { 3019 | regs.wordregs[regcx] = regs.wordregs[regcx] - 1; 3020 | } 3021 | 3022 | totalexec++; 3023 | loopcount++; 3024 | if (!reptype) { 3025 | break; 3026 | } 3027 | 3028 | ip = firstip; 3029 | break; 3030 | 3031 | case 0xAE: /* AE SCASB */ 3032 | if (reptype && (regs.wordregs[regcx] == 0) ) { 3033 | break; 3034 | } 3035 | 3036 | oper1b = regs.byteregs[regal]; 3037 | oper2b = getmem8 (segregs[reges], regs.wordregs[regdi]); 3038 | flag_sub8 (oper1b, oper2b); 3039 | if (df) { 3040 | regs.wordregs[regdi] = regs.wordregs[regdi] - 1; 3041 | } 3042 | else { 3043 | regs.wordregs[regdi] = regs.wordregs[regdi] + 1; 3044 | } 3045 | 3046 | if (reptype) { 3047 | regs.wordregs[regcx] = regs.wordregs[regcx] - 1; 3048 | } 3049 | 3050 | if ( (reptype == 1) && !zf) { 3051 | break; 3052 | } 3053 | else if ( (reptype == 2) && (zf == 1) ) { 3054 | break; 3055 | } 3056 | 3057 | totalexec++; 3058 | loopcount++; 3059 | if (!reptype) { 3060 | break; 3061 | } 3062 | 3063 | ip = firstip; 3064 | break; 3065 | 3066 | case 0xAF: /* AF SCASW */ 3067 | if (reptype && (regs.wordregs[regcx] == 0) ) { 3068 | break; 3069 | } 3070 | 3071 | oper1 = regs.wordregs[regax]; 3072 | oper2 = getmem16 (segregs[reges], regs.wordregs[regdi]); 3073 | flag_sub16 (oper1, oper2); 3074 | if (df) { 3075 | regs.wordregs[regdi] = regs.wordregs[regdi] - 2; 3076 | } 3077 | else { 3078 | regs.wordregs[regdi] = regs.wordregs[regdi] + 2; 3079 | } 3080 | 3081 | if (reptype) { 3082 | regs.wordregs[regcx] = regs.wordregs[regcx] - 1; 3083 | } 3084 | 3085 | if ( (reptype == 1) && !zf) { 3086 | break; 3087 | } 3088 | else if ( (reptype == 2) & (zf == 1) ) { 3089 | break; 3090 | } 3091 | 3092 | totalexec++; 3093 | loopcount++; 3094 | if (!reptype) { 3095 | break; 3096 | } 3097 | 3098 | ip = firstip; 3099 | break; 3100 | 3101 | case 0xB0: /* B0 MOV regs.byteregs[regal] Ib */ 3102 | regs.byteregs[regal] = getmem8 (segregs[regcs], ip); 3103 | StepIP (1); 3104 | break; 3105 | 3106 | case 0xB1: /* B1 MOV regs.byteregs[regcl] Ib */ 3107 | regs.byteregs[regcl] = getmem8 (segregs[regcs], ip); 3108 | StepIP (1); 3109 | break; 3110 | 3111 | case 0xB2: /* B2 MOV regs.byteregs[regdl] Ib */ 3112 | regs.byteregs[regdl] = getmem8 (segregs[regcs], ip); 3113 | StepIP (1); 3114 | break; 3115 | 3116 | case 0xB3: /* B3 MOV regs.byteregs[regbl] Ib */ 3117 | regs.byteregs[regbl] = getmem8 (segregs[regcs], ip); 3118 | StepIP (1); 3119 | break; 3120 | 3121 | case 0xB4: /* B4 MOV regs.byteregs[regah] Ib */ 3122 | regs.byteregs[regah] = getmem8 (segregs[regcs], ip); 3123 | StepIP (1); 3124 | break; 3125 | 3126 | case 0xB5: /* B5 MOV regs.byteregs[regch] Ib */ 3127 | regs.byteregs[regch] = getmem8 (segregs[regcs], ip); 3128 | StepIP (1); 3129 | break; 3130 | 3131 | case 0xB6: /* B6 MOV regs.byteregs[regdh] Ib */ 3132 | regs.byteregs[regdh] = getmem8 (segregs[regcs], ip); 3133 | StepIP (1); 3134 | break; 3135 | 3136 | case 0xB7: /* B7 MOV regs.byteregs[regbh] Ib */ 3137 | regs.byteregs[regbh] = getmem8 (segregs[regcs], ip); 3138 | StepIP (1); 3139 | break; 3140 | 3141 | case 0xB8: /* B8 MOV eAX Iv */ 3142 | oper1 = getmem16 (segregs[regcs], ip); 3143 | StepIP (2); 3144 | regs.wordregs[regax] = oper1; 3145 | break; 3146 | 3147 | case 0xB9: /* B9 MOV eCX Iv */ 3148 | oper1 = getmem16 (segregs[regcs], ip); 3149 | StepIP (2); 3150 | regs.wordregs[regcx] = oper1; 3151 | break; 3152 | 3153 | case 0xBA: /* BA MOV eDX Iv */ 3154 | oper1 = getmem16 (segregs[regcs], ip); 3155 | StepIP (2); 3156 | regs.wordregs[regdx] = oper1; 3157 | break; 3158 | 3159 | case 0xBB: /* BB MOV eBX Iv */ 3160 | oper1 = getmem16 (segregs[regcs], ip); 3161 | StepIP (2); 3162 | regs.wordregs[regbx] = oper1; 3163 | break; 3164 | 3165 | case 0xBC: /* BC MOV eSP Iv */ 3166 | regs.wordregs[regsp] = getmem16 (segregs[regcs], ip); 3167 | StepIP (2); 3168 | break; 3169 | 3170 | case 0xBD: /* BD MOV eBP Iv */ 3171 | regs.wordregs[regbp] = getmem16 (segregs[regcs], ip); 3172 | StepIP (2); 3173 | break; 3174 | 3175 | case 0xBE: /* BE MOV eSI Iv */ 3176 | regs.wordregs[regsi] = getmem16 (segregs[regcs], ip); 3177 | StepIP (2); 3178 | break; 3179 | 3180 | case 0xBF: /* BF MOV eDI Iv */ 3181 | regs.wordregs[regdi] = getmem16 (segregs[regcs], ip); 3182 | StepIP (2); 3183 | break; 3184 | 3185 | case 0xC0: /* C0 GRP2 byte imm8 (80186+) */ 3186 | modregrm(); 3187 | oper1b = readrm8 (rm); 3188 | oper2b = getmem8 (segregs[regcs], ip); 3189 | StepIP (1); 3190 | writerm8 (rm, op_grp2_8 (oper2b) ); 3191 | break; 3192 | 3193 | case 0xC1: /* C1 GRP2 word imm8 (80186+) */ 3194 | modregrm(); 3195 | oper1 = readrm16 (rm); 3196 | oper2 = getmem8 (segregs[regcs], ip); 3197 | StepIP (1); 3198 | writerm16 (rm, op_grp2_16 ( (byte) oper2) ); 3199 | break; 3200 | 3201 | case 0xC2: /* C2 RET Iw */ 3202 | oper1 = getmem16 (segregs[regcs], ip); 3203 | ip = pop(); 3204 | regs.wordregs[regsp] = regs.wordregs[regsp] + oper1; 3205 | break; 3206 | 3207 | case 0xC3: /* C3 RET */ 3208 | ip = pop(); 3209 | break; 3210 | 3211 | case 0xC4: /* C4 LES Gv Mp */ 3212 | modregrm(); 3213 | getea (rm); 3214 | putreg16 (reg, read86 (ea) + read86 (ea + 1) * 256); 3215 | segregs[reges] = read86 (ea + 2) + read86 (ea + 3) * 256; 3216 | break; 3217 | 3218 | case 0xC5: /* C5 LDS Gv Mp */ 3219 | modregrm(); 3220 | getea (rm); 3221 | putreg16 (reg, read86 (ea) + read86 (ea + 1) * 256); 3222 | segregs[regds] = read86 (ea + 2) + read86 (ea + 3) * 256; 3223 | break; 3224 | 3225 | case 0xC6: /* C6 MOV Eb Ib */ 3226 | modregrm(); 3227 | writerm8 (rm, getmem8 (segregs[regcs], ip) ); 3228 | StepIP (1); 3229 | break; 3230 | 3231 | case 0xC7: /* C7 MOV Ev Iv */ 3232 | modregrm(); 3233 | writerm16 (rm, getmem16 (segregs[regcs], ip) ); 3234 | StepIP (2); 3235 | break; 3236 | 3237 | case 0xC8: /* C8 ENTER (80186+) */ 3238 | stacksize = getmem16 (segregs[regcs], ip); 3239 | StepIP (2); 3240 | nestlev = getmem8 (segregs[regcs], ip); 3241 | StepIP (1); 3242 | push (regs.wordregs[regbp]); 3243 | frametemp = regs.wordregs[regsp]; 3244 | if (nestlev) { 3245 | for (temp16 = 1; temp16 < nestlev; temp16++) { 3246 | regs.wordregs[regbp] = regs.wordregs[regbp] - 2; 3247 | push (regs.wordregs[regbp]); 3248 | } 3249 | 3250 | push (regs.wordregs[regsp]); 3251 | } 3252 | 3253 | regs.wordregs[regbp] = frametemp; 3254 | regs.wordregs[regsp] = regs.wordregs[regbp] - stacksize; 3255 | 3256 | break; 3257 | 3258 | case 0xC9: /* C9 LEAVE (80186+) */ 3259 | regs.wordregs[regsp] = regs.wordregs[regbp]; 3260 | regs.wordregs[regbp] = pop(); 3261 | break; 3262 | 3263 | case 0xCA: /* CA RETF Iw */ 3264 | oper1 = getmem16 (segregs[regcs], ip); 3265 | ip = pop(); 3266 | segregs[regcs] = pop(); 3267 | regs.wordregs[regsp] = regs.wordregs[regsp] + oper1; 3268 | break; 3269 | 3270 | case 0xCB: /* CB RETF */ 3271 | ip = pop();; 3272 | segregs[regcs] = pop(); 3273 | break; 3274 | 3275 | case 0xCC: /* CC INT 3 */ 3276 | intcall86 (3); 3277 | break; 3278 | 3279 | case 0xCD: /* CD INT Ib */ 3280 | oper1b = getmem8 (segregs[regcs], ip); 3281 | StepIP (1); 3282 | intcall86 (oper1b); 3283 | break; 3284 | 3285 | case 0xCE: /* CE INTO */ 3286 | if (of) { 3287 | intcall86 (4); 3288 | } 3289 | break; 3290 | 3291 | case 0xCF: /* CF IRET */ 3292 | ip = pop(); 3293 | segregs[regcs] = pop(); 3294 | decodeflagsword (pop() ); 3295 | 3296 | /* 3297 | * if (net.enabled) net.canrecv = 1; 3298 | */ 3299 | break; 3300 | 3301 | case 0xD0: /* D0 GRP2 Eb 1 */ 3302 | modregrm(); 3303 | oper1b = readrm8 (rm); 3304 | writerm8 (rm, op_grp2_8 (1) ); 3305 | break; 3306 | 3307 | case 0xD1: /* D1 GRP2 Ev 1 */ 3308 | modregrm(); 3309 | oper1 = readrm16 (rm); 3310 | writerm16 (rm, op_grp2_16 (1) ); 3311 | break; 3312 | 3313 | case 0xD2: /* D2 GRP2 Eb regs.byteregs[regcl] */ 3314 | modregrm(); 3315 | oper1b = readrm8 (rm); 3316 | writerm8 (rm, op_grp2_8 (regs.byteregs[regcl]) ); 3317 | break; 3318 | 3319 | case 0xD3: /* D3 GRP2 Ev regs.byteregs[regcl] */ 3320 | modregrm(); 3321 | oper1 = readrm16 (rm); 3322 | writerm16 (rm, op_grp2_16 (regs.byteregs[regcl]) ); 3323 | break; 3324 | 3325 | case 0xD4: /* D4 AAM I0 */ 3326 | oper1 = getmem8 (segregs[regcs], ip); 3327 | StepIP (1); 3328 | if (!oper1) { 3329 | intcall86 (0); 3330 | break; 3331 | } /* division by zero */ 3332 | 3333 | regs.byteregs[regah] = (regs.byteregs[regal] / oper1) & 255; 3334 | regs.byteregs[regal] = (regs.byteregs[regal] % oper1) & 255; 3335 | flag_szp16 (regs.wordregs[regax]); 3336 | break; 3337 | 3338 | case 0xD5: /* D5 AAD I0 */ 3339 | oper1 = getmem8 (segregs[regcs], ip); 3340 | StepIP (1); 3341 | regs.byteregs[regal] = (regs.byteregs[regah] * oper1 + regs.byteregs[regal]) & 255; 3342 | regs.byteregs[regah] = 0; 3343 | flag_szp16 (regs.byteregs[regah] * oper1 + regs.byteregs[regal]); 3344 | sf = 0; 3345 | break; 3346 | 3347 | case 0xD6: /* D6 XLAT on V20/V30, SALC on 8086/8088 */ 3348 | regs.byteregs[regal] = cf ? 0xFF : 0x00; 3349 | break; 3350 | 3351 | case 0xD7: /* D7 XLAT */ 3352 | regs.byteregs[regal] = read86(useseg * 16 + (regs.wordregs[regbx]) + regs.byteregs[regal]); 3353 | break; 3354 | 3355 | case 0xD8: 3356 | case 0xD9: 3357 | case 0xDA: 3358 | case 0xDB: 3359 | case 0xDC: 3360 | case 0xDE: 3361 | case 0xDD: 3362 | case 0xDF: /* escape to x87 FPU (unsupported) */ 3363 | modregrm(); 3364 | break; 3365 | 3366 | case 0xE0: /* E0 LOOPNZ Jb */ 3367 | temp16 = signext (getmem8 (segregs[regcs], ip) ); 3368 | StepIP (1); 3369 | regs.wordregs[regcx] = regs.wordregs[regcx] - 1; 3370 | if ( (regs.wordregs[regcx]) && !zf) { 3371 | ip = ip + temp16; 3372 | } 3373 | break; 3374 | 3375 | case 0xE1: /* E1 LOOPZ Jb */ 3376 | temp16 = signext (getmem8 (segregs[regcs], ip) ); 3377 | StepIP (1); 3378 | regs.wordregs[regcx] = regs.wordregs[regcx] - 1; 3379 | if (regs.wordregs[regcx] && (zf == 1) ) { 3380 | ip = ip + temp16; 3381 | } 3382 | break; 3383 | 3384 | case 0xE2: /* E2 LOOP Jb */ 3385 | temp16 = signext (getmem8 (segregs[regcs], ip) ); 3386 | StepIP (1); 3387 | regs.wordregs[regcx] = regs.wordregs[regcx] - 1; 3388 | if (regs.wordregs[regcx]) { 3389 | ip = ip + temp16; 3390 | } 3391 | break; 3392 | 3393 | case 0xE3: /* E3 JCXZ Jb */ 3394 | temp16 = signext (getmem8 (segregs[regcs], ip) ); 3395 | StepIP (1); 3396 | if (!regs.wordregs[regcx]) { 3397 | ip = ip + temp16; 3398 | } 3399 | break; 3400 | 3401 | case 0xE4: /* E4 IN regs.byteregs[regal] Ib */ 3402 | oper1b = getmem8 (segregs[regcs], ip); 3403 | StepIP (1); 3404 | // regs.byteregs[regal] = (byte) portin (oper1b); 3405 | break; 3406 | 3407 | case 0xE5: /* E5 IN eAX Ib */ 3408 | oper1b = getmem8 (segregs[regcs], ip); 3409 | StepIP (1); 3410 | //regs.wordregs[regax] = portin16 (oper1b); 3411 | break; 3412 | 3413 | case 0xE6: /* E6 OUT Ib regs.byteregs[regal] */ 3414 | oper1b = getmem8 (segregs[regcs], ip); 3415 | StepIP (1); 3416 | //portout (oper1b, regs.byteregs[regal]); 3417 | break; 3418 | 3419 | case 0xE7: /* E7 OUT Ib eAX */ 3420 | oper1b = getmem8 (segregs[regcs], ip); 3421 | StepIP (1); 3422 | //portout16 (oper1b, regs.wordregs[regax]); 3423 | break; 3424 | 3425 | case 0xE8: /* E8 CALL Jv */ 3426 | oper1 = getmem16 (segregs[regcs], ip); 3427 | StepIP (2); 3428 | push (ip); 3429 | ip = ip + oper1; 3430 | break; 3431 | 3432 | case 0xE9: /* E9 JMP Jv */ 3433 | oper1 = getmem16 (segregs[regcs], ip); 3434 | StepIP (2); 3435 | ip = ip + oper1; 3436 | break; 3437 | 3438 | case 0xEA: /* EA JMP Ap */ 3439 | oper1 = getmem16 (segregs[regcs], ip); 3440 | StepIP (2); 3441 | oper2 = getmem16 (segregs[regcs], ip); 3442 | ip = oper1; 3443 | segregs[regcs] = oper2; 3444 | break; 3445 | 3446 | case 0xEB: /* EB JMP Jb */ 3447 | oper1 = signext (getmem8 (segregs[regcs], ip) ); 3448 | StepIP (1); 3449 | ip = ip + oper1; 3450 | break; 3451 | 3452 | case 0xEC: /* EC IN regs.byteregs[regal] regdx */ 3453 | oper1 = regs.wordregs[regdx]; 3454 | // regs.byteregs[regal] = (byte) portin (oper1); 3455 | break; 3456 | 3457 | case 0xED: /* ED IN eAX regdx */ 3458 | oper1 = regs.wordregs[regdx]; 3459 | // regs.wordregs[regax] = portin16 (oper1); 3460 | break; 3461 | 3462 | case 0xEE: /* EE OUT regdx regs.byteregs[regal] */ 3463 | oper1 = regs.wordregs[regdx]; 3464 | //portout (oper1, regs.byteregs[regal]); 3465 | break; 3466 | 3467 | case 0xEF: /* EF OUT regdx eAX */ 3468 | oper1 = regs.wordregs[regdx]; 3469 | //portout16 (oper1, regs.wordregs[regax]); 3470 | break; 3471 | 3472 | case 0xF0: /* F0 LOCK */ 3473 | break; 3474 | 3475 | case 0xF4: /* F4 HLT */ 3476 | hltstate = 1; 3477 | break; 3478 | 3479 | case 0xF5: /* F5 CMC */ 3480 | if (!cf) { 3481 | cf = 1; 3482 | } 3483 | else { 3484 | cf = 0; 3485 | } 3486 | break; 3487 | 3488 | case 0xF6: /* F6 GRP3a Eb */ 3489 | modregrm(); 3490 | oper1b = readrm8 (rm); 3491 | op_grp3_8(); 3492 | if ( (reg > 1) && (reg < 4) ) { 3493 | writerm8 (rm, res8); 3494 | } 3495 | break; 3496 | 3497 | case 0xF7: /* F7 GRP3b Ev */ 3498 | modregrm(); 3499 | oper1 = readrm16 (rm); 3500 | op_grp3_16(); 3501 | if ( (reg > 1) && (reg < 4) ) { 3502 | writerm16 (rm, res16); 3503 | } 3504 | break; 3505 | 3506 | case 0xF8: /* F8 CLC */ 3507 | cf = 0; 3508 | break; 3509 | 3510 | case 0xF9: /* F9 STC */ 3511 | cf = 1; 3512 | break; 3513 | 3514 | case 0xFA: /* FA CLI */ 3515 | ifl = 0; 3516 | break; 3517 | 3518 | case 0xFB: /* FB STI */ 3519 | ifl = 1; 3520 | break; 3521 | 3522 | case 0xFC: /* FC CLD */ 3523 | df = 0; 3524 | break; 3525 | 3526 | case 0xFD: /* FD STD */ 3527 | df = 1; 3528 | break; 3529 | 3530 | case 0xFE: /* FE GRP4 Eb */ 3531 | modregrm(); 3532 | oper1b = readrm8 (rm); 3533 | oper2b = 1; 3534 | if (!reg) { 3535 | tempcf = cf; 3536 | res8 = oper1b + oper2b; 3537 | flag_add8 (oper1b, oper2b); 3538 | cf = tempcf; 3539 | writerm8 (rm, res8); 3540 | } 3541 | else { 3542 | tempcf = cf; 3543 | res8 = oper1b - oper2b; 3544 | flag_sub8 (oper1b, oper2b); 3545 | cf = tempcf; 3546 | writerm8 (rm, res8); 3547 | } 3548 | break; 3549 | 3550 | case 0xFF: /* FF GRP5 Ev */ 3551 | modregrm(); 3552 | oper1 = readrm16 (rm); 3553 | op_grp5(); 3554 | break; 3555 | 3556 | default: 3557 | break; 3558 | } 3559 | 3560 | skipexecution: 3561 | if (!running) { 3562 | return; 3563 | } 3564 | } 3565 | } 3566 | -------------------------------------------------------------------------------- /avr-x86/cpu.h: -------------------------------------------------------------------------------- 1 | /* 2 | avr-x86 - x86 emulator running on AVR Arduino! 3 | Copyright (C) 2021 @raspiduino 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #include 20 | #include 21 | #include "outputserial.cpp" 22 | #include "ram.h" 23 | 24 | void decodeflagsword( word x); 25 | void modregrm(); 26 | void write86 (uint32_t addr32, byte value); 27 | void writew86 (uint32_t addr32, word value); 28 | void flag_szp8 (byte value); 29 | void flag_szp16 (word value); 30 | void flag_log8 (byte value); 31 | void flag_log16 (word value); 32 | void flag_adc8 (byte v1, byte v2, byte v3); 33 | void flag_adc16 (word v1, word v2, word v3); 34 | void flag_add8 (byte v1, byte v2); 35 | void flag_add16 (word v1, word v2); 36 | void flag_sbb8 (byte v1, byte v2, byte v3); 37 | void flag_sbb16 (word v1, word v2, word v3); 38 | void flag_sub8 (byte v1, byte v2); 39 | void flag_sub16 (word v1, word v2); 40 | void op_adc8(); 41 | void op_adc16(); 42 | void op_add8(); 43 | void op_add16(); 44 | void op_and8(); 45 | void op_and16(); 46 | void op_or8(); 47 | void op_or16(); 48 | void op_xor8(); 49 | void op_xor16(); 50 | void op_sub8(); 51 | void op_sub16(); 52 | void op_sbb8(); 53 | void op_sbb16(); 54 | void getea (byte rmval); 55 | void push (word pushval); 56 | void reset86(); 57 | void writerm16 (byte rmval, word value); 58 | void writerm8 (byte rmval, byte value); 59 | void intcall86 (byte intnum); 60 | void op_div8 (word valdiv, byte divisor); 61 | void op_idiv8 (word valdiv, byte divisor); 62 | void op_grp3_8(); 63 | void op_div16 (uint32_t valdiv, word divisor); 64 | void op_idiv16 (uint32_t valdiv, word divisor); 65 | void op_grp3_16(); 66 | void op_grp5(); 67 | void init86 (); 68 | void exec86 (uint32_t execloops); 69 | byte read86 (uint32_t addr32); 70 | byte readrm8 (byte rmval); 71 | word readw86 (uint32_t addr32); 72 | byte op_grp2_8 (byte cnt); 73 | -------------------------------------------------------------------------------- /avr-x86/outputserial.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | avr-x86 - x86 emulator running on AVR Arduino! 3 | Copyright (C) 2021 @raspiduino 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | 18 | outputserial.cpp - Based on https://stackoverflow.com/questions/66632376/how-to-call-serial-print-from-c-file-in-arduino-ide 19 | */ 20 | 21 | #include 22 | //extern "C" { 23 | // #include "outputserial.h" 24 | //} 25 | -------------------------------------------------------------------------------- /avr-x86/ram.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | avr-x86 - x86 emulator running on AVR Arduino! 3 | Copyright (C) 2021 @raspiduino 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | Note on avr-x86's RAM: 21 | A few KB is not enough for our emulator. So ram.cpp will create a 22 | virutal RAM on the SD card, read and write from it and send to the emulator. 23 | 24 | Virtual RAM file is located in RAM_FILE macro path 25 | Default is 'RAM.BIN' 26 | */ 27 | 28 | #include "ram.h" 29 | 30 | SdCard card; 31 | Fat16 file; 32 | 33 | #ifdef BOOT_PROMPT 34 | char filepath[12]; // Virtual disk filepath 35 | #endif 36 | #ifndef BOOT_PROMPT 37 | char filepath[] = BOOT_FILE; 38 | #endif 39 | 40 | void sdinit(){ 41 | /* Init the SD card */ 42 | Serial.print(F("Init SD card")); 43 | while(!card.begin(CHIP_SELECT)) Serial.print("."); // Mount filesystem 44 | Serial.print(F(". Done! Init filesystem")); 45 | while(!Fat16::init(&card)) Serial.print("."); 46 | Serial.println(F(". Done!")); 47 | } 48 | 49 | void ramload(){ 50 | #ifdef BOOT_PROMPT 51 | fileinput(); 52 | while(!file.open(filepath, O_READ|O_WRITE)){ 53 | //Serial.print(F("Error opening ")); 54 | //Serial.println(filepath); 55 | fileinput(); 56 | } 57 | #endif 58 | 59 | #ifndef ONE_USE 60 | int ramloc = 0; 61 | char buf[RAM_BUFFER]; 62 | Serial.print(F("Loading disk image")); 63 | 64 | while (1) { 65 | // Read disk image 66 | file.open(filepath, O_READ); 67 | file.seekSet(ramloc); // Change the cusor 68 | int nr = file.read(buf, RAM_BUFFER); // Read disk image 69 | //const int ntb = file.fileSize()%RAM_BUFFER; // Number left on the last read 70 | //if (nr <= ntb) break; // Break at the end of file 71 | file.close(); 72 | 73 | // Write to vram 74 | file.open(RAM_FILE, O_WRITE|O_CREAT); // Open ram image file 75 | file.seekSet(ramloc); // Change the cusor 76 | file.write(buf, RAM_BUFFER); 77 | file.close(); 78 | 79 | if (nr < RAM_BUFFER) break; 80 | ramloc = ramloc + RAM_BUFFER; // Increase ramloc 81 | 82 | //file.open(filepath, O_READ); 83 | Serial.print(F(".")); 84 | } 85 | 86 | Serial.println(F(". Done!")); 87 | #endif 88 | } 89 | 90 | byte ramread(uint32_t addr){ 91 | byte buf[1]; 92 | 93 | #ifdef ONE_USE 94 | file.open(filepath, O_READ); // Open image file 95 | #endif 96 | #ifndef ONE_USE 97 | file.open(RAM_FILE, O_READ); // Open ram image file 98 | #endif 99 | 100 | file.seekSet(addr); // Seek to the location 101 | file.read(buf, 1); 102 | file.close(); 103 | return buf[0]; // Return the buffer 104 | } 105 | 106 | void ramwrite(uint32_t addr, byte value){ 107 | byte buf[1]; 108 | buf[0] = value; 109 | 110 | #ifdef ONE_USE 111 | file.open(filepath, O_WRITE); 112 | #endif 113 | #ifndef ONE_USE 114 | file.open(RAM_FILE, O_WRITE); 115 | #endif 116 | 117 | file.seekSet(addr); 118 | file.write(buf, 1); 119 | file.close(); 120 | } 121 | 122 | /* fileinput() - Ask for virtual disk file to boot from */ 123 | #ifdef BOOT_PROMPT 124 | void fileinput(){ 125 | Serial.print(F("$ ")); 126 | 127 | //while(Serial.available() == 0); // Wait until Serial input 128 | 129 | String tmpstring; 130 | while (1){ 131 | if(Serial.available() > 0){ 132 | // Read the char 133 | int incomingByte = Serial.read(); //Read the character ASCII number to the incomingByte varrible 134 | 135 | if(incomingByte == 10 | incomingByte == 13) break; 136 | else{ 137 | tmpstring = String(tmpstring + char(incomingByte)); 138 | } 139 | } 140 | } 141 | 142 | tmpstring.toUpperCase(); // Convert the string to upper case for FAT filesystem 143 | tmpstring.toCharArray(filepath, tmpstring.length()+1); // Convert the filepath to char array 144 | Serial.println(filepath); 145 | } 146 | #endif 147 | -------------------------------------------------------------------------------- /avr-x86/ram.h: -------------------------------------------------------------------------------- 1 | /* 2 | avr-x86 - x86 emulator running on AVR Arduino! 3 | Copyright (C) 2021 @raspiduino 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | /* Fat16 */ 20 | #include 21 | 22 | #include 23 | 24 | #include "outputserial.cpp" 25 | #include "config.h" 26 | 27 | byte ramread(uint32_t addr); 28 | void ramwrite(uint32_t addr, byte value); 29 | void ramload(); 30 | void sdinit(); 31 | 32 | extern char filepath[12]; 33 | extern SdCard card; 34 | extern Fat16 file; 35 | void fileinput(); 36 | --------------------------------------------------------------------------------