Source file: /~heha/basteln/8bit/KC85/kcemu/kcemusrc.zip/KC880.ASM

;**********************************************************
;*
;*  Z80 Emulator für KC Emulator
;*
;*****

;
; es: Adreßbereich KC
; ds: restliche Daten (Windows automatisches Datensegment [HInstance])
; si: Programcounter
; ch: Taktzähler
; di: zeigt auf regs.hl oder regs.ix oder regs.iy
; dx: enthält HL/(M) oder IX/(IX+d) oder IY/(IY+d)
;
	IDEAL
	%TITLE	"KCEMU U880 (Z80) emulator library"
	model	small, pascal
	P286
	warn pro	;Protected-Mode-Fehler anmeckern

;type TRegs=record
; case Integer of
;  0: (BC,DE,HL,AF,BC_,DE_,HL_,AF_,PC,SP_,IX,IY:Word)
;  1: (C,B,E,D,L,H,F,A:Byte;
;	rsv: array[0..7] of Word;
;	I,R,IM,IF: Byte)

union TRegs
 struc
  BC	dw	?
  DE	dw	?
  HL	dw	?
  AF	dw	?
  BC_	dw	?
  DE_	dw	?
  HL_	dw	?
  AF_	dw	?
  PC	dw	?
  SP_	dw	?
  IX	dw	?
  IY	dw	?
 ends
 struc
  C	db	?
  B	db	?
  E	db	?
  D	db	?
  L	db	?
  H	db	?
  F	db	?
  A	db	?
	dw	8 dup (?)
  I	db	?
  R	db	?	;Alle Bits sind hier 1 Stelle nach links rotiert
  IM	db	?	;Interrupt-Modus
  IFF	db	?	;Interrupt-Flags IFF1^=bit1, IFF2^=bit2
 ends
ends
;IFF Bit 0: NMI-in-service-Flag (keine Verschachtelung möglich)
;IFF Bit 1: IFF1
;IFF Bit 2: IFF2
;IFF Bit 3: EI erfolgte (verzögerter Interrupt)
;IFF Bit 4: HALT erfolgte (Int-Quelle muß SI erhöhen)
;IFF Bit 5: RETI erfolgte (Signal für Peripherie?)

extrn MemKCSel: Word
extrn MemWr: Word	;ES:BX=Adresse, AL=Datenbyte, VR: Flags
extrn IORd: Word	;AX=Portadresse, PA: AL=Datenbyte
extrn IOWr: Word	;AX=Portadresse, BL=Datenbyte
extrn IrqPtr: Word	;AX=ID, DX:CX=User1
extrn Regs: TRegs	;var Regs: TRegs
extrn cticks: DWord	;Taktzähler für Statistik
extrn expire: Word	;wenn <0: Zurück zu Windows!
public CpuEmu
public CallAX		;für IrqProc wichtig
public DoNMI
public DoInt
public SetTimer,CancelTimer

macro MOVALBX		;zu Debugzwecken umsetzbar
	mov	al,[es:bx]
endm
macro MOVAXBX
	mov	ax,[es:bx]
endm

ofs	equ	<offset>
by	equ	<byte>
wo	equ	<word>

struc TTimeEntry
 next	dw	?	;Zeiger aufs nächste Element
 id	dw	?	;ID für Cancel und Re-Set, darf nicht 0 sein!
 count	dd	?	;"absolute" Zeit in Ticks
 user1	dd	?	;User-Daten
ends

UDATASEG
Timers		TTimeEntry	32 dup (?)	;max. 32 Zeitgeber!
Anker		dw	?
IrqExpire	dd	?	;enthält Taktzahl bis zum Knall

CODESEG
proc CancelTimer1	;liefert DI<>0 wenn geCANCELt
;interne Routine ohne Stackrahmen
;PE: AX: ID
;VR: SI,DI,Flags
	mov	ax,[ID]
	lea	di,[Anker]	;Adresse vorheriger Knoten (PREV)
@@l:	mov	si,di		;PREV:=CUR
	mov	di,[si]		;Anker oder .next auslesen (CUR)
	or	di,di		;NIL?
	jz	@@e		;Leere Liste oder Liste zu Ende!
	cmp	[(TTimeEntry di).id],ax	;ID gefunden?
	jne	@@l		;nicht hier!
	mov	ax,[di]
	mov	[si],ax		;Aus Liste herausnehmen
	mov	[(TTimeEntry di).id],0		;"Gelöscht" markieren
@@e:	ret
endp

proc CancelTimer		;liefert <>0 wenn geCANCELt
arg ID:Word
	mov	ax,[ID]
	call	CancelTimer
	xchg	ax,di
	ret
endp

proc FindFreeSlot
;PA: BX: Slot, Z=0: nichts frei (dann auch AL=0)!
;VR: BX,CX,Flags,(bei Fehler) AL
	lea	bx,[Timers]
	mov	cx,32
@@l:	cmp	[(TTimeEntry bx).id],0	;frei?
	jz	@@e
	add	bx,size TTimeEntry	;Z<>0!
	loop	@@l
	int	3
	mov	al,0
@@e:	ret
endp

proc SetTimer
arg ID:Word, TimeExp:DWord, User1:DWord
;Einfügen eines Timers mit ID
;Falls ID existiert, wird der vorhergehende Timer geCANCELt.
;Timer sind hier vom Typ One_Shot (nicht periodisch)
	mov	ax,[ID]
	or	ax,ax
	jz	@@e		;keine ID=0 setzen!
	call	CancelTimer1	;falls vorhanden: raus!
	call	FindFreeSlot	;Neuen Platz suchen (BX)
	jnz	@@e		;Fehler
;Felder füllen (außer .next)
	mov	cx,[word LOW  TimeExp]
	mov	dx,[word HIGH TimeExp]
	add	cx,[word LOW  cTicks]
	adc	dx,[word HIGH cTicks]	;DX:CX=absolute Zeit
	mov	[(TTimeEntry bx).id],ax
	mov	[word LOW  (TTimeEntry bx).count],cx
	mov	[word HIGH (TTimeEntry bx).count],dx
	mov	ax,[word LOW User1]
	mov	[word LOW  (TTimeEntry bx).user1],ax
	mov	ax,[word HIGH User1]
	mov	[word HIGH (TTimeEntry bx).user1],ax
;Nun in richtiger Reihenfolge einsortieren
	lea	di,[Anker]	;Adresse Knoten (CUR)
@@l:	mov	si,di		;PREV:=CUR
	mov	di,[si]		;Anker oder .next auslesen (CUR)
	or	di,di		;CUR=NIL?
	jz	@@f		;Leere Liste oder Liste zu Ende!
	mov	ax,dx		;es gibt kein CMP-with-borrow
	cmp	cx,[word LOW  (TTimeEntry di).count]
	sbb	ax,[word HIGH (TTimeEntry di).count]
	jns	@@l		;nicht hier davor, weitergehen
@@f:	mov	[si],bx		;PREV.next auf HERE setzen
	mov	[bx],di		;HERE.next auf CUR setzen
;IrqTick neu setzen, falls Einfügung am Anfang
	cmp	si,offset Anker
	jne	@@w
	mov	ax,[word LOW  TimeExp]
	mov	dx,[word HIGH TimeExp]
	mov	[word LOW  IrqExpire],ax
	mov	[word HIGH IrqExpire],dx
@@w:	mov	al,1
@@e:	cbw
	ret
endp

proc GenTimer
;wenn die Zeit (via IrqExpire) abgelaufen ist...
	push	ax		;retten Takte
	 mov	[regs.pc],si
@@l:	 mov	bx,[Anker]
	 or	bx,bx		;NIL?
	 jz	@@e		;Nichts tun, war bloßer Überlauf
	 mov	ax,[word LOW (TTimeEntry bx).count]
	 mov	dx,[word LOW (TTimeEntry bx).count]
	 sub	ax,[word LOW cTicks]
	 sbb	dx,[word LOW cTicks]
	 jns	@@k		;positiv: kein Aufruf!
	 pusha
	  mov	ax,[(TTimeEntry bx).next]
	  mov	[Anker],ax	;Node ausketten
	  xor	ax,ax
	  xchg	[(TTimeEntry bx).id],ax	;Node löschen
	  mov	cx,[word LOW  (TTimeEntry bx).user1]
	  mov	dx,[word HIGH (TTimeEntry bx).user1]
	  call	[IrqPtr]	;mit AX=ID, DX:CX=User1
	 popa
	 jmp	@@l
