[Teensy 4.1] Emulateur Z80 sur la base d'un PCB MCLZ8.

Couvre tous les domaines de l'émulation logicielle ou de la virtualisation ainsi que les discussions sur les divers outils associés.

Modérateurs : Papy.G, fneck, Carl

Avatar de l’utilisateur
hlide
Messages : 3470
Inscription : 29 nov. 2017 10:23

[Teensy 4.1] Emulateur Z80 sur la base d'un PCB MCLZ8.

Message par hlide »

J'ouvre ce fil pour la partie logicielle (ou firmware devrai-je dire) qui va émuler le Z80 en exploitant les signaux du bus Z80 d'une machine.

Initialement, MCLZ8 a bien son firmware qui émule un Z80 pour un TRS80. Mais à l'usage, il s'avère mal adapté à mon besoin donc j'ai décidé de faire mon propre émulateur.

Etant donné que je programme en C++, je me suis dit que je vais utiliser à fond la programmation générique (les templates C++) pour factoriser le source et compter sur le compilateur pour qu'il génère le code optimal. J'ai donc commencer ainsi en me fondant sur ce lien.

Mais je dois dire que c'est long, très long donc entre temps j'ai regardé les autres sources d'émulateur de Z80, dont celui-ci. J'ai donc adapté et fait en sorte que ça compile. Mais je l'ai jamais testé car il me semblait évident que ça ne fonctionnerait pas très bien. L'auteur n'en est pas fautif, il connaissait le problème et il a dû faire un choix : comme il émule tout un système, il a choisi de traiter les signaux comme un événement déclencheur d'un seul cycle alors que dans un vrai Z80 ces signaux ne sont pas actifs en même temps et perdurent sur plusieurs cycles. Je comprends le dilemme.

Donc je suis revenu à ma première tentative pour compléter les instructions manquantes mais en reprenant une partie de l'émulation des instructions de chips/z80.h. Néanmoins, j'ai eu un comportement différent. A force de copier/coller, il fallait s'attendre que j'ai introduit des bugs en oubliant les adaptations d'une instruction à une autre. Ainsi je me retrouvais coincé dans la boucle de détection du VBLANK parce qu'à l'initialisation, une autre instruction qui devait configurer l'i8255 le faisait avec le mauvais registre suite à une subtile erreur d'affectation du registre. Du coup, le port sur lequel je voulais lire le VBLANK restait figé. D'autres bugs comme ce saut JP nnnn qui affectait deux fois la partie LSB du PC au lieu de faire le LSB puis le MSB du PC (un copier/coller sans adaptation).

Mes tests sont effectués sur un MZ-80 K et pour le moment je n'arrive pas correctement sur le prompt du moniteur car j'imagine qu'il doit y avoir des erreurs sur d'autres instructions et sans possibilité de déboguer comme sur un PC, ça reste une gageure.

Pas le choix, il me faut un interpréteur Z80 croisé. Qu'est-ce que c'est ? c'est un autre émulateur Z80 dont on a en quelque sorte l'assurance qu'il fonctionne. Il n'a pas besoin d'accéder au bus Z80. Il n'a pas non plus besoin d'être fidèle en cycle.

Le truc c'est de copier les registres de mon émulateur dans le contexte de l'émulateur croisé, de faire exécuter une instruction par mon émulateur, puis de faire exécuter la même instruction par l'émulateur croisé et enfin de comparer les valeurs des registres pour détecter une divergence et la tracer. C'est une technique qui m'avait servi à mettre au point un JIT en le comparant à l'interpréteur croisé Allegrex (MIPS32) de mon feu émulateur PSP. Les accès mémoires ou port I/O en lecture se contenteront de reprendre ce que mon émulateur a récupéré et on ignore les écritures.

Mais voilà, quel émulateur Z80 choisir pour la partie croisée ?

