Initial import

This commit is contained in:
Hugo Villeneuve
2004-05-08 02:56:47 +00:00
commit 1c6cc28cf5
46 changed files with 10803 additions and 0 deletions

0
AUTHORS Normal file
View File

340
COPYING Normal file
View File

@@ -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.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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.
<signature of Ty Coon>, 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.

492
ChangeLog Normal file
View File

@@ -0,0 +1,492 @@
------------------------------------------------------------------------------
2002/11/12 Hugo Villeneuve <hugovil@videotron.ca>
-Removed some warnings for GCC 3.2: replaced <fstream.h> by <fstream>
and <iostream.h> by <iostream>.
-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 <iostream>'
-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 <villen01@gel.ulaval.ca>
- 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 <villen01@gel.ulaval.ca>
- 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 <standr00@gel.ulaval.ca>
- 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 <standr00@gel.ulaval.ca>
- 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 <standr00@gel.ulaval.ca>
- 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 <villen01@gel.ulaval.ca>
-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 <standr00@gel.ulaval.ca>
- 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 <standr00@gel.ulaval.ca>
- 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 <villen01@gel.ulaval.ca>
- 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 <standr00@gel.ulaval.ca>
- 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 <fectea00@gel.ulaval.ca>
- Ajoute .h comme extension aux fichiers inclus, sinon ca ne
fonctionne pas a l'universite.
Pascal Fecteau <fectea00@gel.ulaval.ca>
Hugo Villeneuve <villen01@gel.ulaval.ca>
- Corrige une erreur dans les instructions AJMP addr11
------------------------------------------------------------------------------
99/03/28 Hugo Villeneuve <villen01@gel.ulaval.ca>
- 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 <villen01@gel.ulaval.ca>
- Correction d'un probleme avec l'instruction CJNE.
- Correction de bugs dans LoadHexFile (voir 99/03/22)
Jonathan St-Andre <standr00@gel.ulaval.ca>
- 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 <standr00@gel.ulaval.ca>
- 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 <standr00@gel.ulaval.ca>
- 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 <villen01@gel.ulaval.ca>
- 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 <villen01@gel.ulaval.ca>
- 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 <standr00@gel.ulaval.ca
- Fait le menage dans la fonction main
- Modifie Makefile.console et Makefile.gtk
- Rearrangement des fichiers pour limiter les impacts sur
tout le projet lors de modifications dans une partie et
pour accelerer la compilation (en modules).
- Creation de mainconsole.hpp + mainconsole.cpp
- Creation de maingtk.cpp + maingtk.hpp
- Creation de mainemu.cpp + mainemu.hpp
- Elimine fonctions.cpp.
- Elimination du 2e parametre a unasm. Desassemble
de nouveau 16 instructions.
- Ajustement du menu pour qu'il rentre dans la largeur
d'un terminal 80x25.
Jimmy Ringuette <ringue00@gel.ulaval.ca>
- Ajout des interruptions du port serie.
- Ajout du timer 2 (8052).
------------------------------------------------------------------------------
99/03/20 Hugo Villeneuve <villen01@gel.ulaval.ca>
- 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 <stdlib.h>
- 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 <standr00@gel.ulaval.ca>
- 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 <ringue00@gel.ulaval.ca>
- Les interruptions sont maintenant implementees. check_hardware() a
ete supprimee et Do_timers() est appelee directement de exec8051().
------------------------------------------------------------------------------
99/03/18 Hugo Villeneuve <villen01@gel.ulaval.ca>
- 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 <standr00@gel.ulaval.ca>
- 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 <villen01@gel.ulaval.ca
- Corrige les instructions LJMP et LCALL qui ne calculaient pas la
bonne adresse pour le PC. Toutes les autres instructions de
branchement sont probablement a revoir pour le meme probleme. Le
probleme etait cause par la syntaxe dans le fichier instructions.hpp
(lignes ou on retrouve addr16 = (pgm_mem[PC++] << 8)+pgm_mem[PC++] a
remplacer par addr16 = (pgm_mem[PC+1] << 8) + pgm_mem[PC+2] )
- Modifie la commande TRACE pour qu'on puisse lui passer une adresse
de depart comme parametre (main.cpp lignes 406-409) et modifie
en consequence ascii2hex pour qu'il ignore les espaces avant
l'adresse. (main.cpp ligne 133).
------------------------------------------------------------------------------
99/03/14 Pascal Fecteau <fectea00@gel.ulaval.ca>
- Correction de bugs relatifs a la compilation sur VC5.
Dont ajout de #include <string.h>.
------------------------------------------------------------------------------
99/03/13 Jimmy Ringuette <ringue00@gel.ulaval.ca>
- Ajout des timers dans cpu8051.cpp. Il faudrait tester a fond.
------------------------------------------------------------------------------
99/03/12 Jonathan St-Andre <standr00@gel.ulaval.ca>
- 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 <ringue00@gel.ulaval.ca>
- 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 <standr00@gel.ulaval.ca>
- Corrige un warning de compilation sous Solaris.
------------------------------------------------------------------------------
99/03/04 Jonathan St-Andre <standr00@gel.ulaval.ca>
- 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 <standr00@gel.ulaval.ca>
- 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 <standr00@gel.ulaval.ca>
- 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 <standr00@gel.ulaval.ca>
- 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 <standr00@gel.ulaval.ca>
- 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

