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