Bonjour.
Il y a très longtemps, il y avait un désir d'écrire un émulateur d'un processeur.
Et quoi de mieux que d'inventer un vélo?
Le nom du vélo est V16, du collage du mot virtuel et, en fait, de la profondeur de bits.
Par où commencer?
Et vous devez bien sûr commencer par une description du processeur.
Au tout début, j'avais prévu d'écrire un émulateur DCPU-16, mais il y a plus qu'assez de tels miracles sur Internet, j'ai donc décidé de me concentrer uniquement sur "lécher" les plus basiques avec DCPU-16 1.1.
L'architecture
Mémoire et ports
- V16 adresse 128 Ko (65 536 mots) de RAM, qui peuvent également être utilisés comme tampons de périphérique et la pile.
- La pile commence par l'adresse FFFF, par conséquent, RSP a une valeur standard de 0xFFFF
- Les ports d'E / S V16 en ont 256, ils ont tous une longueur de 16 bits. Leur lecture et leur écriture s'effectuent à travers les instructions
IN b, a
ET OUT b, a
.
Registres
V16 possède deux ensembles de registres à usage général: primaire et alternatif.
Un processeur ne peut fonctionner qu'avec un seul ensemble, vous pouvez donc basculer entre les ensembles à l'aide de l'instruction XCR
.
Instructions
Toutes les instructions ont une longueur maximale de trois mots et sont entièrement définies en premier
Le premier mot est divisé en trois valeurs: l'octet bas est l'opcode, l'octet haut sous la forme de deux valeurs de 4 bits est la description des opérandes.
Interruptions
Les interruptions ne sont ici rien de plus qu'une table avec des adresses auxquelles le processeur duplique l'instruction CALL
. Si la valeur d'adresse est nulle, alors l'interruption ne fait rien, elle réinitialise simplement l'indicateur HF.
Un exemple de pseudocode et de mots dans lesquels tout cela devrait être traduit:
MOV RAX, 0xABCD ; 350D ABCD MOV [RAX], 0x1234 ; 354D 1234
Cycles
V16 peut exécuter une instruction en 1, 2 ou 3 mesures. Chaque accès mémoire est un cycle d'horloge distinct. L'instruction n'est pas du tact!
Commençons à écrire!
Implémentation de structures de processeur de base
Un ensemble de registres. Il n'y a que quatre registres, mais la situation s'améliore car il y a deux de ces ensembles dans le processeur. La commutation se produit à l'aide de l'instruction XCR
.
typedef struct Regs { uint16_t rax, rbx;
Drapeaux Contrairement à DCPU-16, V16 a des sauts conditionnels, des appels de sous-programme et des retours de la même. À l'heure actuelle, le processeur dispose de 8 indicateurs, dont 5 sont des indicateurs de condition.
En fait, le processeur lui-même. Il décrit également le tableau des adresses d'interruption, qui peuvent être appelées descripteurs et trouver une autre référence à x86.
typedef struct CPU {
Opérande. Lors de l'obtention des valeurs, nous devons d'abord lire, puis modifier, puis réécrire la valeur à l'endroit où nous l'avons obtenue.
typedef struct Opd { uint8_t code : 4; uint16_t value; uint16_t nextw; } opd_t;
Fonctions de travail avec les structures
Lorsque toutes les structures sont décrites, le besoin se fait sentir de fonctions qui doteront ces structures de la puissance magique du code désactivé.
cpu_t * cpu_create(void);
De plus, je n'ai pas mentionné une grande énumération avec les codes d'opération, mais ce n'est pas nécessaire et n'est nécessaire que pour comprendre ce qui se passe dans tout ce gâchis.
Fonction Tick ()
En outre, il existe des appels à des fonctions statiques destinées uniquement à appeler à partir de tick()
.
void cpu_tick(cpu_t *cpu) {
Que faire ensuite?
Afin de trouver la réponse à cette question, j'ai réécrit l'émulateur cinq fois de C en C ++, et vice versa.
Cependant, les principaux objectifs peuvent être identifiés maintenant:
- Fixez les interruptions normales (au lieu d'appeler simplement une fonction et d'interdire la réception d'autres interruptions, effectuez un appel de fonction et ajoutez de nouvelles interruptions à la file d'attente).
- Les dispositifs à vis, ainsi que les moyens de communiquer avec eux, l'avantage des opcodes peut être 256.
- Enseigner
Ne t'écris aucune hérésie sur Habr Le processeur fonctionne à une vitesse d'horloge spécifique de 200 MHz.
Conclusion
J'espère que cet "article" sera utile à quelqu'un, quelqu'un le poussera à écrire quelque chose de similaire.
Mes tartes peuvent être consultées sur github .
Aussi, à propos de l'horreur, j'ai un assembleur pour l'ancienne version de cet émulateur (non, n'essayez même pas, l'émulateur se plaindra au moins du mauvais format de ROM)