229
INSTALL Normal file
View File

@@ -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.

25
Makefile.am Normal file
View File

@@ -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

0
NEWS Normal file
View File

0
README Normal file
View File

15
TODO Normal file
View File

@@ -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)

28
autogen.sh Executable file
View File

@@ -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

18
config/debug.m4 Normal file
View File

@@ -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 )
])

17
config/gtk2.m4 Normal file
View File

@@ -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 )
])

89
configure.in Normal file
View File

@@ -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.
---------------------------------------------------------------------------"

9
doc/Makefile.am Normal file
View File

@@ -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

123
doc/emu8051.man Normal file
View File

@@ -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-servername>
POP3 server name.
.TP
.BI "port " <pop3-portnumber>
POP3 port number (optional, default value is 110).
.TP
.BI "username " <pop3-username>
POP3 username.
.TP
.BI "password " <pop3-password>
POP3 password.
.TP
.BI "mailcheckdelay " <delay-in-minutes>
Mail check interval, in minutes (optional, default value is 1).
.TP
.BI "mailclient " <program>
The program to start when double-clicking on the mailbox image (optional).
.TP
.BI "enablebeep " <value>
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-to-audiofile>
Path and filename of the WAV or AU audio sound file to play when new message(s)
are detected (optional).
.TP
.BI "volume " <value>
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 <hugovil@videotron.ca>, based on
the WMPop3 program by Scott Holden <scotth@thezone.net>.
.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

54
pixmaps/reset.xpm Normal file
View File

@@ -0,0 +1,54 @@
/* XPM */
static char * reset_xpm[] = {
"48 48 3 1",
" c None",
". c #005A9C",
"+ c #FFFFFF",
"................................................",
"................................................",
"................................................",
"................................................",
"................................................",
"................................................",
"................................................",
"................................................",
"................................................",
"................................................",
"................................................",
"................................................",
"................................................",
"................................................",
"................................................",
"................................................",
"................................................",
"................................................",
"..+++++++..++++++++..+++++++.++++++++.++++++++..",
"..++++++++.++++++++.++++++++.++++++++.++++++++..",
"..++....++.++.......++.......++..........++.....",
"..++....++.++.......++.......++..........++.....",
"..++....++.++.......++.......++..........++.....",
"..++....++.+++++++..+++++++..+++++++.....++.....",
"..+++++++..+++++++...+++++++.+++++++.....++.....",
"..+++++++..++.............++.++..........++.....",
"..++....++.++.............++.++..........++.....",
"..++....++.++.............++.++..........++.....",
"..++....++.++++++++.++++++++.++++++++....++.....",
"..++....++.++++++++.+++++++..++++++++....++.....",
"................................................",
"................................................",
"................................................",
"................................................",
"................................................",
"................................................",
"................................................",
"................................................",
"................................................",
"................................................",
"................................................",
"................................................",
"................................................",
"................................................",
"................................................",
"................................................",
"................................................",
"................................................"};

