Testovací kód pro 8080 a peklo s DAA

Jak vyzkoušet emulátor procesoru? Nejlépe programem, který používá všechny instrukce. A co když vám zatvrzele padá?

Ti, co sledují můj Twitter, to už vědí: V pátek v noci jsem napsal emulátor pro BOB-85, v sobotu pak PMD. S PMD bylo trošku problémů, a po odpoledni stráveném s debuggerem a výpisy ROMky i BASICu padlo moje podezření na emulační jádro procesoru 8080. Pravděpodobně tam nějaká instrukce nefunguje jak má.

Jak ji najít? Nejlepší je použít nějaký „instrukční pangram“:

Pangram (z řeckého pan gramma, „každé písmeno“) je věta či úsek textu obsahující všechna písmena abecedy. Jedná se zpravidla o slovní hříčku, cílem je zpravidla vytvořit co nejkratší, popř. vtipný či jinak zajímavý text s touto vlastností.

Tedy kód, který obsahuje všechny instrukce a otestuje, jestli dělají co mají a jestli jsou příznaky nastavené tak jak by měly být apod. Pro procesor 8080 je takových testů několik, já použil takzvaný Kelly Smith Test (Microcosm test). Po pár krocích bylo jasno: špatně se počítá paritní bit! Upravil jsem tedy emulační jádro, a test začal fungovat…

… a fungoval až skoro na konec, kde se testuje instrukce DAA, tedy dekadické zarovnání po aritmetické operaci. Tam sveřepě padal.

Podíval jsem se, jak je instrukce DAA napsána, nevykazovala chybu. Podíval jsem se, jak je definováno její chování:

Instrukce DAA (decimal adjust accumulator) dekadicky koriguje součet kladných čísel v kódu BCD a při tom jediná využívá indikátor AC. Korekce probíhá podle tohoto algoritmu: je-li číslo v dolní tetrádě střadače A větší než 9 nebo AC=1, přičte se ke střadači 6; obsahuje-li pak horní tetráda střadače číslo větší než 9 nebo je-li CY=1, přičte se ke střadači ještě 60H.

Tak. Takhle by to mělo fungovat, a takhle je to taky implementované. Což je v pořádku, ale test na tom havaroval. On totiž téhle instrukci zlomyslně předhazoval hodnoty, které by normálně dostávat neměla, a testoval, že se zachová jako opravdová 8080.

Například – v A je hodnota 55H a AC je nastavený. Podle výše uvedeného algoritmu by měl být výsledek 5BH. Logicky. Ale stejně tak je to (logicky) nesmysl – výsledkem DAA přeci nemůže být 5BH!

Chvíli jsem pátral a přemýšlel. Oněch 55H + AC nastavený na vstupu je nesmysl – jaká dvě čísla by se musela sčítat, aby došlo k přetečení u nejnižší tetrády (čtveřice bitů), a zároveň byl výsledek 5? Inu, musely by se sčítat čísla mimo rozsah 0-9, protože 9+9 dá dohromady 12H, víc ani ťuk. Takže 55 a AC na vstupu je chyba, hurá, příčina odhalena, matematik si může jít odpočinout, ale programátorovi to není nic platné, protože mu test neběží.

A tak jsem se dal do googlení, a nejpodrobnější informaci, co jsem sehnal, je ta, že DAA je „správně“ implementovaná třeba v Z80, ale v 8080 se chová „trochu“ jinak pro nestandardní vstupní data. Mnoho autorů „emulátoru 8080“ s tímhle skončilo a často jsem četl prohlášení: „DAA prostě nefunguje úplně stejně, ale on to stejně nikdo příčetný nepoužívá“. Hm, to sice je řešení, ale test stejně neběží. Co teď?

Vypadá to (ale fakt jen vypadá!), že chování DAA by se mohlo řídit o něco složitějším algoritmem. Nějak takhle:

Je-li číslo dolního nibble >9 nebo příznak AC nastaven, přičítá se 6. Je-li příznak AC nastaven a zároveň je dolní nibble v rozsahu [3..9], jedná se o chybná vstupní data a šestka se nepřičítá.

Mno, bylo by fajn to ještě pořádně ověřit na skutečném, křemíkovém procesoru, ale bohužel, moje PMI ještě není provozuschopné. Každopádně když jsem to takto napsal, tak celý test prošel bez problémů.

Jo a taky se „zázračně“ rozběhalo PMD.

Odkazy:

