home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 10
/
aminetcdnumber101996.iso
/
Aminet
/
misc
/
emu
/
Frodo.lha
/
Frodo
/
src
/
6510SC.asm
< prev
next >
Wrap
Assembly Source File
|
1995-12-12
|
57KB
|
3,397 lines
*
* 6510SC.asm - Einzelzyklus-6510-Emulation
*
* Copyright (C) 1995 by Christian Bauer
*
*
* Anmerkungen:
* ------------
*
* Registerbelegung:
* d5: Von VIC-Emulation benutzt
* d6: Von VIC-Emulation benutzt
* d7: 6510-Programmzähler
* a3: Von VIC-Emulation benutzt
* a4: Zeiger für Near-Adressierung
* a5: Zeiger in C64-RAM, Offset 32K (für Adressierung mit Vorzeichen)
* a6: Zeiger auf die Routine für den nächsten Taktzyklus. Er wird immer
* am Ende einer Zyklusroutine gesetzt.
*
* Opcode-Ausführung:
* - Alle Opcodes sind in einzelne Taktzyklen aufgelöst, für jeden
* Taktzyklus eines Opcodes existiert eine Routine
* - Die Zyklusroutinen werden vom VIC-Emulator über jsr (CONT)
* angesprungen, jede Routine setzt diesen Zeiger am Ende auf die
* nächste Routine
* - Die Taktzyklen werden von 1 bis 8 gezählt, jede Zyklusroutine
* enthält die Nummer der Zyklus im Namen getrennt durch einen Punkt
* - Im ersten Taktzyklus wird immer der Opcode gelesen
* - In jedem Taktzyklus findet genau ein Speicherzugriff statt
*
* Speicherkonfigurationen:
*
* $01 $a000-$bfff $d000-$dfff $e000-$ffff
* -----------------------------------------------
* 0 RAM RAM RAM
* 1 RAM Char-ROM RAM
* 2 RAM Char-ROM Kernal-ROM
* 3 Basic-ROM Char-ROM Kernal-ROM
* 4 RAM RAM RAM
* 5 RAM I/O RAM
* 6 RAM I/O Kernal-ROM
* 7 Basic-ROM I/O Kernal-ROM
*
* Zugriff auf den C64-Speicher:
* - Alle Speicherzugriffe laufen über die Read/Write-Makros,
* es sind keine Abkürzungen erlaubt
* - Das RAM wird immer über ein 16-Bit-Offset angesprochen (also mit
* Vorzeichen)
*
* Inkompatibilitäten:
* - RRA und ISB kennen keinen Dezimalmodus
* - BRK kann nicht von IRQ/NMI unterbrochen werden
* - Wenn BA low und AEC high ist, sollte ein Lesezugriff stattfinden
*
DEBUG_DETAIL SET 0
DEBUG_PC = $0000
DE00_COMPATIBLE SET 1
MACHINE 68020
INCLUDE "exec/types.i"
INCLUDE "exec/macros.i"
INCLUDE "dos/dostags.i"
INCLUDE "Frodo_rev.i"
CATCOMP_NUMBERS = 1
INCLUDE "LocStrings.i"
INCLUDE "debug.i"
XREF _SysBase
XREF _DOSBase
XREF _IntuitionBase
XREF GetString ;Strings.o
XREF TheLocale
XDEF TheRAM ;Main.asm
XDEF TheBasic
XDEF TheKernal
XDEF TheChar
XDEF TheColor
XREF MainTask
XREF Random
XREF ResetC64
XREF _InitDisplayFrom6510 ;Display.c
XREF _ExitDisplayFrom6510
XREF _EmulToBack
XREF _EmulToFront
XREF ReadFrom6526A ;6526SC.asm
XREF ReadFrom6526B
XREF WriteTo6526A
XREF WriteTo6526B
XREF Main6569 ;6569SC.asm
XREF ReadFrom6569
XREF WriteTo6569
IFNE DE00_COMPATIBLE
NREF LastVICByte
ENDC
NREF CycleCounter
XREF ReadFrom6581 ;6581.asm
XREF WriteTo6581
XREF IECOut ;IEC.asm
XREF IECOutATN
XREF IECOutSec
XREF IECIn
XREF IECSetATN
XREF IECRelATN
XREF IECTurnaround
XREF IECRelease
XDEF Init6510
XDEF Reset6510
XDEF Start6510
XDEF Stop6510
XDEF _Pause6510
XDEF _Resume6510
XDEF _SAMReadByte
XDEF _SAMWriteByte
XDEF Localize6510
XDEF IntIsRESET
XDEF IntIsNMI
XDEF IntIsIRQ
XDEF IntIsVICIRQ
XDEF IntIsCIAIRQ
XDEF FirstIRQCycle
XDEF FirstNMICycle
XDEF NMIState
XDEF BALow
XDEF CPUTask
XDEF IsFrodoSC
XDEF _IsFrodoSC
IFNE DEBUG_DETAIL
XDEF DEBUGON
ENDC
NEAR a4,-2
XREF _DATA_BAS_
SECTION "text",CODE
FAR
**
** Definitionen
**
; Registerbelegung
RPC EQUR d7 ;PC
RAMPTR EQUR a5 ;Zeiger in C64-RAM, Offset 32K (für Adressierung mit Vorzeichen)
CONT EQUR a6 ;Zyklusfortsetzungszeiger
**
** Emulation vorbereiten (Sprungtabellen aufbauen)
**
; ReadTabs aufbauen
Init6510 lea ReadTab0,a0 ;Alle mit RAM vorbelegen
move.w #256*8-1,d0
1$ move.l #ReadByteRAM,(a0)+
dbra d0,1$
move.l #ReadBytePage0,ReadTab0 ;Zeropage immer speziell
move.l #ReadBytePage0,ReadTab1
move.l #ReadBytePage0,ReadTab2
move.l #ReadBytePage0,ReadTab3
move.l #ReadBytePage0,ReadTab4
move.l #ReadBytePage0,ReadTab5
move.l #ReadBytePage0,ReadTab6
move.l #ReadBytePage0,ReadTab7
lea ReadTab3+160*4,a0 ;Basic-ROM
moveq #31,d0
21$ move.l #ReadByteBasic,(a0)+
dbra d0,21$
lea ReadTab7+160*4,a0
moveq #31,d0
22$ move.l #ReadByteBasic,(a0)+
dbra d0,22$
lea ReadTab2+224*4,a0 ;Kernal-ROM
moveq #31,d0
31$ move.l #ReadByteKernal,(a0)+
dbra d0,31$
lea ReadTab3+224*4,a0
moveq #31,d0
32$ move.l #ReadByteKernal,(a0)+
dbra d0,32$
lea ReadTab6+224*4,a0
moveq #31,d0
33$ move.l #ReadByteKernal,(a0)+
dbra d0,33$
lea ReadTab7+224*4,a0
moveq #31,d0
34$ move.l #ReadByteKernal,(a0)+
dbra d0,34$
lea ReadTab5+208*4,a0 ;I/O-Bereich
move.l #ReadByteVIC,(a0)+
move.l #ReadByteVIC,(a0)+
move.l #ReadByteVIC,(a0)+
move.l #ReadByteVIC,(a0)+
move.l #ReadByteSID,(a0)+
move.l #ReadByteSID,(a0)+
move.l #ReadByteSID,(a0)+
move.l #ReadByteSID,(a0)+
move.l #ReadByteColor,(a0)+
move.l #ReadByteColor,(a0)+
move.l #ReadByteColor,(a0)+
move.l #ReadByteColor,(a0)+
move.l #ReadByteCIA1,(a0)+
move.l #ReadByteCIA2,(a0)+
move.l #ReadByteUndef,(a0)+
move.l #ReadByteUndef,(a0)
lea ReadTab6+208*4,a0
move.l #ReadByteVIC,(a0)+
move.l #ReadByteVIC,(a0)+
move.l #ReadByteVIC,(a0)+
move.l #ReadByteVIC,(a0)+
move.l #ReadByteSID,(a0)+
move.l #ReadByteSID,(a0)+
move.l #ReadByteSID,(a0)+
move.l #ReadByteSID,(a0)+
move.l #ReadByteColor,(a0)+
move.l #ReadByteColor,(a0)+
move.l #ReadByteColor,(a0)+
move.l #ReadByteColor,(a0)+
move.l #ReadByteCIA1,(a0)+
move.l #ReadByteCIA2,(a0)+
move.l #ReadByteUndef,(a0)+
move.l #ReadByteUndef,(a0)
lea ReadTab7+208*4,a0
move.l #ReadByteVIC,(a0)+
move.l #ReadByteVIC,(a0)+
move.l #ReadByteVIC,(a0)+
move.l #ReadByteVIC,(a0)+
move.l #ReadByteSID,(a0)+
move.l #ReadByteSID,(a0)+
move.l #ReadByteSID,(a0)+
move.l #ReadByteSID,(a0)+
move.l #ReadByteColor,(a0)+
move.l #ReadByteColor,(a0)+
move.l #ReadByteColor,(a0)+
move.l #ReadByteColor,(a0)+
move.l #ReadByteCIA1,(a0)+
move.l #ReadByteCIA2,(a0)+
move.l #ReadByteUndef,(a0)+
move.l #ReadByteUndef,(a0)
lea ReadTab1+208*4,a0 ;Char-ROM
moveq #15,d0
41$ move.l #ReadByteChar,(a0)+
dbra d0,41$
lea ReadTab2+208*4,a0
moveq #15,d0
42$ move.l #ReadByteChar,(a0)+
dbra d0,42$
lea ReadTab3+208*4,a0
moveq #15,d0
43$ move.l #ReadByteChar,(a0)+
dbra d0,43$
; WriteTabs aufbauen
lea WriteTab0,a0 ;Alle mit RAM vorbelegen
move.w #256*8-1,d0
5$ move.l #WriteByteRAM,(a0)+
dbra d0,5$
move.l #WriteBytePage0,WriteTab0 ;Zeropage immer speziell
move.l #WriteBytePage0,WriteTab1
move.l #WriteBytePage0,WriteTab2
move.l #WriteBytePage0,WriteTab3
move.l #WriteBytePage0,WriteTab4
move.l #WriteBytePage0,WriteTab5
move.l #WriteBytePage0,WriteTab6
move.l #WriteBytePage0,WriteTab7
lea WriteTab5+208*4,a0 ;I/O-Bereich
move.l #WriteByteVIC,(a0)+
move.l #WriteByteVIC,(a0)+
move.l #WriteByteVIC,(a0)+
move.l #WriteByteVIC,(a0)+
move.l #WriteByteSID,(a0)+
move.l #WriteByteSID,(a0)+
move.l #WriteByteSID,(a0)+
move.l #WriteByteSID,(a0)+
move.l #WriteByteColor,(a0)+
move.l #WriteByteColor,(a0)+
move.l #WriteByteColor,(a0)+
move.l #WriteByteColor,(a0)+
move.l #WriteByteCIA1,(a0)+
move.l #WriteByteCIA2,(a0)+
move.l #WriteByteUndef,(a0)+
move.l #WriteByteUndef,(a0)
lea WriteTab6+208*4,a0
move.l #WriteByteVIC,(a0)+
move.l #WriteByteVIC,(a0)+
move.l #WriteByteVIC,(a0)+
move.l #WriteByteVIC,(a0)+
move.l #WriteByteSID,(a0)+
move.l #WriteByteSID,(a0)+
move.l #WriteByteSID,(a0)+
move.l #WriteByteSID,(a0)+
move.l #WriteByteColor,(a0)+
move.l #WriteByteColor,(a0)+
move.l #WriteByteColor,(a0)+
move.l #WriteByteColor,(a0)+
move.l #WriteByteCIA1,(a0)+
move.l #WriteByteCIA2,(a0)+
move.l #WriteByteUndef,(a0)+
move.l #WriteByteUndef,(a0)
lea WriteTab7+208*4,a0
move.l #WriteByteVIC,(a0)+
move.l #WriteByteVIC,(a0)+
move.l #WriteByteVIC,(a0)+
move.l #WriteByteVIC,(a0)+
move.l #WriteByteSID,(a0)+
move.l #WriteByteSID,(a0)+
move.l #WriteByteSID,(a0)+
move.l #WriteByteSID,(a0)+
move.l #WriteByteColor,(a0)+
move.l #WriteByteColor,(a0)+
move.l #WriteByteColor,(a0)+
move.l #WriteByteColor,(a0)+
move.l #WriteByteCIA1,(a0)+
move.l #WriteByteCIA2,(a0)+
move.l #WriteByteUndef,(a0)+
move.l #WriteByteUndef,(a0)
rts
**
** 6510 zurücksetzen
**
Reset6510 st.b IntIsRESET
rts
**
** 6510-Task starten
** Rückgabe: d0#0 = Fehler
**
; Signal einrichten
Start6510 move.l _SysBase,a6
moveq #-1,d0
JSRLIB AllocSignal
move.b d0,ReadySig
moveq #0,d1
bset d0,d1
move.l d1,ReadySet
; Task starten
move.l _DOSBase,a6
move.l #ProcTags,d1
JSRLIB CreateNewProc
move.l d0,CPUProc
beq 1$
; Auf Signal warten
move.l _SysBase,a6
move.l ReadySet,d0
JSRLIB Wait
moveq #0,d0 ;Alles OK
rts
; Fehler aufgetreten
1$ moveq #-1,d0
rts
**
** 6510-Task stoppen
**
; Task stoppen
Stop6510 move.l _SysBase,a6
tst.l CPUProc
beq 1$
st RESETIsEXIT ;EXIT-Reset auslösen
st IntIsRESET
move.l ReadySet,d0
JSRLIB Wait
; Signal freigeben
1$ move.b ReadySig,d0
JMPLIB FreeSignal
**
** 6510-Task anhalten, Zustand sichern
**
_Pause6510 move.l a6,-(sp)
move.l _SysBase,a6
st RESETIsPause ;Pause-Reset auslösen
st IntIsRESET
move.l ReadySet,d0
JSRLIB Wait
move.l (sp)+,a6
rts
**
** 6510-Task fortsetzen, Zustand übernehmen
**
_Resume6510 move.l a6,-(sp)
move.l _SysBase,a6
move.l CPUTask,a1 ;Continue-Signal schicken
move.l ContinueSet,d0
JSRLIB Signal
move.l (sp)+,a6
rts
**
** Byte lesen (für SAM)
**
_SAMReadByte moveq #0,d0
move.w 6(sp),d0
movem.l d2/a4/RAMPTR,-(sp)
lea _DATA_BAS_,a4
lea 32766(a4),a4
move.l TheRAMPTR,RAMPTR
move.l d0,d1
lsr.w #8,d1
move.b _SAMMemConfig,d2
and.w #7,d2
move.l (ConfigTab,d2.w*8),a0
move.l (a0,d1.w*4),a0
jsr (a0)
movem.l (sp)+,d2/a4/RAMPTR
rts
**
** Byte schreiben (für SAM)
**
_SAMWriteByte moveq #0,d0
move.w 6(sp),d0
move.l 8(sp),d1
cmp.w #$d000,d0
blo 1$
movem.l d2/a4/RAMPTR,-(sp)
lea _DATA_BAS_,a4
lea 32766(a4),a4
move.l TheRAMPTR,RAMPTR
move.b _SAMMemConfig,d2
and.w #7,d2
move.l (ConfigTab+4,d2.w*8),a0
move.l d0,d2
lsr.w #8,d2
move.l (a0,d2.w*4),a0
jsr (a0)
movem.l (sp)+,d2/a4/RAMPTR
rts
1$ move.l TheRAMPTR,a0
move.b d1,(a0,d0.w)
rts
**
** Strings in Datenstrukturen lokalisieren
**
GetStr MACRO ;Label
lea TheLocale,a0
move.l #\1,d0
jsr GetString
ENDM
Localize6510 GetStr MSG_REQTITLE
move.l d0,IllegalOpReq+8
GetStr MSG_REQGADS3
move.l d0,IllegalOpReq+16
GetStr MSG_ILLEGALOP
move.l d0,IllegalOpReq+12
rts
**
** 6510-Emulator
**
NEAR
*
* Makros
*
; Speicherkonfiguration neu einstellen
NewConfig MACRO
move.b RDDR,d0 ;Zustand der Ausgabepins lesen
not.b d0 ;Eingabepins sind 1
or.b RPR,d0
and.w #7,d0 ;Relevante Bits maskieren
move.l (ConfigTab,d0.w*8),RDTAB
move.l (ConfigTab+4,d0.w*8),WRTAB
ENDM
; Abschluß einer Zyklusroutine, Fortsetzungszeiger setzen
Next MACRO ;Nächste Routine
lea \1,CONT
rts
ENDM
; Abschluß eines Opcodes, im nächsten Zyklus neuen Opcode lesen
Last MACRO
Next Fetch
ENDM
; Anfang eines Opcodes, Zeiger auf ersten Zyklus holen
Execute MACRO
ReadPCInc
and.w #$00ff,d0
move.l (OpcodeTable,d0.w*4),CONT
rts
ENDM
; Stackzeiger erhöhen
IncS MACRO
addq.b #1,RS+1
ENDM
; Stackzeiger erniedrigen
DecS MACRO
subq.b #1,RS+1
ENDM
; Byte bei (PC) lesen
ReadPC MACRO ;[Ziel]
move.w RPC,d0
bsr ReadByte
IFGE NARG-1
move.b d0,\1
ENDC
ENDM
; Byte bei (PC) lesen und PC inkrementieren
ReadPCInc MACRO ;[Ziel]
move.w RPC,d0
bsr ReadByte
addq.w #1,RPC
IFGE NARG-1
move.b d0,\1
ENDC
ENDM
; Byte bei (ADR) lesen
ReadADR MACRO ;[Ziel]
move.w RADR,d0
bsr ReadByte
IFGE NARG-1
move.b d0,\1
ENDC
ENDM
; Byte bei (ADR2) lesen
ReadADR2 MACRO ;[Ziel]
move.w RADR2,d0
bsr ReadByte
IFGE NARG-1
move.b d0,\1
ENDC
ENDM
; Byte bei $0100,S lesen
ReadStack MACRO ;[Ziel]
move.w RS,d0 ;S ist ja 16-Bit, $01xx
bsr ReadByte
IFGE NARG-1
move.b d0,\1
ENDC
ENDM
; Status vom Stack holen
PopP MACRO
ReadStack
clr.b RCCR+1
tst.b d0 ;N holen
bpl PopPNoN\@
or.b #$08,RCCR+1
PopPNoN\@ add.b d0,d0 ;V holen
smi ROVERFLOW
lsl.b #3,d0 ;D holen
smi RDECIMAL
add.b d0,d0 ;I holen
smi RINTERRUPT
add.b d0,d0 ;Z holen
bpl PopPNoZ\@
or.b #$04,RCCR+1
PopPNoZ\@ add.b d0,d0 ;C holen
smi RCARRY
ENDM
; Byte nach (ADR) schreiben
WriteADR MACRO ;Quelle
move.w RADR,d0
move.b \1,d1
bsr WriteByte
ENDM
; Byte nach $0100,S schreiben
WriteStack MACRO ;[Quelle]
move.w RS,d0
IFGE NARG-1
move.b \1,d1
ENDC
bsr WriteByte
ENDM
; Status auf den Stack legen
PushP MACRO ;Break-Bit
moveq #0,d1
move.w RS,d0
btst #3,RCCR+1 ;N dazunehmen
beq PushPNoN\@
or.b #$80,d1
PushPNoN\@ tst.b ROVERFLOW ;V dazunehmen
beq PushPNoV\@
or.b #$40,d1
PushPNoV\@ tst.b RDECIMAL ;D dazunehmen
beq PushPNoD\@
or.b #$08,d1
PushPNoD\@ tst.b RINTERRUPT ;I dazunehmen
beq PushPNoI\@
or.b #$04,d1
PushPNoI\@ btst #2,RCCR+1 ;Z dazunehmen
beq PushPNoZ\@
or.b #$02,d1
PushPNoZ\@ tst.b RCARRY ;C dazunehmen
beq PushPNoC\@
or.b #$01,d1
PushPNoC\@
IFEQ \1
or.b #$20,d1 ;1 setzen
ELSE
or.b #$30,d1 ;B und 1 setzen
ENDC
bsr WriteByte
DecS
ENDM
; Zyklus 2: Byte über unmittelbare Adressierung lesen
ReadByteImm MACRO ;[Ziel]
ReadPCInc \1
ENDM
; Zyklus 2: Adresse für Zero-Page-Adressierung nach ADR lesen
ReadAdrZero MACRO ;Name des Opcodes
ReadPCInc RADRL
clr.b RADRH
Next \1_3
\1_3
ENDM
; Zyklus 2/3: Byte über Zero-Page-Adressierung lesen
ReadByteZero MACRO ;Name des Opcodes, [Ziel]
ReadAdrZero \1
ReadADR \2
ENDM
; Zyklus 2/3/4: Byte über Zero-Page-Adressierung nach RDBUF lesen und zurückschreiben
ReadRMWZero MACRO ;Name des Opcodes
ReadAdrZero \1
ReadADR RDBUF
Next \1_4
\1_4 WriteADR RDBUF
Next \1_5
\1_5
ENDM
; Zyklus 2/3: Adresse für X-indizierte Zero-Page-Adressierung nach ADR lesen
ReadAdrZeroX MACRO ;Name des Opcodes
ReadPCInc RADRL
clr.b RADRH
Next \1_3
\1_3 ReadADR
move.b RX,d0
add.b d0,RADRL ;Keine Seitenüberschreitung
Next \1_4
\1_4
ENDM
; Zyklus 2/3/4: Byte über X-indizierte Zero-Page-Adressierung lesen
ReadByteZeroX MACRO ;Name des Opcodes, [Ziel]
ReadAdrZeroX \1
ReadADR \2
ENDM
; Zyklus 2/3/4/5: Byte über X-indizierte Zero-Page-Adressierung nach RDBUF lesen und zurückschreiben
ReadRMWZeroX MACRO ;Name des Opcodes
ReadAdrZeroX \1
ReadADR RDBUF
Next \1_5
\1_5 WriteADR RDBUF
Next \1_6
\1_6
ENDM
; Zyklus 2/3: Adresse für Y-indizierte Zero-Page-Adressierung nach ADR lesen
ReadAdrZeroY MACRO ;Name des Opcodes
ReadPCInc RADRL
clr.b RADRH
Next \1_3
\1_3 ReadADR
move.b RY,d0
add.b d0,RADRL ;Keine Seitenüberschreitung
Next \1_4
\1_4
ENDM
; Zyklus 2/3/4: Byte über Y-indizierte Zero-Page-Adressierung lesen
ReadByteZeroY MACRO ;Name des Opcodes, [Ziel]
ReadAdrZeroY \1
ReadADR \2
ENDM
; Zyklus 2/3: Adresse für absolute Adressierung nach ADR lesen
ReadAdrAbs MACRO ;Name des Opcodes
ReadPCInc RADRL
Next \1_3
\1_3 ReadPCInc RADRH
Next \1_4
\1_4
ENDM
; Zyklus 2/3/4: Byte über absolute Adressierung lesen
ReadByteAbs MACRO ;Name des Opcodes, [Ziel]
ReadAdrAbs \1
ReadADR \2
ENDM
; Zyklus 2/3/4/5: Byte über absolute Adressierung nach RDBUF lesen und zurückschreiben
ReadRMWAbs MACRO ;Name des Opcodes
ReadAdrAbs \1
ReadADR RDBUF
Next \1_5
\1_5 WriteADR RDBUF
Next \1_6
\1_6
ENDM
; Zyklus 2/3/4: Adresse für X-indizierte absolute Adressierung nach ADR lesen
; Kein Extrazyklus bei Seitenüberschreitung
ReadAdrAbsX MACRO ;Name des Opcodes
ReadPCInc RADRL
Next \1_3
\1_3 ReadPCInc RADRH
move.b RX,d0
add.b d0,RADRL
bcs \@1$ ;Seitenüberschreitung?
Next \1_4a
\@1$ Next \1_4b
\1_4a ReadADR ;Nein, von Adresse lesen
Next \1_5
\1_4b ReadADR ;Ja, von falscher Adresse lesen
addq.b #1,RADRH ; und Adresse korrigieren
Next \1_5
\1_5
ENDM
; Zyklus 2/3/(4)/5: Byte über X-indizierte absolute Adressierung lesen
; Extrazyklus bei Seitenüberschreitung
ReadByteAbsX MACRO ;Name des Opcodes, [Ziel]
ReadPCInc RADRL
Next \1_3
\1_3 ReadPCInc RADRH
move.b RX,d0
add.b d0,RADRL
bcs \@1$ ;Seitenüberschreitung?
Next \1_5
\@1$ Next \1_4
\1_4 ReadADR ;Ja, erst von falscher Adresse lesen
addq.b #1,RADRH ; und Adresse korrigieren
Next \1_5
\1_5 ReadADR \2 ;Byte lesen
ENDM
; Zyklus 2/3/4/5/6: Byte über X-indizierte absolute Adressierung nach RDBUF lesen und zurückschreiben
; Kein Extrazyklus bei Seitenüberschreitung
ReadRMWAbsX MACRO ;Name des Opcodes
ReadAdrAbsX \1
ReadADR RDBUF
Next \1_6
\1_6 WriteADR RDBUF
Next \1_7
\1_7
ENDM
; Zyklus 2/3/4: Adresse für Y-indizierte absolute Adressierung nach ADR lesen
; Kein Extrazyklus bei Seitenüberschreitung
ReadAdrAbsY MACRO ;Name des Opcodes
ReadPCInc RADRL
Next \1_3
\1_3 ReadPCInc RADRH
move.b RY,d0
add.b d0,RADRL
bcs \@1$ ;Seitenüberschreitung?
Next \1_4a
\@1$ Next \1_4b
\1_4a ReadADR ;Nein, von Adresse lesen (unnötig)
Next \1_5
\1_4b ReadADR ;Ja, von falscher Adresse lesen
addq.b #1,RADRH ; und Adresse korrigieren
Next \1_5
\1_5
ENDM
; Zyklus 2/3/(4)/5: Byte über Y-indizierte absolute Adressierung lesen
; Extrazyklus bei Seitenüberschreitung
ReadByteAbsY MACRO ;Name des Opcodes, [Ziel]
ReadPCInc RADRL
Next \1_3
\1_3 ReadPCInc RADRH
move.b RY,d0
add.b d0,RADRL
bcs \@1$ ;Seitenüberschreitung?
Next \1_5
\@1$ Next \1_4
\1_4 ReadADR ;Ja, erst von falscher Adresse lesen
addq.b #1,RADRH ; und Adresse korrigieren
Next \1_5
\1_5 ReadADR \2 ;Byte lesen
ENDM
; Zyklus 2/3/4/5/6: Byte über Y-indizierte absolute Adressierung nach RDBUF lesen und zurückschreiben
; Kein Extrazyklus bei Seitenüberschreitung
ReadRMWAbsY MACRO ;Name des Opcodes
ReadAdrAbsY \1
ReadADR RDBUF
Next \1_6
\1_6 WriteADR RDBUF
Next \1_7
\1_7
ENDM
; Zyklus 2/3/4/5: Adresse für indiziert-indirekte Adressierung nach ADR lesen
ReadAdrIndX MACRO ;Name des Opcodes
ReadPCInc RADR2L
clr.b RADR2H
Next \1_3
\1_3 ReadADR2
move.b RX,d0
add.b d0,RADR2L
Next \1_4
\1_4 ReadADR2 RADRL
addq.b #1,RADR2L ;Keine Seitenüberschreitung
Next \1_5
\1_5 ReadADR2 RADRH
Next \1_6
\1_6
ENDM
; Zyklus 2/3/4/5/6: Byte über indiziert-indirekte Adressierung lesen
ReadByteIndX MACRO ;Name des Opcodes, [Ziel]
ReadAdrIndX \1
ReadADR \2
ENDM
; Zyklus 2/3/4/5/6/7: Byte über indiziert-indirekte Adressierung nach RDBUF lesen und zurückschreiben
ReadRMWIndX MACRO ;Name des Opcodes
ReadAdrIndX \1
ReadADR RDBUF
Next \1_7
\1_7 WriteADR RDBUF
Next \1_8
\1_8
ENDM
; Zyklus 2/3/4/5: Adresse für indirekt-indizierte Adressierung nach ADR lesen
; Kein Extrazyklus bei Seitenüberschreitung
ReadAdrIndY MACRO ;Name des Opcodes
ReadPCInc RADR2L
clr.b RADR2H
Next \1_3
\1_3 ReadADR2 RADRL
addq.b #1,RADR2L ;Keine Seitenüberschreitung
Next \1_4
\1_4 ReadADR2 RADRH
move.b RY,d0
add.b d0,RADRL
bcs \@1$ ;Seitenüberschreitung?
Next \1_5a
\@1$ Next \1_5b
\1_5a ReadADR ;Nein, von Adresse lesen (unnötig)
Next \1_6
\1_5b ReadADR ;Ja, von falscher Adresse lesen
addq.b #1,RADRH ; und Adresse korrigieren
Next \1_6
\1_6
ENDM
; Zyklus 2/3/4/(5)/6: Byte über indirekt-indizierte Adressierung lesen
; Extrazyklus bei Seitenüberschreitung
ReadByteIndY MACRO ;Name des Opcodes, [Ziel]
ReadPCInc RADR2L
clr.b RADR2H
Next \1_3
\1_3 ReadADR2 RADRL
addq.b #1,RADR2L ;Keine Seitenüberschreitung
Next \1_4
\1_4 ReadADR2 RADRH
move.b RY,d0
add.b d0,RADRL
bcs \@1$ ;Seitenüberschreitung?
Next \1_6
\@1$ Next \1_5
\1_5 ReadADR ;Ja, erst von falscher Adresse lesen
addq.b #1,RADRH ; und Adresse korrigieren
Next \1_6
\1_6 ReadADR \2 ;Byte lesen
ENDM
; Zyklus 2/3/4/5/6/7: Byte über indirekt-indizierte Adressierung nach RDBUF lesen und zurückschreiben
; Kein Extrazyklus bei Seitenüberschreitung
ReadRMWIndY MACRO ;Name des Opcodes
ReadAdrIndY \1
ReadADR RDBUF
Next \1_7
\1_7 WriteADR RDBUF
Next \1_8
\1_8
ENDM
*
* Byte lesen
*
; Ein Byte von der CPU aus lesen
; -> d0.w: Adresse
; <- d0.b: Byte
ReadByte tst.b BALow ;BA low?
bne ReadBAIsLow
IFNE DEBUG_DETAIL
tst.b DEBUGON
beq 1$
move.l d0,-(sp)
bsr 1$
move.l (sp)+,d1
and.l #$00ff,d0
and.l #$ffff,d1
DPRINTF "CPU Read %04lx -> #%02lx",d1,d0
rts
1$
ENDC
move.w d0,d1 ;Nein, Lesezugriff ausführen
lsr.w #8,d1
move.l RDTAB,a0
move.l (a0,d1.w*4),a0
jmp (a0)
ReadBAIsLow move.w d0,HALTADRSTORE ;Sonst Register retten
move.l CONT,HALTCONTSTORE
move.l (sp)+,HALTRETADR
IFNE DEBUG_DETAIL
tst.b DEBUGON
beq 1$
DPRINTF "CPU Halted (RDY 1->0)"
1$
ENDC
Next ReadCheckBA ;und in Warteschleife gehen
ReadCheckBA tst.b BALow ;Nächster Zyklus: BA immer noch low?
beq ReadBADone
IFNE DEBUG_DETAIL
tst.b DEBUGON
beq 1$
DPRINTF "CPU Halted (RDY 0)"
1$
ENDC
Next ReadCheckBA ;Ja, weiter warten
ReadBADone move.w HALTADRSTORE,d0 ;Nein, Register wieder holen
move.l HALTCONTSTORE,CONT
move.w d0,d1
move.l HALTRETADR,-(sp)
IFNE DEBUG_DETAIL
tst.b DEBUGON
beq 1$
move.l d0,-(sp)
bsr 1$
move.l (sp)+,d1
and.l #$00ff,d0
and.l #$ffff,d1
DPRINTF "CPU Read %04lx -> #%02lx",d1,d0
rts
1$
ENDC
lsr.w #8,d1
move.l RDTAB,a0
move.l (a0,d1.w*4),a0
jmp (a0)
ReadBytePage0 cmp.w #2,d0
bhs ReadByteRAM
tst.w d0 ;Adresse 0: DDR
bne 1$
move.b RDDR,d0
rts
1$ move.b RDDR,d0 ;Adresse 1: PR
move.b d0,d1
and.b RPR,d0
not.b d1
and.b #%00010111,d1 ;Eingabepins
or.b d1,d0
rts
ReadByteRAM move.b (RAMPTR,d0.w),d0
rts
ReadByteBasic and.w #$1fff,d0
move.l TheBasic,a0
move.b (a0,d0.w),d0
rts
ReadByteVIC and.w #$3f,d0
bra ReadFrom6569
ReadByteSID and.w #$1f,d0
jmp ReadFrom6581
ReadByteColor and.w #$03ff,d0
move.l TheColor,a0
move.b (a0,d0.w),d0
and.b #$0f,d0
IFNE DE00_COMPATIBLE
move.b LastVICByte,d1 ;Oberes Nibble kommt vom VIC
and.b #$f0,d1
or.b d1,d0
ENDC
rts
ReadByteCIA1 and.w #$0f,d0
bra ReadFrom6526A
ReadByteCIA2 and.w #$0f,d0
bra ReadFrom6526B
ReadByteUndef
IFNE DE00_COMPATIBLE
move.b LastVICByte,d0
ELSE
move.b #$aa,d0
ENDC
rts
ReadByteKernal and.w #$1fff,d0
move.l TheKernal,a0
move.b (a0,d0.w),d0
rts
ReadByteChar and.w #$0fff,d0
move.l TheChar,a0
move.b (a0,d0.w),d0
rts
*
* Byte schreiben
*
; Ein Byte von der CPU aus schreiben
; -> d0.w: Adresse
; -> d1.b: Byte
WriteByte
IFNE DEBUG_DETAIL
tst.b DEBUGON
beq 1$
and.l #$ffff,d0
and.l #$00ff,d1
DPRINTF "CPU Write #%02lx -> %04lx",d1,d0
1$
ENDC
move.w d0,d2
lsr.w #8,d2
move.l WRTAB,a0
move.l (a0,d2.w*4),a0
jmp (a0)
WriteBytePage0 cmp.w #2,d0
bhs WriteByteRAM
tst.w d0
bne 1$
move.b d1,RDDR ;Adresse 0: DDR
IFNE DE00_COMPATIBLE
move.b LastVICByte,(RAMPTR)
ENDC
NewConfig
rts
1$ move.b d1,RPR ;Adresse 1: PR
IFNE DE00_COMPATIBLE
move.b LastVICByte,1(RAMPTR)
ENDC
NewConfig
rts
WriteByteRAM move.b d1,(RAMPTR,d0.w)
rts
WriteByteVIC and.w #$3f,d0
bra WriteTo6569
WriteByteSID and.w #$1f,d0
jmp WriteTo6581
WriteByteColor and.w #$03ff,d0
move.l TheColor,a0
move.b d1,(a0,d0.w)
rts
WriteByteCIA1 and.w #$0f,d0
bra WriteTo6526A
WriteByteCIA2 and.w #$0f,d0
bra WriteTo6526B
WriteByteUndef rts
*
* Start
*
; Near-Adressierung initialisieren
CPUTaskProc lea _DATA_BAS_,a4
lea 32766(a4),a4
; Stackpointer retten
move.l a7,InitialSP
; Task ermitteln
move.l _SysBase,a6
sub.l a1,a1
JSRLIB FindTask
move.l d0,CPUTask
; Continue-Signal holen
moveq #-1,d0
JSRLIB AllocSignal
move.b d0,ContinueSig
moveq #0,d1
bset d0,d1
move.l d1,ContinueSet
; Grafik initialisieren
jsr _InitDisplayFrom6510
; Signal an den Emulator schicken
move.l _SysBase,a6
move.l MainTask,a1
move.l ReadySet,d0
JSRLIB Signal
; RAM mit Einschaltmuster initialisieren
move.l TheRAM,d0
add.l #$8000,d0
move.l d0,TheRAMPTR
move.l TheRAM,a0
move.w #511,d1
3$ moveq #63,d0
1$ clr.b (a0)+ ;Abwechselnd 64 Bytes $00
dbra d0,1$
moveq #63,d0
2$ st (a0)+ ;Und 64 Bytes $ff
dbra d0,2$
dbra d1,3$
; Farb-RAM mit Zufallswerten initialisieren
move.l TheColor,a2
move.w #$03ff,d2
4$ jsr Random
move.b d0,(a2)+
dbra d2,4$
; Prozessor initilisieren
move.l TheRAMPTR,RAMPTR
clr.l Interrupt ;Interrupts aus
clr.b RESETIsEXIT
clr.b RESETIsPause
clr.b NMIState
clr.b RA ;Register löschen
clr.b RX
clr.b RY
move.w #$01ff,RS
clr.w RCCR
st RINTERRUPT
clr.b RDECIMAL
clr.b RCARRY
clr.w RADR
clr.b RDDR ;Speicherkonfiguration einstellen
clr.b RPR
NewConfig
clr.b BALow
; Reset-Vektor lesen, PC setzen und für ersten Befehl vorbereiten
move.w #$fffd,d0
bsr ReadByte
move.b d0,RPC
lsl.w #8,RPC
move.w #$fffc,d0
bsr ReadByte
move.b d0,RPC
lea Fetch,CONT
; Ab jetzt kontrolliert der VIC alles
bra Main6569
*
* Opcode lesen
*
Fetch
IFNE DEBUG_DETAIL
cmp.w #DEBUG_PC,RPC
bne 1$
st DEBUGON
1$
ENDC
tst.l Interrupt
bne HandleInt
Execute
*
* Ungültiger Opcode
*
; Unbekannten Opcode entdeckt: Requester darstellen
IllegalOp movem.l a2-a6,-(sp)
and.w #$00ff,d0 ;Opcode
move.w d0,RequestStream
move.w RPC,d0 ;und PC anzeigen
subq.w #1,d0
move.w d0,RequestStream+2
jsr _EmulToBack
move.l _IntuitionBase,a6
sub.l a0,a0
lea IllegalOpReq,a1
move.l a0,a2
lea RequestStream,a3
JSRLIB EasyRequestArgs
move.l d0,-(sp)
jsr _EmulToFront
move.l (sp)+,d0
movem.l (sp)+,a2-a6
tst.l d0
beq 1$
jsr ResetC64
1$ Last
*
* Interrupts handhaben
*
; Art des Interrupt feststellen (Priorität)
HandleInt tst.b IntIsRESET
bne HandleRESET
tst.b IntIsNMI
bne HandleNMI
tst.w IntIsIRQ
bne HandleIRQ
; Kein Interrupt, Befehl ausführen
IntDont Execute
; IRQ: Interrupt-Bit testen, nach ($fffe) springen
HandleIRQ move.l CycleCounter,d0 ;IRQ muß seit zwei Zyklen anliegen
sub.l FirstIRQCycle,d0
moveq #2,d1
cmp.l d1,d0
blo IntDont
tst.b RINTERRUPT
bne IntDont
IFNE DEBUG_DETAIL
tst.b DEBUGON
beq 1$
DPRINTF "CPU IRQ Sequence"
1$
ENDC
IRQ_1 ReadPC
Next IRQ_2
IRQ_2 ReadPC
Next IRQ_3
IRQ_3 move.w RPC,d1
lsr.w #8,d1
WriteStack
DecS
Next IRQ_4
IRQ_4 move.b RPC,d1
WriteStack
DecS
Next IRQ_5
IRQ_5 PushP 0 ;B auf 0
Next IRQ_6
IRQ_6 st RINTERRUPT
move.w #$fffe,d0 ;IRQ-Vektor
bsr ReadByte
move.b d0,RPC
lsl.w #8,RPC
Next IRQ_7
IRQ_7 move.w #$ffff,d0
bsr ReadByte
move.b d0,RPC
ror.w #8,RPC
Last
; NMI: Nach ($fffa) springen
HandleNMI move.l CycleCounter,d0 ;NMI muß seit zwei Zyklen anliegen
sub.l FirstNMICycle,d0
moveq #2,d1
cmp.l d1,d0
blo IntDont
clr.b IntIsNMI ;Simuliert einen flankengetriggerten Eingang
IFNE DEBUG_DETAIL
tst.b DEBUGON
beq 1$
DPRINTF "CPU NMI Sequence"
1$
ENDC
NMI_1 ReadPC
Next NMI_2
NMI_2 ReadPC
Next NMI_3
NMI_3 move.w RPC,d1
lsr.w #8,d1
WriteStack
DecS
Next NMI_4
NMI_4 move.b RPC,d1
WriteStack
DecS
Next NMI_5
NMI_5 PushP 0 ;B auf 0
Next NMI_6
NMI_6 st RINTERRUPT
move.w #$fffa,d0 ;NMI-Vektor
bsr ReadByte
move.b d0,RPC
lsl.w #8,RPC
Next NMI_7
NMI_7 move.w #$fffb,d0
bsr ReadByte
move.b d0,RPC
ror.w #8,RPC
Last
; RESET: Emulator beenden, anhalten oder nach ($fffc) springen
HandleRESET tst.b RESETIsEXIT ;Beenden?
bne HandleEXIT
tst.b RESETIsPause ;Pause?
bne HandlePause
clr.l Interrupt ;Nein, RESET
clr.b NMIState
move.l TheRAM,a0 ;Adressierung ohne Vorzeichen!
cmp.l #$c3c2cd38,$4(a0) ; $4 ist $8004!
bne 1$
cmp.b #$30,$8(a0)
bne 1$
clr.b $4(a0) ;CBM80 löschen, wenn vorhanden
1$ clr.b RDDR ;Speicherkonfiguration einstellen
clr.b RPR
NewConfig
move.w #$fffd,d0 ;RESET-Vektor
bsr ReadByte
move.b d0,RPC
lsl.w #8,RPC
move.w #$fffc,d0
bsr ReadByte
move.b d0,RPC
bra Fetch
; EXIT: Signal an den Emulator schicken
HandleEXIT jsr _ExitDisplayFrom6510 ;Grafik aufräumen
move.l _SysBase,a6
moveq #0,d0
move.b ContinueSig,d0
JSRLIB FreeSignal
JSRLIB Forbid
move.l MainTask,a1
move.l ReadySet,d0
JSRLIB Signal
move.l InitialSP,a7
moveq #0,d0
rts
; Pause: Signal an den Emulator schicken und dann selbst auf
; ein Signal warten
HandlePause clr.b IntIsRESET
clr.b RESETIsPause
move.b RA,_RA ;Register für SAM bereitstellen
move.b RX,_RX
move.b RY,_RY
moveq #0,d0
btst #3,RCCR+1 ;N dazunehmen
beq 1$
or.b #$80,d0
1$ tst.b ROVERFLOW ;V dazunehmen
beq 2$
or.b #$40,d0
2$ tst.b RDECIMAL ;D dazunehmen
beq 3$
or.b #$08,d0
3$ tst.b RINTERRUPT ;I dazunehmen
beq 4$
or.b #$04,d0
4$ btst #2,RCCR+1 ;Z dazunehmen
beq 5$
or.b #$02,d0
5$ tst.b RCARRY ;C dazunehmen
beq 6$
or.b #$01,d0
6$ move.b d0,_RP
move.b RDDR,_RDDR
move.b RPR,d0
and.b #$3f,d0
move.b d0,_RPR
move.b RDDR,d0
not.b d0
or.b RPR,d0
and.b #$07,d0
move.b d0,_SAMMemConfig
move.w RPC,_RPC
move.w RS,_RS
move.l a6,-(sp)
move.l _SysBase,a6
move.l MainTask,a1
move.l ReadySet,d0
JSRLIB Signal
move.l ContinueSet,d0
JSRLIB Wait
move.l (sp)+,a6
move.b _RA,RA ;Register von SAM lesen
move.b _RX,RX
move.b _RY,RY
clr.b RCCR+1
move.b _RP,d0 ;N holen
bpl 7$
or.b #$08,RCCR+1
7$ add.b d0,d0 ;V holen
smi ROVERFLOW
lsl.b #3,d0 ;D holen
smi RDECIMAL
add.b d0,d0 ;I holen
smi RINTERRUPT
add.b d0,d0 ;Z holen
bpl 8$
or.b #$04,RCCR+1
8$ add.b d0,d0 ;C holen
smi RCARRY
move.b _RDDR,RDDR
move.b _RPR,RPR
move.w _RPC,RPC
move.w _RS,RS
move.b #$01,RS
NewConfig
bra Fetch
**
** Opcodes
**
*
* Load-Gruppe
*
LoadA MACRO
move.b d0,RA
move ccr,RCCR
Last
ENDM
LDAImm_2 ReadByteImm
LoadA
LDAZero_2 ReadByteZero LDAZero
LoadA
LDAZeroX_2 ReadByteZeroX LDAZeroX
LoadA
LDAAbs_2 ReadByteAbs LDAAbs
LoadA
LDAAbsX_2 ReadByteAbsX LDAAbsX
LoadA
LDAAbsY_2 ReadByteAbsY LDAAbsY
LoadA
LDAIndX_2 ReadByteIndX LDAIndX
LoadA
LDAIndY_2 ReadByteIndY LDAIndY
LoadA
LoadX MACRO
move.b d0,RX
move ccr,RCCR
Last
ENDM
LDXImm_2 ReadByteImm
LoadX
LDXZero_2 ReadByteZero LDXZero
LoadX
LDXZeroY_2 ReadByteZeroY LDXZeroY
LoadX
LDXAbs_2 ReadByteAbs LDXAbs
LoadX
LDXAbsY_2 ReadByteAbsY LDXAbsY
LoadX
LoadY MACRO
move.b d0,RY
move ccr,RCCR
Last
ENDM
LDYImm_2 ReadByteImm
LoadY
LDYZero_2 ReadByteZero LDYZero
LoadY
LDYZeroX_2 ReadByteZeroX LDYZeroX
LoadY
LDYAbs_2 ReadByteAbs LDYAbs
LoadY
LDYAbsX_2 ReadByteAbsX LDYAbsX
LoadY
LoadAX MACRO
move.b d0,RA
move.b d0,RX
move ccr,RCCR
Last
ENDM
LAXZero_2 ReadByteZero LAXZero
LoadAX
LAXZeroY_2 ReadByteZeroY LAXZeroY
LoadAX
LAXAbs_2 ReadByteAbs LAXAbs
LoadAX
LAXAbsY_2 ReadByteAbsY LAXAbsY
LoadAX
*
* Store-Gruppe
*
StoreA MACRO
WriteADR RA
Last
ENDM
STAZero_2 ReadAdrZero STAZero
StoreA
STAZeroX_2 ReadAdrZeroX STAZeroX
StoreA
STAAbs_2 ReadAdrAbs STAAbs
StoreA
STAAbsX_2 ReadAdrAbsX STAAbsX
StoreA
STAAbsY_2 ReadAdrAbsY STAAbsY
StoreA
STAIndX_2 ReadAdrIndX STAIndX
StoreA
STAIndY_2 ReadAdrIndY STAIndY
StoreA
STXZero_2 ReadAdrZero STXZero
WriteADR RX
Last
STXZeroY_2 ReadAdrZeroY STXZeroY
WriteADR RX
Last
STXAbs_2 ReadAdrAbs STXAbs
WriteADR RX
Last
STYZero_2 ReadAdrZero STYZero
WriteADR RY
Last
STYZeroX_2 ReadAdrZeroX STYZeroX
WriteADR RY
Last
STYAbs_2 ReadAdrAbs STYAbs
WriteADR RY
Last
StoreAX MACRO
move.b RA,d1
move.w RADR,d0
and.b RX,d1
bsr WriteByte
Last
ENDM
SAXZero_2 ReadAdrZero SAXZero
StoreAX
SAXZeroY_2 ReadAdrZeroY SAXZeroY
StoreAX
SAXAbs_2 ReadAdrAbs SAXAbs
StoreAX
SAXIndX_2 ReadAdrIndX SAXIndX
StoreAX
*
* Transfer-Gruppe
*
TAX_2 ReadPC
move.b RA,RX
move ccr,RCCR
Last
TAY_2 ReadPC
move.b RA,RY
move ccr,RCCR
Last
TXA_2 ReadPC
move.b RX,RA
move ccr,RCCR
Last
TYA_2 ReadPC
move.b RY,RA
move ccr,RCCR
Last
TXS_2 ReadPC
move.b RX,RS+1
Last
TSX_2 ReadPC
move.b RS+1,RX
move ccr,RCCR
Last
*
* Stack-Gruppe
*
PHA_2 ReadPC
Next PHA_3
PHA_3 WriteStack RA
DecS
Last
PLA_2 ReadPC
Next PLA_3
PLA_3 ReadStack
IncS
Next PLA_4
PLA_4 ReadStack
move.b d0,RA
move ccr,RCCR
Last
PHP_2 ReadPC
Next PHP_3
PHP_3 PushP 1 ;B immer 1
Last
PLP_2 ReadPC
Next PLP_3
PLP_3 ReadStack
IncS
Next PLP_4
PLP_4 PopP
Last
*
* Vergleichs-Gruppe
*
CompareA MACRO
move.b RA,d1
cmp.b d0,d1
move ccr,RCCR
scc RCARRY ;Inverses Carry holen
Last
ENDM
CMPImm_2 ReadByteImm
CompareA
CMPZero_2 ReadByteZero CMPZero
CompareA
CMPZeroX_2 ReadByteZeroX CMPZeroX
CompareA
CMPAbs_2 ReadByteAbs CMPAbs
CompareA
CMPAbsX_2 ReadByteAbsX CMPAbsX
CompareA
CMPAbsY_2 ReadByteAbsY CMPAbsY
CompareA
CMPIndX_2 ReadByteIndX CMPIndX
CompareA
CMPIndY_2 ReadByteIndY CMPIndY
CompareA
CompareX MACRO
move.b RX,d1
cmp.b d0,d1
move ccr,RCCR
scc RCARRY ;Inverses Carry holen
Last
ENDM
CPXImm_2 ReadByteImm
CompareX
CPXZero_2 ReadByteZero CPXZero
CompareX
CPXAbs_2 ReadByteAbs CPXAbs
CompareX
CompareY MACRO
move.b RY,d1
cmp.b d0,d1
move ccr,RCCR
scc RCARRY ;Inverses Carry holen
Last
ENDM
CPYImm_2 ReadByteImm
CompareY
CPYZero_2 ReadByteZero CPYZero
CompareY
CPYAbs_2 ReadByteAbs CPYAbs
CompareY
*
* Logik-Gruppe
*
AndA MACRO
and.b d0,RA
move ccr,RCCR
Last
ENDM
ANDImm_2 ReadByteImm
AndA
ANDZero_2 ReadByteZero ANDZero
AndA
ANDZeroX_2 ReadByteZeroX ANDZeroX
AndA
ANDAbs_2 ReadByteAbs ANDAbs
AndA
ANDAbsX_2 ReadByteAbsX ANDAbsX
AndA
ANDAbsY_2 ReadByteAbsY ANDAbsY
AndA
ANDIndX_2 ReadByteIndX ANDIndX
AndA
ANDIndY_2 ReadByteIndY ANDIndY
AndA
OrA MACRO
or.b d0,RA
move ccr,RCCR
Last
ENDM
ORAImm_2 ReadByteImm
OrA
ORAZero_2 ReadByteZero ORAZero
OrA
ORAZeroX_2 ReadByteZeroX ORAZeroX
OrA
ORAAbs_2 ReadByteAbs ORAAbs
OrA
ORAAbsX_2 ReadByteAbsX ORAAbsX
OrA
ORAAbsY_2 ReadByteAbsY ORAAbsY
OrA
ORAIndX_2 ReadByteIndX ORAIndX
OrA
ORAIndY_2 ReadByteIndY ORAIndY
OrA
EorA MACRO
eor.b d0,RA
move ccr,RCCR
Last
ENDM
EORImm_2 ReadByteImm
EorA
EORZero_2 ReadByteZero EORZero
EorA
EORZeroX_2 ReadByteZeroX EORZeroX
EorA
EORAbs_2 ReadByteAbs EORAbs
EorA
EORAbsX_2 ReadByteAbsX EORAbsX
EorA
EORAbsY_2 ReadByteAbsY EORAbsY
EorA
EORIndX_2 ReadByteIndX EORIndX
EorA
EORIndY_2 ReadByteIndY EORIndY
EorA
BitTest MACRO
tst.b d0 ;N holen
move ccr,RCCR
btst #6,d0 ;Bit 6 -> V
sne ROVERFLOW
and.b RA,d0 ;A AND M -> Z
beq BitZ\@
and.b #$fb,RCCR+1
Last
BitZ\@ or.b #$04,RCCR+1
Last
ENDM
BITZero_2 ReadByteZero BITZero
BitTest
BITAbs_2 ReadByteAbs BITAbs
BitTest
*
* Arithmetik-Gruppe
*
AdcA MACRO
move.b RCARRY,d1
tst.b RDECIMAL
bne \@1$
add.b d1,d1 ;Carry -> X
move.b RA,d1
addx.b d0,d1
scs RCARRY ;Carry holen
svs ROVERFLOW ;Overflow holen
move.b d1,RA
move ccr,RCCR ;N und Z holen
Last
\@1$ bsr AdcDec
Last
ENDM
AdcDec move.b d0,TMPS ;Dezimalmodus
move.b RA,d2
move.b d2,TMPA
clr.w RCCR
clr.b ROVERFLOW
move.b d2,d3 ;Unteres Nybble berechnen
and.b #$0f,d0
and.b #$0f,d3
add.b d1,d1 ;Carry -> X
addx.b d0,d3 ; -> d3
cmp.b #10,d3 ;BCD-Fixup für das untere Nybble
blo 2$
addq.b #6,d3
2$
move.b TMPS,d0 ;Oberes Nybble berechnen
lsr.b #4,d0
lsr.b #4,d2
add.b d0,d2
cmp.b #$10,d3
blo 1$
addq.b #1,d2 ; -> d2
1$
move.b TMPS,d0 ;Z holen (wie im Binärmodus)
move.b TMPA,d4
add.b d1,d1 ;Carry -> X
addx.b d0,d4
tst.b d4 ;Wegen addx
bne 6$
or.w #$04,RCCR
6$
btst #3,d2 ;N berechnen
beq 4$
or.w #$08,RCCR
4$
move.b d2,d0 ;V berechnen
lsl.b #4,d0
move.b TMPA,d1
eor.b d1,d0
bpl 5$
move.b TMPS,d0
eor.b d1,d0
spl ROVERFLOW
5$
cmp.b #10,d2 ;BCD-Fixup für das obere Nybble
blo 3$
addq.b #6,d2
3$
cmp.b #$10,d2 ;Carry holen
shs RCARRY
and.b #$0f,d3 ;Ergebnis zusammensetzen
lsl.b #4,d2
or.b d3,d2
move.b d2,RA
rts
ADCImm_2 ReadByteImm
AdcA
ADCZero_2 ReadByteZero ADCZero
AdcA
ADCZeroX_2 ReadByteZeroX ADCZeroX
AdcA
ADCAbs_2 ReadByteAbs ADCAbs
AdcA
ADCAbsX_2 ReadByteAbsX ADCAbsX
AdcA
ADCAbsY_2 ReadByteAbsY ADCAbsY
AdcA
ADCIndX_2 ReadByteIndX ADCIndX
AdcA
ADCIndY_2 ReadByteIndY ADCIndY
AdcA
SbcA MACRO
move.b RCARRY,d1
not.b d1
tst.b RDECIMAL
bne \@1$
add.b d1,d1 ;Inverses Carry -> X
move.b RA,d1
subx.b d0,d1
scc RCARRY ;Inverses Carry holen
svs ROVERFLOW ;Overflow holen
move.b d1,RA
move ccr,RCCR
Last
\@1$ bsr SbcDec
Last
ENDM
SbcDec move.b d0,TMPS ;Dezimalmodus
move.b RA,d2
move.b d2,TMPA
and.b #$0f,d0 ;Unteres Nybble berechnen
and.b #$0f,d2
add.b d1,d1 ;Inverses Carry -> X
subx.b d0,d2
move ccr,d4
bcc 1$ ;BCD-Fixup
subq.b #6,d2
st d4
1$ and.b #$0f,d2
move.b d2,d3 ;-> d3
move.b TMPS,d0 ;Oberes Nybble berechnen
move.b TMPA,d2
and.b #$f0,d0
and.b #$f0,d2
sub.b d0,d2
bcc 2$ ;BCD-Fixup
and.b #$f0,d2
sub.b #$60,d2
btst #0,d4
beq 4$
sub.b #$10,d2
bra 4$
2$ and.b #$f0,d2
btst #0,d4
beq 4$
sub.b #$10,d2
bcc 4$
sub.b #$60,d2
4$ or.b d3,d2 ;Ergebnis zusammenbauen
move.b d2,RA
add.b d1,d1 ;Inverses Carry -> X
move.b TMPS,d0 ;Flags berechnen (wie im Binärmodus)
move.b TMPA,d1
subx.b d0,d1 ;Flags berechnen
scc RCARRY ;Inverses Carry holen
svs ROVERFLOW ;Overflow holen
tst.b d1
move ccr,RCCR ;N und Z holen
rts
SBCImm_2 ReadByteImm
SbcA
SBCZero_2 ReadByteZero SBCZero
SbcA
SBCZeroX_2 ReadByteZeroX SBCZeroX
SbcA
SBCAbs_2 ReadByteAbs SBCAbs
SbcA
SBCAbsX_2 ReadByteAbsX SBCAbsX
SbcA
SBCAbsY_2 ReadByteAbsY SBCAbsY
SbcA
SBCIndX_2 ReadByteIndX SBCIndX
SbcA
SBCIndY_2 ReadByteIndY SBCIndY
SbcA
*
* Inkrement/Dekrement-Gruppe
*
Increment MACRO
move.b RDBUF,d1
move.w RADR,d0
addq.b #1,d1
move ccr,RCCR
bsr WriteByte
Last
ENDM
INCZero_2 ReadRMWZero INCZero
Increment
INCZeroX_2 ReadRMWZeroX INCZeroX
Increment
INCAbs_2 ReadRMWAbs INCAbs
Increment
INCAbsX_2 ReadRMWAbsX INCAbsX
Increment
Decrement MACRO
move.b RDBUF,d1
move.w RADR,d0
subq.b #1,d1
move ccr,RCCR
bsr WriteByte
Last
ENDM
DECZero_2 ReadRMWZero DECZero
Decrement
DECZeroX_2 ReadRMWZeroX DECZeroX
Decrement
DECAbs_2 ReadRMWAbs DECAbs
Decrement
DECAbsX_2 ReadRMWAbsX DECAbsX
Decrement
INX_2 ReadPC
addq.b #1,RX
move ccr,RCCR
Last
INY_2 ReadPC
addq.b #1,RY
move ccr,RCCR
Last
DEX_2 ReadPC
subq.b #1,RX
move ccr,RCCR
Last
DEY_2 ReadPC
subq.b #1,RY
move ccr,RCCR
Last
*
* Schiebe-/Rotations-Gruppe
*
ShiftLeft MACRO
move.b RDBUF,d1
move.w RADR,d0
add.b d1,d1
move ccr,RCCR
scs RCARRY ;Carry holen
bsr WriteByte
Last
ENDM
ASLA_2 ReadPC
move.b RA,d0
add.b d0,d0
move ccr,RCCR
scs RCARRY ;Carry holen
move.b d0,RA
Last
ASLZero_2 ReadRMWZero ASLZero
ShiftLeft
ASLZeroX_2 ReadRMWZeroX ASLZeroX
ShiftLeft
ASLAbs_2 ReadRMWAbs ASLAbs
ShiftLeft
ASLAbsX_2 ReadRMWAbsX ASLAbsX
ShiftLeft
ShiftRight MACRO
move.b RDBUF,d1
move.w RADR,d0
lsr.b #1,d1
move ccr,RCCR
scs RCARRY ;Carry holen
bsr WriteByte
Last
ENDM
LSRA_2 ReadPC
move.b RA,d0
lsr.b #1,d0
move ccr,RCCR
scs RCARRY ;Carry holen
move.b d0,RA
Last
LSRZero_2 ReadRMWZero LSRZero
ShiftRight
LSRZeroX_2 ReadRMWZeroX LSRZeroX
ShiftRight
LSRAbs_2 ReadRMWAbs LSRAbs
ShiftRight
LSRAbsX_2 ReadRMWAbsX LSRAbsX
ShiftRight
RotateLeft MACRO
move.b RCARRY,d2
move.b RDBUF,d1
move.w RADR,d0
add.b d2,d2 ;Carry -> X
roxl.b #1,d1 ;Vorsicht bei addx und dem Z-Flag!
move ccr,RCCR
scs RCARRY ;Carry holen
bsr WriteByte
Last
ENDM
ROLA_2 ReadPC
move.b RCARRY,d2
move.b RA,d1
add.b d2,d2 ;Carry -> X
roxl.b #1,d1 ;Vorsicht bei addx und dem Z-Flag!
move ccr,RCCR
scs RCARRY ;Carry holen
move.b d1,RA
Last
ROLZero_2 ReadRMWZero ROLZero
RotateLeft
ROLZeroX_2 ReadRMWZeroX ROLZeroX
RotateLeft
ROLAbs_2 ReadRMWAbs ROLAbs
RotateLeft
ROLAbsX_2 ReadRMWAbsX ROLAbsX
RotateLeft
RotateRight MACRO
move.b RCARRY,d2
move.b RDBUF,d1
move.w RADR,d0
add.b d2,d2 ;Carry -> X
roxr.b #1,d1
move ccr,RCCR
scs RCARRY ;Carry holen
bsr WriteByte
Last
ENDM
RORA_2 ReadPC
move.b RCARRY,d2
move.b RA,d1
add.b d2,d2 ;Carry -> X
roxr.b #1,d1
move ccr,RCCR
scs RCARRY ;Carry holen
move.b d1,RA
Last
RORZero_2 ReadRMWZero RORZero
RotateRight
RORZeroX_2 ReadRMWZeroX RORZeroX
RotateRight
RORAbs_2 ReadRMWAbs RORAbs
RotateRight
RORAbsX_2 ReadRMWAbsX RORAbsX
RotateRight
*
* Sprungbefehle
*
JMPAbs_2 ReadPCInc RADRL
Next JMPAbs_3
JMPAbs_3 ReadPC RPC
lsl.w #8,RPC
move.b RADRL,RPC
Last
JMPInd_2 ReadByteAbs JMPInd,RPC
addq.b #1,RADRL ;Keine Seitenüberschreitung
lsl.w #8,RPC
Next JMPInd_5
JMPInd_5 ReadADR RPC
ror.w #8,RPC
Last
JSR_2 ReadPCInc RADRL
Next JSR_3
JSR_3 ReadStack
Next JSR_4
JSR_4 move.w RPC,d1
lsr.w #8,d1
WriteStack
DecS
Next JSR_5
JSR_5 move.b RPC,d1
WriteStack
DecS
Next JSR_6
JSR_6 ReadPC RPC
lsl.w #8,RPC
move.b RADRL,RPC
Last
RTS_2 ReadPC
Next RTS_3
RTS_3 ReadStack
IncS
Next RTS_4
RTS_4 ReadStack RADRL
IncS
Next RTS_5
RTS_5 ReadStack RPC
lsl.w #8,RPC
move.b RADRL,RPC
Next RTS_6
RTS_6 ReadPCInc
Last
BRK_2 ReadPC
Next BRK_3
BRK_3 move.w RPC,d1
lsr.w #8,d1
WriteStack
DecS
Next BRK_4
BRK_4 move.b RPC,d1
WriteStack
DecS
Next BRK_5
BRK_5 PushP 1 ;B auf 1
Next BRK_6
BRK_6 st RINTERRUPT
move.w #$fffe,d0 ;IRQ-Vektor
bsr ReadByte
move.b d0,RPC
lsl.w #8,RPC
Next BRK_7
BRK_7 move.w #$ffff,d0
bsr ReadByte
move.b d0,RPC
ror.w #8,RPC
Last
RTI_2 ReadPC
Next RTI_3
RTI_3 ReadStack
IncS
Next RTI_4
RTI_4 PopP
IncS
Next RTI_5
RTI_5 ReadStack RADRL
IncS
Next RTI_6
RTI_6 ReadStack RPC
lsl.w #8,RPC
move.b RADRL,RPC
Last
*
* Verzweigungsbefehle
*
BranchB MACRO ;Name des Opcodes, zu testendes Bit, 0/1
;Also: Verzweige, wenn Bit \2 in RCCR gleich \4 ist
ReadByteImm RADRL
btst #\2,RCCR+1 ;Verzweigung genommen?
IFEQ \3
beq \1Yes
ELSE
bne \1Yes
ENDC
Last ;Nein, nächster Opcode
\1Yes Next \1_3
\1_3 ReadPC
move.b RADRL,d0 ;Ja, PC erhöhen
bpl \1Forward
neg.b d0 ;Sprung zurück, Seitenüberschreitung?
sub.b d0,RPC
bcs \1BPage
Last ;Nein, nächster Opcode
\1BPage Next \1_4b
\1_4b ReadPC ;Ja, PC korrigieren
sub.w #$100,RPC
Last
\1Forward add.b d0,RPC ;Sprung nach vorne, Seitenüberschreitung?
bcs \1FPage
Last ;Nein, nächster Opcode
\1FPage Next \1_4f
\1_4f ReadPC
add.w #$100,RPC ;Ja, PC korrigieren
Last
ENDM
BranchF MACRO ;Name des Opcodes, Flag, 0/1
;Also: Verzweige, wenn \2 gleich \3 ist
ReadByteImm RADRL
tst.b \2 ;Verzweigung genommen?
IFEQ \3
beq \1Yes
ELSE
bne \1Yes
ENDC
Last ;Nein, nächster Opcode
\1Yes Next \1_3
\1_3 ReadPC
move.b RADRL,d0 ;Ja, PC erhöhen
bpl \1Forward
neg.b d0 ;Sprung zurück, Seitenüberschreitung?
sub.b d0,RPC
bcs \1BPage
Last ;Nein, nächster Opcode
\1BPage Next \1_4b
\1_4b ReadPC ;Ja, PC korrigieren
sub.w #$100,RPC
Last
\1Forward add.b d0,RPC ;Sprung nach vorne, Seitenüberschreitung?
bcs \1FPage
Last ;Nein, nächster Opcode
\1FPage Next \1_4f
\1_4f ReadPC
add.w #$100,RPC ;Ja, PC korrigieren
Last
ENDM
BVC_2 BranchF BVC,ROVERFLOW,0
BVS_2 BranchF BVS,ROVERFLOW,1
BEQ_2 BranchB BEQ,2,1
BNE_2 BranchB BNE,2,0
BPL_2 BranchB BPL,3,0
BMI_2 BranchB BMI,3,1
BCC_2 BranchF BCC,RCARRY,0
BCS_2 BranchF BCS,RCARRY,1
*
* Flag-Gruppe
*
CLI_2 ReadPC
clr.b RINTERRUPT
Last
SEI_2 ReadPC
st RINTERRUPT
Last
CLC_2 ReadPC
clr.b RCARRY
Last
SEC_2 ReadPC
st RCARRY
Last
CLD_2 ReadPC
clr.b RDECIMAL
Last
SED_2 ReadPC
st RDECIMAL
Last
CLV_2 ReadPC
clr.b ROVERFLOW
Last
*
* NOPs
*
NOPImpl_2 ReadPC
Last
NOPImm_2 ReadByteImm
Last
NOPZero_2 ReadByteZero NOPZero
Last
NOPZeroX_2 ReadByteZeroX NOPZeroX
Last
NOPAbs_2 ReadByteAbs NOPAbs
Last
NOPAbsX_2 ReadByteAbsX NOPAbsX
Last
*
* ASL/ORA-Gruppe (SLO)
*
ShiftLeftOr MACRO
move.b RDBUF,d1
move.w RADR,d0
add.b d1,d1
scs RCARRY ;Carry holen
or.b d1,RA
move ccr,RCCR
bsr WriteByte
Last
ENDM
SLOZero_2 ReadRMWZero SLOZero
ShiftLeftOr
SLOZeroX_2 ReadRMWZeroX SLOZeroX
ShiftLeftOr
SLOAbs_2 ReadRMWAbs SLOAbs
ShiftLeftOr
SLOAbsX_2 ReadRMWAbsX SLOAbsX
ShiftLeftOr
SLOAbsY_2 ReadRMWAbsY SLOAbsY
ShiftLeftOr
SLOIndX_2 ReadRMWIndX SLOIndX
ShiftLeftOr
SLOIndY_2 ReadRMWIndY SLOIndY
ShiftLeftOr
*
* ROL/AND-Gruppe (RLA)
*
RotateLeftAnd MACRO
move.b RCARRY,d2
move.b RDBUF,d1
move.w RADR,d0
add.b d2,d2 ;Carry -> X
roxl.b #1,d1
scs RCARRY ;Carry holen
and.b d1,RA
move ccr,RCCR
bsr WriteByte
Last
ENDM
RLAZero_2 ReadRMWZero RLAZero
RotateLeftAnd
RLAZeroX_2 ReadRMWZeroX RLAZeroX
RotateLeftAnd
RLAAbs_2 ReadRMWAbs RLAAbs
RotateLeftAnd
RLAAbsX_2 ReadRMWAbsX RLAAbsX
RotateLeftAnd
RLAAbsY_2 ReadRMWAbsY RLAAbsY
RotateLeftAnd
RLAIndX_2 ReadRMWIndX RLAIndX
RotateLeftAnd
RLAIndY_2 ReadRMWIndY RLAIndY
RotateLeftAnd
*
* LSR/EOR-Gruppe (SRE)
*
ShiftRightEor MACRO
move.b RDBUF,d1
move.w RADR,d0
lsr.b #1,d1
scs RCARRY ;Carry holen
eor.b d1,RA
move ccr,RCCR
bsr WriteByte
Last
ENDM
SREZero_2 ReadRMWZero SREZero
ShiftRightEor
SREZeroX_2 ReadRMWZeroX SREZeroX
ShiftRightEor
SREAbs_2 ReadRMWAbs SREAbs
ShiftRightEor
SREAbsX_2 ReadRMWAbsX SREAbsX
ShiftRightEor
SREAbsY_2 ReadRMWAbsY SREAbsY
ShiftRightEor
SREIndX_2 ReadRMWIndX SREIndX
ShiftRightEor
SREIndY_2 ReadRMWIndY SREIndY
ShiftRightEor
*
* ROR/ADC-Gruppe (RRA)
*
RotateRightAdc MACRO
move.b RCARRY,d2
move.b RDBUF,d1
move.w RADR,d0
add.b d2,d2 ;Carry -> X
roxr.b #1,d1
scs RCARRY ;Carry holen
move.b RA,d2
addx.b d1,d2
svs ROVERFLOW ;Overflow holen
move.b d2,RA
move ccr,RCCR
bsr WriteByte
Last
ENDM
RRAZero_2 ReadRMWZero RRAZero
RotateRightAdc
RRAZeroX_2 ReadRMWZeroX RRAZeroX
RotateRightAdc
RRAAbs_2 ReadRMWAbs RRAAbs
RotateRightAdc
RRAAbsX_2 ReadRMWAbsX RRAAbsX
RotateRightAdc
RRAAbsY_2 ReadRMWAbsY RRAAbsY
RotateRightAdc
RRAIndX_2 ReadRMWIndX RRAIndX
RotateRightAdc
RRAIndY_2 ReadRMWIndY RRAIndY
RotateRightAdc
*
* DEC/CMP-Gruppe (DCP)
*
DecCompare MACRO
move.b RA,d2
move.b RDBUF,d1
move.w RADR,d0
subq.b #1,d1
cmp.b d1,d2
move ccr,RCCR
scc RCARRY ;Inverses Carry holen
bsr WriteByte
Last
ENDM
DCPZero_2 ReadRMWZero DCPZero
DecCompare
DCPZeroX_2 ReadRMWZeroX DCPZeroX
DecCompare
DCPAbs_2 ReadRMWAbs DCPAbs
DecCompare
DCPAbsX_2 ReadRMWAbsX DCPAbsX
DecCompare
DCPAbsY_2 ReadRMWAbsY DCPAbsY
DecCompare
DCPIndX_2 ReadRMWIndX DCPIndX
DecCompare
DCPIndY_2 ReadRMWIndY DCPIndY
DecCompare
*
* INC/SBC-Gruppe (ISB)
*
IncSbc MACRO
move.b RCARRY,d2
move.b RDBUF,d1
not.b d2
move.w RADR,d0
addq.b #1,d1
add.b d2,d2 ;Inverses Carry -> X
move.b RA,d2
subx.b d1,d2
scc RCARRY ;Inverses Carry holen
svs ROVERFLOW ;Overflow holen
move.b d2,RA
move ccr,RCCR
bsr WriteByte
Last
ENDM
ISBZero_2 ReadRMWZero ISBZero
IncSbc
ISBZeroX_2 ReadRMWZeroX ISBZeroX
IncSbc
ISBAbs_2 ReadRMWAbs ISBAbs
IncSbc
ISBAbsX_2 ReadRMWAbsX ISBAbsX
IncSbc
ISBAbsY_2 ReadRMWAbsY ISBAbsY
IncSbc
ISBIndX_2 ReadRMWIndX ISBIndX
IncSbc
ISBIndY_2 ReadRMWIndY ISBIndY
IncSbc
*
* Unübliche Befehle
*
ANCImm_2 ReadByteImm ;??? ($0b, $2b)
and.b d0,RA
move ccr,RCCR
smi RCARRY ;N -> C (??)
Last
SBXImm_2 ReadByteImm
move.b RX,d1
and.b RA,d1
sub.b d0,d1
move ccr,RCCR
scc RCARRY ;Inverses Carry holen
move.b d1,RX
Last
*
* Erweiterte Opcodes
*
; $f2 $xx
OpIEC ReadPCInc
tst.b d0
beq OpIECOut
cmp.b #1,d0
beq OpIECOutATN
cmp.b #2,d0
beq OpIECOutSec
cmp.b #3,d0
beq OpIECIn
cmp.b #4,d0
beq OpIECSetATN
cmp.b #5,d0
beq OpIECRelATN
cmp.b #6,d0
beq OpIECTurnaround
cmp.b #7,d0
beq OpIECRelease
bra IllegalOp
OpIECOut move.b $95(RAMPTR),d0 ;Auszugebendes Byte holen
move.b $a3(RAMPTR),d1 ;EOI-Flag holen
jsr IECOut
bra IECSetST
OpIECOutATN move.b $95(RAMPTR),d0 ;Auszugebendes Byte holen
jsr IECOutATN
bra IECSetST
OpIECOutSec move.b $95(RAMPTR),d0 ;Auszugebendes Byte holen
jsr IECOutSec
bra IECSetST
OpIECIn jsr IECIn
move.b d1,RA ;Byte in den Akku
move ccr,RCCR ;Flags entsprechend setzen
bra IECSetST
OpIECSetATN jsr IECSetATN
move.w #$edfb,RPC ;Nach $edfb springen
Last
OpIECRelATN jsr IECRelATN
bra IECReturn
OpIECTurnaround jsr IECTurnaround
bra IECReturn
OpIECRelease jsr IECRelease
bra IECReturn
IECSetST or.b d0,$90(RAMPTR) ;Status setzen
clr.b RCARRY ;Carry löschen
IECReturn bra RTS_2 ;RTS ausführen
**
** Konstanten
**
*
* Opcode Dispatch Table
* Jeder Eintrag zeigt auf die erste Zyklusroutine (d.h. die Routine
* des zweiten Zyklus) eines Opcodes
* "*" bezeichnet einen undokumentierten Opcode
*
CNOP 0,4
OpcodeTable dc.l BRK_2 ;$00
dc.l ORAIndX_2
dc.l IllegalOp
dc.l SLOIndX_2 ;*
dc.l NOPZero_2 ;*
dc.l ORAZero_2
dc.l ASLZero_2
dc.l SLOZero_2 ;*
dc.l PHP_2 ;$08
dc.l ORAImm_2
dc.l ASLA_2
dc.l ANCImm_2 ;*
dc.l NOPAbs_2 ;*
dc.l ORAAbs_2
dc.l ASLAbs_2
dc.l SLOAbs_2 ;*
dc.l BPL_2 ;$10
dc.l ORAIndY_2
dc.l IllegalOp
dc.l SLOIndY_2 ;*
dc.l NOPZeroX_2 ;*
dc.l ORAZeroX_2
dc.l ASLZeroX_2
dc.l SLOZeroX_2 ;*
dc.l CLC_2 ;$18
dc.l ORAAbsY_2
dc.l NOPImpl_2 ;*
dc.l SLOAbsY_2 ;*
dc.l NOPAbsX_2 ;*
dc.l ORAAbsX_2
dc.l ASLAbsX_2
dc.l SLOAbsX_2 ;*
dc.l JSR_2 ;$20
dc.l ANDIndX_2
dc.l IllegalOp
dc.l RLAIndX_2 ;*
dc.l BITZero_2
dc.l ANDZero_2
dc.l ROLZero_2
dc.l RLAZero_2 ;*
dc.l PLP_2 ;$28
dc.l ANDImm_2
dc.l ROLA_2
dc.l ANCImm_2 ;*
dc.l BITAbs_2
dc.l ANDAbs_2
dc.l ROLAbs_2
dc.l RLAAbs_2 ;*
dc.l BMI_2 ;$30
dc.l ANDIndY_2
dc.l IllegalOp
dc.l RLAIndY_2 ;*
dc.l NOPZeroX_2 ;*
dc.l ANDZeroX_2
dc.l ROLZeroX_2
dc.l RLAZeroX_2 ;*
dc.l SEC_2 ;$38
dc.l ANDAbsY_2
dc.l NOPImpl_2 ;*
dc.l RLAAbsY_2 ;*
dc.l NOPAbsX_2 ;*
dc.l ANDAbsX_2
dc.l ROLAbsX_2
dc.l RLAAbsX_2 ;*
dc.l RTI_2 ;$40
dc.l EORIndX_2
dc.l IllegalOp
dc.l SREIndX_2 ;*
dc.l NOPZero_2 ;*
dc.l EORZero_2
dc.l LSRZero_2
dc.l SREZero_2 ;*
dc.l PHA_2 ;$48
dc.l EORImm_2
dc.l LSRA_2
dc.l IllegalOp
dc.l JMPAbs_2
dc.l EORAbs_2
dc.l LSRAbs_2
dc.l SREAbs_2 ;*
dc.l BVC_2 ;$50
dc.l EORIndY_2
dc.l IllegalOp
dc.l SREIndY_2 ;*
dc.l NOPZeroX_2 ;*
dc.l EORZeroX_2
dc.l LSRZeroX_2
dc.l SREZeroX_2 ;*
dc.l CLI_2 ;$58
dc.l EORAbsY_2
dc.l NOPImpl_2 ;*
dc.l SREAbsY_2 ;*
dc.l NOPAbsX_2 ;*
dc.l EORAbsX_2
dc.l LSRAbsX_2
dc.l SREAbsX_2 ;*
dc.l RTS_2 ;$60
dc.l ADCIndX_2
dc.l IllegalOp
dc.l RRAIndX_2 ;*
dc.l NOPZero_2 ;*
dc.l ADCZero_2
dc.l RORZero_2
dc.l RRAZero_2 ;*
dc.l PLA_2 ;$68
dc.l ADCImm_2
dc.l RORA_2
dc.l IllegalOp
dc.l JMPInd_2
dc.l ADCAbs_2
dc.l RORAbs_2
dc.l RRAAbs_2 ;*
dc.l BVS_2 ;$70
dc.l ADCIndY_2
dc.l IllegalOp
dc.l RRAIndY_2 ;*
dc.l NOPZeroX_2 ;*
dc.l ADCZeroX_2
dc.l RORZeroX_2
dc.l RRAZeroX_2 ;*
dc.l SEI_2 ;$78
dc.l ADCAbsY_2
dc.l NOPImpl_2 ;*
dc.l RRAAbsY_2 ;*
dc.l NOPAbsX_2 ;*
dc.l ADCAbsX_2
dc.l RORAbsX_2
dc.l RRAAbsX_2 ;*
dc.l NOPImm_2 ;* $80
dc.l STAIndX_2
dc.l NOPImm_2 ;*
dc.l SAXIndX_2 ;*
dc.l STYZero_2
dc.l STAZero_2
dc.l STXZero_2
dc.l SAXZero_2 ;*
dc.l DEY_2 ;$88
dc.l NOPImm_2 ;*
dc.l TXA_2
dc.l IllegalOp
dc.l STYAbs_2
dc.l STAAbs_2
dc.l STXAbs_2
dc.l SAXAbs_2 ;*
dc.l BCC_2 ;$90
dc.l STAIndY_2
dc.l IllegalOp
dc.l IllegalOp
dc.l STYZeroX_2
dc.l STAZeroX_2
dc.l STXZeroY_2
dc.l SAXZeroY_2 ;*
dc.l TYA_2 ;$98
dc.l STAAbsY_2
dc.l TXS_2
dc.l IllegalOp
dc.l IllegalOp
dc.l STAAbsX_2
dc.l IllegalOp
dc.l IllegalOp
dc.l LDYImm_2 ;$a0
dc.l LDAIndX_2
dc.l LDXImm_2
dc.l IllegalOp
dc.l LDYZero_2
dc.l LDAZero_2
dc.l LDXZero_2
dc.l LAXZero_2 ;*
dc.l TAY_2 ;$a8
dc.l LDAImm_2
dc.l TAX_2
dc.l IllegalOp
dc.l LDYAbs_2
dc.l LDAAbs_2
dc.l LDXAbs_2
dc.l LAXAbs_2 ;*
dc.l BCS_2 ;$b0
dc.l LDAIndY_2
dc.l IllegalOp
dc.l IllegalOp
dc.l LDYZeroX_2
dc.l LDAZeroX_2
dc.l LDXZeroY_2
dc.l LAXZeroY_2 ;*
dc.l CLV_2 ;$b8
dc.l LDAAbsY_2
dc.l TSX_2
dc.l IllegalOp
dc.l LDYAbsX_2
dc.l LDAAbsX_2
dc.l LDXAbsY_2
dc.l LAXAbsY_2 ;*
dc.l CPYImm_2 ;$c0
dc.l CMPIndX_2
dc.l NOPImm_2 ;*
dc.l DCPIndX_2 ;*
dc.l CPYZero_2
dc.l CMPZero_2
dc.l DECZero_2
dc.l DCPZero_2 ;*
dc.l INY_2 ;$c8
dc.l CMPImm_2
dc.l DEX_2
dc.l SBXImm_2 ;*
dc.l CPYAbs_2
dc.l CMPAbs_2
dc.l DECAbs_2
dc.l DCPAbs_2 ;*
dc.l BNE_2 ;$d0
dc.l CMPIndY_2
dc.l IllegalOp
dc.l DCPIndY_2 ;*
dc.l NOPZeroX_2 ;*
dc.l CMPZeroX_2
dc.l DECZeroX_2
dc.l DCPZeroX_2 ;*
dc.l CLD_2 ;$d8
dc.l CMPAbsY_2
dc.l NOPImpl_2 ;*
dc.l DCPAbsY_2 ;*
dc.l NOPAbsX_2 ;*
dc.l CMPAbsX_2
dc.l DECAbsX_2
dc.l DCPAbsX_2 ;*
dc.l CPXImm_2 ;$e0
dc.l SBCIndX_2
dc.l NOPImm_2 ;*
dc.l ISBIndX_2 ;*
dc.l CPXZero_2
dc.l SBCZero_2
dc.l INCZero_2
dc.l ISBZero_2 ;*
dc.l INX_2 ;$e8
dc.l SBCImm_2
dc.l NOPImpl_2
dc.l SBCImm_2 ;*
dc.l CPXAbs_2
dc.l SBCAbs_2
dc.l INCAbs_2
dc.l ISBAbs_2 ;*
dc.l BEQ_2 ;$f0
dc.l SBCIndY_2
dc.l OpIEC ;Patch
dc.l ISBIndY_2 ;*
dc.l NOPZeroX_2 ;*
dc.l SBCZeroX_2
dc.l INCZeroX_2
dc.l ISBZeroX_2 ;*
dc.l SED_2 ;$f8
dc.l SBCAbsY_2
dc.l NOPImpl_2 ;*
dc.l ISBAbsY_2 ;*
dc.l NOPAbsX_2 ;*
dc.l SBCAbsX_2
dc.l INCAbsX_2
dc.l ISBAbsX_2 ;*
*
* Speicherkonfigurationstabelle
*
; Diese Tabelle enthält für alle 8 Speicherkonfigurationen
; die Zeiger auf die zugehörigen Read- und WriteTabs
ConfigTab dc.l ReadTab0,WriteTab0
dc.l ReadTab1,WriteTab1
dc.l ReadTab2,WriteTab2
dc.l ReadTab3,WriteTab3
dc.l ReadTab4,WriteTab4
dc.l ReadTab5,WriteTab5
dc.l ReadTab6,WriteTab6
dc.l ReadTab7,WriteTab7
*
* Sonstige Konstanten
*
; Taglist für CreateNewProc
ProcTags dc.l NP_Entry,CPUTaskProc
dc.l NP_Name,CPUTaskName
dc.l NP_Priority,-1
dc.l 0
; Strings
CPUTaskName dc.b "6510",0
; Flag: Dies ist Frodo SC
CNOP 0,4
_IsFrodoSC
IsFrodoSC dc.w 1
**
** Initialisierte Daten
**
SECTION "DATA",DATA
; Requester
IllegalOpReq dc.l 20,0,0,0,0
**
** Nicht initialisierte Daten
**
SECTION "BSS",BSS
; Sprungtabellen für Speicherzugriff: Ein Eintrag pro Seite
; Eine Tabelle für jede der 8 Speicherkonfigurationen
ReadTab0 ds.l 256
ReadTab1 ds.l 256
ReadTab2 ds.l 256
ReadTab3 ds.l 256
ReadTab4 ds.l 256
ReadTab5 ds.l 256
ReadTab6 ds.l 256
ReadTab7 ds.l 256
WriteTab0 ds.l 256
WriteTab1 ds.l 256
WriteTab2 ds.l 256
WriteTab3 ds.l 256
WriteTab4 ds.l 256
WriteTab5 ds.l 256
WriteTab6 ds.l 256
WriteTab7 ds.l 256
SECTION "__MERGED",BSS
; 6510-Task
CPUProc ds.l 1 ;Prozess-Handle
XDEF _CPUTask
_CPUTask
CPUTask ds.l 1 ;Task des Prozesses
InitialSP ds.l 1 ;Stackpointer
ReadySet ds.l 1 ;Signal des Hauptprogramms
ContinueSet ds.l 1 ;Signal des CPU-Tasks
ReadySig ds.b 1
ContinueSig ds.b 1
; 6510-Register
RA ds.b 1 ;A
RX ds.b 1 ;X
RY ds.b 1 ;Y
RDBUF ds.b 1 ;Puffer für RMW-Befehle
RS ds.w 1 ;S (16-Bit, $01xx)
RCCR ds.w 1 ;CCR, nur N und Z
RCARRY ds.b 1 ;6510-Carry
ROVERFLOW ds.b 1 ;6510-Overflow-Flag
RDECIMAL ds.b 1 ;6510-Dezimalflag
RINTERRUPT ds.b 1 ;6510-Interruptflag
RADR
RADRH ds.b 1 ;Adreß-Latch
RADRL ds.b 1
RADR2
RADR2H ds.b 1 ;Zweites Adreß-Latch für indiziert-indirekt
RADR2L ds.b 1
RPR ds.b 1 ;Prozessorport Datenregister
RDDR ds.b 1 ;Prozessorport Datenrichtungsregister
; Zwischenspeicher für Adc/Sbc im Dezimalmodus
TMPS ds.b 1
TMPA ds.b 1
IFNE DEBUG_DETAIL
DEBUGON ds.b 1
ENDC
; Zeiger auf die der aktuellen Speicherkonfiguration entsprechenden
; Read/WriteTab
CNOP 0,4
RDTAB ds.l 1
WRTAB ds.l 1
; Speicherzeiger
TheRAM ds.l 1 ;Zeiger auf C64-RAM (64K)
TheRAMPTR ds.l 1 ;Zeiger auf C64-RAM, Offset 32K (für Adressierung mit Vorzeichen)
TheBasic ds.l 1 ;Zeiger auf Basic-ROM
TheKernal ds.l 1 ;Zeiger auf Kernal-ROM
TheChar ds.l 1 ;Zeiger auf Char-ROM
TheColor ds.l 1 ;Zeiger auf Farb-RAM
; Interrupt-Flags. Bei einem Interrupt wird eins dieser Flags gesetzt.
; Das bewirkt, daß beim nächsten Opcode-Fetch der 6510-Task in die
; Routine "HandleInt" springt. Dort werden diese Flags ausgewertet und
; entsprechend verzweigt.
CNOP 0,4
Interrupt ;Zusammenfassung als Langwort
IntIsRESET ds.b 1 ;RESET aufgetreten, 6510 beenden oder Pause
IntIsNMI ds.b 1 ;NMI aufgetreten
IntIsIRQ ;Zusammenfassung als Wort
IntIsVICIRQ ds.b 1 ;IRQ durch VIC aufgetreten
IntIsCIAIRQ ds.b 1 ;IRQ durch CIA-A aufgetreten
FirstIRQCycle ds.l 1 ;Zyklus, an dem IRQ zuletzt auf low ging
FirstNMICycle ds.l 1 ;Zyklus, an dem NMI zuletzt auf low ging
RESETIsEXIT ds.b 1 ;Zur Unterscheidung von RESET und EXIT
RESETIsPause ds.b 1 ;Zur Unterscheidung von RESET und Pause
NMIState ds.b 1 ;Aktueller Zustand der NMI-Leitung (für Flankentriggerung)
; Bus Available vom VIC
BALow ds.b 1
; Zwischenspeicher für Lesezugriff mit BA
CNOP 0,4
HALTCONTSTORE ds.l 1
HALTRETADR ds.l 1
HALTADRSTORE ds.w 1
; Argumente für EasyRequest
CNOP 0,4
RequestStream ds.l 16
; Registerinhalte für SAM, nur gültig innerhalb von Pause6510/Resume6510
XDEF _RA
_RA ds.b 1
XDEF _RX
_RX ds.b 1
XDEF _RY
_RY ds.b 1
XDEF _RP
_RP ds.b 1
XDEF _RPR
_RPR ds.b 1
XDEF _RDDR
_RDDR ds.b 1
XDEF _RPC
_RPC ds.w 1
XDEF _RS
_RS ds.w 1
XDEF _SAMMemConfig
_SAMMemConfig ds.b 1 ;CHAREN, LORAM, HIRAM
END