- https://github.com/redcode/Z80 : on m'en a vanté les mérites. Cependant, il y a une dépendance "cachée" avec le projet Zeta (bourré d'entêtes) donc trop de fichiers à copier.

- https://github.com/ggambetta/libz80 : celui-ci demande probablement 5 fichiers mais il y a probablement matière à les fusionner. J'ignore s'il contient encore des bugs toutefois.

- https://github.com/floooh/chips/blob/master/chips/z80.h : je pourrais reprendre ce code et faire en sorte que z80_tick n'exécute pas un cycle mais tous les cycles de l'instruction, les _mread reprenant la valeur lue en mémoire par mon émulateur et en ignorant _wait et _mwrite. Assez paradoxal vous me direz puisque mon émulateur se fonde en partie dessus. Cela aura au moins le mérite de partager le même contexte. Mais il faudra des changements dans le source.

- https://github.com/MicroCoreLabs/Projec ... /MCLZ8.ino : euh, je pourrais effectivement reprendre une partie de son implémentation (l'auteur nous affirme qu'il passe le test ZEXALL), retirer l'accès au bus Z80, virer les cycles, etc.

Si vous avez d'autres sources d'émulateur Z80 qui soit fonctionnel et pas avec des zillions de fichiers à faire installer avec un CMake, je suis intéressé.
Dernière modification par hlide le 12 avr. 2023 20:43, modifié 2 fois.
Avatar de l’utilisateur
hlide
Messages : 3470
Inscription : 29 nov. 2017 10:23

Re: [Teensy 4.1] Emulateur Z80 sur la base d'un PCB MCLZ8.

Message par hlide »

En attendant je vous explique comment l'émulateur Z80 gère l'exécution d'une instruction. Je vais uniquement me concentrer sur la table des opcodes principaux.

Voici la fonction qui implémente l'exécution de toutes les instructions sans suffixe de la table principale :

Code : Tout sélectionner

template <uint8_t OPCODE> inline auto on_xx_opcode() -> void
	{
		constexpr int x = (OPCODE >> 6) & 3;
		constexpr int y = (OPCODE >> 3) & 7;
		constexpr int z = (OPCODE >> 0) & 7;
		constexpr int p = y >> 1;
		constexpr int q = y & 1;

		//////// http://www.z80.info/decoding.htm

		// Relative jumps and assorted ops

		// NOP							1 4 (4)
		/**/ if (x == 0 && y == 0 && z == 0) // $00
		{
			// (4)
		}
...
		// 8-bit loading

		// LD (HL),r					2 7 (4,3)
		else if (x == 1 && y == 6) // $70,$71,$72,$73,$74,$75,$77
		{
			// (4)
			_write_byte(this->hl, _byte_r< z >());
			// (4,3)
		}

		// LD r,(HL)					2 7 (4,3)
		else if (x == 1 && z == 6) // $46,$4E,$56,$5E,$66,$6E,$7E
		{
			// (4)
			_byte_r< y >() = _read_byte(this->hl);
			// (4,3)
		}

		// LD r,r'						1 4 (4)
		else if (x == 1) // $40,$41,$42,$43,$44,$45,$47,$48,$49,$4A,$4B,$4C,$4D,$4F,$50,$51,$52,$53,$54,$55,$57,$58,$59,$5A,$5B,$5C,$5D,$5F,$60,$61,$62,$63,$64,$65,$67,$68,$69,$6A,$6B,$6C,$6D,$6F,$78,$79,$7A,$7B,$7C,$47,$7F
		{
			// (4)
			_byte_r< y >() = _byte_r< z >();
			// (4)
		}
...
		// RST y*8				3 11(5,3,3)
		else if (x == 3 && z == 7) // $C7,$CF,$D7,$DF,$E7,$EF,$F7,$FF
		{
			// (4)
			bus_extra_cycles< 5 - 4 >();
			// (5)
			_write_byte(--this->sp, this->pch);
			// (5,3)
			_write_byte(--this->sp, this->pcl);
			// (5,3,3)
			this->wz = y * 8;
			this->pc = this->wz;
			// (5,3,3)
		}
	}