55
pixmaps/run.xpm Normal file
View File

@@ -0,0 +1,55 @@
/* XPM */
static char * run_xpm[] = {
"48 48 4 1",
" c None",
". c #000000",
"+ c #008C6B",
"@ c #FFFFFF",
" ........... ",
" ................... ",
" ........+++++++........ ",
" ......+++++++++++++++...... ",
" .....+++++++++++++++++++..... ",
" .....+++++++++++++++++++++++..... ",
" .....+++++++++++++++++++++++++..... ",
" ....+++++++++++++++++++++++++++++.... ",
" ...+++++++++++++++++++++++++++++++... ",
" ...+++++++++++++++++++++++++++++++++... ",
" ....+++++++++++++++++++++++++++++++++.... ",
" ...+++++++++++++++++++++++++++++++++++... ",
" ...+++++++++++++++++++++++++++++++++++++... ",
" ...+++++++++++++++++++++++++++++++++++++... ",
" ...+++++++++++++++++++++++++++++++++++++++... ",
" ...+++++++++++++++++++++++++++++++++++++++... ",
" ..+++++++++++++++++++++++++++++++++++++++++.. ",
" ..++++++++@@@@@@@++@@++++@@+@@++++@@+++++++.. ",
"...++++++++@@@@@@@@+@@++++@@+@@@+++@@+++++++... ",
"...++++++++@@++++@@+@@++++@@+@@@+++@@+++++++... ",
"..+++++++++@@++++@@+@@++++@@+@@@@++@@++++++++.. ",
"..+++++++++@@++++@@+@@++++@@+@@@@++@@++++++++.. ",
"..+++++++++@@++++@@+@@++++@@+@@+@@+@@++++++++.. ",
"..+++++++++@@@@@@@++@@++++@@+@@+@@+@@++++++++.. ",
"..+++++++++@@@@@@@++@@++++@@+@@++@@@@++++++++.. ",
"..+++++++++@@++++@@+@@++++@@+@@++@@@@++++++++.. ",
"..+++++++++@@++++@@+@@++++@@+@@+++@@@++++++++.. ",
"...++++++++@@++++@@+@@@@@@@@+@@+++@@@+++++++... ",
"...++++++++@@++++@@++@@@@@@++@@++++@@+++++++... ",
" ..+++++++++++++++++++++++++++++++++++++++++.. ",
" ..+++++++++++++++++++++++++++++++++++++++++.. ",
" ...+++++++++++++++++++++++++++++++++++++++... ",
" ...+++++++++++++++++++++++++++++++++++++++... ",
" ...+++++++++++++++++++++++++++++++++++++... ",
" ...+++++++++++++++++++++++++++++++++++++... ",
" ...+++++++++++++++++++++++++++++++++++... ",
" ....+++++++++++++++++++++++++++++++++.... ",
" ...+++++++++++++++++++++++++++++++++... ",
" ...+++++++++++++++++++++++++++++++... ",
" ....+++++++++++++++++++++++++++++.... ",
" .....+++++++++++++++++++++++++..... ",
" .....+++++++++++++++++++++++..... ",
" .....+++++++++++++++++++..... ",
" ......+++++++++++++++...... ",
" ........+++++++........ ",
" ................... ",
" ........... ",
" "};

56
pixmaps/step.xpm Normal file
View File

