1986-Club80-17, S27-32 ## ﻿Z80, HD64180 und Illegals im ROM-Modus Das Herz unseres kleinen Haufens Silikonmasse besteht bekanntermaßen aus einem Z80. Dieser Z80 kann über 1100 Befehle verarbeiten, von denen aber nur 694 von den Erbauern vorgesehen waren. Der Rest ist also Abfallprodukt. Nun gibt es einen neuen Prozessor, den HD64180, der Z80-kompatibel ist, aber einige Sachen mehr kann (512Kb RAM verwalten. DMA, Schnittstelle...). Nur haben die Erbauer dieses Dings leider vergessen, die Befehle des Z80 zu berücksichtigen, die nicht offiziell dokumentiert sind. Das kann böse Probleme geben, denn wenn der neue Proz auf einen ihm unbekannten Befehl trifft, macht er einen Brutalo-Reset nach 0000h, was in unserem Fall jedes Programm ins Jenseits befördert. Es wäre dies kein Problem, wenn niemand die "Illegals" bzw. die nicht dokumentierten Befehle benutzen würde, aber viele Programmierer tun es doch. Prominentes Beispiel der Editor/Assembler ZEUS (3 Illegals). Ihr könnt nun den neuen Prozessor vergessen (sehr schwer!), alle Programme mit Illegals vergessen (nicht ganz so schwer), alle Illegals durch normale Befehle ersetzen (schwer) oder dem HD64180 die unbekannten Befehle beibringen (fast leicht). Punkt 3 erschien mir brauchbar, bis sich ZEUS nach den Änderungen so merkwürdig benahm. Leider sind die Ersatz-Befehle für die Illegals nämlich einen kleinen Tick länger als die Illegals und das gibt big problems. Also auf zu Punkt 4! Vorraussetzung: Veränderliches RAM/ROM bei 0000h: bei jedem CP/M-fähigen Rechner der Fall. Außerdem habe ich in meinem kleinen Programm noch einiges ausgenutzt: Arnulf hett seggt1, daß RST 00h nie gebraucht wird. Also benutze man RST 00h für etwas anderes. In diesem Fall bot sich ein Banking an, das Helmuts alten Banker simuliert. Verfahrensweise: Der Speicher von 8000h-ffffh wird als Common 1 definiert und je nach gewünschter Bank wird der Offset von Common 1 neu gesetzt. Bank 0 ist die normale Bank, also sind dann Interrupts erlaubt. Ansonsten werden die Interrupts gesperrt. Die Bank-Nr. wird vor dem RST 00h in A geladen. Mein kleiner IIs kennt ein Parallel-RAM. D.h. Neben Tastatur. Bildschirm etc., die ja memory-mapped-I/O sind, gibt es einen RAM-Bereich von 3400h-3fffh. Je nach Wunsch kann ich nun entweder Ein-/Ausgaben vornehmen oder in diesem Extra-RAM einige zusätzliche Programme laufen lassen. Wiederum müßte jeder TRS80-CP/M-Rechner irgendetwas in der Richtung haben. Nun versteht Ihr auch, warum ich in der Überschrift von "ROM-Modus" sprach. Der ganze Kram klappt bei CP/M in dieser Form nicht. Dafür andere Lösungen zu suchen, überlasse ich den CP/M-Freaks. Zu guter Letzt kann ich auch das ROM/RAM überschreiben (s. wiederum CP/M-fähige Rechner). Da sich in dem ROM allerhand Müll angesammelt hat kann man gewisse Teile ohne Skrupel killen, was ich auch getan habe. Mit diesen ganzen Einschränkungen wird das Programm zwar sehr auf eine Maschine festgelegt, aber wer wird sich schon einen HD64180 anschaffen? Wohl doch nur Leute, die sowieso am Satteln sind und bei deren Drahtansammlungen nicht viel vom TRS80 übrig geblieben ist. Noch kurz zum eigentlichen Programm: Der erste Teil ist nur der Ansprung der Routine von 0C00h aus. Der zweite Teil ist ein Ausgang aus der Routine, bei dem die Interrupts ausgeschaltet bleiben. Die anderen Ein/Aus-Routinen stellt OVL3/SYS aus dem Gdos 2.4 zur Verfügung. Der dritte Teil ist derjenige, der beim Aufruf die Routine ins Parallel-RAM bringt. Danach folgt die eigentliche Routine, die im gegenwärtigen Zustand noch nicht mal 100h Bytes lang ist. Sie berücksichtigt alle Illegals, die in einen Artikel der "data welt" in Mai/Juni 1986 erwähnt wurden. Die HD64180-spezifischen Befehle IN0/OUT0 wurden über DBs realisiert, weil mein alter ZEUS sie natürlich nicht kennt. Der Programmierstil ist leider sehr "unschön", wie mein Prof sagen würde, vor allem aufgrund der vielen Patches direkt im Programmablauf, aber es tut seinen Dienst. Gerald Schröder Hardware: Helmut Bernhardt Literatur: "TAV’s Z80 Tuning" aus "data welt" 5 und 6 ’86 Z80-Reference-Manual
    		00001 ;	Error-Trap für Genie IIs mit HD64180
    		00002 ;	Weihnachten ’86 by Gerald Schröder
    		00003
    		00004
    	06A0	00005 pramon	EQU	06a0h		;schaltet Par.-RAM ein
    	06AB	00006 pramoff	EQU	06abh		;schaltet Par.-RAM aus
    		00007
    		00008
    		00009 ;
    		00010
    		00011 ; 0000: Ansprung Error-Trap und RST 00h
    		00012
    0000		00013		ORG	0
    0000	CDA006	00014		CALL	pramon		;Par.-RAM ein
    0003	C30034	00015		JP	routin-offset	;anspringen
    		00016
    		00017
    		00018	;
    		00019
    		00020	;	neuer Ausgang: Par.-RAM aus und Interrupts
    		00021	;	bleiben disabled
    		00022
    06D2		00023		ORG	06d2h
    06D2	DBFE 	00024 prama	IN	A,(0feh)
    06D4	CB87 	00025		RES	0,A
    06D6	D3FE 	00026		OUT	(0feh),A
    06D8	F1	00027		POP	AF
    06D9	C9	00028		RET
    		00029
    		00030
    		00031	;
    		00032
    		00033	;	Initialisierungsroutine
    		00034
    5200		00035		ORG	5200H
    5200	3E80	00036 start	LD	A,80h		;Common 1 ab 8000h
    5202	ED	00037		DB	0edh,39h,3ah 	;setzen (OUT0 (3ah),A)
    		00038
    5205	CDA006 	00039 		CALL	pramon		;Par.-RAM ein
    5208	211652 	00040		LD	HL,routin	;Routine
    520B	110034 	00041		LD	DE,routin-offset ;dorthin
    520E	01C900 	00042		LD	BC,ende-routin	;übertragen
    5211	EDB0	00043		LDIR
    5213	C3AB06	00044		JP	pramoff 	;Par.-RAM aus und ab
    		00045
    		00046
    		00047	;
    		00048
    		00049	;	Routine im Par.-RAM für Error-Trap und RST 00h
    		00050	;	bei Error: fehlende Codes simulieren
    		00051	;	bei RST 00h: Bank A einschalten
    		00052
    1E16		00053 offset	EQU	$-3400h
    5216	F5	00054 routin	PUSH	AF
    5217	ED	00055		DB	0edh,38h,34h	;IN0 A,(34h)
    521A	CB7F	00056		BIT	7,A		;TRAP gesetzt?
    521C	2010	00057		JR	NZ,illopc	;ja, illegaler Opcode
    		00058
    		00059	;*******************************
    		00060	;* Banking; Bank A einschalten *
    		00061	;*******************************
    		00062
    521E	F1	00063		POP	AF
    521F	F5	00064		PUSH	AF 		;retten
    5220	07	00065		RLCA
    5221	07	00066		RLCA			;korr. Offset erzeugen
    5222	07	00067		RLCA			;(Basis Common 1 neu)
    5223	ED	00068		DB	0edh,39h,38h	;OUT0 (38h),A
    5226	B7	00069		OR	A 		;Bank 0?
    5227	C2D206 	00070		JP	NZ,prama	;nein, keine Interrupts
    522A	F1	00071		POP	AF
    522B	C3AB06 	00072		JP	pramoff 	;Interrupts ein
    		00073
    		00074
    		00075
    		00076	;*********************************
    		00077	;* illegaler Opcode: simulieren  *
    		00078	;*********************************
    		00079
    522E	CBBF	00080 illopc	RES	7,A 		;TRAP löschen
    5230	ED	00081		DB	0edh,39h,34h	;OUT0 (34h),A
    5233	322534 	00082		LD	(ufo-offset),A 	;UFO retten
    5236	F1	00083		POP	AF 		;A vom Stack
    5237	E3	00084		EX	(SP),HL 	;HL mit Err.-Adr. tausch
    5238	F5	00085		PUSH	AF 		;A wieder retten
    5239	C5	00086		PUSH	BC 		;BC als Hilfsregister
    523A	3E00	00087		LD	A,0 		;UFO
    523B		00088 ufo	EQU	$-1
    523C	CB77	00089		BIT	6,A 		;gesetzt?
    523E	2801	00090		JR	Z,nosub 	;nein, Opc. direkt davor
    5240	2B	00091		DEC	HL
    5241	2B	00092 nosub	DEC	HL 		;Zeiger auf ill. Opc.
    5242	7E	00093		LD	A,(HL) 		;laden
    5243	47	00094		LD	B,A 		;und retten
    5244	FECB	00095		CP	0cbh		;CBxx? (SLIA)
    5246	23	00096		INC	HL 		;Zeiger weiter
    5247	7E	00097		LD	A,(HL) 		;2. Byte laden
    5248	200F	00098		JR	NZ,ddfd 	;nein, Oper. mit IX/Y
    		00099
    		00100	;***********************************
    		00101	;* illegaler Opcode; CBxx = SLIA x *
    		00102	;***********************************
    		00103
    524A	D620	00104		SUB	20h 		;korrigieren
    524C	323F34 	00105		LD	(CBxx-offset),A ;in den Programm-Text
    		00106
    524F	C1	00107		POP	BC 		;Register zurück
    5250	F1	00108		POP 	AF
    5251	23	00109		INC	HL 		;PC neu setzen
    5252	E3	00110		EX	(SP),HL 	;und HL zurück
    5253	37	00111		SCF			;für invertiert!!!
    5254	CB10	00112		RL	B		;und rotieren
    5255		00113 CBxx	EQU 	$-1 		;10-17 für Register B-A
    5256	C3AB06 	00114 ab	JP	pramoff 	;weiter im Programm
    		00115
    		00116
    		00117	;***************************************
    		00118	;* illegaler Opcode: erstes Byte DD/FD *
    		00119	;***************************************
    				00120
    5259	FECB	00121 ddfd	CP 	0cbh		;danach CBh?
    525B	2828	00122		JR 	Z,ddfdcb	;ja
    525D	326834	00123		LD 	(ersatz-offset),A 	;in den Text
    5260	FE26	00124		CP	26h		;"LD hX/Y, konstante"?
    5262	2807	00125		JR 	Z,ldkon		;ja
    5264	FE2E	00126		CP 	2eh		;"LD IX/Y, konstante"?
    5266	2803	00127		JR 	Z,ldkon		;ja
    		00128
    5268	AF	00129		XOR 	A 		;keine Konstante; NOP
    5269	1802	00130		JR	weiter
    		00131
    		00132	;	Konstante nach MSB/LSB von IX/Y
    		00133
    526B	23	00134 ldkon	INC	HL 		; Zeiger auf Konstante
    526C	7E	00135		LD 	A,(HL) 		;diese laden
    		00136
    526D	326934 	00137 weiter	LD	(konst-offset),A 	;u. in den Text
    5270	78	00138		LD	A,B 			;DD/FD zurück
    5271	326534 	00139		LD 	(ddfd1-offset),A	;setzen
    5274	326B34	00140		LD 	(ddfd2-offset),A
    		00141
    5277	C1	00142		POP	BC 		;alle Register zurück
    5278	F1	00143		POP	AF
    5279	23	00144		INC	HL 		;PC neu
    527A	E3	00145		EX	(SP),HL 	;HL zurück
    		00146
    527B	DDE5	00147 ddfd1	PUSH	IX 		;bzw. IY
    527D	E3	00148		EX	(SP),HL 	;nach HL
    527E	7F	00149 ersatz LD 	A,A 		;Operation ausführen
    527F	00	00150 konst	NOP 			;evtl. Konstante
    5280	E3	00151		EX	(SP),HL 	;neues IX/Y zurück
    5281	DDE1	00152 ddfd2 POP		IX 		;bzw. IY
    5283	18D1	00153		JR	ab
    		00154
    		00155
    		00156	;*************************************
    		00157	;* DD/FD gefolgt von CB		     *
    		00158	;* RLC/RRC/RL/RR/SLA/SRA/(SLIA)/SRL, *
    		00159	;* (IX/Y+d),B/C/D/E/H/L/A	     *
    		00160	;*************************************
    		00161
    5285	78	00162 ddfdcb	LD	A,B		;DD/FD zurück
    5286	32C034 	00163		LD	(ddfd3-offset),A ;setzen
    5289	32C534 	00164		LD	(ddfd4-offset),A
    528C	23	00165		INC	HL 		;Zeiger auf Offset
    528D	7E	00166		LD	A,(HL) 		;"d" aus (IX/Y+d) laden
    528E	32C234 	00167		LD	(offs1-offset),A ;setzen
    5291	32C734 	00168		LD	(offs2-offset),A
    5294	23	00169		INC	HL 		;Zeiger auf Operation
    		00170
    		00171	;	Lade-Befehl errechnen und in den Text
    		00172
    5295	7E	00173		LD	A,(HL) 		;Befehl laden
    5296	E607	00174		AND	7		;nur die Bits 0-2
    5298	3C	00175		INC	A		;+1
    5299	47	00176		LD	B,A		;als Zähler
    529A	3E3E	00177		LD	A,3eh		;Opcode 46h-7eh erzeugen
    00178
    529C	C608	00179 loop1 ADD		A,8				;(46/4e/56/5e/66/6e/7e)
    529E	10FC	00180		DJNZ	loop1		;=LD B/C/D/E/H/L/A, (IX..)
    52A0	32C634 	00181		LD	(lade-offset),A ;setzen
    		00182
    		00183	;	Rotations-/Schiebe-Befehl erzeugen
    		00184
    52A3	7E	00185		LD	A,(HL)
    52A4	E6F8	00186		AND	0f8h		;die Bits 0-2 löschen
    52A6	0F	00187		RRCA			;und raus rotieren
    52A7	0F	00188		RRCA
    52A8	0F	00189		RRCA
    52A9	3C	00190		INC	A		;+1
    52AA	47	00191		LD	B,A		;als Zähler
    52AB	3EFE	00192		LD	A,0feh		;6/e/16/le/26/2e/3e=RLC,
    00193
    52AD	C608	00194 loop2	ADD		A,8				;RRC,RL,RR,SLA,SRA,SRL
    52AF	10FC	00195		DJNZ	loop2		;(u. RES/SET x)
    		00196
    52B1	48	00197		LD	C,B 		;NOP erzeugen (für reta)
    		00198
    52B2	FE36	00199		CP	36h		;SLIA?
    52B4	200B	00200		JR	NZ,noSLIA	;nein
    		00201
    		00202	;	SLIA (IX/Y+d) oder SLIA (IX/Y+d),r
    		00203
    52B6	0637	00204		LD	B,37h		;SCF erzeugen
    52B8	7E	00205		LD	A,(HL)		;SLIA (IX/Y+d)?
    52B9	FE36	00206		CP	36h
    52BB	2002	00207		JR	NZ,nopro	;nein, kein Problem
    52BD	0EC9	00208		LD	C,0c9h		;RET für reta erzeugen
    		00209
    52BF	3E16	00210 nopro	LD	A,16h		;RL erzeugen (statt SLIA)
    		00211
    52C1	32C334 	00212 noSLIA	LD	(opera-offset),A ;setzen
    52C4	78	00213		LD	A,B		;SCF oder NOP
    52C5	32BF34 	00214		LD	cflag-offset),A	;setzen
    52C8	79	00215		LD	A,C		;RET oder NOP
    52C9	32C434 	00216		LD	(reta-offset),A ;setzen
    		00217
    52CC	C1	00218		POP	BC		;Register zurück
    52CD	F1	00219		POP	AF
    52CE	23	00220		INC	HL		;PC korrigieren
    52CF	E3	00221		EX	(SP),HL		;und HL zurück
    		00222
    52D0	CDBF34 	00223		CALL	cflag-offset	;Operation ausführen
    52D3	1881	00224		JR	ab
    		00225
    		00226	;	Unterprogramm; Operation simulieren
    		00227
    52D5	00	00228 cflag	NOP			;oder SCF
    		00229
    52D6	00	00230 ddfd3 	NOP			;DD o. FD für IX/Y
    52D7	CB	00231		DB	0cbh		;immer CBh
    52D8	00	00232 offs1	NOP			;Offset d (IX/Y+d)
    52D9	00	00233 opera	NOP			;Operationsanweisung
    		00234
    52DA	00	00235 reta	NOP			;RETurn bei SLIA (IX/Y+d)
    		00236
    52DB	00	00237 ddfd4	NOP			;DD/FD für IX/Y
    52DC	7F	00238 lade	LD	A,A		;Ladebefehl
    52DD	00	00239 offs2	NOP			;Offset (s. offs1)
    52DE	C9	00240		RET
    		00241
    52DF		00242 ende	EQU	$
    00243
    00244
    5200		00245		END	start
1 hett seggt = plattdeutsch oder auch umgangssprachlicher Ausdruck für "hat gesagt"