.DATA ;@ Reesy's Z80 Emulator Version 0.001 ;@ (c) Copyright 2004 Reesy, All rights reserved ;@ DrZ80 is free for non-commercial use. ;@ For commercial use, separate licencing terms must be obtained. .global DrZ80Run .global DrZ80Ver .equiv INTERRUPT_MODE, 1 ;@0 = Use internal int handler, 1 = Use Mames int handler .equiv FAST_Z80SP, 1 ;@0 = Use mem functions for stack pointer, 1 = Use direct mem pointer .equiv UPDATE_CONTEXT, 0 .equiv FAST_REBASE_PC, 1 ;@1=try not to call the rebase functions .equiv FAST_REBASE_SP, 1 ;@1=try not to call the rebase functions .equiv FAKE_PORTIO, 1 ;@1=don't really do any port IO .if INTERRUPT_MODE .extern Interrupt .endif DrZ80Ver: .long 0x0001 ;@--------------------------------------- .macro fetch cycs subs z80_icount,z80_icount,#\cycs .if UPDATE_CONTEXT str z80pc,[cpucontext,#z80pc_pointer] str z80_icount,[cpucontext,#cycles_pointer] ldr r1,[cpucontext,#z80pc_base] sub r2,z80pc,r1 str r2,[cpucontext,#previouspc] .endif ldrplb r0,[z80pc],#1 ldrpl pc,[opcodes,r0, lsl #2] bmi z80_execute_end .endm .macro eatcycles cycs sub z80_icount,z80_icount,#\cycs .if UPDATE_CONTEXT str z80_icount,[cpucontext,#cycles_pointer] .endif .endm .macro readmem8 .if UPDATE_CONTEXT str z80pc,[cpucontext,#z80pc_pointer] .endif stmfd sp!,{r3,r12} mov lr,pc ldr pc,[cpucontext,#z80_read8] ;@ r0 = addr - data returned in r0 ldmfd sp!,{r3,r12} .endm .macro readmem8HL mov r0,z80hl, lsr #16 readmem8 .endm .macro readmem16 .if UPDATE_CONTEXT str z80pc,[cpucontext,#z80pc_pointer] .endif stmfd sp!,{r3,r12} mov lr,pc ldr pc,[cpucontext,#z80_read16] ldmfd sp!,{r3,r12} .endm .macro writemem8 .if UPDATE_CONTEXT str z80pc,[cpucontext,#z80pc_pointer] .endif stmfd sp!,{r3,r12} mov lr,pc ldr pc,[cpucontext,#z80_write8] ;@ r0=data r1=addr ldmfd sp!,{r3,r12} .endm .macro writemem8DE mov r1,z80de, lsr #16 writemem8 .endm .macro writemem8HL mov r1,z80hl, lsr #16 writemem8 .endm .macro writemem16 .if UPDATE_CONTEXT str z80pc,[cpucontext,#z80pc_pointer] .endif stmfd sp!,{r3,r12} mov lr,pc ldr pc,[cpucontext,#z80_write16] ;@ r0=data r1=addr ldmfd sp!,{r3,r12} .endm .macro copymem8HL_DE .if UPDATE_CONTEXT str z80pc,[cpucontext,#z80pc_pointer] .endif mov r0,z80hl, lsr #16 stmfd sp!,{r3,r12} mov lr,pc ldr pc,[cpucontext,#z80_read8] ;@ r0 = addr - data returned in r0 .if UPDATE_CONTEXT str z80pc,[cpucontext,#z80pc_pointer] .endif mov r1,z80de, lsr #16 mov lr,pc ldr pc,[cpucontext,#z80_write8] ;@ r0=data r1=addr ldmfd sp!,{r3,r12} .endm ;@--------------------------------------- .macro rebasepc .if UPDATE_CONTEXT str z80pc,[cpucontext,#z80pc_pointer] .endif .if FAST_REBASE_PC ldr r1,[cpucontext,#z80pc_base] add z80pc,r0,r1 .else stmfd sp!,{r3,r12} mov lr,pc ldr pc,[cpucontext,#z80_rebasePC] ;@ r0=new pc - external function sets z80pc_base and returns new z80pc in r0 ldmfd sp!,{r3,r12} mov z80pc,r0 .endif .endm .macro rebasesp .if UPDATE_CONTEXT str z80pc,[cpucontext,#z80pc_pointer] .endif .if FAST_REBASE_SP ldr r1,[cpucontext,#z80sp_base] add r0,r0,r1 .else stmfd sp!,{r3,r12} mov lr,pc ldr pc,[cpucontext,#z80_rebaseSP] ;@ external function must rebase sp ldmfd sp!,{r3,r12} .endif .endm ;@---------------------------------------------------------------------------- .macro opADC movs z80f,z80f,lsr#2 ;@ get C subcs r0,r0,#0x100 eor z80f,r0,z80a,lsr#24 ;@ prepare for check of half carry adcs z80a,z80a,r0,ror#8 mrs r0,cpsr ;@ S,Z,V&C eor z80f,z80f,z80a,lsr#24 and z80f,z80f,#1< 0xFF writemem8HL add z80hl,z80hl,#1<<16 sub z80bc,z80bc,#1<<24 tst z80bc,#0xFF<<24 orrmi z80f,z80f,#1< 0xFF sub z80bc,z80bc,#1<<24 tst z80bc,#0xFF<<24 orrmi z80f,z80f,#1< 0xFF writemem8HL sub z80hl,z80hl,#1<<16 sub z80bc,z80bc,#1<<24 tst z80bc,#0xFF<<24 orrmi z80f,z80f,#1< 0xFF sub z80bc,z80bc,#1<<24 tst z80bc,#0xFF<<24 orrmi z80f,z80f,#1< 0xFF writemem8HL add z80hl,z80hl,#1<<16 sub z80bc,z80bc,#1<<24 tst z80bc,#0xFF<<24 orrmi z80f,z80f,#1< 0xFF sub z80bc,z80bc,#1<<24 tst z80bc,#0xFF<<24 orrmi z80f,z80f,#1< 0xFF writemem8HL sub z80hl,z80hl,#1<<16 sub z80bc,z80bc,#1<<24 tst z80bc,#0xFF<<24 orrmi z80f,z80f,#1< 0xFF sub z80bc,z80bc,#1<<24 tst z80bc,#0xFF<<24 orrmi z80f,z80f,#1<