La fonction étant très longue, je n'ai mis que le début et la fin ainsi que le code au milieu que je vais expliquer sans tarder. L'objectif est de factoriser autant que possible l'implémentation via le triplet (X,Y,Z) de l'encodage de l'opcode.

Code : Tout sélectionner

	template< int SEL, int IDX = 0 > inline auto _byte_r() -> uint8_t &
	{
		return
			((SEL & 7) == 0 ? (this->b                                                  ) :
			 (SEL & 7) == 1 ? (this->c                                                  ) :
			 (SEL & 7) == 2 ? (this->d                                                  ) :
			 (SEL & 7) == 3 ? (this->e                                                  ) :
			 (SEL & 7) == 4 ? ((IDX == 1) ? this->ixh : (IDX == 2) ? this->iyh : this->h) :
			 (SEL & 7) == 5 ? ((IDX == 1) ? this->ixl : (IDX == 2) ? this->iyl : this->l) :
			 (SEL & 7) == 6 ? (this->dlatch /* (hl)/(ix+d)/(iy+d) */                    ) :
			 /* else       */ (this->a                                                  ));
	}
Cette fonction générique me permet d'accéder au bon registre par son code SEL (via X ou Y). Comme c'est une fonction template, c'est lors de la compilation que l'optimisation se passe. En effet, quand le compilateur va lire un _byte_r<7>(), il insère le code this->a à la place !

Et il en va de même pour on_xx_opcode<0x37>() qui donne X = 1, Y = 0 et Z = 7, soit le cas LD r,r' dans la fonction. Le code compilé inséré à la place de on_xx_opcode<0x47>() sera alors this->b = this->a;.

Reste la fonction qui permet d'exécuter l'instruction principale (sans suffixe) :

Code : Tout sélectionner

	auto do_xx_opcode(uint8_t opcode) -> void
	{
		switch (opcode)
		{
		case 0x00: on_xx_opcode< 0x00 >(); break;
...
		case 0x47: on_xx_opcode< 0x47 >(); break; ---> que le compilateur remplace par : case 0x47: this->b = this->a; break;
...
		case 0xFF: on_xx_opcode< 0xFF >(); break;
		default:   __builtin_unreachable();
		}
	}
Et donc si on appelle do_xx_opcode(opcode) avec opcode = 0x47, on a un saut direct via une table au label qui exécutera this->b = this->a; break;.

La contrepartie, c'est le risque d'avoir beaucoup plus de code dans le binaire car je n'utilise pas le LTO (Linking Time Optimization).
Dernière modification par hlide le 10 avr. 2023 14:22, modifié 1 fois.
Notator
Messages : 1286
Inscription : 09 août 2015 20:13

Re: [Teensys 4.1] Emulateur Z80 sur la base d'un PCB MCLZ8.

Message par Notator »

Pas le choix, il me faut un interpréteur Z80 croisé. Qu'est-ce que c'est ? c'est un autre émulateur Z80 dont on a en quelque sorte l'assurance qu'il fonctionne. Il n'a pas besoin d'accéder au bus Z80. Il n'a pas non plus besoin d'être fidèle en cycle.

Le truc c'est de copier les registres de mon émulateur dans le contexte de l'émulateur croisé, de faire exécuter une instruction par mon émulateur, puis de faire exécuter la même instruction par l'émulateur croisé et enfin de comparer les valeurs des registres pour détecter une divergence et la tracer.
Et pourquoi ne pas prendre un vrai Z80, plutôt qu'un émulateur, comme 'modèle' ?
Je pense par exemple à un MPF-1B, ou P, dont il est possible d'exécuter le programme en pas à pas, et d'examiner les registres à tout moment. :wink:
Notator est le nom d'un programme séquenceur Midi et notation musicale pour Atari ST(e) (puis Mac).
Avatar de l’utilisateur
hlide
Messages : 3470
Inscription : 29 nov. 2017 10:23

