Het hart van de MSX turbo R wordt gevormd door een nieuwe processor: de R800. In dit artikel wordt alles uitgelegd over het selecteren van de processor, de DRAM, kloksnelheid en nog veel meer. In de Sunrise Times vindt u de complete instructietabellen van de R800, die nog nooit eerder in Nederland werden gepubliceerd!
De turbo R bezit twee microprocessors, een Z80 (een Z80A om precies te zijn) en een R800. Het is dus niet zo dat tijdens de Z80 mode gewoon de R800 wordt vertraagd, er is daadwerkelijk een andere processor actief.
De R800 is upwards compatible met de Z80, en kan dus alle Z80 instructies verwerken. Maar de R800 kan meer. Ten eerste kan hij de instructies gemiddeld acht keer sneller uitvoeren, en ten tweede heeft de R800 een aantal nieuwe instructies. Om het verschil in snelheid beter te kunnen uitleggen ga ik u eerst uitleggen wat de term "kloksnelheid" nu eigenlijk precies betekent.
Dit zal u wel een beetje vreemd in de oren klinken, maar de kloksnelheid zegt eigenlijk weinig over de werkelijke snelheid van de microprocessor, en nog minder over de totale snelheid van de computer.
De Z80A heeft een kloksnelheid van 3.579.545 Hz (meestal afgekort tot 3.58 MHz). Dit betekent dat de Z80A per seconde 3.579.545 (ruim 3,5 miljoen!) klokpulsen genereert. Tijdens zo'n klokpuls kan de processor een bepaalde hoeveelheid taken verrichten. En de truuk is nu, dat deze hoeveelheid taken per processor niet gelijk is!
Daarom kan een processor met een lagere kloksnelheid toch sneller zijn. Een voorbeeld: een R800 die draait op 2 MHz, is sneller dan een Z80 op 3.58 MHz! Zo ziet u dat de kloksnelheid slechts weinig zegt. Alleen bij processoren waarvan alleen de kloksnelheid verschilt, is dat een duidelijke maatstaf voor de snelheid. Een Z80B die op 7.16 MHz draait is uiteraard wel twee keer zo snel als een Z80A die op 3.58 MHz draait, omdat het hier om dezelfde soort processor gaat.
Voor de snelheid van de totale computer zegt de kloksnelheid zoals gezegd nog minder. Daar is namelijk ook de snelheid van bijvoorbeeld de videochip, en het geheugen van belang. We kunnen stellen dat een gemiddeld programma op een MSX turbo R vijf � zes keer sneller is dan op een MSX2.
De kloksnelheid van de R800 (dus het aantal klokpulsen van de R800 per seconde), is 7.159.090 Hz, oftewel precies twee maal de kloksnelheid van de Z80A. Dit wordt meestal 7.16 MHz genoemd. Dit betekent overigens dat een klokpuls 1 seconde/ 7159090 = 140 ns (nanoseconde, miljardste seconde) duurt.
Waarom lees je dan overal (zelfs in de offici�le Japanse handboeken van Panasonic!) dat de klokfrequentie van de R800 28.636.360 Hz (28.6 MHz) bedraagt? Dit lijkt onzin, maar is toch ook weer niet zo heel vreemd.
Als men zou schrijven dat de R800 een klokfrequentie heeft van 7.16 MHz (de waarheid!), dan zouden de meeste MSX'ers waarschijnlijk denken dat deze CPU dus net zo snel is als een 7.16 MHz Z80. En dat is niet zo, met zuiver rekenwerk is de R800 gemiddeld (!) acht keer sneller dan een 3.58 MHz Z80. En zo komt men aan 28.636.360 Hz, dat is namelijk exact 8 maal 3.579.545 Hz!
Hoe kan het dat de R800 acht maal zo snel is als de Z80, maar toch maar een twee keer zo hoge kloksnelheid heeft? De oplettende lezertjes weten het antwoord al: de R800 kan meer doen in ��n klokpuls dan de Z80! Een voorbeeld:
De instructie LD A,B neemt op de zowel de Z80 als de R800 1 zogenaamde "machine cycle" (M-cycle) in beslag. Bij de R800 duurt een M-cycle ook ��n T-State, maar bij de Z80 duurt die M-cycle maar liefst vier T-States.
Het aantal klokpulsen is gelijk aan het aantal T-States plus eventuele extra klokpulsen. Bij de Z80 is dat er altijd minimaal 1 (voor de refresh), bij de R800 zijn er een heleboel instructies waarbij geen extra klokpulsen nodig zijn (de refresh vindt daar niet bij elke instructie plaats, maar ongeveer 32 keer per seconde).
Bij deze instructie (LD A,B) is er bij de Z80 een extra klokpuls nodig, waardoor het totaal op vijf komt, bij de R800 is het gewoon ��n klokpuls. Hierdoor is de R800 (bij de instructie LD A,B) dus vijf keer zo snel als de Z80.
Bovendien is de klokfrequentie van de R800 twee keer zo hoog (zoals we al eerder hebben vastgesteld). De instructie wordt op de R800 dus twee maal vijf is TIEN keer zo snel uitgevoerd! Even narekenen: een klokpuls duurt bij de R800 140 ns, en bij de Z80 280 ns. We berekenen nu hoe lang beide processoren doen over het uitvoeren van de instructie LD A,B:
Z80: 5 klokpulsen * 280 ns = 1397 ns R800: 1 klokpuls * 140 ns = 139,7 ns
Dit is dus inderdaad precies tien maal zo snel!
Een overzicht van een aantala andere instructies:
LD A,B 5 (1,1) 1 (1,0) 10 LD A,(HL) 8 (2,1) 3 (2,1) 5,3 LD A,(IX+0) 21 (5,2) 5 (5,0) 8,4 PUSH HL 12 (3,1) 4 (4,0) 6 LDIR (BC<>0) 23 (5,2) 7 (4,3) 6,6 ADD A,B 5 (1,1) 1 (1,0) 10 INC A 5 (1,1) 1 (1,0) 10 ADD HL,DE 12 (3,1) 1 (1,0) 24 (!!!) INC HL 7 (1,1) 1 (1,0) 14 JP 11 (3,1) 3 (3,0) 7,3 JR 13 (3,1) 3 (3,0) 8,7 DJNZ (B<>0) 14 (3,1) 3 (2,1) 9,3 CALL 18 (5,1) 6 (5,1) 6 RET 11 (3,1) 4 (3,1) 5,5
Gemiddeld 9,36
Zoals u ziet is de gemiddelde versnelling in deze tabel dus 9,36 maal, maar u moet niet vergeten dat niet elke instructie evenveel voorkomt in een routine, dus de versnelling zal van routine tot routine verschillen. Het is in ieder geval zeer onwaarschijnlijk dat bovenstaande instructies (en soortgelijke, want LD D,E duurt natuurlijk net zo lang als LD A,B) allemaal evenveel voorkomen. De totale versnelling van een programma is ook nog afhankelijk van andere zaken, zoals bijvoorbeeld de snelheid van de videochip (die overigens ongewijzigd is t.o.v. MSX2/2+!).
Hoe moet u bovenstaande tabel nu lezen? Links staat de mnemonic, in Z80 formaat. Daarnaast het aantal klokpulsen op de Z80. De tijd die zo'n instructie vergt kunt u uitrekenen door dit getal te delen door de kloksnelheid van de Z80. Daarnaast staan twee getallen tussen haakjes. Het eerste getal is het aantal M-cycles, het tweede getal het aantal extra klokpulsen. U kunt het aantal T-states dus vinden door van het opgegeven aantal klokpulsen dat getal af te trekken.
De volgende kolom geeft het aantal klokpulsen van dezelfde instructie op de R800. De tijd kunt u weer uitrekenen door dit getal te delen door de kloksnelheid van de R800 (wel de goede nemen natuurlijk). Het eerste getal tussen haakjes is het aantal M-cycles. Het aantal T-states is bij de R800 altijd gelijk aan het aantal M-cycles! Het tweede getal geeft aan hoeveel extra klokpulsen er zijn. Een voorbeeld:
DJNZ (B<>0) 14 (3,1) 3 (2,1) 9,3
Dit moet als volgt worden gelezen:
Klokpulsen: 14 3 Tijd: 3.91 microseconde 0.42 microseconde M-cycles: 3 2 T-states: 13 (14-1) 2 (3-1) Extra pulsen: 1 1 Versnelling: 9,3
Over het algemeen is het aantal M-cycles op de Z80 en de R800 gelijk, en komt de versnelling vooral doordat de R800 maar ��n T-state nodig heeft per M-cycle, en dit er bij de Z80 meestal 3 � 4 zijn. Bovendien wordt er soms ook nog "bezuiningd" op de extra klokpulsen.
De meest opvallende versnelling is toch wel de ADD HL,DE instruktie, die op de R800 maar liefst 24 keer sneller wordt. Deze instructie is vooral sneller doordat het aantal M-cycles drastisch is verminderd van 3 naar 1. Hoe kan dat? Bij de meeste instructies is het aantal M-cycles bij de R800 en de Z80 gelijk, zoals eerder opgemerkt.
Dit komt door de R800 zoveel mogelijk (!) 16 bits is gemaakt. In Japan wordt er ook geadverteerd dat de R800 16 bit is. Toch is de R800 niet helemaal 16 bit, de externe adresbus is namelijk nog steeds acht bits. De hele MSX computer is acht bits, en als je een processor met een 16 bits externe adresbus in een MSX zou plaatsen, dan lijkt het niet veel meer op een MSX! Er zouden dan veel (dure) aanpassingen nodig zijn.
Vandaar dat men de externe adresbus ongemoeid heeft gelaten. Maar intern is de R800 wel 16 bits, en daardoor gaan de 16 bits instructies (zoals ADD HL,DE) zo ontzettend snel!
In de Sunrise Times staan de complete instructietabellen van de R800. Dit is de eerste keer dat deze tabellen in Nederland worden gepubliceerd!!
Als u de instructietabellen bekijkt, zult u zien dat de meeste mnemonics zijn veranderd. De instructies zijn hetzelfde gebleven, maar de namen zijn gemoderniseerd. Een overzicht van de instructies die een naamsverandering hebben ondergaan:
XCH EX XCHX EXX MOVE (HL++),(DE++) LDI MOVE (HL--),(DE--) LDD MOVEM (HL++),(DE++) LDIR MOVEM (HL--),(DE--) LDDR CMP A,(HL++) CPI CMP A,(HL--) CPD CMPM A,(HL++) CPIR CMPM A,(HL--) CPDR ADDC ADC SUBC SBC AND A, AND OR A, OR XOR A, XOR CMP A, CP CLR RES ROLA RLCA RORA RRCA ROLCA RLA RORCA RRA ROL RLC ROR RRC ROLC RL RORC RR ROL4 (HL) RLD ROR4 (HL) RRD SHL SLA SHR SRL SHRA SRA BR JP BNZ JP NZ, BZ JP Z, BNC JP NC, BC JP C, BPO JP PO, BPE JP PE, BP JP P, BM JP M, SHORT BR JR SHORT BNZ JR NZ, SHORT BZ JR Z, SHORT BNC JR NC, SHORT BC JR C, DBNZ DJNZ BRK RST IN (HL++),(C) INI IN (HL--),(C) IND INM (HL++),(C) INIR INM (HL--),(C) INDR OUT (C),(HL++) OUTI OUT (C),(HL--) OUTD OUTM (C),(HL++) OTIR OUTM (C),(HL--) OTDR ADJ A DAA NOT A CPL NEG A NEG NOTC CCF SETC SCF
Voor degenen die nog nooit een instructietabel hebben gezien is een beetje uitleg wel op z'n plaats. In de eerste kolom staat de mnemonic, de "syntax" van de instructie. Daarnaast een symbolische notatie van de werking van deze instruktie. In de volgende kolom wordt aangegeven hoe de vlaggen worden be�nvloedt. Daarvoor worden de volgende tekens gebruikt:
stip vlag wordt niet be�nvloedt pijltje stand van vlag wordt bepaald door de uitkomst van de instructie 0 vlag staat op 0 na instructie 1 vlag staat op 1 na instructie ? vlag onbekend P P/V vlag geeft pariteit V P/V vlag geeft overflow
In de volgende kolommen wordt de opcode gegeven, in binair en in hexadecimaal. De kolom "B" geeft aan hoeveel bytes de instructie in beslag neemt, de kolom "C" het aantal M-cycles (C is dus een afkorting van Cycles). Zoals we eerder hebben vastgesteld is dit altijd gelijk aan het aantal T-states, maar het aantal klokpulsen kan een paar meer zijn.
Verder worden nog een heleboel symbolen gebruikt. Een overzicht:
a{7} bit 7 van register a a{4..7} bit 4 t/m 7 van register a de:hl een 32 bits waarde, waarbij DE de hoogste 16 bits bevat (ix+d) d is de 8 bits offset C carry vlag Z zero vlag P/V parity/overflow vlag S sign vlag N subtract vlag H half-carry vlag IFF interrupt flipflop r,r' A,B,C,D,E,H,L u,u' A,B,C,D,E,IXH,IXL v,v' A,B,C,D,E,IYH,IYL p IXH,IYL q IYH,IYL ss BC,DE,HL,SP pp BC,DE,IX,SP rr BC,DE,IY,SP qq BC,DE,HL,AF e offset bij SHORT BR (JR bij Z80) k adres bij BRK (RST bij Z80) nn 16 bits constante n 8 bits constante b bitnummer (0-7) NOT logische bewerking tmp tijdelijke opslag van een bit B aantal bytes C aantal (M) cycles
Voor de logische bewerkingen OR, XOR en AND worden de wiskundige notaties gebruikt (OR is een "V", XOR een "omgekeerde A" en AND een "omgekeerde V").
De instructietabellen zouden wel erg lang worden als per mogelijke instructie de opcode zou zijn vermeld. Bovendien is dan de logica in de opcodes niet meer uit de tabel op te maken. Vaak moet de opcode dan ook (op binaire wijze) zelf worden samengesteld. Met een voorbeeld kan ik het beste laten zien hoe dat gaat.
U wilt bijvoorbeeld de opcode van de instructie LD C,H weten. Als u de instructietabellen in de Sunrise Times erbij pakt, kunt u daar LD r,r' vinden. In de kolom opcode staat:
7 6 5 4 3 2 1 0 <-- bitnummers 0 1 r r' <-- opcode
Onderaan ziet u de tabel voor r en r'. U ziet daar dat 001 staat voor C en 100 voor H. U vervang nu r en r' in de binaire opcode door de gevonden codes voor C en H. De opcode wordt dan:
7 6 5 4 3 2 1 0 <-- bitnummers 0 1 0 0 1 1 0 0 <-- opcode
U heeft de opcode gevonden, het is &B01001100.
De R800 kent ten opzichte van de Z80 drie geheel nieuwe instructies, bovendien zijn de indexregisters (IX en IY) nu ook per 8 bits aanspreekbaar. U kunt in de instructietabellen opzoeken bij welke instructies dat mogelijk is, te herkennen aan u, v, p of q.
De andere nieuwe instructies zijn:
IN F,(C)
MULUB A,r
MULUW HL,ss
De eerste instructie is erg handig. Routines waarbij (een) bepaald(e) bit(s) in de gaten wordt gehouden, worden door deze instructies korter, sneller en gebruiken minder registers. Een voorbeeld: stel u moet bit 0 van I/O poort C in de gaten houden. De routine moet net zolang wachten tot bit 0 op 0 staat. Op de Z80 zou dat er als volgt uit zien:
WACHT: IN A,(C)
BIT 0,A
JR NZ,WACHT
Dit zijn 6 bytes en het A-register wordt gebruikt.
Op de R800 kan het ook zo:
WACHT: IN F,(C)
JR C,WACHT
Dit zijn 4 bytes en het A-register wordt niet gebruikt. Bovendien is deze manier sneller. (N.B. Het carry bit is bit 0 van het F-register.)
Echt super zijn de vermenigvuldigingsinstructies van de R800. De instructie MULUB (MULtiply Bytes) vermenigvuldigt A met B, C, D of E en zet het 16 bits antwoord in HL. Dit gaat razendsnel, deze instructie gebruikt slechts 14 klokpulsen (1.96 micro- seconde).
De instructie MULUW (MULtiply Words) vermenigvuldigt HL met BC of SP (zal in de praktijk meestal BC zijn), en zet het antwoord in DE en HL, waarbij de hoogste bits in DE terecht komen. Deze instructie duurt slechts 5.03 microseconde (36 klokpulsen)!
Deze twee instructies zijn ontzettend krachtig en maken zeer snelle "realtime calculated" animaties mogelijk, bijvoorbeeld vectorgraphics. Ook voor fractals is dit erg handig, die kunnen nu veel en veel sneller worden berekend.
Een leuke vergelijking met de Z80 is dat de MULUW HL,BC instructie op de R800 net zolang duurt als een CALL instructie op de Z80!! Bij de Z80 moet voor vermenigvuldigen een aparte routine worden geschreven, en als je die met een CALL aanroept is de R800 in de tussentijd al klaar met de complete vermenigvuldiging. U begrijpt wel dat de R800 als het om vermenigvuldigen gaat veel meer dan acht maal sneller is, ik denk wel honderd maal sneller. Bovendien spaart het een hoop programmeertijd, want berekeningen kunnen een stuk makkelijker worden geprogrammeerd.
Onderstaand voorbeeld is een routine die HL=A*B uitrekent. Op de R800 is ��n instructie daarvoor voldoende: MULUB A,B. Deze instructie is sneller dan een CALL instructie bij de Z80! Bij de Z80 zou je dan ongeveer zo'n routine krijgen:
; MULUB A,B voor de Z80
; Door Stefan Boer
; Voor Sunrise Special #1
; Werking: HL=A*B
; In: A,B
; Uit: HL
; Gebruikt: DE
; Methode: Herhaald optellen
MULUB: LD HL,0
LD E,A
LD D,0 ; LD DE,A
XOR A
CP B
RET Z ; B=0, dan antwoord 0
MULTI: ADD HL,DE
DJNZ MULTI ; tel B maal DE bij HL op
RET
U kunt zien dat dit heel wat meer bytes en tijd in beslag neemt, de CALL MULUB duurt op de Z80 al langer dan de MULUB A,B instructie op de R800.
Nu denkt u misschien dat u een nieuwe assembler nodig heeft als u software voor de R800 wilt ontwikkelen. Dit is zeker niet het geval! Alle bestaande Z80 assemblers kunnen gewoon worden gebruikt. Dit is ook de reden waarom er nog geen speciale R800 assembler op de markt is gebracht.
Het zou trouwens ook verwarrend zijn voor een programmeur die de Z80 assemblertaal al beheerst, om de nieuwe mnemonics voor de R800 te leren.
"En de nieuwe instructies dan?" hoor ik u denken. Nu, die kunt u gewoon met DEFB instructies simuleren! Alleen de disassembler zal hier een beetje van in de war raken, maar dat is toch niet zo'n ramp? Ik zal nu voor alle nieuwe instructies uitleggen hoe ze met een gewone Z80 assembler (zoals WB-ASS2) kunnen worden gebruikt.
Bij de indexregisters IX en IY is het ontzettend makkelijk. Het is u vast al wel eens opgevallen, dat de opcodes hetzelfde zijn als die voor de instructies voor HL, behalve dan dat er een extra code voor staat. Die code is &HDD voor IX en &HFD voor IY. Een voorbeeld:
Mnemonic: Opcode:
LD HL,&H1BBF 21 BF 1B LD IX,&H1BBF DD 21 BF 1B LD IY,&H1BBF FD 21 BF 1B
U kunt voor alle instructies met IXL, IXH, IYL en IYH de assembler op een heel eenvoudige manier voor de gek houden. Voor IXL en IYL zet u een L en voor IYH en IXH een H. Door er een DEFB &HDD voor te zetten wordt de L resp. H voor de R800 IXL resp. IXH, met een &HFD hetzelfde voor IY. Voorbeelden:
DEFB &HDD
LD A,L ; LD A,IXL
DEFB &HFD
LD L,H ; LD IYL,IYH
DEFB &HDD
LD H,B ; LD IXH,B
Zoals u ziet is de instructie LD IXH,IYL niet mogelijk, u kunt immers niet de code voor IX �n de code voor IY voor een instructie plaatsen. Maar verder is alles mogelijk, zie de instructietabellen in de Sunrise Times.
Voor deze instructie kunt u gewoon DEFB &HED,&H70 invullen. U kunt dat het beste zo in de assemblerlisting zetten:
DEFB &HED,&H70 ; IN F,(C)
Zo kunt u goed zien dat het geen data bytes zijn maar eigenlijk gewoon een opcode. Door een foutje in die assemblers zullen sommige assemblers dit overigens disassembleren als IN (HL),(C). Dit is een niet bestaande instructie, maar het komt omdat IN F,(C) voor de R800 gewoon een speciaal geval is van IN r,(C). Bij andere instructies (bijvoorbeeld LD A,(HL)) wordt (HL) weergegeven door dezelfde bits als F bij de IN F,(C) instructie, vandaar de fout.
Voor deze instructies kunt u de instructietabellen van de R800 die in de Sunrise Times staan afgedrukt gebruiken. U kunt de opcodes aan de hand daarvan samenstellen (zie het stukje over opcodes samenstellen), en ze met DEFB instructies in de code opnemen. Bijvoorbeeld:
DEFB &HED,&B11000001 ; MULUB A,B
Ook hier is het weer aan te raden om bij het commentaar de R800 mnemonic in te vullen, zo houdt u uw assemblerlistings leesbaar.
Nu zit ik wel een lang artikel over de R800 te schrijven, maar als u niet weet hoe u deze wonderprocessor moet selecteren heeft u daar nog niet veel aan.
In het MAIN ROM van de MSX turbo R zitten vier nieuwe BIOS routines, waarvan er twee voor het schakelen tussen de Z80 en de R800 zijn bedoeld. Dat zijn:
CHGCPU &H0180 Selecteer CPU
Invoer: A register
MSB 7 6 5 4 3 2 1 0 LSB
LED 0 0 0 0 0 X X
LED=1: led wordt bestuurd
LED=0: led wordt niet bestuurd
XX=00: Z80
XX=01: R800 ROM
XX=10: R800 DRAM
Gebruikt: AF
GETCPU &H0183 Bepaal huidige CPU
Invoer: -
Uitvoer: A register
0: Z80
1: R800 ROM
2: R800 DRAM
Over LED is wegens foutieve publikaties in andere Nederlandse MSX bladen een misverstand ontstaan. Dit bit bestuurt niet het led (1=aan, 0=uit), maar bepaalt of de status van het led (aan of uit) door de gekozen CPU moet worden be�nvloed!
Stel u zit in R800 mode en het lampje brandt. Doet u nu LD A,0 en daarna CALL CHGCPU, dan zal de Z80 uitgaan, maar het lampje blijft branden. Bit 7 van register A (LED) is immers 0, en dus zal het led niet door de gekozen CPU (Z80, normaal gesproken moet het lampje dus uit!) worden be�nvloed.
Andersom kan ook, als u in Z80 mode zit (lampje uit) en u selecteert de R800 mode door een CALL &H180 te geven terwijl het A register de waarde 1 bevat (R800), dan zal de R800 wel aangaan, maar het lampje niet!
Bij "normaal" gebruik van deze BIOS routine, waarbij de stand van het lampje in overeenkomst is met de actieve processor (aan=R800, uit=Z80), dient u dus ��n van de volgende drie waardes te gebruiken:
&H80 Z80 &H81 R800 ROM &H82 R800 DRAM
U kunt met GETCPU opvragen welke processor er op dat ogenblik actief is. U kunt op de volgende manier dus het lampje in de goede stand zetten:
CALL &H183 ; welke CPU actief?
SET 7,A ; LED besturen aan
CALL &H180 ; CPU zelfde, LED besturen
Ik heb het in bovenstaande tekst vrolijk over DRAM, zonder uit te leggen wat dat nou eigenlijk inhoudt. De DRAM mode is een slimme truuk, die ook door andere moderne computers wordt gebruikt. In feite is het niet de R800 die voor de DRAM mode zorgt, maar de S1990.
Bij de Z80 maakt het niet uit of er RAM of ROM wordt gelezen, dit gaat beiden even snel. Omdat er in de turbo R dezelfde ROMs worden gebruikt als in een MSX1/2/2+, moeten die op een langzame snelheid worden gelezen. Telkens als de R800 ROM moet lezen, schakelt hij even terug naar een langzamere snelheid. Vandaar dat op een R800 het lezen van RAM sneller is dan ROM, want in de turbo R wordt "snel" RAM gebruikt, zodat terugschakelen niet nodig is.
Vooral in BASIC wordt er continu uit de ROM gelezen. De BASIC zelf staat immers op ROM! De R800 ROM mode is daarom in BASIC helemaal niet zo snel, omdat er telkens wordt teruggeschakeld naar een lagere snelheid. De oplossing is de DRAM mode.
Bij het opstarten van de computer wordt de 64 kB meest gebruikte ROM naar de bovenste 64 kB van het RAM gekopieerd. De turbo R heeft dan dus 64 kB minder werkgeheugen over. De ROM die gekopieerd wordt is:
MAXPGE-3: MAIN ROM 0000-3FFF MAXPGE-2: MAIN ROM 4000-7FFF MAXPGE-1: SUB ROM MAXPGE : KANJI ROM
Voor MAXPGE moet u het hoogste memorymapper segment invullen. De FS-A1ST heeft bijvoorbeeld 256 kB, dat zijn 16 memorymapper segmenten van 16 kB. Daar het nummeren bij 0 begint, is MAXPGE dus gelijk aan 15. De SUB ROM staat dus in memorymapper segment 14.
Als de DRAM mode wordt geselecteerd komt de S1990 in actie. Wordt nu ��n van de hierboven genoemde ROMs gelezen door de R800, dan zorgt de S1990 ervoor dat niet de ROM maar de RAM (waarin het ROM is gekopieerd) wordt gelezen. De R800 hoeft dan niet te wachten op het langzame ROM, en werkt een stuk sneller. De S1990 zorgt ervoor dat er niet in de DRAM kan worden geschreven (zo heet de tot ROM verklaarde RAM), en zorgt er tevens voor dat het RAM dat voor de DRAM wordt gebruikt niet meer te gebruiken is. Probeert u er toch iets uit te lezen, dan zal dat altijd de waarde &HFF opleveren.
Er zijn dus twee verschillende R800 standen. Bij de R800 ROM mode gaat het net als bij de Z80 mode, er wordt gewoon ROM gelezen. Vandaar de naam ROM mode. Deze mode is vooral onder BASIC langzaam, omdat daar veel ROM wordt gelezen. Onder machinetaal springt de computer ook 60 keer per seconde naar ROM, voor de interrupt routine op &H38. Ook als het machinetaalprogramma de BIOS gebruikt zal er naar het ROM worden gesprongen. Daarom heeft het selecteren van de DRAM mode ook bij machinetaal zin, al is heeft het minder effect dan bij BASIC. De R800 ROM mode heeft als belangrijkste voordeel dat het volledige RAM geheugen vrij is als werkgeheugen.
De DRAM mode is sneller, maar kost wel 64 kB geheugen. U kunt dus zelf per situatie beslissen of u de ROM mode of de DRAM mode wilt gebruiken.
U kunt bij de turbo R als het ware in het ROM POKEn. Dit gaat als volgt:
- Selecteer de R800 ROM mode (of Z80 mode)
In de bovenste 64 kB van de memorymapper staat nu een kopie van de ROM, waar u net zoveel in kunt knoeien als u wilt. Als u klaar bent
- Selecteert u de R800 DRAM mode
Nu wordt het RAM waar u zojuist in hebt geknoeid gebruikt voor de DRAM, en dus hebt u als het ware in de ROM gePOKEt!
Je zou misschien denken dat het ROM elke keer dat de DRAM wordt geselecteerd in het RAM wordt gekopieerd. Dat is niet zo, anders zou bovenstaande truuk ook niet werken. De reden hiervoor is dat het kopi�ren van 64 kB toch wel even tijd kost, en op die manier zou de CHGCPU routine veel te langzaam worden.
Het ROM wordt alleen bij een reset in het RAM gekopieerd, en hiermee dient terdege rekening gehouden te worden! Als u de DRAM mode selecteert terwijl het RAM dat voor de DRAM mode wordt gebruikt verminkt is, kan dit onverwachte gevolgen hebben!
Het aansturen van de diskdrive gaat niet goed onder R800 stand. De diskcontroller kan bij zo'n hoge snelheid de processor blijkbaar niet bijhouden. Tenminste, bij het saven. Het laden onder R800 stand gaat prima, maar bij saven kan er van alles mis gaan. Het gaat niet altijd fout, maar vaak treedt er een Disk I/O error op of er wordt gewoon niets gesaved.
Bij MSX-DOS2.31/MSX Disk BASIC 2.01 is daar rekening mee gehouden. Bij elke diskactie wordt de R800 stiekem uitgezet. Ik schrijf "stiekem", omdat het lampje niet wordt uitgezet. Dat blijft branden, omdat de R800 wordt uitgezet door
LD A,0
CALL &H180 ; R800 uit, lampje niet
En u hebt aan het begin van het artikel al geleerd dat het lampje dan niet uitgaat. Hierdoor wordt behalve het saven ook het laden vertraagd, wat eigenlijk niet nodig is.
De ontwikkelaars van de turbo R hebben dit in de MSX- DOS2.31/Disk BASIC 2.01 ROMs ingebouwd, omdat dat normaal gesproken onder R800 stand wordt gedraaid.
Onder DOS1 mode (MSX-DOS1.11/Disk BASIC 1.0) wordt dit niet gedaan. Die stand is tenslotte bedoeld voor het uitvoeren van MSX1/2/2+ programma's, en die werken toch onder Z80 stand.
Toch zullen programmeurs vaak MSX turbo R software voor DOS1 mode ontwikkelen, omdat de geheugenhuishouding van DOS2 nogal irritant is. De R800 wordt dan dus aangezet onder DOS1 mode, terwijl de diskROM daar geen rekening mee houdt.
In het technical databook van de turbo R staat dan ook dat als een programmeur toch de combinatie DOS1/R800 gebruikt, hij bij elke diskactie de R800 uit moet zetten. De programmeur van Seed of Dragon heeft zich daar netjes aan gehouden; elke keer als het disklampje gaat branden zie je bij dat spel het R800 lampje uitgaan.
Hoewel dit niet in het technical databook staat, kan de R800 bij het laden rustig aan blijven staan. Alleen bij saven zijn er problemen. Onder R800 stand gaat het laden zelfs aanmerkelijk sneller! MicroCabin wist dit blijkbaar ook, want bij bijvoorbeeld Fray wordt de R800 alleen uitgezet als er wordt gesaved.
Conclusie:
Z E T D E R 8 0 0 A L T I J D U I T A L S
E R I N D O S 1 M O D E N A A R D I S K
W O R D T G E S C H R E V E N ! ! !
Nogmaals: bij laden kunt u de R800 rustig aan laten staan.
Bij het bekijken van een artikel over de R800 in een Japans blad kwam ik de term "DRAM page access" tegen, en ik had eerst geen flauw idee wat dat was. Later kwam ik er wel achter.
Wanneer van het adres in de externe databus de high-byte niet verandert, zal de R800 de high-byte van het adres niet opnieuw op de adresbus plaatsen (lijkt heel logisch, maar de Z80 kent deze truuk niet!)
Een "page" is in de processorwereld een stukje geheugen van 256 bytes, dat op een 256-byte grens begint, dus &H??00 - &H??FF. Verwar dit niet met de bij MSX bekende term "page", een stuk geheugen van 16 kB.
Het hierboven beschreven truukje dat de R800 gebruikt heet "Page mode access" en verhoogt de snelheid nog eens met ongeveer een factor twee.
De programmeur kan met "paged DRAM access" maximaal van deze truuk gebruik maken. Paged DRAM access betekent dat alle geheugentoegang van een routine (dus ook de routine zelf) in dezelfde page staat (bijvoorbeeld &HD000-&HD0FF). Dit is wel zeer beperkt, want met alle geheugentoegang bedoel ik dan dus echt ALLE geheugentoegang, inclusief stack, variabelen en constanten. Het uitzetten van de interrupts is in verband met die stack dan ook ten zeerste aan te raden. Maar deze moeite wordt wel beloond met een ultra-snelle routine!
We begrijpen nu ook beter hoe het komt dat een LD A,B instruktie op de R800 tien keer zo snel is dan op de Z80, terwijl een LD A,(HL) maar 5,3 keer zo snel is.
Bij het uitvoeren van een instructie hoort namelijk ook het ophalen van de opcode uit het geheugen. Omdat bij een LD A,B instructie de externe adresbus niet wordt gewijzigd, hoeft bij het ophalen van de volgende opcode (meestal) alleen de low-byte van de externe adresbus te worden veranderd. Bij de LD A,(HL) instructie is de externe adresbus wel veranderd, zodat zowel de low- als de high-byte van het PC register (Program Counter) naar de externe adresbus moeten worden verplaatst.
Tot slot wil ik Alex Wulms nog bedanken voor zijn medewerking, een gedeelte van de informatie in dit artikel is van hem afkomstig. De overige informatie heb ik zelf uitgevonden of komt uit Japanse bladen.
De R800 is (inclusief toetsenbord, diskdrive, kast en een zooitje chips onder de naam FS-A1GT) te koop bij MSX Club Gouda voor fl. 1795,-. Verplicht voor elke MSX'er die bij de tijd wil blijven (maar nu nog een antieke MSX2 heeft)!
Stefan Boer