ub's #20

ub's Space at the End of the Universe

Od emulatora k HW (alebo ako vznikol m1hunter)

2018-02-10, tagged as divide, hardware, tbios
Cele to zacalo jedneho pekneho vecera, ked sa mi z00m postazoval ze v spedive nefunguje T-BIOS. Ja som si matne spominal, ze som T-BIOS skusal a ze mi to aj islo. Cely problem ale je, ze ja som vtedy skusal len klasicky RESET+SS+A test, neskusal som ziadne dalsie testy (priznam sa, ze som o nich ani nevedel). Z00m mi o tychto dalsich testoch (prehravanie dividea a zobrazovanie dithvide obrazkov) povedal a ked som nieco z toho skusil, tak som musel sucho skonstatovat, ze to naozaj nejde.

Nuz a tak som sa pohruzil do debugovania. A o malu chvilu som mal predpoklad, uz ho len overit. Spravil som zasah do emulatora, pustil T-BIOS a zrazu divideo hralo.

A o co vlastne islo?

T-BIOS hadam ako jediny firmware pre divide pouziva pri navrate z NMI prefikane umiestnenu instrukciu RETN na adrese 0x1FF7. To preto, lebo je dvojbajtova a keby sme ju dali na 0x1FF8, tak by sa prefix 0xED vycital este z divide pamate, ale kod instrukcie by sa cital uz zo zx rom. Preto ju bolo treba dat o jeden bajt skor, aby sa pamat odmapovala az po precitani kodu instrukcie. A tu bol problem. Spediv totiz mapoval divide len pri citani prveho bajtu celej instrukcie v tomto pripade len pri citani prefixu a kedze prefix je na adrese 0x1FF7, tak sa divide pamat neodmapovala.

Matne som si ale spominal, ze som volakedy dakde cital, ze ak je instrukcia prefixova, tak sa obsah registra R zvysi aj pri citani prefixu a aj pri citani dalsieho kodu instrukcie. A tak mi napadlo, ci to tak nie je aj pre /M1. No a kedze v tbiose je RETN pouzita prave tak, akoby sa /M1 malo generovat na oboch bajtoch, tak som mily spediv upravil, aby pri prefixovyxh instrukciach mapovalo divide nie len na prvom, ale aj na druhom bajte instrukcie a vtedy sa divideo rozbehlo.

Nedalo mi to a pustil som sa do hladania, aby som informaciu o dvoch /M1 pri instrukcii RETN overil. V datasheete k z80 od Zilogu, ktory mam som takto detailnu informaciu nenasiel, len, ze /M1 spolu s /MREQ indikuje ze prave vykonavany cyklus je citanie kodu instrukcie z pamate (popis /M1 v casti "Pin Functions"). Avsak, v datasheete k z80 od Mosteku uz tato informacia bola (opat popis /M1 v casti "Z80-CPU PIN DESCRIPTION"). Hladal som dalej, ci nenajdem niekde nejake nedokumentovane informacie (podobne ako sa da najst popis oficialne nedokumentovanych instrukcii). A v tom som narazil na poznamku nielen o dvojbajtovych prefixovych instrukciach, ale aj na zaujimavu poznamku o stvorbajtovych instrukciach (s dvomi prefixmi DD CB / FD CB). Informaciu najdete tu "z80_special_reset", prispevok "(Nov 22, 2016) Anonymous". Tato informacia hovori, ze nie kazde citanie kodu instrukcie generuje /M1. Totiz, pri DD CB nn XX instrukciach su 2 prefixy, pri nich sa /M1 generuje, ale pri citani kodu instrukcie (posledny bajt - XX) sa uz /M1 negeneruje...

Nuz a tak som pozrel zdrojove kody opensource kniznice z80ex, ktora emuluje z80 a ona /M1 generuje presne tak ako z predchadzajuceho vyplyva. Pri neprefixovych instrukciach len na prvom bajte instrukcie, pri jednoprefixovych na prvych dvoch bajtoch a pri dvojprefixovych opat len na prvych dvoch bajtoch.

A tu sa pomaly dostavame k HW casti clanku. Totiz, tato informacia o 2oj prefixovych instrukciach bola ziskana len z "druhej ruky" a teda mohla byt nepresna. V ziadnej oficialnej dokumentacii som sa o dvojprefixovych instrukciach a ich /M1 nedozvedel. Chcelo to zistit, ako sa chova realne HW z80.

A tak vznikol miniprojektik "m1hunter". Ide o jednoduche zariadenie, ktore pripojime ku spektru a spustime pripraveny program a po navrate z programu bude m1hunter zobrazovat, kolkokrat bol pri vykonavani programu aktivovany signal /M1. Na pocitanie /M1 signalov mali sluzit 2 ks 7493 (jedna 7493 na jeden nibble), ako dekoder /M1, /MREQ, /RD a adresy mali sluzit GAL16v8, ktore mali rovnako sluzit aj na dekodovanie BCD na 7segmentovy display (na kazdy nibble jeden GAL).

Ale kedze som bol velmi zvedavy a riesenie s GALmi vypadalo na dlhsie (musel by som pripravovat nejake prostredie na ich naprogramovanie a podobne), tak som od 7segmentovych displayov upustil, s tym, ze zatial mi bude stacit, ked bude vysledok zobrazeny v dvojkovej sustave pomocou 8 LED diod. Kedze som sa chcel GAL-ov zbavit, musel som vymysliet aj iny dekoder signalov cpu. Nuz a tu ma osvietilo a nakoniec mi hravo postacila jedna 74138. Najskor som myslel ze bude treba 2, ale potom som si pozrel datasheet a vsimol som si ze okrem 3och vstupnych signalov ma 74138 este dalsie 3 aktivacne signaly, co je spolu 6 signalov a to je presne tolko, kolko som potreboval.

Vo finalnom prototype som este miesto dvoch 7493 pouzil jednu 74393 a tak sa cele zariadenie zminimalizovalo na 2 IO, 8 diod, 9 rezistorov a jeden mikrospinac (na reset countrov pred spustenim programu).

Schema m1huntera:


Zo schemy vidno, ze m1hunter pocita /M1 signaly, v oblasti 0x8000-0x80FF (dekoduje stav A15, A9 a A8). Tak si do tejto oblasti pripravime testovane instrukcie a na adresu 0x8100 dame RET (ktory sa uz nezapocita, lebo je mimo oblast). V skutocnosti je viac oblasti, kde sa rata, pretoze nedekodujeme cely vyssi bajt adresy, to nam ale nevadi, podstatne je ze na adresach 0x80XX pocitame /M1 a na 0x81XX uz nie.

Testovaci program pripravime pomocou jednoducheho BASICu:

Nas testovaci program pozostava zo 64 instrukcii BIT 0,(IX+0) v oblasti 0x8000-0x80FF a instrukcie RET na adrese 0x8100. Instrukcia BIT 0,(IX+0) ma dva prefixy a teda m1hunter by mal napocitat 128 /M1 signalov.

Po spusteni tohto BASIC programu treba stlacit mikrospinac, na vynulovanie citacov a potom zadat prikaz RANDOMIZE USR 32768.

M1hunter naozaj potvrdil, ze dvojprefixove instrukcie aktivuju /M1 len dvakrat, pretoze pocitadlo po spusteni testovacieho programu ukazovalo presne 128.

--