Re: [Teensy 4.1] Emulateur Z80 sur la base d'un PCB MCLZ8.

Message par hlide »

La boucle d'attente de VBLANK au pas à pas ? pas possible. Je n'ai pas envie de faire du pas au pas. Je veux juste qu'il s'arrête dès qu'il détecte une divergence et qu'il me l'indique sur mon terminal USB. Prendre un vrai Z80, c'est l'impossibilité de consulter tous ses registres en interne pour comparer les comparer à ceux de l'émulateur. C'est aussi faire un PCB spécial pour pouvoir placer un vrai Z80 et faire que le Teensy puisse lire et écrire le bus d'adresse et non juste écrire. Trop de complication, trop de broches, etc.
Dernière modification par hlide le 10 avr. 2023 22:24, modifié 1 fois.
Avatar de l’utilisateur
hlide
Messages : 3470
Inscription : 29 nov. 2017 10:23

Re: [Teensy 4.1] Emulateur Z80 sur la base d'un PCB MCLZ8.

Message par hlide »

Bon j'ai quelque chose de mis en place - j'ai repris l'ancien firmware MCLZ8 comme émulateur croisé où j'ai supprimé le compteur de cycles et les accès au bus Z80. Voici un aperçu :
Sans titre.png
Sans titre.png (57.68 Kio) Consulté 3596 fois
A partir de là, je regarde si le problème est bien lié à une instruction (ici CP $0D).

Je compare quasiment tous les registres, y compris IFF1, IFF2, IM et IR à chaque exécution d'une instruction pour m'assurer que ces deux émulateurs sont en phase.

EDIT: Ah ben oui, ça ne risquait pas de fonctionner comme ça, il fallait _alu8< y > et non _add8.

Code : Tout sélectionner

		// alu n				2 7 (4,3)
		else if (x == 3 && z == 6) // $C6,$CE,$D6,$DE,$E6,$EE,$F6,$FE
		{
			// (4)
			_add8(_fetch_byte());
			// (4,3)
		}
Avatar de l’utilisateur
hlide
Messages : 3470
Inscription : 29 nov. 2017 10:23

Re: [Teensy 4.1] Emulateur Z80 sur la base d'un PCB MCLZ8.

Message par hlide »

Bon c'est cool, ils tournent en phase et j'ai mon prompt. Va falloir que je trouve un ZEXALL adapté au MZ-80 K pour lancer un test plus poussif.
Dernière modification par hlide le 12 avr. 2023 20:42, modifié 1 fois.
Avatar de l’utilisateur
hlide
Messages : 3470
Inscription : 29 nov. 2017 10:23

Re: [Teensy 4.1] Emulateur Z80 sur la base d'un PCB MCLZ8.

Message par hlide »

Et voilà un cap de passé ! le chargement de cassette qui ne fonctionnait pas avec le firmware MCLZ8, fonctionne avec le mien mais je pense qu'il reste encore des erreurs car non seulement je ne gère pas encore les interruptions mais je suis loin d'avoir testé toutes les instructions.

Résultats sur un MZ-80 K2E (pas le mien, une version japonaise) :
338907947_1489226811484051_4681756955976709292_n.jpg
338907947_1489226811484051_4681756955976709292_n.jpg (1.17 Mio) Consulté 3556 fois
339832596_243329928254288_1930840398674456854_n.jpg
339832596_243329928254288_1930840398674456854_n.jpg (1.19 Mio) Consulté 3556 fois
Avatar de l’utilisateur
hlide
Messages : 3470
Inscription : 29 nov. 2017 10:23

Re: [Teensy 4.1] Emulateur Z80 sur la base d'un PCB MCLZ8.

Message par hlide »

