├── 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 | 
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 |
--------------------------------------------------------------------------------