Příspěvek byl publikován v rubrice ASM80.com se štítky . Můžete si uložit jeho odkaz mezi své oblíbené záložky.
  • Veľmi ma mrzí, že posledné dni som sa dosť zavalil prácami na pripravovanom music-trackeri [http://sourceforge.net/projects/mif85tracker/] a nemal som čas poriadne otestovať ASM80, tj. že som zanedbával aj Twitter a RSSko, takže mi tieto články ušli… Sorry 🙁

    Každopádne, v našich oboch emulátoroch (tom hlavnom pre Windows aj v mojom linuxovskom GPMD85Emulatore) máme emuláciu DAA overenú presne podľa fungovania reálneho i8080. Pri spustení emulátora sa predgenerujú tabuľky na nastavenia flagov a výsledkov inštrukcie DAA touto metódou:

    http://sourceforge.net/p/gpmd85emulator/code/HEAD/tree/trunk/src/ChipCpu8080.cpp#l108

  • Jojo, koukal jsem se, jak to máte, a přemýšlel jsem, že bych to vyřešil stejně, tj. předpočítanou tabulkou.

  • Jo, a už len pre upresnenie: Tá tabulka je dlhá 1024 bajtov preto, že sa do nej samozrejme pozerá na základe nastavených flagov v danom momente, viď: http://sourceforge.net/p/gpmd85emulator/code/HEAD/tree/trunk/src/ChipCpu8080.cpp#l425

  • Roman Bórik

    Z čírej zvedavosti som chcel overiť, či to DAA funguje skutočne správne a zistil som, že DAA možno áno, ale problém je, že aritmetické a logické inštrukcie nesprávne nastavujú príznak pomocného prenosu AC. Overiť to môžeš na nasledujúcom príklade konverzie binárnej číslice na ASCII HEXA znak (rutina pochádza z Monitora PMD 85-2(A) a je na adrese 8888h).
    V tomto konkrétnom prípade je kameň úrazu v inštrukcii SBI, ktorá nenastaví správne AC a DAA potom „zlyhá“.
    Ale keď som v tejto rutine porovnával nastavenia AC pre ANI a CPI voči nášmu emulátoru, tak sa AC tiež korektne nenastavovalo.
    Spusti si svoj emulátor PMD 85 s Monitorom 2 a daj DUMP 8000, uvidíš tie haluze, čo ti to bude vypisovať…

    .ORG 0
    LXI SP,0080h
    MVI A,3
    CALL PRE00 ; výsledkom bude 39h namiesto 33h
    MVI A,13
    CALL PRE00 ; tu je výsledok správny, teda 44h
    JMP 0

    PRE00: ANI 0Fh ; zaujímajú nás iba dolné 4 bity
    CPI 10 ; CY=1 pre 0 až 9, CY=0 pre A až F
    SBI 2Fh ; „čudný“, ale zjavne dômyselný odpočet
    DAA ; „desiatková korekcia“, ktorej výsledkom sú hodnoty 30h až 39h a 41h až 46h, teda ASCII kódy šestnáskových číslic.
    RET

  • Roman Bórik

    Nuž, musím si nasypať popol na hlavu… Spustil som Exerciser test v našom Emulátore a pre oba ALUOP testy sa vrátila chyba. Takže aj náš emulátor má nejaké chyby v nastaveniach flagov pri logických a aritmetických inštrukciách. Budem to musieť preskúmať.
    Exerciser test na „živom“ PMD 85 prešiel bez problémov.

  • Díky, mrknu na to. Teď jsem někde zahlédnul dokonce info, že 8080 nastavovala nějaký bit podle toho, jestli instrukce byla ADD nebo SUB… ?! Po svátcích zkontroluju.

  • Roman Bórik

    Previedol som analýzu našej emulácie i8080 voči „živej“ MHB8080A v PMD 85 a nakoniec som problém vyriešil. Ako je vidieť na obrázku z emulátora, všetky testy teraz prebehli bez chýb. Problém bol (a aj som to tušil) v nastavovaní príznaku AC po vykonaní inštrukcií ANA a ANI.
    Je to tak, inštrukcie ADD a SUB odlišne nastavujú príznak AC, čo sa samozrejme prejaví iba pri prípadne nasledujúcej inštrukcii DAA.

    Pri tej príležitosti som zosumarizoval informácie o nastavovaní príznakov:
    http://pmd85.borik.net/_work/priznaky-i8080.xlsx
    http://pmd85.borik.net/_work/priznaky-i8080.txt

  • Skvělá práce, díky za info. Po svátcích se na to vrhnu… Díky moc.

  • Tak, SBI, ANI a CPI jsem trošku poladil (zatím na lokále), díky za tipy. Jdu nějak zkusit přeložit ten exerciser na automatizované testování.

  • Roman Bórik

    Super.

    Len pre úplnosť. Nedefinované kódy inštrukcií i8080 majú nasledujúce chovanie:
    08h, 10h, 18h, 20h, 28h, 30h, 38h – NOP
    0CBh – JMP adr
    0D9h – RET
    0DDh, 0EDh, 0FDh – CALL adr

    Nemá to možno „praktický“ zmysel, pretože rozumný assembler a ani programátor tieto kódy nikdy nepoužijú, ale aby bola emulácia kompletná, je vhodné to tam doplniť.

  • Dík, hodím to tam. Mimochodem, nemáš někde Exerciser přeložený pro PMD? Já se tu s ním celé odpoledne mořím a nejde, tak nevím, jestli mám chybu v kódu nebo v postupu nebo v překladači 🙁

  • Roman Bórik

    Na nasledujúcom linku je binárka. Nahráva a spúšťa sa od adresy 0100h. Je to prakticky pôvodný kód, iba služby BDOSu pre výpis na konzolu sú nahradené volaním 8500h v Monitore PMD 85.
    http://pmd85.borik.net/_work/8080EX1.bin

  • Děkuju, vyzkouším to, aspoň zjistím, jestli je problém u mne nebo… u mne… 🙂

  • Aha, tak ne že by to nefungovalo… ono to jen tak děsně dlouho trvá! 🙂

  • Roman Bórik

    Je to tak, celý test trvá asi 3,5 hodiny.

  • … a na PMD 85-1 je k ničemu, protože tam jsou malá písmena a PRTOUT neodřádkuje, tak to zkouším s monitorem z verze 2, to už je lepší, a trošku jsem CPU přitopil, takže to není na tři hodiny, ale na 40 minut… ALUOP nn je OK, chybu mám u DAD. Flagy jsem sice napravil, ale ještě tam něco vrže. 🙂

  • Aha. Už vím, co vrzalo… Nenastavoval jsem bity 1, 3 a 5 u F registru, takže když test podvrhl třeba bit 3 jako 1, tak tam ta jednička zůstala! Takže mi havarovaly i testy na MOV 🙂 Teď už to proběhne všechno OK kromě setu , tak poladím ještě tohle… 🙂