Donc, étant donné que j'ai mon MZ-80 K, je me suis dit que je vais tester mon lecteur de cassette. Seulement, je ne retrouve pas ma cassette BASIC. Mais qu’à cela ne tienne ! pourquoi ne pas tester la sauvegarde du BASIC sur la cassette puis tenter de lire la cassette ? après tout, le BASIC est présent sur le µSD et je peux le précharger en DRAM. Depuis le moniteur en ROM virtuel (j'utilise un plus puissant que l'original), je tente la sauvegarde puis la lecture.

Mais je fais ça d'abord avec la sauvegarde du moniteur lui-même et son chargement qui... se passe bien !
IMG_20230412_140125.jpg
IMG_20230412_140125.jpg (151.02 Kio) Consulté 3413 fois
Fort de ce succès, je tente de faire la même chose avec le BASIC SP-5025. Et ça semble fonctionner. Je dis semble car il y a très sûrement des corrections à apporter sur l'émulation du Z80 pour que le BASIC fonctionne (il semble passer un temps effroyable à calculer les octets libres pour le BASIC). Pour en avoir le cœur net, je teste le chargement du BASIC via le µSD et son lancement : même bug.

Qu'est-ce que cela me dit tout ça ? que le timing des cycles Z80 à 2MHz est respecté par mon émulateur (et ce même en incluant l'émulateur croisé pour détecter une divergence).
Avatar de l’utilisateur
hlide
Messages : 3470
Inscription : 29 nov. 2017 10:23

Re: [Teensy 4.1] Emulateur Z80 sur la base d'un PCB MCLZ8.

Message par hlide »

Décidément, j'ai la poisse. J'ai inclus ZEXALL dans le firmware et que ce soit avec mon émulateur ou l'émulateur croisé, j'obtiens que des "ERROR **** crc expected:...".

Cela m'interpelle sur comment ZEXALL et ZEXDOC calculent leurs CRC. Je veux dire, quels autres éléments pourraient interférer dans le calcul ? les cycles ?

Je m'explique :

1) Pour faire le test de ZEXALL, je m'appuis sur ce projet : https://github.com/anotherlin/z80emu. J'ai donc appliqué ce qu'il fallait faire pour faire fonctionner le même test sur mon firmware en détournant l'usage de IN et OUT et en patchant ZEXALL qui est intégré dans le firmware. ZEXALL sera vu comme une ROM alors j'espère qu'il ne pratique pas du "self-modified-code" (pas vérifié).

2) L'émulateur croisé reprend le code d'origine de MCLZ8 avec la différence que l'on ne prend pas en compte le calcul des cycles et des accès en mémoire extérieur (l'instruction reprend les valeurs lues/écrites par l'autre émulateur qui s'exécute avant lui). Dans ce cas, je synchronise les registres entre les deux émulateurs de façon à ce que ce soit l'émulateur croisé qui l'emporte. Donc la séquence qui calcule le CRC est donné par l'émulateur croisé. Et pourtant, j'obtiens que des "ERROR" quand bien même que l'auteur certifie que son firmware passe les tests de ZEXALL (je n'ai pas vu de preuve). Bref, je ne sais pas comment il s'y est pris pour que ZEXALL fonctionne sur son émulateur.

3) Mon émulateur bien que fondé sur celui floooh/chips a fait l'objet de son propre décodeur - donc oui, on a potentiellement des erreurs humaines introduites. Je peux donc m'attendre à ce que ZEXALL aient des erreurs mais pas pour tous puisque l'auteur a indiqué que le test ZEXALL passe également sur son émulateur.

4) Quand j'active l'émulation croisée, je tombe déjà sur une différence de FLAGS entre les deux émulateurs sur ADD/ADC. Mais qui a raison ?

Ça devient franchement très pénible.
tz80-zexall.png
tz80-zexall.png (455.21 Kio) Consulté 3234 fois
EDIT: Ah purée ! je dois bien être fatigué !!!! si le programme est vu comme une ROM alors ces données ne seront pas modifiables donc cela participerait au résultat que j'obtiens !
EDIT2: Visiblement pas un problème de RAM/ROM non plus... ou bien ça ne change pas la donne.
Avatar de l’utilisateur
hlide
Messages : 3470
Inscription : 29 nov. 2017 10:23