@@ -0,0 +1,56 @@
/* XPM */
static char * step_xpm[] = {
"48 48 5 1",
" c None",
". c #FFDE08",
"+ c #000000",
"@ c #FFFFFF",
"# c #080800",
"..........++++++++++++............++++++++++++..",
"...........++++++++++++............++++++++++++.",
"............++++++++++++............++++++++++++",
"+............++++++++++++............+++++++++++",
"++............++++++++++++............++++++++++",
"+++............++++++++++++............+++++++++",
"++++............++++++++++++............++++++++",
"+++++............++++++++++++............+++++++",
"++++++............++++++++++++............++++++",
"+++++++............++++++++++++............+++++",
"++++++++............++++++++++++............++++",
"+++++++++............++++++++++++............+++",
"++++++++++............++++++++++++............++",
"+++++++++++............++++++++++++............+",
"++++++++++++............++++++++++++............",
".++++++++++++++++++++++++++++++++++++++++++++...",
"..+++++++++++++++++++++++++++++++++++++++++++...",
"...++++++++++++++++++++++++++++++++++++++++++...",
"....++++@@@@@@@+@@@@@@@@+@@@@@@@@+@@@@@@@++++...",
"....+++@@@@@@@@+@@@@@@@@+@@@@@@@@+@@@@@@@@+++...",
"....+++@@++++++++++@@++++@@+++++++@@++++@@+++...",
"....+++@@++++++++++@@++++@@+++++++@@++++@@+++...",
"....+++@@++++++++++@@++++@@+++++++@@++++@@+++...",
"....+++@@@@@@@+++++@@++++@@@@@@@++@@++++@@+++...",
"....++++@@@@@@@++++@@++++@@@@@@@++@@@@@@@@++++..",
"....+++++++++@@++++@@++++@@+++++++@@@@@@@++++++.",
"....+++++++++@@++++@@++++@@+++++++@@++++++++++++",
"+...+++++++++@@++++@@++++@@+++++++@@++++++++++++",
"++..+++@@@@@@@@++++@@++++@@@@@@@@+@@++++++++++++",
"+++.+++@@@@@@@+++++@@++++@@@@@@@@+@@++++++++++++",
"++++++++++++++++++++++++++++++++++++++++++++++++",
"++++++++++++++++++++++++++++++++++++++++++++++++",
"++++++++++++++++++++++++++++++++++++++++++++++++",
"+++++++............++++++++++++............+++++",
"++++++++............++++++++++++............++++",
"+++++++++............+#++++++++++............+++",
"++++++++++............++++++++++++............++",
"#++++++++++............++++++++++++............+",
"++++++++++++............++++++++++++............",
".+#++++++++++............+#++++++++++...........",
"..++++++++++++............+#++++++++++..........",
"...++++++++++++............++++++++++++.........",
"....++++++++++++............++++++++++++........",
".....+#++++++++++............+#++++++++++.......",
"......++++++++++++............++++++++++++......",
".......++++++++++++............++++++++++++.....",
"........+#++++++++++............++++++++++++....",
".........++++++++++++............+#++++++++++..."};

55
pixmaps/stop.xpm Normal file
View File

