├── .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 | ![alt text](screenshot.png) 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 --------------------------------------------------------------------------------