;@ 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. .data .align 4 .global DrZ80Run .global DrZ80Ver .equiv INTERRUPT_MODE, 0 ;@0 = Use internal int handler, 1 = Use Mames int handler .equiv FAST_Z80SP, 0 ;@0 = Use mem functions for stack pointer, 1 = Use direct mem pointer .equiv UPDATE_CONTEXT, 0 .equiv DRZ80_XMAP, 1 .equiv DRZ80_XMAP_MORE_INLINE, 1 .if DRZ80_XMAP .equ Z80_MEM_SHIFT, 13 .endif .if INTERRUPT_MODE .extern Interrupt .endif DrZ80Ver: .long 0x0001 ;@ --------------------------- Defines ---------------------------- ;@ Make sure that regs/pointers for z80pc to z80sp match up! z80_icount .req r3 opcodes .req r4 cpucontext .req r5 z80pc .req r6 z80a .req r7 z80f .req r8 z80bc .req r9 z80de .req r10 z80hl .req r11 z80sp .req r12 z80xx .req lr .equ z80pc_pointer, 0 ;@ 0 .equ z80a_pointer, z80pc_pointer+4 ;@ 4 .equ z80f_pointer, z80a_pointer+4 ;@ 8 .equ z80bc_pointer, z80f_pointer+4 ;@ .equ z80de_pointer, z80bc_pointer+4 .equ z80hl_pointer, z80de_pointer+4 .equ z80sp_pointer, z80hl_pointer+4 .equ z80pc_base, z80sp_pointer+4 .equ z80sp_base, z80pc_base+4 .equ z80ix, z80sp_base+4 .equ z80iy, z80ix+4 .equ z80i, z80iy+4 .equ z80a2, z80i+4 .equ z80f2, z80a2+4 .equ z80bc2, z80f2+4 .equ z80de2, z80bc2+4 .equ z80hl2, z80de2+4 .equ cycles_pointer, z80hl2+4 .equ previouspc, cycles_pointer+4 .equ z80irq, previouspc+4 .equ z80if, z80irq+1 .equ z80im, z80if+1 .equ z80r, z80im+1 .equ z80irqvector, z80r+1 .equ z80irqcallback, z80irqvector+4 .equ z80_write8, z80irqcallback+4 .equ z80_write16, z80_write8+4 .equ z80_in, z80_write16+4 .equ z80_out, z80_in+4 .equ z80_read8, z80_out+4 .equ z80_read16, z80_read8+4 .equ z80_rebaseSP, z80_read16+4 .equ z80_rebasePC, z80_rebaseSP+4 .equ VFlag, 0 .equ CFlag, 1 .equ ZFlag, 2 .equ SFlag, 3 .equ HFlag, 4 .equ NFlag, 5 .equ Flag3, 6 .equ Flag5, 7 .equ Z80_CFlag, 0 .equ Z80_NFlag, 1 .equ Z80_VFlag, 2 .equ Z80_Flag3, 3 .equ Z80_HFlag, 4 .equ Z80_Flag5, 5 .equ Z80_ZFlag, 6 .equ Z80_SFlag, 7 .equ Z80_IF1, 1<<0 .equ Z80_IF2, 1<<1 .equ Z80_HALT, 1<<2 .equ Z80_NMI, 1<<3 ;@--------------------------------------- .text .if DRZ80_XMAP z80_xmap_read8: @ addr ldr r1,[cpucontext,#z80_read8] mov r2,r0,lsr #Z80_MEM_SHIFT ldr r1,[r1,r2,lsl #2] movs r1,r1,lsl #1 ldrccb r0,[r1,r0] bxcc lr z80_xmap_read8_handler: @ addr, func str z80_icount,[cpucontext,#cycles_pointer] stmfd sp!,{r12,lr} mov lr,pc bx r1 ldr z80_icount,[cpucontext,#cycles_pointer] ldmfd sp!,{r12,pc} z80_xmap_write8: @ data, addr ldr r2,[cpucontext,#z80_write8] add r2,r2,r1,lsr #Z80_MEM_SHIFT-2 bic r2,r2,#3 ldr r2,[r2] movs r2,r2,lsl #1 strccb r0,[r2,r1] bxcc lr z80_xmap_write8_handler: @ data, addr, func str z80_icount,[cpucontext,#cycles_pointer] mov r3,r0 mov r0,r1 mov r1,r3 stmfd sp!,{r12,lr} mov lr,pc bx r2 ldr z80_icount,[cpucontext,#cycles_pointer] ldmfd sp!,{r12,pc} z80_xmap_read16: @ addr @ check if we cross bank boundary add r1,r0,#1 eor r1,r1,r0 tst r1,#1< r1 .if FAST_Z80SP .if DRZ80_XMAP stack_check .endif mov r1,\reg, lsr #8 strb r1,[z80sp,#-1]! strb \reg,[z80sp,#-1]! .else mov r0,\reg sub z80sp,z80sp,#2 mov r1,z80sp writemem16 .endif .endm .macro opPUSHreg reg .if FAST_Z80SP .if DRZ80_XMAP stack_check .endif mov r1,\reg, lsr #24 strb r1,[z80sp,#-1]! mov r1,\reg, lsr #16 strb r1,[z80sp,#-1]! .else mov r0,\reg,lsr #16 sub z80sp,z80sp,#2 mov r1,z80sp writemem16 .endif .endm ;@--------------------------------------- .macro opRESmemHL bit mov r0,z80hl, lsr #16 .if DRZ80_XMAP bl z80_xmap_read8 bic r0,r0,#1<<\bit mov r1,z80hl, lsr #16 bl z80_xmap_write8 .else stmfd sp!,{r3,r12} mov lr,pc ldr pc,[cpucontext,#z80_read8] ;@ r0 = addr - data returned in r0 bic r0,r0,#1<<\bit mov r1,z80hl, lsr #16 mov lr,pc ldr pc,[cpucontext,#z80_write8] ;@ r0=data r1=addr ldmfd sp!,{r3,r12} .endif fetch 15 .endm ;@--------------------------------------- .macro opRESmem bit .if DRZ80_XMAP stmfd sp!,{r0} ;@ save addr as well bl z80_xmap_read8 bic r0,r0,#1<<\bit ldmfd sp!,{r1} ;@ restore addr into r1 bl z80_xmap_write8 .else stmfd sp!,{r3,r12} stmfd sp!,{r0} ;@ save addr as well mov lr,pc ldr pc,[cpucontext,#z80_read8] ;@ r0=addr - data returned in r0 bic r0,r0,#1<<\bit ldmfd sp!,{r1} ;@ restore addr into r1 mov lr,pc ldr pc,[cpucontext,#z80_write8] ;@ r0=data r1=addr ldmfd sp!,{r3,r12} .endif fetch 23 .endm ;@--------------------------------------- .macro opRL reg1 reg2 shift movs \reg1,\reg2,lsl \shift tst 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<