Re: [Teensy 4.1] Emulateur Z80 sur la base d'un PCB MCLZ8.

Message par hlide »

Bon, j'essaye de reprendre ce projet doucement. Pas mal de mésaventure :

1) Mon laptop personnel que je vais appeler l'ancien ne veut plus me laisser reprogrammer les Teensy par ses ports USB. Pas la moindre idée du pourquoi mais il m'aura usé jusqu'à la corde.

2) J'étais motivé pour me prendre un nouveau laptop genre ultra puissant mais au bout d'un mois, ses ports USB-C ne veulent plus faire office de DisplayPort pour mon Samsung 5K (gaming et développement) ni ma télé 4K (récréation). Demande de réparation -> irréparable -> remboursement -> de nouveau à la case de départ.

3) Je suis donc obligé de continuer le développement sur mon laptop de travail puisque c'est le seul qui veut bien me reprogrammer les Teensy. Vous savez le truc avec plein d'interdit des IT qui vous pourrit la vie (veille excessive, droit administrateur le plus chiant possible).

Mais, voilà, j'étais passé à platform.io (via visual studio code) que j'apprécie bien mieux que cette daube d'Arduino IDE 2.0. Et en fait, quoique je produise avec, je ne parviens pas à accéder aux ports USB une fois claqué le firmware produit. Il y a donc un problème avec platform.io.

Je suis obligé de continuer avec Arduino IDE 2.0 sur le portable de travail. Misère...
Avatar de l’utilisateur
hlide
Messages : 3470
Inscription : 29 nov. 2017 10:23

Re: [Teensy 4.1] Emulateur Z80 sur la base d'un PCB MCLZ8.

Message par hlide »

Donc je reprends mon firmware dont j'ai décidé le nom : TZZ80. Son logo sur PCB (le nouveau qui est en cours de fabrication) :
image.png
image.png (6.49 Kio) Consulté 1667 fois
Donc j'utilise une émulation croisée entre mon émulateur de Z80 et celui de MCLZ8. Le Teensy tourne en stand-alone (ni de PCB MCLZ8 ni de machine) pour lequel j'ai établi une ram virtuelle de 64 Ko avec un ZEXALL qui est chargé dans cette RAM. Il n'y a plus d'accès au bus extérieur, plus de cycles à respecter (CLK désactivé) le temps de mettre au point cet émulateur. Pour cela, le firmware MCLZ8 a sa ram avec la même copie de ZEXALL aussi. J'exécute une instruction sur MCLZ8 puis sur TZZ80 et compare le contexte de registre (cela inclut aussi PC, I, R, IFF1, IFF2, etc.) pour détecter une divergence. Pour mieux suivre ce qui se passe, je trace sur un port USB sériel l'instruction avec son adresse, son opcode, son mnémonique et les accès mémoires s'il y a. A noter qu'à chaque lecture ou écriture en mémoire, je compare l'octet à celui du MCLZ8 pour détecter très rapidement à quel moment il y a divergence en mémoire car si on rate ce point, c'est très difficile de déterminer quel est l'instruction qui a provoqué cette divergence. Par exemple ici, quand je n'avais pas cette détection, j'avais un POP qui divergeait par son contenu dépilé : accrochez-vous pour trouver le coupable ! avec cette détection, je peux enfin trouver le coupable en la personne du PUSH IX qui se comporte comme un PUSH HL vu les octets qu'il empile. Reste à déterminer pourquoi ce PUSH IX se comporte mal.
Sans titre.png
Sans titre.png (202.55 Kio) Consulté 1667 fois
Avatar de l’utilisateur
hlide
Messages : 3470
Inscription : 29 nov. 2017 10:23