@@k:	 mov	[word LOW  IrqExpire],ax
	 mov	[word HIGH IrqExpire],dx
@@e:	 mov	si,[regs.pc]	;könnte verändert sein!
	pop	ax
	jmp	WTimer
endp


;**********************************************************
;*
;*  Emulator
;*

proc Cpuemu
	mov	es,[MemKcSel]
	mov	si,[regs.pc]
@@l:	add	[regs.r],2
	and	[regs.iff],not 8	;EI-Flag nach(!) IrqProc löschen
	seges	lodsb			;AL:=[ES:SI], Inc(SI)
	mov	ch,4			;Mindest-Taktzahl
CpuEmu1:	;Einsprungpunkt für INT im Modus 0
	xor	ah,ah
	add	ax,ax
	mov	bx,ax
	lea	di,[regs.hl]		;DI zeigt auf regs.hl
	mov	dx,[di]			;DX enthält im Normalfall HL
	call	[cs:codetab+bx]		;PA: ch=Takte
CpuEmu2:	;Einsprungpunkt für INT Modus 1 und 2 sowie NMI
	mov	al,ch
	cbw				;AL->AX (mov ah,0)
	add	[word low  cticks],ax
	adc	[word high cticks],0
@@a2:	sub	[word LOW  IrqExpire],ax
	jc	@@s1
WTimer:	sub	[expire],ax
	jnc	@@l
	mov	[regs.pc],si
	ret
@@s1:
	sbb	[word HIGH IrqExpire],0
	jnc	WTimer
	jmp	GenTimer
endp

proc DoNMI
	mov	es,[MemKCSel]
	mov	si,[Regs.pc]
	test	[Regs.iff],10h	;{HALT aktiv?}
	jz	@@1
	inc	si
@@1:	and	[Regs.iff],not 2 ;{IFF1 löschen}
	or	[Regs.iff],1	;{NMI ist aktiv}
	mov	ch,4		;{NMI INTA = 11 Takte}
	mov	ax,66h		;{NMI-Startadresse}
	call	CallAX
	jmp	CpuEmu2
endp

proc DoINT			;{Interrupt mit Vektor AL ausführen}
	mov	es,[MemKCSel]
	mov	si,[Regs.pc]
	test	[Regs.iff],10h	;{HALT aktiv?}
	jz	@@1
	inc	si
