From 1c6cc28cf5317f2ee9fbc1a408bcaaef3b7378b3 Mon Sep 17 00:00:00 2001 From: Hugo Villeneuve Date: Sat, 8 May 2004 02:56:47 +0000 Subject: [PATCH 1/1] Initial import --- AUTHORS | 0 COPYING | 340 ++++ ChangeLog | 492 +++++ INSTALL | 229 +++ Makefile.am | 25 + NEWS | 0 README | 0 TODO | 15 + autogen.sh | 28 + config/debug.m4 | 18 + config/gtk2.m4 | 17 + configure.in | 89 + doc/Makefile.am | 9 + doc/emu8051.man | 123 ++ pixmaps/reset.xpm | 54 + pixmaps/run.xpm | 55 + pixmaps/step.xpm | 56 + pixmaps/stop.xpm | 55 + src/CPU8051.cpp | 644 +++++++ src/CPU8051.hpp | 62 + src/EmuConsole.cpp | 737 ++++++++ src/EmuConsole.hpp | 65 + src/EmuGtk.cpp | 735 ++++++++ src/EmuGtk.hpp | 111 ++ src/GtkSizes.hpp | 24 + src/Inst_Def.hpp | 266 +++ src/Inst_Imp.cpp | 4208 ++++++++++++++++++++++++++++++++++++++++++ src/Keyboard.hpp | 59 + src/Makefile.am | 37 + src/MemWin.cpp | 128 ++ src/MemWin.hpp | 29 + src/Memory.cpp | 51 + src/Memory.hpp | 24 + src/Opcode2cpp.pl | 785 ++++++++ src/PgmWin.cpp | 186 ++ src/PgmWin.hpp | 41 + src/Reg8051.hpp | 44 + src/RegWin.cpp | 131 ++ src/RegWin.hpp | 26 + src/disasm.hpp | 211 +++ src/exceptions.hpp | 19 + src/opcodes.lst | 258 +++ test_files/siae1.hex | 115 ++ test_files/test.hex | 13 + test_files/timer.asm | 179 ++ test_files/timer.hex | 10 + 46 files changed, 10803 insertions(+) create mode 100644 AUTHORS create mode 100644 COPYING create mode 100644 ChangeLog create mode 100644 INSTALL create mode 100644 Makefile.am create mode 100644 NEWS create mode 100644 README create mode 100644 TODO create mode 100755 autogen.sh create mode 100644 config/debug.m4 create mode 100644 config/gtk2.m4 create mode 100644 configure.in create mode 100644 doc/Makefile.am create mode 100644 doc/emu8051.man create mode 100644 pixmaps/reset.xpm create mode 100644 pixmaps/run.xpm create mode 100644 pixmaps/step.xpm create mode 100644 pixmaps/stop.xpm create mode 100644 src/CPU8051.cpp create mode 100644 src/CPU8051.hpp create mode 100644 src/EmuConsole.cpp create mode 100644 src/EmuConsole.hpp create mode 100644 src/EmuGtk.cpp create mode 100644 src/EmuGtk.hpp create mode 100644 src/GtkSizes.hpp create mode 100644 src/Inst_Def.hpp create mode 100644 src/Inst_Imp.cpp create mode 100644 src/Keyboard.hpp create mode 100644 src/Makefile.am create mode 100644 src/MemWin.cpp create mode 100644 src/MemWin.hpp create mode 100644 src/Memory.cpp create mode 100644 src/Memory.hpp create mode 100755 src/Opcode2cpp.pl create mode 100644 src/PgmWin.cpp create mode 100644 src/PgmWin.hpp create mode 100644 src/Reg8051.hpp create mode 100644 src/RegWin.cpp create mode 100644 src/RegWin.hpp create mode 100644 src/disasm.hpp create mode 100644 src/exceptions.hpp create mode 100644 src/opcodes.lst create mode 100644 test_files/siae1.hex create mode 100644 test_files/test.hex create mode 100644 test_files/timer.asm create mode 100644 test_files/timer.hex diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..e69de29 diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..d60c31a --- /dev/null +++ b/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..25aa334 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,492 @@ +------------------------------------------------------------------------------ +2002/11/12 Hugo Villeneuve + -Removed some warnings for GCC 3.2: replaced by + and by . + -Added "using namespace std;" in EmuGtk.hpp (for GCC 3.2) + -Removed all unused variables + -Corrected error in CPU8051.cpp, in function: + 'void CPU8051::IntMemBitInfo( unsigned int BitAddress, char *Text )' + Modified this: + 'sprintf( &Text[ TextLength ], ".%X", BitAddress );' + instead of: + 'sprintf( &Text[ TextLength ], ".%X" );' + -In Opcode2cpp.pl (line 767), modified for GCC 3.2: + 'print INST_IMP " funcptr[$i]=&CPU8051::$ifunc;\n";' + instead of: + 'print INST_IMP " funcptr[$i]=&$ifunc;\n";' + -EmuGtk.cpp, added '#include ' + -Modified the return type of some functions to void to remove warnings. + -In function 'void RegWin::Show( CPU8051 *CPU )' (RegWin.cpp), removed all + the '\n' in 'gtk_clist_set_text' calls (to fix a display problem) +------------------------------------------------------------------------------ +99/04/27 Hugo Villeneuve + + - Ajoute les fonctions DumpInt dans EmuConsole.hpp ainsi que ReadInt + dans CPU8051.hpp. Corrige des bugs dans WriteInt et WriteExt. + + - Corrige l'implementation des timers. Les 4 modes ont ete testes et + semblent bien fonctionner maintenant. LEs flags sont mis correctement + et les timers augmentent maintenant (au lieu d'etre decrementes). + - Ajoute un fichier timer.hex pour tester les timers. + +----------------------------------------------------------------------------- +99/04/22 Hugo Villeneuve + + - Ajoute les fonctions ME, MI et MP (voir definitions dans + EmuConsole.cpp). Ajoute les fonctions membres WriteExt et WriteInt + dans la classe CPU8051 afin de suivre la logique de l'espace + memoire du 8051. WriteExt permet de modifier la memoire externe + qui va de $00 a $FFFF (et non de $100 a $FFFF comme c'etait le cas + avant). De meme, WriteInt permet de modifier la memoire interne qui + va de $00 a $FF (incluant les SFR). Meme si la memoire externe + contient les adresses $00 a $FF, il n'y a pas de conflit avec la + memoire interne de $00 a $FF car la memoire externe est accedee avec + l'instruction MOVX alors que la memoire interne l'est avec les + instructions MOV (direct ou indirect). + + - Renomme l'option DD du menu pour DE (dump External data memory). + Change la description de l'option DI du menu pour Dump External + Data Memory. + + - Ajoute la fonction ReadExt dans la classe CPU8051, toujours pour + la logique de la memoire du 8051. Ajoute la fonction DumpExt dans la + classe EmuConsole pour dumper la memoire externe. + - Ces nouvelles fonctions ont ete testees et semblent bien fonctionner. +------------------------------------------------------------------------------ +99/04/09 Jonathan St-Andre + + - Refait marche le RunningState avec les classes. + - Reconnecte les signaux aux boutons Trace, Run, Reset et Quit. + - Ajoute bouton Step qui ajoute un breakpoint a la ligne suivante + et passe en RunningState. Pratique lorsqu'arrive un CALL et qu'on ne + veut pas y entrer contrairement a Trace. +------------------------------------------------------------------------------ +99/04/06 Jonathan St-Andre + + - Creation de EmuConsole.hpp et EmuConsole.cpp + - Cette nouvelle archive est presque rendue au meme niveau que + l'ancienne. Vous allez pouvoir commencer a laisser faire l'ancienne + et vous concentrer sur celle-ci. +------------------------------------------------------------------------------ +(Les modifs annoncee se rapportent a l'ancienne archive mais elles ont ete +ramenee dans celle-ci par Jonathan St-Andre) +99/04/05 Jonathan St-Andre + + - Corrige qq malfonctions dans exec de mainconsole.cpp (nb d'inst. + peut etre l'infini, caractere est attendu au clavier seulement + si l'execution est arretee par une touche. + - Corrige probleme d'instructions sans operandes mal desassemblees + (il ne faut pas ecrire le caractere ' ' dans la chaine, il faut + utiliser sprintf avec " " a la place car sprintf termine la chaine + avec un 0 a la fin. La chaine n'etait pas terminee par un 0 et elle + affichait du garbage de la memoire) + - Corrige probleme dans disasm.cpp en rapport avec addr11 qui ne + prenait pas opcode mais memoire[opcode] (je devais etre chaud quand + j'ai ecrit ca). + - Bouton Run se change en Stop dans l'interface Gtk+ lorsque l'on + clique dessus et le cpu se met en mode execution. Les fonctions de + l'interface restent disponibles. N'importe quelle action dans + l'interface(excepte le fait de cliquer dans les fenetre memoire + et programme) cause l'arret de l'execution et la mise a jour + de l'affichage. + - Il est possible de placer des breakpoints pendant qu'il est + dans le "RunningState". + - Enleve les pixmaps sur les boutons dans l'interface Gtk+ + - Ajoute verification de breakpoint deja existant dans + setbreakpoint. + + Hugo Villeneuve + + -Modifie l'affichage de disasm pour que les operandes soient alignees. + -Modifie la fonction DP pour qu'elle prenne l'adresse du PC par + defaut si aucune adresse n'est specifiee. + + - Erreur avec l'instruction ACALL qui ne calculait pas l'adresse + correctement et qui ne poussait pas l'adresse de retour sur la pile. + Il est important que le PC soit incremente de 2 avant de calculer + addr11 et de pousser le PC sur la pile... + Il faut aussi modifier le dessassemblage de cette instruction qui + n'affiche que la deuxieme operande (adresse de 8 bits), alors que + l'adresse est sur 11 bits... + -Erreur avec l'instruction RET( fichier siae1.asm adresse 03A4) , + affiche RET @%K + -Ajoute la possibilite d'arreter l'execution du programme en pesant + sur n'importe quelle touche grace a la fonction kbhit(). + -Ajoute les fonctions SB, RB et DB pour les breakpoints dans le + mode console. L'execution se fait jusqu'au breakpoint. Une fois + arrive au breakpoint, si on fait de nouveau EM, on peut continuer + l'execution du programme passe ce breakpoint. Autrement dit, EM + ne verifie pas si la premiere instruction qu'il execute est un + break point, ce qui est pratique pour continuer l'execution du prog + apres un breakpoint. +------------------------------------------------------------------------------ +99/03/31- +99/04/03 Jonathan St-Andre + + - Reecriture de TOUT les sources en imbriquant au maximum + dans des classes pour que ce soit plus lisible et reutilisable. + - Les classes sont CPU8051, Memory, EmuGtk, MemWin, RegWin, PgmWin + et les exceptions. + - Tout est en anglais pour rendre le programme disponible sur + internet. + - Je n'ai pas encore refais l'interface Console en classes donc + elle n'est pas incluse dans cette archive. Il faudrait vraiment + la refaire en tant que classe. + - Ajout fichiers TODO, CREDITS et COPYING (license GPL) +------------------------------------------------------------------------------ +99/03/30 Jonathan St-Andre + + - Corrige bug lors du desassemblage dans l'interpretation des + adresses directes dans 0-7F. disasm.cpp + - Corrige bug dans l'opcode 0x85, ajoute conditions particulieres + pour cette instruction dans script Perl et dans desassemblage. + Les operandes de cette instruction sont inversees dans la memoire + programme. Ex.: MOV 50H,51H est ecrit 85 51 50 dans la memoire + programme. + + Hugo Villeneuve + + - Bug dans les instructions ayant un mode d'adressage direct qui + utilisent des adresses dans 0-7F. Le desassembleur interprete les + adresses comme etant des adresses de bit. + - Bug dans l'opcode 0x85 MOV direct,direct. La source et la + destination sont inverses dans le desassemblage et dans l'execution. +------------------------------------------------------------------------------ +99/03/29 Jonathan St-Andre + + - Remplace string::erase pour string::replace partout, g++ a + l'universite ne connait pas encore string::erase, c'est trop recent. + - Ajoute "-w" pour disabler les warnings et "-fhandle-exceptions" + pour activer les exceptions a l'universite. + + Pascal Fecteau + + - Ajoute .h comme extension aux fichiers inclus, sinon ca ne + fonctionne pas a l'universite. + + Pascal Fecteau + Hugo Villeneuve + + - Corrige une erreur dans les instructions AJMP addr11 +------------------------------------------------------------------------------ +99/03/28 Hugo Villeneuve + + - Modification de la presentation de "Dump Register" sur la console. + Beaucoup plus facile a lire maintenant. + - Correction d'un bug dans l'instruction DA (opcode 0xD4). +------------------------------------------------------------------------------ +99/03/27 Hugo Villeneuve + + - Correction d'un probleme avec l'instruction CJNE. + - Correction de bugs dans LoadHexFile (voir 99/03/22) + + Jonathan St-Andre + + - Augmente la hauteur de la fenetre Internal RAM. + - Correction de probleme avec tous les XCH et XCHD, l'operande source + n'etait pas modifiee (Trouve par Hugo et suggestion de correction par + Hugo). + - Ajout de P0, P1, P2 et P3 dans la fenetre des registres. + (Suggestion d'Hugo). + - View -> Data Memory Dump et View -> Program Memory Dump sont + fonctionnels. On ne peut visionner que les 16384 premiers octets. + Il ne veut pas prendre 65536 lignes dans une scrolled window. + Probablement parce que 18colonnes x 65536lignes = 1179648 cellules + est beaucoup trop. + - J'ai remarque qu'avec Gtk, on peut facilement changer les raccoucis + dans les menus. Pour associer "View -> Program Memory Dump" au + raccourci "Alt-2" par exemple, il suffit d'aller dans le menu "View", + se placer au dessus de "Program Memory Dump" et appuyer "Alt-2". + Le menu se modifiera automatiquement pour afficher "Alt-2" au bout + de la ligne et desormais, lorsque vous appuierez "Alt-2", l'action + sera executee. Ca dure seulement durant la session presente. + - Reduit la taille de la fenetre principale en largeur de 120 pixels + et en hauteur de 20 pixels. +------------------------------------------------------------------------------ +99/03/25 Jonathan St-Andre + + - Fenetre dump connais la position ou on clique dedans. + - Generalise dans une classe la fenetre memorydump, il sera plus + facile d'ajouter plusieurs fenetres memory dump a partir du menu + plus tard. + - Implemente Run jusqu'a un breakpoint (si aucun breakpoint, + loop sans fin -> il faut killer). + - Suffit de cliquer sur une ligne de programme dans Gtk pour placer + ou retirer un breakpoint. Les breakpoints apparaissent comme une + asterisque (*) a droite de l'adresse dans la fenetre program. + - Ajoute bouton Run dans interface Gtk + - Implemente quelques fonctions necessaires au breakpoints. + - Change un peu le layout + - Enleve image de fond (cause leger delai au chargement) + - Fait un peu de menage dans fichiers relatifs au Gtk +------------------------------------------------------------------------------ +99/03/23 Jonathan St-Andre + + - Changement des champs GTK_TEXT des fenetres Registre, Program et + Internal RAM pour des champs GTK_CLIST. Plus beau, moins de + flickering quand on trace et plus pratique pour ce qui s'en vient. + - Integration des fichiers xpm dans l'executable. Mais c'est encore + trop long a charger lors de l'execution, va probablement falloir les + compresser ou laisser faire l'image de fond. + - Ajout de pixmaps sur les boutons Trace, Reset et Quit (Gtk) + - Ajout de pixmap comme fond (Gtk) +------------------------------------------------------------------------------ +99/03/22 Hugo Villeneuve + + - Corrige un bug dans la fonction LoadHexFile : Le checksum n'etait + pas calcule correctement, ce qui entrainait des erreurs a l'ouverture + de certains fichiers HEX. L'erreur venait du fait que le checksum se + calculait avec la valeur absolue du LoadOffset, au lieu d'utiliser + les caracteres composant le LoadOffset. Exemple : si LoadOffset = + 0103, il faut additionner 01h+03h=4h au Checksum et non pas 0103h = + 259 en decimal. + - Deplace la fonction enleve_espaces de main_console vers mainemu + car elle est commune aux deux interfaces graphiques. + - Modifie la fonction majuscules pour qu'elle puisse convertir les + lettres de minuscule a majuscule meme si la chaine contient des + chiffres ou autres signes de ponctuation. + - Modifie la declaration des fonctions dans tous les fichiers .hpp: + enleve le nom des parametres car c'etait inutile. + - Stocke le nom des registres dans un fichier registres8051.hpp. + Ainsi, si on veut emuler un autre type de processeur, il suffira + de se creer un autre fichier registres8052xxx.hpp par exemple. + - Implemente l'affichage en francais ou en anglais dependant de + l'option passee sur la ligne de commande. L'interface est beaucoup + plus lisible de cette facon. Par defaut, l'affichage est en anglais. +------------------------------------------------------------------------------ +99/03/21 Hugo Villeneuve + + - Ajoute deux parametres qu'on peut passer par la ligne de commande: + /? affiche les options disponibles sur la ligne de commande. + -f force l'affichage en francais (pas encore implemente!!!) + - Ajoute le controle d'erreur pour le chargement d'un fichier HEX. + Les differentes erreurs sont controlees ( checksum, rectype, + fin de fichier, etc.). + - Modifie la fonction unasm pour qu'elle accepte 0,1 ou 2 parametres. + U (adresse) (nombre d'instructions) + Si adresse et nombre d'instructions non-specifies: + Adresse = PC et Nombre d'Instructions = 16 + Si adresse specifie et nombre d'instructions non-specifie: + Adresse = adresse specifiee et Nombre d'Instructions = 16 + Si adresse specifie et nombre d'instructions specifie: + Adresse = adresse specifiee et Nombre d'Instructions = nb specifie + A noter: on peut specifier une adresse comme etant un nombre + hexadecimal, ou tout simplement en entrant "PC" ou "pc". + + Jonathan St-Andre + + - Ajout des interruptions du port serie. + - Ajout du timer 2 (8052). +------------------------------------------------------------------------------ +99/03/20 Hugo Villeneuve + + - Separe le fichier main.cpp en deux: main.cpp et fonctions.cpp. + fonctions.cpp contient les fonctions necessaires a main.cpp. + - Ajoute un fichier exceptions.hpp qui permet de gerer les erreurs. + - Modifie le Makefile en consequence. + - On peut maintenant entrer les adresses < a quatre caracteres : + ex: adresse 0000h = 0 ou 00 ou 000 ou 0000. + - Enleve le include + - Remplace toutes les commandes printf du main par cout. + - Modifie l'apparence du menu. + - Le programme est maintenant plus robuste en ce qui concerne les + erreurs de syntaxe, les adresses invalides, etc (a tester...). + - Modifier l'operation et la syntaxe de certaines commandes + S (set register) devient MR (modify register) car set veut + plutot dire "mettre a 1", et on pourra aussi implementer + MM (modify Memory). + R devient DR (display Register), pour suivre la logique de + DP, DM et DI. + - Ajoute une commande Execute Memory: EM addr n + - La gestion des chaines de caracteres se fait maintenant + uniquement avec des variables de type STRING, selon le C++. + - Enleve variables i,j,k et inputcars dans le main. + - Modifie la fonction RESET pour quelle n'affiche pas les + registres au demarrage... ca faisait pas beau! Ajoute + cependant un message pour dire que le up est resette. + - Pour changer un registre, on doit entrer PC (et non p) ainsi + que SP (et non seulement s). + - Ajoute une fonction qui convertit une chaine de caracteres + en majuscules. +------------------------------------------------------------------------------ +99/03/19 Jonathan St-Andre + + - Fonction reset51() ajoutee dans cpu8051.cpp, reset() ajoutee + dans main.cpp. + - Commande "Z" fait un reset du processeur sur la console et le + bouton Reset fonctionne dans le GUI. + + Jimmy Ringuette + + - Les interruptions sont maintenant implementees. check_hardware() a + ete supprimee et Do_timers() est appelee directement de exec8051(). +------------------------------------------------------------------------------ +99/03/18 Hugo Villeneuve + + - Modifie l'entree des commandes pour gerer un peu plus les erreurs + de syntaxe (je n'ai pas fini, il y a encore de la job a faire pour + mettre ca error proof). + - Simplifie l'entree des parametres pour chacune des fonctions. + - Re-modifie l'instruction trace pour avoir seulement deux modes: + trace a adresse et trace 1 instruction. Cela simplifie l'entree de + la commande (on n'a pas a faire TA, qui n'est pas une commande + standard dans les emulateurs). Si on veut faire tracer pour plusieurs + instructions, alors il suffira d'implementer la commande + EXECUTE Nombre_instructions, ce qui est beaucoup plus logique et + c'est ce qu'on retrouve dans la plupart des emulateurs. + - Ajoute la description des commandes en francais (loi 101). +------------------------------------------------------------------------------ +99/03/18 Jonathan St-Andre + + - Le bouton Trace dans la version Gtk+ fonctionne. On peut tracer + et les 3 fenetres(registres, memoire, programme) se mettent a jour. + - Ajout de 2 nouvelles fonctions trace : "tracenb()" et "traceat()" + Qui, respectivement, prenent un nombre d'instruction a executer ou + une adresse ou commencer l'execution. La fonction trace() a ete + resimplifiee. + - Dans les instructions RET, RETI, LCALL, PUSH et POP la pile prend + la iram seulement pour les adresses sous 0x80, la data RAM est + utilisee autrement. Avant, les SFR se faisaient ecraser! + - Modes d'addressage addr16, reladdr, #data16 modifies! + En tenant compte de ce que Hugo avait fait remarquer ce matin : + ex.: si PC++ apparait 2 fois sur une ligne, les 2 fois il repartira + de la meme valeur de PC et suite a cette ligne, on se trouve avec + un PC incremente 1 fois au lieu de 2. + - Menu accepte maj/minuscules + - Corrige bug dans "setreg", les registres peuvent vraiment + etre donnes en maj/minuscules maintenant. +------------------------------------------------------------------------------ +99/03/17 Hugo Villeneuve + + - Correction de bugs relatifs a la compilation sur VC5. + Dont ajout de #include . +------------------------------------------------------------------------------ +99/03/13 Jimmy Ringuette + + - Ajout des timers dans cpu8051.cpp. Il faudrait tester a fond. +------------------------------------------------------------------------------ +99/03/12 Jonathan St-Andre + + - Je crois qu'il sera plus interessant si on garde le memory + dump normal dans une fenetre exterieur et dont on pourra en ouvrir + plusieurs pour monitorer differents endroits de la memoire, c'est + pourquoi je n'ai place que "Internal RAM" comme memory dump dans + la fenetre principale. + - Au demarrage, effectue un premier memory dump dans la fenetre + "Internal RAM", un unasm dans "Program" et un show register dans + "Registers". + - Bouton Quit, menus "File -> Quit" et "Help -> About" reagissent. + - Comporte maintenant 2 Makefile : Makefile.console(fonctionne sur + toutes les plateformes) et Makefile.gtk(teste seulement sous Linux). + - DEBUT d'interface graphique Gtk+ (ne fait qu'afficher une fenetre + avec un layout tres simple), presentement je cours apres des sources + de documentations.(le manuel n'est pas encore complet) +------------------------------------------------------------------------------ +99/03/09 Jimmy Ringuette + + - Regle le bug avec mul (probleme avec les bits 15-8 du resultat + ne se ramenaient pas dans les bits 7-0 du registre B) + - La conversion chaine->hexadecimal accepte les minuscules + - Il n'est plus obligatoire d'ecrire les 4 caracteres lorsqu'il faut + entrer une valeur hexadecimale. +------------------------------------------------------------------------------ +99/03/05 Jonathan St-Andre + + - Corrige un warning de compilation sous Solaris. +------------------------------------------------------------------------------ +99/03/04 Jonathan St-Andre + + - Ca execute! (presque) + - Phase de corrections des bugs dans les instructions, une premiere + implementation est faite pour toutes les instructions. + - Ajout fonction "trace" et "dump internal memory" + - Les modes d'adressage sont pratiquement termines dans + les instructions. + - Certaines instructions ont un debut d'implementation. + - Desassembleur, bit addressable segment 00-7F -> 20.0-2F.7 +------------------------------------------------------------------------------ +99/03/03 Jonathan St-Andre + + - Ajout automatique de certaines lignes de codes concernant + l'adressage dans les fonctions d'instructions tres brouillon + - Ajout de stub pour write_mem et read_mem, modifs dans exec8051 + - Ajout de la fonction showregister() et de la commande 'r'. + - Correction d'une erreur iram_mem doit etre unsigned char et non int + - Note : Il y a des references a certaines parties du 8052 mais + elles ne seront pas implementees. Ce n'est qu'a titre d'informations. + - Ajout de #define pour faire correspondre les registres SFR avec + leur adresse dans la iram. + - Renomme instructions.cpp a instructions.hpp et ajout du tableau + de pointeurs sur les fonctions + - Ajout de la ram interne 00-FF et valeurs initiale au reset + dans cpu8051.cpp avec le registre : unsigned int PC. + - Ajout de cpu8051.cpp contenant exec8051() +------------------------------------------------------------------------------ +99/03/02 Jonathan St-Andre + + - Ajout de remarques dans le source + - Il faudrait maintenant tester avec plusieurs programmes pour + reperer les bugs. + - Le desassembleur reconnait maintenant les registres du SFR + (ex.: 88H est remplace par TCON, F0 par B, etc...) + - Changement au desassembleur (instructions peuvent avoir jusqu'a 3 + arguments ex.: CJNE R0,#data,reladdr) + - La vrai instruction CJNE comporte 3 arguments il faut changer + radicalement le desassembleur +------------------------------------------------------------------------------ +99/03/01 Jonathan St-Andre + + - Probleme dans opcodes.lst au niveau de l'instruction CJNE (mauvaise + definition) + - Tous les types d'adressages semblent fonctionner + - Le desassembleur peut lire les arguments et les afficher + (ex.: MOV A,#data peut devenir plus concret MOV A,#20) + - Desassembleur (instructions ont 2 arguments : instleftarg et + instrightarg) +------------------------------------------------------------------------------ +99/02/28 Jonathan St-Andre + + - Charge un fichier .hex donne en parametre (format Intel Hexadecimal + produit par ASM51) + - Effectue le dump program memory et dump data memory + - On peut quitter (YEAH!) + - Affiche le menu + - Creation de opcodes.lst et script Perl pour l'interpreter + - Debut + + + + + + + + diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..a4b3414 --- /dev/null +++ b/INSTALL @@ -0,0 +1,229 @@ +Copyright 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software +Foundation, Inc. + + This file is free documentation; the Free Software Foundation gives +unlimited permission to copy, distribute and modify it. + +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. (Caching is +disabled by default to prevent problems with accidental use of stale +cache files.) + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You only need +`configure.ac' if you want to change it or regenerate `configure' using +a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. Run `./configure --help' +for details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not support the `VPATH' +variable, you have to compile the package for one architecture at a +time in the source code directory. After you have installed the +package for one architecture, use `make distclean' before reconfiguring +for another architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' cannot figure out +automatically, but needs to determine by the type of machine the package +will run on. Usually, assuming the package is built to be run on the +_same_ architectures, `configure' can figure that out, but if it prints +a message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the `--target=TYPE' option to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + + Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +will cause the specified gcc to be used as the C compiler (unless it is +overridden in the site shell script). + +`configure' Invocation +====================== + + `configure' recognizes the following options to control how it +operates. + +`--help' +`-h' + Print a summary of the options to `configure', and exit. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..db1bf04 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,25 @@ +## Makefile.am -- Process this file with automake to produce Makefile.in + +AUTOMAKE_OPTIONS = gnu + +SUBDIRS = src doc + +EXTRA_DIST = bootstrap \ + $(ac_aux_dir)/debug.m4 \ + $(ac_aux_dir)/gtk2.m4 \ + pixmaps/*.xpm \ + test_files/* + +ACLOCAL = aclocal -I $(ac_aux_dir) + +CLEANFILES = *~ + +DISTCLEANFILES = .deps/*.P + +MAINTAINERCLEANFILES = Makefile.in aclocal.m4 configure config-h.in stamp-h.in \ + $(ac_aux_dir)/depcomp $(ac_aux_dir)/install-sh $(ac_aux_dir)/missing \ + $(ac_aux_dir)/mkinstalldirs $(ac_aux_dir)/config.guess \ + $(ac_aux_dir)/config.sub $(ac_aux_dir)/ltmain.sh + + + diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..e69de29 diff --git a/README b/README new file mode 100644 index 0000000..e69de29 diff --git a/TODO b/TODO new file mode 100644 index 0000000..4896be3 --- /dev/null +++ b/TODO @@ -0,0 +1,15 @@ + THINGS TO DO + ------------ + +-Compile only one program for both graphical and console modes, or + support only the graphical mode. +- Some fine tuning around the classes +- Make MemWin, RegWin be able to make a standalone + window if parentwin=0. +- Connect File->Open, View->... and Help->License menus. +- Make the RegWin and MemWin react when mouse clicked. (modify register or + memory) +- Enlever les fonctions ReadI, WriteI, dumpI etc... et plutot utiliser les + fonctions ReadInt, WriteInt, DumpInt, DumpExt, etc. +- Lors d'un DumpInt, verifier a ne pas afficher plus haut que la taille + reelle de la memoire interne. (Detail) diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..3cbbe7d --- /dev/null +++ b/autogen.sh @@ -0,0 +1,28 @@ +#! /bin/sh +# bootstrap -- Use this script to create generated files from the CVS dist +# Copyright (C) 2000 Gary V. Vaughan +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +## @start 1 +#! /bin/sh + +set -x +aclocal -I config +##libtoolize --force --copy +autoheader +automake --add-missing --copy +autoconf +## @end 1 diff --git a/config/debug.m4 b/config/debug.m4 new file mode 100644 index 0000000..f8fc330 --- /dev/null +++ b/config/debug.m4 @@ -0,0 +1,18 @@ +dnl +dnl Macro for adding an option to 'configure' for enabling debugging messages +dnl +AC_DEFUN([HV_CHECK_FOR_DEBUG],[ +AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug], + [enable debugging messages on console + (default is NO)]),[ + if test x"${enableval}" = xyes; then + debug_messages=1 + AC_DEFINE([DEBUG],1,[Set to 1 to enable debugging messages.]) + elif test x"${enableval}" = xno; then + debug_messages=0 + else + AC_MSG_ERROR(bad value for --enable-debug option) + fi +], debug_messages=0 ) +]) + diff --git a/config/gtk2.m4 b/config/gtk2.m4 new file mode 100644 index 0000000..46f02a7 --- /dev/null +++ b/config/gtk2.m4 @@ -0,0 +1,17 @@ +dnl +dnl Macro for adding an option to 'configure' for choosing GTK+-2 instead of the +dnl GTK+-1 default +dnl +AC_DEFUN([HV_CHECK_FOR_GTK2],[dnl +AC_ARG_WITH(gtk2, AC_HELP_STRING([--with-gtk2], [use GTK2 (default is GTK1)]),[dnl + if test x"${withval}" = xyes; then + use_gtk2=1 + AC_DEFINE([USE_GTK2],1,[Set to 1 to use the Gtk+-2 library.]) + elif test x"${withval}" = xno; then + use_gtk2=0 + else + AC_MSG_ERROR(bad value for --with-gtk2 option) + fi +], use_gtk2=0 ) +]) + diff --git a/configure.in b/configure.in new file mode 100644 index 0000000..d033b20 --- /dev/null +++ b/configure.in @@ -0,0 +1,89 @@ +# configure.in -- Process this file with autoconf to produce configure + +dnl Initialization stuff. +AC_INIT(emu8051, 0.1.0) +AC_CONFIG_AUX_DIR(config) +AC_CONFIG_SRCDIR(src/CPU8051.cpp) +AM_CONFIG_HEADER(config.h:config-h.in) +dnl Checking if the NEWS file has been updated to reflect the current version. +AM_INIT_AUTOMAKE(check-news) + +dnl Tests the C compiler +AC_PROG_CC +AC_LANG_C + +dnl Checking for header files. +AC_HEADER_STDC +AC_HEADER_SYS_WAIT +AC_CHECK_HEADERS(strings.h unistd.h) + +dnl Checking for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_TYPE_PID_T +AC_TYPE_SIZE_T + +dnl Basic CFLAGS values +CFLAGS="-Wall" + +dnl Checks for '--enable-debug' option +HV_CHECK_FOR_DEBUG + +if test x"${debug_messages}" = x1; then +dnl -g is for GDB debugging + CFLAGS="${CFLAGS} -g -gdwarf-2 -g3" +fi + +dnl Checks for '--with-gtk2' option +HV_CHECK_FOR_GTK2 + +if test x"${use_gtk2}" = x0; then + dnl Checks for Gtk+-1.2.0 + AM_PATH_GTK(1.2.0, CFLAGS="${CFLAGS} ${GTK_CFLAGS}" LIBS="${LIBS} ${GTK_LIBS}", + AC_MSG_ERROR(GTK+ not found!))dnl +else + dnl Checks for Gtk+-2.0 + PKG_CHECK_MODULES(GTK,gtk+-2.0 >= 2.0.5, CFLAGS="${CFLAGS} ${GTK_CFLAGS}" \ + LIBS="${LIBS} ${GTK_LIBS}",AC_MSG_ERROR(GTK+-2.0 not found!))dnl +fi + +dnl Tests the C++ compiler +AC_PROG_CXX +AC_LANG_CPLUSPLUS + +CXXFLAGS="${CFLAGS}" + +AC_SUBST(CFLAGS) +AC_SUBST(CXXFLAGS) +AC_SUBST(LIBS) +AC_SUBST(ac_aux_dir) + +dnl Creating output file(s) +AC_OUTPUT(Makefile src/Makefile doc/Makefile) + +echo \ +"--------------------------------------------------------------------------- +Configuration: + + Install path: ${prefix} + Compiler: ${CC} + Compiler flags: ${CFLAGS} + Linker flags: ${LIBS}" + +echo -n " GTK base version: " +if test x"${use_gtk2}" = x1; then + echo "2" +else + echo "1" +fi + +echo -n " Debugging messages: " +if test x"${debug_messages}" = x1; then + echo "yes" +else + echo "no" +fi + +echo \ +" + See config.h for further configuration information. +---------------------------------------------------------------------------" diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 0000000..edc4c8a --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,9 @@ +## Makefile.am -- Process this file with automake to produce Makefile.in + +man1_MANS = emu8051.man + +EXTRA_DIST = $(man1_MANS) + +CLEANFILES = *~ + +MAINTAINERCLEANFILES = Makefile.in diff --git a/doc/emu8051.man b/doc/emu8051.man new file mode 100644 index 0000000..aa9cef6 --- /dev/null +++ b/doc/emu8051.man @@ -0,0 +1,123 @@ +.TH WMNOTIFY 1 "March 2003" "wmnotify" "User's Manual" + +.SH NAME +wmnotify \- Dockable E-mail notification program for single POP3 account + +.SH SYNOPSIS +.B wmnotify +[\fIOPTION\fR]... + +.SH DESCRIPTION +\fBwmnotify\fR is a dockable application (DockApp) for the WindowMaker window +manager to periodically check a POP3 E-mail account for new messages. If there +are new messages in the mailbox, a simple animation is started to notify the +user. An optional beep or sound can also be produced if desired. + +The interface is kept very simple. To immediately check for new messages, +single-click on the mailbox image. To start your favorite email program, +double-click on the mailbox image. + +When you double-click on the mailbox image to start your email program, +the new messages animation is stopped, assuming that you will read your new +messages. If you don't, the wmnotify program will simply continue it's +periodic checking of your email account and will restart the new messages +animation after the usual delay if new messages are unread. + +By default, the interval between checks is 1 minute, and this can be changed in +the configuration file. You can also enable audio notification as well as +specify an optional audio sound file (WAV or AU). If audio notification is +enabled but no audio sound file is specified, a beep will be produced. There is +an option in the configuration file to adjust the volume of the sound file. + +.SH "OPTIONS" +.TP +.BI "\-\^c " config-file +.B wmnotify +reads your POP3 account settings and preferences from the specified +configuration file. This option overrides the use of the default config file, +.IR "$HOME/.wmnotifyrc". + +.TP +.BI \-display " host" : display +Specifies the host and screen to be used by \fBwmnotify\fR. By default this +is obtained from the environment variable +.SB DISPLAY. + +.TP +.BI \-geometry " geometry" +.RB ( *geometry ) +Specifies the initial geometry of the window. + +.TP +\fB\-h\fR +display usage and exit +.TP +\fB\-v\fR +output version information and exit + +.SH "CONFIGURATION FILE" +.IR $HOME/.wmnotifyrc + +The first time the program is run, it will check for the presence of the +configuration file in the user's home directory. If this file is not found, +wmnotify will automatically create a new one, and exit. Then the user must +enter it's POP3 account settings and preferences in the configuration file +before restarting wmnotify. + +.TP +.BI "server " +POP3 server name. + +.TP +.BI "port " +POP3 port number (optional, default value is 110). + +.TP +.BI "username " +POP3 username. + +.TP +.BI "password " +POP3 password. + +.TP +.BI "mailcheckdelay " +Mail check interval, in minutes (optional, default value is 1). + +.TP +.BI "mailclient " +The program to start when double-clicking on the mailbox image (optional). + +.TP +.BI "enablebeep " +This option controls the audio notification enabling/disabling. If this option +is enabled and the "audiofile" option below contains a valid audio file, it +will be played whenever new message(s) are detected. If "audiofile" is +commented, the console beep will be used to produce the audio notification. The +value may be set to "0" to disable or to "1" to enable (optional, default value is 0, disabled). + +.TP +.BI "audiofile " +Path and filename of the WAV or AU audio sound file to play when new message(s) +are detected (optional). + +.TP +.BI "volume " +Volume value, in percent, when playing an audio file (optional, default value is +100%). This volume value is relative to the values you have set in your sound +card mixer settings. If you find the audio notification sound to be too loud, +just reduce the volume value. On the other hand, if you want to increase the +audio notification sound amplitude, just increase the volume. If you increase +the volume value to 100% and you find that it is not sufficient, then you would +have to increase the volume using your favorite sound card mixer program +(ex: with alsamixer, increase the PCM or master value). + +.SH CREDITS +\fBwmnotify\fR was written by Hugo Villeneuve , based on +the WMPop3 program by Scott Holden . + +.SH COPYRIGHT +\fBwmnotify\fR is free; anyone may redistribute it to anyone under the terms +stated in the GNU General Public License. A copy of the license is included in +the \fBwmnotify\fR distribution. You can also browse it online at +.I http://www.gnu.org/copyleft/gpl.html diff --git a/pixmaps/reset.xpm b/pixmaps/reset.xpm new file mode 100644 index 0000000..a7df6bd --- /dev/null +++ b/pixmaps/reset.xpm @@ -0,0 +1,54 @@ +/* XPM */ +static char * reset_xpm[] = { +"48 48 3 1", +" c None", +". c #005A9C", +"+ c #FFFFFF", +"................................................", +"................................................", +"................................................", +"................................................", +"................................................", +"................................................", +"................................................", +"................................................", +"................................................", +"................................................", +"................................................", +"................................................", +"................................................", +"................................................", +"................................................", +"................................................", +"................................................", +"................................................", +"..+++++++..++++++++..+++++++.++++++++.++++++++..", +"..++++++++.++++++++.++++++++.++++++++.++++++++..", +"..++....++.++.......++.......++..........++.....", +"..++....++.++.......++.......++..........++.....", +"..++....++.++.......++.......++..........++.....", +"..++....++.+++++++..+++++++..+++++++.....++.....", +"..+++++++..+++++++...+++++++.+++++++.....++.....", +"..+++++++..++.............++.++..........++.....", +"..++....++.++.............++.++..........++.....", +"..++....++.++.............++.++..........++.....", +"..++....++.++++++++.++++++++.++++++++....++.....", +"..++....++.++++++++.+++++++..++++++++....++.....", +"................................................", +"................................................", +"................................................", +"................................................", +"................................................", +"................................................", +"................................................", +"................................................", +"................................................", +"................................................", +"................................................", +"................................................", +"................................................", +"................................................", +"................................................", +"................................................", +"................................................", +"................................................"}; diff --git a/pixmaps/run.xpm b/pixmaps/run.xpm new file mode 100644 index 0000000..d456e74 --- /dev/null +++ b/pixmaps/run.xpm @@ -0,0 +1,55 @@ +/* XPM */ +static char * run_xpm[] = { +"48 48 4 1", +" c None", +". c #000000", +"+ c #008C6B", +"@ c #FFFFFF", +" ........... ", +" ................... ", +" ........+++++++........ ", +" ......+++++++++++++++...... ", +" .....+++++++++++++++++++..... ", +" .....+++++++++++++++++++++++..... ", +" .....+++++++++++++++++++++++++..... ", +" ....+++++++++++++++++++++++++++++.... ", +" ...+++++++++++++++++++++++++++++++... ", +" ...+++++++++++++++++++++++++++++++++... ", +" ....+++++++++++++++++++++++++++++++++.... ", +" ...+++++++++++++++++++++++++++++++++++... ", +" ...+++++++++++++++++++++++++++++++++++++... ", +" ...+++++++++++++++++++++++++++++++++++++... ", +" ...+++++++++++++++++++++++++++++++++++++++... ", +" ...+++++++++++++++++++++++++++++++++++++++... ", +" ..+++++++++++++++++++++++++++++++++++++++++.. ", +" ..++++++++@@@@@@@++@@++++@@+@@++++@@+++++++.. ", +"...++++++++@@@@@@@@+@@++++@@+@@@+++@@+++++++... ", +"...++++++++@@++++@@+@@++++@@+@@@+++@@+++++++... ", +"..+++++++++@@++++@@+@@++++@@+@@@@++@@++++++++.. ", +"..+++++++++@@++++@@+@@++++@@+@@@@++@@++++++++.. ", +"..+++++++++@@++++@@+@@++++@@+@@+@@+@@++++++++.. ", +"..+++++++++@@@@@@@++@@++++@@+@@+@@+@@++++++++.. ", +"..+++++++++@@@@@@@++@@++++@@+@@++@@@@++++++++.. ", +"..+++++++++@@++++@@+@@++++@@+@@++@@@@++++++++.. ", +"..+++++++++@@++++@@+@@++++@@+@@+++@@@++++++++.. ", +"...++++++++@@++++@@+@@@@@@@@+@@+++@@@+++++++... ", +"...++++++++@@++++@@++@@@@@@++@@++++@@+++++++... ", +" ..+++++++++++++++++++++++++++++++++++++++++.. ", +" ..+++++++++++++++++++++++++++++++++++++++++.. ", +" ...+++++++++++++++++++++++++++++++++++++++... ", +" ...+++++++++++++++++++++++++++++++++++++++... ", +" ...+++++++++++++++++++++++++++++++++++++... ", +" ...+++++++++++++++++++++++++++++++++++++... ", +" ...+++++++++++++++++++++++++++++++++++... ", +" ....+++++++++++++++++++++++++++++++++.... ", +" ...+++++++++++++++++++++++++++++++++... ", +" ...+++++++++++++++++++++++++++++++... ", +" ....+++++++++++++++++++++++++++++.... ", +" .....+++++++++++++++++++++++++..... ", +" .....+++++++++++++++++++++++..... ", +" .....+++++++++++++++++++..... ", +" ......+++++++++++++++...... ", +" ........+++++++........ ", +" ................... ", +" ........... ", +" "}; diff --git a/pixmaps/step.xpm b/pixmaps/step.xpm new file mode 100644 index 0000000..167cac3 --- /dev/null +++ b/pixmaps/step.xpm @@ -0,0 +1,56 @@ +/* XPM */ +static char * step_xpm[] = { +"48 48 5 1", +" c None", +". c #FFDE08", +"+ c #000000", +"@ c #FFFFFF", +"# c #080800", +"..........++++++++++++............++++++++++++..", +"...........++++++++++++............++++++++++++.", +"............++++++++++++............++++++++++++", +"+............++++++++++++............+++++++++++", +"++............++++++++++++............++++++++++", +"+++............++++++++++++............+++++++++", +"++++............++++++++++++............++++++++", +"+++++............++++++++++++............+++++++", +"++++++............++++++++++++............++++++", +"+++++++............++++++++++++............+++++", +"++++++++............++++++++++++............++++", +"+++++++++............++++++++++++............+++", +"++++++++++............++++++++++++............++", +"+++++++++++............++++++++++++............+", +"++++++++++++............++++++++++++............", +".++++++++++++++++++++++++++++++++++++++++++++...", +"..+++++++++++++++++++++++++++++++++++++++++++...", +"...++++++++++++++++++++++++++++++++++++++++++...", +"....++++@@@@@@@+@@@@@@@@+@@@@@@@@+@@@@@@@++++...", +"....+++@@@@@@@@+@@@@@@@@+@@@@@@@@+@@@@@@@@+++...", +"....+++@@++++++++++@@++++@@+++++++@@++++@@+++...", +"....+++@@++++++++++@@++++@@+++++++@@++++@@+++...", +"....+++@@++++++++++@@++++@@+++++++@@++++@@+++...", +"....+++@@@@@@@+++++@@++++@@@@@@@++@@++++@@+++...", +"....++++@@@@@@@++++@@++++@@@@@@@++@@@@@@@@++++..", +"....+++++++++@@++++@@++++@@+++++++@@@@@@@++++++.", +"....+++++++++@@++++@@++++@@+++++++@@++++++++++++", +"+...+++++++++@@++++@@++++@@+++++++@@++++++++++++", +"++..+++@@@@@@@@++++@@++++@@@@@@@@+@@++++++++++++", +"+++.+++@@@@@@@+++++@@++++@@@@@@@@+@@++++++++++++", +"++++++++++++++++++++++++++++++++++++++++++++++++", +"++++++++++++++++++++++++++++++++++++++++++++++++", +"++++++++++++++++++++++++++++++++++++++++++++++++", +"+++++++............++++++++++++............+++++", +"++++++++............++++++++++++............++++", +"+++++++++............+#++++++++++............+++", +"++++++++++............++++++++++++............++", +"#++++++++++............++++++++++++............+", +"++++++++++++............++++++++++++............", +".+#++++++++++............+#++++++++++...........", +"..++++++++++++............+#++++++++++..........", +"...++++++++++++............++++++++++++.........", +"....++++++++++++............++++++++++++........", +".....+#++++++++++............+#++++++++++.......", +"......++++++++++++............++++++++++++......", +".......++++++++++++............++++++++++++.....", +"........+#++++++++++............++++++++++++....", +".........++++++++++++............+#++++++++++..."}; diff --git a/pixmaps/stop.xpm b/pixmaps/stop.xpm new file mode 100644 index 0000000..e8d3d85 --- /dev/null +++ b/pixmaps/stop.xpm @@ -0,0 +1,55 @@ +/* XPM */ +static char * stop_xpm[] = { +"48 48 4 1", +" c None", +". c #000000", +"+ c #C60021", +"@ c #FFFFFF", +" .................... ", +" .++++++++++++++++++++. ", +" .++@@@@@@@@@@@@@@@@@@++. ", +" .++@@++++++++++++++++@@++. ", +" .++@@++++++++++++++++++@@++. ", +" .++@@++++++++++++++++++++@@++. ", +" .++@@++++++++++++++++++++++@@++. ", +" .++@@++++++++++++++++++++++++@@++. ", +" .++@@++++++++++++++++++++++++++@@++. ", +" .++@@++++++++++++++++++++++++++++@@++. ", +" .++@@++++++++++++++++++++++++++++++@@++. ", +" .++@@++++++++++++++++++++++++++++++++@@++. ", +" .++@@++++++++++++++++++++++++++++++++++@@++. ", +" .++@@++++++++++++++++++++++++++++++++++++@@++. ", +".++@@++++++++++++++++++++++++++++++++++++++@@++.", +".+@@++++++++++++++++++++++++++++++++++++++++@@+.", +".+@++++++++++++++++++++++++++++++++++++++++++@+.", +".+@++++++++++++++++++++++++++++++++++++++++++@+.", +".+@+++++@@@@@@@+@@@@@@@@++@@@@@@++@@@@@@@++++@+.", +".+@++++@@@@@@@@+@@@@@@@@++@@@@@@++@@@@@@@@+++@+.", +".+@++++@@++++++++++@@++++@@@++@@@+@@++++@@+++@+.", +".+@++++@@++++++++++@@++++@@++++@@+@@++++@@+++@+.", +".+@++++@@++++++++++@@++++@@++++@@+@@++++@@+++@+.", +".+@++++@@@@@@@+++++@@++++@@++++@@+@@++++@@+++@+.", +".+@+++++@@@@@@@++++@@++++@@++++@@+@@@@@@@@+++@+.", +".+@++++++++++@@++++@@++++@@++++@@+@@@@@@@++++@+.", +".+@++++++++++@@++++@@++++@@++++@@+@@+++++++++@+.", +".+@++++++++++@@++++@@++++@@@++@@@+@@+++++++++@+.", +".+@++++@@@@@@@@++++@@+++++@@@@@@++@@+++++++++@+.", +".+@++++@@@@@@@+++++@@+++++@@@@@@++@@+++++++++@+.", +".+@++++++++++++++++++++++++++++++++++++++++++@+.", +".+@++++++++++++++++++++++++++++++++++++++++++@+.", +".+@@++++++++++++++++++++++++++++++++++++++++@@+.", +".++@@++++++++++++++++++++++++++++++++++++++@@++.", +" .++@@++++++++++++++++++++++++++++++++++++@@++. ", +" .++@@++++++++++++++++++++++++++++++++++@@++. ", +" .++@@++++++++++++++++++++++++++++++++@@++. ", +" .++@@++++++++++++++++++++++++++++++@@++. ", +" .++@@++++++++++++++++++++++++++++@@++. ", +" .++@@++++++++++++++++++++++++++@@++. ", +" .++@@++++++++++++++++++++++++@@++. ", +" .++@@++++++++++++++++++++++@@++. ", +" .++@@++++++++++++++++++++@@++. ", +" .++@@++++++++++++++++++@@++. ", +" .++@@++++++++++++++++@@++. ", +" .++@@@@@@@@@@@@@@@@@@@+. ", +" .++++++++++++++++++++. ", +" .................... "}; diff --git a/src/CPU8051.cpp b/src/CPU8051.cpp new file mode 100644 index 0000000..b0a45de --- /dev/null +++ b/src/CPU8051.cpp @@ -0,0 +1,644 @@ +// CPU8051.cpp + +#include +#include +#include "CPU8051.hpp" +#include "disasm.hpp" + +////////////////////////////////////////////////////////////////////////////// +// CPU8051::CPU8051( ) +// CPU8051 constructor +////////////////////////////////////////////////////////////////////////////// +CPU8051::CPU8051( ) +{ + InitFuncPtr( ); + // Cree les objets Memory + SFRMem = new Memory( 128 ); + PGMMem = new Memory( 65536 ); + IntMem = new Memory( 128 ); + ExtMem = new Memory( 65536 ); + PC = 0; CLOCK = 0; ActivePriority = -1; +} + +////////////////////////////////////////////////////////////////////////////// +// CPU8051::~CPU8051( ) +// CPU8051 destructor +////////////////////////////////////////////////////////////////////////////// +CPU8051::~CPU8051( ) +{ + // Detruit les objets Memory + delete SFRMem; + delete PGMMem; + delete IntMem; + delete ExtMem; + + SFRMem = 0; + PGMMem = 0; + IntMem = 0; + ExtMem = 0; + PC = 0; + CLOCK = 0; +} + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::Exec( ) +// Execute at address PC from PGMMem +////////////////////////////////////////////////////////////////////////////// +void CPU8051::Exec( ) +{ +int i; +unsigned char opcode = PGMMem->Read8( PC++ ); +int insttiming = ( this->*funcptr[ opcode ] )(); + +for ( i = 0; i < insttiming; i++) + { + CheckInterrupts(); + DoTimers(); + CLOCK++; + } +} + +////////////////////////////////////////////////////////////////////////////// +// unsigned int CPU8051::GetNextAddress( ) +// Return PC + size in bytes of current instruction +////////////////////////////////////////////////////////////////////////////// +unsigned int CPU8051::GetNextAddress( ) +{ +return ( PC + InstSizesTbl[ PGMMem->Read8( PC ) ] ); +} + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::Reset( ) +// Reset the registers and CPU state +////////////////////////////////////////////////////////////////////////////// +void CPU8051::Reset( ) +{ + PC = 0; CLOCK = 0; ActivePriority = -1; + // Reinitialisation des registres + int i; + for ( i = 0; i < 128; i++ ) + { + SFRMem->Write8( i, 0 ); + IntMem->Write8( i, 0 ); + } + SFRMem->Write8( _P0_ - 0x80, 0xFF ); + SFRMem->Write8( _P1_ - 0x80, 0xFF ); + SFRMem->Write8( _P2_ - 0x80, 0xFF ); + SFRMem->Write8( _P3_ - 0x80, 0xFF ); + SFRMem->Write8( _SP_ - 0x80, 0x07 ); +} + +////////////////////////////////////////////////////////////////////////////// +// unsigned int CPU8051::GetPC( ) +// Return the value of PC register +////////////////////////////////////////////////////////////////////////////// +unsigned int CPU8051::GetPC( ) +{ + return PC; +} + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::SetPC( unsigned int NewPC ) +// Set the new value of PC register +////////////////////////////////////////////////////////////////////////////// +void CPU8051::SetPC( unsigned int NewPC ) +{ + PC = NewPC; +} + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::WriteD( unsigned int Address, unsigned char Value ) +// Write with a direct addressing mode at Address the new Value +////////////////////////////////////////////////////////////////////////////// +void CPU8051::WriteD( unsigned int Address, unsigned char Value ) +{ + if ( Address > 0x7F ) { SFRMem->Write8( Address - 0x80, Value ); return; } + IntMem->Write8( Address, Value ); +} + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::WriteExt( unsigned int Address, unsigned char Value ) +// Ecriture d'une valeur dans la memoire externe ( Address = $00 a $FFFF ) +////////////////////////////////////////////////////////////////////////////// +void CPU8051::WriteExt( unsigned int Address, unsigned char Value ) +{ + ExtMem->Write8( Address, Value ); + return; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::WriteInt( unsigned int Address, unsigned char Value ) +// Ecriture d'une valeur dans la memoire interne ( Address = $00 a $FF ) +////////////////////////////////////////////////////////////////////////////// +void CPU8051::WriteInt( unsigned int Address, unsigned char Value ) +{ + if ( Address > 0x7F ) + SFRMem->Write8( Address - 0x80, Value ); + else + IntMem->Write8( Address, Value ); + return; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::WriteI( unsigned int Address, unsigned char Value ) +// Write with an indirect addressing mode at Address the new Value +////////////////////////////////////////////////////////////////////////////// +void CPU8051::WriteI( unsigned int Address, unsigned char Value ) +{ + if ( Address > 0x7F ) { ExtMem->Write8( Address, Value ); return; } + IntMem->Write8( Address, Value ); +} + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::WritePGM( unsigned int Address, unsigned char Value ) +// Write at Address the new Value in PGMMem +////////////////////////////////////////////////////////////////////////////// +void CPU8051::WritePGM( unsigned int Address, unsigned char Value ) +{ + PGMMem->Write8( Address, Value ); +} + +////////////////////////////////////////////////////////////////////////////// +// unsigned char CPU8051::ReadD( unsigned int Address ) +// Read with a direct addressing mode at Address +////////////////////////////////////////////////////////////////////////////// +unsigned char CPU8051::ReadD( unsigned int Address ) +{ + if ( Address > 0xFF ) return ExtMem->Read8( Address ); + if ( Address > 0x7F ) return SFRMem->Read8( Address - 0x80 ); + return IntMem->Read8( Address ); +} + + +////////////////////////////////////////////////////////////////////////////// +// unsigned char CPU8051::ReadInt( unsigned int Address ) +// Read Internal data memory at Address +////////////////////////////////////////////////////////////////////////////// +unsigned char CPU8051::ReadInt( unsigned int Address ) +{ + if ( Address > 0x7F ) + return SFRMem->Read8( Address - 0x80 ); + return IntMem->Read8( Address ); +} + +////////////////////////////////////////////////////////////////////////////// +// unsigned char CPU8051::ReadExt( unsigned int Address ) +// Lecture du contenu de la memoire externe +////////////////////////////////////////////////////////////////////////////// +unsigned char CPU8051::ReadExt( unsigned int Address ) +{ + return ExtMem->Read8( Address ); +} + + +////////////////////////////////////////////////////////////////////////////// +// unsigned char CPU8051::ReadI( unsigned int Address ) +// Read with a indirect addressing mode at Address +////////////////////////////////////////////////////////////////////////////// +unsigned char CPU8051::ReadI( unsigned int Address ) +{ + if ( Address > 0x7F ) return ExtMem->Read8( Address ); + return IntMem->Read8( Address ); +} + +////////////////////////////////////////////////////////////////////////////// +// unsigned char CPU8051::ReadPGM( unsigned int Address ) +// Read at Address from PGMMem +////////////////////////////////////////////////////////////////////////////// +unsigned char CPU8051::ReadPGM( unsigned int Address ) +{ + return PGMMem->Read8( Address ); +} + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::WriteB( unsigned int BitAddress, unsigned char Value ) +// Write with a bit addressing mode at BitAddress the new Value +////////////////////////////////////////////////////////////////////////////// +void CPU8051::WriteB( unsigned int BitAddress, unsigned char Value ) +{ +unsigned int ByteAddress, BitNumber; +unsigned char ByteValue, ByteMask; + if ( BitAddress > 0x7F ) { + // SFR 80-FF + ByteAddress = BitAddress & 0xF8; + BitNumber = BitAddress & 0x07; + } + else { + // 20-2F + ByteAddress = ( BitAddress >> 3 ) + 0x20; + BitNumber = BitAddress & 0x07; + } + ByteMask = ( ( 1 << BitNumber ) ^ 0xFF ); + ByteValue = ReadD( ByteAddress ) & ByteMask; + ByteValue += Value << BitNumber; + WriteD( ByteAddress, ByteValue ); +} + + +////////////////////////////////////////////////////////////////////////////// +// unsigned char CPU8051::ReadB( unsigned int BitAddress ) +// Read with a bit addressing mode at BitAddress +////////////////////////////////////////////////////////////////////////////// +unsigned char CPU8051::ReadB( unsigned int BitAddress ) +{ +unsigned int ByteAddress, BitNumber; +unsigned char BitValue; + if ( BitAddress > 0x7F ) { + // SFR 80-FF + ByteAddress = BitAddress & 0xF8; + BitNumber = BitAddress & 0x07; + } + else { + // 20-2F + ByteAddress = ( BitAddress >> 3 ) + 0x20; + BitNumber = BitAddress & 0x07; + } + BitValue = ( ReadD( ByteAddress ) >> BitNumber ); + BitValue &= 1; + return BitValue; +} + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::CheckInterrupts() +// Check interrupts state and process them as needed +////////////////////////////////////////////////////////////////////////////// +void CPU8051::CheckInterrupts() +{ +unsigned char SP; + + if ( ReadD( _IE_ ) & 0x80 ) { + for ( int i = 1; i >= 0; i-- ) + if ( ActivePriority < i ) { +//------------------------- External interrupt 0 ---------------------------- +// if ( ( ReadD( _IE_ ) & 0x01 ) && ( ( ReadD( _IP_ ) & 0x01 ) ? i : !i ) && pin0 ) +//-------------------------- Interrupt timer 0 ------------------------------- + if ( ( ReadD( _IE_ ) & 0x02 ) && ( ( ReadD( _IP_ & 0x02 ) ? i : !i ) && ( ReadD( _TCON_ ) & 0x20 ) ) ){ + WriteD( _TCON_, ReadD( _TCON_ ) & 0xDF ); + SP = ReadD( _SP_ ); + WriteI( ++SP, ( PC & 0xFF ) ); + WriteI( ++SP, ( PC >> 8 ) ); + WriteD( _SP_, SP ); + PC = 0x0B; + ActivePriority = i; + return; + } +//-------------------------- External interrupt 1 ---------------------------- +// if ( ( ReadD( _IE_ ) & 0x04 ) && ( ( ReadD( _IP_ ) & 0x04 ) ? i : !i ) && pin1 ) +//-------------------------- Interrupt timer 1 ------------------------------- + if ( ( ReadD( _IE_ ) & 0x08 ) && ( ( ReadD( _IP_ ) & 0x08 ) ? i : !i ) && ( ReadD( _TCON_ ) & 0x80 ) ) { + WriteD( _TCON_, ReadD( _TCON_ ) & 0x7F ); + SP = ReadD( _SP_ ); + WriteI( ++SP, ( PC & 0xFF ) ); + WriteI( ++SP, ( PC >> 8 ) ); + WriteD( _SP_, SP ); + PC = 0x1B; + ActivePriority = i; + return; + } +//-------------------------- Serial Interrupts ------------------------------- + if ( ( ReadD( _IE_ ) & 0x10 ) && ( ( ReadD( _IP_ ) & 0x10 ) ? i : !i ) && ( ReadD( _SCON_ ) & 0x03 ) ) { + SP = ReadD( _SP_ ); + WriteI( ++SP, ( PC & 0xFF ) ); + WriteI( ++SP, ( PC >> 8 ) ); + WriteD( _SP_, SP ); + PC = 0x23; + ActivePriority = i; + return; + } +//-------------------------- Interrupt timer 2 ------------------------------- + if ( ( ReadD( _IE_ ) & 0x20 ) && ( ( ReadD( _IP_ ) & 0x20 ) ? i : !i ) && ( ReadD( _T2CON_ ) & 0x80 ) ) { + SP = ReadD( _SP_ ); + WriteI( ++SP, ( PC & 0xFF ) ); + WriteI( ++SP, ( PC >> 8 ) ); + WriteD( _SP_, SP ); + PC = 0x2B; + ActivePriority = i; + return; + } + } + } +} + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::DoTimers( ) +// Execute les timers +////////////////////////////////////////////////////////////////////////////// +void CPU8051::DoTimers( ) +{ + unsigned int tmp; + unsigned int TR; + unsigned int MODE; + unsigned int GATE; + unsigned int TimerCounter; + + // ----- Timer 0 + TR = ReadD( _TCON_ ) & 0x10; + MODE = ReadD( _TMOD_ ) & 0x03; + GATE = ReadD( _TMOD_ ) & 0x08; + TimerCounter = ReadD( _TMOD_ ) & 0x04; + + if ( ( TR && !GATE && !TimerCounter ) || ( MODE == 3 ) ) + switch( MODE ) { + // Mode 0, compteur de 13 bits. + case 0 : + tmp = ReadD( _TH0_ ) * 0x100 + ReadD( _TL0_ ); + ++tmp &= 0x1FFF; // On ne garde que 13 bits. + if ( tmp == 0 ) // If overflow set TF0 + WriteD( _TCON_, ReadD( _TCON_ ) | 0x20 ); + WriteD( _TH0_, tmp / 0x100 ); + WriteD( _TL0_, tmp & 0xFF ); + break; + + // Mode 1, compteur de 16 bits. + case 1 : + tmp = ReadD( _TH0_ ) * 0x100 + ReadD( _TL0_ ); + ++tmp &= 0xFFFF; // On ne garde que 16 bits. + if ( tmp == 0 ) // If overflow set TF0 + WriteD( _TCON_, ReadD( _TCON_ ) | 0x20 ); + WriteD( _TH0_, ( tmp / 0x100 ) ); + WriteD( _TL0_, ( tmp & 0xFF ) ); + break; + + // Mode 2, Compteur de 8 bits avec Auto-Reload + case 2 : + tmp = ReadD( _TL0_ ); + ++tmp &= 0xFF; + if ( tmp == 0 ) { // If overflow -> reload et set TF0 + WriteD( _TCON_, ReadD( _TCON_ ) | 0x20 ); + WriteD( _TL0_, ReadD( _TH0_ ) ); + } + else + WriteD( _TL0_, tmp ); + break; + + // Mode 3 : TL0 et TH0 sont 2 Timers independants de 8 bits chacuns. + case 3 : + if ( TR && !GATE && !TimerCounter ) { + tmp = ReadD( _TL0_ ); + ++tmp &= 0xFF; + if ( tmp == 0 ) // If TL0 overflow set TF0 + WriteD( _TCON_, ReadD( _TCON_ ) | 0x20 ); + WriteD( _TL0_, tmp ); + } // TH0 utilise TR1 et TF1. + TR = ReadD( _TCON_ ) & 0x40; + if ( TR ) { + tmp = ReadD( _TH0_ ); + ++tmp &= 0xFF; + if ( tmp == 0 ) // If TH0 overflow set TF1 + WriteD( _TCON_, ReadD( _TCON_ ) | 0x80 ); // TF1 = 1. + WriteD( _TH0_, tmp ); + } + break; + }; + + + // ----- Timer 1 + TR = ReadD( _TCON_ ) & 0x40; + MODE = ( ReadD( _TMOD_ ) & 0x30 ) >> 4 ; + GATE = ReadD( _TMOD_ ) & 0x80; + TimerCounter = ReadD( _TMOD_ ) & 0x40; + + if ( TR && !GATE && !TimerCounter ) + switch( MODE ) { + // Mode 0, compteur de 13 bits. + case 0 : + tmp = ReadD( _TH1_ ) * 0x100 + ReadD( _TL1_ ); + ++tmp &= 0x1FFF; // On ne garde que 13 bits. + if ( tmp == 0 ) // If overflow set TF1 + WriteD( _TCON_, ReadD( _TCON_ ) | 0x80 ); + WriteD( _TH1_, tmp / 0x100 ); + WriteD( _TL1_, tmp & 0xFF ); + break; + + // Mode 1, compteur de 16 bits. + case 1 : + tmp = ReadD( _TH1_ ) * 0x100 + ReadD( _TL1_ ); + ++tmp &= 0xFFFF; // On ne garde que 16 bits. + if ( tmp == 0 ) // If overflow set TF1 + WriteD( _TCON_, ReadD( _TCON_ ) | 0x80 ); + WriteD( _TH1_, ( tmp / 0x100 ) ); + WriteD( _TL1_, ( tmp & 0xFF ) ); + break; + + // Mode 2, Compteur de 8 bits avec Auto-Reload + case 2 : + tmp = ReadD( _TL1_ ); + ++tmp &= 0xFF; + if ( tmp == 0 ) { // If overflow -> reload et set TF1 + WriteD( _TCON_, ReadD( _TCON_ ) | 0x80 ); + WriteD( _TL1_, ReadD( _TH1_ ) ); + } + else + WriteD( _TL1_, tmp ); + break; + + // Mode 3 : mode inactif: retient la valeur de TH1 et TL1. + // Equivalent a TR1 = 0. + case 3 : + break; + + }; +} + + + +// Addressing modes defined in the order as they appear in disasm.hpp +// from table argstext[] +#define ADDR11 0 +#define ADDR16 1 +#define DIRECT 3 +#define BITADDR 14 +#define RELADDR 15 +#define DATAIMM 16 +#define DATA16 22 +#define CBITADDR 23 + +// SFR Memory map [80h - FFh] +// --------------------------------------------------------------- +// F8 | | | | | | | | | FF +// F0 | B | | | | | | | | F7 +// E8 | | | | | | | | | EF +// E0 | ACC | | | | | | | | E7 +// D8 | | | | | | | | | DF +// D0 | PSW | | | | | | | | D7 +// C8 | T2CON| |RCAP2L|RCAP2H| TL2 | TH2 | | | CF +// C0 | | | | | | | | | C7 +// B8 | IP | | | | | | | | BF +// B0 | P3 | | | | | | | | B7 +// A8 | IE | | | | | | | | AF +// A0 | P2 | | | | | | | | A7 +// 98 | SCON | SBUF | | | | | | | 9F +// 90 | P1 | | | | | | | | 97 +// 88 | TCON | TMOD | TL0 | TL1 | TH0 | TH1 | | | 8F +// 80 | P0 | SP | DPL | DPH | | | | PCON | 87 +// --------------------------------------------------------------- + +////////////////////////////////////////////////////////////////////////////// +// int CPU8051::SFRMemInfo( unsigned int Address, char *Text ) +// Return as Text the name of the SFR register at Address if any +////////////////////////////////////////////////////////////////////////////// + int CPU8051::SFRMemInfo( unsigned int Address, char *Text ) + { + switch( Address ) { + case 0x80 : return sprintf( Text, "P0" ); + case 0x81 : return sprintf( Text, "SP" ); + case 0x82 : return sprintf( Text, "DPL" ); + case 0x83 : return sprintf( Text, "DPH" ); + case 0x87 : return sprintf( Text, "PCON" ); + case 0x88 : return sprintf( Text, "TCON" ); + case 0x89 : return sprintf( Text, "TMOD" ); + case 0x8A : return sprintf( Text, "TL0" ); + case 0x8B : return sprintf( Text, "TL1" ); + case 0x8C : return sprintf( Text, "TH0" ); + case 0x8D : return sprintf( Text, "TH1" ); + case 0x90 : return sprintf( Text, "P1" ); + case 0x98 : return sprintf( Text, "SCON" ); + case 0x99 : return sprintf( Text, "SBUF" ); + case 0xA0 : return sprintf( Text, "P2" ); + case 0xA8 : return sprintf( Text, "IE" ); + case 0xB0 : return sprintf( Text, "P3" ); + case 0xB8 : return sprintf( Text, "IP" ); + case 0xC8 : return sprintf( Text, "T2CON" ); + case 0xCA : return sprintf( Text, "RCAP2L" ); + case 0xCB : return sprintf( Text, "RCAP2H" ); + case 0xCC : return sprintf( Text, "TL2" ); + case 0xCD : return sprintf( Text, "TH2" ); + case 0xD0 : return sprintf( Text, "PSW" ); + case 0xE0 : return sprintf( Text, "ACC" ); + case 0xF0 : return sprintf( Text, "B" ); + default : return sprintf( Text, "%.2XH", Address ); + } +} + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::IntMemBitInfo( unsigned int BitAddress, char *Text ) +// Return as Text the decoded BitAddress +////////////////////////////////////////////////////////////////////////////// +void CPU8051::IntMemBitInfo( unsigned int BitAddress, char *Text ) +{ +unsigned int ByteAddress, BitNumber; +int TextLength; + if ( BitAddress > 0x7F ) { + // SFR 80-FF + ByteAddress = BitAddress & 0xF8; + BitNumber = BitAddress & 0x07; + } + else { + // 20-2F + ByteAddress = ( BitAddress >> 3 ) + 0x20; + BitNumber = BitAddress & 0x07; + } + + TextLength = SFRMemInfo( ByteAddress, Text ); + // sprintf( &Text[ TextLength ], ".%X" ); + // Modified by Hugo Villeneuve to remove compilation warning + sprintf( &Text[ TextLength ], ".%X", BitAddress ); +} + + +////////////////////////////////////////////////////////////////////////////// +// int CPU8051::Disasm( unsigned int Address, char *Text ) +// Disasm one instruction at Address into a Text string +////////////////////////////////////////////////////////////////////////////// +int CPU8051::Disasm( unsigned int Address, char *Text ) +{ +int TextLength=0; +char TextTmp[20]; +unsigned char OpCode; +int ArgTblOfs; +int InstSize; +int i; + +OpCode = PGMMem->Read8( Address ); +InstSize = InstSizesTbl[ OpCode ]; +//printf("%.4X\n", Address); + +TextLength += sprintf( Text, " %.4X ", Address ); + +for (i = 0; i < InstSize; i++ ) + TextLength += sprintf( &Text[TextLength], " %.2X", PGMMem->Read8( Address + i ) ); + +Address++; + +for (; TextLength < 17; ) TextLength += sprintf( &Text[ TextLength ], " " ); + +TextLength += sprintf( &Text[ TextLength ], "%s ", InstTextTbl[ InstTypesTbl[ OpCode ] ] ); +ArgTblOfs = OpCode << 2; + +for (; TextLength < 25; ) TextLength += sprintf( &Text[ TextLength ], " " ); + + // MOV direct, direct (OpCode 85h) is peculiar, the operands are inverted + if ( OpCode == 0x85 ) { + SFRMemInfo( PGMMem->Read8( Address + 1 ), TextTmp ); + TextLength += sprintf( &Text[ TextLength ], "%s,", TextTmp ); + SFRMemInfo( PGMMem->Read8( Address ), TextTmp ); + TextLength += sprintf( &Text[ TextLength ], "%s", TextTmp ); + Address += 2; + return InstSize; + } + + for ( i = 1; i <= InstArgTbl[ ArgTblOfs ]; i++ ) { + switch( InstArgTbl[ ArgTblOfs + i ] ) { + case ADDR11 : { + TextLength += sprintf( &Text[ TextLength ], "%.4XH", ( ( OpCode << 3) & 0xF00 ) + ( PGMMem->Read8( Address ) ) ); + Address++; + break; + } + case ADDR16 : { + TextLength += sprintf( &Text[ TextLength ], "%.4XH", ( ( PGMMem->Read8( Address ) << 8 ) + PGMMem->Read8( Address + 1 ) ) ); + Address += 2; + break; + } + case DIRECT : { + SFRMemInfo( PGMMem->Read8( Address ), TextTmp ); + TextLength += sprintf( &Text[ TextLength ], "%s", TextTmp ); + Address++; + break; + } + case BITADDR : { + IntMemBitInfo( ( PGMMem->Read8( Address ) & 0xF8 ), TextTmp ); + TextLength += sprintf( &Text[ TextLength ], "%s.%X" , TextTmp, ( PGMMem->Read8( Address ) & 7 ) ); + Address++; + break; + } + case RELADDR : { + Address++; + TextLength += sprintf( &Text[ TextLength ], "%.4XH", ( Address & 0xFF00 ) + ( ( ( Address & 0xFF ) + PGMMem->Read8( Address - 1 ) ) & 0xFF ) ); + break; + } + case DATAIMM : { + TextLength += sprintf( &Text[ TextLength ], "#%.2XH", PGMMem->Read8( Address ) ); + Address++; + break; + } + case DATA16 : { + TextLength += sprintf( &Text[ TextLength ],"#%.4XH", ( ( PGMMem->Read8( Address ) << 8 ) + PGMMem->Read8( Address+1 ) ) ); + Address += 2; + break; + } + case CBITADDR : { + IntMemBitInfo( ( PGMMem->Read8( Address ) & 0xF8 ), TextTmp ); + TextLength += sprintf( &Text[ TextLength ], "/%s.%X", TextTmp, ( PGMMem->Read8( Address ) & 7 ) ); + Address++; + break; + } + default : { + TextLength += sprintf( &Text[ TextLength ],"%s", ArgsTextTbl[ InstArgTbl[ ArgTblOfs + i ] ] ); + } + } + if (i < InstArgTbl[ ArgTblOfs ]) { TextLength += sprintf( &Text[ TextLength ], "," ); } + } + +return InstSize; +} + + +#include "Inst_Imp.cpp" + + + + + + diff --git a/src/CPU8051.hpp b/src/CPU8051.hpp new file mode 100644 index 0000000..d51d8aa --- /dev/null +++ b/src/CPU8051.hpp @@ -0,0 +1,62 @@ +#ifndef _CPU8051_HPP_ +#define _CPU8051_HPP_ + +#include "Memory.hpp" +#include "Reg8051.hpp" + +#define BANKPSW ( ReadD( _PSW_ ) & 0x18 ) + +////////////////////////////////////////////////////////////////////////////// +// CPU8051 +// Implements the 8051 CPU Object +////////////////////////////////////////////////////////////////////////////// +class CPU8051 { +public: + CPU8051( ); + ~CPU8051( ); + + void Exec( ); + void Reset( ); + unsigned int GetPC( ); + void SetPC( unsigned int NewPC ); + void WriteD( unsigned int Address, unsigned char Value ); + void WriteExt( unsigned int Address, unsigned char Value ); + void WriteInt( unsigned int Address, unsigned char Value ); + void WriteI( unsigned int Address, unsigned char Value ); + void WritePGM( unsigned int Address, unsigned char Value ); + unsigned char ReadD( unsigned int Address ); + unsigned char ReadInt( unsigned int Address ); + unsigned char ReadExt( unsigned int Address ); + unsigned char ReadI( unsigned int Address ); + unsigned char ReadPGM( unsigned int Address ); + unsigned int GetNextAddress( ); + + void WriteB( unsigned int BitAddress, unsigned char Value ); + unsigned char ReadB( unsigned int BitAddress ); + + void CheckInterrupts( ); + void DoTimers( ); + + int SFRMemInfo( unsigned int Address, char *Text ); + void IntMemBitInfo( unsigned int BitAddress, char *Text ); + int Disasm( unsigned int Address, char *Text ); + +private: + Memory *SFRMem; + Memory *PGMMem; + Memory *IntMem; + Memory *ExtMem; + unsigned int PC; + unsigned long CLOCK; + int ActivePriority; + int (CPU8051::*funcptr[256])(); + + #include "Inst_Def.hpp" + +}; + + + + +#endif + diff --git a/src/EmuConsole.cpp b/src/EmuConsole.cpp new file mode 100644 index 0000000..0a0fe66 --- /dev/null +++ b/src/EmuConsole.cpp @@ -0,0 +1,737 @@ +// EmuConsole.cpp + +#include +#include +#include +#include "config.h" +#include "EmuConsole.hpp" +#include "CPU8051.hpp" +#include "Reg8051.hpp" +#include "Keyboard.hpp" + + +int main( int argc, char **argv ) +{ + CPU8051 *maincpu = new CPU8051; + + EmuConsole *emuUI = new EmuConsole( argc, argv, maincpu ); + + emuUI->Main(); + printf( "End of program.\n" ); + + delete emuUI; + delete maincpu; + + return 0; +} + + +////////////////////////////////////////////////////////////////////////////// +// EmuConsole::EmuConsole( int argc, char **argv, CPU8051 *mCPU ) +// EmuConsole constructor +////////////////////////////////////////////////////////////////////////////// +EmuConsole::EmuConsole( int argc, char **argv, CPU8051 *mCPU ) +{ + CPU = mCPU; + CPU->Reset( ); + NbBreakpoints = 0; + if ( argc > 1 ) LoadHexFile( argv[ 1 ] ); +} + +////////////////////////////////////////////////////////////////////////////// +// EmuConsole::~EmuConsole( ) +// EmuConsole destructor +////////////////////////////////////////////////////////////////////////////// +EmuConsole::~EmuConsole( ) +{ +} + +////////////////////////////////////////////////////////////////////////////// +// void EmuConsole::Main( ) +// EmuConsole main loop +////////////////////////////////////////////////////////////////////////////// +void EmuConsole::Main( ) +{ + /*int ASCII_Code;*/ + unsigned int Index; + + string InputString; + string Command; + string Parameter1; + string Parameter2; + char prompt[] = "-> "; + + char *Title[] = { " *******************", + " * 8051 Emulator *", + " *******************", + "", 0 }; + + char *Menu[] = { + " Available commands, [ ] = options", + "", + " Set Breakpoint.............. SB [address]", + " Remove Breakpoint........... RB [address]", + " Display Breakpoint(s)....... DB", + " Dump External Data Memory... DE [address]", + " Dump Internal Data Memory... DI [address]", + " Dump Program Memory......... DP [address]", + " Display Registers content... DR", + " Execute..................... EM [address [number of instructions]]", + " Help........................ H", + " Modify External Data Memory. ME address value", + " Modify Internal Data Memory. MI address value", + " Modify Program Memory....... MP address value", + " Modify Register............. MR register value", + " Quit Emulator............... Q", + " Trace mode.................. T [address]", + " Unassemble.................. U [address [numberof instructions]]", + " Reset processor............. Z", 0 }; + + + Index = 0; + while ( Title[ Index ] != 0 ) printf( "%s%s", Title[ Index++ ], ENDLINE ); + Index = 0; + while ( Menu[ Index ] != 0 ) printf( "%s%s", Menu[ Index++ ], ENDLINE ); + + Reset( ); + int QuitRequest = 0; + + while( !QuitRequest ) { + try { + + printf( prompt ); + getline ( cin, InputString, '\n' ); + Capitalize( &InputString ); + RemoveSpaces( &InputString ); + + for ( Index = 0; Index < InputString.size( ); Index++ ) { + if ( InputString[ Index ] < 'A' || InputString[ Index ] > 'z' ) + break; + } + + Command = InputString; + // Keep only the Command part from the input line + Command.replace( Index, Command.size( ), 0, ( char )0 ); + // Keep only the arguments + InputString.replace( 0, Index, 0, ( char )0 ); + + RemoveSpaces ( &InputString ); + Index = 0; + while ( ( Index < InputString.size( ) ) && ( InputString [ Index ] != ' ' ) ) Index++; + Parameter1 = InputString; + Parameter1.replace( Index, Parameter1.size( ), 0, ( char )0 ); + InputString.replace( 0, Index, 0, ( char )0 ); + + RemoveSpaces ( &InputString ); + Index = 0; + while ( ( Index < InputString.size( ) ) && ( InputString [ Index ] != ' ' ) ) Index++; + Parameter2 = InputString; + Parameter2.replace( Index, Parameter2.size( ), 0, ( char )0 ); + InputString.replace( 0, Index, 0, ( char )0 ); + + RemoveSpaces ( &InputString ); + if ( !InputString.empty( ) ) + throw SyntaxError( ); + + if ( Command.empty( ) && !Parameter1.empty( ) ) + throw SyntaxError( ); + + if ( ( Parameter1.size( ) > 4 ) || ( Parameter2.size( ) > 4 ) ) + throw InvalidParameter( ); + + if ( !Command.empty( ) ) { + switch ( Command [ 0 ] ) { + + case 'D' : + if ( Parameter2.empty( ) ) { + if ( Command == "DB" && Parameter1.empty( ) ) + ShowBreakpoints( ); + else if ( Command == "DE" ) + DumpExt( Parameter1 ); + else if ( Command == "DI" ) + DumpInt( Parameter1 ); + else if ( Command == "DP" ) { + if ( Parameter1.empty( ) ) + Parameter1 = "PC"; + DumpPGM( Parameter1 ); + } + else if ( Command == "DR" && Parameter1.empty( ) ) + ShowRegisters( ); + else + throw SyntaxError( ); + } + else + throw SyntaxError( ); + break; + + case 'E' : + if ( Command == "EM" ) + Exec( Parameter1, Parameter2 ); + else + throw SyntaxError( ); + break; + case 'H' : + if ( Command == "H" && Parameter1.empty( ) && Parameter2.empty( ) ) + { + Index = 0; + while ( Menu[ Index ] != 0 ) printf( "%s%s", Menu[ Index++ ], ENDLINE ); + } + else + throw SyntaxError( ); + break; + case 'M' : + if ( Parameter1.empty() || Parameter2.empty() ) + throw MissingParameter(); + else if ( Command == "ME" ) { + unsigned int adresse = Ascii2Hex( Parameter1, 4 ); + unsigned char valeur = Ascii2Hex( Parameter2, 2 ); + CPU->WriteExt( adresse, valeur ); + } + else if ( Command == "MI" ) { + unsigned char adresse = Ascii2Hex( Parameter1, 2 ); + unsigned char valeur = Ascii2Hex( Parameter2, 2 ); + CPU->WriteInt( adresse, valeur ); + } + else if ( Command == "MP" ) { + unsigned int adresse = Ascii2Hex( Parameter1, 4 ); + unsigned char valeur = Ascii2Hex( Parameter2, 2 ); + CPU->WritePGM( adresse, valeur ); + } + else if ( Command == "MR" ) + SetRegister( Parameter1, Parameter2 ); + else + throw SyntaxError(); + break; + case 'Q' : + if ( Command == "Q" && Parameter1.empty( ) && Parameter2.empty( ) ) + QuitRequest = 1; + else + throw SyntaxError( ); + break; + case 'R' : + if ( !Parameter2.empty( ) ) + throw TooMuchParameters( ); + if ( Command == "RB" ) { + if ( Parameter1.empty( ) ) + ClearBreakpoint( CPU->GetPC( ) ); + else + ClearBreakpoint( Ascii2Hex( Parameter1, 4 ) ); + } + else + throw SyntaxError( ); + break; + case 'S' : + if ( !Parameter2.empty( ) ) + throw TooMuchParameters( ); + if ( Command == "SB" ) { + if ( Parameter1.empty( ) ) + SetBreakpoint( CPU->GetPC( ) ); + else + SetBreakpoint( Ascii2Hex( Parameter1, 4 ) ); + } + else + throw SyntaxError( ); + break; + case 'T' : + if ( !Parameter2.empty( ) ) + throw TooMuchParameters( ); + if ( Command == "T" ) + Trace( Parameter1 ); + else + throw SyntaxError( ); + break; + case 'U' : + if ( Command == "U" ) + Disasm( Parameter1, Parameter2 ); + else + throw SyntaxError( ); + break; + case 'Z' : + if ( Command == "Z" && Parameter1.empty( ) && Parameter2.empty( ) ) + Reset( ); + else + throw SyntaxError( ); + break; + case '\n' : + break; + default : + throw SyntaxError( ); + } + } + } + catch ( SyntaxError ) { + printf( "Syntax Error!%s", ENDLINE ); + } + catch ( MissingParameter ) { + printf( "Missing Parameter!%s", ENDLINE ); + } + catch ( InvalidParameter ) { + printf( "Invalid Parameter Format!%s", ENDLINE ); + } + catch ( TooMuchParameters ) { + printf( "Wrong Number of Parameters!%s", ENDLINE ); + } + catch ( ResetRequest ) { + printf( "Resetting Microcontroler...%s", ENDLINE ); + } + catch ( InvalidRegister ) { + printf( "%sInvalid register name!%s", ENDLINE, ENDLINE ); + printf( "Valid registers are A, B, PC and SP.%s", ENDLINE ); + } + } +} + +////////////////////////////////////////////////////////////////////////////// +// void EmuConsole::Reset( ) +// CPU reset and Console UI update +////////////////////////////////////////////////////////////////////////////// +void EmuConsole::Reset( ) +{ + printf( "Resetting... " ); + CPU->Reset( ); + printf( "Done.%s", ENDLINE ); + ShowRegisters( ); +} + +////////////////////////////////////////////////////////////////////////////// +// void EmuConsole::Trace( string Address ) +// CPU trace and Console UI update +////////////////////////////////////////////////////////////////////////////// +void EmuConsole::Trace( string Address ) +{ + if ( !Address.empty( ) ) CPU->SetPC( Ascii2Hex( Address, Address.size( ) ) ); + CPU->Exec( ); + ShowRegisters( ); + DisasmN( CPU->GetPC( ), 1 ); +} + +////////////////////////////////////////////////////////////////////////////// +// void EmuConsole::Exec( string Address, string NumberInst ) +// CPU exec and Console UI update +////////////////////////////////////////////////////////////////////////////// +void EmuConsole::Exec( string Address, string NumberInst ) +{ + char dummy; + int NbInst = -1; // -1 is infinity + if ( !Address.empty( ) ) { + Capitalize( &Address ); + if ( Address != "PC" ) CPU->SetPC( Ascii2Hex( Address, Address.size( ) ) ); + } + + if ( !NumberInst.empty( ) ) NbInst = Ascii2Hex( NumberInst, NumberInst.size( ) ); + + InitUnixKB( ); + + printf( "Program executing...%s", ENDLINE ); + + do { + CPU->Exec( ); + if ( NbInst > 0 ) NbInst--; + } while ( !IsBreakpoint( CPU->GetPC( ) ) && ( NbInst != 0 ) && !kbhit( ) ); + if ( kbhit( ) ) { + dummy = getch( ); // flush key + printf( "Caught break signal!%s", ENDLINE ); + } + if ( NbInst == 0 ) printf( "Number of instructions reached! Stopping!%s", ENDLINE ); + if ( IsBreakpoint( CPU->GetPC( ) ) ) printf( "Breakpoint hit at %.4X! Stopping!%s", CPU->GetPC( ), ENDLINE ); + + ResetUnixKB( ); +} + +////////////////////////////////////////////////////////////////////////////// +// void EmuConsole::ShowBreakpoints( ) +// Show Breakpoints list +////////////////////////////////////////////////////////////////////////////// +void EmuConsole::ShowBreakpoints( ) +{ + for ( int Index = 0; Index < NbBreakpoints ; Index++ ) + printf( "Breakpoint at Address = %.4X%s", Breakpoints[ Index ], ENDLINE ); +} + +////////////////////////////////////////////////////////////////////////////// +// void EmuConsole::ClearBreakpoint( unsigned int Address ) +// Clear Breakpoint at Address from list +////////////////////////////////////////////////////////////////////////////// +void EmuConsole::ClearBreakpoint( unsigned int Address ) +{ + int Index = 0; + while ( Index < NbBreakpoints && Breakpoints[ Index ] != Address ) Index++; + if ( Breakpoints[ Index ] != Address ) return; + Breakpoints[ Index ] = Breakpoints[ NbBreakpoints - 1 ]; + NbBreakpoints--; +} + +////////////////////////////////////////////////////////////////////////////// +// void EmuConsole::SetBreakpoint( unsigned int Address ) +// Set Breakpoint at Address from list +////////////////////////////////////////////////////////////////////////////// +void EmuConsole::SetBreakpoint( unsigned int Address ) +{ + if ( IsBreakpoint( Address ) ) return; + if ( NbBreakpoints < MAXBP ) Breakpoints[ NbBreakpoints++ ] = Address; +} + +////////////////////////////////////////////////////////////////////////////// +// int EmuConsole::IsBreakpoint( unsigned int Address ) +// Is the a breakpoint at Address +////////////////////////////////////////////////////////////////////////////// +int EmuConsole::IsBreakpoint( unsigned int Address ) +{ + int Index = 0; + while ( Index < NbBreakpoints && Breakpoints[ Index ] != Address ) Index++; + return ( Breakpoints[ Index ] == Address && Index < NbBreakpoints ); +} + + +////////////////////////////////////////////////////////////////////////////// +// void EmuConsole::Disasm( string Address, string NumberInst ) +// Disassemble 16 instructions at Address +////////////////////////////////////////////////////////////////////////////// +void EmuConsole::Disasm( string Address, string NumberInst ) +{ + unsigned int MemAddress, NbInst; + Capitalize( &Address ); + if ( Address.empty( ) || ( Address == "PC" ) ) MemAddress = CPU->GetPC( ); + else MemAddress = Ascii2Hex( Address, Address.size( ) ); + if ( NumberInst.empty( ) ) NumberInst = "10"; + NbInst = Ascii2Hex( NumberInst, NumberInst.size( ) ); + DisasmN( MemAddress, NbInst ); +} + +////////////////////////////////////////////////////////////////////////////// +// void EmuConsole::DisasmN( unsigned int Address, int NumberInst ) +// Disassemble NumberInst instructions at Address +////////////////////////////////////////////////////////////////////////////// +void EmuConsole::DisasmN( unsigned int Address, int NumberInst ) +{ +char TextTmp[255]; +int Row; + for ( Row = 0; Row < NumberInst ; Row++ ) { + Address += CPU->Disasm( Address, TextTmp ); + printf( "%s%s", TextTmp, ENDLINE ); + } +} + +////////////////////////////////////////////////////////////////////////////// +// void EmuConsole::DumpPGM( string Address ) +// Dump Program memory +////////////////////////////////////////////////////////////////////////////// +void EmuConsole::DumpPGM( string Address ) +{ + unsigned int MemAddress = 0; + int Offset, Column; + unsigned char Byte; + if ( !Address.empty( ) ) { + Capitalize( &Address ); + if ( Address == "PC" ) + MemAddress = CPU->GetPC( ); + else + MemAddress = Ascii2Hex( Address, Address.size( ) ); + } + for ( Offset = 0; Offset < 256; Offset += 16 ) { + printf( "%.4X ", MemAddress + Offset ); + for ( Column = 0; Column < 16; Column++ ) + printf( " %.2X", ( int )CPU->ReadPGM( MemAddress + Offset + Column ) ); + printf( " " ); + for ( Column = 0; Column < 16; Column++ ) { + Byte = CPU->ReadPGM( MemAddress + Offset + Column ); + if ( ( int )Byte >= 32 && ( int )Byte <= 126 ) + printf( "%c", Byte ); + else printf( "." ); + } + printf( "%s", ENDLINE ); + } + +} + + + + +////////////////////////////////////////////////////////////////////////////// +// void EmuConsole::DumpI( string Address ) +// Dump using Indirect read access +////////////////////////////////////////////////////////////////////////////// +void EmuConsole::DumpI( string Address ) +{ + unsigned int MemAddress = 0; + int Offset, Column; + unsigned char Byte; + if ( !Address.empty( ) ) MemAddress = Ascii2Hex( Address, Address.size( ) ); + for ( Offset = 0; Offset < 256; Offset += 16 ) { + printf( "%.4X ", MemAddress + Offset ); + for ( Column = 0; Column < 16; Column++ ) + printf( " %.2X", ( int )CPU->ReadI( MemAddress + Offset + Column ) ); + printf( " " ); + for ( Column = 0; Column < 16; Column++ ) { + Byte = CPU->ReadI( MemAddress + Offset + Column ); + if ( ( int )Byte >= 32 && ( int )Byte <= 126 ) + printf( "%c", Byte ); + else printf( "." ); + } + printf( "%s", ENDLINE ); + } +} + +////////////////////////////////////////////////////////////////////////////// +// void EmuConsole::DumpInt( string Address ) +// Dump internal Data memory +////////////////////////////////////////////////////////////////////////////// +void EmuConsole::DumpInt( string Address ) +{ + unsigned int MemAddress = 0; + int Offset, Column; + unsigned char Byte; + if ( !Address.empty( ) ) + MemAddress = Ascii2Hex( Address, 4 ); + for ( Offset = 0; Offset < 256; Offset += 16 ) { + printf( "%.4X ", MemAddress + Offset ); + for ( Column = 0; Column < 16; Column++ ) + printf( " %.2X", ( int )CPU->ReadInt( MemAddress + Offset + Column ) ); + printf( " " ); + for ( Column = 0; Column < 16; Column++ ) { + Byte = CPU->ReadInt( MemAddress + Offset + Column ); + if ( ( int )Byte >= 32 && ( int )Byte <= 126 ) + printf( "%c", Byte ); + else printf( "." ); + } + printf( "%s", ENDLINE ); + } +} + + +////////////////////////////////////////////////////////////////////////////// +// void EmuConsole::DumpExt( string Address ) +// Dump de la memoire externe ( $00 a $FFFF) +////////////////////////////////////////////////////////////////////////////// +void EmuConsole::DumpExt( string Address ) +{ + unsigned int MemAddress = 0; + int Offset, Column; + unsigned char Byte; + if ( !Address.empty( ) ) + MemAddress = Ascii2Hex( Address, 4 ); + for ( Offset = 0; Offset < 256; Offset += 16 ) { + printf( "%.4X ", MemAddress + Offset ); + for ( Column = 0; Column < 16; Column++ ) + printf( " %.2X", ( int )CPU->ReadExt( MemAddress + Offset + Column ) ); + printf( " " ); + for ( Column = 0; Column < 16; Column++ ) { + Byte = CPU->ReadExt( MemAddress + Offset + Column ); + if ( ( int )Byte >= 32 && ( int )Byte <= 126 ) + printf( "%c", Byte ); + else printf( "." ); + } + printf( "%s", ENDLINE ); + } +} + +////////////////////////////////////////////////////////////////////////////// +// void EmuConsole::DumpD( string Address ) +// Dump using Direct read access +////////////////////////////////////////////////////////////////////////////// +void EmuConsole::DumpD( string Address ) +{ + unsigned int MemAddress = 0; + int Offset, Column; + unsigned char Byte; + if ( !Address.empty( ) ) MemAddress = Ascii2Hex( Address, Address.size( ) ); + for ( Offset = 0; Offset < 256; Offset += 16 ) { + printf( "%.4X ", MemAddress + Offset ); + for ( Column = 0; Column < 16; Column++ ) + printf( " %.2X", ( int )CPU->ReadD( MemAddress + Offset + Column ) ); + printf( " " ); + for ( Column = 0; Column < 16; Column++ ) { + Byte = CPU->ReadD( MemAddress + Offset + Column ); + if ( ( int )Byte >= 32 && ( int )Byte <= 126 ) + printf( "%c", Byte ); + else printf( "." ); + } + printf( "%s", ENDLINE ); + } +} + +////////////////////////////////////////////////////////////////////////////// +// void EmuConsole::SetRegister( string Register, string NewValue ) +// Set NewValue to Register +////////////////////////////////////////////////////////////////////////////// +void EmuConsole::SetRegister( string Register, string NewValue ) +{ + Capitalize( &Register ); + if ( Register == "PC" ) CPU->SetPC( Ascii2Hex( NewValue, 4 ) ); + else if ( Register == "A" ) CPU->WriteD( _ACC_, Ascii2Hex( NewValue, 2 ) ); + else if ( Register == "B" ) CPU->WriteD( _B_, Ascii2Hex( NewValue, 2 ) ); + else if ( Register == "SP" ) CPU->WriteD( _SP_, Ascii2Hex( NewValue, 2 ) ); + else throw InvalidRegister( ); +} + +////////////////////////////////////////////////////////////////////////////// +// void EmuConsole::Capitalize( string *InputString ) +// Capitalize all letters in InputString +////////////////////////////////////////////////////////////////////////////// +void EmuConsole::Capitalize( string *InputString ) +{ + for (unsigned int Index = 0; Index < InputString->size( ); Index++ ) { + { + if ( ( ( *InputString )[ Index ] >= 'a' ) && ( ( *InputString )[ Index ] <= 'z' ) ) + ( *InputString )[ Index ] -= ( ( int )'a'- ( int )'A' ); + } + } +} + +////////////////////////////////////////////////////////////////////////////// +// void EmuConsole::RemoveSpaces( string *InputString ) +// Remove spaces from InputString +////////////////////////////////////////////////////////////////////////////// +void EmuConsole::RemoveSpaces( string *InputString ) +{ + unsigned int Index = 0; + + while ( ( Index < ( *InputString ).size( ) ) && ( *InputString )[ Index ] == ' ' ) { + Index++; + } + ( *InputString ).replace( 0, Index, 0, ( char )0 ); +} + +////////////////////////////////////////////////////////////////////////////// +// void EmuConsole::ShowRegisters( ) +// Show CPU registers +////////////////////////////////////////////////////////////////////////////// +void EmuConsole::ShowRegisters( ) +{ + unsigned char PSW = CPU->ReadD( _PSW_ ); + int BankSelect = ( PSW & 0x18 ); + + printf( "----------------------------------------------------------------------%s", ENDLINE ); + printf( "| PC | SP | DPTR | ACC | B | PSW: CY AC F0 RS1 RS0 OV - P |%s", ENDLINE ); + printf( "| %.4X | %.2X | %.4X | %.2X | %.2X |", CPU->GetPC( ), CPU->ReadD( _SP_ ), ( CPU->ReadD( _DPTRHIGH_ ) << 8 ) + CPU->ReadD( _DPTRLOW_ ), CPU->ReadD( _ACC_ ), CPU->ReadD( _B_ ) ); + printf( " %d %d %d %d %d %d %d %d |", ( PSW >> 7 ) & 1, ( PSW >> 6 ) & 1, ( PSW >> 5 ) & 1, ( PSW >> 4 ) & 1, ( PSW >> 3 ) & 1, ( PSW >> 2 ) & 1, ( PSW >> 1 ) & 1, PSW & 1 ); + printf( "%s", ENDLINE ); + printf( "----------------------------------------------------------------------%s", ENDLINE ); + + printf( "| TCON | TMOD | IE | IP | R0 | R1 | R2 | R3 | R4 | R5 | R6 | R7 | |%s", ENDLINE ); + printf( "| %.2X | %.2X | %.2X | %.2X ", CPU->ReadD( _TCON_ ), CPU->ReadD( _TMOD_ ), CPU->ReadD( _IE_ ), CPU->ReadD( _IP_ ) ); + printf( "| %.2X | %.2X | %.2X | %.2X ", CPU->ReadD( BankSelect + _R0_ ), CPU->ReadD( BankSelect + _R1_ ), CPU->ReadD( BankSelect + _R2_ ), CPU->ReadD( BankSelect + _R3_ ) ); + printf( "| %.2X | %.2X | %.2X | %.2X ", CPU->ReadD( BankSelect + _R4_ ), CPU->ReadD( BankSelect + _R5_ ), CPU->ReadD( BankSelect + _R6_ ), CPU->ReadD( BankSelect + _R7_ ) ); + printf( "| |%s", ENDLINE ); + + printf( "----------------------------------------------------------------------%s", ENDLINE ); + +} + +////////////////////////////////////////////////////////////////////////////// +// void EmuConsole::LoadHexFile( string Filename ) +// +////////////////////////////////////////////////////////////////////////////// +void EmuConsole::LoadHexFile( string Filename ) +{ + + printf("LoadHex\n"); + int i, j, RecLength, LoadOffset, RecType, Data, Checksum; + char Line[ 250 ]; + + ifstream HexFile( Filename.c_str() ); + try { + if ( ! HexFile ) + throw ErrorOpeningFile(); + + while( ! HexFile.eof() ) { + i = 0; + Checksum = 0; + HexFile.getline( Line, 250, '\n' ); + + if ( Line[ i++ ] != ':' ) + throw ErrorHexFileFormat(); + + RecLength = Ascii2Hex( &Line[ i ], 2 ); + i += 2; + Checksum += RecLength; + + LoadOffset = Ascii2Hex( &Line[i], 4 ); + Checksum += LoadOffset / 256; + Checksum += LoadOffset % 256; + i += 4; + + RecType = Ascii2Hex( &Line[i],2); + i += 2; + Checksum += RecType; + + if ( RecType == 1 ) { + Checksum += Ascii2Hex( &Line[ i ], 2 ); + if ( Checksum &= 0x000000FF ) + throw ErrorHexFileFormat(); + throw FinishedLoading(); + } + if ( RecType ) + throw ErrorHexFileFormat(); + + for ( j = 0; j < RecLength; j++ ) { + Data = Ascii2Hex( &Line[ i ], 2 ); + CPU->WritePGM( (unsigned int)(LoadOffset + j), (unsigned char)Data ); + i += 2; + Checksum += Data; + } + RecType = Ascii2Hex( &Line[ i ], 2 ); + Checksum += RecType; + + if ( Checksum &= 0x000000FF ) + throw ErrorHexFileFormat(); + } + throw ErrorHexFileFormat(); + } + catch ( ErrorOpeningFile ) { + cout << "Error opening file " << Filename << endl; + } + catch ( ErrorHexFileFormat ) { + cout << "Invalid format for " << Filename << " file..." << endl; + } + catch ( SyntaxError ) { + cout << "Invalid format for " << Filename << " file..." << endl; + } + catch ( MissingParameter ) { + cout << "Invalid format for " << Filename << " file..." << endl; + } + catch ( FinishedLoading ) { + cout << "Using file " << Filename << " as input program." << endl; + } + HexFile.close(); + +} + +////////////////////////////////////////////////////////////////////////////// +// unsigned int EmuConsole::Ascii2Hex( string istring, int length ) +// +////////////////////////////////////////////////////////////////////////////// +unsigned int EmuConsole::Ascii2Hex( string istring, unsigned int length ) +{ + if ( !length || ( length > istring.size() ) ) + length = istring.size(); + + if ( istring.empty() ) + throw MissingParameter(); + + unsigned int result = 0; + unsigned int i, ascii_code; + for ( i = 0; i < length; i++ ) { + ascii_code = istring[ i ]; + if ( ascii_code > 0x39 ) + ascii_code &= 0xDF; + if ( ( ascii_code >= 0x30 && ascii_code <= 0x39 ) || ( ascii_code >= 0x41 && ascii_code <= 0x46 ) ) { + ascii_code -= 0x30; + if ( ascii_code > 9 ) + ascii_code -= 7; + result <<= 4; + result += ascii_code; + } + else { + throw SyntaxError(); + } + } + return result; +} + + + + + + + diff --git a/src/EmuConsole.hpp b/src/EmuConsole.hpp new file mode 100644 index 0000000..0c2c094 --- /dev/null +++ b/src/EmuConsole.hpp @@ -0,0 +1,65 @@ +#ifndef _EMUCONSOLE_HPP_ +#define _EMUCONSOLE_HPP_ + +#include "CPU8051.hpp" +#include +#include "exceptions.hpp" + +using namespace std; + +// Maximum number of BreakPoints +#define MAXBP 32 + +#define ENDLINE "\n" + + + +////////////////////////////////////////////////////////////////////////////// +// EmuConsole +// Implements the Console User Interface as an Object +////////////////////////////////////////////////////////////////////////////// +class EmuConsole { +public: + + EmuConsole( int argc, char **argv, CPU8051 *mCPU ); + ~EmuConsole( ); + + void Main( ); + + void Reset( ); + void Trace( string Address ); + void Exec( string Address, string NumberInst ); + void ShowBreakpoints( ); + void SetBreakpoint( unsigned int Address ); + void ClearBreakpoint( unsigned int Address ); + int IsBreakpoint( unsigned int Address ); + void Disasm( string Address, string NumberInst ); + void DisasmN( unsigned int Address, int NumberInst ); + void DumpPGM( string Address ); + void DumpD( string Address ); + void DumpInt( string Address ); + void DumpExt( string Address ); + void DumpI( string Address ); + void ShowRegisters( ); + void SetRegister( string Register, string NewValue ); + + + +private: + CPU8051 *CPU; + int NbBreakpoints; + unsigned int Breakpoints[ MAXBP ]; + + void LoadHexFile( string Filename ); + unsigned int Ascii2Hex( string istring, unsigned int length ); + void Capitalize( string *InputString ); + void RemoveSpaces( string *InputString ); + +}; + + + +#endif + + + diff --git a/src/EmuGtk.cpp b/src/EmuGtk.cpp new file mode 100644 index 0000000..ee91146 --- /dev/null +++ b/src/EmuGtk.cpp @@ -0,0 +1,735 @@ +// EmuGtk.cpp + +#include +#include +#include "config.h" +#include "CPU8051.hpp" +#include "EmuGtk.hpp" +#include "exceptions.hpp" +#include "pixmaps/reset.xpm" +#include "pixmaps/run.xpm" +#include "pixmaps/stop.xpm" +#include "pixmaps/step.xpm" + + +int EmuGtkNumber = 0; +int NbSignals = 0; +int SignalsData[ 32 ]; +EmuGtk *EmuGtkPtr; + + +enum +{ + DestroySignal=0, + DeleteSignal, + OpenISignal, + QuitISignal, + AboutISignal, + ResetBSignal, + RunBSignal, + StopBSignal, + StepBSignal +}; + + +int main( int argc, char **argv ) +{ + CPU8051 *maincpu = new CPU8051; + EmuGtk *emuUI = new EmuGtk( argc, argv, maincpu ); + + emuUI->Main(); + printf( "End of program.\n" ); + + delete emuUI; + delete maincpu; + + return 0; +} + +////////////////////////////////////////////////////////////////////////////// +// EmuGtk::EmuGtk( ) +// EmuGtk constructor +////////////////////////////////////////////////////////////////////////////// +EmuGtk::EmuGtk( int argc, char **argv, CPU8051 *mCPU ) +{ + CPU = mCPU; + RunningState = 0; + + g_print( "\n" ); + + gtk_init( &argc, &argv ); + + emuwin = gtk_window_new( GTK_WINDOW_TOPLEVEL ); + gtk_window_set_title( GTK_WINDOW( emuwin ), "emu8051" ); + gtk_container_set_border_width( GTK_CONTAINER( emuwin ), 0 ); + gtk_widget_show( emuwin ); + + emufixed = gtk_fixed_new(); + gtk_widget_set_usize( GTK_WIDGET( emufixed ), MAIN_WIN_WIDTH, MAIN_WIN_HEIGHT ); + gtk_container_add( GTK_CONTAINER( emuwin ), emufixed ); + gtk_widget_show( emufixed ); + + // EmuMenuBar( ); + + // Main window + emumainfixed = gtk_fixed_new(); + gtk_widget_set_usize( GTK_WIDGET( emumainfixed ), MAIN_WIN_WIDTH, REG_WIN_HEIGHT + MEM_WIN_HEIGHT + BUTTONS_BAR_HEIGHT + 10 ); + gtk_fixed_put( GTK_FIXED( emufixed ), emumainfixed, 0, 25 ); + gtk_widget_show( emumainfixed ); + + ShowMenu(); + + AddButtons(); + + // Registers frame + regfrm = gtk_frame_new( 0 ); + gtk_frame_set_shadow_type( GTK_FRAME( regfrm ), GTK_SHADOW_ETCHED_OUT ); + gtk_widget_set_usize( GTK_WIDGET( regfrm ), REG_WIN_WIDTH, REG_WIN_HEIGHT ); + gtk_fixed_put( GTK_FIXED( emumainfixed ), regfrm, 0, BUTTONS_BAR_HEIGHT ); + regwin = new RegWin( regfrm ); + gtk_widget_show( regfrm ); + + // Program disassembly frame + pgmfrm = gtk_frame_new( 0 ); + gtk_frame_set_shadow_type( GTK_FRAME( pgmfrm ), GTK_SHADOW_ETCHED_OUT ); + gtk_widget_set_usize( GTK_WIDGET( pgmfrm ), PGM_WIN_WIDTH, PGM_WIN_HEIGHT ); + gtk_fixed_put( GTK_FIXED( emumainfixed ), pgmfrm, REG_WIN_WIDTH + 10, BUTTONS_BAR_HEIGHT ); + pgmwin = new PgmWin( pgmfrm, CPU ); + gtk_widget_show( pgmfrm ); + + // Memory dump frame + memfrm = gtk_frame_new( 0 ); + gtk_frame_set_shadow_type( GTK_FRAME( memfrm ), GTK_SHADOW_ETCHED_OUT ); + gtk_widget_set_usize( GTK_WIDGET( memfrm ), MEM_WIN_WIDTH, MEM_WIN_HEIGHT ); + gtk_fixed_put( GTK_FIXED( emumainfixed ), memfrm, 0, REG_WIN_HEIGHT + BUTTONS_BAR_HEIGHT ); + memwin = new MemWin( memfrm ); + gtk_widget_show( memfrm ); + + + if ( EmuGtkNumber >= 1 ) + g_print( "WARNING! Signal too much EmuGtk Objects to handle signals!\n"); + else + { + EmuGtkPtr = this; + NbSignals = 0; + + // Window DESTROY signal + SignalsData[ NbSignals ] = DestroySignal; + gtk_signal_connect( GTK_OBJECT( emuwin ), "destroy", GTK_SIGNAL_FUNC( EmuGtkSignalStub2 ), &SignalsData[ NbSignals ] ); + NbSignals++; + + // Window DELETE event + SignalsData[ NbSignals ] = DeleteSignal; + gtk_signal_connect( GTK_OBJECT( emuwin ), "delete_event", GTK_SIGNAL_FUNC( EmuGtkSignalStub3 ), &SignalsData[ NbSignals ] ); + NbSignals++; + + // File->Open + SignalsData[ NbSignals ] = OpenISignal; + gtk_signal_connect( GTK_OBJECT( OpenItem ), "activate", GTK_SIGNAL_FUNC( EmuGtkSignalStub2 ), &SignalsData[ NbSignals ] ); + NbSignals++; + + // File->Quit + SignalsData[ NbSignals ] = QuitISignal; + gtk_signal_connect( GTK_OBJECT( QuitItem ), "activate", GTK_SIGNAL_FUNC( EmuGtkSignalStub2 ), &SignalsData[ NbSignals ] ); + NbSignals++; + + // Help->About + SignalsData[ NbSignals ] = AboutISignal; + gtk_signal_connect( GTK_OBJECT( AboutItem ), "activate", GTK_SIGNAL_FUNC( EmuGtkSignalStub2 ), &SignalsData[ NbSignals ] ); + NbSignals++; + + // RESET button + SignalsData[ NbSignals ] = ResetBSignal; + gtk_signal_connect( GTK_OBJECT( ButtonReset ), "button-press-event", GTK_SIGNAL_FUNC( EmuGtkSignalStub3 ), &SignalsData[ NbSignals ] ); + NbSignals++; + + // RUN button + SignalsData[ NbSignals ] = RunBSignal; + gtk_signal_connect( GTK_OBJECT( ButtonRun ), "button-press-event", GTK_SIGNAL_FUNC( EmuGtkSignalStub3 ), &SignalsData[ NbSignals ] ); + NbSignals++; + + // STOP button + SignalsData[ NbSignals ] = StopBSignal; + gtk_signal_connect( GTK_OBJECT( ButtonStop ), "button-press-event", GTK_SIGNAL_FUNC( EmuGtkSignalStub3 ), &SignalsData[ NbSignals ] ); + NbSignals++; + + // STEP button + SignalsData[ NbSignals ] = StepBSignal; + gtk_signal_connect( GTK_OBJECT( ButtonStep ), "button-press-event", GTK_SIGNAL_FUNC( EmuGtkSignalStub3 ), &SignalsData[ NbSignals ] ); + NbSignals++; + + EmuGtkNumber++; + } + + if ( argc > 1 ) + LoadHexFile( argv[1] ); +} + + + +////////////////////////////////////////////////////////////////////////////// +// void AddButtons() +// Create and show the Reset, Run, Stop, Trace and Step buttons +////////////////////////////////////////////////////////////////////////////// +void EmuGtk::AddButtons( void ) +{ + //GtkStyle *Style = gtk_widget_get_style( GTK_WIDGET( emuwin ) ); + + RESET_pixmap = gdk_pixmap_colormap_create_from_xpm_d( NULL, + gtk_widget_get_default_colormap(), + &RESET_mask, + NULL, + ( gchar ** ) reset_xpm ); + RESET_widget = gtk_pixmap_new( RESET_pixmap, RESET_mask ); + + RUN_pixmap = gdk_pixmap_colormap_create_from_xpm_d( NULL, + gtk_widget_get_default_colormap(), + &RUN_mask, + NULL, + ( gchar ** ) run_xpm ); + RUN_widget = gtk_pixmap_new( RUN_pixmap, RUN_mask ); + + STOP_pixmap = gdk_pixmap_colormap_create_from_xpm_d( NULL, + gtk_widget_get_default_colormap(), + &STOP_mask, + NULL, + ( gchar ** ) stop_xpm ); + STOP_widget = gtk_pixmap_new( STOP_pixmap, STOP_mask ); + + STEP_pixmap = gdk_pixmap_colormap_create_from_xpm_d( NULL, + gtk_widget_get_default_colormap(), + &STEP_mask, + NULL, + ( gchar ** ) step_xpm ); + STEP_widget = gtk_pixmap_new( STEP_pixmap, STEP_mask ); + + ButtonTable = gtk_table_new( 1, 4, TRUE ); + gtk_widget_set_usize( GTK_WIDGET( ButtonTable ), BUTTONS_BAR_WIDTH, BUTTONS_BAR_HEIGHT ); + gtk_fixed_put( GTK_FIXED( emumainfixed ), ButtonTable, 0, 0 ); + + ButtonReset = gtk_button_new(); + ButtonRun = gtk_button_new(); + ButtonStop = gtk_button_new(); + ButtonStep = gtk_button_new(); + + gtk_container_add( GTK_CONTAINER( ButtonReset ), RESET_widget ); + gtk_container_add( GTK_CONTAINER( ButtonRun ), RUN_widget ); + gtk_container_add( GTK_CONTAINER( ButtonStop ), STOP_widget ); + gtk_container_add( GTK_CONTAINER( ButtonStep ), STEP_widget ); + + + gtk_widget_set_usize( GTK_WIDGET( ButtonReset ), BUTTON_WIDTH, BUTTON_HEIGHT ); + gtk_widget_set_usize( GTK_WIDGET( ButtonRun ), BUTTON_WIDTH, BUTTON_HEIGHT ); + gtk_widget_set_usize( GTK_WIDGET( ButtonStop ), BUTTON_WIDTH, BUTTON_HEIGHT ); + gtk_widget_set_usize( GTK_WIDGET( ButtonStep ), BUTTON_WIDTH, BUTTON_HEIGHT ); + + gtk_table_attach_defaults( GTK_TABLE( ButtonTable ), ButtonReset, 0, 1, 0, 1); + gtk_table_attach_defaults( GTK_TABLE( ButtonTable ), ButtonRun, 1, 2, 0, 1); + gtk_table_attach_defaults( GTK_TABLE( ButtonTable ), ButtonStop, 2, 3, 0, 1); + gtk_table_attach_defaults( GTK_TABLE( ButtonTable ), ButtonStep, 3, 4, 0, 1); + + gtk_widget_show( GTK_WIDGET( ButtonReset ) ); + gtk_widget_show( GTK_WIDGET( ButtonRun ) ); + gtk_widget_show( GTK_WIDGET( ButtonStop ) ); + gtk_widget_show( GTK_WIDGET( ButtonStep ) ); + + gtk_widget_show_all( GTK_WIDGET( ButtonTable ) ); +} + +////////////////////////////////////////////////////////////////////////////// +// EmuGtk::~EmuGtk( ) +// EmuGtk destructor +////////////////////////////////////////////////////////////////////////////// +EmuGtk::~EmuGtk( ) +{ + g_print( "EmuGtk::~EmuGtk( )\n" ); +} + +////////////////////////////////////////////////////////////////////////////// +// void EmuGtk::Reset( ) +// CPU reset and Gtk UI update +////////////////////////////////////////////////////////////////////////////// +void EmuGtk::Reset( ) +{ + CPU->Reset( ); + regwin->Show( CPU ); + pgmwin->Disasm( ); + memwin->DumpD( CPU, 0 ); +} + +////////////////////////////////////////////////////////////////////////////// +// void EmuGtk::Step( ) +// CPU Step and Gtk UI update +////////////////////////////////////////////////////////////////////////////// +void EmuGtk::Step( ) +{ + CPU->Exec( ); + regwin->Show( CPU ); + pgmwin->Disasm( ); + memwin->DumpD( CPU, 0 ); +} + +////////////////////////////////////////////////////////////////////////////// +// void EmuGtk::Main( ) +// Gtk UI Main function +////////////////////////////////////////////////////////////////////////////// +void EmuGtk::Main( ) +{ + Reset( ); + gtk_main(); + g_print( "End of EmuGtk::Main( )\n" ); +} + + +////////////////////////////////////////////////////////////////////////////// +// void EmuGtk::ShowMenu( ) +// Show the menu +////////////////////////////////////////////////////////////////////////////// +void EmuGtk::ShowMenu( ) +{ + FileMenu = gtk_menu_new( ); + OpenItem = gtk_menu_item_new_with_label( "Open" ); + QuitItem = gtk_menu_item_new_with_label( "Quit" ); + gtk_menu_append( GTK_MENU( FileMenu ), GTK_WIDGET( OpenItem ) ); + gtk_menu_append( GTK_MENU( FileMenu ), GTK_WIDGET( QuitItem ) ); + gtk_widget_show( GTK_WIDGET( OpenItem ) ); + gtk_widget_show( GTK_WIDGET( QuitItem ) ); + + ViewMenu = gtk_menu_new( ); + ExtMemItem = gtk_menu_item_new_with_label( "External Memory Dump" ); + IntMemItem = gtk_menu_item_new_with_label( "Internal Memory Dump" ); + //PgmMemItem = gtk_menu_item_new_with_label( "Program Memory Dump" ); + gtk_menu_append( GTK_MENU( ViewMenu ), GTK_WIDGET( ExtMemItem ) ); + gtk_menu_append( GTK_MENU( ViewMenu ), GTK_WIDGET( IntMemItem ) ); + //gtk_menu_append( GTK_MENU( ViewMenu ), GTK_WIDGET( PgmMemItem ) ); + gtk_widget_show( GTK_WIDGET( ExtMemItem ) ); + gtk_widget_show( GTK_WIDGET( IntMemItem ) ); + //gtk_widget_show( GTK_WIDGET( PgmMemItem ) ); + + HelpMenu = gtk_menu_new( ); + AboutItem = gtk_menu_item_new_with_label( "About" ); + gtk_menu_append( GTK_MENU( HelpMenu ), GTK_WIDGET( AboutItem ) ); + gtk_widget_show( GTK_WIDGET( AboutItem ) ); + + MenuBar = gtk_menu_bar_new( ); + gtk_fixed_put( GTK_FIXED( emufixed ), MenuBar, 0, 0 ); + gtk_widget_show( GTK_WIDGET( MenuBar ) ); + + FileItem = gtk_menu_item_new_with_label( "File" ); + ViewItem = gtk_menu_item_new_with_label( "View" ); + HelpItem = gtk_menu_item_new_with_label( "Help" ); + gtk_widget_show( GTK_WIDGET( FileItem ) ); + gtk_widget_show( GTK_WIDGET( ViewItem ) ); + gtk_widget_show( GTK_WIDGET( HelpItem ) ); + gtk_menu_item_set_submenu( GTK_MENU_ITEM( FileItem ), FileMenu ); + gtk_menu_item_set_submenu( GTK_MENU_ITEM( ViewItem ), ViewMenu ); + gtk_menu_item_set_submenu( GTK_MENU_ITEM( HelpItem ), HelpMenu ); + gtk_menu_bar_append( GTK_MENU_BAR( MenuBar ), FileItem ); + gtk_menu_bar_append( GTK_MENU_BAR( MenuBar ), ViewItem ); + gtk_menu_bar_append( GTK_MENU_BAR( MenuBar ), HelpItem ); +} + +////////////////////////////////////////////////////////////////////////////// +// gint EmuGtk::DeleteEvent( GtkWidget *widget, GdkEvent *event, gpointer data ) +// Signal DeleteEvent +////////////////////////////////////////////////////////////////////////////// +gboolean EmuGtk::DeleteEvent( GtkWidget *widget, GdkEvent *event, gpointer data ) +{ + g_print( "EmuGtk::DeleteEvent(...)\n" ); + StopRunning( ); + return FALSE; +} + +////////////////////////////////////////////////////////////////////////////// +// gint EmuGtk::DestroyEvent( GtkWidget *widget, gpointer data ) +// Signal DestroyEvent +////////////////////////////////////////////////////////////////////////////// +void EmuGtk::DestroyEvent( GtkWidget *widget, gpointer data ) +{ + g_print( "EmuGtk::DestroyEvent(...)\n" ); + gtk_main_quit(); +} + +////////////////////////////////////////////////////////////////////////////// +// gint EmuGtk::AboutEvent( GtkWidget *widget, gpointer data ) +// Signal AboutEvent ( Help->About in menu ) +////////////////////////////////////////////////////////////////////////////// +void EmuGtk::AboutEvent( GtkWidget *widget, gpointer data ) +{ + char about_string[256]; + GtkWidget *about_window; + GtkWidget *text_window; + + sprintf( about_string, "%s\n\nversion %s\n\n\nAuthors:\nHugo Villeneuve\nJonathan St-André\n", PACKAGE, VERSION ); + + about_window = gtk_window_new( GTK_WINDOW_TOPLEVEL ); + gtk_window_set_title( GTK_WINDOW( about_window ), "About" ); + gtk_container_set_border_width( GTK_CONTAINER( about_window ), 20 ); + + text_window = gtk_label_new( about_string ); + gtk_container_add( GTK_CONTAINER( about_window ), text_window ); + + gtk_widget_show_all( GTK_WIDGET( about_window ) ); +} + +////////////////////////////////////////////////////////////////////////////// +// gint EmuGtk::OpenEvent( GtkWidget *widget, gpointer data ) +// Signal OpenEvent ( File->Open in menu ) +////////////////////////////////////////////////////////////////////////////// +void EmuGtk::OpenEvent( GtkWidget *widget, gpointer data ) +{ + GtkWidget *FileOpendialog; + + // g_print( "EmuGtk::OpenEvent(...)\n" ); + + FileOpendialog = gtk_file_selection_new( "Open Intel Hex file" ); + + // Connect the file dialog's OK button up to a handler. + gtk_signal_connect( GTK_OBJECT( GTK_FILE_SELECTION ( FileOpendialog ) -> ok_button ), + "clicked", + GTK_SIGNAL_FUNC( FileOpenDialog_OK ), + FileOpendialog ); + + // Connect the file dialog's CANCEL button up to a handler. + gtk_signal_connect( GTK_OBJECT( GTK_FILE_SELECTION ( FileOpendialog ) -> cancel_button ), + "clicked", + GTK_SIGNAL_FUNC( FileOpenDialog_CANCEL ), + FileOpendialog ); + + // Set the 'File Open dialog' to show only Intel HEX files (.hex). + // gtk_file_selection_complete( GTK_FILE_SELECTION( FileOpendialog ), "*.hex" ); + + // Show the dialog + gtk_widget_show( GTK_WIDGET( FileOpendialog ) ); +} + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +void FileOpenDialog_OK( GtkButton *button, gpointer data ) +{ + g_print( "EmuGtk::FileOpenDialog_OK Event(...)\n" ); + + const gchar *SelectedFile; + + SelectedFile = gtk_file_selection_get_filename ( GTK_FILE_SELECTION ( data ) ); + + g_print( "EmuGtk::File = %s\n", SelectedFile ); + + EmuGtkPtr->StopRunning( ); + + EmuGtkPtr->LoadHexFile( SelectedFile ); + + gtk_widget_destroy( GTK_WIDGET( data ) ); + + EmuGtkPtr->Reset( ); + EmuGtkPtr->UpdateDisplay(); +} + + +void EmuGtk::UpdateDisplay( void ) +{ + regwin->Show( CPU ); + pgmwin->Disasm( ); + memwin->DumpD( CPU, 0 ); +} + + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +void FileOpenDialog_CANCEL( GtkButton *button, gpointer data ) +{ + g_print( "EmuGtk::FileOpenDialog_CANCEL Event(...)\n" ); + + gtk_widget_destroy( GTK_WIDGET( data ) ); +} + + + +////////////////////////////////////////////////////////////////////////////// +// gint EmuGtk::QuitEvent( GtkWidget *widget, gpointer data ) +// Signal QuitEvent ( File->Quit in menu ) +////////////////////////////////////////////////////////////////////////////// +void EmuGtk::QuitEvent( GtkWidget *widget, gpointer data ) +{ + g_print( "EmuGtk::QuitEvent(...)\n" ); + StopRunning( ); + gtk_main_quit( ); +} + +////////////////////////////////////////////////////////////////////////////// +// gint EmuGtk::ResetEvent( GtkWidget *widget, GdkEvent *event, gpointer data ) +// Signal ResetEvent ( ResetButton ) +////////////////////////////////////////////////////////////////////////////// +void EmuGtk::ResetEvent( GtkWidget *widget, GdkEvent *event, gpointer data ) +{ + g_print( "EmuGtk::ResetEvent(...)\n" ); + StopRunning( ); + Reset( ); +} + +////////////////////////////////////////////////////////////////////////////// +// gint EmuGtk::RunEvent( GtkWidget *widget, GdkEvent *event, gpointer data ) +// Signal RunEvent ( RunButton ) +////////////////////////////////////////////////////////////////////////////// +void EmuGtk::RunEvent( GtkWidget *widget, GdkEvent *event, gpointer data ) +{ + g_print( "EmuGtk::RunEvent(...)\n" ); + if ( RunningState ) { + // g_print( "Getting out of RunningState! \n" ); + StopRunning( ); + } + else { + // g_print( "Going In RunningState! \n" ); + StartRunning( ); + } +} + +////////////////////////////////////////////////////////////////////////////// +// gint EmuGtk::StopEvent( GtkWidget *widget, GdkEvent *event, gpointer data ) +// Signal StopEvent ( StopButton ) +////////////////////////////////////////////////////////////////////////////// +void EmuGtk::StopEvent( GtkWidget *widget, GdkEvent *event, gpointer data ) +{ + g_print( "EmuGtk::StopEvent(...)\n" ); + StopRunning( ); +} + +////////////////////////////////////////////////////////////////////////////// +// gint EmuGtk::StepEvent( GtkWidget *widget, GdkEvent *event, gpointer data ) +// Signal StepEvent ( StepButton ) +////////////////////////////////////////////////////////////////////////////// +void EmuGtk::StepEvent( GtkWidget *widget, GdkEvent *event, gpointer data ) +{ + g_print( "EmuGtk::StepEvent(...)\n" ); + StopRunning( ); + Step( ); +} + +////////////////////////////////////////////////////////////////////////////// +// unsigned int EmuGtk::Ascii2Hex( string istring, int length = 0 ) +// Convert an ascii string to an hexadecimal number +////////////////////////////////////////////////////////////////////////////// +unsigned int EmuGtk::Ascii2Hex( string istring, int length = 0 ) +{ + if ( !length || ( length > (int) istring.size() ) ) + length = istring.size(); + + if ( istring.empty() ) + throw MissingParameter(); + + unsigned int result = 0; + int i, ascii_code; + for ( i = 0; i < length; i++ ) { + ascii_code = istring[ i ]; + if ( ascii_code > 0x39 ) + ascii_code &= 0xDF; + if ( ( ascii_code >= 0x30 && ascii_code <= 0x39 ) || ( ascii_code >= 0x41 && ascii_code <= 0x46 ) ) { + ascii_code -= 0x30; + if ( ascii_code > 9 ) + ascii_code -= 7; + result <<= 4; + result += ascii_code; + } + else { + throw SyntaxError(); + } + } + return result; +} + +////////////////////////////////////////////////////////////////////////////// +// void EmuGtk::LoadHexFile( string Filename ) +// Load an HEX file into program memory +////////////////////////////////////////////////////////////////////////////// +void EmuGtk::LoadHexFile( string Filename ) +{ + printf("LoadHex\n"); + int i, j, RecLength, LoadOffset, RecType, Data, Checksum; + char Line[ 250 ]; + + ifstream HexFile( Filename.c_str() ); + try { + if ( ! HexFile ) + throw ErrorOpeningFile(); + + while( ! HexFile.eof() ) { + i = 0; + Checksum = 0; + HexFile.getline( Line, 250, '\n' ); + + if ( Line[ i++ ] != ':' ) + throw ErrorHexFileFormat(); + + RecLength = Ascii2Hex( &Line[ i ], 2 ); + i += 2; + Checksum += RecLength; + + LoadOffset = Ascii2Hex( &Line[i], 4 ); + Checksum += LoadOffset / 256; + Checksum += LoadOffset % 256; + i += 4; + + RecType = Ascii2Hex( &Line[i],2); + i += 2; + Checksum += RecType; + + if ( RecType == 1 ) { + Checksum += Ascii2Hex( &Line[ i ], 2 ); + if ( Checksum &= 0x000000FF ) + throw ErrorHexFileFormat(); + throw FinishedLoading(); + } + if ( RecType ) + throw ErrorHexFileFormat(); + + for ( j = 0; j < RecLength; j++ ) { + Data = Ascii2Hex( &Line[ i ], 2 ); + CPU->WritePGM( (unsigned int)(LoadOffset + j), (unsigned char)Data ); + i += 2; + Checksum += Data; + } + RecType = Ascii2Hex( &Line[ i ], 2 ); + Checksum += RecType; + + if ( Checksum &= 0x000000FF ) + throw ErrorHexFileFormat(); + } + throw ErrorHexFileFormat(); + } + catch ( ErrorOpeningFile ) { + cout << "Error opening file " << Filename << endl; + } + catch ( ErrorHexFileFormat ) { + cout << "Invalid format for " << Filename << " file..." << endl; + } + catch ( SyntaxError ) { + cout << "Invalid format for " << Filename << " file..." << endl; + } + catch ( MissingParameter ) { + cout << "Invalid format for " << Filename << " file..." << endl; + } + catch ( FinishedLoading ) { + cout << "Using file " << Filename << " as input program." << endl; + } + HexFile.close(); +} + +////////////////////////////////////////////////////////////////////////////// +// gint EmuGtkSignalStub2( GtkWidget *widget, gpointer data ) +// Signal Stub with 2 parameters +////////////////////////////////////////////////////////////////////////////// +void EmuGtkSignalStub2( GtkWidget *widget, gpointer data ) +{ + //g_print( "EmuGtkSignalStub2(...)\n"); + int SigNumber = (* ( static_cast< int * >( data ) ) ); + + switch( SigNumber ) + { + case DestroySignal: + EmuGtkPtr->DestroyEvent( widget, 0 ); + break; + case AboutISignal: + EmuGtkPtr->AboutEvent( widget, 0 ); + break; + case OpenISignal: + EmuGtkPtr->OpenEvent( widget, 0 ); + break; + case QuitISignal: + EmuGtkPtr->QuitEvent( widget, 0 ); + break; + default: + g_print( "*** error: EmuGtkSignalStub2: default case reached\n" ); + break; + }; +} + + +////////////////////////////////////////////////////////////////////////////// +// gint EmuGtkSignalStub3( GtkWidget *widget, GdkEvent *event, gpointer data ) +// Signal Stub with 3 parameters +////////////////////////////////////////////////////////////////////////////// +void EmuGtkSignalStub3( GtkWidget *widget, GdkEvent *event, gpointer data ) +{ + //g_print( "EmuGtkSignalStub3(...)\n"); + int SigNumber = (* ( static_cast< int * >( data ) ) ); + + switch( SigNumber ) + { + case DeleteSignal: + EmuGtkPtr->DeleteEvent( widget, event, 0 ); + break; + case ResetBSignal: + EmuGtkPtr->ResetEvent( widget, event, 0 ); + break; + case RunBSignal: + EmuGtkPtr->RunEvent( widget, event, 0 ); + break; + case StopBSignal: + EmuGtkPtr->StopEvent( widget, event, 0 ); + break; + case StepBSignal: + EmuGtkPtr->StepEvent( widget, event, 0 ); + break; + default: + g_print( "*** error: EmuGtkSignalStub3: default case reached\n" ); + break; + }; +} + +////////////////////////////////////////////////////////////////////////////// +// void EmuGtk::Running( ) +// Running called by RunningFunction( ) +////////////////////////////////////////////////////////////////////////////// +void EmuGtk::Running( ) +{ + CPU->Exec( ); + if ( pgmwin->IsBreakpoint( CPU->GetPC( ) ) ) { + g_print( "Breakpoint Hit, stopping!\n" ); + StopRunning( ); + } +} + +////////////////////////////////////////////////////////////////////////////// +// gint RunningFunction( ) +// RunningFunction called when idle from gtk_main +////////////////////////////////////////////////////////////////////////////// +gint RunningFunction( ) +{ + EmuGtkPtr->Running( ); + return TRUE; +} + +////////////////////////////////////////////////////////////////////////////// +// void EmuGtk::StartRunning( ) +// Get in the RunningState +////////////////////////////////////////////////////////////////////////////// +void EmuGtk::StartRunning( ) +{ + if ( !RunningState ) { + printf( "EmuGtk::StartRunning( )\n" ); + RunFuncTag = gtk_idle_add( GtkFunction( RunningFunction ),0 ); + RunningState = 1; + // gtk_widget_hide( GTK_WIDGET( ButtonRun ) ); + // gtk_widget_show_now( GTK_WIDGET( ButtonStop ) ); + // gtk_table_attach_defaults( GTK_TABLE( ButtonTable ), ButtonStop, 3, 4, 0, 1); + } +} + +////////////////////////////////////////////////////////////////////////////// +// void EmuGtk::StopRunning( ) +// Step out of RunningState +////////////////////////////////////////////////////////////////////////////// +void EmuGtk::StopRunning( ) +{ + if (RunningState) { + printf( "EmuGtk::StopRunning( )\n" ); + gtk_idle_remove( RunFuncTag ); + RunningState = 0; + //gtk_widget_hide( GTK_WIDGET( ButtonStop ) ); + //gtk_widget_show( GTK_WIDGET( ButtonRun ) ); + // gtk_table_attach_defaults( GTK_TABLE( ButtonTable ), ButtonRun, 3, 4, 0, 1); + regwin->Show( CPU ); + pgmwin->Disasm( ); + memwin->DumpD( CPU, 0 ); + } +} diff --git a/src/EmuGtk.hpp b/src/EmuGtk.hpp new file mode 100644 index 0000000..8fe4713 --- /dev/null +++ b/src/EmuGtk.hpp @@ -0,0 +1,111 @@ +#ifndef _EMUGTK_HPP_ +#define _EMUGTK_HPP_ + +#include +#include +#include +#include "CPU8051.hpp" +#include "MemWin.hpp" +#include "PgmWin.hpp" +#include "RegWin.hpp" +#include "GtkSizes.hpp" +#include "exceptions.hpp" + +using namespace std; + + +////////////////////////////////////////////////////////////////////////////// +// EmuGtk +// Implements the Gtk+ Graphical User Interface as an Object +////////////////////////////////////////////////////////////////////////////// +class EmuGtk { +public: + EmuGtk( int argc , char **argv, CPU8051 *mCPU ); + ~EmuGtk( ); + + void Main( ); + + void Reset( ); + void Step( ); + // void Step( ); + // void Exec( ); + + void AddButtons( ); + void ShowMenu( ); + + gboolean DeleteEvent( GtkWidget *widget, GdkEvent *event, gpointer data ); + void DestroyEvent( GtkWidget *widget, gpointer data ); + + void OpenEvent( GtkWidget *widget, gpointer data ); + void QuitEvent( GtkWidget *widget, gpointer data ); + void AboutEvent( GtkWidget *widget, gpointer data ); + + void ResetEvent( GtkWidget *widget, GdkEvent *event, gpointer data ); + void RunEvent( GtkWidget *widget, GdkEvent *event, gpointer data ); + void StopEvent( GtkWidget *widget, GdkEvent *event, gpointer data ); + void StepEvent( GtkWidget *widget, GdkEvent *event, gpointer data ); + + void StartRunning( ); + void StopRunning( ); + void Running( ); + + void LoadHexFile( string Filename ); + void UpdateDisplay(); + +private: + int EmuGtkID; + CPU8051 *CPU; + int RunningState; + int RunFuncTag; + MemWin *memwin; + PgmWin *pgmwin; + RegWin *regwin; + GtkWidget *emuwin, *emufixed, *emumainfixed; + GtkWidget *regfrm, *pgmfrm, *memfrm; + GtkWidget *ButtonTable; + + // GdkPixmap *PixMapT, *PixMapRun, *PixMapR, *PixMapQ; + // GtkWidget *PixMapWidT, *PixMapWidRun, *PixMapWidR, *PixMapWidQ; + // GdkBitmap *mask; + GtkWidget *FileMenu, *OpenItem, *QuitItem, *FileItem; + GtkWidget *ViewMenu, *ExtMemItem, *IntMemItem, *ViewItem; + // GtkWidget *ViewMenu, *ExtMemItem, *IntMemItem, *PgmMemItem, *ViewItem; + GtkWidget *HelpMenu, *AboutItem, *LicenseItem, *HelpItem; + GtkWidget *MenuBar; + + // RESET button + GdkBitmap *RESET_mask; + GdkPixmap *RESET_pixmap; + GtkWidget *RESET_widget; + GtkWidget *ButtonReset; + + // RUN button + GdkBitmap *RUN_mask; + GdkPixmap *RUN_pixmap; + GtkWidget *RUN_widget; + GtkWidget *ButtonRun; + + // STOP button + GdkBitmap *STOP_mask; + GdkPixmap *STOP_pixmap; + GtkWidget *STOP_widget; + GtkWidget *ButtonStop; + + // STEP button + GdkBitmap *STEP_mask; + GdkPixmap *STEP_pixmap; + GtkWidget *STEP_widget; + GtkWidget *ButtonStep; + + unsigned int Ascii2Hex( string istring, int length ); +}; + +void EmuGtkSignalStub3( GtkWidget *widget, GdkEvent *event, gpointer data ); +void EmuGtkSignalStub2( GtkWidget *widget, gpointer data ); +void FileOpenDialog_OK( GtkButton *button, gpointer data ); +void FileOpenDialog_CANCEL( GtkButton *button, gpointer data ); + +gint RunningFunction( ); + + +#endif diff --git a/src/GtkSizes.hpp b/src/GtkSizes.hpp new file mode 100644 index 0000000..9bffe25 --- /dev/null +++ b/src/GtkSizes.hpp @@ -0,0 +1,24 @@ +#ifndef _GTKSIZES_HPP_ +#define _GTKSIZES_HPP_ + +#define NUMBER_OF_BUTTONS 5 +#define BUTTON_WIDTH 60 +#define BUTTON_HEIGHT 60 +#define BUTTONS_BAR_WIDTH (NUMBER_OF_BUTTONS * BUTTON_WIDTH) +#define BUTTONS_BAR_HEIGHT BUTTON_HEIGHT + +#define REG_WIN_WIDTH 100 +#define REG_WIN_HEIGHT 390 + +#define PGM_WIN_WIDTH 480 +#define PGM_WIN_HEIGHT 390 + +#define MEM_WIN_WIDTH 590 +#define MEM_WIN_HEIGHT 280 + +#define MENU_BAR_HEIGHT 0 + +#define MAIN_WIN_WIDTH (REG_WIN_WIDTH + PGM_WIN_WIDTH) +#define MAIN_WIN_HEIGHT (BUTTONS_BAR_HEIGHT + REG_WIN_HEIGHT + MEM_WIN_HEIGHT) + +#endif diff --git a/src/Inst_Def.hpp b/src/Inst_Def.hpp new file mode 100644 index 0000000..2ef66da --- /dev/null +++ b/src/Inst_Def.hpp @@ -0,0 +1,266 @@ +#ifndef __INST_DEF_HPP_ +#define __INST_DEF_HPP_ +// Do not modify this file directly, it was created by Opcode2cpp.pl +// Any modification made directly on this file will be lost + + +int OP_00( ); +int OP_01( ); +int OP_02( ); +int OP_03( ); +int OP_04( ); +int OP_05( ); +int OP_06( ); +int OP_07( ); +int OP_08( ); +int OP_09( ); +int OP_0A( ); +int OP_0B( ); +int OP_0C( ); +int OP_0D( ); +int OP_0E( ); +int OP_0F( ); +int OP_10( ); +int OP_11( ); +int OP_12( ); +int OP_13( ); +int OP_14( ); +int OP_15( ); +int OP_16( ); +int OP_17( ); +int OP_18( ); +int OP_19( ); +int OP_1A( ); +int OP_1B( ); +int OP_1C( ); +int OP_1D( ); +int OP_1E( ); +int OP_1F( ); +int OP_20( ); +int OP_21( ); +int OP_22( ); +int OP_23( ); +int OP_24( ); +int OP_25( ); +int OP_26( ); +int OP_27( ); +int OP_28( ); +int OP_29( ); +int OP_2A( ); +int OP_2B( ); +int OP_2C( ); +int OP_2D( ); +int OP_2E( ); +int OP_2F( ); +int OP_30( ); +int OP_31( ); +int OP_32( ); +int OP_33( ); +int OP_34( ); +int OP_35( ); +int OP_36( ); +int OP_37( ); +int OP_38( ); +int OP_39( ); +int OP_3A( ); +int OP_3B( ); +int OP_3C( ); +int OP_3D( ); +int OP_3E( ); +int OP_3F( ); +int OP_40( ); +int OP_41( ); +int OP_42( ); +int OP_43( ); +int OP_44( ); +int OP_45( ); +int OP_46( ); +int OP_47( ); +int OP_48( ); +int OP_49( ); +int OP_4A( ); +int OP_4B( ); +int OP_4C( ); +int OP_4D( ); +int OP_4E( ); +int OP_4F( ); +int OP_50( ); +int OP_51( ); +int OP_52( ); +int OP_53( ); +int OP_54( ); +int OP_55( ); +int OP_56( ); +int OP_57( ); +int OP_58( ); +int OP_59( ); +int OP_5A( ); +int OP_5B( ); +int OP_5C( ); +int OP_5D( ); +int OP_5E( ); +int OP_5F( ); +int OP_60( ); +int OP_61( ); +int OP_62( ); +int OP_63( ); +int OP_64( ); +int OP_65( ); +int OP_66( ); +int OP_67( ); +int OP_68( ); +int OP_69( ); +int OP_6A( ); +int OP_6B( ); +int OP_6C( ); +int OP_6D( ); +int OP_6E( ); +int OP_6F( ); +int OP_70( ); +int OP_71( ); +int OP_72( ); +int OP_73( ); +int OP_74( ); +int OP_75( ); +int OP_76( ); +int OP_77( ); +int OP_78( ); +int OP_79( ); +int OP_7A( ); +int OP_7B( ); +int OP_7C( ); +int OP_7D( ); +int OP_7E( ); +int OP_7F( ); +int OP_80( ); +int OP_81( ); +int OP_82( ); +int OP_83( ); +int OP_84( ); +int OP_85( ); +int OP_86( ); +int OP_87( ); +int OP_88( ); +int OP_89( ); +int OP_8A( ); +int OP_8B( ); +int OP_8C( ); +int OP_8D( ); +int OP_8E( ); +int OP_8F( ); +int OP_90( ); +int OP_91( ); +int OP_92( ); +int OP_93( ); +int OP_94( ); +int OP_95( ); +int OP_96( ); +int OP_97( ); +int OP_98( ); +int OP_99( ); +int OP_9A( ); +int OP_9B( ); +int OP_9C( ); +int OP_9D( ); +int OP_9E( ); +int OP_9F( ); +int OP_A0( ); +int OP_A1( ); +int OP_A2( ); +int OP_A3( ); +int OP_A4( ); +int OP_A5( ); +int OP_A6( ); +int OP_A7( ); +int OP_A8( ); +int OP_A9( ); +int OP_AA( ); +int OP_AB( ); +int OP_AC( ); +int OP_AD( ); +int OP_AE( ); +int OP_AF( ); +int OP_B0( ); +int OP_B1( ); +int OP_B2( ); +int OP_B3( ); +int OP_B4( ); +int OP_B5( ); +int OP_B6( ); +int OP_B7( ); +int OP_B8( ); +int OP_B9( ); +int OP_BA( ); +int OP_BB( ); +int OP_BC( ); +int OP_BD( ); +int OP_BE( ); +int OP_BF( ); +int OP_C0( ); +int OP_C1( ); +int OP_C2( ); +int OP_C3( ); +int OP_C4( ); +int OP_C5( ); +int OP_C6( ); +int OP_C7( ); +int OP_C8( ); +int OP_C9( ); +int OP_CA( ); +int OP_CB( ); +int OP_CC( ); +int OP_CD( ); +int OP_CE( ); +int OP_CF( ); +int OP_D0( ); +int OP_D1( ); +int OP_D2( ); +int OP_D3( ); +int OP_D4( ); +int OP_D5( ); +int OP_D6( ); +int OP_D7( ); +int OP_D8( ); +int OP_D9( ); +int OP_DA( ); +int OP_DB( ); +int OP_DC( ); +int OP_DD( ); +int OP_DE( ); +int OP_DF( ); +int OP_E0( ); +int OP_E1( ); +int OP_E2( ); +int OP_E3( ); +int OP_E4( ); +int OP_E5( ); +int OP_E6( ); +int OP_E7( ); +int OP_E8( ); +int OP_E9( ); +int OP_EA( ); +int OP_EB( ); +int OP_EC( ); +int OP_ED( ); +int OP_EE( ); +int OP_EF( ); +int OP_F0( ); +int OP_F1( ); +int OP_F2( ); +int OP_F3( ); +int OP_F4( ); +int OP_F5( ); +int OP_F6( ); +int OP_F7( ); +int OP_F8( ); +int OP_F9( ); +int OP_FA( ); +int OP_FB( ); +int OP_FC( ); +int OP_FD( ); +int OP_FE( ); +int OP_FF( ); +void InitFuncPtr( ); + + +#endif diff --git a/src/Inst_Imp.cpp b/src/Inst_Imp.cpp new file mode 100644 index 0000000..b8998ab --- /dev/null +++ b/src/Inst_Imp.cpp @@ -0,0 +1,4208 @@ +#ifndef __INST_IMP_HPP_ +#define __INST_IMP_HPP_ + +//#include "CPU8051.hpp" + +// Do not modify this file directly, it was created by Opcode2cpp.pl +// Any modification made directly on this file will be lost + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_00( ) +// Instruction "NOP" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_00( ) +{ +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_01( ) +// Instruction "AJMP addr11" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_01( ) +{ +unsigned int addr11 = ( ( PGMMem->Read8( PC - 1 ) << 3 ) & 0xF00 ) + PGMMem->Read8( PC++ ); +PC = ( PC & 0xF800 ) | addr11; +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_02( ) +// Instruction "LJMP addr16" takes 2 cycle(s) and 3 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_02( ) +{ +unsigned int addr16 = ( PGMMem->Read8( PC++ ) << 8 ); +addr16 += PGMMem->Read8( PC++ ); +PC = addr16; +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_03( ) +// Instruction "RR A" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_03( ) +{ +unsigned char destination = ReadD( _ACC_ ); +destination = ( destination >> 1 ) | ( destination << 7 ); +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_04( ) +// Instruction "INC A" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_04( ) +{ +unsigned char destination = ReadD( _ACC_ ); +destination++; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_05( ) +// Instruction "INC direct" takes 1 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_05( ) +{ +unsigned char destaddr = PGMMem->Read8( PC++ ); +unsigned char destination = ReadD( destaddr ); +destination++; +WriteD( destaddr, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_06( ) +// Instruction "INC @R0" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_06( ) +{ +unsigned char destination = ReadI ( ReadD( BANKPSW + _R0_ ) ); +destination++; +WriteI( ReadD( BANKPSW + _R0_ ), destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_07( ) +// Instruction "INC @R1" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_07( ) +{ +unsigned char destination = ReadI ( ReadD( BANKPSW + _R1_ ) ); +destination++; +WriteI( ReadD( BANKPSW + _R1_ ), destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_08( ) +// Instruction "INC R0" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_08( ) +{ +unsigned char destination = ReadD( BANKPSW + _R0_ ); +destination++; +WriteD( BANKPSW + _R0_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_09( ) +// Instruction "INC R1" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_09( ) +{ +unsigned char destination = ReadD( BANKPSW + _R1_ ); +destination++; +WriteD( BANKPSW + _R1_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_0A( ) +// Instruction "INC R2" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_0A( ) +{ +unsigned char destination = ReadD( BANKPSW + _R2_ ); +destination++; +WriteD( BANKPSW + _R2_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_0B( ) +// Instruction "INC R3" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_0B( ) +{ +unsigned char destination = ReadD( BANKPSW + _R3_ ); +destination++; +WriteD( BANKPSW + _R3_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_0C( ) +// Instruction "INC R4" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_0C( ) +{ +unsigned char destination = ReadD( BANKPSW + _R4_ ); +destination++; +WriteD( BANKPSW + _R4_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_0D( ) +// Instruction "INC R5" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_0D( ) +{ +unsigned char destination = ReadD( BANKPSW + _R5_ ); +destination++; +WriteD( BANKPSW + _R5_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_0E( ) +// Instruction "INC R6" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_0E( ) +{ +unsigned char destination = ReadD( BANKPSW + _R6_ ); +destination++; +WriteD( BANKPSW + _R6_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_0F( ) +// Instruction "INC R7" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_0F( ) +{ +unsigned char destination = ReadD( BANKPSW + _R7_ ); +destination++; +WriteD( BANKPSW + _R7_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_10( ) +// Instruction "JBC bitaddr,reladdr" takes 2 cycle(s) and 3 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_10( ) +{ +unsigned char destination, dstbitaddr = PGMMem->Read8( PC++ ); +destination = ReadB( dstbitaddr ); +PC++; +unsigned int source = ( ( PGMMem->Read8( PC - 1 ) + PC ) & 0xFF ) + ( PC & 0xFF00 ); +if ( destination == 1 ) { PC = source; destination = 0; } +WriteB( dstbitaddr, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_11( ) +// Instruction "ACALL addr11" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_11( ) +{ +unsigned int addr11 = ( ( PGMMem->Read8( PC - 1 ) << 3 ) & 0xF00 ) + PGMMem->Read8( PC++ ); +unsigned char SP = ReadD( _SP_ ); +WriteI( ++SP, ( PC & 0x00FF ) ); +WriteI( ++SP, ( PC >> 8 ) ); +WriteD( _SP_, SP ); +PC = ( PC & 0xF800 ) | addr11; +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_12( ) +// Instruction "LCALL addr16" takes 2 cycle(s) and 3 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_12( ) +{ +unsigned int addr16 = ( PGMMem->Read8( PC++ ) << 8 ); +addr16 += PGMMem->Read8( PC++ ); +unsigned char SP = ReadD( _SP_ ); +WriteI( ++SP, ( PC & 0x00FF ) ); +WriteI( ++SP, ( PC >> 8 ) ); +WriteD( _SP_, SP ); +PC = addr16; +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_13( ) +// Instruction "RRC A" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_13( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char tmpval = destination; +destination = ( destination >> 1 ) | ( ReadD( _PSW_ ) & 0x80 ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x7F ) | ( tmpval << 7 ) ); +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_14( ) +// Instruction "DEC A" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_14( ) +{ +unsigned char destination = ReadD( _ACC_ ); +destination--; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_15( ) +// Instruction "DEC direct" takes 1 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_15( ) +{ +unsigned char destaddr = PGMMem->Read8( PC++ ); +unsigned char destination = ReadD( destaddr ); +destination--; +WriteD( destaddr, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_16( ) +// Instruction "DEC @R0" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_16( ) +{ +unsigned char destination = ReadI ( ReadD( BANKPSW + _R0_ ) ); +destination--; +WriteI( ReadD( BANKPSW + _R0_ ), destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_17( ) +// Instruction "DEC @R1" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_17( ) +{ +unsigned char destination = ReadI ( ReadD( BANKPSW + _R1_ ) ); +destination--; +WriteI( ReadD( BANKPSW + _R1_ ), destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_18( ) +// Instruction "DEC R0" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_18( ) +{ +unsigned char destination = ReadD( BANKPSW + _R0_ ); +destination--; +WriteD( BANKPSW + _R0_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_19( ) +// Instruction "DEC R1" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_19( ) +{ +unsigned char destination = ReadD( BANKPSW + _R1_ ); +destination--; +WriteD( BANKPSW + _R1_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_1A( ) +// Instruction "DEC R2" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_1A( ) +{ +unsigned char destination = ReadD( BANKPSW + _R2_ ); +destination--; +WriteD( BANKPSW + _R2_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_1B( ) +// Instruction "DEC R3" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_1B( ) +{ +unsigned char destination = ReadD( BANKPSW + _R3_ ); +destination--; +WriteD( BANKPSW + _R3_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_1C( ) +// Instruction "DEC R4" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_1C( ) +{ +unsigned char destination = ReadD( BANKPSW + _R4_ ); +destination--; +WriteD( BANKPSW + _R4_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_1D( ) +// Instruction "DEC R5" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_1D( ) +{ +unsigned char destination = ReadD( BANKPSW + _R5_ ); +destination--; +WriteD( BANKPSW + _R5_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_1E( ) +// Instruction "DEC R6" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_1E( ) +{ +unsigned char destination = ReadD( BANKPSW + _R6_ ); +destination--; +WriteD( BANKPSW + _R6_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_1F( ) +// Instruction "DEC R7" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_1F( ) +{ +unsigned char destination = ReadD( BANKPSW + _R7_ ); +destination--; +WriteD( BANKPSW + _R7_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_20( ) +// Instruction "JB bitaddr,reladdr" takes 2 cycle(s) and 3 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_20( ) +{ +unsigned char destination, dstbitaddr = PGMMem->Read8( PC++ ); +destination = ReadB( dstbitaddr ); +PC++; +unsigned int source = ( ( PGMMem->Read8( PC - 1 ) + PC ) & 0xFF ) + ( PC & 0xFF00 ); +if ( destination == 1 ) { PC = source; } +WriteB( dstbitaddr, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_21( ) +// Instruction "AJMP addr11" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_21( ) +{ +unsigned int addr11 = ( ( PGMMem->Read8( PC - 1 ) << 3 ) & 0xF00 ) + PGMMem->Read8( PC++ ); +PC = ( PC & 0xF800 ) | addr11; +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_22( ) +// Instruction "RET" takes 2 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_22( ) +{ +unsigned char SP = ReadD( _SP_ ); +PC = ( ReadI( SP-- ) << 8 ); +PC += ReadI ( SP-- ); +WriteD( _SP_, SP ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_23( ) +// Instruction "RL A" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_23( ) +{ +unsigned char destination = ReadD( _ACC_ ); +destination = ( destination << 1 ) | ( destination >> 7 ); +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_24( ) +// Instruction "ADD A,#data" takes 1 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_24( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = PGMMem->Read8( PC++ ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x3B ) ); +if ( destination + source > 0xFF ) { + WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); + if ( ( destination & 0x7F ) + ( source & 0x7F ) < 0x80 ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +} else if ( ( destination & 0x7F ) + ( source & 0x7F ) > 0x7F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +if ( ( destination & 0x0F ) + ( source & 0x0F ) > 0x0F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +destination += source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_25( ) +// Instruction "ADD A,direct" takes 1 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_25( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char srcaddr = PGMMem->Read8( PC++ ); +unsigned char source = ReadD( srcaddr ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x3B ) ); +if ( destination + source > 0xFF ) { + WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); + if ( ( destination & 0x7F ) + ( source & 0x7F ) < 0x80 ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +} else if ( ( destination & 0x7F ) + ( source & 0x7F ) > 0x7F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +if ( ( destination & 0x0F ) + ( source & 0x0F ) > 0x0F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +destination += source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_26( ) +// Instruction "ADD A,@R0" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_26( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadI ( ReadD( BANKPSW + _R0_ ) ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x3B ) ); +if ( destination + source > 0xFF ) { + WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); + if ( ( destination & 0x7F ) + ( source & 0x7F ) < 0x80 ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +} else if ( ( destination & 0x7F ) + ( source & 0x7F ) > 0x7F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +if ( ( destination & 0x0F ) + ( source & 0x0F ) > 0x0F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +destination += source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_27( ) +// Instruction "ADD A,@R1" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_27( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadI ( ReadD( BANKPSW + _R1_ ) ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x3B ) ); +if ( destination + source > 0xFF ) { + WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); + if ( ( destination & 0x7F ) + ( source & 0x7F ) < 0x80 ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +} else if ( ( destination & 0x7F ) + ( source & 0x7F ) > 0x7F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +if ( ( destination & 0x0F ) + ( source & 0x0F ) > 0x0F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +destination += source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_28( ) +// Instruction "ADD A,R0" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_28( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R0_ ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x3B ) ); +if ( destination + source > 0xFF ) { + WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); + if ( ( destination & 0x7F ) + ( source & 0x7F ) < 0x80 ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +} else if ( ( destination & 0x7F ) + ( source & 0x7F ) > 0x7F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +if ( ( destination & 0x0F ) + ( source & 0x0F ) > 0x0F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +destination += source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_29( ) +// Instruction "ADD A,R1" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_29( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R1_ ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x3B ) ); +if ( destination + source > 0xFF ) { + WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); + if ( ( destination & 0x7F ) + ( source & 0x7F ) < 0x80 ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +} else if ( ( destination & 0x7F ) + ( source & 0x7F ) > 0x7F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +if ( ( destination & 0x0F ) + ( source & 0x0F ) > 0x0F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +destination += source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_2A( ) +// Instruction "ADD A,R2" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_2A( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R2_ ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x3B ) ); +if ( destination + source > 0xFF ) { + WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); + if ( ( destination & 0x7F ) + ( source & 0x7F ) < 0x80 ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +} else if ( ( destination & 0x7F ) + ( source & 0x7F ) > 0x7F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +if ( ( destination & 0x0F ) + ( source & 0x0F ) > 0x0F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +destination += source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_2B( ) +// Instruction "ADD A,R3" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_2B( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R3_ ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x3B ) ); +if ( destination + source > 0xFF ) { + WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); + if ( ( destination & 0x7F ) + ( source & 0x7F ) < 0x80 ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +} else if ( ( destination & 0x7F ) + ( source & 0x7F ) > 0x7F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +if ( ( destination & 0x0F ) + ( source & 0x0F ) > 0x0F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +destination += source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_2C( ) +// Instruction "ADD A,R4" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_2C( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R4_ ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x3B ) ); +if ( destination + source > 0xFF ) { + WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); + if ( ( destination & 0x7F ) + ( source & 0x7F ) < 0x80 ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +} else if ( ( destination & 0x7F ) + ( source & 0x7F ) > 0x7F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +if ( ( destination & 0x0F ) + ( source & 0x0F ) > 0x0F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +destination += source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_2D( ) +// Instruction "ADD A,R5" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_2D( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R5_ ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x3B ) ); +if ( destination + source > 0xFF ) { + WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); + if ( ( destination & 0x7F ) + ( source & 0x7F ) < 0x80 ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +} else if ( ( destination & 0x7F ) + ( source & 0x7F ) > 0x7F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +if ( ( destination & 0x0F ) + ( source & 0x0F ) > 0x0F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +destination += source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_2E( ) +// Instruction "ADD A,R6" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_2E( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R6_ ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x3B ) ); +if ( destination + source > 0xFF ) { + WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); + if ( ( destination & 0x7F ) + ( source & 0x7F ) < 0x80 ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +} else if ( ( destination & 0x7F ) + ( source & 0x7F ) > 0x7F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +if ( ( destination & 0x0F ) + ( source & 0x0F ) > 0x0F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +destination += source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_2F( ) +// Instruction "ADD A,R7" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_2F( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R7_ ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x3B ) ); +if ( destination + source > 0xFF ) { + WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); + if ( ( destination & 0x7F ) + ( source & 0x7F ) < 0x80 ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +} else if ( ( destination & 0x7F ) + ( source & 0x7F ) > 0x7F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +if ( ( destination & 0x0F ) + ( source & 0x0F ) > 0x0F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +destination += source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_30( ) +// Instruction "JNB bitaddr,reladdr" takes 2 cycle(s) and 3 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_30( ) +{ +unsigned char destination, dstbitaddr = PGMMem->Read8( PC++ ); +destination = ReadB( dstbitaddr ); +PC++; +unsigned int source = ( ( PGMMem->Read8( PC - 1 ) + PC ) & 0xFF ) + ( PC & 0xFF00 ); +if ( destination == 0 ) { PC = source; } +WriteB( dstbitaddr, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_31( ) +// Instruction "ACALL addr11" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_31( ) +{ +unsigned int addr11 = ( ( PGMMem->Read8( PC - 1 ) << 3 ) & 0xF00 ) + PGMMem->Read8( PC++ ); +unsigned char SP = ReadD( _SP_ ); +WriteI( ++SP, ( PC & 0x00FF ) ); +WriteI( ++SP, ( PC >> 8 ) ); +WriteD( _SP_, SP ); +PC = ( PC & 0xF800 ) | addr11; +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_32( ) +// Instruction "RETI" takes 2 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_32( ) +{ +ActivePriority = -1; +unsigned char SP = ReadD( _SP_ ); +PC = ( ReadI( SP-- ) << 8 ); +PC += ReadI( SP-- ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_33( ) +// Instruction "RLC A" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_33( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char tmpval = destination; +destination = ( destination << 1 ) | ( ( ReadD( _PSW_ ) & 0x80 ) >> 7 ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x7F ) | ( tmpval & 0x80 ) ); +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_34( ) +// Instruction "ADDC A,#data" takes 1 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_34( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = PGMMem->Read8( PC++ ); +unsigned char carryflag = ( ReadD( _PSW_ ) >> 7 ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x3B ) ); +if ( destination + source + carryflag > 0xFF ) { + WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); + if ( ( destination & 0x7F ) + ( source & 0x7F ) + carryflag < 0x80 ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +} else if ( ( destination & 0x7F ) + ( source & 0x7F ) + carryflag > 0x7F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +if ( ( destination & 0x0F ) + ( source & 0x0F ) + carryflag > 0x0F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x40 ) ); +destination += source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_35( ) +// Instruction "ADDC A,direct" takes 1 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_35( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char srcaddr = PGMMem->Read8( PC++ ); +unsigned char source = ReadD( srcaddr ); +unsigned char carryflag = ( ReadD( _PSW_ ) >> 7 ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x3B ) ); +if ( destination + source + carryflag > 0xFF ) { + WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); + if ( ( destination & 0x7F ) + ( source & 0x7F ) + carryflag < 0x80 ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +} else if ( ( destination & 0x7F ) + ( source & 0x7F ) + carryflag > 0x7F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +if ( ( destination & 0x0F ) + ( source & 0x0F ) + carryflag > 0x0F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x40 ) ); +destination += source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_36( ) +// Instruction "ADDC A,@R0" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_36( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadI ( ReadD( BANKPSW + _R0_ ) ); +unsigned char carryflag = ( ReadD( _PSW_ ) >> 7 ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x3B ) ); +if ( destination + source + carryflag > 0xFF ) { + WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); + if ( ( destination & 0x7F ) + ( source & 0x7F ) + carryflag < 0x80 ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +} else if ( ( destination & 0x7F ) + ( source & 0x7F ) + carryflag > 0x7F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +if ( ( destination & 0x0F ) + ( source & 0x0F ) + carryflag > 0x0F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x40 ) ); +destination += source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_37( ) +// Instruction "ADDC A,@R1" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_37( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadI ( ReadD( BANKPSW + _R1_ ) ); +unsigned char carryflag = ( ReadD( _PSW_ ) >> 7 ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x3B ) ); +if ( destination + source + carryflag > 0xFF ) { + WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); + if ( ( destination & 0x7F ) + ( source & 0x7F ) + carryflag < 0x80 ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +} else if ( ( destination & 0x7F ) + ( source & 0x7F ) + carryflag > 0x7F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +if ( ( destination & 0x0F ) + ( source & 0x0F ) + carryflag > 0x0F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x40 ) ); +destination += source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_38( ) +// Instruction "ADDC A,R0" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_38( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R0_ ); +unsigned char carryflag = ( ReadD( _PSW_ ) >> 7 ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x3B ) ); +if ( destination + source + carryflag > 0xFF ) { + WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); + if ( ( destination & 0x7F ) + ( source & 0x7F ) + carryflag < 0x80 ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +} else if ( ( destination & 0x7F ) + ( source & 0x7F ) + carryflag > 0x7F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +if ( ( destination & 0x0F ) + ( source & 0x0F ) + carryflag > 0x0F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x40 ) ); +destination += source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_39( ) +// Instruction "ADDC A,R1" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_39( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R1_ ); +unsigned char carryflag = ( ReadD( _PSW_ ) >> 7 ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x3B ) ); +if ( destination + source + carryflag > 0xFF ) { + WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); + if ( ( destination & 0x7F ) + ( source & 0x7F ) + carryflag < 0x80 ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +} else if ( ( destination & 0x7F ) + ( source & 0x7F ) + carryflag > 0x7F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +if ( ( destination & 0x0F ) + ( source & 0x0F ) + carryflag > 0x0F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x40 ) ); +destination += source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_3A( ) +// Instruction "ADDC A,R2" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_3A( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R2_ ); +unsigned char carryflag = ( ReadD( _PSW_ ) >> 7 ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x3B ) ); +if ( destination + source + carryflag > 0xFF ) { + WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); + if ( ( destination & 0x7F ) + ( source & 0x7F ) + carryflag < 0x80 ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +} else if ( ( destination & 0x7F ) + ( source & 0x7F ) + carryflag > 0x7F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +if ( ( destination & 0x0F ) + ( source & 0x0F ) + carryflag > 0x0F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x40 ) ); +destination += source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_3B( ) +// Instruction "ADDC A,R3" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_3B( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R3_ ); +unsigned char carryflag = ( ReadD( _PSW_ ) >> 7 ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x3B ) ); +if ( destination + source + carryflag > 0xFF ) { + WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); + if ( ( destination & 0x7F ) + ( source & 0x7F ) + carryflag < 0x80 ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +} else if ( ( destination & 0x7F ) + ( source & 0x7F ) + carryflag > 0x7F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +if ( ( destination & 0x0F ) + ( source & 0x0F ) + carryflag > 0x0F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x40 ) ); +destination += source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_3C( ) +// Instruction "ADDC A,R4" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_3C( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R4_ ); +unsigned char carryflag = ( ReadD( _PSW_ ) >> 7 ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x3B ) ); +if ( destination + source + carryflag > 0xFF ) { + WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); + if ( ( destination & 0x7F ) + ( source & 0x7F ) + carryflag < 0x80 ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +} else if ( ( destination & 0x7F ) + ( source & 0x7F ) + carryflag > 0x7F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +if ( ( destination & 0x0F ) + ( source & 0x0F ) + carryflag > 0x0F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x40 ) ); +destination += source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_3D( ) +// Instruction "ADDC A,R5" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_3D( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R5_ ); +unsigned char carryflag = ( ReadD( _PSW_ ) >> 7 ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x3B ) ); +if ( destination + source + carryflag > 0xFF ) { + WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); + if ( ( destination & 0x7F ) + ( source & 0x7F ) + carryflag < 0x80 ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +} else if ( ( destination & 0x7F ) + ( source & 0x7F ) + carryflag > 0x7F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +if ( ( destination & 0x0F ) + ( source & 0x0F ) + carryflag > 0x0F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x40 ) ); +destination += source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_3E( ) +// Instruction "ADDC A,R6" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_3E( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R6_ ); +unsigned char carryflag = ( ReadD( _PSW_ ) >> 7 ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x3B ) ); +if ( destination + source + carryflag > 0xFF ) { + WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); + if ( ( destination & 0x7F ) + ( source & 0x7F ) + carryflag < 0x80 ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +} else if ( ( destination & 0x7F ) + ( source & 0x7F ) + carryflag > 0x7F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +if ( ( destination & 0x0F ) + ( source & 0x0F ) + carryflag > 0x0F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x40 ) ); +destination += source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_3F( ) +// Instruction "ADDC A,R7" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_3F( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R7_ ); +unsigned char carryflag = ( ReadD( _PSW_ ) >> 7 ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x3B ) ); +if ( destination + source + carryflag > 0xFF ) { + WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); + if ( ( destination & 0x7F ) + ( source & 0x7F ) + carryflag < 0x80 ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +} else if ( ( destination & 0x7F ) + ( source & 0x7F ) + carryflag > 0x7F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +if ( ( destination & 0x0F ) + ( source & 0x0F ) + carryflag > 0x0F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x40 ) ); +destination += source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_40( ) +// Instruction "JC reladdr" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_40( ) +{ +PC++; +unsigned int destination = ( ( PGMMem->Read8( PC - 1 ) + PC ) & 0xFF ) + ( PC & 0xFF00 ); +if ( ReadD( _PSW_ ) > 0x7F) { PC = destination; } +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_41( ) +// Instruction "AJMP addr11" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_41( ) +{ +unsigned int addr11 = ( ( PGMMem->Read8( PC - 1 ) << 3 ) & 0xF00 ) + PGMMem->Read8( PC++ ); +PC = ( PC & 0xF800 ) | addr11; +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_42( ) +// Instruction "ORL direct,A" takes 1 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_42( ) +{ +unsigned char destaddr = PGMMem->Read8( PC++ ); +unsigned char destination = ReadD( destaddr ); +unsigned char source = ReadD( _ACC_ ); +destination |= source; +WriteD( destaddr, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_43( ) +// Instruction "ORL direct,#data" takes 2 cycle(s) and 3 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_43( ) +{ +unsigned char destaddr = PGMMem->Read8( PC++ ); +unsigned char destination = ReadD( destaddr ); +unsigned char source = PGMMem->Read8( PC++ ); +destination |= source; +WriteD( destaddr, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_44( ) +// Instruction "ORL A,#data" takes 1 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_44( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = PGMMem->Read8( PC++ ); +destination |= source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_45( ) +// Instruction "ORL A,direct" takes 1 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_45( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char srcaddr = PGMMem->Read8( PC++ ); +unsigned char source = ReadD( srcaddr ); +destination |= source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_46( ) +// Instruction "ORL A,@R0" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_46( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadI ( ReadD( BANKPSW + _R0_ ) ); +destination |= source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_47( ) +// Instruction "ORL A,@R1" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_47( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadI ( ReadD( BANKPSW + _R1_ ) ); +destination |= source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_48( ) +// Instruction "ORL A,R0" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_48( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R0_ ); +destination |= source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_49( ) +// Instruction "ORL A,R1" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_49( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R1_ ); +destination |= source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_4A( ) +// Instruction "ORL A,R2" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_4A( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R2_ ); +destination |= source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_4B( ) +// Instruction "ORL A,R3" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_4B( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R3_ ); +destination |= source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_4C( ) +// Instruction "ORL A,R4" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_4C( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R4_ ); +destination |= source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_4D( ) +// Instruction "ORL A,R5" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_4D( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R5_ ); +destination |= source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_4E( ) +// Instruction "ORL A,R6" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_4E( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R6_ ); +destination |= source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_4F( ) +// Instruction "ORL A,R7" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_4F( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R7_ ); +destination |= source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_50( ) +// Instruction "JNC reladdr" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_50( ) +{ +PC++; +unsigned int destination = ( ( PGMMem->Read8( PC - 1 ) + PC ) & 0xFF ) + ( PC & 0xFF00 ); +if ( ReadD( _PSW_ ) < 0x80 ) { PC = destination; } +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_51( ) +// Instruction "ACALL addr11" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_51( ) +{ +unsigned int addr11 = ( ( PGMMem->Read8( PC - 1 ) << 3 ) & 0xF00 ) + PGMMem->Read8( PC++ ); +unsigned char SP = ReadD( _SP_ ); +WriteI( ++SP, ( PC & 0x00FF ) ); +WriteI( ++SP, ( PC >> 8 ) ); +WriteD( _SP_, SP ); +PC = ( PC & 0xF800 ) | addr11; +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_52( ) +// Instruction "ANL direct,A" takes 1 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_52( ) +{ +unsigned char destaddr = PGMMem->Read8( PC++ ); +unsigned char destination = ReadD( destaddr ); +unsigned char source = ReadD( _ACC_ ); +destination &= source; +WriteD( destaddr, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_53( ) +// Instruction "ANL direct,#data" takes 2 cycle(s) and 3 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_53( ) +{ +unsigned char destaddr = PGMMem->Read8( PC++ ); +unsigned char destination = ReadD( destaddr ); +unsigned char source = PGMMem->Read8( PC++ ); +destination &= source; +WriteD( destaddr, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_54( ) +// Instruction "ANL A,#data" takes 1 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_54( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = PGMMem->Read8( PC++ ); +destination &= source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_55( ) +// Instruction "ANL A,direct" takes 1 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_55( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char srcaddr = PGMMem->Read8( PC++ ); +unsigned char source = ReadD( srcaddr ); +destination &= source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_56( ) +// Instruction "ANL A,@R0" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_56( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadI ( ReadD( BANKPSW + _R0_ ) ); +destination &= source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_57( ) +// Instruction "ANL A,@R1" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_57( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadI ( ReadD( BANKPSW + _R1_ ) ); +destination &= source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_58( ) +// Instruction "ANL A,R0" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_58( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R0_ ); +destination &= source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_59( ) +// Instruction "ANL A,R1" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_59( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R1_ ); +destination &= source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_5A( ) +// Instruction "ANL A,R2" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_5A( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R2_ ); +destination &= source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_5B( ) +// Instruction "ANL A,R3" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_5B( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R3_ ); +destination &= source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_5C( ) +// Instruction "ANL A,R4" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_5C( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R4_ ); +destination &= source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_5D( ) +// Instruction "ANL A,R5" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_5D( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R5_ ); +destination &= source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_5E( ) +// Instruction "ANL A,R6" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_5E( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R6_ ); +destination &= source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_5F( ) +// Instruction "ANL A,R7" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_5F( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R7_ ); +destination &= source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_60( ) +// Instruction "JZ reladdr" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_60( ) +{ +PC++; +unsigned int destination = ( ( PGMMem->Read8( PC - 1 ) + PC ) & 0xFF ) + ( PC & 0xFF00 ); +if ( ReadD( _ACC_ ) == 0 ) { PC = destination; } +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_61( ) +// Instruction "AJMP addr11" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_61( ) +{ +unsigned int addr11 = ( ( PGMMem->Read8( PC - 1 ) << 3 ) & 0xF00 ) + PGMMem->Read8( PC++ ); +PC = ( PC & 0xF800 ) | addr11; +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_62( ) +// Instruction "XRL direct,A" takes 1 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_62( ) +{ +unsigned char destaddr = PGMMem->Read8( PC++ ); +unsigned char destination = ReadD( destaddr ); +unsigned char source = ReadD( _ACC_ ); +destination ^= source; +WriteD( destaddr, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_63( ) +// Instruction "XRL direct,#data" takes 2 cycle(s) and 3 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_63( ) +{ +unsigned char destaddr = PGMMem->Read8( PC++ ); +unsigned char destination = ReadD( destaddr ); +unsigned char source = PGMMem->Read8( PC++ ); +destination ^= source; +WriteD( destaddr, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_64( ) +// Instruction "XRL A,#data" takes 1 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_64( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = PGMMem->Read8( PC++ ); +destination ^= source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_65( ) +// Instruction "XRL A,direct" takes 1 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_65( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char srcaddr = PGMMem->Read8( PC++ ); +unsigned char source = ReadD( srcaddr ); +destination ^= source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_66( ) +// Instruction "XRL A,@R0" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_66( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadI ( ReadD( BANKPSW + _R0_ ) ); +destination ^= source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_67( ) +// Instruction "XRL A,@R1" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_67( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadI ( ReadD( BANKPSW + _R1_ ) ); +destination ^= source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_68( ) +// Instruction "XRL A,R0" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_68( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R0_ ); +destination ^= source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_69( ) +// Instruction "XRL A,R1" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_69( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R1_ ); +destination ^= source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_6A( ) +// Instruction "XRL A,R2" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_6A( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R2_ ); +destination ^= source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_6B( ) +// Instruction "XRL A,R3" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_6B( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R3_ ); +destination ^= source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_6C( ) +// Instruction "XRL A,R4" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_6C( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R4_ ); +destination ^= source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_6D( ) +// Instruction "XRL A,R5" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_6D( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R5_ ); +destination ^= source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_6E( ) +// Instruction "XRL A,R6" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_6E( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R6_ ); +destination ^= source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_6F( ) +// Instruction "XRL A,R7" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_6F( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R7_ ); +destination ^= source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_70( ) +// Instruction "JNZ reladdr" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_70( ) +{ +PC++; +unsigned int destination = ( ( PGMMem->Read8( PC - 1 ) + PC ) & 0xFF ) + ( PC & 0xFF00 ); +if ( ReadD( _ACC_ ) != 0 ) { PC = destination; } +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_71( ) +// Instruction "ACALL addr11" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_71( ) +{ +unsigned int addr11 = ( ( PGMMem->Read8( PC - 1 ) << 3 ) & 0xF00 ) + PGMMem->Read8( PC++ ); +unsigned char SP = ReadD( _SP_ ); +WriteI( ++SP, ( PC & 0x00FF ) ); +WriteI( ++SP, ( PC >> 8 ) ); +WriteD( _SP_, SP ); +PC = ( PC & 0xF800 ) | addr11; +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_72( ) +// Instruction "ORL C,bitaddr" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_72( ) +{ +unsigned char destination = ( ReadD( _PSW_ ) >> 7 ); +unsigned char source, srcbitaddr = PGMMem->Read8( PC++ ); +source = ReadB( srcbitaddr ); +WriteD( _PSW_ , ( ( destination | source ) << 7 ) ); +WriteD( _PSW_, ( ( ReadD( _PSW_ ) & 0x7F) | ( destination << 7 ) ) ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_73( ) +// Instruction "JMP @A+DPTR" takes 2 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_73( ) +{ +unsigned int destination = ReadI( ReadD( _ACC_ ) + ReadD( _DPTRLOW_ ) + ( ReadD( _DPTRHIGH_ ) << 8 ) ); +PC = destination; +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_74( ) +// Instruction "MOV A,#data" takes 1 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_74( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = PGMMem->Read8( PC++ ); +destination = source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_75( ) +// Instruction "MOV direct,#data" takes 2 cycle(s) and 3 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_75( ) +{ +unsigned char destaddr = PGMMem->Read8( PC++ ); +unsigned char destination = ReadD( destaddr ); +unsigned char source = PGMMem->Read8( PC++ ); +destination = source; +WriteD( destaddr, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_76( ) +// Instruction "MOV @R0,#data" takes 1 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_76( ) +{ +unsigned char destination = ReadI ( ReadD( BANKPSW + _R0_ ) ); +unsigned char source = PGMMem->Read8( PC++ ); +destination = source; +WriteI( ReadD( BANKPSW + _R0_ ), destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_77( ) +// Instruction "MOV @R1,#data" takes 1 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_77( ) +{ +unsigned char destination = ReadI ( ReadD( BANKPSW + _R1_ ) ); +unsigned char source = PGMMem->Read8( PC++ ); +destination = source; +WriteI( ReadD( BANKPSW + _R1_ ), destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_78( ) +// Instruction "MOV R0,#data" takes 1 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_78( ) +{ +unsigned char destination = ReadD( BANKPSW + _R0_ ); +unsigned char source = PGMMem->Read8( PC++ ); +destination = source; +WriteD( BANKPSW + _R0_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_79( ) +// Instruction "MOV R1,#data" takes 1 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_79( ) +{ +unsigned char destination = ReadD( BANKPSW + _R1_ ); +unsigned char source = PGMMem->Read8( PC++ ); +destination = source; +WriteD( BANKPSW + _R1_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_7A( ) +// Instruction "MOV R2,#data" takes 1 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_7A( ) +{ +unsigned char destination = ReadD( BANKPSW + _R2_ ); +unsigned char source = PGMMem->Read8( PC++ ); +destination = source; +WriteD( BANKPSW + _R2_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_7B( ) +// Instruction "MOV R3,#data" takes 1 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_7B( ) +{ +unsigned char destination = ReadD( BANKPSW + _R3_ ); +unsigned char source = PGMMem->Read8( PC++ ); +destination = source; +WriteD( BANKPSW + _R3_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_7C( ) +// Instruction "MOV R4,#data" takes 1 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_7C( ) +{ +unsigned char destination = ReadD( BANKPSW + _R4_ ); +unsigned char source = PGMMem->Read8( PC++ ); +destination = source; +WriteD( BANKPSW + _R4_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_7D( ) +// Instruction "MOV R5,#data" takes 1 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_7D( ) +{ +unsigned char destination = ReadD( BANKPSW + _R5_ ); +unsigned char source = PGMMem->Read8( PC++ ); +destination = source; +WriteD( BANKPSW + _R5_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_7E( ) +// Instruction "MOV R6,#data" takes 1 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_7E( ) +{ +unsigned char destination = ReadD( BANKPSW + _R6_ ); +unsigned char source = PGMMem->Read8( PC++ ); +destination = source; +WriteD( BANKPSW + _R6_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_7F( ) +// Instruction "MOV R7,#data" takes 1 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_7F( ) +{ +unsigned char destination = ReadD( BANKPSW + _R7_ ); +unsigned char source = PGMMem->Read8( PC++ ); +destination = source; +WriteD( BANKPSW + _R7_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_80( ) +// Instruction "SJMP reladdr" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_80( ) +{ +PC++; +unsigned int destination = ( ( PGMMem->Read8( PC - 1 ) + PC ) & 0xFF ) + ( PC & 0xFF00 ); +PC = destination; +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_81( ) +// Instruction "AJMP addr11" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_81( ) +{ +unsigned int addr11 = ( ( PGMMem->Read8( PC - 1 ) << 3 ) & 0xF00 ) + PGMMem->Read8( PC++ ); +PC = ( PC & 0xF800 ) | addr11; +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_82( ) +// Instruction "ANL C,bitaddr" takes 1 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_82( ) +{ +unsigned char destination = ( ReadD( _PSW_ ) >> 7 ); +unsigned char source, srcbitaddr = PGMMem->Read8( PC++ ); +source = ReadB( srcbitaddr ); +WriteD( _PSW_, ( ( destination & source) << 7 ) ); +WriteD( _PSW_, ( ( ReadD( _PSW_ ) & 0x7F) | ( destination << 7 ) ) ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_83( ) +// Instruction "MOVC A,@A+PC" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_83( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = PGMMem->Read8( ReadD( _ACC_ ) + ( ++PC ) ); +destination = source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_84( ) +// Instruction "DIV AB" takes 4 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_84( ) +{ +unsigned char A = ReadD( _ACC_ ), B = ReadD( _B_ ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x7B ) ); +if ( B != 0 ) { +WriteD( _ACC_, A/B ); WriteD( _B_, A%B ); +} else WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +return 4; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_85( ) +// Instruction "MOV direct,direct" takes 1 cycle(s) and 3 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_85( ) +{ +unsigned char srcaddr = PGMMem->Read8( PC++ ); +unsigned char source = ReadD( srcaddr ); +unsigned char destaddr = PGMMem->Read8( PC++ ); +unsigned char destination = ReadD( destaddr ); +destination = source; +WriteD( destaddr, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_86( ) +// Instruction "MOV direct,@R0" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_86( ) +{ +unsigned char destaddr = PGMMem->Read8( PC++ ); +unsigned char destination = ReadD( destaddr ); +unsigned char source = ReadI ( ReadD( BANKPSW + _R0_ ) ); +destination = source; +WriteD( destaddr, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_87( ) +// Instruction "MOV direct,@R1" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_87( ) +{ +unsigned char destaddr = PGMMem->Read8( PC++ ); +unsigned char destination = ReadD( destaddr ); +unsigned char source = ReadI ( ReadD( BANKPSW + _R1_ ) ); +destination = source; +WriteD( destaddr, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_88( ) +// Instruction "MOV direct,R0" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_88( ) +{ +unsigned char destaddr = PGMMem->Read8( PC++ ); +unsigned char destination = ReadD( destaddr ); +unsigned char source = ReadD( BANKPSW + _R0_ ); +destination = source; +WriteD( destaddr, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_89( ) +// Instruction "MOV direct,R1" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_89( ) +{ +unsigned char destaddr = PGMMem->Read8( PC++ ); +unsigned char destination = ReadD( destaddr ); +unsigned char source = ReadD( BANKPSW + _R1_ ); +destination = source; +WriteD( destaddr, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_8A( ) +// Instruction "MOV direct,R2" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_8A( ) +{ +unsigned char destaddr = PGMMem->Read8( PC++ ); +unsigned char destination = ReadD( destaddr ); +unsigned char source = ReadD( BANKPSW + _R2_ ); +destination = source; +WriteD( destaddr, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_8B( ) +// Instruction "MOV direct,R3" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_8B( ) +{ +unsigned char destaddr = PGMMem->Read8( PC++ ); +unsigned char destination = ReadD( destaddr ); +unsigned char source = ReadD( BANKPSW + _R3_ ); +destination = source; +WriteD( destaddr, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_8C( ) +// Instruction "MOV direct,R4" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_8C( ) +{ +unsigned char destaddr = PGMMem->Read8( PC++ ); +unsigned char destination = ReadD( destaddr ); +unsigned char source = ReadD( BANKPSW + _R4_ ); +destination = source; +WriteD( destaddr, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_8D( ) +// Instruction "MOV direct,R5" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_8D( ) +{ +unsigned char destaddr = PGMMem->Read8( PC++ ); +unsigned char destination = ReadD( destaddr ); +unsigned char source = ReadD( BANKPSW + _R5_ ); +destination = source; +WriteD( destaddr, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_8E( ) +// Instruction "MOV direct,R6" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_8E( ) +{ +unsigned char destaddr = PGMMem->Read8( PC++ ); +unsigned char destination = ReadD( destaddr ); +unsigned char source = ReadD( BANKPSW + _R6_ ); +destination = source; +WriteD( destaddr, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_8F( ) +// Instruction "MOV direct,R7" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_8F( ) +{ +unsigned char destaddr = PGMMem->Read8( PC++ ); +unsigned char destination = ReadD( destaddr ); +unsigned char source = ReadD( BANKPSW + _R7_ ); +destination = source; +WriteD( destaddr, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_90( ) +// Instruction "MOV DPTR,#data16" takes 2 cycle(s) and 3 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_90( ) +{ +unsigned int destination = ( ReadD( _DPTRHIGH_ ) << 8 ) + ReadD( _DPTRLOW_ ); +unsigned char source = ( PGMMem->Read8( PC++ ) << 8 ); +source += PGMMem->Read8( PC++ ); +destination = source; +WriteD( _DPTRHIGH_, ( destination >> 8 ) ); +WriteD( _DPTRLOW_, ( destination & 0xFF ) ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_91( ) +// Instruction "ACALL addr11" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_91( ) +{ +unsigned int addr11 = ( ( PGMMem->Read8( PC - 1 ) << 3 ) & 0xF00 ) + PGMMem->Read8( PC++ ); +unsigned char SP = ReadD( _SP_ ); +WriteI( ++SP, ( PC & 0x00FF ) ); +WriteI( ++SP, ( PC >> 8 ) ); +WriteD( _SP_, SP ); +PC = ( PC & 0xF800 ) | addr11; +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_92( ) +// Instruction "MOV bitaddr,C" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_92( ) +{ +unsigned char destination, dstbitaddr = PGMMem->Read8( PC++ ); +destination = ReadB( dstbitaddr ); +unsigned char source = ( ReadD( _PSW_ ) >> 7 ); +destination = source; +WriteB( dstbitaddr, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_93( ) +// Instruction "MOVC A,@A+DPTR" takes 2 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_93( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = PGMMem->Read8( ReadD( _ACC_ ) + ReadD( _DPTRLOW_ ) + ( ReadD( _DPTRHIGH_ ) << 8 ) ); +destination = source; +WriteD( _ACC_, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_94( ) +// Instruction "SUBB A,#data" takes 1 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_94( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = PGMMem->Read8( PC++ ); +unsigned char carryflag = ReadD( _PSW_ ) >> 7; +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x3B ) ); +if ( destination < ( source + carryflag ) ) { + WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); + if ( ( destination & 0x7F ) > ( ( source + carryflag ) & 0x7F ) ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +} else if ( ( destination & 0x7F ) < ( ( source + carryflag ) & 0x7F ) ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +if ( ( destination & 0x0F ) < ( ( source + carryflag ) & 0x0F ) ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x40 ) ); +destination -= source + carryflag; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_95( ) +// Instruction "SUBB A,direct" takes 1 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_95( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char srcaddr = PGMMem->Read8( PC++ ); +unsigned char source = ReadD( srcaddr ); +unsigned char carryflag = ReadD( _PSW_ ) >> 7; +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x3B ) ); +if ( destination < ( source + carryflag ) ) { + WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); + if ( ( destination & 0x7F ) > ( ( source + carryflag ) & 0x7F ) ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +} else if ( ( destination & 0x7F ) < ( ( source + carryflag ) & 0x7F ) ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +if ( ( destination & 0x0F ) < ( ( source + carryflag ) & 0x0F ) ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x40 ) ); +destination -= source + carryflag; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_96( ) +// Instruction "SUBB A,@R0" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_96( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadI ( ReadD( BANKPSW + _R0_ ) ); +unsigned char carryflag = ReadD( _PSW_ ) >> 7; +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x3B ) ); +if ( destination < ( source + carryflag ) ) { + WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); + if ( ( destination & 0x7F ) > ( ( source + carryflag ) & 0x7F ) ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +} else if ( ( destination & 0x7F ) < ( ( source + carryflag ) & 0x7F ) ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +if ( ( destination & 0x0F ) < ( ( source + carryflag ) & 0x0F ) ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x40 ) ); +destination -= source + carryflag; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_97( ) +// Instruction "SUBB A,@R1" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_97( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadI ( ReadD( BANKPSW + _R1_ ) ); +unsigned char carryflag = ReadD( _PSW_ ) >> 7; +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x3B ) ); +if ( destination < ( source + carryflag ) ) { + WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); + if ( ( destination & 0x7F ) > ( ( source + carryflag ) & 0x7F ) ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +} else if ( ( destination & 0x7F ) < ( ( source + carryflag ) & 0x7F ) ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +if ( ( destination & 0x0F ) < ( ( source + carryflag ) & 0x0F ) ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x40 ) ); +destination -= source + carryflag; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_98( ) +// Instruction "SUBB A,R0" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_98( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R0_ ); +unsigned char carryflag = ReadD( _PSW_ ) >> 7; +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x3B ) ); +if ( destination < ( source + carryflag ) ) { + WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); + if ( ( destination & 0x7F ) > ( ( source + carryflag ) & 0x7F ) ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +} else if ( ( destination & 0x7F ) < ( ( source + carryflag ) & 0x7F ) ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +if ( ( destination & 0x0F ) < ( ( source + carryflag ) & 0x0F ) ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x40 ) ); +destination -= source + carryflag; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_99( ) +// Instruction "SUBB A,R1" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_99( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R1_ ); +unsigned char carryflag = ReadD( _PSW_ ) >> 7; +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x3B ) ); +if ( destination < ( source + carryflag ) ) { + WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); + if ( ( destination & 0x7F ) > ( ( source + carryflag ) & 0x7F ) ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +} else if ( ( destination & 0x7F ) < ( ( source + carryflag ) & 0x7F ) ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +if ( ( destination & 0x0F ) < ( ( source + carryflag ) & 0x0F ) ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x40 ) ); +destination -= source + carryflag; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_9A( ) +// Instruction "SUBB A,R2" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_9A( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R2_ ); +unsigned char carryflag = ReadD( _PSW_ ) >> 7; +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x3B ) ); +if ( destination < ( source + carryflag ) ) { + WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); + if ( ( destination & 0x7F ) > ( ( source + carryflag ) & 0x7F ) ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +} else if ( ( destination & 0x7F ) < ( ( source + carryflag ) & 0x7F ) ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +if ( ( destination & 0x0F ) < ( ( source + carryflag ) & 0x0F ) ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x40 ) ); +destination -= source + carryflag; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_9B( ) +// Instruction "SUBB A,R3" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_9B( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R3_ ); +unsigned char carryflag = ReadD( _PSW_ ) >> 7; +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x3B ) ); +if ( destination < ( source + carryflag ) ) { + WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); + if ( ( destination & 0x7F ) > ( ( source + carryflag ) & 0x7F ) ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +} else if ( ( destination & 0x7F ) < ( ( source + carryflag ) & 0x7F ) ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +if ( ( destination & 0x0F ) < ( ( source + carryflag ) & 0x0F ) ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x40 ) ); +destination -= source + carryflag; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_9C( ) +// Instruction "SUBB A,R4" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_9C( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R4_ ); +unsigned char carryflag = ReadD( _PSW_ ) >> 7; +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x3B ) ); +if ( destination < ( source + carryflag ) ) { + WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); + if ( ( destination & 0x7F ) > ( ( source + carryflag ) & 0x7F ) ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +} else if ( ( destination & 0x7F ) < ( ( source + carryflag ) & 0x7F ) ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +if ( ( destination & 0x0F ) < ( ( source + carryflag ) & 0x0F ) ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x40 ) ); +destination -= source + carryflag; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_9D( ) +// Instruction "SUBB A,R5" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_9D( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R5_ ); +unsigned char carryflag = ReadD( _PSW_ ) >> 7; +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x3B ) ); +if ( destination < ( source + carryflag ) ) { + WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); + if ( ( destination & 0x7F ) > ( ( source + carryflag ) & 0x7F ) ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +} else if ( ( destination & 0x7F ) < ( ( source + carryflag ) & 0x7F ) ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +if ( ( destination & 0x0F ) < ( ( source + carryflag ) & 0x0F ) ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x40 ) ); +destination -= source + carryflag; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_9E( ) +// Instruction "SUBB A,R6" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_9E( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R6_ ); +unsigned char carryflag = ReadD( _PSW_ ) >> 7; +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x3B ) ); +if ( destination < ( source + carryflag ) ) { + WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); + if ( ( destination & 0x7F ) > ( ( source + carryflag ) & 0x7F ) ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +} else if ( ( destination & 0x7F ) < ( ( source + carryflag ) & 0x7F ) ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +if ( ( destination & 0x0F ) < ( ( source + carryflag ) & 0x0F ) ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x40 ) ); +destination -= source + carryflag; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_9F( ) +// Instruction "SUBB A,R7" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_9F( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R7_ ); +unsigned char carryflag = ReadD( _PSW_ ) >> 7; +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x3B ) ); +if ( destination < ( source + carryflag ) ) { + WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); + if ( ( destination & 0x7F ) > ( ( source + carryflag ) & 0x7F ) ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +} else if ( ( destination & 0x7F ) < ( ( source + carryflag ) & 0x7F ) ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +if ( ( destination & 0x0F ) < ( ( source + carryflag ) & 0x0F ) ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x40 ) ); +destination -= source + carryflag; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_A0( ) +// Instruction "ORL C,/bitaddr" takes 1 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_A0( ) +{ +unsigned char destination = ( ReadD( _PSW_ ) >> 7 ); +unsigned char source, srcbitaddr = PGMMem->Read8( PC++ ); +source = ( ReadB( srcbitaddr ) ^ 1 ); +WriteD( _PSW_ , ( ( destination | source ) << 7 ) ); +WriteD( _PSW_, ( ( ReadD( _PSW_ ) & 0x7F) | ( destination << 7 ) ) ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_A1( ) +// Instruction "AJMP addr11" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_A1( ) +{ +unsigned int addr11 = ( ( PGMMem->Read8( PC - 1 ) << 3 ) & 0xF00 ) + PGMMem->Read8( PC++ ); +PC = ( PC & 0xF800 ) | addr11; +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_A2( ) +// Instruction "MOV C,bitaddr" takes 1 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_A2( ) +{ +unsigned char destination = ( ReadD( _PSW_ ) >> 7 ); +unsigned char source, srcbitaddr = PGMMem->Read8( PC++ ); +source = ReadB( srcbitaddr ); +destination = source; +WriteD( _PSW_, ( ( ReadD( _PSW_ ) & 0x7F) | ( destination << 7 ) ) ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_A3( ) +// Instruction "INC DPTR" takes 2 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_A3( ) +{ +unsigned int destination = ( ReadD( _DPTRHIGH_ ) << 8 ) + ReadD( _DPTRLOW_ ); +destination++; +WriteD( _DPTRHIGH_, ( destination >> 8 ) ); +WriteD( _DPTRLOW_, ( destination & 0xFF ) ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_A4( ) +// Instruction "MUL AB" takes 4 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_A4( ) +{ +unsigned char A = ReadD( _ACC_ ), B = ReadD( _B_ ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x7B ) ); +WriteD( _ACC_ , ( ( A * B ) & 0x00FF ) ); WriteD( _B_, ( A * B ) / 0x100 ); +if ( ReadD( _B_ ) > 0) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) ); +return 4; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_A5( ) +// Instruction "INVALID" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_A5( ) +{ +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_A6( ) +// Instruction "MOV @R0,direct" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_A6( ) +{ +unsigned char destination = ReadI ( ReadD( BANKPSW + _R0_ ) ); +unsigned char srcaddr = PGMMem->Read8( PC++ ); +unsigned char source = ReadD( srcaddr ); +destination = source; +WriteI( ReadD( BANKPSW + _R0_ ), destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_A7( ) +// Instruction "MOV @R1,direct" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_A7( ) +{ +unsigned char destination = ReadI ( ReadD( BANKPSW + _R1_ ) ); +unsigned char srcaddr = PGMMem->Read8( PC++ ); +unsigned char source = ReadD( srcaddr ); +destination = source; +WriteI( ReadD( BANKPSW + _R1_ ), destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_A8( ) +// Instruction "MOV R0,direct" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_A8( ) +{ +unsigned char destination = ReadD( BANKPSW + _R0_ ); +unsigned char srcaddr = PGMMem->Read8( PC++ ); +unsigned char source = ReadD( srcaddr ); +destination = source; +WriteD( BANKPSW + _R0_, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_A9( ) +// Instruction "MOV R1,direct" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_A9( ) +{ +unsigned char destination = ReadD( BANKPSW + _R1_ ); +unsigned char srcaddr = PGMMem->Read8( PC++ ); +unsigned char source = ReadD( srcaddr ); +destination = source; +WriteD( BANKPSW + _R1_, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_AA( ) +// Instruction "MOV R2,direct" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_AA( ) +{ +unsigned char destination = ReadD( BANKPSW + _R2_ ); +unsigned char srcaddr = PGMMem->Read8( PC++ ); +unsigned char source = ReadD( srcaddr ); +destination = source; +WriteD( BANKPSW + _R2_, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_AB( ) +// Instruction "MOV R3,direct" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_AB( ) +{ +unsigned char destination = ReadD( BANKPSW + _R3_ ); +unsigned char srcaddr = PGMMem->Read8( PC++ ); +unsigned char source = ReadD( srcaddr ); +destination = source; +WriteD( BANKPSW + _R3_, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_AC( ) +// Instruction "MOV R4,direct" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_AC( ) +{ +unsigned char destination = ReadD( BANKPSW + _R4_ ); +unsigned char srcaddr = PGMMem->Read8( PC++ ); +unsigned char source = ReadD( srcaddr ); +destination = source; +WriteD( BANKPSW + _R4_, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_AD( ) +// Instruction "MOV R5,direct" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_AD( ) +{ +unsigned char destination = ReadD( BANKPSW + _R5_ ); +unsigned char srcaddr = PGMMem->Read8( PC++ ); +unsigned char source = ReadD( srcaddr ); +destination = source; +WriteD( BANKPSW + _R5_, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_AE( ) +// Instruction "MOV R6,direct" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_AE( ) +{ +unsigned char destination = ReadD( BANKPSW + _R6_ ); +unsigned char srcaddr = PGMMem->Read8( PC++ ); +unsigned char source = ReadD( srcaddr ); +destination = source; +WriteD( BANKPSW + _R6_, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_AF( ) +// Instruction "MOV R7,direct" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_AF( ) +{ +unsigned char destination = ReadD( BANKPSW + _R7_ ); +unsigned char srcaddr = PGMMem->Read8( PC++ ); +unsigned char source = ReadD( srcaddr ); +destination = source; +WriteD( BANKPSW + _R7_, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_B0( ) +// Instruction "ANL C,/bitaddr" takes 1 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_B0( ) +{ +unsigned char destination = ( ReadD( _PSW_ ) >> 7 ); +unsigned char source, srcbitaddr = PGMMem->Read8( PC++ ); +source = ( ReadB( srcbitaddr ) ^ 1 ); +WriteD( _PSW_, ( ( destination & source) << 7 ) ); +WriteD( _PSW_, ( ( ReadD( _PSW_ ) & 0x7F) | ( destination << 7 ) ) ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_B1( ) +// Instruction "ACALL addr11" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_B1( ) +{ +unsigned int addr11 = ( ( PGMMem->Read8( PC - 1 ) << 3 ) & 0xF00 ) + PGMMem->Read8( PC++ ); +unsigned char SP = ReadD( _SP_ ); +WriteI( ++SP, ( PC & 0x00FF ) ); +WriteI( ++SP, ( PC >> 8 ) ); +WriteD( _SP_, SP ); +PC = ( PC & 0xF800 ) | addr11; +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_B2( ) +// Instruction "CPL bitaddr" takes 1 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_B2( ) +{ +unsigned char destination, dstbitaddr = PGMMem->Read8( PC++ ); +destination = ReadB( dstbitaddr ); +destination ^= 0x01; +WriteB( dstbitaddr, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_B3( ) +// Instruction "CPL C" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_B3( ) +{ +unsigned char destination = ( ReadD( _PSW_ ) >> 7 ); +destination ^= 0x01; +WriteD( _PSW_, ( ( ReadD( _PSW_ ) & 0x7F) | ( destination << 7 ) ) ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_B4( ) +// Instruction "CJNE A,#data,reladdr" takes 2 cycle(s) and 3 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_B4( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = PGMMem->Read8( PC++ ); +unsigned int reladdr = ( ( PGMMem->Read8( PC++ ) + ( ( PC + 1 ) & 0x00FF ) ) & 0x00FF ) + ( ( PC + 1 ) & 0xFF00 ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x7F ) ); +if ( destination < source ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); +if ( destination != source ) PC = reladdr; +WriteD( _ACC_, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_B5( ) +// Instruction "CJNE A,direct,reladdr" takes 2 cycle(s) and 3 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_B5( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char srcaddr = PGMMem->Read8( PC++ ); +unsigned char source = ReadD( srcaddr ); +unsigned int reladdr = ( ( PGMMem->Read8( PC++ ) + ( ( PC + 1 ) & 0x00FF ) ) & 0x00FF ) + ( ( PC + 1 ) & 0xFF00 ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x7F ) ); +if ( destination < source ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); +if ( destination != source ) PC = reladdr; +WriteD( _ACC_, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_B6( ) +// Instruction "CJNE @R0,#data,reladdr" takes 2 cycle(s) and 3 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_B6( ) +{ +unsigned char destination = ReadI ( ReadD( BANKPSW + _R0_ ) ); +unsigned char source = PGMMem->Read8( PC++ ); +unsigned int reladdr = ( ( PGMMem->Read8( PC++ ) + ( ( PC + 1 ) & 0x00FF ) ) & 0x00FF ) + ( ( PC + 1 ) & 0xFF00 ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x7F ) ); +if ( destination < source ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); +if ( destination != source ) PC = reladdr; +WriteI( ReadD( BANKPSW + _R0_ ), destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_B7( ) +// Instruction "CJNE @R1,#data,reladdr" takes 2 cycle(s) and 3 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_B7( ) +{ +unsigned char destination = ReadI ( ReadD( BANKPSW + _R1_ ) ); +unsigned char source = PGMMem->Read8( PC++ ); +unsigned int reladdr = ( ( PGMMem->Read8( PC++ ) + ( ( PC + 1 ) & 0x00FF ) ) & 0x00FF ) + ( ( PC + 1 ) & 0xFF00 ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x7F ) ); +if ( destination < source ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); +if ( destination != source ) PC = reladdr; +WriteI( ReadD( BANKPSW + _R1_ ), destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_B8( ) +// Instruction "CJNE R0,#data,reladdr" takes 2 cycle(s) and 3 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_B8( ) +{ +unsigned char destination = ReadD( BANKPSW + _R0_ ); +unsigned char source = PGMMem->Read8( PC++ ); +unsigned int reladdr = ( ( PGMMem->Read8( PC++ ) + ( ( PC + 1 ) & 0x00FF ) ) & 0x00FF ) + ( ( PC + 1 ) & 0xFF00 ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x7F ) ); +if ( destination < source ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); +if ( destination != source ) PC = reladdr; +WriteD( BANKPSW + _R0_, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_B9( ) +// Instruction "CJNE R1,#data,reladdr" takes 2 cycle(s) and 3 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_B9( ) +{ +unsigned char destination = ReadD( BANKPSW + _R1_ ); +unsigned char source = PGMMem->Read8( PC++ ); +unsigned int reladdr = ( ( PGMMem->Read8( PC++ ) + ( ( PC + 1 ) & 0x00FF ) ) & 0x00FF ) + ( ( PC + 1 ) & 0xFF00 ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x7F ) ); +if ( destination < source ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); +if ( destination != source ) PC = reladdr; +WriteD( BANKPSW + _R1_, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_BA( ) +// Instruction "CJNE R2,#data,reladdr" takes 2 cycle(s) and 3 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_BA( ) +{ +unsigned char destination = ReadD( BANKPSW + _R2_ ); +unsigned char source = PGMMem->Read8( PC++ ); +unsigned int reladdr = ( ( PGMMem->Read8( PC++ ) + ( ( PC + 1 ) & 0x00FF ) ) & 0x00FF ) + ( ( PC + 1 ) & 0xFF00 ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x7F ) ); +if ( destination < source ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); +if ( destination != source ) PC = reladdr; +WriteD( BANKPSW + _R2_, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_BB( ) +// Instruction "CJNE R3,#data,reladdr" takes 2 cycle(s) and 3 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_BB( ) +{ +unsigned char destination = ReadD( BANKPSW + _R3_ ); +unsigned char source = PGMMem->Read8( PC++ ); +unsigned int reladdr = ( ( PGMMem->Read8( PC++ ) + ( ( PC + 1 ) & 0x00FF ) ) & 0x00FF ) + ( ( PC + 1 ) & 0xFF00 ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x7F ) ); +if ( destination < source ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); +if ( destination != source ) PC = reladdr; +WriteD( BANKPSW + _R3_, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_BC( ) +// Instruction "CJNE R4,#data,reladdr" takes 2 cycle(s) and 3 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_BC( ) +{ +unsigned char destination = ReadD( BANKPSW + _R4_ ); +unsigned char source = PGMMem->Read8( PC++ ); +unsigned int reladdr = ( ( PGMMem->Read8( PC++ ) + ( ( PC + 1 ) & 0x00FF ) ) & 0x00FF ) + ( ( PC + 1 ) & 0xFF00 ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x7F ) ); +if ( destination < source ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); +if ( destination != source ) PC = reladdr; +WriteD( BANKPSW + _R4_, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_BD( ) +// Instruction "CJNE R5,#data,reladdr" takes 2 cycle(s) and 3 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_BD( ) +{ +unsigned char destination = ReadD( BANKPSW + _R5_ ); +unsigned char source = PGMMem->Read8( PC++ ); +unsigned int reladdr = ( ( PGMMem->Read8( PC++ ) + ( ( PC + 1 ) & 0x00FF ) ) & 0x00FF ) + ( ( PC + 1 ) & 0xFF00 ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x7F ) ); +if ( destination < source ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); +if ( destination != source ) PC = reladdr; +WriteD( BANKPSW + _R5_, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_BE( ) +// Instruction "CJNE R6,#data,reladdr" takes 2 cycle(s) and 3 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_BE( ) +{ +unsigned char destination = ReadD( BANKPSW + _R6_ ); +unsigned char source = PGMMem->Read8( PC++ ); +unsigned int reladdr = ( ( PGMMem->Read8( PC++ ) + ( ( PC + 1 ) & 0x00FF ) ) & 0x00FF ) + ( ( PC + 1 ) & 0xFF00 ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x7F ) ); +if ( destination < source ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); +if ( destination != source ) PC = reladdr; +WriteD( BANKPSW + _R6_, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_BF( ) +// Instruction "CJNE R7,#data,reladdr" takes 2 cycle(s) and 3 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_BF( ) +{ +unsigned char destination = ReadD( BANKPSW + _R7_ ); +unsigned char source = PGMMem->Read8( PC++ ); +unsigned int reladdr = ( ( PGMMem->Read8( PC++ ) + ( ( PC + 1 ) & 0x00FF ) ) & 0x00FF ) + ( ( PC + 1 ) & 0xFF00 ); +WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x7F ) ); +if ( destination < source ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); +if ( destination != source ) PC = reladdr; +WriteD( BANKPSW + _R7_, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_C0( ) +// Instruction "PUSH direct" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_C0( ) +{ +unsigned char destaddr = PGMMem->Read8( PC++ ); +unsigned char destination = ReadD( destaddr ); +unsigned char SP = ReadD( _SP_ ); +WriteI( ++SP, destination ); +WriteD( _SP_, SP ); +WriteD( destaddr, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_C1( ) +// Instruction "AJMP addr11" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_C1( ) +{ +unsigned int addr11 = ( ( PGMMem->Read8( PC - 1 ) << 3 ) & 0xF00 ) + PGMMem->Read8( PC++ ); +PC = ( PC & 0xF800 ) | addr11; +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_C2( ) +// Instruction "CLR bitaddr" takes 1 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_C2( ) +{ +unsigned char destination, dstbitaddr = PGMMem->Read8( PC++ ); +destination = ReadB( dstbitaddr ); +destination = 0; +WriteB( dstbitaddr, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_C3( ) +// Instruction "CLR C" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_C3( ) +{ +unsigned char destination = ( ReadD( _PSW_ ) >> 7 ); +destination = 0; +WriteD( _PSW_, ( ( ReadD( _PSW_ ) & 0x7F) | ( destination << 7 ) ) ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_C4( ) +// Instruction "SWAP A" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_C4( ) +{ +unsigned char destination = ReadD( _ACC_ ); +destination = ( destination << 4 ) + ( destination >> 4 ); +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_C5( ) +// Instruction "XCH A,direct" takes 1 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_C5( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char srcaddr = PGMMem->Read8( PC++ ); +unsigned char source = ReadD( srcaddr ); +unsigned char tmpval = destination; +destination = source; source = tmpval; +WriteD( _ACC_, destination ); +WriteD( srcaddr, source ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_C6( ) +// Instruction "XCH A,@R0" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_C6( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadI ( ReadD( BANKPSW + _R0_ ) ); +unsigned char tmpval = destination; +destination = source; source = tmpval; +WriteD( _ACC_, destination ); +WriteI( ReadD( BANKPSW + _R0_ ), source ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_C7( ) +// Instruction "XCH A,@R1" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_C7( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadI ( ReadD( BANKPSW + _R1_ ) ); +unsigned char tmpval = destination; +destination = source; source = tmpval; +WriteD( _ACC_, destination ); +WriteI( ReadD( BANKPSW + _R1_ ), source ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_C8( ) +// Instruction "XCH A,R0" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_C8( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R0_ ); +unsigned char tmpval = destination; +destination = source; source = tmpval; +WriteD( _ACC_, destination ); +WriteD( BANKPSW + _R0_, source ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_C9( ) +// Instruction "XCH A,R1" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_C9( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R1_ ); +unsigned char tmpval = destination; +destination = source; source = tmpval; +WriteD( _ACC_, destination ); +WriteD( BANKPSW + _R1_, source ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_CA( ) +// Instruction "XCH A,R2" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_CA( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R2_ ); +unsigned char tmpval = destination; +destination = source; source = tmpval; +WriteD( _ACC_, destination ); +WriteD( BANKPSW + _R2_, source ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_CB( ) +// Instruction "XCH A,R3" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_CB( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R3_ ); +unsigned char tmpval = destination; +destination = source; source = tmpval; +WriteD( _ACC_, destination ); +WriteD( BANKPSW + _R3_, source ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_CC( ) +// Instruction "XCH A,R4" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_CC( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R4_ ); +unsigned char tmpval = destination; +destination = source; source = tmpval; +WriteD( _ACC_, destination ); +WriteD( BANKPSW + _R4_, source ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_CD( ) +// Instruction "XCH A,R5" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_CD( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R5_ ); +unsigned char tmpval = destination; +destination = source; source = tmpval; +WriteD( _ACC_, destination ); +WriteD( BANKPSW + _R5_, source ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_CE( ) +// Instruction "XCH A,R6" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_CE( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R6_ ); +unsigned char tmpval = destination; +destination = source; source = tmpval; +WriteD( _ACC_, destination ); +WriteD( BANKPSW + _R6_, source ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_CF( ) +// Instruction "XCH A,R7" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_CF( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R7_ ); +unsigned char tmpval = destination; +destination = source; source = tmpval; +WriteD( _ACC_, destination ); +WriteD( BANKPSW + _R7_, source ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_D0( ) +// Instruction "POP direct" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_D0( ) +{ +unsigned char destaddr = PGMMem->Read8( PC++ ); +unsigned char destination = ReadD( destaddr ); +unsigned char SP = ReadD( _SP_ ); +destination = ReadI( SP-- ); +WriteD( _SP_, SP ); +WriteD( destaddr, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_D1( ) +// Instruction "ACALL addr11" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_D1( ) +{ +unsigned int addr11 = ( ( PGMMem->Read8( PC - 1 ) << 3 ) & 0xF00 ) + PGMMem->Read8( PC++ ); +unsigned char SP = ReadD( _SP_ ); +WriteI( ++SP, ( PC & 0x00FF ) ); +WriteI( ++SP, ( PC >> 8 ) ); +WriteD( _SP_, SP ); +PC = ( PC & 0xF800 ) | addr11; +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_D2( ) +// Instruction "SETB bitaddr" takes 1 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_D2( ) +{ +unsigned char destination, dstbitaddr = PGMMem->Read8( PC++ ); +destination = ReadB( dstbitaddr ); +destination = 1; +WriteB( dstbitaddr, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_D3( ) +// Instruction "SETB C" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_D3( ) +{ +unsigned char destination = ( ReadD( _PSW_ ) >> 7 ); +destination = 1; +WriteD( _PSW_, ( ( ReadD( _PSW_ ) & 0x7F) | ( destination << 7 ) ) ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_D4( ) +// Instruction "DA A" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_D4( ) +{ +unsigned char destination = ReadD( _ACC_ ); +if ( ( ( destination & 0x0F ) > 9) || ( ReadD( _PSW_ ) | 0x40)) { + if ( ( destination + 6 ) > 0xFF) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); + destination += 6; +} +if ( ( ReadD( _PSW_ ) & 0x80) || ( ( destination & 0xF0 ) > 0x90 ) ) { + if ( ( destination + 0x60 ) > 0xFF ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) ); + destination += 0x60; +} +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_D5( ) +// Instruction "DJNZ direct,reladdr" takes 2 cycle(s) and 3 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_D5( ) +{ +unsigned char destaddr = PGMMem->Read8( PC++ ); +unsigned char destination = ReadD( destaddr ); +PC++; +unsigned int source = ( ( PGMMem->Read8( PC - 1 ) + PC ) & 0xFF ) + ( PC & 0xFF00 ); +destination--; +if ( destination != 0 ) PC = source; +WriteD( destaddr, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_D6( ) +// Instruction "XCHD A,@R0" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_D6( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadI ( ReadD( BANKPSW + _R0_ ) ); +unsigned char tmpval = ( destination & 0x0F ); +destination = ( destination & 0xF0 ) + ( source & 0x0F ); +source = ( source & 0xF0 ) + tmpval; +WriteD( _ACC_, destination ); +WriteI( ReadD( BANKPSW + _R0_ ), source ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_D7( ) +// Instruction "XCHD A,@R1" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_D7( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadI ( ReadD( BANKPSW + _R1_ ) ); +unsigned char tmpval = ( destination & 0x0F ); +destination = ( destination & 0xF0 ) + ( source & 0x0F ); +source = ( source & 0xF0 ) + tmpval; +WriteD( _ACC_, destination ); +WriteI( ReadD( BANKPSW + _R1_ ), source ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_D8( ) +// Instruction "DJNZ R0,reladdr" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_D8( ) +{ +unsigned char destination = ReadD( BANKPSW + _R0_ ); +PC++; +unsigned int source = ( ( PGMMem->Read8( PC - 1 ) + PC ) & 0xFF ) + ( PC & 0xFF00 ); +destination--; +if ( destination != 0 ) PC = source; +WriteD( BANKPSW + _R0_, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_D9( ) +// Instruction "DJNZ R1,reladdr" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_D9( ) +{ +unsigned char destination = ReadD( BANKPSW + _R1_ ); +PC++; +unsigned int source = ( ( PGMMem->Read8( PC - 1 ) + PC ) & 0xFF ) + ( PC & 0xFF00 ); +destination--; +if ( destination != 0 ) PC = source; +WriteD( BANKPSW + _R1_, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_DA( ) +// Instruction "DJNZ R2,reladdr" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_DA( ) +{ +unsigned char destination = ReadD( BANKPSW + _R2_ ); +PC++; +unsigned int source = ( ( PGMMem->Read8( PC - 1 ) + PC ) & 0xFF ) + ( PC & 0xFF00 ); +destination--; +if ( destination != 0 ) PC = source; +WriteD( BANKPSW + _R2_, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_DB( ) +// Instruction "DJNZ R3,reladdr" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_DB( ) +{ +unsigned char destination = ReadD( BANKPSW + _R3_ ); +PC++; +unsigned int source = ( ( PGMMem->Read8( PC - 1 ) + PC ) & 0xFF ) + ( PC & 0xFF00 ); +destination--; +if ( destination != 0 ) PC = source; +WriteD( BANKPSW + _R3_, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_DC( ) +// Instruction "DJNZ R4,reladdr" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_DC( ) +{ +unsigned char destination = ReadD( BANKPSW + _R4_ ); +PC++; +unsigned int source = ( ( PGMMem->Read8( PC - 1 ) + PC ) & 0xFF ) + ( PC & 0xFF00 ); +destination--; +if ( destination != 0 ) PC = source; +WriteD( BANKPSW + _R4_, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_DD( ) +// Instruction "DJNZ R5,reladdr" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_DD( ) +{ +unsigned char destination = ReadD( BANKPSW + _R5_ ); +PC++; +unsigned int source = ( ( PGMMem->Read8( PC - 1 ) + PC ) & 0xFF ) + ( PC & 0xFF00 ); +destination--; +if ( destination != 0 ) PC = source; +WriteD( BANKPSW + _R5_, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_DE( ) +// Instruction "DJNZ R6,reladdr" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_DE( ) +{ +unsigned char destination = ReadD( BANKPSW + _R6_ ); +PC++; +unsigned int source = ( ( PGMMem->Read8( PC - 1 ) + PC ) & 0xFF ) + ( PC & 0xFF00 ); +destination--; +if ( destination != 0 ) PC = source; +WriteD( BANKPSW + _R6_, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_DF( ) +// Instruction "DJNZ R7,reladdr" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_DF( ) +{ +unsigned char destination = ReadD( BANKPSW + _R7_ ); +PC++; +unsigned int source = ( ( PGMMem->Read8( PC - 1 ) + PC ) & 0xFF ) + ( PC & 0xFF00 ); +destination--; +if ( destination != 0 ) PC = source; +WriteD( BANKPSW + _R7_, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_E0( ) +// Instruction "MOVX A,@DPTR" takes 2 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_E0( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadI( ( ReadD( _DPTRHIGH_ ) << 8 ) + ReadD( _DPTRLOW_) ); +destination = source; +WriteD( _ACC_, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_E1( ) +// Instruction "AJMP addr11" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_E1( ) +{ +unsigned int addr11 = ( ( PGMMem->Read8( PC - 1 ) << 3 ) & 0xF00 ) + PGMMem->Read8( PC++ ); +PC = ( PC & 0xF800 ) | addr11; +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_E2( ) +// Instruction "MOVX A,@R0" takes 2 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_E2( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadI ( ReadD( BANKPSW + _R0_ ) ); +destination = source; +WriteD( _ACC_, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_E3( ) +// Instruction "MOVX A,@R1" takes 2 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_E3( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadI ( ReadD( BANKPSW + _R1_ ) ); +destination = source; +WriteD( _ACC_, destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_E4( ) +// Instruction "CLR A" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_E4( ) +{ +unsigned char destination = ReadD( _ACC_ ); +destination = 0; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_E5( ) +// Instruction "MOV A,direct" takes 1 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_E5( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char srcaddr = PGMMem->Read8( PC++ ); +unsigned char source = ReadD( srcaddr ); +destination = source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_E6( ) +// Instruction "MOV A,@R0" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_E6( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadI ( ReadD( BANKPSW + _R0_ ) ); +destination = source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_E7( ) +// Instruction "MOV A,@R1" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_E7( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadI ( ReadD( BANKPSW + _R1_ ) ); +destination = source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_E8( ) +// Instruction "MOV A,R0" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_E8( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R0_ ); +destination = source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_E9( ) +// Instruction "MOV A,R1" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_E9( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R1_ ); +destination = source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_EA( ) +// Instruction "MOV A,R2" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_EA( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R2_ ); +destination = source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_EB( ) +// Instruction "MOV A,R3" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_EB( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R3_ ); +destination = source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_EC( ) +// Instruction "MOV A,R4" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_EC( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R4_ ); +destination = source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_ED( ) +// Instruction "MOV A,R5" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_ED( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R5_ ); +destination = source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_EE( ) +// Instruction "MOV A,R6" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_EE( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R6_ ); +destination = source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_EF( ) +// Instruction "MOV A,R7" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_EF( ) +{ +unsigned char destination = ReadD( _ACC_ ); +unsigned char source = ReadD( BANKPSW + _R7_ ); +destination = source; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_F0( ) +// Instruction "MOVX @DPTR,A" takes 2 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_F0( ) +{ +unsigned char destination = ReadI( ( ReadD( _DPTRHIGH_ ) << 8 ) + ReadD( _DPTRLOW_) ); +unsigned char source = ReadD( _ACC_ ); +destination = source; +WriteI( ( ReadD( _DPTRHIGH_ ) << 8 ) + ReadD( _DPTRLOW_ ), destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_F1( ) +// Instruction "ACALL addr11" takes 2 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_F1( ) +{ +unsigned int addr11 = ( ( PGMMem->Read8( PC - 1 ) << 3 ) & 0xF00 ) + PGMMem->Read8( PC++ ); +unsigned char SP = ReadD( _SP_ ); +WriteI( ++SP, ( PC & 0x00FF ) ); +WriteI( ++SP, ( PC >> 8 ) ); +WriteD( _SP_, SP ); +PC = ( PC & 0xF800 ) | addr11; +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_F2( ) +// Instruction "MOVX @R0,A" takes 2 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_F2( ) +{ +unsigned char destination = ReadI ( ReadD( BANKPSW + _R0_ ) ); +unsigned char source = ReadD( _ACC_ ); +destination = source; +WriteI( ReadD( BANKPSW + _R0_ ), destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_F3( ) +// Instruction "MOVX @R1,A" takes 2 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_F3( ) +{ +unsigned char destination = ReadI ( ReadD( BANKPSW + _R1_ ) ); +unsigned char source = ReadD( _ACC_ ); +destination = source; +WriteI( ReadD( BANKPSW + _R1_ ), destination ); +return 2; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_F4( ) +// Instruction "CPL A" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_F4( ) +{ +unsigned char destination = ReadD( _ACC_ ); +destination ^= 0xFF; +WriteD( _ACC_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_F5( ) +// Instruction "MOV direct,A" takes 1 cycle(s) and 2 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_F5( ) +{ +unsigned char destaddr = PGMMem->Read8( PC++ ); +unsigned char destination = ReadD( destaddr ); +unsigned char source = ReadD( _ACC_ ); +destination = source; +WriteD( destaddr, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_F6( ) +// Instruction "MOV @R0,A" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_F6( ) +{ +unsigned char destination = ReadI ( ReadD( BANKPSW + _R0_ ) ); +unsigned char source = ReadD( _ACC_ ); +destination = source; +WriteI( ReadD( BANKPSW + _R0_ ), destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_F7( ) +// Instruction "MOV @R1,A" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_F7( ) +{ +unsigned char destination = ReadI ( ReadD( BANKPSW + _R1_ ) ); +unsigned char source = ReadD( _ACC_ ); +destination = source; +WriteI( ReadD( BANKPSW + _R1_ ), destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_F8( ) +// Instruction "MOV R0,A" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_F8( ) +{ +unsigned char destination = ReadD( BANKPSW + _R0_ ); +unsigned char source = ReadD( _ACC_ ); +destination = source; +WriteD( BANKPSW + _R0_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_F9( ) +// Instruction "MOV R1,A" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_F9( ) +{ +unsigned char destination = ReadD( BANKPSW + _R1_ ); +unsigned char source = ReadD( _ACC_ ); +destination = source; +WriteD( BANKPSW + _R1_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_FA( ) +// Instruction "MOV R2,A" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_FA( ) +{ +unsigned char destination = ReadD( BANKPSW + _R2_ ); +unsigned char source = ReadD( _ACC_ ); +destination = source; +WriteD( BANKPSW + _R2_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_FB( ) +// Instruction "MOV R3,A" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_FB( ) +{ +unsigned char destination = ReadD( BANKPSW + _R3_ ); +unsigned char source = ReadD( _ACC_ ); +destination = source; +WriteD( BANKPSW + _R3_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_FC( ) +// Instruction "MOV R4,A" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_FC( ) +{ +unsigned char destination = ReadD( BANKPSW + _R4_ ); +unsigned char source = ReadD( _ACC_ ); +destination = source; +WriteD( BANKPSW + _R4_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_FD( ) +// Instruction "MOV R5,A" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_FD( ) +{ +unsigned char destination = ReadD( BANKPSW + _R5_ ); +unsigned char source = ReadD( _ACC_ ); +destination = source; +WriteD( BANKPSW + _R5_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_FE( ) +// Instruction "MOV R6,A" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_FE( ) +{ +unsigned char destination = ReadD( BANKPSW + _R6_ ); +unsigned char source = ReadD( _ACC_ ); +destination = source; +WriteD( BANKPSW + _R6_, destination ); +return 1; +} + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::OP_FF( ) +// Instruction "MOV R7,A" takes 1 cycle(s) and 1 byte(s) +////////////////////////////////////////////////////////////////////////////// +int CPU8051::OP_FF( ) +{ +unsigned char destination = ReadD( BANKPSW + _R7_ ); +unsigned char source = ReadD( _ACC_ ); +destination = source; +WriteD( BANKPSW + _R7_, destination ); +return 1; +} + + + + +////////////////////////////////////////////////////////////////////////////// +// void CPU8051::InitFuncPtr( ) +// Initialize Functions Pointers +////////////////////////////////////////////////////////////////////////////// +void CPU8051::InitFuncPtr( ) +{ + funcptr[0]=&CPU8051::OP_00; + funcptr[1]=&CPU8051::OP_01; + funcptr[2]=&CPU8051::OP_02; + funcptr[3]=&CPU8051::OP_03; + funcptr[4]=&CPU8051::OP_04; + funcptr[5]=&CPU8051::OP_05; + funcptr[6]=&CPU8051::OP_06; + funcptr[7]=&CPU8051::OP_07; + funcptr[8]=&CPU8051::OP_08; + funcptr[9]=&CPU8051::OP_09; + funcptr[10]=&CPU8051::OP_0A; + funcptr[11]=&CPU8051::OP_0B; + funcptr[12]=&CPU8051::OP_0C; + funcptr[13]=&CPU8051::OP_0D; + funcptr[14]=&CPU8051::OP_0E; + funcptr[15]=&CPU8051::OP_0F; + funcptr[16]=&CPU8051::OP_10; + funcptr[17]=&CPU8051::OP_11; + funcptr[18]=&CPU8051::OP_12; + funcptr[19]=&CPU8051::OP_13; + funcptr[20]=&CPU8051::OP_14; + funcptr[21]=&CPU8051::OP_15; + funcptr[22]=&CPU8051::OP_16; + funcptr[23]=&CPU8051::OP_17; + funcptr[24]=&CPU8051::OP_18; + funcptr[25]=&CPU8051::OP_19; + funcptr[26]=&CPU8051::OP_1A; + funcptr[27]=&CPU8051::OP_1B; + funcptr[28]=&CPU8051::OP_1C; + funcptr[29]=&CPU8051::OP_1D; + funcptr[30]=&CPU8051::OP_1E; + funcptr[31]=&CPU8051::OP_1F; + funcptr[32]=&CPU8051::OP_20; + funcptr[33]=&CPU8051::OP_21; + funcptr[34]=&CPU8051::OP_22; + funcptr[35]=&CPU8051::OP_23; + funcptr[36]=&CPU8051::OP_24; + funcptr[37]=&CPU8051::OP_25; + funcptr[38]=&CPU8051::OP_26; + funcptr[39]=&CPU8051::OP_27; + funcptr[40]=&CPU8051::OP_28; + funcptr[41]=&CPU8051::OP_29; + funcptr[42]=&CPU8051::OP_2A; + funcptr[43]=&CPU8051::OP_2B; + funcptr[44]=&CPU8051::OP_2C; + funcptr[45]=&CPU8051::OP_2D; + funcptr[46]=&CPU8051::OP_2E; + funcptr[47]=&CPU8051::OP_2F; + funcptr[48]=&CPU8051::OP_30; + funcptr[49]=&CPU8051::OP_31; + funcptr[50]=&CPU8051::OP_32; + funcptr[51]=&CPU8051::OP_33; + funcptr[52]=&CPU8051::OP_34; + funcptr[53]=&CPU8051::OP_35; + funcptr[54]=&CPU8051::OP_36; + funcptr[55]=&CPU8051::OP_37; + funcptr[56]=&CPU8051::OP_38; + funcptr[57]=&CPU8051::OP_39; + funcptr[58]=&CPU8051::OP_3A; + funcptr[59]=&CPU8051::OP_3B; + funcptr[60]=&CPU8051::OP_3C; + funcptr[61]=&CPU8051::OP_3D; + funcptr[62]=&CPU8051::OP_3E; + funcptr[63]=&CPU8051::OP_3F; + funcptr[64]=&CPU8051::OP_40; + funcptr[65]=&CPU8051::OP_41; + funcptr[66]=&CPU8051::OP_42; + funcptr[67]=&CPU8051::OP_43; + funcptr[68]=&CPU8051::OP_44; + funcptr[69]=&CPU8051::OP_45; + funcptr[70]=&CPU8051::OP_46; + funcptr[71]=&CPU8051::OP_47; + funcptr[72]=&CPU8051::OP_48; + funcptr[73]=&CPU8051::OP_49; + funcptr[74]=&CPU8051::OP_4A; + funcptr[75]=&CPU8051::OP_4B; + funcptr[76]=&CPU8051::OP_4C; + funcptr[77]=&CPU8051::OP_4D; + funcptr[78]=&CPU8051::OP_4E; + funcptr[79]=&CPU8051::OP_4F; + funcptr[80]=&CPU8051::OP_50; + funcptr[81]=&CPU8051::OP_51; + funcptr[82]=&CPU8051::OP_52; + funcptr[83]=&CPU8051::OP_53; + funcptr[84]=&CPU8051::OP_54; + funcptr[85]=&CPU8051::OP_55; + funcptr[86]=&CPU8051::OP_56; + funcptr[87]=&CPU8051::OP_57; + funcptr[88]=&CPU8051::OP_58; + funcptr[89]=&CPU8051::OP_59; + funcptr[90]=&CPU8051::OP_5A; + funcptr[91]=&CPU8051::OP_5B; + funcptr[92]=&CPU8051::OP_5C; + funcptr[93]=&CPU8051::OP_5D; + funcptr[94]=&CPU8051::OP_5E; + funcptr[95]=&CPU8051::OP_5F; + funcptr[96]=&CPU8051::OP_60; + funcptr[97]=&CPU8051::OP_61; + funcptr[98]=&CPU8051::OP_62; + funcptr[99]=&CPU8051::OP_63; + funcptr[100]=&CPU8051::OP_64; + funcptr[101]=&CPU8051::OP_65; + funcptr[102]=&CPU8051::OP_66; + funcptr[103]=&CPU8051::OP_67; + funcptr[104]=&CPU8051::OP_68; + funcptr[105]=&CPU8051::OP_69; + funcptr[106]=&CPU8051::OP_6A; + funcptr[107]=&CPU8051::OP_6B; + funcptr[108]=&CPU8051::OP_6C; + funcptr[109]=&CPU8051::OP_6D; + funcptr[110]=&CPU8051::OP_6E; + funcptr[111]=&CPU8051::OP_6F; + funcptr[112]=&CPU8051::OP_70; + funcptr[113]=&CPU8051::OP_71; + funcptr[114]=&CPU8051::OP_72; + funcptr[115]=&CPU8051::OP_73; + funcptr[116]=&CPU8051::OP_74; + funcptr[117]=&CPU8051::OP_75; + funcptr[118]=&CPU8051::OP_76; + funcptr[119]=&CPU8051::OP_77; + funcptr[120]=&CPU8051::OP_78; + funcptr[121]=&CPU8051::OP_79; + funcptr[122]=&CPU8051::OP_7A; + funcptr[123]=&CPU8051::OP_7B; + funcptr[124]=&CPU8051::OP_7C; + funcptr[125]=&CPU8051::OP_7D; + funcptr[126]=&CPU8051::OP_7E; + funcptr[127]=&CPU8051::OP_7F; + funcptr[128]=&CPU8051::OP_80; + funcptr[129]=&CPU8051::OP_81; + funcptr[130]=&CPU8051::OP_82; + funcptr[131]=&CPU8051::OP_83; + funcptr[132]=&CPU8051::OP_84; + funcptr[133]=&CPU8051::OP_85; + funcptr[134]=&CPU8051::OP_86; + funcptr[135]=&CPU8051::OP_87; + funcptr[136]=&CPU8051::OP_88; + funcptr[137]=&CPU8051::OP_89; + funcptr[138]=&CPU8051::OP_8A; + funcptr[139]=&CPU8051::OP_8B; + funcptr[140]=&CPU8051::OP_8C; + funcptr[141]=&CPU8051::OP_8D; + funcptr[142]=&CPU8051::OP_8E; + funcptr[143]=&CPU8051::OP_8F; + funcptr[144]=&CPU8051::OP_90; + funcptr[145]=&CPU8051::OP_91; + funcptr[146]=&CPU8051::OP_92; + funcptr[147]=&CPU8051::OP_93; + funcptr[148]=&CPU8051::OP_94; + funcptr[149]=&CPU8051::OP_95; + funcptr[150]=&CPU8051::OP_96; + funcptr[151]=&CPU8051::OP_97; + funcptr[152]=&CPU8051::OP_98; + funcptr[153]=&CPU8051::OP_99; + funcptr[154]=&CPU8051::OP_9A; + funcptr[155]=&CPU8051::OP_9B; + funcptr[156]=&CPU8051::OP_9C; + funcptr[157]=&CPU8051::OP_9D; + funcptr[158]=&CPU8051::OP_9E; + funcptr[159]=&CPU8051::OP_9F; + funcptr[160]=&CPU8051::OP_A0; + funcptr[161]=&CPU8051::OP_A1; + funcptr[162]=&CPU8051::OP_A2; + funcptr[163]=&CPU8051::OP_A3; + funcptr[164]=&CPU8051::OP_A4; + funcptr[165]=&CPU8051::OP_A5; + funcptr[166]=&CPU8051::OP_A6; + funcptr[167]=&CPU8051::OP_A7; + funcptr[168]=&CPU8051::OP_A8; + funcptr[169]=&CPU8051::OP_A9; + funcptr[170]=&CPU8051::OP_AA; + funcptr[171]=&CPU8051::OP_AB; + funcptr[172]=&CPU8051::OP_AC; + funcptr[173]=&CPU8051::OP_AD; + funcptr[174]=&CPU8051::OP_AE; + funcptr[175]=&CPU8051::OP_AF; + funcptr[176]=&CPU8051::OP_B0; + funcptr[177]=&CPU8051::OP_B1; + funcptr[178]=&CPU8051::OP_B2; + funcptr[179]=&CPU8051::OP_B3; + funcptr[180]=&CPU8051::OP_B4; + funcptr[181]=&CPU8051::OP_B5; + funcptr[182]=&CPU8051::OP_B6; + funcptr[183]=&CPU8051::OP_B7; + funcptr[184]=&CPU8051::OP_B8; + funcptr[185]=&CPU8051::OP_B9; + funcptr[186]=&CPU8051::OP_BA; + funcptr[187]=&CPU8051::OP_BB; + funcptr[188]=&CPU8051::OP_BC; + funcptr[189]=&CPU8051::OP_BD; + funcptr[190]=&CPU8051::OP_BE; + funcptr[191]=&CPU8051::OP_BF; + funcptr[192]=&CPU8051::OP_C0; + funcptr[193]=&CPU8051::OP_C1; + funcptr[194]=&CPU8051::OP_C2; + funcptr[195]=&CPU8051::OP_C3; + funcptr[196]=&CPU8051::OP_C4; + funcptr[197]=&CPU8051::OP_C5; + funcptr[198]=&CPU8051::OP_C6; + funcptr[199]=&CPU8051::OP_C7; + funcptr[200]=&CPU8051::OP_C8; + funcptr[201]=&CPU8051::OP_C9; + funcptr[202]=&CPU8051::OP_CA; + funcptr[203]=&CPU8051::OP_CB; + funcptr[204]=&CPU8051::OP_CC; + funcptr[205]=&CPU8051::OP_CD; + funcptr[206]=&CPU8051::OP_CE; + funcptr[207]=&CPU8051::OP_CF; + funcptr[208]=&CPU8051::OP_D0; + funcptr[209]=&CPU8051::OP_D1; + funcptr[210]=&CPU8051::OP_D2; + funcptr[211]=&CPU8051::OP_D3; + funcptr[212]=&CPU8051::OP_D4; + funcptr[213]=&CPU8051::OP_D5; + funcptr[214]=&CPU8051::OP_D6; + funcptr[215]=&CPU8051::OP_D7; + funcptr[216]=&CPU8051::OP_D8; + funcptr[217]=&CPU8051::OP_D9; + funcptr[218]=&CPU8051::OP_DA; + funcptr[219]=&CPU8051::OP_DB; + funcptr[220]=&CPU8051::OP_DC; + funcptr[221]=&CPU8051::OP_DD; + funcptr[222]=&CPU8051::OP_DE; + funcptr[223]=&CPU8051::OP_DF; + funcptr[224]=&CPU8051::OP_E0; + funcptr[225]=&CPU8051::OP_E1; + funcptr[226]=&CPU8051::OP_E2; + funcptr[227]=&CPU8051::OP_E3; + funcptr[228]=&CPU8051::OP_E4; + funcptr[229]=&CPU8051::OP_E5; + funcptr[230]=&CPU8051::OP_E6; + funcptr[231]=&CPU8051::OP_E7; + funcptr[232]=&CPU8051::OP_E8; + funcptr[233]=&CPU8051::OP_E9; + funcptr[234]=&CPU8051::OP_EA; + funcptr[235]=&CPU8051::OP_EB; + funcptr[236]=&CPU8051::OP_EC; + funcptr[237]=&CPU8051::OP_ED; + funcptr[238]=&CPU8051::OP_EE; + funcptr[239]=&CPU8051::OP_EF; + funcptr[240]=&CPU8051::OP_F0; + funcptr[241]=&CPU8051::OP_F1; + funcptr[242]=&CPU8051::OP_F2; + funcptr[243]=&CPU8051::OP_F3; + funcptr[244]=&CPU8051::OP_F4; + funcptr[245]=&CPU8051::OP_F5; + funcptr[246]=&CPU8051::OP_F6; + funcptr[247]=&CPU8051::OP_F7; + funcptr[248]=&CPU8051::OP_F8; + funcptr[249]=&CPU8051::OP_F9; + funcptr[250]=&CPU8051::OP_FA; + funcptr[251]=&CPU8051::OP_FB; + funcptr[252]=&CPU8051::OP_FC; + funcptr[253]=&CPU8051::OP_FD; + funcptr[254]=&CPU8051::OP_FE; + funcptr[255]=&CPU8051::OP_FF; + +} + + +#endif diff --git a/src/Keyboard.hpp b/src/Keyboard.hpp new file mode 100644 index 0000000..35b0f14 --- /dev/null +++ b/src/Keyboard.hpp @@ -0,0 +1,59 @@ +// Keyboard.hpp + +#ifndef _KEYBOARD_HPP_ +#define _KEYBOARD_HPP_ + +#include +#include + +static struct termios orig, newtio; +static int peek = -1; + +int kbhit() +{ + char ch; + int nread; + if(peek != -1) return 1; + newtio.c_cc[VMIN]=0; + tcsetattr(0, TCSANOW, &newtio); + nread = read(0,&ch,1); + newtio.c_cc[VMIN]=1; + tcsetattr(0, TCSANOW, &newtio); + if(nread == 1) { + peek = ch; + return 1; + } + return 0; +} + +int getch() +{ + char ch; + if(peek != -1) { + ch = peek; + peek = -1; + return ch; + } + read(0,&ch,1); + return ch; +} + +void InitUnixKB( ) +{ + tcgetattr(0, &orig); + newtio = orig; + newtio.c_lflag &= ~ICANON; + newtio.c_lflag &= ~ECHO; + newtio.c_lflag &= ~ISIG; + newtio.c_cc[VMIN] = 1; + newtio.c_cc[VTIME] = 0; + tcsetattr(0, TCSANOW, &newtio); +} + +void ResetUnixKB( ) +{ + tcsetattr(0,TCSANOW, &orig); +} + +#endif + diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..f17fac9 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,37 @@ +# This file is processed by GNU automake to generate Makefile.in + +INCLUDES = -I$(top_srcdir)/pixmaps + +bin_PROGRAMS = emu8051 emu8051_console + +emu8051_SOURCES = EmuGtk.hpp EmuGtk.cpp CPU8051.hpp CPU8051.cpp Memory.hpp Memory.cpp \ + MemWin.hpp MemWin.cpp PgmWin.hpp PgmWin.cpp RegWin.hpp RegWin.cpp + +emu8051_console_SOURCES = EmuConsole.hpp EmuConsole.cpp CPU8051.hpp CPU8051.cpp Memory.hpp \ + Memory.cpp Keyboard.hpp + +# These headers will be included in the distribution tarball, but will not be +# installed by 'make install' +noinst_HEADERS = Inst_Def.hpp EmuConsole.hpp Keyboard.hpp Reg8051.hpp GtkSizes.hpp disasm.hpp \ + exceptions.hpp + +CLEANFILES = *~ + +DISTCLEANFILES = .deps/*.P + +MAINTAINERCLEANFILES = Makefile.in + +EXTRA_DIST = Opcode2cpp.pl opcodes.lst Inst_Imp.cpp + +# This rule is used to bypass the default rule which is generated by Automake, in order +# to get rid of all the cluttered informations that are displayed by Make before +# calling the compiler like in the following example: +# source='programming.c' object='programming.o' libtool=no \ +# depfile='.deps/programming.Po' tmpdepfile='.deps/programming.TPo' \ +# depmode=gcc3 /bin/sh ../config/depcomp \ +# gcc -DHAVE_CONFIG_H -I. -I. -I.. -c `test -f 'main.c' || echo './'`main.c +.c.o: + $(COMPILE) -c $< + +.cpp.o: + $(CXXCOMPILE) -c $< diff --git a/src/MemWin.cpp b/src/MemWin.cpp new file mode 100644 index 0000000..26bd464 --- /dev/null +++ b/src/MemWin.cpp @@ -0,0 +1,128 @@ +/* memwin.cpp */ + + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include "MemWin.hpp" +#include + + +////////////////////////////////////////////////////////////////////////////// +// MemWin::MemWin( GtkWidget *parentwin ) +// MemWin constructor +////////////////////////////////////////////////////////////////////////////// +MemWin::MemWin( GtkWidget *parentwin ) +{ + int i; + GtkStyle *style; + GdkFont *fixedfont; + fixedfont = gdk_font_load( "-adobe-courier-medium-r-normal--12-120-75-75-m-70-iso8859-1" ); + + memclist = gtk_clist_new( 18 ); + gtk_clist_set_selection_mode( GTK_CLIST( memclist ), GTK_SELECTION_SINGLE ); + gtk_widget_set_usize( GTK_WIDGET( memclist ), 620, 250 ); + + for ( i = 0; i < 18; i++ ) gtk_clist_set_column_justification( GTK_CLIST( memclist ), i, GTK_JUSTIFY_LEFT ); + gtk_clist_set_column_width( GTK_CLIST( memclist ), 0, 5*8 ); + for ( i = 1; i < 17; i++ ) gtk_clist_set_column_width( GTK_CLIST( memclist ), i, 2*8 ); + gtk_clist_set_column_width( GTK_CLIST( memclist ), 17, 16*8 ); + + style = gtk_widget_get_style( GTK_WIDGET( memclist ) ); + +#ifdef USE_GTK2 + gtk_style_set_font( style, fixedfont ); +#else + style->font = fixedfont; +#endif + + gtk_widget_set_style( GTK_WIDGET( memclist ), style ); + + char *memdummy[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; + for ( i = 0; i < 16; i++ ) gtk_clist_append( GTK_CLIST( memclist ), memdummy ); + + gtk_container_add( GTK_CONTAINER( parentwin ), memclist ); + + gtk_widget_show( memclist ); +} + + +////////////////////////////////////////////////////////////////////////////// +// MemWin::~MemWin( ) +// MemWin destructor +////////////////////////////////////////////////////////////////////////////// +MemWin::~MemWin( ) +{ + +} + +////////////////////////////////////////////////////////////////////////////// +// void MemWin::DumpD( CPU8051 *mCPU, unsigned int Address ) +// Dump 16 rows of 16 bytes from Address in Memory (direct addressing) +////////////////////////////////////////////////////////////////////////////// +void MemWin::DumpD( CPU8051 *mCPU, unsigned int Address) +{ +char TextTmp[255]; +int row, column, TextLength; + +gtk_clist_freeze( GTK_CLIST( memclist ) ); + for ( row = 0; row < 16; row++ ) { + sprintf( TextTmp, "%.4X", Address ); + gtk_clist_set_text( GTK_CLIST( memclist ), row, 0, TextTmp ); + + for ( column = 0; column < 16; column++ ) { + sprintf( TextTmp, "%.2X", ( int ) mCPU->ReadD( Address + column ) ); + gtk_clist_set_text( GTK_CLIST( memclist ), row, column + 1, TextTmp ); + } + + TextLength = 0; + for ( column = 0; column < 16; column++ ) { + if ( ( ( int ) mCPU->ReadD( Address + column ) >= 32 ) && ( ( int ) mCPU->ReadD( Address + column ) <= 126 ) ) + TextLength += sprintf( &TextTmp[ TextLength ], "%c", mCPU->ReadD( Address + column ) ); + else TextLength += sprintf( &TextTmp[ TextLength ], "." ); + } + gtk_clist_set_text( GTK_CLIST( memclist ), row, 17, TextTmp ); + + Address += 16; + } + +gtk_clist_select_row( GTK_CLIST( memclist ), 0, 0 ); +gtk_clist_thaw( GTK_CLIST( memclist ) ); +} + +////////////////////////////////////////////////////////////////////////////// +// void MemWin::DumpI( CPU8051 *mCPU, unsigned int Address ) +// Dump 16 rows of 16 bytes from Address in Memory (indirect addressing) +////////////////////////////////////////////////////////////////////////////// +void MemWin::DumpI( CPU8051 *mCPU, unsigned int Address) +{ +char TextTmp[255]; +int row, column, TextLength; + +gtk_clist_freeze( GTK_CLIST( memclist ) ); + for ( row = 0; row < 16; row++ ) { + sprintf( TextTmp, "%.4X", Address ); + gtk_clist_set_text( GTK_CLIST( memclist ), row, 0, TextTmp ); + + for ( column = 0; column < 16; column++ ) { + sprintf( TextTmp, "%.2X", ( int ) mCPU->ReadI( Address + column ) ); + gtk_clist_set_text( GTK_CLIST( memclist ), row, column + 1, TextTmp ); + } + + TextLength = 0; + for ( column = 0; column < 16; column++ ) { + if ( ( ( int ) mCPU->ReadI( Address + column ) >= 32 ) && ( ( int ) mCPU->ReadI( Address + column ) <= 126 ) ) + TextLength += sprintf( &TextTmp[ TextLength ], "%c", mCPU->ReadI( Address + column ) ); + else TextLength += sprintf( &TextTmp[ TextLength ], "." ); + } + gtk_clist_set_text( GTK_CLIST( memclist ), row, 17, TextTmp ); + + Address += 16; + } +gtk_clist_thaw( GTK_CLIST( memclist ) ); +} + + + + diff --git a/src/MemWin.hpp b/src/MemWin.hpp new file mode 100644 index 0000000..0a610d0 --- /dev/null +++ b/src/MemWin.hpp @@ -0,0 +1,29 @@ +#ifndef _MEMWIN_HPP_ +#define _MEMWIN_HPP_ + +#include +#include "CPU8051.hpp" + +////////////////////////////////////////////////////////////////////////////// +// MemWin +// Implements a memory Window in Gtk+ as an Object +////////////////////////////////////////////////////////////////////////////// +class MemWin { +public: + MemWin( GtkWidget *parentwin ); + ~MemWin( ); + + void DumpD( CPU8051 *mCPU, unsigned int Address ); + void DumpI( CPU8051 *mCPU, unsigned int Address ); + +private: + GtkWidget *memwin; + GtkWidget *memclist; + + +}; + + + + +#endif diff --git a/src/Memory.cpp b/src/Memory.cpp new file mode 100644 index 0000000..8570264 --- /dev/null +++ b/src/Memory.cpp @@ -0,0 +1,51 @@ +#include "Memory.hpp" + +////////////////////////////////////////////////////////////////////////////// +// Memory::Memory( unsigned long MemSize ) +// Memory object constructor +////////////////////////////////////////////////////////////////////////////// +Memory::Memory( unsigned long MemSize ) +{ + memsize = MemSize; + memarray = new unsigned char[memsize]; +} + +////////////////////////////////////////////////////////////////////////////// +// Memory::~Memory( ) +// Memory object destructor +////////////////////////////////////////////////////////////////////////////// +Memory::~Memory( ) +{ + delete[] memarray; + memarray = 0; + memsize = 0; +} + +////////////////////////////////////////////////////////////////////////////// +// unsigned long Memory::GetSize( ) +// Get Memory size +////////////////////////////////////////////////////////////////////////////// +unsigned long Memory::GetSize( ) +{ + return memsize; +} + +////////////////////////////////////////////////////////////////////////////// +// void Memory::Write8( unsigned long Address, unsigned char Value ) +// Write 8-bit Value at Address into Memory +////////////////////////////////////////////////////////////////////////////// +void Memory::Write8( unsigned long Address, unsigned char Value ) +{ + if (Address >= memsize) return; + memarray[Address] = Value; +} + +////////////////////////////////////////////////////////////////////////////// +// unsigned char Memory::Read8( unsigned long Address ) +// Read 8-bit value at Address in Memory +////////////////////////////////////////////////////////////////////////////// +unsigned char Memory::Read8( unsigned long Address ) +{ + if (Address < memsize) { return memarray[Address]; } + return 0; +} diff --git a/src/Memory.hpp b/src/Memory.hpp new file mode 100644 index 0000000..a4aaba8 --- /dev/null +++ b/src/Memory.hpp @@ -0,0 +1,24 @@ +#ifndef _MEMORY_HPP_ +#define _MEMORY_HPP_ + + +////////////////////////////////////////////////////////////////////////////// +// Memory +// Implements a Memory array to be used by the CPU8051 as an Object +////////////////////////////////////////////////////////////////////////////// +class Memory { +public: + Memory( unsigned long MemSize ); + ~Memory( ); + + unsigned long GetSize( ); + + void Write8( unsigned long Address, unsigned char Value ); + unsigned char Read8( unsigned long Address ); + + unsigned char *memarray; + unsigned long memsize; +}; + + +#endif diff --git a/src/Opcode2cpp.pl b/src/Opcode2cpp.pl new file mode 100755 index 0000000..66ab1c2 --- /dev/null +++ b/src/Opcode2cpp.pl @@ -0,0 +1,785 @@ +#!/usr/bin/perl + +open INST_DEF,">Inst_Def.hpp" or die "Erreur ouverture Inst_Def.hpp : $!\n"; +open INST_IMP,">Inst_Imp.cpp" or die "Erreur ouverture Inst_Imp.hpp : $!\n"; +open OPCODELST,"opcodes.lst" or die "Erreur ouverture opcodes.lst : $!\n"; +open DISASM_HPP,">disasm.hpp" or die "Erreur ouverture disasm.hpp : $!\n"; + +print INST_IMP "#ifndef __INST_IMP_HPP_\n"; +print INST_IMP "#define __INST_IMP_HPP_\n\n"; +print INST_IMP "// Do not modify this file directly, it was created by Opcode2cpp.pl\n"; +print INST_IMP "// Any modification made directly on this file will be lost\n\n\n"; + + +print INST_DEF "#ifndef __INST_DEF_HPP_\n"; +print INST_DEF "#define __INST_DEF_HPP_\n"; +print INST_DEF "// Do not modify this file directly, it was created by Opcode2cpp.pl\n"; +print INST_DEF "// Any modification made directly on this file will be lost\n\n\n"; + +print DISASM_HPP "#ifndef __DISASM_HPP_\n"; +print DISASM_HPP "#define __DISASM_HPP_\n"; +print DISASM_HPP "// Do not modify this file directly, it was created by Opcode2cpp.pl\n"; +print DISASM_HPP "// Any modification made directly on this file will be lost\n\n\n"; + +$nbinst=0; +$nbaddr=0; +$nbargs=0; +$instnumb=0; + +$ligne=; +$ligne=; +while($ligne=) { + chop $ligne; + if (length $ligne < 2) {next;} + @wordlist=split ' ',$ligne; + $nbword=@wordlist; + $instruction=$wordlist[2]; + for($i=3;$i<($nbword-2);$i++) {$instruction="$instruction $wordlist[$i]";} + + $a_instruction[$instnumb]=$instruction; + $a_bytes[$instnumb]=$wordlist[$nbword-2]; + $a_cycles[$instnumb]=$wordlist[$nbword-1]; + $a_opcodehex[$instnumb]=$wordlist[1]; + $a_opcodebin[$instnumb]=$wordlist[0]; + + + $instfunction[$instnumb]="CPU8051::OP_$wordlist[1]"; + + $instargs[$instnumb << 2]=$instargs[($instnumb << 2) + 1]=$instargs[($instnumb << 2) + 2]=$instargs[($instnumb << 2) + 3]=0; + if ($nbword > 5) { + @argslist=split /\,/,$wordlist[3]; + $argslistsize=@argslist; + $instargs[$instnumb << 2]=$argslistsize; + for ($i=0;$i<$argslistsize;$i++) { + if (not exists $argstypes{$argslist[$i]}) { + $argstypes[$nbargs]=$argslist[$i]; + $argstypes{$argslist[$i]}=$nbargs++; + } + $instargs[($instnumb << 2) + $i + 1]=$argstypes{$argslist[$i]}; + } + } + + if (not exists $insttext{$wordlist[2]}) { + $insttext[$nbinst]=$wordlist[2]; + $insttext{$wordlist[2]}=$nbinst++; + } + + $insttype[$instnumb]=$insttext{$wordlist[2]}; + + if ( not exists $addrmode{$wordlist[3]}) { + $addrmode[$nbaddr]=$wordlist[3]; + $addrmode{$wordlist[3]}=$nbaddr++; + } + + $nbbytes[$instnumb]=$wordlist[$nbword-2]; + + $instaddr[$instnumb]=$addrmode{$wordlist[3]}; + + $instnumb++; +} +# ------------------------------------------------------------------------------ +print DISASM_HPP "// For all 256 opcodes, the value in this table gives the instruction type\n"; +print DISASM_HPP "// ex.: MOV, INC, CLR, CPL,...\n"; +print DISASM_HPP "// To know what is the instruction type, use the number as an offset in the InstTextTbl[]\n"; +print DISASM_HPP "static int InstTypesTbl[] = {\n"; +for($i=0;$i<256;$i++) { + print DISASM_HPP " $insttype[$i]"; + ($i != 255) and print DISASM_HPP ","; + if (($i+1) % 16 == 0) { print DISASM_HPP "\n"; } +} +print DISASM_HPP "};\n"; +print DISASM_HPP "\n\n"; +# ------------------------------------------------------------------------------ +print DISASM_HPP "// Size(in bytes) of each instruction (offset in table is instruction opcode)\n"; +print DISASM_HPP "static int InstSizesTbl[] = {\n"; +for($i=0;$i<256;$i++) { + print DISASM_HPP " $nbbytes[$i]"; + ($i != 255) and print DISASM_HPP ","; + if (($i+1) % 16 == 0) { print DISASM_HPP "\n"; } +} +print DISASM_HPP "};\n"; +print DISASM_HPP "\n\n"; +# ------------------------------------------------------------------------------ +print DISASM_HPP "// List of instructions types referenced by InstTypesTbl[]\n"; +$nbelement=@insttext; +print DISASM_HPP "\#define InstTextTblLength $nbelement\n"; +$elementnb=0; +print DISASM_HPP "static char *InstTextTbl[] = {\n"; +foreach $instruc (@insttext) { + print DISASM_HPP " \"$instruc\""; + ($elementnb++ < $nbelement-1) and print DISASM_HPP ","; + print DISASM_HPP "\n"; +} +print DISASM_HPP "};\n"; +print DISASM_HPP "\n\n"; +# ------------------------------------------------------------------------------ +print DISASM_HPP "// Table describing all arguments types of an instruction\n"; +print DISASM_HPP "// The table is indexed InstArgTbl[ opcode * 4]\n"; +print DISASM_HPP "// InstArgTbl[opcode*4 + 1] gives the number of arguments the instruction has\n"; +print DISASM_HPP "// InstArgTbl[opcode*4 + i] for i=1,2 and 3 give the type of each argument\n"; +print DISASM_HPP "// for most instructions, the 3rd argument isn't used\n"; +print DISASM_HPP "// the argument type is referecing to ArgsTextTbl[]\n"; +print DISASM_HPP "\#define InstArgTblLength 256\n"; +print DISASM_HPP "static int InstArgTbl[] = {\n"; +for($i=0;$i<1024;$i++) { + print DISASM_HPP " $instargs[$i]"; + ($i != 1023) and print DISASM_HPP ","; + if (($i+1) % 16 == 0) { print DISASM_HPP "\n"; } +} +print DISASM_HPP "};\n"; +print DISASM_HPP "\n\n"; +# ------------------------------------------------------------------------------ +print DISASM_HPP "// List all types of arguments available to instructions\n"; +print DISASM_HPP "// Referenced by InstArgsTbl[]\n"; +$nbelement=@argstypes; +print DISASM_HPP "\#define ArgsTextTblLength $nbelement\n"; +$elementnb=0; +print DISASM_HPP "static char *ArgsTextTbl[] = {\n"; +foreach $args (@argstypes) { + print DISASM_HPP " \"$args\""; + ($elementnb++ < $nbelement-1) and print DISASM_HPP ","; + print DISASM_HPP "\n"; +} +print DISASM_HPP "};\n"; +print DISASM_HPP "\n\n"; +# ------------------------------------------------------------------------------ +for ($i=0 ; $i< 256; $i++) { + print INST_IMP "/"x78,"\n"; + print INST_IMP "// void CPU8051::OP_$a_opcodehex[$i]( )\n"; + print INST_IMP "// Instruction \"$a_instruction[$i]\" takes $a_cycles[$i] cycle(s) and $a_bytes[$i] byte(s)\n"; + print INST_IMP "/"x78,"\n"; + print INST_IMP "int CPU8051::OP_$a_opcodehex[$i]( )\n"; + print INST_DEF "int OP_$a_opcodehex[$i]( );\n"; + print INST_IMP "{\n"; + + if ($i == 0x85) { + # Cas particulier pour MOV direct,direct -> src et dest sont inverses dans la memoire + print INST_IMP "unsigned char srcaddr = PGMMem->Read8( PC++ );\n"; + print INST_IMP "unsigned char source = ReadD( srcaddr );\n"; + print INST_IMP "unsigned char destaddr = PGMMem->Read8( PC++ );\n"; + print INST_IMP "unsigned char destination = ReadD( destaddr );\n"; + print INST_IMP "destination = source;\n"; + print INST_IMP "WriteD( destaddr, destination );\n"; + } else { + +if ($instargs[$i*4] > 0) { + $op_destination=$instargs[$i*4+1]; + if ($op_destination == 0) { # addr11 + print INST_IMP "unsigned int addr11 = ( ( PGMMem->Read8( PC - 1 ) << 3 ) & 0xF00 ) + PGMMem->Read8( PC++ );\n"; + } + if ($op_destination == 1) { # addr16 + print INST_IMP "unsigned int addr16 = ( PGMMem->Read8( PC++ ) << 8 );\n"; + print INST_IMP "addr16 += PGMMem->Read8( PC++ );\n"; + } + if ($op_destination == 2) { # A + print INST_IMP "unsigned char destination = ReadD( _ACC_ );\n"; + } + if ($op_destination == 3) { # direct + print INST_IMP "unsigned char destaddr = PGMMem->Read8( PC++ );\n"; + print INST_IMP "unsigned char destination = ReadD( destaddr );\n"; + } + if ($op_destination == 4) { # @R0 + print INST_IMP "unsigned char destination = ReadI ( ReadD( BANKPSW + _R0_ ) );\n"; + } + if ($op_destination == 5) { # @R1 + print INST_IMP "unsigned char destination = ReadI ( ReadD( BANKPSW + _R1_ ) );\n"; + } + + if ($op_destination == 6) { # R0 + print INST_IMP "unsigned char destination = ReadD( BANKPSW + _R0_ );\n"; + } + if ($op_destination == 7) { # R1 + print INST_IMP "unsigned char destination = ReadD( BANKPSW + _R1_ );\n"; + } + if ($op_destination == 8) { # R2 + print INST_IMP "unsigned char destination = ReadD( BANKPSW + _R2_ );\n"; + } + if ($op_destination == 9) { # R3 + print INST_IMP "unsigned char destination = ReadD( BANKPSW + _R3_ );\n"; + } + if ($op_destination == 10) { # R4 + print INST_IMP "unsigned char destination = ReadD( BANKPSW + _R4_ );\n"; + } + if ($op_destination == 11) { # R5 + print INST_IMP "unsigned char destination = ReadD( BANKPSW + _R5_ );\n"; + } + if ($op_destination == 12) { # R6 + print INST_IMP "unsigned char destination = ReadD( BANKPSW + _R6_ );\n"; + } + if ($op_destination == 13) { # R7 + print INST_IMP "unsigned char destination = ReadD( BANKPSW + _R7_ );\n"; + } + if ($op_destination == 14) { # bitaddr + print INST_IMP "unsigned char destination, dstbitaddr = PGMMem->Read8( PC++ );\n"; + print INST_IMP "destination = ReadB( dstbitaddr );\n"; + } + if ($op_destination == 15) { # reladdr + print INST_IMP "PC++;\n"; + print INST_IMP "unsigned int destination = ( ( PGMMem->Read8( PC - 1 ) + PC ) & 0xFF ) + ( PC & 0xFF00 );\n"; + } + if ($op_destination == 16) { # #data + print INST_IMP "unsigned char destination = PGMMem->Read8( PC++ );\n"; + } + if ($op_destination == 17) { # C + print INST_IMP "unsigned char destination = ( ReadD( _PSW_ ) >> 7 );\n"; + } + if ($op_destination == 18) { # @A+DPTR + print INST_IMP "unsigned int destination = ReadI( ReadD( _ACC_ ) + ReadD( _DPTRLOW_ ) + ( ReadD( _DPTRHIGH_ ) << 8 ) );\n"; + } +# Mis en commentaire car donnait un warning (destination et source unused variables...) +# if ($op_destination == 20) { # AB +# print INST_IMP "unsigned char destination = ReadD( _ACC_ );\n"; +# print INST_IMP "unsigned char source = ReadD( _B_ );\n"; +# } + if ($op_destination == 21) { # DPTR + print INST_IMP "unsigned int destination = ( ReadD( _DPTRHIGH_ ) << 8 ) + ReadD( _DPTRLOW_ );\n"; + } + if ($op_destination == 22) { # #data16 + print INST_IMP "unsigned char destination = ( PGMMem->Read8( PC++ ) << 8 );\n"; + print INST_IMP "destination += PGMMem->Read8( PC++ );\n"; + } + if ($op_destination == 23) { # /bitaddr + print INST_IMP "unsigned char destination, dstbitaddr = PGMMem->Read8( PC++ );\n"; + print INST_IMP "destination = ( ReadB( dstbitaddr ) ^ 1 );\n"; + } + if ($op_destination == 24) { # @DPTR + print INST_IMP "unsigned char destination = ReadI( ( ReadD( _DPTRHIGH_ ) << 8 ) + ReadD( _DPTRLOW_) );\n"; + } + } + + if ($instargs[$i*4] > 1) { + $op_source=$instargs[$i*4+2]; + if ($op_source == 0) { # addr11 + print INST_IMP "unsigned int addr11 = ( ( PGMMem->Read8( PC - 1 ) << 3 ) & 0xF00 ) + PGMMem->Read8( PC++ );\n"; + } + if ($op_source == 1) { # addr16 + print INST_IMP "unsigned int addr16 = ( PGMMem->Read8( PC++ ) << 8 );\n"; + print INST_IMP "addr16 += PGMMem->Read8( PC++ );\n"; + } + if ($op_source == 2) { # A + print INST_IMP "unsigned char source = ReadD( _ACC_ );\n"; + } + if ($op_source == 3) { # direct + print INST_IMP "unsigned char srcaddr = PGMMem->Read8( PC++ );\n"; + print INST_IMP "unsigned char source = ReadD( srcaddr );\n"; + } + if ($op_source == 4) { # @R0 + print INST_IMP "unsigned char source = ReadI ( ReadD( BANKPSW + _R0_ ) );\n"; + } + if ($op_source == 5) { # @R1 + print INST_IMP "unsigned char source = ReadI ( ReadD( BANKPSW + _R1_ ) );\n"; + } + if ($op_source == 6) { # R0 + print INST_IMP "unsigned char source = ReadD( BANKPSW + _R0_ );\n"; + } + if ($op_source == 7) { # R1 + print INST_IMP "unsigned char source = ReadD( BANKPSW + _R1_ );\n"; + } + if ($op_source == 8) { # R2 + print INST_IMP "unsigned char source = ReadD( BANKPSW + _R2_ );\n"; + } + if ($op_source == 9) { # R3 + print INST_IMP "unsigned char source = ReadD( BANKPSW + _R3_ );\n"; + } + if ($op_source == 10) { # R4 + print INST_IMP "unsigned char source = ReadD( BANKPSW + _R4_ );\n"; + } + if ($op_source == 11) { # R5 + print INST_IMP "unsigned char source = ReadD( BANKPSW + _R5_ );\n"; + } + if ($op_source == 12) { # R6 + print INST_IMP "unsigned char source = ReadD( BANKPSW + _R6_ );\n"; + } + if ($op_source == 13) { # R7 + print INST_IMP "unsigned char source = ReadD( BANKPSW + _R7_ );\n"; + } + + if ($op_source == 14) { # bitaddr + print INST_IMP "unsigned char source, srcbitaddr = PGMMem->Read8( PC++ );\n"; + print INST_IMP "source = ReadB( srcbitaddr );\n"; + } + if ($op_source == 15) { # reladdr + print INST_IMP "PC++;\n"; + print INST_IMP "unsigned int source = ( ( PGMMem->Read8( PC - 1 ) + PC ) & 0xFF ) + ( PC & 0xFF00 );\n"; + } + if ($op_source == 16) { # #data + print INST_IMP "unsigned char source = PGMMem->Read8( PC++ );\n"; + } + if ($op_source == 17) { # C + print INST_IMP "unsigned char source = ( ReadD( _PSW_ ) >> 7 );\n"; + } + if ($op_source == 18) { # @A+DPTR + print INST_IMP "unsigned char source = PGMMem->Read8( ReadD( _ACC_ ) + ReadD( _DPTRLOW_ ) + ( ReadD( _DPTRHIGH_ ) << 8 ) );\n"; + } + if ($op_source == 19) { # @A+PC + print INST_IMP "unsigned char source = PGMMem->Read8( ReadD( _ACC_ ) + ( ++PC ) );\n"; + } + if ($op_source == 21) { # DPTR + print INST_IMP "unsigned int source = ( ReadD( _DPTRHIGH_ ) << 8 ) + ReadD( _DPTRLOW_ );\n"; + } + if ($op_source == 22) { # #data16 + print INST_IMP "unsigned char source = ( PGMMem->Read8( PC++ ) << 8 );\n"; + print INST_IMP "source += PGMMem->Read8( PC++ );\n"; + } + if ($op_source == 23) { # /bitaddr + print INST_IMP "unsigned char source, srcbitaddr = PGMMem->Read8( PC++ );\n"; + print INST_IMP "source = ( ReadB( srcbitaddr ) ^ 1 );\n"; + } + if ($op_source == 24) { # @DPTR + print INST_IMP "unsigned char source = ReadI( ( ReadD( _DPTRHIGH_ ) << 8 ) + ReadD( _DPTRLOW_) );\n"; + } + } + +############################################################################## + $modifysrc=0; +# print INST_IMP "\n// Inserer le code ici\n\n"; + + # RR + if ($insttype[$i] == 3) { + print INST_IMP "destination = ( destination >> 1 ) | ( destination << 7 );\n"; + } + + # INC + if ($insttype[$i] == 4) { + print INST_IMP "destination++;\n"; + } + + # JBC + if ($insttype[$i] == 5) { + print INST_IMP "if ( destination == 1 ) { PC = source; destination = 0; }\n"; + } + + # ACALL + if ($insttype[$i] == 6) { + print INST_IMP "unsigned char SP = ReadD( _SP_ );\n"; + print INST_IMP "WriteI( ++SP, ( PC & 0x00FF ) );\n"; + print INST_IMP "WriteI( ++SP, ( PC >> 8 ) );\n"; + print INST_IMP "WriteD( _SP_, SP );\n"; + } + + # LCALL + if ($insttype[$i] == 7) { + print INST_IMP "unsigned char SP = ReadD( _SP_ );\n"; + print INST_IMP "WriteI( ++SP, ( PC & 0x00FF ) );\n"; + print INST_IMP "WriteI( ++SP, ( PC >> 8 ) );\n"; + print INST_IMP "WriteD( _SP_, SP );\n"; + } + + # RRC + if ($insttype[$i] == 8) { + print INST_IMP "unsigned char tmpval = destination;\n"; + print INST_IMP "destination = ( destination >> 1 ) | ( ReadD( _PSW_ ) & 0x80 );\n"; + print INST_IMP "WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x7F ) | ( tmpval << 7 ) );\n"; + } + + # DEC + if ($insttype[$i] == 9) { + print INST_IMP "destination--;\n"; + } + + # JB + if ($insttype[$i] == 10) { + print INST_IMP "if ( destination == 1 ) { PC = source; }\n"; + } + + # RET + if ($insttype[$i] == 11) { + print INST_IMP "unsigned char SP = ReadD( _SP_ );\n"; + print INST_IMP "PC = ( ReadI( SP-- ) << 8 );\n"; + print INST_IMP "PC += ReadI ( SP-- );\n"; + print INST_IMP "WriteD( _SP_, SP );\n"; + } + + # RL + if ($insttype[$i] == 12) { + print INST_IMP "destination = ( destination << 1 ) | ( destination >> 7 );\n"; + } + + # ADD + if ($insttype[$i] == 13) { + print INST_IMP "WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x3B ) );\n"; + print INST_IMP "if ( destination + source > 0xFF ) {\n"; + print INST_IMP " WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) );\n"; + print INST_IMP " if ( ( destination & 0x7F ) + ( source & 0x7F ) < 0x80 ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) );\n"; + print INST_IMP "} else if ( ( destination & 0x7F ) + ( source & 0x7F ) > 0x7F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) );\n"; + print INST_IMP "if ( ( destination & 0x0F ) + ( source & 0x0F ) > 0x0F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) );\n"; + print INST_IMP "destination += source;\n"; + } + + # JNB + if ($insttype[$i] == 14) { + print INST_IMP "if ( destination == 0 ) { PC = source; }\n"; + } + + # RETI + if ($insttype[$i] == 15) { + print INST_IMP "ActivePriority = -1;\n"; + print INST_IMP "unsigned char SP = ReadD( _SP_ );\n"; + print INST_IMP "PC = ( ReadI( SP-- ) << 8 );\n"; + print INST_IMP "PC += ReadI( SP-- );\n"; + } + + # RLC + if ($insttype[$i] == 16) { + print INST_IMP "unsigned char tmpval = destination;\n"; + print INST_IMP "destination = ( destination << 1 ) | ( ( ReadD( _PSW_ ) & 0x80 ) >> 7 );\n"; + print INST_IMP "WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x7F ) | ( tmpval & 0x80 ) );\n"; + } + + # ADDC + if ($insttype[$i] == 17) { + print INST_IMP "unsigned char carryflag = ( ReadD( _PSW_ ) >> 7 );\n"; + print INST_IMP "WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x3B ) );\n"; + print INST_IMP "if ( destination + source + carryflag > 0xFF ) {\n"; + print INST_IMP " WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) );\n"; + print INST_IMP " if ( ( destination & 0x7F ) + ( source & 0x7F ) + carryflag < 0x80 ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) );\n"; + print INST_IMP "} else if ( ( destination & 0x7F ) + ( source & 0x7F ) + carryflag > 0x7F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) );\n"; + print INST_IMP "if ( ( destination & 0x0F ) + ( source & 0x0F ) + carryflag > 0x0F ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x40 ) );\n"; + print INST_IMP "destination += source;\n"; + } + + # JC + if ($insttype[$i] == 18) { + print INST_IMP "if ( ReadD( _PSW_ ) > 0x7F) { PC = destination; }\n"; + } + + # ORL + if ($insttype[$i] == 19) { + if ($instargs[$i*4+1] == 17) { + # sur des bits + print INST_IMP "WriteD( _PSW_ , ( ( destination | source ) << 7 ) );\n"; + } else { + # sur des bytes + print INST_IMP "destination |= source;\n"; + } + } + + # JNC + if ($insttype[$i] == 20) { + print INST_IMP "if ( ReadD( _PSW_ ) < 0x80 ) { PC = destination; }\n"; + } + + # ANL + if ($insttype[$i] == 21) { + if ($instargs[$i*4+1] == 17) { + # sur des bits + print INST_IMP "WriteD( _PSW_, ( ( destination & source) << 7 ) );\n"; + } else { + # sur des bytes + print INST_IMP "destination &= source;\n"; + } + } + + # JZ + if ($insttype[$i] == 22) { + print INST_IMP "if ( ReadD( _ACC_ ) == 0 ) { PC = destination; }\n"; + } + + # XRL + if ($insttype[$i] == 23) { + print INST_IMP "destination ^= source;\n"; + } + + # JNZ + if ($insttype[$i] == 24) { + print INST_IMP "if ( ReadD( _ACC_ ) != 0 ) { PC = destination; }\n"; + } + + # JMP + if ($insttype[$i] == 25) { + print INST_IMP "PC = destination;\n"; + } + + # MOV + if ($insttype[$i] == 26) { + print INST_IMP "destination = source;\n"; + } + + # SJMP + if ($insttype[$i] == 27) { + print INST_IMP "PC = destination;\n"; + } + + # MOVC + if ($insttype[$i] == 28) { + print INST_IMP "destination = source;\n"; + } + + # DIV + if ($insttype[$i] == 29) { + print INST_IMP "unsigned char A = ReadD( _ACC_ ), B = ReadD( _B_ );\n"; + print INST_IMP "WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x7B ) );\n"; + print INST_IMP "if ( B != 0 ) {\n"; + print INST_IMP "WriteD( _ACC_, A/B ); WriteD( _B_, A%B );\n"; + print INST_IMP "} else WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) );\n"; + } + + # SUBB + if ($insttype[$i] == 30) { + print INST_IMP "unsigned char carryflag = ReadD( _PSW_ ) >> 7;\n"; + print INST_IMP "WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x3B ) );\n"; + print INST_IMP "if ( destination < ( source + carryflag ) ) {\n"; + print INST_IMP " WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) );\n"; + print INST_IMP " if ( ( destination & 0x7F ) > ( ( source + carryflag ) & 0x7F ) ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) );\n"; + print INST_IMP "} else if ( ( destination & 0x7F ) < ( ( source + carryflag ) & 0x7F ) ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) );\n"; + print INST_IMP "if ( ( destination & 0x0F ) < ( ( source + carryflag ) & 0x0F ) ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x40 ) );\n"; + print INST_IMP "destination -= source + carryflag;\n"; + } + + # MUL + if ($insttype[$i] == 31) { + print INST_IMP "unsigned char A = ReadD( _ACC_ ), B = ReadD( _B_ );\n"; + print INST_IMP "WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x7B ) );\n"; + print INST_IMP "WriteD( _ACC_ , ( ( A * B ) & 0x00FF ) ); WriteD( _B_, ( A * B ) / 0x100 );\n"; + print INST_IMP "if ( ReadD( _B_ ) > 0) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x04 ) );\n"; + } + + # CPL + if ($insttype[$i] == 33) { + if ($instargs[$i*4+1] == 2) { print INST_IMP "destination ^= 0xFF;\n"; } + else { print INST_IMP "destination ^= 0x01;\n"; } + } + + # CJNE + if ($insttype[$i] == 34) { + print INST_IMP "unsigned int reladdr = ( ( PGMMem->Read8( PC ) + ( ( PC + 1 ) & 0x00FF ) ) & 0x00FF ) + ( ( PC + 1 ) & 0xFF00 );\n"; + print INST_IMP "WriteD( _PSW_, ( ReadD( _PSW_ ) & 0x7F ) );\n"; + print INST_IMP "if ( destination < source ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) );\n"; + print INST_IMP "if ( destination != source ) PC = reladdr;\n"; + } + + # PUSH + if ($insttype[$i] == 35) { + print INST_IMP "unsigned char SP = ReadD( _SP_ );\n"; + print INST_IMP "WriteI( ++SP, destination );\n"; + print INST_IMP "WriteD( _SP_, SP );\n"; + } + + # CLR + if ($insttype[$i] == 36) { + print INST_IMP "destination = 0;\n"; + } + + # SWAP + if ($insttype[$i] == 37) { + print INST_IMP "destination = ( destination << 4 ) + ( destination >> 4 );\n"; + } + + # XCH + if ($insttype[$i] == 38) { + print INST_IMP "unsigned char tmpval = destination;\n"; + print INST_IMP "destination = source; source = tmpval;\n"; + $modifysrc=1; + } + + # POP + if ($insttype[$i] == 39) { + print INST_IMP "unsigned char SP = ReadD( _SP_ );\n"; + print INST_IMP "destination = ReadI( SP-- );\n"; + print INST_IMP "WriteD( _SP_, SP );\n"; + } + + # SETB + if ($insttype[$i] == 40) { + print INST_IMP "destination = 1;\n"; + } + + # DA + if ($insttype[$i] == 41) { + print INST_IMP "if ( ( ( destination & 0x0F ) > 9) || ( ReadD( _PSW_ ) | 0x40)) {\n"; + print INST_IMP " if ( ( destination + 6 ) > 0xFF) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) );\n"; + print INST_IMP " destination += 6;\n"; + print INST_IMP "}\n"; + print INST_IMP "if ( ( ReadD( _PSW_ ) & 0x80) || ( ( destination & 0xF0 ) > 0x90 ) ) {\n"; + print INST_IMP " if ( ( destination + 0x60 ) > 0xFF ) WriteD( _PSW_, ( ReadD( _PSW_ ) | 0x80 ) );\n"; + print INST_IMP " destination += 0x60;\n"; + print INST_IMP "}\n"; + } + + # DJNZ + if ($insttype[$i] == 42) { + print INST_IMP "destination--;\n"; + print INST_IMP "if ( destination != 0 ) PC = source;\n"; + } + + # XCHD + if ($insttype[$i] == 43) { + print INST_IMP "unsigned char tmpval = ( destination & 0x0F );\n"; + print INST_IMP "destination = ( destination & 0xF0 ) + ( source & 0x0F );\n"; + print INST_IMP "source = ( source & 0xF0 ) + tmpval;\n"; + $modifysrc=1; + } + + # MOVX + if ($insttype[$i] == 44) { + print INST_IMP "destination = source;\n"; + } + + + +############################################################################## + + + if ($instargs[$i*4] > 0) { + $op_destination=$instargs[$i*4+1]; + if ($op_destination == 0) { # addr11 + print INST_IMP "PC = ( PC & 0xF800 ) | addr11;\n"; + } + if ($op_destination == 1) { # addr16 + print INST_IMP "PC = addr16;\n"; + } + if ($op_destination == 2) { # A + print INST_IMP "WriteD( _ACC_, destination );\n"; + } + if ($op_destination == 3) { # direct + print INST_IMP "WriteD( destaddr, destination );\n"; + } + if ($op_destination == 4) { # @R0 + print INST_IMP "WriteI( ReadD( BANKPSW + _R0_ ), destination );\n"; + } + if ($op_destination == 5) { # @R1 + print INST_IMP "WriteI( ReadD( BANKPSW + _R1_ ), destination );\n"; + } + if ($op_destination == 6) { # R0 + print INST_IMP "WriteD( BANKPSW + _R0_, destination );\n"; + } + if ($op_destination == 7) { # R1 + print INST_IMP "WriteD( BANKPSW + _R1_, destination );\n"; + } + if ($op_destination == 8) { # R2 + print INST_IMP "WriteD( BANKPSW + _R2_, destination );\n"; + } + if ($op_destination == 9) { # R3 + print INST_IMP "WriteD( BANKPSW + _R3_, destination );\n"; + } + if ($op_destination == 10) { # R4 + print INST_IMP "WriteD( BANKPSW + _R4_, destination );\n"; + } + if ($op_destination == 11) { # R5 + print INST_IMP "WriteD( BANKPSW + _R5_, destination );\n"; + } + if ($op_destination == 12) { # R6 + print INST_IMP "WriteD( BANKPSW + _R6_, destination );\n"; + } + if ($op_destination == 13) { # R7 + print INST_IMP "WriteD( BANKPSW + _R7_, destination );\n"; + } + + if ($op_destination == 14) { # bitaddr + print INST_IMP "WriteB( dstbitaddr, destination );\n"; + } + if ($op_destination == 17) { # C + print INST_IMP "WriteD( _PSW_, ( ( ReadD( _PSW_ ) & 0x7F) | ( destination << 7 ) ) );\n"; + } + if ($op_destination == 21) { # DPTR + print INST_IMP "WriteD( _DPTRHIGH_, ( destination >> 8 ) );\n"; + print INST_IMP "WriteD( _DPTRLOW_, ( destination & 0xFF ) );\n"; + } + if ($op_destination == 23) { # /bitaddr + print INST_IMP "WriteB( dstbitaddr, destination );\n"; + } + if ($op_destination == 24) { # @DPTR + print INST_IMP "WriteI( ( ReadD( _DPTRHIGH_ ) << 8 ) + ReadD( _DPTRLOW_ ), destination );\n"; + } + } + + if ($modifysrc == 1) { + if ($instargs[$i*4] > 1) { + $op_source=$instargs[$i*4+2]; + if ($op_source == 0) { # addr11 + print INST_IMP "PC = ( PC & 0xF800 ) | addr11;\n"; + } + if ($op_source == 1) { # addr16 + print INST_IMP "PC = addr16;\n"; + } + if ($op_source == 2) { # A + print INST_IMP "WriteD( _ACC_, source );\n"; + } + if ($op_source == 3) { # direct + print INST_IMP "WriteD( srcaddr, source );\n"; + } + if ($op_source == 4) { # @R0 + print INST_IMP "WriteI( ReadD( BANKPSW + _R0_ ), source );\n"; + } + if ($op_source == 5) { # @R1 + print INST_IMP "WriteI( ReadD( BANKPSW + _R1_ ), source );\n"; + } + if ($op_source == 6) { # R0 + print INST_IMP "WriteD( BANKPSW + _R0_, source );\n"; + } + if ($op_source == 7) { # R1 + print INST_IMP "WriteD( BANKPSW + _R1_, source );\n"; + } + if ($op_source == 8) { # R2 + print INST_IMP "WriteD( BANKPSW + _R2_, source );\n"; + } + if ($op_source == 9) { # R3 + print INST_IMP "WriteD( BANKPSW + _R3_, source );\n"; + } + if ($op_source == 10) { # R4 + print INST_IMP "WriteD( BANKPSW + _R4_, source );\n"; + } + if ($op_source == 11) { # R5 + print INST_IMP "WriteD( BANKPSW + _R5_, source );\n"; + } + if ($op_source == 12) { # R6 + print INST_IMP "WriteD( BANKPSW + _R6_, source );\n"; + } + if ($op_source == 13) { # R7 + print INST_IMP "WriteD( BANKPSW + _R7_, source );\n"; + } + if ($op_source == 14) { # bitaddr + print INST_IMP "WriteB( srcbitaddr, source );\n"; + } + if ($op_source == 17) { # C + print INST_IMP "WriteD( _PSW_, ( ( ReadD( _PSW_ ) & 0x7F) | ( source << 7 ) ) );\n"; + } + if ($op_source == 21) { # DPTR + print INST_IMP "WriteD( _DPTRHIGH_, ( source >> 8 ) );\n"; + print INST_IMP "WriteD( _DPTRLOW_, ( source & 0xFF ) );\n"; + } + if ($op_source == 23) { # /bitaddr + print INST_IMP "WriteB( srcbitaddr, source );\n"; + } + if ($op_source == 24) { # @DPTR + print INST_IMP "WriteI( ( ReadD( _DPTRHIGH_ ) << 8 ) + ReadD( _DPTRLOW_ ), source );\n"; + } + } +} +} + print INST_IMP "return $a_cycles[$i];\n"; + print INST_IMP "}\n"; + print INST_IMP "\n\n"; +} +# ------------------------------------------------------------------------------ +print INST_IMP "\n\n"; + + print INST_IMP "/"x78,"\n"; + print INST_IMP "// void CPU8051::InitFuncPtr( )\n"; + print INST_IMP "// Initialize Functions Pointers\n"; + print INST_IMP "/"x78,"\n"; + print INST_IMP "void CPU8051::InitFuncPtr( )\n"; + print INST_DEF "void InitFuncPtr( );\n"; + print INST_IMP "{\n"; + + +#print INST_IMP "static int (*instfnc[])() = {\n"; +for ($i=0;$i<256;$i++) { + $ifunc=substr($instfunction[$i], 9); + print INST_IMP " funcptr[$i]=&CPU8051::$ifunc;\n"; +# ($i < 255) and print INST_IMP ",\n"; +# (($i+1) % 4 == 0) and print INST_IMP "\n"; +} +print INST_IMP "\n}\n"; + +print INST_IMP "\n\n#endif\n"; +print INST_DEF "\n\n#endif\n"; +print DISASM_HPP "\n\n#endif\n"; + + +close DISASM_HPP; +close OPCODELST; +close INST_DEF; +close INST_IMP; + + diff --git a/src/PgmWin.cpp b/src/PgmWin.cpp new file mode 100644 index 0000000..b362709 --- /dev/null +++ b/src/PgmWin.cpp @@ -0,0 +1,186 @@ +/* pgmwin.cpp */ + + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include "PgmWin.hpp" +#include + +int PgmWinNumber = 0; +int PgmWinNumbers[ 1 ]; +PgmWin *PgmWinPtrs[ 1 ]; + +////////////////////////////////////////////////////////////////////////////// +// PgmWin::PgmWin( GtkWidget *parentwin, CPU8051 *mCPU ) +// PgmWin constructor +////////////////////////////////////////////////////////////////////////////// +PgmWin::PgmWin( GtkWidget *parentwin, CPU8051 *mCPU ) +{ + CPU = mCPU; + int i; + GtkStyle *style; + GdkFont *fixedfont; + fixedfont = gdk_font_load( "-adobe-courier-medium-r-normal--12-120-75-75-m-70-iso8859-1" ); + + pgmclist = gtk_clist_new( 1 ); + gtk_clist_set_selection_mode( GTK_CLIST( pgmclist ), GTK_SELECTION_SINGLE ); + gtk_widget_set_usize( GTK_WIDGET( pgmclist ), PGM_WIN_WIDTH, PGM_WIN_HEIGHT ); + gtk_clist_set_column_justification( GTK_CLIST( pgmclist ), 0, GTK_JUSTIFY_LEFT ); + gtk_clist_set_column_width( GTK_CLIST( pgmclist ), 0, PGM_WIN_WIDTH-10 ); + + style = gtk_widget_get_style( GTK_WIDGET( pgmclist ) ); + +#ifdef USE_GTK2 + gtk_style_set_font( style, fixedfont ); +#else + style->font = fixedfont; +#endif + + gtk_widget_set_style( GTK_WIDGET( pgmclist ), style ); + + char *pgmdummy[] = { 0 }; + for ( i = 0; i < 24; i++ ) gtk_clist_append( GTK_CLIST( pgmclist ), pgmdummy ); + + gtk_container_add( GTK_CONTAINER( parentwin ), pgmclist ); + + gtk_widget_show( pgmclist ); + + NbBreakpoints = 0; + + if ( PgmWinNumber >= 1 ) g_print( "WARNING! Too many PgmWin objects to handle signals!\n"); + else { + PgmWinPtrs[ PgmWinNumber ] = this; + PgmWinNumbers[ PgmWinNumber ] = PgmWinNumber; + gtk_signal_connect( GTK_OBJECT( pgmclist ), "button-press-event", GTK_SIGNAL_FUNC( PgmWinButtonPress ), &PgmWinNumbers[ PgmWinNumber++ ] ); + } +} + + +////////////////////////////////////////////////////////////////////////////// +// PgmWin::~PgmWin( ) +// PgmWin destructor +////////////////////////////////////////////////////////////////////////////// +PgmWin::~PgmWin( ) +{ + +} + +////////////////////////////////////////////////////////////////////////////// +// void PgmWin::Disasm( ) +// Disasm 24 lines from CPU +////////////////////////////////////////////////////////////////////////////// +void PgmWin::Disasm( ) +{ +char TextTmp[255]; +int row; +//int TextLength; +int InstSize; +unsigned int Address; +Address = CPU->GetPC( ); + +gtk_clist_freeze( GTK_CLIST( pgmclist ) ); + for ( row = 0; row < 24; row++ ) { + InstSize = CPU->Disasm( Address, TextTmp ); + if ( IsBreakpoint( Address ) ) TextTmp[0] = '*'; + gtk_clist_set_text( GTK_CLIST( pgmclist ), row, 0, TextTmp ); + DisasmAddresses[ row ] = Address; + Address += InstSize; + } +gtk_clist_select_row( GTK_CLIST( pgmclist ), 0, 0 ); +gtk_clist_thaw( GTK_CLIST( pgmclist ) ); +} + +////////////////////////////////////////////////////////////////////////////// +// gint PgmWin::ButtonPressEvent( GtkWidget *widget, GdkEvent *event, gpointer data ) +// Mouse button pressed in the window +////////////////////////////////////////////////////////////////////////////// +gint PgmWin::ButtonPressEvent( GtkWidget *widget, GdkEvent *event, gpointer data ) +{ + gint row, column; + char TextTmp[ 255 ]; + //g_print( "PgmWin::ButtonPressEvent(...)\n" ); + gtk_clist_get_selection_info( GTK_CLIST( pgmclist ), ( int )event->button.x ,( int )event->button.y, &row, &column ); + if (row >= 24 || row < 0) + return TRUE; + if (column >= 1 || column < 0) + return TRUE; + sprintf( TextTmp, "PgmWin::ButtonPressEvent( ) at %d,%d\n", column, row ); + g_print( TextTmp ); + ToggleBreakpoint( DisasmAddresses[ row ] ); + Disasm( ); + return FALSE; +} + +////////////////////////////////////////////////////////////////////////////// +// gint PgmWinButtonPress( GtkWidget *widget, GdkEvent *event, gpointer data ) +// Signal Stub with 3 parameters +////////////////////////////////////////////////////////////////////////////// +void PgmWinButtonPress( GtkWidget *widget, GdkEvent *event, gpointer data ) +{ +int PWNumber = (* ( static_cast< int * >( data ) ) ); +PgmWinPtrs[ PWNumber ]->ButtonPressEvent( widget, event, 0 ); +} + + +////////////////////////////////////////////////////////////////////////////// +// void PgmWin::ShowBreakpoints( ) +// Show Breakpoints list +////////////////////////////////////////////////////////////////////////////// +void PgmWin::ShowBreakpoints( ) +{ + for ( int Index = 0; Index < NbBreakpoints ; Index++ ) + printf( "Breakpoint at Address = %.4X\n", Breakpoints[ Index ] ); +} + +////////////////////////////////////////////////////////////////////////////// +// void PgmWin::ClearBreakpoint( unsigned int Address ) +// Clear Breakpoint at Address from list +////////////////////////////////////////////////////////////////////////////// +void PgmWin::ClearBreakpoint( unsigned int Address ) +{ + int Index = 0; + while ( Index < NbBreakpoints && Breakpoints[ Index ] != Address ) Index++; + if ( Breakpoints[ Index ] != Address ) return; + Breakpoints[ Index ] = Breakpoints[ NbBreakpoints - 1 ]; + NbBreakpoints--; +} + +////////////////////////////////////////////////////////////////////////////// +// void PgmWin::SetBreakpoint( unsigned int Address ) +// Set Breakpoint at Address from list +////////////////////////////////////////////////////////////////////////////// +void PgmWin::SetBreakpoint( unsigned int Address ) +{ + if ( IsBreakpoint( Address ) ) return; + if ( NbBreakpoints < MAXBP ) Breakpoints[ NbBreakpoints++ ] = Address; +} + +////////////////////////////////////////////////////////////////////////////// +// int PgmWin::IsBreakpoint( unsigned int Address ) +// Is the a breakpoint at Address +////////////////////////////////////////////////////////////////////////////// +int PgmWin::IsBreakpoint( unsigned int Address ) +{ + int Index = 0; + while ( Index < NbBreakpoints && Breakpoints[ Index ] != Address ) Index++; + return ( Breakpoints[ Index ] == Address && Index < NbBreakpoints ); +} + +////////////////////////////////////////////////////////////////////////////// +// void PgmWin::ToggleBreakpoint( unsigned int Address ) +// Toggle the breakpoint at Address +////////////////////////////////////////////////////////////////////////////// +void PgmWin::ToggleBreakpoint( unsigned int Address ) +{ + if ( IsBreakpoint( Address ) ) ClearBreakpoint( Address ); + else SetBreakpoint( Address ); +} + + + + + + + diff --git a/src/PgmWin.hpp b/src/PgmWin.hpp new file mode 100644 index 0000000..0bf5820 --- /dev/null +++ b/src/PgmWin.hpp @@ -0,0 +1,41 @@ +#ifndef _PGMWIN_HPP_ +#define _PGMWIN_HPP_ + +#include +#include "CPU8051.hpp" +#include "GtkSizes.hpp" + +#define MAXBP 32 + +////////////////////////////////////////////////////////////////////////////// +// PgmWin +// Implements a Program Window in Gtk+ as an Object +////////////////////////////////////////////////////////////////////////////// +class PgmWin { +public: + PgmWin( GtkWidget *parentwin, CPU8051 *mCPU ); + ~PgmWin( ); + + void Disasm( ); + gint ButtonPressEvent( GtkWidget *widget, GdkEvent *event, gpointer data ); + + void ShowBreakpoints( ); + void SetBreakpoint( unsigned int Address ); + void ClearBreakpoint( unsigned int Address ); + int IsBreakpoint( unsigned int Address ); + void ToggleBreakpoint( unsigned int Address ); + +private: + CPU8051 *CPU; + GtkWidget *pgmwin; + GtkWidget *pgmclist; + int NbBreakpoints; + unsigned int Breakpoints[ MAXBP ]; + unsigned int DisasmAddresses[ 24 ]; + +}; + +void PgmWinButtonPress( GtkWidget *widget, GdkEvent *event, gpointer data ); + + +#endif diff --git a/src/Reg8051.hpp b/src/Reg8051.hpp new file mode 100644 index 0000000..1e6a65e --- /dev/null +++ b/src/Reg8051.hpp @@ -0,0 +1,44 @@ +#ifndef __REGISTRES8051_HPP_ +#define __REGISTRES8051_HPP_ + +// SFR Registers ( $80 - $FF ) +#define _ACC_ 0xE0 +#define _B_ 0xF0 +#define _PSW_ 0xD0 +#define _SP_ 0x81 +#define _DPTRLOW_ _DPL_ +#define _DPTRHIGH_ _DPH_ +#define _DPL_ 0x82 +#define _DPH_ 0x83 +#define _P0_ 0x80 +#define _P1_ 0x90 +#define _P2_ 0xA0 +#define _P3_ 0xB0 +#define _IP_ 0xB8 +#define _IE_ 0xA8 +#define _TMOD_ 0x89 +#define _TCON_ 0x88 +#define _TH0_ 0x8C +#define _TL0_ 0x8A +#define _TH1_ 0x8D +#define _TL1_ 0x8B +#define _SCON_ 0x98 +#define _SBUF_ 0x99 +#define _PCON_ 0x87 +#define _T2CON_ 0xC8 + +#define _R0_ 0x00 +#define _R1_ 0x01 +#define _R2_ 0x02 +#define _R3_ 0x03 +#define _R4_ 0x04 +#define _R5_ 0x05 +#define _R6_ 0x06 +#define _R7_ 0x07 + +#define _BANK0_ 0x00 +#define _BANK1_ 0x08 +#define _BANK2_ 0x10 +#define _BANK3_ 0x18 + +#endif diff --git a/src/RegWin.cpp b/src/RegWin.cpp new file mode 100644 index 0000000..0047ec5 --- /dev/null +++ b/src/RegWin.cpp @@ -0,0 +1,131 @@ +/* regwin.cpp */ + + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include "RegWin.hpp" + + +////////////////////////////////////////////////////////////////////////////// +// RegWin::RegWin( GtkWidget *parentwin ) +// RegWin constructor +////////////////////////////////////////////////////////////////////////////// +RegWin::RegWin( GtkWidget *parentwin ) +{ + int i; + GtkStyle *style; + GdkFont *fixedfont; + fixedfont = gdk_font_load( "-adobe-courier-medium-r-normal--12-120-75-75-m-70-iso8859-1" ); + + regclist = gtk_clist_new( 1 ); + gtk_clist_set_selection_mode( GTK_CLIST( regclist ), GTK_SELECTION_SINGLE ); + gtk_widget_set_usize( GTK_WIDGET( regclist ), REG_WIN_WIDTH, REG_WIN_HEIGHT ); + gtk_clist_set_column_justification( GTK_CLIST( regclist ), 0, GTK_JUSTIFY_LEFT ); + gtk_clist_set_column_width( GTK_CLIST( regclist ), 0, REG_WIN_WIDTH ); + + style = gtk_widget_get_style( GTK_WIDGET( regclist ) ); + +#ifdef USE_GTK2 + gtk_style_set_font( style, fixedfont ); +#else + style->font = fixedfont; +#endif + + gtk_widget_set_style( GTK_WIDGET( regclist ), style ); + + char *regdummy[] = { 0 }; + for ( i = 0; i < 24; i++ ) + gtk_clist_append( GTK_CLIST( regclist ), regdummy ); + + gtk_container_add( GTK_CONTAINER( parentwin ), regclist ); + + gtk_widget_show( regclist ); +} + + +////////////////////////////////////////////////////////////////////////////// +// RegWin::~RegWin( ) +// RegWin destructor +////////////////////////////////////////////////////////////////////////////// +RegWin::~RegWin( ) +{ +} + +////////////////////////////////////////////////////////////////////////////// +// void RegWin::Show( CPU8051 *CPU ) +// Show registers +////////////////////////////////////////////////////////////////////////////// +void RegWin::Show( CPU8051 *CPU ) +{ + char TextTmp[255]; + int row = 0; + unsigned char PSW = CPU->ReadD( _PSW_ ); + unsigned char Rbank; + + gtk_clist_freeze( GTK_CLIST( regclist ) ); + + // Main registers + sprintf( TextTmp , "PC = %.4X", CPU->GetPC( ) ); + gtk_clist_set_text( GTK_CLIST( regclist ), row++, 0, TextTmp ); + sprintf( TextTmp , "SP = %.2X", CPU->ReadD( _SP_ ) ); + gtk_clist_set_text( GTK_CLIST( regclist ), row++, 0, TextTmp ); + sprintf( TextTmp , "A = %.2X", CPU->ReadD( _ACC_ ) ); + gtk_clist_set_text( GTK_CLIST( regclist ), row++, 0, TextTmp ); + sprintf( TextTmp , "B = %.2X", CPU->ReadD( _B_ ) ); + gtk_clist_set_text( GTK_CLIST( regclist ), row++, 0, TextTmp ); + sprintf( TextTmp , "DPTR = %.4X", ( CPU->ReadD( _DPTRHIGH_ ) << 8 ) + CPU->ReadD( _DPTRLOW_ ) ); + gtk_clist_set_text( GTK_CLIST( regclist ), row++, 0, TextTmp ); + + // Program Status Word + sprintf( TextTmp , "PSW = %.2X",PSW); + gtk_clist_set_text( GTK_CLIST( regclist ), row++, 0, TextTmp ); + + // Ports registers + sprintf( TextTmp , "P0 = %.2X", CPU->ReadD( _P0_ ) ); + gtk_clist_set_text( GTK_CLIST( regclist ), row++, 0, TextTmp ); + sprintf( TextTmp , "P1 = %.2X", CPU->ReadD( _P1_ ) ); + gtk_clist_set_text( GTK_CLIST( regclist ), row++, 0, TextTmp ); + sprintf( TextTmp , "P2 = %.2X", CPU->ReadD( _P2_ ) ); + gtk_clist_set_text( GTK_CLIST( regclist ), row++, 0, TextTmp ); + sprintf( TextTmp , "P3 = %.2X", CPU->ReadD( _P3_ ) ); + gtk_clist_set_text( GTK_CLIST( regclist ), row++, 0, TextTmp ); + + // Misc Registers + sprintf( TextTmp , "TCON = %.2X", CPU->ReadD( _TCON_ ) ); + gtk_clist_set_text( GTK_CLIST( regclist ), row++, 0, TextTmp ); + sprintf( TextTmp , "TMOD = %.2X", CPU->ReadD( _TMOD_ ) ); + gtk_clist_set_text( GTK_CLIST( regclist ), row++, 0, TextTmp ); + sprintf( TextTmp , "SCON = %.2X", CPU->ReadD( _SCON_ ) ); + gtk_clist_set_text( GTK_CLIST( regclist ), row++, 0, TextTmp ); + sprintf( TextTmp , "IE = %.2X", CPU->ReadD( _IE_ ) ); + gtk_clist_set_text( GTK_CLIST( regclist ), row++, 0, TextTmp ); + sprintf( TextTmp , "IP = %.2X", CPU->ReadD( _IP_ ) ); + gtk_clist_set_text( GTK_CLIST( regclist ), row++, 0, TextTmp ); + + // R0-R7 Registers in current Bank + Rbank = CPU->ReadD( _PSW_ ) & 0x18; + sprintf( TextTmp , "Bank = %.2X", Rbank); + gtk_clist_set_text( GTK_CLIST( regclist ), row++, 0, TextTmp ); + sprintf( TextTmp , "R0 = %.2X", CPU->ReadD( _R0_ + Rbank ) ); + gtk_clist_set_text( GTK_CLIST( regclist ), row++, 0, TextTmp ); + sprintf( TextTmp , "R1 = %.2X", CPU->ReadD( _R1_ + Rbank ) ); + gtk_clist_set_text( GTK_CLIST( regclist ), row++, 0, TextTmp ); + sprintf( TextTmp , "R2 = %.2X", CPU->ReadD( _R2_ + Rbank ) ); + gtk_clist_set_text( GTK_CLIST( regclist ), row++, 0, TextTmp ); + sprintf( TextTmp , "R3 = %.2X", CPU->ReadD( _R3_ + Rbank ) ); + gtk_clist_set_text( GTK_CLIST( regclist ), row++, 0, TextTmp ); + sprintf( TextTmp , "R4 = %.2X", CPU->ReadD( _R4_ + Rbank ) ); + gtk_clist_set_text( GTK_CLIST( regclist ), row++, 0, TextTmp ); + sprintf( TextTmp , "R5 = %.2X", CPU->ReadD( _R5_ + Rbank ) ); + gtk_clist_set_text( GTK_CLIST( regclist ), row++, 0, TextTmp ); + sprintf( TextTmp , "R6 = %.2X", CPU->ReadD( _R6_ + Rbank ) ); + gtk_clist_set_text( GTK_CLIST( regclist ), row++, 0, TextTmp ); + sprintf( TextTmp , "R7 = %.2X", CPU->ReadD( _R7_ + Rbank ) ); + gtk_clist_set_text( GTK_CLIST( regclist ), row++, 0, TextTmp ); + + gtk_clist_select_row(GTK_CLIST(regclist),0,0); + gtk_clist_thaw( GTK_CLIST( regclist ) ); +} diff --git a/src/RegWin.hpp b/src/RegWin.hpp new file mode 100644 index 0000000..cd43721 --- /dev/null +++ b/src/RegWin.hpp @@ -0,0 +1,26 @@ +#ifndef _REGWIN_HPP_ +#define _REGWIN_HPP_ + +#include +#include "CPU8051.hpp" +#include "GtkSizes.hpp" + +////////////////////////////////////////////////////////////////////////////// +// RegWin +// Implements a Registers Window in Gtk+ as an Object +////////////////////////////////////////////////////////////////////////////// +class RegWin { +public: + RegWin( GtkWidget *parentwin ); + ~RegWin( ); + + void Show( CPU8051 *CPU ); + +private: + GtkWidget *regwin; + GtkWidget *regclist; + + +}; + +#endif diff --git a/src/disasm.hpp b/src/disasm.hpp new file mode 100644 index 0000000..bd4460f --- /dev/null +++ b/src/disasm.hpp @@ -0,0 +1,211 @@ +#ifndef __DISASM_HPP_ +#define __DISASM_HPP_ +// Do not modify this file directly, it was created by Opcode2cpp.pl +// Any modification made directly on this file will be lost + + +// For all 256 opcodes, the value in this table gives the instruction type +// ex.: MOV, INC, CLR, CPL,... +// To know what is the instruction type, use the number as an offset in the InstTextTbl[] +static int InstTypesTbl[] = { + 0, 1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 10, 1, 11, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 14, 6, 15, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 18, 1, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 20, 6, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 22, 1, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 24, 6, 19, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 27, 1, 21, 28, 29, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 6, 26, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 19, 1, 26, 4, 31, 32, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 21, 6, 33, 33, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 35, 1, 36, 36, 37, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, + 39, 6, 40, 40, 41, 42, 43, 43, 42, 42, 42, 42, 42, 42, 42, 42, + 44, 1, 44, 44, 36, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 44, 6, 44, 44, 33, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26 +}; + + +// Size(in bytes) of each instruction (offset in table is instruction opcode) +static int InstSizesTbl[] = { + 1, 2, 3, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 3, 2, 3, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 3, 2, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 3, 2, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 1, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 1, 1, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 3, 2, 2, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 1, 1, 3, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +}; + + +// List of instructions types referenced by InstTypesTbl[] +#define InstTextTblLength 45 +static char *InstTextTbl[] = { + "NOP", + "AJMP", + "LJMP", + "RR", + "INC", + "JBC", + "ACALL", + "LCALL", + "RRC", + "DEC", + "JB", + "RET", + "RL", + "ADD", + "JNB", + "RETI", + "RLC", + "ADDC", + "JC", + "ORL", + "JNC", + "ANL", + "JZ", + "XRL", + "JNZ", + "JMP", + "MOV", + "SJMP", + "MOVC", + "DIV", + "SUBB", + "MUL", + "INVALID", + "CPL", + "CJNE", + "PUSH", + "CLR", + "SWAP", + "XCH", + "POP", + "SETB", + "DA", + "DJNZ", + "XCHD", + "MOVX" +}; + + +// Table describing all arguments types of an instruction +// The table is indexed InstArgTbl[ opcode * 4] +// InstArgTbl[opcode*4 + 1] gives the number of arguments the instruction has +// InstArgTbl[opcode*4 + i] for i=1,2 and 3 give the type of each argument +// for most instructions, the 3rd argument isn't used +// the argument type is referecing to ArgsTextTbl[] +#define InstArgTblLength 256 +static int InstArgTbl[] = { + 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 2, 0, 0, + 1, 2, 0, 0, 1, 3, 0, 0, 1, 4, 0, 0, 1, 5, 0, 0, + 1, 6, 0, 0, 1, 7, 0, 0, 1, 8, 0, 0, 1, 9, 0, 0, + 1, 10, 0, 0, 1, 11, 0, 0, 1, 12, 0, 0, 1, 13, 0, 0, + 2, 14, 15, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 2, 0, 0, + 1, 2, 0, 0, 1, 3, 0, 0, 1, 4, 0, 0, 1, 5, 0, 0, + 1, 6, 0, 0, 1, 7, 0, 0, 1, 8, 0, 0, 1, 9, 0, 0, + 1, 10, 0, 0, 1, 11, 0, 0, 1, 12, 0, 0, 1, 13, 0, 0, + 2, 14, 15, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, + 2, 2, 16, 0, 2, 2, 3, 0, 2, 2, 4, 0, 2, 2, 5, 0, + 2, 2, 6, 0, 2, 2, 7, 0, 2, 2, 8, 0, 2, 2, 9, 0, + 2, 2, 10, 0, 2, 2, 11, 0, 2, 2, 12, 0, 2, 2, 13, 0, + 2, 14, 15, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, + 2, 2, 16, 0, 2, 2, 3, 0, 2, 2, 4, 0, 2, 2, 5, 0, + 2, 2, 6, 0, 2, 2, 7, 0, 2, 2, 8, 0, 2, 2, 9, 0, + 2, 2, 10, 0, 2, 2, 11, 0, 2, 2, 12, 0, 2, 2, 13, 0, + 1, 15, 0, 0, 1, 0, 0, 0, 2, 3, 2, 0, 2, 3, 16, 0, + 2, 2, 16, 0, 2, 2, 3, 0, 2, 2, 4, 0, 2, 2, 5, 0, + 2, 2, 6, 0, 2, 2, 7, 0, 2, 2, 8, 0, 2, 2, 9, 0, + 2, 2, 10, 0, 2, 2, 11, 0, 2, 2, 12, 0, 2, 2, 13, 0, + 1, 15, 0, 0, 1, 0, 0, 0, 2, 3, 2, 0, 2, 3, 16, 0, + 2, 2, 16, 0, 2, 2, 3, 0, 2, 2, 4, 0, 2, 2, 5, 0, + 2, 2, 6, 0, 2, 2, 7, 0, 2, 2, 8, 0, 2, 2, 9, 0, + 2, 2, 10, 0, 2, 2, 11, 0, 2, 2, 12, 0, 2, 2, 13, 0, + 1, 15, 0, 0, 1, 0, 0, 0, 2, 3, 2, 0, 2, 3, 16, 0, + 2, 2, 16, 0, 2, 2, 3, 0, 2, 2, 4, 0, 2, 2, 5, 0, + 2, 2, 6, 0, 2, 2, 7, 0, 2, 2, 8, 0, 2, 2, 9, 0, + 2, 2, 10, 0, 2, 2, 11, 0, 2, 2, 12, 0, 2, 2, 13, 0, + 1, 15, 0, 0, 1, 0, 0, 0, 2, 17, 14, 0, 1, 18, 0, 0, + 2, 2, 16, 0, 2, 3, 16, 0, 2, 4, 16, 0, 2, 5, 16, 0, + 2, 6, 16, 0, 2, 7, 16, 0, 2, 8, 16, 0, 2, 9, 16, 0, + 2, 10, 16, 0, 2, 11, 16, 0, 2, 12, 16, 0, 2, 13, 16, 0, + 1, 15, 0, 0, 1, 0, 0, 0, 2, 17, 14, 0, 2, 2, 19, 0, + 1, 20, 0, 0, 2, 3, 3, 0, 2, 3, 4, 0, 2, 3, 5, 0, + 2, 3, 6, 0, 2, 3, 7, 0, 2, 3, 8, 0, 2, 3, 9, 0, + 2, 3, 10, 0, 2, 3, 11, 0, 2, 3, 12, 0, 2, 3, 13, 0, + 2, 21, 22, 0, 1, 0, 0, 0, 2, 14, 17, 0, 2, 2, 18, 0, + 2, 2, 16, 0, 2, 2, 3, 0, 2, 2, 4, 0, 2, 2, 5, 0, + 2, 2, 6, 0, 2, 2, 7, 0, 2, 2, 8, 0, 2, 2, 9, 0, + 2, 2, 10, 0, 2, 2, 11, 0, 2, 2, 12, 0, 2, 2, 13, 0, + 2, 17, 23, 0, 1, 0, 0, 0, 2, 17, 14, 0, 1, 21, 0, 0, + 1, 20, 0, 0, 0, 0, 0, 0, 2, 4, 3, 0, 2, 5, 3, 0, + 2, 6, 3, 0, 2, 7, 3, 0, 2, 8, 3, 0, 2, 9, 3, 0, + 2, 10, 3, 0, 2, 11, 3, 0, 2, 12, 3, 0, 2, 13, 3, 0, + 2, 17, 23, 0, 1, 0, 0, 0, 1, 14, 0, 0, 1, 17, 0, 0, + 3, 2, 16, 15, 3, 2, 3, 15, 3, 4, 16, 15, 3, 5, 16, 15, + 3, 6, 16, 15, 3, 7, 16, 15, 3, 8, 16, 15, 3, 9, 16, 15, + 3, 10, 16, 15, 3, 11, 16, 15, 3, 12, 16, 15, 3, 13, 16, 15, + 1, 3, 0, 0, 1, 0, 0, 0, 1, 14, 0, 0, 1, 17, 0, 0, + 1, 2, 0, 0, 2, 2, 3, 0, 2, 2, 4, 0, 2, 2, 5, 0, + 2, 2, 6, 0, 2, 2, 7, 0, 2, 2, 8, 0, 2, 2, 9, 0, + 2, 2, 10, 0, 2, 2, 11, 0, 2, 2, 12, 0, 2, 2, 13, 0, + 1, 3, 0, 0, 1, 0, 0, 0, 1, 14, 0, 0, 1, 17, 0, 0, + 1, 2, 0, 0, 2, 3, 15, 0, 2, 2, 4, 0, 2, 2, 5, 0, + 2, 6, 15, 0, 2, 7, 15, 0, 2, 8, 15, 0, 2, 9, 15, 0, + 2, 10, 15, 0, 2, 11, 15, 0, 2, 12, 15, 0, 2, 13, 15, 0, + 2, 2, 24, 0, 1, 0, 0, 0, 2, 2, 4, 0, 2, 2, 5, 0, + 1, 2, 0, 0, 2, 2, 3, 0, 2, 2, 4, 0, 2, 2, 5, 0, + 2, 2, 6, 0, 2, 2, 7, 0, 2, 2, 8, 0, 2, 2, 9, 0, + 2, 2, 10, 0, 2, 2, 11, 0, 2, 2, 12, 0, 2, 2, 13, 0, + 2, 24, 2, 0, 1, 0, 0, 0, 2, 4, 2, 0, 2, 5, 2, 0, + 1, 2, 0, 0, 2, 3, 2, 0, 2, 4, 2, 0, 2, 5, 2, 0, + 2, 6, 2, 0, 2, 7, 2, 0, 2, 8, 2, 0, 2, 9, 2, 0, + 2, 10, 2, 0, 2, 11, 2, 0, 2, 12, 2, 0, 2, 13, 2, 0 +}; + + +// List all types of arguments available to instructions +// Referenced by InstArgsTbl[] +#define ArgsTextTblLength 25 +static char *ArgsTextTbl[] = { + "addr11", + "addr16", + "A", + "direct", + "@R0", + "@R1", + "R0", + "R1", + "R2", + "R3", + "R4", + "R5", + "R6", + "R7", + "bitaddr", + "reladdr", + "#data", + "C", + "@A+DPTR", + "@A+PC", + "AB", + "DPTR", + "#data16", + "/bitaddr", + "@DPTR" +}; + + + + +#endif diff --git a/src/exceptions.hpp b/src/exceptions.hpp new file mode 100644 index 0000000..5aa1af7 --- /dev/null +++ b/src/exceptions.hpp @@ -0,0 +1,19 @@ +// Exceptions.hpp +// Gestion des erreurs pour le programme d'emulation du 8051. + +#ifndef _EXCEPTION_HPP_ +#define _EXCEPTION_HPP_ + +class ShowOptions { /* ... */ }; +class FinishedLoading { /* ... */ }; +class ErrorOpeningFile { /* ... */ }; +class ErrorHexFileFormat { /* ... */ }; +class SyntaxError { /* ... */ }; +class InvalidAddress { /* ... */ }; +class MissingParameter { /* ... */ }; +class InvalidParameter { /* ... */ }; +class InvalidRegister { /* ... */ }; +class TooMuchParameters { /* ... */ }; +class ResetRequest { /* ... */ }; + +#endif diff --git a/src/opcodes.lst b/src/opcodes.lst new file mode 100644 index 0000000..1494258 --- /dev/null +++ b/src/opcodes.lst @@ -0,0 +1,258 @@ +Opcode(bin) Opcode Instruction Bytes Cycles +-------------------------------------------------------------- +00000000 00 NOP 1 1 +00000001 01 AJMP addr11 2 2 +00000010 02 LJMP addr16 3 2 +00000011 03 RR A 1 1 +00000100 04 INC A 1 1 +00000101 05 INC direct 2 1 +00000110 06 INC @R0 1 1 +00000111 07 INC @R1 1 1 +00001000 08 INC R0 1 1 +00001001 09 INC R1 1 1 +00001010 0A INC R2 1 1 +00001011 0B INC R3 1 1 +00001100 0C INC R4 1 1 +00001101 0D INC R5 1 1 +00001110 0E INC R6 1 1 +00001111 0F INC R7 1 1 +00010000 10 JBC bitaddr,reladdr 3 2 +00010001 11 ACALL addr11 2 2 +00010010 12 LCALL addr16 3 2 +00010011 13 RRC A 1 1 +00010100 14 DEC A 1 1 +00010101 15 DEC direct 2 1 +00010110 16 DEC @R0 1 1 +00010111 17 DEC @R1 1 1 +00011000 18 DEC R0 1 1 +00011001 19 DEC R1 1 1 +00011010 1A DEC R2 1 1 +00011011 1B DEC R3 1 1 +00011100 1C DEC R4 1 1 +00011101 1D DEC R5 1 1 +00011110 1E DEC R6 1 1 +00011111 1F DEC R7 1 1 +00100000 20 JB bitaddr,reladdr 3 2 +00100001 21 AJMP addr11 2 2 +00100010 22 RET 1 2 +00100011 23 RL A 1 1 +00100100 24 ADD A,#data 2 1 +00100101 25 ADD A,direct 2 1 +00100110 26 ADD A,@R0 1 1 +00100111 27 ADD A,@R1 1 1 +00101000 28 ADD A,R0 1 1 +00101001 29 ADD A,R1 1 1 +00101010 2A ADD A,R2 1 1 +00101011 2B ADD A,R3 1 1 +00101100 2C ADD A,R4 1 1 +00101101 2D ADD A,R5 1 1 +00101110 2E ADD A,R6 1 1 +00101111 2F ADD A,R7 1 1 +00110000 30 JNB bitaddr,reladdr 3 2 +00110001 31 ACALL addr11 2 2 +00110010 32 RETI 1 2 +00110011 33 RLC A 1 1 +00110100 34 ADDC A,#data 2 1 +00110101 35 ADDC A,direct 2 1 +00110110 36 ADDC A,@R0 1 1 +00110111 37 ADDC A,@R1 1 1 +00111000 38 ADDC A,R0 1 1 +00111001 39 ADDC A,R1 1 1 +00111010 3A ADDC A,R2 1 1 +00111011 3B ADDC A,R3 1 1 +00111100 3C ADDC A,R4 1 1 +00111101 3D ADDC A,R5 1 1 +00111110 3E ADDC A,R6 1 1 +00111111 3F ADDC A,R7 1 1 +01000000 40 JC reladdr 2 2 +01000001 41 AJMP addr11 2 2 +01000010 42 ORL direct,A 2 1 +01000011 43 ORL direct,#data 3 2 +01000100 44 ORL A,#data 2 1 +01000101 45 ORL A,direct 2 1 +01000110 46 ORL A,@R0 1 1 +01000111 47 ORL A,@R1 1 1 +01001000 48 ORL A,R0 1 1 +01001001 49 ORL A,R1 1 1 +01001010 4A ORL A,R2 1 1 +01001011 4B ORL A,R3 1 1 +01001100 4C ORL A,R4 1 1 +01001101 4D ORL A,R5 1 1 +01001110 4E ORL A,R6 1 1 +01001111 4F ORL A,R7 1 1 +01010000 50 JNC reladdr 2 2 +01010001 51 ACALL addr11 2 2 +01010010 52 ANL direct,A 2 1 +01010011 53 ANL direct,#data 3 2 +01010100 54 ANL A,#data 2 1 +01010101 55 ANL A,direct 2 1 +01010110 56 ANL A,@R0 1 1 +01010111 57 ANL A,@R1 1 1 +01011000 58 ANL A,R0 1 1 +01011001 59 ANL A,R1 1 1 +01011010 5A ANL A,R2 1 1 +01011011 5B ANL A,R3 1 1 +01011100 5C ANL A,R4 1 1 +01011101 5D ANL A,R5 1 1 +01011110 5E ANL A,R6 1 1 +01011111 5F ANL A,R7 1 1 +01100000 60 JZ reladdr 2 2 +01100001 61 AJMP addr11 2 2 +01100010 62 XRL direct,A 2 1 +01100011 63 XRL direct,#data 3 2 +01100100 64 XRL A,#data 2 1 +01100101 65 XRL A,direct 2 1 +01100110 66 XRL A,@R0 1 1 +01100111 67 XRL A,@R1 1 1 +01101000 68 XRL A,R0 1 1 +01101001 69 XRL A,R1 1 1 +01101010 6A XRL A,R2 1 1 +01101011 6B XRL A,R3 1 1 +01101100 6C XRL A,R4 1 1 +01101101 6D XRL A,R5 1 1 +01101110 6E XRL A,R6 1 1 +01101111 6F XRL A,R7 1 1 +01110000 70 JNZ reladdr 2 2 +01110001 71 ACALL addr11 2 2 +01110010 72 ORL C,bitaddr 2 2 +01110011 73 JMP @A+DPTR 1 2 +01110100 74 MOV A,#data 2 1 +01110101 75 MOV direct,#data 3 2 +01110110 76 MOV @R0,#data 2 1 +01110111 77 MOV @R1,#data 2 1 +01111000 78 MOV R0,#data 2 1 +01111001 79 MOV R1,#data 2 1 +01111010 7A MOV R2,#data 2 1 +01111011 7B MOV R3,#data 2 1 +01111100 7C MOV R4,#data 2 1 +01111101 7D MOV R5,#data 2 1 +01111110 7E MOV R6,#data 2 1 +01111111 7F MOV R7,#data 2 1 +10000000 80 SJMP reladdr 2 2 +10000001 81 AJMP addr11 2 2 +10000010 82 ANL C,bitaddr 2 1 +10000011 83 MOVC A,@A+PC 1 1 +10000100 84 DIV AB 1 4 +10000101 85 MOV direct,direct 3 1 +10000110 86 MOV direct,@R0 2 2 +10000111 87 MOV direct,@R1 2 2 +10001000 88 MOV direct,R0 2 2 +10001001 89 MOV direct,R1 2 2 +10001010 8A MOV direct,R2 2 2 +10001011 8B MOV direct,R3 2 2 +10001100 8C MOV direct,R4 2 2 +10001101 8D MOV direct,R5 2 2 +10001110 8E MOV direct,R6 2 2 +10001111 8F MOV direct,R7 2 2 +10010000 90 MOV DPTR,#data16 3 2 +10010001 91 ACALL addr11 2 2 +10010010 92 MOV bitaddr,C 2 2 +10010011 93 MOVC A,@A+DPTR 1 2 +10010100 94 SUBB A,#data 2 1 +10010101 95 SUBB A,direct 2 1 +10010110 96 SUBB A,@R0 1 1 +10010111 97 SUBB A,@R1 1 1 +10011000 98 SUBB A,R0 1 1 +10011001 99 SUBB A,R1 1 1 +10011010 9A SUBB A,R2 1 1 +10011011 9B SUBB A,R3 1 1 +10011100 9C SUBB A,R4 1 1 +10011101 9D SUBB A,R5 1 1 +10011110 9E SUBB A,R6 1 1 +10011111 9F SUBB A,R7 1 1 +10100000 A0 ORL C,/bitaddr 2 1 +10100001 A1 AJMP addr11 2 2 +10100010 A2 MOV C,bitaddr 2 1 +10100011 A3 INC DPTR 1 2 +10100100 A4 MUL AB 1 4 +10100101 A5 INVALID 1 1 +10100110 A6 MOV @R0,direct 2 2 +10100111 A7 MOV @R1,direct 2 2 +10101000 A8 MOV R0,direct 2 2 +10101001 A9 MOV R1,direct 2 2 +10101010 AA MOV R2,direct 2 2 +10101011 AB MOV R3,direct 2 2 +10101100 AC MOV R4,direct 2 2 +10101101 AD MOV R5,direct 2 2 +10101110 AE MOV R6,direct 2 2 +10101111 AF MOV R7,direct 2 2 +10110000 B0 ANL C,/bitaddr 2 1 +10110001 B1 ACALL addr11 2 2 +10110010 B2 CPL bitaddr 2 1 +10110011 B3 CPL C 1 1 +10110100 B4 CJNE A,#data,reladdr 3 2 +10110101 B5 CJNE A,direct,reladdr 3 2 +10110110 B6 CJNE @R0,#data,reladdr 3 2 +10110111 B7 CJNE @R1,#data,reladdr 3 2 +10111000 B8 CJNE R0,#data,reladdr 3 2 +10111001 B9 CJNE R1,#data,reladdr 3 2 +10111010 BA CJNE R2,#data,reladdr 3 2 +10111011 BB CJNE R3,#data,reladdr 3 2 +10111100 BC CJNE R4,#data,reladdr 3 2 +10111101 BD CJNE R5,#data,reladdr 3 2 +10111110 BE CJNE R6,#data,reladdr 3 2 +10111111 BF CJNE R7,#data,reladdr 3 2 +11000000 C0 PUSH direct 2 2 +11000001 C1 AJMP addr11 2 2 +11000010 C2 CLR bitaddr 2 1 +11000011 C3 CLR C 1 1 +11000100 C4 SWAP A 1 1 +11000101 C5 XCH A,direct 2 1 +11000110 C6 XCH A,@R0 1 1 +11000111 C7 XCH A,@R1 1 1 +11001000 C8 XCH A,R0 1 1 +11001001 C9 XCH A,R1 1 1 +11001010 CA XCH A,R2 1 1 +11001011 CB XCH A,R3 1 1 +11001100 CC XCH A,R4 1 1 +11001101 CD XCH A,R5 1 1 +11001110 CE XCH A,R6 1 1 +11001111 CF XCH A,R7 1 1 +11010000 D0 POP direct 2 2 +11010001 D1 ACALL addr11 2 2 +11010010 D2 SETB bitaddr 2 1 +11010011 D3 SETB C 1 1 +11010100 D4 DA A 1 1 +11010101 D5 DJNZ direct,reladdr 3 2 +11010110 D6 XCHD A,@R0 1 1 +11010111 D7 XCHD A,@R1 1 1 +11011000 D8 DJNZ R0,reladdr 2 2 +11011001 D9 DJNZ R1,reladdr 2 2 +11011010 DA DJNZ R2,reladdr 2 2 +11011011 DB DJNZ R3,reladdr 2 2 +11011100 DC DJNZ R4,reladdr 2 2 +11011101 DD DJNZ R5,reladdr 2 2 +11011110 DE DJNZ R6,reladdr 2 2 +11011111 DF DJNZ R7,reladdr 2 2 +11100000 E0 MOVX A,@DPTR 1 2 +11100001 E1 AJMP addr11 2 2 +11100010 E2 MOVX A,@R0 1 2 +11100011 E3 MOVX A,@R1 1 2 +11100100 E4 CLR A 1 1 +11100101 E5 MOV A,direct 2 1 +11100110 E6 MOV A,@R0 1 1 +11100111 E7 MOV A,@R1 1 1 +11101000 E8 MOV A,R0 1 1 +11101001 E9 MOV A,R1 1 1 +11101010 EA MOV A,R2 1 1 +11101011 EB MOV A,R3 1 1 +11101100 EC MOV A,R4 1 1 +11101101 ED MOV A,R5 1 1 +11101110 EE MOV A,R6 1 1 +11101111 EF MOV A,R7 1 1 +11110000 F0 MOVX @DPTR,A 1 2 +11110001 F1 ACALL addr11 2 2 +11110010 F2 MOVX @R0,A 1 2 +11110011 F3 MOVX @R1,A 1 2 +11110100 F4 CPL A 1 1 +11110101 F5 MOV direct,A 2 1 +11110110 F6 MOV @R0,A 1 1 +11110111 F7 MOV @R1,A 1 1 +11111000 F8 MOV R0,A 1 1 +11111001 F9 MOV R1,A 1 1 +11111010 FA MOV R2,A 1 1 +11111011 FB MOV R3,A 1 1 +11111100 FC MOV R4,A 1 1 +11111101 FD MOV R5,A 1 1 +11111110 FE MOV R6,A 1 1 +11111111 FF MOV R7,A 1 1 diff --git a/test_files/siae1.hex b/test_files/siae1.hex new file mode 100644 index 0000000..7324c56 --- /dev/null +++ b/test_files/siae1.hex @@ -0,0 +1,115 @@ +:0600000002003302003390 +:03000B00020033BD +:03001300020033B5 +:03001B00020033AD +:03002300020033A5 +:03002B000200339D +:100033007581801202D312024375540075550085F1 +:100043004356854457755BC61204C8120493740360 +:100053002557F543855A56855B57755B0A1204C8C5 +:10006300120493E5574430F55E75F000E543120240 +:10007300DC85514F85525085535175522E855E5301 +:1000830074501203067404120306E54F120306E5C7 +:1000930050120306E551120306E552120306E55317 +:1000A300120306745A12030675300075315D7532FA +:1000B300C01204E78534F0E5351202DC74501203F4 +:1000C300067401120306E54F120306E550120306F8 +:1000D300E551120306E552120306E55312030674B3 +:1000E3005A12030675F000E5361202DC745012034F +:1000F300067405120306E551120306E552120306C0 +:10010300E553120306745A12030675F000E537121D +:1001130002DC74501203067406120306E55112033F +:1001230006E552120306E553120306745A12030638 +:10013300E53875F00584C5F0C3334430F55FC5F089 +:1001430075F0001202DC85525085535175522E858D +:100153005F5374501203067408120306E55012032A +:1001630006E551120306E552120306E55312030690 +:10017300745A12030675540075550085415685421D +:1001830057755B641204C87554001204938556F0C6 +:10019300E5571202DC74501203067402120306E5DB +:1001A30051120306E552120306E553120306745A6D +:1001B300120306755400755500853B56853C5775EB +:1001C3005B0F1204C812049385575C855A56855BEE +:1001D30057755B641204C81204938556F0E55712F1 +:1001E30002DC85525D85535E75F000E55C1202DC2E +:1001F30085524F85535075512E855D52855E5374DC +:10020300501203067407120306E54F120306E55066 +:10021300120306E551120306E552120306E55312D3 +:100223000306745A12030674201203060139756219 +:1002330016740075F000D5F0FDD5E0F7D562F22213 +:10024300783B7900E9120255A64E08A64D0809B974 +:1002530008F2D2B3C2B1C2B300D2B3C2B6C2B300C2 +:10026300D2B3F580C2B300D2B3D2B6C2B300D2B315 +:10027300D2B1C2B31202CA7580FFD2B3C2B1C2B344 +:1002830000D2B3C2B7C2B30085804DD2B3D2B7C2D6 +:10029300B300D2B3D2B1C2B300D2B3D2B2C2B300AD +:1002A300D2B3C2B1C2B300D2B3C2B7C2B300858066 +:1002B3004E00D2B3D2B7C2B300D2B3D2B1C2B300ED +:1002C300D2B3C2B2C2B322D2B300C2B330B0F822A7 +:1002D30075D54475B0F3513122C00078537554007D +:1002E30075550085F056F557755800755900755AC0 +:1002F30000755B0A120314E55B4430F618B84EE848 +:10030300D00022F586B290E5AA53E08060F9E58635 +:1003130022C004C003C002C001C0007504207503DD +:100323000075020075010075000012038F1203A50A +:100333004022C3E5039558403A7019C3E502955925 +:1003430040317010C3E501955A40287007C3E5009A +:10035300955B401FC3E500955BF500E501955AF5F4 +:1003630001E5029559F502E5039558F503E557D2E2 +:10037300E0F557DCB585035885025985015A850098 +:100383005BD000D001D002D003D00422C3E55733A1 +:10039300F557E55633F556E55533F555E55433F53D +:1003A3005422E50033F500E50133F501E50233F5A9 +:1003B30002E50333F50322C002C001C00075021B2E +:1003C30075010075000012040312041D4010C3E5FB +:1003D30001955A401C7007C3E500955B4013C3E5C4 +:1003E30000955BF500E501955AF501E557D2E0F577 +:1003F30057DAD385015A85005BD000D001D00222A1 +:10040300C3E55733F557E55633F556E55533F555FB +:10041300E5543392E35407F55422E50033F500E540 +:100423000133F50122C002C001C000750216750137 +:10043300007500001204711204844010C3E5019595 +:100443005A401C7007C3E500955B4013C3E5009554 +:100453005BF500E501955AF501E557D2E0F557DA6A +:10046300D385015A85005BD000D001D00222C3E5B9 +:100473005733F557E55633F556E55533F55592E6BB +:1004830022E50033F500E5013392E6543FF50122FE +:1004930085575B85565A535A0F1204B81204B81283 +:1004A30004B81204B853540F8556578555568554CE +:1004B3005575540022E55413F554E55513F555E5E8 +:1004C3005613F55622E556855BF0A4F55685F0558F +:1004D300E557855BF0A4F557C5F02556F556E43589 +:1004E30055F555221205751205981205B5E53654D2 +:1004F300F0C4C5F0E53754F025F0F5F01205DAF84D +:10050300E5F0240130D605E8F90205131205DAF9FE +:10051300E5F024105007E8FAE9FB020536F5F0127E +:1005230005DAFAE5F0240130D605EAFB02053612B6 +:1005330005DAFB88F0E9AC36120553F88AF0EBAC28 +:1005430036120553FA88F0EAAC37120553F5382210 +:10055300C0F0C223C395F05005F42401D223F5F073 +:10056300EC540FA454F0C4302303F42401D0F02539 +:10057300F02275540775552775560E755700E530EB +:10058300B4000B85315A85325B71BA0205918556E9 +:100593003485573522C3E5359490F556E5349401F7 +:1005A300F555755700C3755A25755B809128855796 +:1005B3003622755400755500C3E54394285001E471 +:1005C300F556755700755800755900755A00755BD7 +:1005D300A071148557372224E8F58274053400F599 +:1005E3008374009322111123465F5F666666666615 +:1005F3006666585858111123465F5F6666666666DD +:100603006666585858111123465F5F6666666666CC +:100613006666585858111123465F5F6666666666BC +:100623006666585858111123465F5F6666666666AC +:100633006666585858111123465F5F66666666669C +:100643006666585858111123465F5F66666666668C +:100653006666585858111123465B5B626262626298 +:1006630062625454541111234651515858585858E2 +:100673005858585858111123464A4A51515151510B +:10068300515151515111111C3846464A4A4A4A4A5E +:100693004A4A4A4A4A11111C343F3F4343434343A6 +:1006A300434343434311111C3438383C3C3C3C3CEA +:1006B3003C3C3C3C3C11111C2A2D2D313131313154 +:1006C300313131313111111C3438383C3C3C3C3C24 +:1006D3003C3C3C3C3C11111C2A2D2D313131313134 +:0506E30031313131311D +:00000001FF diff --git a/test_files/test.hex b/test_files/test.hex new file mode 100644 index 0000000..7a42308 --- /dev/null +++ b/test_files/test.hex @@ -0,0 +1,13 @@ +:03000000020033C8 +:1000330075818075D54475A000C290E4F500E50094 +:1000430012007DF586D29005A07400D5E0FDC29024 +:10005300E5AA53E08060F9E5861200690500C3E56F +:1000630000945040D92222752005740075F000D504 +:10007300F0FDD5E0F7D520F20022248BF582740041 +:100083003400F5837400932252504D3A31303234A8 +:1000930035204D41503A313033204D41543A3131BE +:1000A30030204241543A31322E3420202020202067 +:1000B3000D0A0A45474F3A31342E36202054505307 +:1000C3003A31303020414E473A33302020434C54AC +:0B00D3003A313038202020202020206F +:00000001FF diff --git a/test_files/timer.asm b/test_files/timer.asm new file mode 100644 index 0000000..aac4885 --- /dev/null +++ b/test_files/timer.asm @@ -0,0 +1,179 @@ +;******************************************************************************* +;* Système d'Injection et d'Allumage Électronique * +;* Version : 01 * +;* Auteur : Hugo Villeneuve * +;* * +;* 10 mars 1999 * +;******************************************************************************* + + $MOD52 ; Micro-contrôleur Atmel AT89S8252 + + +;******************************************************************************* +;* Définition des constantes * +;******************************************************************************* + +TOS EQU 60h ; Adresse du dessus de la pile. +CR EQU 0Dh ; Code ASCII pour un retour de chariot. +LF EQU 0Ah ; Code ASCII pour un changement de ligne + + +;******************************************************************************* +;* Définition des variables * +;******************************************************************************* + BSEG + ORG 20h +C_FLAG: DBIT 1 +Z_FLAG: DBIT 2 +N_FLAG: DBIT 3 ; Utilisé par la sous-routine MULT8_16 +SIGNE: DBIT 4 ; Utilisé pour l'interpolation. + + DSEG + ORG 30h +PERIODE2: DS 1 ; Période pour une rotation du vilebrequin, sur 24 bits. +PERIODE1: DS 1 +PERIODE0: DS 1 +POSITION_VILB: DS 1 ; Renseignement sur la position actuelle du vilebrequin (zones 0,1 ou 2). +VITESSE_RPM: DS 2 ; Vitesse de rotation du moteur en RPM. +INDEX_RPM: DS 1 ; Index de 8 bits pour l'adressage des colonnes de la table d'allumage. +INDEX_MAP: DS 1 ; Index de 8 bits pour l'adressage des lignes de la table d'allumage. +ANGLE: DS 1 ; Angle d'allumage calculé à partir de la table. +BAT: DS 2 ; Voltage de la batterie. +MAT: DS 2 ; Manifold Air Temperature. +CLT: DS 2 ; Coolant Temperature. +TPS: DS 2 ; Throttle Position Sensor. +MAP: DS 2 ; Manifold Absolute Pressure. +EGO: DS 2 ; Exhaust Gas-Oxygen Sensor. +CAN6: DS 2 ; Canal #6 du convertisseur AN. +CAN7: DS 2 ; Canal #7 du convertisseur AN. +GAMMA: DS 2 ; Rapport Air/Carburant. +LSB_CAN: DS 1 ; Octet de poids faible de la conversion Analogique-Numérique. +MSB_CAN: DS 1 ; Octet de poids fort de la conversion Analogique-Numérique. +NOMBRE4: DS 1 ; Stockage des codes ASCII pour les conversions. +NOMBRE3: DS 1 +NOMBRE2: DS 1 +NOMBRE1: DS 1 +NOMBRE0: DS 1 +C3: DS 1 ; Accumulateur C de 32 bits pour les calculs mathématiques. +C2: DS 1 +C1: DS 1 +C0: DS 1 +D3: DS 1 ; Accumulateur D de 32 bits pour les calculs mathématiques. +D2: DS 1 +D1: DS 1 +D0: DS 1 +TMP6: DS 1 ; Variables temporaires utilisées pour les calculs mathématiques. +TMP5: DS 1 ; FAIRE LE MÉNAGE VARIABLES NON UTILISEES!!! +TMP4: DS 1 +TMP3: DS 1 +TMP2: DS 1 +TMP1: DS 1 +TMP0: DS 1 +VAR0: DS 1 +VAR1: DS 1 +VAR2: DS 1 + + +;******************************************************************************* +;* Définition des régistres spécifiques au AT89S8252 * +;******************************************************************************* +SPCR DATA 0D5h ; SPCR - SPI Control Register +SPSR DATA 0AAh ; SPSR - SPI Status Register +SPIF EQU 10000000b ; Masque pour le drapeau SPI. +WCOL EQU 01000000b ; Masque pour le drapeau Write Collision. +SPDR DATA 086h ; SPDR - SPI Data Register + + +;******************************************************************************* +;* Vecteurs d'interruptions * +;******************************************************************************* + CSEG + + ORG 0000h ; Vecteur d'interruption du RESET. + JMP DEBUT + + ORG 0003h ; Vecteur pour l'interruption EXTERNE 0. + JMP VILEBREQUIN + + ORG 000Bh ; Vecteur pour l'interruption du TIMER 0. + JMP DEBUT + + ORG 0013h ; Vecteur pour l'interruption EXTERNE 1. + JMP DEBUT + + ORG 001Bh ; Vecteur pour l'interruption du TIMER 1. + JMP DEBUT + + ORG 0023h ; Vecteur pour l'interruption du Port série. + JMP DEBUT + + ORG 002Bh ; Vecteur pour l'interruption du TIMER 2. + JMP DEBUT + + +;******************************************************************************* +;* Début du programme principal * +;******************************************************************************* + ORG 0033h + +DEBUT: + MOV SP,#TOS ; Initialisation de la pile. + CALL INITIALISATION + ; il ne faut pas modifier la valeur de P1.0!!! + +ICI: + NOP + NOP + NOP + NOP + + JMP ICI + + +;******************************************************************************* +;* Délai * +;******************************************************************************* +DELAI: MOV TMP0,#016h ; Délai de 1/2 seconde. +B3: MOV A,#0 +B2: MOV B,#0 +B1: DJNZ B,B1 + DJNZ ACC,B2 + DJNZ TMP0,B3 + RET + + + +;******************************************************************************* +;* INTERRUPTION * +;******************************************************************************* +VILEBREQUIN: + RETI + + +;******************************************************************************* +;* Initialisation * +;******************************************************************************* +INITIALISATION: MOV SPCR,#01000100b ; Interruption SPI désactivée; + ; Activation du port SPI; + ; Ordre des transferts : MSB en premier; + ; Opération en mode escalve (SLAVE); + ; Polarité de l'horloge : niveau bas si inactif. + ; Phase de l'horloge : transfert sur front montant. + MOV TH0,#2 + MOV TL0,#55h + SETB TCON.4 ; Timer 0 ON. + SETB TCON.6 ; Timer 1 ON. + MOV TMOD,#00010001B ; Initialisation des timers 0 et 1 en timers de + ; 16 bits, incrémentés par l'horloge interne + ; Chaque timer est incrémenté tant que le bit correspondant de + ; TCON est à 1 (TCON.4 et TCON.6). + RET + + + + END + + + + + diff --git a/test_files/timer.hex b/test_files/timer.hex new file mode 100644 index 0000000..3fadd1b --- /dev/null +++ b/test_files/timer.hex @@ -0,0 +1,10 @@ +:0600000002003302005172 +:03000B00020033BD +:03001300020033B5 +:03001B00020033AD +:03002300020033A5 +:03002B000200339D +:100033007581601200520000000080FA756016742A +:100043000075F000D5F0FDD5E0F7D560F2223275EA +:10005300D544758C02758A55D28CD28E758911223E +:00000001FF -- 2.20.1