@@ -0,0 +1,55 @@
/* XPM */
static char * stop_xpm[] = {
"48 48 4 1",
" c None",
". c #000000",
"+ c #C60021",
"@ c #FFFFFF",
" .................... ",
" .++++++++++++++++++++. ",
" .++@@@@@@@@@@@@@@@@@@++. ",
" .++@@++++++++++++++++@@++. ",
" .++@@++++++++++++++++++@@++. ",
" .++@@++++++++++++++++++++@@++. ",
" .++@@++++++++++++++++++++++@@++. ",
" .++@@++++++++++++++++++++++++@@++. ",
" .++@@++++++++++++++++++++++++++@@++. ",
" .++@@++++++++++++++++++++++++++++@@++. ",
" .++@@++++++++++++++++++++++++++++++@@++. ",
" .++@@++++++++++++++++++++++++++++++++@@++. ",
" .++@@++++++++++++++++++++++++++++++++++@@++. ",
" .++@@++++++++++++++++++++++++++++++++++++@@++. ",
".++@@++++++++++++++++++++++++++++++++++++++@@++.",
".+@@++++++++++++++++++++++++++++++++++++++++@@+.",
".+@++++++++++++++++++++++++++++++++++++++++++@+.",
".+@++++++++++++++++++++++++++++++++++++++++++@+.",
".+@+++++@@@@@@@+@@@@@@@@++@@@@@@++@@@@@@@++++@+.",
".+@++++@@@@@@@@+@@@@@@@@++@@@@@@++@@@@@@@@+++@+.",
".+@++++@@++++++++++@@++++@@@++@@@+@@++++@@+++@+.",
".+@++++@@++++++++++@@++++@@++++@@+@@++++@@+++@+.",
".+@++++@@++++++++++@@++++@@++++@@+@@++++@@+++@+.",
".+@++++@@@@@@@+++++@@++++@@++++@@+@@++++@@+++@+.",
".+@+++++@@@@@@@++++@@++++@@++++@@+@@@@@@@@+++@+.",
".+@++++++++++@@++++@@++++@@++++@@+@@@@@@@++++@+.",
".+@++++++++++@@++++@@++++@@++++@@+@@+++++++++@+.",
".+@++++++++++@@++++@@++++@@@++@@@+@@+++++++++@+.",
".+@++++@@@@@@@@++++@@+++++@@@@@@++@@+++++++++@+.",
".+@++++@@@@@@@+++++@@+++++@@@@@@++@@+++++++++@+.",
".+@++++++++++++++++++++++++++++++++++++++++++@+.",
".+@++++++++++++++++++++++++++++++++++++++++++@+.",
".+@@++++++++++++++++++++++++++++++++++++++++@@+.",
".++@@++++++++++++++++++++++++++++++++++++++@@++.",
" .++@@++++++++++++++++++++++++++++++++++++@@++. ",
" .++@@++++++++++++++++++++++++++++++++++@@++. ",
" .++@@++++++++++++++++++++++++++++++++@@++. ",
" .++@@++++++++++++++++++++++++++++++@@++. ",
" .++@@++++++++++++++++++++++++++++@@++. ",
" .++@@++++++++++++++++++++++++++@@++. ",
" .++@@++++++++++++++++++++++++@@++. ",
" .++@@++++++++++++++++++++++@@++. ",
" .++@@++++++++++++++++++++@@++. ",
" .++@@++++++++++++++++++@@++. ",
" .++@@++++++++++++++++@@++. ",
" .++@@@@@@@@@@@@@@@@@@@+. ",
" .++++++++++++++++++++. ",
" .................... "};

644
src/CPU8051.cpp Normal file
View File

@@ -0,0 +1,644 @@
// CPU8051.cpp
#include <stdio.h>
#include <iostream>
#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"

62
src/CPU8051.hpp Normal file
View File

@@ -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

737
src/EmuConsole.cpp Normal file
View File

@@ -0,0 +1,737 @@
// EmuConsole.cpp
#include <stdio.h>
#include <iostream>
#include <fstream>
#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;
}

65
src/EmuConsole.hpp Normal file
View File

@@ -0,0 +1,65 @@
#ifndef _EMUCONSOLE_HPP_
#define _EMUCONSOLE_HPP_
#include "CPU8051.hpp"
#include <string>
#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

735
src/EmuGtk.cpp Normal file
View File

@@ -0,0 +1,735 @@
// EmuGtk.cpp
#include <iostream>
#include <stdio.h>
#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<64>\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 );
}
}

111
src/EmuGtk.hpp Normal file
View File

@@ -0,0 +1,111 @@
#ifndef _EMUGTK_HPP_
#define _EMUGTK_HPP_
#include <gtk/gtk.h>
#include <string>
#include <fstream>
#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

24
src/GtkSizes.hpp Normal file
View File

@@ -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

266
src/Inst_Def.hpp Normal file
View File

@@ -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

4208
src/Inst_Imp.cpp Normal file

File diff suppressed because it is too large Load Diff

59
src/Keyboard.hpp Normal file
View File

@@ -0,0 +1,59 @@
// Keyboard.hpp
#ifndef _KEYBOARD_HPP_
#define _KEYBOARD_HPP_
#include <termios.h>
#include <unistd.h>
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

37
src/Makefile.am Normal file
View File

@@ -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 $<

128
src/MemWin.cpp Normal file
View File

@@ -0,0 +1,128 @@
/* memwin.cpp */
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include "MemWin.hpp"
#include <stdio.h>
//////////////////////////////////////////////////////////////////////////////
// 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 ) );
}

29
src/MemWin.hpp Normal file
View File

