From: Hugo Villeneuve Date: Sat, 8 May 2004 02:56:47 +0000 (+0000) Subject: Initial import X-Git-Tag: v0.0.1 X-Git-Url: http://gitweb.hugovil.com/?a=commitdiff_plain;h=1c6cc28cf5317f2ee9fbc1a408bcaaef3b7378b3;p=emu8051.git Initial import --- 1c6cc28cf5317f2ee9fbc1a408bcaaef3b7378b3 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