Re: [Teensy 4.1] Emulateur Z80 sur la base d'un PCB MCLZ8.

Message par hlide »

Oh là là me voilà excité comme une puce !

Code : Tout sélectionner

ZEXALL virtual Z80 by Christophe Avoinne
Frequency: 816000000 Hz
[SETUP]
[BUS] Setup... done.
[Z80] Setup... done.
SD initialization failed!
SD contents:
---
Testing "zexall"...
[Z80] Initing... done.
[Z80] Now running!
Z80 instruction exerciser

<adc,sbc> hl,<bc,de,hl,sp>....  OK
add hl,<bc,de,hl,sp>..........  OK
add ix,<bc,de,ix,sp>..........
[Z80] Now exited!
Enfin des OK!

Mais bon, il y a visiblement du travail du côté décodage de la table DD/FD (IX/IY). C'est assez attendu du fait que le lien http://www.z80.info/decoding.htm ne décrit pas exhaustivement les triplets (X, Y, Z) pour les tables DD/FD contrairement aux autres tables. Il y a donc forcément des erreurs, des oublis que je dois corriger. Mais ça avance maintenant.
Sans titre2.png
Sans titre2.png (15.87 Kio) Consulté 1600 fois
Avatar de l’utilisateur
hlide
Messages : 3470
Inscription : 29 nov. 2017 10:23

Re: [Teensy 4.1] Emulateur Z80 sur la base d'un PCB MCLZ8.

Message par hlide »

Je le savais ! l'auteur de MCLZ8 m'a vraiment baladé sur ce problème que j'avais remonté en issue sur sont github.

Pour souvenir, j'avais repris son source et le modifiant très légèrement pour qu'il offre 64 Ko de RAM interne, tourne à plein régime sans se synchroniser sur le bus externe et précharge ZEXALL dans la RAM interne. Le résultat :
235476884-f3ffbf83-a594-42ee-b104-dd7c2924b2a3.png
235476884-f3ffbf83-a594-42ee-b104-dd7c2924b2a3.png (318.95 Kio) Consulté 1503 fois
L'auteur soutenait mordicus que le problème venait de moi et que son test était OK. Sauf que j'avais appris qu'il faisait ses tests avec une version MacOS de son source. Sans entrer dans les détails, il est clair pour moi qu'il n'a jamais utilisé le source qu'il a publié et qu'il m'était impossible de reproduire ses tests pour confirmer ses dires. A noter que j'ignore les bits XF et YF du registre F lors de la comparaison des registres entre mon émulateur et le sien car je considère que ni le mien ni le sien sont bien émulés à ce stade.

Comme vous pouvez voir, il y avait une erreur sur "bit n,(hl)" :
254200268-240a1e4a-8338-419c-a1f4-c8de123eff56.png
254200268-240a1e4a-8338-419c-a1f4-c8de123eff56.png (123.87 Kio) Consulté 1503 fois
La raison est la façon de calculer les flags F du Z80 sur le BIT n,(HL). On doit utiliser le registre interne WZ qui dans ce cas est affecté avec l'adresse contenu dans HL (IX+d ou IY+d quand c'est préfixé avec DD ou FD). Or il utilisait PC dans le cas de HL !? il y avait bien une connerie dans le source qu'il a publié. *sigh*.

La bonne nouvelle c'est que mon firmware passe bien ce test ZEXALL bit n,<b,c,d,e,h,l,(hl),a>.
Avatar de l’utilisateur
hlide
Messages : 3470
Inscription : 29 nov. 2017 10:23

Re: [Teensy 4.1] Emulateur Z80 sur la base d'un PCB MCLZ8.

Message par hlide »

Et autre bonne nouvelle :

Code : Tout sélectionner

