Podpora přerušení procesoru Z80 v monitoru UPM 3.03

Poznámky úvodem: Všechna čísla na této stránce jsou v hexadekadickém tvaru. Assemblerovské výpisy jsou v mnemonice Z80 i u původních kódů pro 8080.

Podpora IRQ

Z80 nabízí tři přerušovací módy označené čísly 0, 1 a 2. Módy 0 a 2 nejsou na PMI-80 jednoduše použitelné, neboť vyžadují spolupráci s dalším hardware. Rozhodl jsem se tedy implementovat mód 1, což naopak bylo velmi jednoduché. Při vzniku IRQ v módu 1 skáče CPU na adresu 0038. Monitor PMI-80 již na této adrese má instrukci skoku na adresu 1FE6 v RAM a i na systému 8080 to slouží ke zpracování přerušení. Na adresu 1FE6 pak můžeme umístit instrukci skoku na libovolnou adresu, kam umístíme program pro obsluhu přerušení. Obsluha přerušení bude bez úprav přenositelná mezi Z80 a 8080.

Mód přerušení se nastavuje instrukcí IM x, kde x je označení módu. Jediné, co tedy bylo potřeba v UPM zajistit za účelem podpory IRQ, bylo někam "vpašovat" instrukci IM 1 tak, aby se vykonala během startu systému. Využil jsem nápad Jirky Koutného. Instrukce IM 1 byla vložena na místo dvou původně nevyužitých byte na adresách 003B a 003C. Dále byla upravena instrukce skoku z adresy 0034 tak, aby došlo k vykonání této instrukce. Vešekerá úprava je tedy následující:

Originální monitor             Monitor s podporou IRQ

0034 : C3 3D 00  jp 003D       0034 : C3 3D 00  jp 003B
...                            ...                     
003B : FF FF                   003B : ED 56     im 1   
003D : 21 E7 01  ld hl, 01E7   003D : 21 E7 01  ld hl, 01E7

Je tedy prakticky vyloučeno, že by takovou úpravou byla ohrožena kompatibilita s původním monitorem. Úprava se provede vždy, pokud je zvolena kompilace pro Z80.

Podpora NMI

#define Z80NMI

Původní monitor neumožňuje zpracovávat NMI. Někomu se může zdát, že zpracování NMI ani není potřeba, já mám na to ovšem jiný názor. PMI-80 slouží především jako výukové, z toho důvodu by podle mého názoru měl mít uživatel možnost si vyzkoušet co nejvíc funkcionality a tedy by měl mít možnost si vyzkoušet použití obou přerušení, IRQ i NMI, když je systém Z80 má k dispozici. Implementovat podporu NMI v monitoru ovšem bylo složitější a došlo při tom k mírné potenciální újmě na kompatibilitě s originálním monitorem. Míru této újmy nechť posoudí každý sám podle následujícího vysvětlení. S ohledem na toto potenciální ohrožení kompatibility je podpora NMI v monitoru UPM nabízena jako možnost, kterou je možno samostatně využít nebo deaktivovat bez ohledu na další nastavení kompilace.

Z80 při NMI skáže na adresu 0066, tuto adresu má v sobě Z80 "nadrátovanou" a nelze ji změnit. Bylo tedy potřeba na adresu 0066 umístit instrukci skoku někam. Nabízí se z 0066 provést skok na 1FE9, kde jsou nevyužité 3 byty a toto místo je 3 byty za bodem, kam se skáče po IRQ. Lze tedy jak na 1FE6, tak na 1FE9 umístit instrukce skoků někam, kde se provede vlastní zpracování přerušení IRQ nebo NMI.

Bylo tedy potřeba na adresu 0066 umístit instrukci jp 1FE9 a zbytek monitoru tomu přizpůsobit.

V originálním monitoru se v oblasti kolem adresy 0066 nachází kód pro rozpoznání příkazové klávesy monitoru, nalezení příslušné procedury v tabulce a její spuštění, případně vypsání chybové hlášky, pokud v tabulce není stisknuté klávese žádný příkaz přiřazen.

Hledal jsem takové řešení, aby se část kódu pro zpracování klávesy i po úpravě stále vešla do původní oblasti končící na adrese 0071, a to se mi zdařilo. Předně bylo potřeba kód zkrátit o 3 byty. To nebyl problém. S ohledem na to, že takto upravený monitor je výhradně určen pro Z80, bylo možno použít Z80 instrukce. Použitím jr místo jednoho jp a využitím djnz místo dec b a jp nz, jsem kýžené 3 byty získal. Další byte by bylo možno získat nahrazením jr za jp na adrese 005E. Celkový zisk by tedy byl 4 byte, takže tu byla možnost získat dokonce ještě jeden byte navíc.

Horší byl problém, jak kód přeuspořádat, aby vložené jp na adrese 0066 nevadilo. Pokud by se totiž mělo toto jp prostě přeskočit přidáním jr 0069 na adresu 0064, ztratí se touto další instrukcí jr dva byty a ve výsledku by tedy jeden byte chyběl. Finální řešení předkládám ve formě porovnání původního a upraveného kódu.

Originální monitor             Monitor s podporou NMI

005C : BE        cp (hl)       005C : BE        cp (hl)
005D : 23        inc hl        005D : 23        inc hl
005E : CA 6D 00  jp z, 006D    005E : C2 69 00  jp nz, 0069
0061 : 23        inc hl        0061 : 4E        ld c, (hl)
0062 : 23        inc hl        0062 : 23        inc hl
0063 : 05        dec b         0063 : 66        ld h, (hl)
0064 : C2 5C 00  jp nz, 005C   0064 : 69        ld l,c
0067 : 21 02 02  ld hl, 0202   0065 : E9        jp (hl)
006A : C3 40 00  jp 0040       0066 : C3 E9 1F  jp 1FE9
006D : 4E        ld c, (hl)    0069 : 23        inc hl
006E : 23        inc hl        006A : 23        inc hl
006F : 66        ld h, (hl)    006B : 10 EF     djnz 005C
0070 : 69        ld l,c        006D : 21 02 02  ld hl, 0202
0071 : E9        jp (hl)       0070 : 18 CE     jr 0040

A teď k té kompatibilitě. Programy, které používájí pouze standardní dokumentované vstupní body do monitoru budou samozřejmě fungovat dále. Problém nastane s programy, které využívaly skok na 0067 k tomu, že se vypsalo Error a skočilo zpět do monitoru. Jedním s těchto programů byly předchozí verze TRAPP, ve stávající verzi jsem to odstranil. Pokud se vyskytne další program, který skáče na 0067 a bude-li jej potřeba používat v této verzi monitoru, bude potřeba skok najít a dotyčný program ručně upravit.

Makro Z80NMI se uplatňuje pouze, je-li kompilace prováděna s makrem PMIZ80, v ostatních případech je makro Z80NMI ignorováno. Pokud zvolíte kompilaci UPM s jiným umístěním RAM, z adresy 0066 se neprovede skok na 1FE9, ale tam, kde bude zadáno umístění RAM při kompilaci.


Zpět