@@ -0,0 +1,29 @@
#ifndef _MEMWIN_HPP_
#define _MEMWIN_HPP_
#include <gtk/gtk.h>
#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

51
src/Memory.cpp Normal file
View File

@@ -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;
}

24
src/Memory.hpp Normal file
View File

@@ -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

785
src/Opcode2cpp.pl Executable file
View File

@@ -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=<OPCODELST>;
$ligne=<OPCODELST>;
while($ligne=<OPCODELST>) {
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;

186
src/PgmWin.cpp Normal file
View File

@@ -0,0 +1,186 @@
/* pgmwin.cpp */
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include "PgmWin.hpp"
#include <stdio.h>
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 );
}

41
src/PgmWin.hpp Normal file
View File

@@ -0,0 +1,41 @@
#ifndef _PGMWIN_HPP_
#define _PGMWIN_HPP_
#include <gtk/gtk.h>
#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

44
src/Reg8051.hpp Normal file
View File

@@ -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

131
src/RegWin.cpp Normal file
View File

@@ -0,0 +1,131 @@
/* regwin.cpp */
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#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 ) );
}

26
src/RegWin.hpp Normal file
View File

@@ -0,0 +1,26 @@
#ifndef _REGWIN_HPP_
#define _REGWIN_HPP_
#include <gtk/gtk.h>
#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

211
src/disasm.hpp Normal file
View File

@@ -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

19
src/exceptions.hpp Normal file
View File

@@ -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

258
src/opcodes.lst Normal file
View File

@@ -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

115
test_files/siae1.hex Normal file
View File

@@ -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

13
test_files/test.hex Normal file
View File

@@ -0,0 +1,13 @@
:03000000020033C8
:1000330075818075D54475A000C290E4F500E50094
:1000430012007DF586D29005A07400D5E0FDC29024
:10005300E5AA53E08060F9E5861200690500C3E56F
:1000630000945040D92222752005740075F000D504
:10007300F0FDD5E0F7D520F20022248BF582740041
:100083003400F5837400932252504D3A31303234A8
:1000930035204D41503A313033204D41543A3131BE
:1000A30030204241543A31322E3420202020202067
:1000B3000D0A0A45474F3A31342E36202054505307
:1000C3003A31303020414E473A33302020434C54AC
:0B00D3003A313038202020202020206F
:00000001FF

179
test_files/timer.asm Normal file
View File

@@ -0,0 +1,179 @@
;*******************************************************************************
;* Syst<73>me d'Injection et d'Allumage <20>lectronique *
;* Version : 01 *
;* Auteur : Hugo Villeneuve *
;* *
;* 10 mars 1999 *
;*******************************************************************************
$MOD52 ; Micro-contr<74>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<69> par la sous-routine MULT8_16
SIGNE: DBIT 4 ; Utilis<69> 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<75> <20> 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<75>rique.
MSB_CAN: DS 1 ; Octet de poids fort de la conversion Analogique-Num<75>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<74>matiques.
C2: DS 1
C1: DS 1
C0: DS 1
D3: DS 1 ; Accumulateur D de 32 bits pour les calculs math<74>matiques.
D2: DS 1
D1: DS 1
D0: DS 1
TMP6: DS 1 ; Variables temporaires utilis<69>es pour les calculs math<74>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<73>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<69>e;
; Activation du port SPI;
; Ordre des transferts : MSB en premier;
; Op<4F>ration en mode escalve (SLAVE);
; Polarit<69> 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<63>ment<6E>s par l'horloge interne
; Chaque timer est incr<63>ment<6E> tant que le bit correspondant de
; TCON est <20> 1 (TCON.4 et TCON.6).
RET
END

10
test_files/timer.hex Normal file
View File

@@ -0,0 +1,10 @@
:0600000002003302005172
:03000B00020033BD
:03001300020033B5
:03001B00020033AD
:03002300020033A5
:03002B000200339D
:100033007581601200520000000080FA756016742A
:100043000075F000D5F0FDD5E0F7D560F2223275EA
:10005300D544758C02758A55D28CD28E758911223E
:00000001FF