Frequency: 816000000 Hz
Testing "zexall"...
[Z80] Initing... done.
[Z80] Now running!
Z80 instruction exerciser
<adc,sbc> hl,<bc,de,hl,sp>....  OK
add hl,<bc,de,hl,sp>..........  OK
add ix,<bc,de,ix,sp>..........  OK
add iy,<bc,de,iy,sp>..........  OK
aluop a,nn....................  OK
aluop a,<b,c,d,e,h,l,(hl),a>..  OK
aluop a,<ixh,ixl,iyh,iyl>.....  OK
aluop a,(<ix,iy>+1)...........  OK
bit n,(<ix,iy>+1).............  OK
bit n,<b,c,d,e,h,l,(hl),a>....  OK
cpd<r>........................  ERROR **** crc expected:134b622d found:62b7026d
cpi<r>........................  OK
<daa,cpl,scf,ccf>.............  OK
<inc,dec> a...................  OK
<inc,dec> b...................  OK
<inc,dec> bc..................  OK
<inc,dec> c...................  OK
<inc,dec> d...................  OK
<inc,dec> de..................  OK
<inc,dec> e...................  OK
<inc,dec> h...................  OK
<inc,dec> hl..................  OK
<inc,dec> ix..................  OK
<inc,dec> iy..................  OK
<inc,dec> l...................  OK
<inc,dec> (hl)................  OK
<inc,dec> sp..................  OK
<inc,dec> (<ix,iy>+1).........  OK
<inc,dec> ixh.................  OK
<inc,dec> ixl.................  OK
<inc,dec> iyh.................  OK
<inc,dec> iyl.................  OK
ld <bc,de>,(nnnn).............  OK
ld hl,(nnnn)..................  OK
ld sp,(nnnn)..................  OK
ld <ix,iy>,(nnnn).............  OK
ld (nnnn),<bc,de>.............  OK
ld (nnnn),hl..................  OK
ld (nnnn),sp..................  OK
ld (nnnn),<ix,iy>.............  OK
ld <bc,de,hl,sp>,nnnn.........  OK
ld <ix,iy>,nnnn...............  OK
ld a,<(bc),(de)>..............  OK
ld <b,c,d,e,h,l,(hl),a>,nn....  OK
ld (<ix,iy>+1),nn.............  OK
ld <b,c,d,e>,(<ix,iy>+1)......  OK
ld <h,l>,(<ix,iy>+1)..........  OK
ld a,(<ix,iy>+1)..............  OK
ld <ixh,ixl,iyh,iyl>,nn.......  OK
ld <bcdehla>,<bcdehla>........  OK
ld <bcdexya>,<bcdexya>........  OK
ld a,(nnnn) / ld (nnnn),a.....  OK
ldd<r> (1)....................  OK
ldd<r> (2)....................  OK
ldi<r> (1)....................  OK
ldi<r> (2)....................  OK
neg...........................  OK
<rrd,rld>.....................  OK
<rlca,rrca,rla,rra>...........  OK
shf/rot (<ix,iy>+1)...........  OK
shf/rot <b,c,d,e,h,l,(hl),a>..  OK
<set,res> n,<bcdehl(hl)a>.....  OK
<set,res> n,(<ix,iy>+1).......  OK
ld (<ix,iy>+1),<b,c,d,e>......  OK
ld (<ix,iy>+1),<h,l>..........  OK
ld (<ix,iy>+1),a..............  OK
ld (<bc,de>),a................  OK
Tests complete
Il me reste qu'à vérifier pourquoi le teste "cpd<r>" foire.
Dernière modification par hlide le 18 juil. 2023 20:30, modifié 1 fois.
Avatar de l’utilisateur
irios
Messages : 3396
Inscription : 04 nov. 2007 19:47
Localisation : Rochefort du Gard (30)
Contact :

Re: [Teensy 4.1] Emulateur Z80 sur la base d'un PCB MCLZ8.

Message par irios »

Bravo pour cet émulateur !
http://irioslabs.over-blog.com/

La connaissance ne vaut que si elle est partagée par tout le monde.
I2C
Répondre