@@1:	mov	ah,[Regs.im]
	or	ah,ah
	jnz	@@n0
	mov	ch,5		;{INTA#0 = 12 Takte (mit RST-Befehl)}
	jmp	CpuEmu1		;{AL als Befehl dekodieren}
@@n0:
	dec	ah
	jnz	@@n1
	mov	ch,6		;{INTA#1 = 13 Takte}
	mov	ax,38h
	jmp	@@w2
@@n1:
	mov	ah,[Regs.I]
	xchg	bx,ax
	MOVAXBX			;{Vektor lesen}
	mov	ch,12		;{INTA#2 = 19 Takte}
@@w2:	call	CallAX
	jmp	CpuEmu2
endp

;**********************************************************
;*
;*  Opcode Jump Tabelle (read-only, daher ins Codesegment)
;*
codetab dw a00x, a01x, a02x, a03x, a04x, a05x, a06x, a07x
	dw a08x, a09x, a0ax, a0bx, a0cx, a0dx, a0ex, a0fx
	dw a10x, a11x, a12x, a13x, a14x, a15x, a16x, a17x
	dw a18x, a19x, a1ax, a1bx, a1cx, a1dx, a1ex, a1fx
	dw a20x, a21x, a22x, a23x, a24x, a25x, a26x, a27x
	dw a28x, a29x, a2ax, a2bx, a2cx, a2dx, a2ex, a2fx
	dw a30x, a31x, a32x, a33x, a34x, a35x, a36x, a37x
	dw a38x, a39x, a3ax, a3bx, a3cx, a3dx, a3ex, a3fx
	dw a40x, a41x, a42x, a43x, a44x, a45x, a46x, a47x
	dw a48x, a49x, a4ax, a4bx, a4cx, a4dx, a4ex, a4fx
	dw a50x, a51x, a52x, a53x, a54x, a55x, a56x, a57x
	dw a58x, a59x, a5ax, a5bx, a5cx, a5dx, a5ex, a5fx
	dw a60x, a61x, a62x, a63x, a64x, a65x, a66x, a67x
	dw a68x, a69x, a6ax, a6bx, a6cx, a6dx, a6ex, a6fx
	dw a70x, a71x, a72x, a73x, a74x, a75x, a76x, a77x
	dw a78x, a79x, a7ax, a7bx, a7cx, a7dx, a7ex, a7fx
	dw a80x, a81x, a82x, a83x, a84x, a85x, a86x, a87x
	dw a88x, a89x, a8ax, a8bx, a8cx, a8dx, a8ex, a8fx
	dw a90x, a91x, a92x, a93x, a94x, a95x, a96x, a97x
	dw a98x, a99x, a9ax, a9bx, a9cx, a9dx, a9ex, a9fx
	dw aa0x, aa1x, aa2x, aa3x, aa4x, aa5x, aa6x, aa7x
	dw aa8x, aa9x, aaax, aabx, aacx, aadx, aaex, aafx
	dw ab0x, ab1x, ab2x, ab3x, ab4x, ab5x, ab6x, ab7x
	dw ab8x, ab9x, abax, abbx, abcx, abdx, abex, abfx
	dw ac0x, ac1x, ac2x, ac3x, ac4x, ac5x, ac6x, ac7x
	dw ac8x, ac9x, acax, acbx, accx, acdx, acex, acfx
	dw ad0x, ad1x, ad2x, ad3x, ad4x, ad5x, ad6x, ad7x
	dw ad8x, ad9x, adax, adbx, adcx, addx, adex, adfx
	dw ae0x, ae1x, ae2x, ae3x, ae4x, ae5x, ae6x, ae7x
	dw ae8x, ae9x, aeax, aebx, aecx, aedx, aeex, aefx
	dw af0x, af1x, af2x, af3x, af4x, af5x, af6x, af7x
	dw af8x, af9x, afax, afbx, afcx, afdx, afex, affx

cbtab	dw crcl, crrc, crl,  crr,  csla, csra, csli, csrl

edltab	dw e40x, e41x, e42x, e43x, e44x, e45x, e46x, e47x
	dw e48x, e49x, e4ax, e4bx, e4cx, e4dx, e4ex, e4fx
	dw e50x, e51x, e52x, e53x, e54x, e55x, e56x, e57x
	dw e58x, e59x, e5ax, e5bx, e5cx, e5dx, e5ex, e5fx
	dw e60x, e61x, e62x, e63x, e64x, e65x, e66x, e67x
	dw e68x, e69x, e6ax, e6bx, e6cx, e6dx, e6ex, e6fx
	dw e70x, e71x, e72x, e73x, e74x, e75x, e76x, e77x
	dw e78x, e79x, e7ax, e7bx, e7cx, e7dx, e7ex, e7fx

edhtab	dw ea0x, ea1x, ea2x, ea3x, ea8x, ea9x, eaax, eabx
	dw eb0x, eb1x, eb2x, eb3x, eb8x, eb9x, ebax, ebbx


;--Opcodes-----------------------------
proc a00x                               ;NOP
a40x:					;LD B,B
a49x:					;LD C,C
a52x:					;LD D,D
a5bx:					;LD E,E
a64x:					;LD H,H
a6Dx:					;LD L,L
a7Fx:					;LD A,A
e77x:					;NOP   (ED 77)
e7fx:					;NOP   (ED 7F)
	ret
endp
proc a08x
	mov	ax,[regs.af]		;EX AF
	xchg	[regs.af_],ax
	mov	[regs.af],ax
	ret
endp
proc a10x				;DJNZ e
	seges	lodsb
	add	ch,4		;4-->8
	dec	[regs.b]
	jnz	jmprel
	ret
endp
proc a18x				;JR e
	seges	lodsb
	add	ch,3
jmprel:	cbw
	add	si,ax
	add	ch,5
	ret
endp
proc a20x				;JR NZ,e
	seges	lodsb
	add	ch,3
	test	[regs.f],40h
	jz	jmprel
	ret
endp
proc a28x				;JR Z,e
	seges	lodsb
	add	ch,3
	test	[regs.f],40h
	jnz	jmprel
	ret
endp
proc a30x				;JR NC,e
	seges	lodsb
	add	ch,3
	test	[regs.f],1
	jz	jmprel
	ret
endp
proc a38x				;JR C,e
	seges	lodsb
	add	ch,3
	test	[regs.f],1
	jnz	jmprel
	ret
endp
proc a01x				;LD BC,nn
	seges	lodsw
	mov	[regs.bc],ax
	add	ch,6
	ret
endp
proc a11x				;LD DE,nn
	seges	lodsw
	mov	[regs.de],ax
	add	ch,6
	ret
endp
proc a21x				;LD HL/IX/IY,nn
	seges	lodsw
	mov	[di],ax
	add	ch,6
	ret
endp
proc a31x				;LD SP,nn
	seges	lodsw
	mov	[regs.sp_],ax
	add	ch,6
	ret
endp
proc a09x				;ADD HL/IX/IY,BC
	mov	ax,[regs.bc]
	jmp	add16
endp
proc a19x				;ADD HL/IX/IY,DE
	mov	ax,[regs.de]
	jmp	add16
endp
proc a29x				;ADD HL/IX/IY,HL/IX/IY
	mov	ax,[di]
	jmp	add16
endp
proc a39x				;ADD HL/IX/IY,SP
	mov	ax,[regs.sp_]
add16:	add	[di],ax
	lahf
	mov	al,[regs.f]
	and	ax,1FCh		;N:=0
	or	al,ah
	mov	[regs.f],al
	add	ch,7
	ret
endp
proc a02x				;LD (BC),A
	mov	bx,[regs.bc]
	jmp	pptest
endp
proc a12x				;LD (DE),A
	mov	bx,[regs.de]
	jmp	pptest
endp
proc a22x				;LD (nn),HL/IX/IY
	seges	lodsw
	xchg	bx,ax
	mov	ax,[di]
memwritew12:
	add	ch,12
memwritew:
	call	[MemWr]
	inc	bx
	xchg	al,ah
memwrj:	jmp	[MemWr]
endp
proc a32x				;LD (nn),A
	seges	lodsw
	xchg	bx,ax
	add	ch,6
endp

pptest:	mov	al,[regs.a]
	add	ch,3
	jmp	memwrj

proc a0ax				;LD A,(BC)
	mov	bx,[regs.bc]
mvabx:	MOVALBX
	mov	[regs.a],al
	add	ch,3
	ret
endp
proc a1ax				;LD A,(DE)
	mov	bx,[regs.de]
	jmp	mvabx
endp
proc a2ax				;LD HL/IX/IY,(nn)
	seges	lodsw
	xchg	bx,ax
	MOVAXBX
	mov	[di],ax
	add	ch,12
	ret
endp
proc a3ax				;LD A,(nn)
	seges	lodsw
	xchg	bx,ax
	add	ch,6
	jmp	mvabx
endp
proc a03x				;INC BC
	inc	[regs.bc]
	add	ch,2
	ret
endp
proc a13x				;INC DE
	inc	[regs.de]
	add	ch,2
	ret
endp
proc a23x				;INC HL/IX/IY
	inc	[word di]
	add	ch,2
	ret
endp
proc a33x				;INC SP
	inc	[regs.sp_]
	add	ch,2
	ret
endp
proc a0bx				;DEC BC
	dec	[regs.bc]
	add	ch,2
	ret
endp
proc a1bx				;DEC DE
	dec	[regs.de]
	add	ch,2
	ret
endp
proc a2bx				;DEC HL/IX/IY
	dec	[word di]
	add	ch,2
	ret
endp
proc a3bx				;DEC SP
	dec	[regs.sp_]
	add	ch,2
	ret
endp
proc a04x				;INC B
	inc	[regs.b]
	jmp	inc8f
endp
proc a0cx				;INC C
	inc	[regs.c]
	jmp	inc8f
endp
proc a14x				;INC D
	inc	[regs.d]
	jmp	inc8f
endp
proc a1cx				;INC E
	inc	[regs.e]
	jmp	inc8f
endp
proc a24x				;INC H/HX/HY
	inc	[by di+1]
	jmp	inc8f
endp
proc a2cx				;INC L/LX/LY
	inc	[by di]
	jmp	inc8f
endp
proc a34x				;INC M/(IX+d)/(IY+d)
	mov	bx,dx
	add	ch,7
	MOVALBX
	inc	al
	pushf
	 call	[MemWr]
	popf
	jmp	inc8f
endp
proc a3cx				;INC A
	inc	[regs.a]
inc8f:	call	lahfv
	mov	al,[regs.f]
	and	ax,0D429h	;CY(Z80) belassen, N=0!
	or	al,ah
	mov	[regs.f],al
	ret
endp
proc a05x				;DEC B
	dec	[regs.b]
	jmp	dec8f
endp
proc a0dx				;DEC C
	dec	[regs.c]
	jmp	dec8f
endp
proc a15x				;DEC D
	dec	[regs.d]
	jmp	dec8f
endp
proc a1dx				;DEC E
	dec	[regs.e]
	jmp	dec8f
endp
proc a25x				;DEC H/HX/HY
	dec	[by di+1]
	jmp	dec8f
endp
proc a2dx				;DEC L/LX/LY
	dec	[by di]
	jmp	dec8f
endp
proc a35x				;DEC M/(IX+d)/(IY+d)
	mov	bx,dx
	add	ch,7
	MOVALBX
	dec	al
	pushf
	 call	[MemWr]
	popf
	jmp	dec8f
endp
proc a3dx				;DEC A
	dec	[regs.a]
dec8f:	call	lahfv
	mov	al,[regs.f]
	or	ax,not 0D429h	;CY(Z80) belassen, N=1!
	and	al,ah
	mov	[regs.f],al
	ret
endp
proc a06x				;LD B,n
	seges	lodsb
	mov	[regs.b],al
	add	ch,3
	ret
endp
proc a0ex				;LD C,n
	seges	lodsb
	mov	[regs.c],al
	add	ch,3
	ret
endp
proc a16x				;LD D,n
	seges	lodsb
	mov	[regs.d],al
	add	ch,3
	ret
endp
proc a1ex				;LD E,n
	seges	lodsb
	mov	[regs.e],al
	add	ch,3
	ret
endp
proc a26x				;LD H/HX/HY,n
	seges	lodsb
	mov	[di+1],al
	add	ch,3
	ret
endp
proc a2ex				;LD L/LX/LY,n
	seges	lodsb
	mov	[di],al
	add	ch,3
	ret
endp
proc a36x				;LD M/(IX+d)/(IY+d),n
	seges	lodsb
	mov	bx,dx
	add	ch,6
	jmp	[MemWr]
proc a3ex				;LD A,n
	seges	lodsb
	mov	[regs.a],al
	add	ch,3
	ret
endp
proc a07x				;RLCA
	rol	[regs.a],1
	jmp	SavCY
endp
proc a0fx				;RRCA
	ror	[regs.a],1
	jmp	SavCY
endp
proc a17x				;RLA
	call	GetCY
	rcl	[regs.a],1
	jmp	SavCY
endp
proc a1fx				;RRA
	call	GetCY
	rcr	[regs.a],1
SavCY:	lahf
	mov	al,[regs.f]
	and	ax,01ECh	;N=0
	or	al,ah
	mov	[regs.f],al
	ret
endp
proc a27x				;DAA
	pushf			;CPU-Status (Interrupt!)
	 mov	ax,[regs.af]
	 xchg	al,ah
	 sahf
	 test	ah,2		;N-Flag: ADD oder SUB?
	 jz	@@add
	 das			;nach Subtraktion
	 jmp	@@1
@@add:	 daa			;nach Addition
@@1:	 lahf
	 xchg	ah,al
	 mov	[regs.af],ax
	popf
	ret
endp
proc a2fx				;CPL
	not	[regs.a]
	or	[regs.f],12h
	ret
endp
proc a37x				;SCF
	mov	al,[regs.f]
	and	al,not 12h	;H und N auf 0
	or	al,1		;CY auf 1
	mov	[regs.f],al
	ret
endp
proc a3fx				;CCF
	mov	al,[regs.f]
	and	al,not 2	;N auf 0
	xor	al,1		;CY umdrehen
	mov	[regs.f],al
	ret
endp
;----------------------------------
proc a41x				;LD B,C
	mov	al,[regs.c]
	mov	[regs.b],al
	ret
endp
proc a42x				;LD B,D
	mov	al,[regs.d]
	mov	[regs.b],al
	ret
endp
proc a43x				;LD B,E
	mov	al,[regs.e]
	mov	[regs.b],al
	ret
endp
proc a44x				;LD B,H/HX/HY
	mov	al,[di+1]
	mov	[regs.b],al
	ret
endp
proc a45x				;LD B,L/LX/LY
	mov	al,[di]
	mov	[regs.b],al
	ret
endp
proc a46x				;LD B,M/(IX+d)/(IY+d)
	mov	bx,dx
	MOVALBX
	mov	[regs.b],al
	add	ch,3
	ret
endp
proc a47x				;LD B,A
	mov	al,[regs.a]
	mov	[regs.b],al
	ret
endp
proc a48x				;LD C,B
	mov	al,[regs.b]
	mov	[regs.c],al
	ret
endp
proc a4ax				;LD C,D
	mov	al,[regs.d]
	mov	[regs.c],al
	ret
endp
proc a4bx				;LD C,E
	mov	al,[regs.e]
	mov	[regs.c],al
	ret
endp
proc a4cx				;LD C,H/HX/HY
	mov	al,[di+1]
	mov	[regs.c],al
	ret
endp
proc a4dx				;LD C,L/LX/LY
	mov	al,[di]
	mov	[regs.c],al
	ret
endp
proc a4ex				;LD C,M/(IX+d)/(IY+d)
	mov	bx,dx
	MOVALBX
	mov	[regs.c],al
	add	ch,3
	ret
endp
proc a4fx				;LD C,A
	mov	al,[regs.a]
	mov	[regs.c],al
	ret
endp
proc a50x				;LD D,B
	mov	al,[regs.b]
	mov	[regs.d],al
	ret
endp
proc a51x				;LD D,C
	mov	al,[regs.c]
	mov	[regs.d],al
	ret
endp
proc a53x				;LD D,E
	mov	al,[regs.e]
	mov	[regs.d],al
	ret
endp
proc a54x				;LD D,H/HX/HY
	mov	al,[di+1]
	mov	[regs.d],al
	ret
endp
proc a55x				;LD D,L/LX/LY
	mov	al,[di]
	mov	[regs.d],al
	ret
endp
proc a56x				;LD D,M/(IX+d)/(IY+d)
	mov	bx,dx
	MOVALBX
	mov	[regs.d],al
	add	ch,3
	ret
endp
proc a57x				;LD D,A
	mov	al,[regs.a]
	mov	[regs.d],al
	ret
endp
proc a58x				;LD E,B
	mov	al,[regs.b]
	mov	[regs.e],al
	ret
endp
proc a59x				;LD E,C
	mov	al,[regs.c]
	mov	[regs.e],al
	ret
endp
proc a5ax				;LD E,D
	mov	al,[regs.d]
	mov	[regs.e],al
	ret
endp
proc a5cx				;LD E,H/HX/HY
	mov	al,[di+1]
	mov	[regs.e],al
	ret
endp
proc a5dx				;LD E,L/LX/LY
	mov	al,[di]
	mov	[regs.e],al
	ret
endp
proc a5ex				;LD E,M/(IX+d)/(IY+d)
	mov	bx,dx
	MOVALBX
	mov	[regs.e],al
	add	ch,3
	ret
endp
proc a5fx				;LD E,A
	mov	al,[regs.a]
	mov	[regs.e],al
	ret
endp
proc a60x				;LD H/HX/HY,B
	mov	al,[regs.b]
	mov	[di+1],al
	ret
endp
proc a61x				;LD H/HX/HY,C
	mov	al,[regs.c]
	mov	[di+1],al
	ret
endp
proc a62x				;LD H/HX/HY,D
	mov	al,[regs.d]
	mov	[di+1],al
	ret
endp
proc a63x				;LD H/HX/HY,E
	mov	al,[regs.e]
	mov	[di+1],al
	ret
endp
proc a65x				;LD H/HX/HY,L/LX/LY
	mov	al,[di]
	mov	[di+1],al
	ret
endp
proc a66x				;LD H,M/(IX+d)/(IY+d)
	mov	bx,dx
	MOVALBX
	mov	[regs.h],al
	add	ch,3
	ret
endp
proc a67x				;LD H/HX/HY,A
	mov	al,[regs.a]
	mov	[di+1],al
	ret
endp
proc a68x				;LD L/LX/LY,B
	mov	al,[regs.b]
	mov	[di],al
	ret
endp
proc a69x				;LD L/LX/LY,C
	mov	al,[regs.c]
	mov	[di],al
	ret
endp
proc a6ax				;LD L/LX/LY,D
	mov	al,[regs.d]
	mov	[di],al
	ret
endp
proc a6bx				;LD L/LX/LY,E
	mov	al,[regs.e]
	mov	[di],al
	ret
endp
proc a6cx				;LD L/LX/LY,H/HX/HY
	mov	al,[di+1]
	mov	[di],al
	ret
endp
proc a6ex				;LD L,M/(IX+d)/(IY+d)
	mov	bx,dx
	MOVALBX
	mov	[regs.l],al
	add	ch,3
	ret
endp
proc a6fx				;LD L/LX/LY,A
	mov	al,[regs.a]
	mov	[di],al
	ret
endp
proc a70x				;LD M/(IX+d)/(IY+d),B
	mov	al,[regs.b]
	jmp	mtest
endp
proc a71x				;LD M/(IX+d)/(IY+d),C
	mov	al,[regs.c]
	jmp	mtest
endp
proc a72x				;LD M/(IX+d)/(IY+d),D
	mov	al,[regs.d]
	jmp	mtest
endp
proc a73x				;LD M/(IX+d)/(IY+d),E
	mov	al,[regs.e]
	jmp	mtest
endp
proc a74x				;LD M/(IX+d)/(IY+d),H
	mov	al,[regs.h]
	jmp	mtest
endp
proc a75x				;LD M/(IX+d)/(IY+d),L
	mov	al,[regs.l]
	jmp	mtest
endp
proc a76x				;HALT (NEIN!!!)
	dec	si
	or	[regs.iff],10h		;HALT-Flag setzen
	ret
endp
;falls auch noch Interrupts gesperrt sind, dann kann die IdleProc
;sofort mit FALSE zurückkaerimas...
proc a77x				;LD M/(IX+d)/(IY+d),A
	mov	al,[regs.a]
mtest:	mov	bx,dx
	add	ch,3
	jmp	[MemWr]
endp
proc a78x				;LD A,B
	mov	al,[regs.b]
	mov	[regs.a],al
	ret
endp
proc a79x				;LD A,C
	mov	al,[regs.c]
	mov	[regs.a],al
	ret
endp
proc a7ax				;LD A,D
	mov	al,[regs.d]
	mov	[regs.a],al
	ret
endp
proc a7bx				;LD A,E
	mov	al,[regs.e]
	mov	[regs.a],al
	ret
endp
proc a7cx				;LD A,H/HX/HY
	mov	al,[di+1]
	mov	[regs.a],al
	ret
endp
proc a7dx				;LD A,L/LX/LY
	mov	al,[di]
	mov	[regs.a],al
	ret
endp
proc a7ex				;LD A,M/(IX+d)/(IY+d)
	mov	bx,dx
	MOVALBX
	mov	[regs.a],al
	add	ch,3
	ret
endp
;------------
proc a80x				;ADD B
	mov	al,[regs.b]
	jmp	a8add
endp
proc a81x				;ADD C
	mov	al,[regs.c]
	jmp	a8add
endp
proc a82x				;ADD D
	mov	al,[regs.d]
	jmp	a8add
endp
proc a83x				;ADD E
	mov	al,[regs.e]
	jmp	a8add
endp
proc a84x				;ADD H/HX/HY
	mov	al,[di+1]
	jmp	a8add
endp
proc a85x				;ADD L/LX/LY
	mov	al,[di]
	jmp	a8add
endp
proc a86x				;ADD M/(IX+d)/(IY+d)
	mov	bx,dx
	MOVALBX
	add	ch,3
	jmp	a8add
endp
proc a87x				;ADD A
	mov	al,[regs.a]
a8add:	add	[regs.a],al
	call	lahfv
	and	ah,not 2	;N:=0
	mov	[regs.f],ah
	ret
endp
proc a88x				;ADC B
	mov	al,[regs.b]
	jmp	a8adc
endp
proc a89x				;ADC C
	mov	al,[regs.c]
	jmp	a8adc
endp
proc a8ax				;ADC D
	mov	al,[regs.d]
	jmp	a8adc
endp
proc a8bx				;ADC E
	mov	al,[regs.e]
	jmp	a8adc
endp
proc a8cx				;ADC H/HX/HY
	mov	al,[di+1]
	jmp	a8adc
endp
proc a8dx				;ADC L/LX/LY
	mov	al,[di]
	jmp	a8adc
endp
proc a8ex				;ADC M/(IX+d)/(IY+d)
	mov	bx,dx
	MOVALBX
	add	ch,3
	jmp	a8adc
endp
proc a8fx				;ADC A
	mov	al,[regs.a]
a8adc:	call	GetCY
	adc	[regs.a],al
	call	lahfv
	and	ah,not 2
	mov	[regs.f],ah
	ret
endp
proc a90x				;SUB B
	mov	al,[regs.b]
	jmp	a8sub
endp
proc a91x				;SUB C
	mov	al,[regs.c]
	jmp	a8sub
endp
proc a92x				;SUB D
	mov	al,[regs.d]
	jmp	a8sub
endp
proc a93x				;SUB E
	mov	al,[regs.e]
	jmp	a8sub
endp
proc a94x				;SUB H/HX/HY
	mov	al,[di+1]
	jmp	a8sub
endp
proc a95x				;SUB L/LX/LY
	mov	al,[di]
	jmp	a8sub
endp
proc a96x				;SUB M/(IX+d)/(IY+d)
	mov	bx,dx
	MOVALBX
	add	ch,3
	jmp	a8sub
endp
proc a97x				;SUB A
	mov	al,[regs.a]
a8sub:	sub	[regs.a],al
	call	lahfv
	or	ah,2	;N:=1
	mov	[regs.f],ah
	ret
endp
endp
proc a98x				;SBC B
	mov	al,[regs.b]
	jmp	a8sbc
endp
proc a99x				;SBC C
	mov	al,[regs.c]
	jmp	a8sbc
endp
proc a9ax				;SBC D
	mov	al,[regs.d]
	jmp	a8sbc
endp
proc a9bx				;SBC E
	mov	al,[regs.e]
	jmp	a8sbc
endp
proc a9cx				;SBC H/HX/HY
	mov	al,[di+1]
	jmp	a8sbc
endp
proc a9dx				;SBC L/LX/LY
	mov	al,[di]
	jmp	a8sbc
endp
proc a9ex				;SBC M/(IX+d)/(IY+d)
	mov	bx,dx
	MOVALBX
	add	ch,3
	jmp	a8sbc
endp
proc a9fx				;SBC A
	mov	al,[regs.a]
a8sbc:	call	GetCY
	sbb	[regs.a],al
	call	lahfv
	or	ah,2
	mov	[regs.f],ah
	ret
endp
proc aa0x				;AND B
	mov	al,[regs.b]
	jmp	a8and
endp
proc aa1x				;AND C
	mov	al,[regs.c]
	jmp	a8and
endp
proc aa2x				;AND D
	mov	al,[regs.d]
	jmp	a8and
endp
proc aa3x				;AND E
	mov	al,[regs.e]
	jmp	a8and
endp
proc aa4x				;AND H/HX/HY
	mov	al,[di+1]
	jmp	a8and
endp
proc aa5x				;AND L/LX/LY
	mov	al,[di]
	jmp	a8and
endp
proc aa6x				;AND M/(IX+d)/(IY+d)
	mov	bx,dx
	MOVALBX
	add	ch,3
	jmp	a8and
endp
proc aa7x				;AND A
	mov	al,[regs.a]
a8and:	and	[regs.a],al
	lahf
	and	ah,not 2	;N auf 0
	or	ah,10h		;H auf 1
	mov	[regs.f],ah
	ret
endp
proc aa8x				;XOR B
	mov	al,[regs.b]
	jmp	a8xor
endp
proc aa9x				;XOR C
	mov	al,[regs.c]
	jmp	a8xor
endp
proc aaax				;XOR D
	mov	al,[regs.d]
	jmp	a8xor
endp
proc aabx				;XOR E
	mov	al,[regs.e]
	jmp	a8xor
endp
proc aacx				;XOR H/HX/HY
	mov	al,[di+1]
	jmp	a8xor
endp
proc aadx				;XOR L/LX/LY
	mov	al,[di]
	jmp	a8xor
endp
proc aaex				;XOR M/(IX+d)/(IY+d)
	mov	bx,dx
	MOVALBX
	add	ch,3
	jmp	a8xor
endp
proc aafx				;XOR A
	mov	al,[regs.a]
a8xor:	xor	[regs.a],al
	lahf
	and	ah,not 12h	;H und N auf 0
	mov	[regs.f],ah
	ret
endp
proc ab0x				;OR B
	mov	al,[regs.b]
	jmp	a8or
endp
proc ab1x				;OR C
	mov	al,[regs.c]
	jmp	a8or
endp
proc ab2x				;OR D
	mov	al,[regs.d]
	jmp	a8or
endp
proc ab3x				;OR E
	mov	al,[regs.e]
	jmp	a8or
endp
proc ab4x				;OR H/HX/HY
	mov	al,[di+1]
	jmp	a8or
endp
proc ab5x				;OR L/LX/LY
	mov	al,[di]
	jmp	a8or
endp
proc ab6x				;OR M/(IX+d)/(IY+d)
	mov	bx,dx
	MOVALBX
	add	ch,3
	jmp	a8or
endp
proc ab7x				;OR A
	mov	al,[regs.a]
a8or:	or	[regs.a],al
	lahf
	and	ah,not 12h	;H und N auf 0
	mov	[regs.f],ah
	ret
endp
proc ab8x				;CP B
	mov	al,[regs.b]
	jmp	a8cp
endp
proc ab9x				;CP C
	mov	al,[regs.c]
	jmp	a8cp
endp
proc abax				;CP D
	mov	al,[regs.d]
	jmp	a8cp
endp
proc abbx				;CP E
	mov	al,[regs.e]
	jmp	a8cp
endp
proc abcx				;CP H/HX/HY
	mov	al,[di+1]
	jmp	a8cp
endp
proc abdx				;CP L/LX/LY
	mov	al,[di]
	jmp	a8cp
endp
proc abex				;CP M/(IX+d)/(IY+d)
	mov	bx,dx
	MOVALBX
	add	ch,3
	jmp	a8cp
endp
proc abfx				;CP A
	mov	al,[regs.a]
a8cp:	cmp	[regs.a],al
	call	lahfv
	or	ah,2
	mov	[regs.f],ah
	ret
endp
;--------
proc ac0x				;RET NZ
	inc	ch
	test	[regs.f],40h
	jz	popsi
	ret
endp
proc ac8x				;RET Z
	inc	ch
	test	[regs.f],40h
	jnz	popsi
	ret
endp
proc ad0x				;RET NC
	inc	ch
	test	[regs.f],1
	jz	popsi
	ret
endp
proc ad8x				;RET C
	inc	ch
	test	[regs.f],1
	jnz	popsi
	ret
endp
proc ae0x				;RET PO
	inc	ch
	test	[regs.f],4
	jz	popsi
	ret
endp
proc ae8x				;RET PE
	inc	ch
	test	[regs.f],4
	jnz	popsi
	ret
endp
proc af0x				;RET P
	inc	ch
	test	[regs.f],80h
	jz	popsi
	ret
endp
proc af8x				;RET M
	inc	ch
	test	[regs.f],80h
	jnz	popsi
	ret
endp
proc ac9x				;RET
popsi:	call	popax
	xchg	si,ax
	ret
endp
proc popax
	mov	bx,[regs.sp_]
	mov	ax,[es:bx]		;Stackbezogen: kein MOVAXBX-Makro!
	add	[regs.sp_],2
	add	ch,6
	ret
endp
proc ac1x				;POP BC
	call	popax
	mov	[regs.bc],ax
	ret
endp
proc ad1x				;POP DE
	call	popax
	mov	[regs.de],ax
	ret
endp
proc ae1x				;POP HL/IX/IY
	call	popax
	mov	[di],ax
	ret
endp
proc af1x				;POP AF
	call	popax
	mov	[regs.af],ax
	ret
endp
proc ac2x				;JP NZ,nn
	seges	lodsw
	add	ch,6
	test	[regs.f],40h
	jz	jmp1
	ret
endp
proc acax				;JP Z,nn
	seges	lodsw
	add	ch,6
	test	[regs.f],40h
	jnz	jmp1
	ret
endp
proc ad2x				;JP NC,nn
	seges	lodsw
	add	ch,6
	test	[regs.f],1
	jz	jmp1
	ret
endp
proc adax				;JP C,nn
	seges	lodsw
	add	ch,6
	test	[regs.f],1
	jnz	jmp1
	ret
endp
proc ae2x				;JP PO,nn
	seges	lodsw
	add	ch,6
	test	[regs.f],4
	jz	jmp1
	ret
endp
proc aeax				;JP PE,nn
	seges	lodsw
	add	ch,6
	test	[regs.f],4
	jnz	jmp1
	ret
endp
proc af2x				;JP P,nn
	seges	lodsw
	add	ch,6
	test	[regs.f],80h
	jz	jmp1
	ret
endp
proc afax				;JP M,nn
	seges	lodsw
	add	ch,6
	test	[regs.f],80h
	jnz	jmp1
	ret
endp
proc ac3x				;JP nn
	seges	lodsw
	add	ch,6
jmp1:	xchg	si,ax
	ret
endp
proc ac4x				;CALL NZ,nn
	seges	lodsw
	add	ch,6
	test	[regs.f],40h
	jz	callax
	ret
endp
proc accx				;CALL Z,nn
	seges	lodsw
	add	ch,6
	test	[regs.f],40h
	jnz	callax
	ret
endp
proc ad4x				;CALL NC,nn
	seges	lodsw
	add	ch,6
	test	[regs.f],1
	jz	callax
	ret
endp
proc adcx				;CALL C,nn
	seges	lodsw
	add	ch,6
	test	[regs.f],1
	jnz	callax
	ret
endp
proc ae4x				;CALL PO,nn
	seges	lodsw
	add	ch,6
	test	[regs.f],4
	jz	callax
	ret
endp
proc aecx				;CALL PE,nn
	seges	lodsw
	add	ch,6
	test	[regs.f],4
	jnz	callax
	ret
endp
proc af4x				;CALL P,nn
	seges	lodsw
	add	ch,6
	test	[regs.f],80h
	jz	callax
	ret
endp
proc afcx				;CALL M,nn
	seges	lodsw
	add	ch,6
	test	[regs.f],80h
	jnz	callax
	ret
endp
proc acdx				;CALL nn
	seges	lodsw
	add	ch,6
callax:	xchg	ax,si
pushax:	add	ch,7
	sub	[regs.sp_],2
	mov	bx,[regs.sp_]
	jmp	memwritew
endp
proc ac5x				;PUSH BC
	mov	ax,[regs.bc]
	jmp	pushax
endp
proc ad5x				;PUSH DE
	mov	ax,[regs.de]
	jmp	pushax
endp
proc ae5x				;PUSH HL/IX/IY
	mov	ax,[di]
	jmp	pushax
endp
proc af5x				;PUSH AF
	mov	ax,[regs.af]
	jmp	pushax
endp
proc ac6x				;ADD n
	seges	lodsb
	jmp	a8add
endp
proc acex				;ADC n
	seges	lodsb
	jmp	a8adc
endp
proc ad6x				;SUB n
	seges	lodsb
	jmp	a8sub
endp
proc adex				;SBC n
	seges	lodsb
	jmp	a8sbc
endp
proc ae6x				;AND n
	seges	lodsb
	jmp	a8and
endp
proc aeex				;XOR n
	seges	lodsb
	jmp	a8xor
endp
proc af6x				;OR n
	seges	lodsb
	jmp	a8or
endp
proc afex				;CP n
	seges	lodsb
	jmp	a8cp
endp
proc ac7x				;RST 0
	xor	ax,ax
	jmp	callax
endp
proc acfx				;RST 8
	mov	ax,8
	jmp	callax
endp
proc ad7x				;RST 10
	mov	ax,10h
	jmp	callax
endp
proc adfx				;RST 18
	mov	ax,18h
	jmp	callax
endp
proc ae7x				;RST 20
	mov	ax,20h
	jmp	callax
endp
proc aefx				;RST 28
	mov	ax,28h
	jmp	callax
endp
proc af7x				;RST 30
	mov	ax,30h
	jmp	callax
endp
proc affx				;RST 38
	mov	ax,38h
	jmp	callax
endp
proc ad3x				;OUT (n),A
	seges	lodsb
	mov	ah,[regs.r]
	mov	bl,[regs.a]
	add	ch,7
	jmp	[IOWr]
endp
proc ad9x				;EXX
	lea	bx,[regs.bc]
	mov	ax,[bx]
	xchg	[bx+8],ax
	mov	[bx],ax
	add	bx,2
	mov	ax,[bx]
	xchg	[bx+8],ax
	mov	[bx],ax
	add	bx,2
	mov	ax,[bx]
	xchg	[bx+8],ax
	mov	[bx],ax
	ret
endp
proc adbx				;IN A,(n)
	seges	lodsb
	mov	ah,[regs.r]
	call	[IORd]
	add	ch,7
	mov	[regs.a],al
	ret
endp
proc ae3x				;EX (SP),HL/IX/IY
	mov	bx,[regs.sp_]
	mov	ax,[es:bx]
	xchg	[di],ax
	add	ch,3
	jmp	memwritew12
endp
proc ae9x				;JP (HL)/(IX)/(IY)
	mov	si,[di]
	ret
endp
proc aebx				;EX DE,HL (niemals mit IX/IY)
	mov	ax,[regs.hl]
	xchg	[regs.de],ax
	mov	[regs.hl],ax
	ret
endp
proc af3x				;DI
	and	[regs.iff],not 6	;IFF1=IFF2=0
	ret
endp
proc af9x				;LD SP,HL/IX/IY
	mov	ax,[di]
	mov	[regs.sp_],ax
	ret
endp
proc afbx				;EI
	or	[regs.iff],0Eh		;IFF1=IFF2=1, Int-Verzögerung setzen
	ret
endp
;-------------------------------------------------------------
; Erweiterter Befehlssatz: Präfix CB
;Bei dieser Befehlsgruppe gibt es (wahrscheinlich) keine Zugriffsmöglichkeit
;auf die Register LX,HX,LY,HY, da DD+CB immer das Displacement impliziert!
proc acbx
	seges	lodsb
	add	ch,4		;mindestens 8 Takte
	mov	bl,al
	mov	cl,al		;Opcode nach CL
	and	bx,7		;Register-Nummer
	cmp	di,offset regs.hl
	jnz	@@ixiy		;IX/IY extra behandeln: immer (IX+d)-Zugriff
	cmp	bl,6		;M?
	je	@@m		;dx hat die Speicheradresse
	ja	@@ra1		;A ist "oben"
	xor	bl,1		;BC, DE und HL sind "verkehrtherum"
@@ra1:	add	bx,offset regs.c ;DS:BX zeigt auf das Register B/C/D/E/A
	mov	al,[bx]		;Register lesen
	call	DoCB		;verarbeiten
	mov	[bx],al		;schreiben
	ret

@@m:	add	ch,7		;weitere 7 Takte bei Zugriff über M (15)
	mov	bx,dx		;immer HL
	MOVALBX			;M lesen
	call	DoCB		;verarbeiten
	jmp	[MemWr]		;M schreiben - fertig
@@ixiy:
	add	ch,3		;4+12+7=23 Takte
	push	bx		;Registernummer retten
	 mov	bx,dx		;immer IX+d/IY+d
	 MOVALBX		;(IX+d)/(IY+d) lesen
	 call	DoCB		;verarbeiten
	pop	di		;Registernummer ins andere Adreßregister!
	cmp	di,6		;Normale (dokumentierte) Kodierung?
	je	@@i		;ja, kein Register mitschreiben
	ja	@@ra2		;A ist "oben"
	xor	di,1		;BC, DE und HL sind "verkehrtherum"
@@ra2:	mov	[di+regs.c],al	;Register mitschreiben (undokumentiert)
@@i:	jmp	[MemWr]		;(IX+d)/(IY+d) schreiben - fertig
endp

proc DoCB
;PE: CL=Opcode, CH=Takte, AL=Datenbyte, DH wird Bitmaske, DL=Opcode-Kopie
;PA: AL=Datenbyte
;VR: AX,CL,DX,DI,Flags
	cmp	cl,40h
	jnc	@@bits
	mov	di,cx
	ror	di,2
	and	di,0eh		;CY bei Aufruf gelöscht
	call	[cs:cbtab+di]
	lahf
	mov	cl,ah
	and	cl,1		;nur CY liefert der 80x86
	or	al,al
	lahf
	and	ah,0C4h		;S,Z,P
	or	ah,cl		;C einsetzen
	mov	[regs.f],ah
	ret
@@bits:
	mov	dl,cl		;Opcode retten
	mov	dh,1
	ror	cl,3		;Bitnummer in Position
	and	cl,7		;und maskieren
	shl	dh,cl		;Bitmaske für Bitbefehle in ah
	test	dl,80h
	jnz	@@8		;SET und RES
	mov	ah,[regs.f]
	or	ah,50h
	test	al,dh
	jz	@@4e
	and	ah,not 40h
@@4e:	mov	[regs.f],ah
	ret
@@8:
	test	dl,40h
	jnz	@@c		;SET
	not	dh
	and	al,dh		;RES
	ret
@@c:	or	al,dh		;SET
	ret
endp

proc crcl			;RCL r
	rol	al,1
	ret
endp
proc crrc			;RRC r
	ror	al,1
	ret
endp
proc crl			;RL r
	call	GetCY
	rcl	al,1
	ret
endp
proc crr			;RR r
	call	GetCY
	rcr	al,1
	ret
endp
proc csla			;SLA r
	shl	al,1
	ret
endp
proc csra			;SRA r
	sar	al,1
	ret
endp
proc csli			;SLS r (bisweilen auch SLE r genannt)
	stc
	rcl	al,1
	ret
endp
proc csrl			;SRL r
	shr	al,1
	ret
endp
;-------------------------------------------------------------
proc addx
	lea	di,[regs.ix]
	jmp	OnIXIY
endp
proc afdx
	lea	di,[regs.iy]
	;jmp	OnIXIY
endp
proc OnIXIY
;PE: DI=regs.ix oder regs.iy
	seges	lodsb	;Opcode lesen
	add	ch,4	;kostet 4 Takte
	js	@@e	;>=128? Raus mit temporärem DI!
;Den Speicher mit DD und/oder FD füllen ist die einzige Möglichkeit,
;Windows aufhängen zu lassen (wegen unendlichem Opcode). Natürlich hängt
;dadurch der Emulator fest, wie in der Wirklichkeit. Aber hiermit wird
;Windows eine Chance gelassen... Interrupts müssen aber temporär gesperrt
;werden, da es sich nicht um ein reguläres Befehls-Ende handelt.
	mov	dx,[di]
	xor	bh,bh
	mov	bl,al
;Untersuchung, ob Displacement (Ablage) folgt...
	cmp	al,0cbh
	je	@@y
	sub	al,46h
	and	al,87h	;Reihe "LD r,M" und "op M"
	jne	@@1
	cmp	al,30h	;HALT (LD M,M), Code 76h
	je	@@n
	jmp	@@y
@@1:	mov	al,bl
	and	al,0F8h
	cmp	al,70h	;Reihe "LD M,r"
	je	@@y
	mov	al,bl
	cmp	al,36h	;LD M,n
	je	@@y
	and	al,not 1
	cmp	al,34h	;INC/DEC M
	jne	@@n
@@y:	seges	lodsb
	cbw
	add	dx,ax	;(IX+d)
	add	ch,8	;Displacement berechnen ist teuer!
@@n:	add	bx,bx
	jmp	[cs:codetab+bx]	;PA: ch=Takte
@@e:	or	[regs.iff],8		;Int-Verzögerung setzen
	ret
endp
;-------------------------------------------------------------
proc aedx
	seges	lodsb
	mov	bl,al
	add	ch,4	;mindestens 8 Takte
	test	al,80h
	jnz	@@8
	test	al,40h	;zwischen 0 und 3Fh ist nichts
	jz	@@e
	and	bx,3fh
	shl	bl,1
	mov	ax,[regs.bc]	;Einstieg für die meisten IN/OUT-Befehle
	jmp	[cs:edltab+bx]
@@8:
	sub	al,0A0h	;zwischen A0..A3, A8..AB, B0..B3 und B8..BB
	test	al,11100100b
	jnz	@@e
	rol	al,1
	and	al,6
	and	bx,18h
	or	bl,al
	mov	ax,[regs.bc]
	jmp	[cs:edhtab+bx]
@@e:	ret
endp
proc e40x				;IN B,(C)
	call	[IORd]
	mov	[regs.b],al
	jmp	ein
endp
proc e48x				;IN C,(C)
	call	[IORd]
	mov	[regs.c],al
	jmp	ein
endp
proc e50x				;IN D,(C)
	call	[IORd]
	mov	[regs.d],al
	jmp	ein
endp
proc e58x				;IN E,(C)
	call	[IORd]
	mov	[regs.e],al
	jmp	ein
endp
proc e60x				;IN H,(C)
	call	[IORd]
	mov	[regs.h],al
	jmp	ein
endp
proc e68x				;IN L,(C)
	call	[IORd]
	mov	[regs.l],al
	jmp	ein
endp
proc e70x				;INF
	call	[IORd]
	jmp	ein
endp
proc e78x				;IN A,(C)
	call	[IORd]
	mov	[regs.a],al
ein:	or	al,al			;Flags setzen!
	lahf
	mov	al,[regs.f]
	and	ax,0D401h
	or	al,ah
ein1:	mov	[regs.f],al
	add	ch,4
	ret
endp
proc e41x				;OUT (C),B
	mov	bl,[regs.b]
	call	[IOWr]
	add	ch,4
	ret
endp
proc e49x				;OUT (C),C
	mov	bl,[regs.c]
	call	[IOWr]
	add	ch,4
	ret
endp
proc e51x				;OUT (C),D
	mov	bl,[regs.d]
	call	[IOWr]
	add	ch,4
	ret
endp
proc e59x				;OUT (C),E
	mov	bl,[regs.e]
	call	[IOWr]
	add	ch,4
	ret
endp
proc e61x				;OUT (C),H
	mov	bl,[regs.h]
	call	[IOWr]
	add	ch,4
	ret
endp
proc e69x				;OUT (C),L
	mov	bl,[regs.l]
	call	[IOWr]
	add	ch,4
	ret
endp
proc e71x				;OTCL
	mov	bl,0
	call	[IOWr]
	add	ch,4
	ret
endp
proc e79x				;OUT (C),A
	mov	bl,[regs.a]
	call	[IOWr]
	add	ch,4
	ret
endp
proc e42x				;SBC HL,BC
	mov	bx,[regs.bc]
sbc16:	call	GetCY
	sbb	[regs.hl],bx
	call	lahfv
	or	ah,2
	mov	[regs.f],ah
	add	ch,7
	ret
endp
proc e4ax				;ADC HL,BC
	mov	bx,[regs.bc]
adc16:	call	GetCY
	adc	[regs.hl],bx
	call	lahfv
	and	ah,not 2
	mov	[regs.f],ah
	add	ch,7
	ret
endp
proc e52x				;SBC HL,DE
	mov	bx,[regs.de]
	jmp	sbc16
endp
proc e5ax				;ADC HL,DE
	mov	bx,[regs.de]
	jmp	adc16
endp
proc e62x				;SBC HL,HL
	mov	bx,[regs.hl]
	jmp	sbc16
endp
proc e6ax				;ADC HL,HL
	mov	bx,[regs.bc]
	jmp	adc16
endp
proc e72x				;SBC HL,SP
	mov	bx,[regs.sp_]
	jmp	sbc16
endp
proc e7ax				;ADC HL,SP
	mov	bx,[regs.sp_]
	jmp	adc16
endp
proc e43x				;LD (nn),BC
	seges	lodsw
	xchg	bx,ax
	mov	ax,[regs.bc]
	jmp	memwritew12
endp
proc e4bx				;LD BC,(nn)
	seges	lodsw
	xchg	bx,ax
	MOVAXBX
	mov	[regs.bc],ax
	add	ch,12
	ret
endp
proc e53x				;LD (nn),DE
	seges	lodsw
	xchg	bx,ax
	mov	ax,[regs.de]
	jmp	memwritew12
endp
proc e5bx				;LD DE,(nn)
	seges	lodsw
	xchg	bx,ax
	MOVAXBX
	mov	[regs.de],ax
	add	ch,12
	ret
endp
proc e63x				;LD (nn),HL
	seges	lodsw
	xchg	bx,ax
	mov	ax,[regs.hl]
	jmp	memwritew12
endp
proc e6bx				;LD HL,(nn)
	seges	lodsw
	xchg	bx,ax
	MOVAXBX
	mov	[regs.hl],ax
	add	ch,12
	ret
endp
proc e73x				;LD (nn),SP
	seges	lodsw
	xchg	bx,ax
	mov	ax,[regs.sp_]
	jmp	memwritew12
endp
proc e7bx				;LD SP,(nn)
	seges	lodsw
	xchg	bx,ax
	MOVAXBX
	mov	[regs.sp_],ax
	add	ch,12
	ret
endp
proc e44x				;NEG
e4cx:
e54x:
e5cx:
e64x:
e6cx:
e74x:
e7cx:	neg	[regs.a]
	call	lahfv
	or	ah,2
	mov	[regs.f],ah
	ret
endp
proc e45x				;RETN
e55x:
e65x:
e75x:	mov	al,[regs.iff]
	mov	ah,al
	and	ah,4
	ror	ah,1
	and	al,not 3
	or	al,ah			;IFF1:=IFF2, NMI-In-Service=0
	mov	[regs.iff],al
	jmp	popsi
endp
proc e4dx				;RETI
e5dx:
e6dx:
e7dx:	or	[regs.iff],20h
	jmp	popsi
endp
proc e46x				;IM0
e4ex:
e66x:
e6ex:	mov	[regs.im],0
	ret
endp
proc e56x				;IM1
e76x:	mov	[regs.im],1
	ret
endp
proc e5ex				;IM2
e7ex:	mov	[regs.im],2
	ret
endp
proc e47x				;LD I,A
	mov	al,[regs.a]
	mov	[regs.i],al
	ret
endp
proc e4fx				;LD R,A
	mov	al,[regs.a]
	rol	al,1
	mov	[regs.r],al
	ret
endp
proc e57x				;LD A,I
	mov	al,[regs.a]
	mov	[regs.i],al
ldpv:	mov	ah,[regs.iff]
	mov	al,[regs.f]
	and	ax,4E9h			;IFF2
	or	al,ah
	mov	[regs.f],al
	ret
endp
proc e5fx				;LD A,R
	mov	al,[regs.a]
	ror	al,1
	mov	[regs.r],al
	jmp	ldpv
endp
proc e67x				;RRD
	mov	bx,[regs.hl]
	mov	ah,[regs.a]
	MOVALBX
	ror	ax,4
	ror	ah,4
	jmp	setf
endp
proc e6fx				;RLD
	mov	bx,[regs.hl]
	mov	ah,[regs.a]
	MOVALBX
	rol	ah,4
	rol	ax,4
setf:	mov	[regs.a],ah
	call	[MemWr]
	and	ah,ah
	lahf
	mov	al,[regs.f]
	and	ax,0c429h
	or	al,ah
	or	[regs.f],al
	add	ch,10
	ret
endp
proc ea0x				;LDI
	mov	di,[regs.hl]
	mov	al,[es:di]
	inc	di
	mov	bx,[regs.de]
	call	[MemWr]
	inc	bx
lde:
	mov	[regs.hl],di
	mov	[regs.de],bx
	add	ch,8
	mov	al,[regs.f]
	and	al,not 16h
	mov	bx,[regs.bc]
	dec	bx
	mov	[regs.bc],bx
	jz	@@1
	or	al,4			;wenn BC<>0
@@1:	mov	[regs.f],al
	ret
endp
proc eb0x				;LDIR
	call	ea0x
erep:	test	al,4
	jz	@@1
	dec	si
	dec	si
	add	ch,5
@@1:	ret
endp
proc ea8x				;LDD
	mov	di,[regs.hl]
	mov	al,[es:di]
	dec	di
	mov	bx,[regs.de]
	call	[MemWr]
	dec	bx
	jmp	lde
endp
proc eb8x				;LDDR
	call	ea8x
	jmp	erep
endp
proc ea1x				;CPI
	mov	ax,[regs.af]
	mov	bx,[regs.hl]
	cmp	ah,[es:bx]
	lahf
	inc	bx
cpe:
	add	ch,8
	mov	[regs.hl],bx
	or	ax,not 0d029h
	and	al,ah
	mov	bx,[regs.bc]
	dec	bx
	mov	[regs.bc],bx
	jnz	@@1
	and	al,not 4
@@1:	mov	[regs.f],al
	ret
endp
proc eb1x				;CPIR
	call	ea1x
ecrep:	test	al,40h
	jz	erep
	ret
endp
proc ea9x				;CPD
	mov	ax,[regs.af]
	mov	bx,[regs.hl]
	cmp	ah,[es:bx]
	lahf
	dec	bx
	jmp	cpe
endp
proc eb9x				;CPDR
	call	ea9x
	jmp	ecrep
endp
proc ea2x				;INI
	call	[IORd]
	mov	bx,[regs.hl]
	call	[MemWr]
	inc	bx
ine:	mov	[regs.hl],bx
oute:	add	ch,8
	mov	al,[regs.f]
	or	al,42h
	dec	ah
	mov	[regs.b],ah
	jz	@@1
	and	al,not 40h
@@1:	mov	[regs.f],al
	ret
endp
proc eb2x				;INIR
	call	ea2x
erepio:	test	al,40h
	jnz	@@1
	dec	si
	dec	si
	add	ch,5
@@1:	ret
endp
proc eaax				;IND
	call	[IORd]
	mov	bx,[regs.hl]
	call	[MemWr]
	dec	bx
	jmp	ine
endp
proc ebax				;INDR
	call	eaax
	jmp	erepio
endp
proc ea3x				;OUTI
	mov	bx,[regs.hl]
	mov	bl,[es:bx]
	call	[IOWr]
	inc	[regs.hl]
	jmp	oute
endp
proc eb3x				;OTIR
	call	ea3x
	jmp	erepio
endp
proc eabx				;OUTD
	mov	bx,[regs.hl]
	mov	bl,[es:bx]
	call	[IOWr]
	dec	[regs.hl]
	jmp	oute
endp
proc ebbx				;OTDR
	call	eabx
	jmp	erepio
endp

;--Unterprogramme--
proc GetCY
	mov	ah,[regs.f]
	ror	ah,1
	ret
endp

;lahf lädt das Paritätsbit (P), nicht das Overflow-Bit (V)
;Deshalb dieses Unterprogramm
proc lahfv
	lahf
	jo	@@s
	and	ah,not 4
	ret
@@s:	or	ah,4
	ret
endp

	END
Detected encoding: OEM (CP437)1
Wrong umlauts? - Assume file is ANSI (CP1252) encoded