;**********************************************************
;*
;* Z80 Emulator fr KC Emulator
;*
;*****
;
; es: Adrebereich KC
; ds: restliche Daten (Windows automatisches Datensegment [HInstance])
; si: Programcounter
; ch: Taktzhler
; di: zeigt auf regs.hl oder regs.ix oder regs.iy
; dx: enthlt 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 mglich)
;IFF Bit 1: IFF1
;IFF Bit 2: IFF2
;IFF Bit 3: EI erfolgte (verzgerter Interrupt)
;IFF Bit 4: HALT erfolgte (Int-Quelle mu SI erhhen)
;IFF Bit 5: RETI erfolgte (Signal fr 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 ;Taktzhler fr Statistik
extrn expire: Word ;wenn <0: Zurck zu Windows!
public CpuEmu
public CallAX ;fr 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 nchste Element
id dw ? ;ID fr 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 ? ;enthlt 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 ;"Gelscht" 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
;Einfgen 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 fllen (auer .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 Einfgung 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 bloer 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 lschen
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] ;knnte verndert 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 lschen
seges lodsb ;AL:=[ES:SI], Inc(SI)
mov ch,4 ;Mindest-Taktzahl
CpuEmu1: ;Einsprungpunkt fr 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 enthlt im Normalfall HL
call [cs:codetab+bx] ;PA: ch=Takte
CpuEmu2: ;Einsprungpunkt fr 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 lschen}
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 ausfhren}
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 zurckkaerimas...
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-Verzgerung setzen
ret
endp
;-------------------------------------------------------------
; Erweiterter Befehlssatz: Prfix CB
;Bei dieser Befehlsgruppe gibt es (wahrscheinlich) keine Zugriffsmglichkeit
;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 Adreregister!
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 gelscht
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 fr 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 temporrem DI!
;Den Speicher mit DD und/oder FD fllen ist die einzige Mglichkeit,
;Windows aufhngen zu lassen (wegen unendlichem Opcode). Natrlich hngt
;dadurch der Emulator fest, wie in der Wirklichkeit. Aber hiermit wird
;Windows eine Chance gelassen... Interrupts mssen aber temporr gesperrt
;werden, da es sich nicht um ein regulres 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-Verzgerung 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 fr 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 ldt das Parittsbit (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
Vorgefundene Kodierung: UTF-8 | 0
|