📄 drz80.asm
字号:
;@---------------------------------------
MACRO
opRR $reg1, $reg2, $shift
movs $reg1,$reg2,lsr #$shift
tst z80f,#1<<CFlag ;@doesn't affect ARM carry, as long as the imidiate value is < 0x100. Watch out!
orrne $reg1,$reg1,#0x00000080
;@ and r2,z80_f,#PSR_C
;@ orr $reg1,$reg1,r2,lsl #6
sub r1,opcodes,#0x100
ldrb z80f,[r1,$reg1]
orrcs z80f,z80f,#1<<CFlag
MEND
MACRO
opRRA
orr z80a,z80a,z80f,lsr #1 ;@get C
movs z80a,z80a,ror #25
mov z80a,z80a,lsl #24
sub r1,opcodes,#0x100
ldrb z80f,[r1,z80a,lsr #24]
orrcs z80f,z80f,#1<<CFlag
fetch 8
MEND
MACRO
opRRH $reg
orr r0,$reg,z80f,lsr #1 ;@get C
movs r0,r0,ror #25
and $reg,$reg,#0x00FF0000 ;@mask out low
orr $reg,$reg,r0,lsl #24
sub r1,opcodes,#0x100
ldrb z80f,[r1,$reg,lsr #24]
orrcs z80f,z80f,#1<<CFlag
fetch 8
MEND
MACRO
opRRL $reg
and r0,$reg,#0x00FF0000 ;@mask out low to r0
opRR r0, r0, 17
and $reg,$reg,#0xFF000000 ;@mask out high
orr $reg,$reg,r0,lsl #16
fetch 8
MEND
MACRO
opRRb
opRR r0, r0, 1
MEND
;@---------------------------------------
MACRO
opRRC $reg1, $reg2, $shift
movs $reg1,$reg2,lsr #$shift
orrcs $reg1,$reg1,#0x00000080
sub r1,opcodes,#0x100
ldrb z80f,[r1,$reg1]
orrcs z80f,z80f,#1<<CFlag
MEND
MACRO
opRRCA
opRRC z80a, z80a, 25
mov z80a,z80a,lsl #24
fetch 8
MEND
MACRO
opRRCH $reg
opRRC r0, $reg, 25
and $reg,$reg,#0x00FF0000 ;@mask out low
orr $reg,$reg,r0,lsl #24
fetch 8
MEND
MACRO
opRRCL $reg
and r0,$reg,#0x00FF0000 ;@mask low to r0
opRRC r0, r0, 17
and $reg,$reg,#0xFF000000 ;@mask out high
orr $reg,$reg,r0,lsl #16
fetch 8
MEND
MACRO
opRRCb
opRRC r0, r0, 1
MEND
;@---------------------------------------
MACRO
opRST $addr
ldr r0,[cpucontext,#z80pc_base]
sub r0,z80pc,r0
IF FAST_Z80SP
mov r1,r0, lsr #8
strb r1,[z80sp,#-1]!
strb r0,[z80sp,#-1]!
ELSE
sub z80sp,z80sp,#2
mov r1,z80sp
writemem16
ENDIF
mov r0,#$addr
rebasepc
fetch 11
MEND
;@---------------------------------------
MACRO
opSBC
eor z80f,z80f,#1<<CFlag ;@ invert C
movs z80f,z80f,lsr #2 ;@ get C
subcc r0,r0,#0x100
eor z80f,r0,z80a,lsr #24 ;@ prepare for check of H
sbcs z80a,z80a,r0,ror #8
mrs r0,cpsr
eor z80f,z80f,z80a,lsr #24
and z80f,z80f,#1<<HFlag ;@ H, correct
orr z80f,z80f,r0,lsr #28 ;@ S,Z,V&C
eor z80f,z80f,#(1<<CFlag)|(1<<NFlag) ;@ invert C and set n.
MEND
MACRO
opSBCA
movs z80f,z80f,lsr #2 ;@ get C
movcc z80a,#0x00000000
movcs z80a,#0xFF000000
movcc z80f,#(1<<NFlag)|(1<<ZFlag)
movcs z80f,#58
fetch 4
MEND
MACRO
opSBCH $reg
mov r0,$reg,lsr #24
opSBC
fetch 4
MEND
MACRO
opSBCL $reg
mov r0,$reg,lsl #8
eor z80f,z80f,#1<<CFlag ;@ invert C
movs z80f,z80f,lsr #2 ;@ get C
sbccc r0,r0,#0xFF000000
mov r1,z80a,lsl #4 ;@ prepare for check of H
sbcs z80a,z80a,r0
mrs z80f,cpsr
mov z80f,z80f,lsr #28 ;@ S,Z,V&C
eor z80f,z80f,#(1<<CFlag)|(1<<NFlag) ;@ invert C and set n.
cmp r1,r0,lsl #4
orrcc z80f,z80f,#1<<HFlag ;@ H, correct
fetch 4
MEND
MACRO
opSBCb
opSBC
MEND
;@---------------------------------------
MACRO
opSBC16 $reg
eor z80f,z80f,#1<<CFlag ;@ invert C
movs z80f,z80f,lsr #2 ;@ get C
sbc r1,r1,r1 ;@ set r1 to -1 or 0.
orr r0,$reg,r1,lsr #16
mov r1,z80hl,lsl #4 ;@ prepare for check of H
sbcs z80hl,z80hl,r0
mrs z80f,cpsr
mov z80f,z80f,lsr #28 ;@ S,Z,V&C
eor z80f,z80f,#(1<<CFlag)|(1<<NFlag) ;@ invert C and set n.
cmp r1,r0,lsl #4
orrcc z80f,z80f,#1<<HFlag ;@ H, correct
fetch 15
MEND
MACRO
opSBC16HL
movs z80f,z80f,lsr #2 ;@ get C
mov z80hl,#0x00000000
subcs z80hl,z80hl,#0x00010000
movcc z80f,#(1<<NFlag)|(1<<ZFlag)
movcs z80f,#58
fetch 15
MEND
;@---------------------------------------
MACRO
opSETmemHL $bit
mov r0,z80hl, lsr #16
stmfd sp!,{r3,r12}
mov lr,pc
ldr pc,[cpucontext,#z80_read8] ;@ r0 = addr - data returned in r0
orr 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}
fetch 15
MEND
;@---------------------------------------
MACRO
opSETmem $bit
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
orr 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}
fetch 23
MEND
;@---------------------------------------
MACRO
opSLA $reg1, $reg2, $shift
movs $reg1,$reg2,lsl #$shift
sub r1,opcodes,#0x100
ldrb z80f,[r1,$reg1,lsr #24]
orrcs z80f,z80f,#1<<CFlag
MEND
MACRO
opSLAA
opSLA z80a, z80a, 1
fetch 8
MEND
MACRO
opSLAH $reg
and r0,$reg,#0xFF000000 ;@mask high to r0
adds $reg,$reg,r0
sub r1,opcodes,#0x100
ldrb z80f,[r1,$reg,lsr #24]
orrcs z80f,z80f,#1<<CFlag
fetch 8
MEND
MACRO
opSLAL $reg
opSLA r0, $reg, 9
and $reg,$reg,#0xFF000000 ;@mask out high
orr $reg,$reg,r0,lsr #8
fetch 8
MEND
MACRO
opSLAb
opSLA r0, r0, 25
mov r0,r0,lsr #24
MEND
;@---------------------------------------
MACRO
opSLL $reg1, $reg2, $shift
movs $reg1,$reg2,lsl #$shift
orr $reg1,$reg1,#0x01000000
sub r1,opcodes,#0x100
ldrb z80f,[r1,$reg1,lsr #24]
orrcs z80f,z80f,#1<<CFlag
MEND
MACRO
opSLLA
opSLL z80a, z80a, 1
fetch 8
MEND
MACRO
opSLLH $reg
and r0,$reg,#0xFF000000 ;@mask high to r0
adds $reg,$reg,r0
orr $reg,$reg,#0x01000000
sub r1,opcodes,#0x100
ldrb z80f,[r1,$reg,lsr #24]
orrcs z80f,z80f,#1<<CFlag
fetch 8
MEND
MACRO
opSLLL $reg
opSLL r0, $reg, 9
and $reg,$reg,#0xFF000000 ;@mask out high
orr $reg,$reg,r0,lsr #8
fetch 8
MEND
MACRO
opSLLb
opSLL r0, r0, 25
mov r0,r0,lsr #24
MEND
;@---------------------------------------
MACRO
opSRA $reg1, $reg2
movs $reg1,$reg2,asr #25
and $reg1,$reg1,#0xFF
sub r1,opcodes,#0x100
ldrb z80f,[r1,$reg1]
orrcs z80f,z80f,#1<<CFlag
MEND
MACRO
opSRAA
movs r0,z80a,asr #25
mov z80a,r0,lsl #24
sub r1,opcodes,#0x100
ldrb z80f,[r1,z80a,lsr #24]
orrcs z80f,z80f,#1<<CFlag
fetch 8
MEND
MACRO
opSRAH $reg
movs r0,$reg,asr #25
and $reg,$reg,#0x00FF0000 ;@mask out low
orr $reg,$reg,r0,lsl #24
sub r1,opcodes,#0x100
ldrb z80f,[r1,$reg,lsr #24]
orrcs z80f,z80f,#1<<CFlag
fetch 8
MEND
MACRO
opSRAL $reg
mov r0,$reg,lsl #8
opSRA r0, r0
and $reg,$reg,#0xFF000000 ;@mask out high
orr $reg,$reg,r0,lsl #16
fetch 8
MEND
MACRO
opSRAb
mov r0,r0,lsl #24
opSRA r0, r0
MEND
;@---------------------------------------
MACRO
opSRL $reg1, $reg2, $shift
movs $reg1,$reg2,lsr #$shift
sub r1,opcodes,#0x100
ldrb z80f,[r1,$reg1]
orrcs z80f,z80f,#1<<CFlag
MEND
MACRO
opSRLA
opSRL z80a, z80a, 25
mov z80a,z80a,lsl #24
fetch 8
MEND
MACRO
opSRLH $reg
opSRL r0, $reg, 25
and $reg,$reg,#0x00FF0000 ;@mask out low
orr $reg,$reg,r0,lsl #24
fetch 8
MEND
MACRO
opSRLL $reg
mov r0,$reg,lsl #8
opSRL r0, r0, 25
and $reg,$reg,#0xFF000000 ;@mask out high
orr $reg,$reg,r0,lsl #16
fetch 8
MEND
MACRO
opSRLb
opSRL r0, r0, 1
MEND
;@---------------------------------------
MACRO
opSUB $reg, $shift
mov r1,z80a,lsl #4 ;@ Prepare for check of half carry
subs z80a,z80a,$reg,lsl #$shift
mrs z80f,cpsr
mov z80f,z80f,lsr #28 ;@ S,Z,V&C
eor z80f,z80f,#(1<<CFlag)|(1<<NFlag) ;@ invert C and set n
cmp r1,$reg,lsl #$shift+4
orrcc z80f,z80f,#1<<HFlag
MEND
MACRO
opSUBA
mov z80a,#0
mov z80f,#(1<<ZFlag)|(1<<NFlag) ;@ set Z & n
fetch 4
MEND
MACRO
opSUBH $reg
and r0,$reg,#0xFF000000
opSUB r0, 0
fetch 4
MEND
MACRO
opSUBL $reg
opSUB $reg, 8
fetch 4
MEND
MACRO
opSUBb
opSUB r0, 24
MEND
;@---------------------------------------
MACRO
opXOR $reg, $shift
eor z80a,z80a,$reg,lsl #$shift
sub r0,opcodes,#0x100
ldrb z80f,[r0,z80a, lsr #24]
MEND
MACRO
opXORA
mov z80a,#0
mov z80f,#(1<<ZFlag)|(1<<VFlag)
fetch 4
MEND
MACRO
opXORH $reg
and r0,$reg,#0xFF000000
opXOR r0, 0
fetch 4
MEND
MACRO
opXORL $reg
opXOR $reg, 8
fetch 4
MEND
MACRO
opXORb
opXOR r0, 24
MEND
;@---------------------------------------
;@ --------------------------- Defines ----------------------------
;@ Make sure that regs/pointers for z80pc to z80sp match up!
opcodes RN 3
z80_icount RN 4
cpucontext RN 5
z80pc RN 6
z80a RN 7
z80f RN 8
z80bc RN 9
z80de RN 10
z80hl RN 11
z80sp RN 12
z80xx RN lr
z80pc_pointer EQU 0 ;@ 0
z80a_pointer EQU z80pc_pointer+4 ;@ 4
z80f_pointer EQU z80a_pointer+4 ;@ 8
z80bc_pointer EQU z80f_pointer+4 ;@
z80de_pointer EQU z80bc_pointer+4
z80hl_pointer EQU z80de_pointer+4
z80sp_pointer EQU z80hl_pointer+4
z80pc_base EQU z80sp_pointer+4
z80sp_base EQU z80pc_base+4
z80ix EQU z80sp_base+4
z80iy EQU z80ix+4
z80i EQU z80iy+4
z80a2 EQU z80i+4
z80f2 EQU z80a2+4
z80bc2 EQU z80f2+4
z80de2 EQU z80bc2+4
z80hl2 EQU z80de2+4
cycles_pointer EQU z80hl2+4
previouspc EQU cycles_pointer+4
z80irq EQU previouspc+4
z80if EQU z80irq+1
z80im EQU z80if+1
z80r EQU z80im+1
z80irqvector EQU z80r+1
z80irqcallback EQU z80irqvector+4
z80_write8 EQU z80irqcallback+4
z80_write16 EQU z80_write8+4
z80_in EQU z80_write16+4
z80_out EQU z80_in+4
z80_read8 EQU z80_out+4
z80_read16 EQU z80_read8+4
z80_rebaseSP EQU z80_read16+4
z80_rebasePC EQU z80_rebaseSP+4
VFlag EQU 0
CFlag EQU 1
ZFlag EQU 2
SFlag EQU 3
HFlag EQU 4
NFlag EQU 5
Flag3 EQU 6
Flag5 EQU 7
Z80_CFlag EQU 0
Z80_NFlag EQU 1
Z80_VFlag EQU 2
Z80_Flag3 EQU 3
Z80_HFlag EQU 4
Z80_Flag5 EQU 5
Z80_ZFlag EQU 6
Z80_SFlag EQU 7
Z80_IF1 EQU 1<<0
Z80_IF2 EQU 1<<1
Z80_HALT EQU 1<<2
;@ --------------------------- Framework --------------------------
DrZ80Run PROC
;@ r0 = pointer to cpu context
;@ r1 = ISTATES to execute
;@#########################################
stmdb sp!,{r4-r12,lr} ;@ save registers on stack
mov cpucontext,r0 ;@ setup main memory pointer
mov z80_icount,r1 ;@ setup number of Tstates to execute
ldmia cpucontext,{z80pc-z80sp} ;@ load Z80 registers
ldr opcodes,MAIN_opcodes_POINTER2
IF INTERRUPT_MODE = 0
;@ check ints
bl DoInterrupt ;@ done in mame now
ENDIF
ldrb r0,[z80pc],#1 ;@ get first op code
ldr pc,[opcodes,r0, lsl #2] ;@ execute op code
MAIN_opcodes_POINTER2 DCD MAIN_opcodes
z80_execute_end
;@ save registers in CPU context
stmia cpucontext,{z80pc-z80sp} ;@ save Z80 registers
ldmia sp!,{r4-r12,pc} ;@ restore registers from stack and return to C code
IF INTERRUPT_MODE
Interrupt_local
DCD Interrupt
ENDIF
DoInterrupt
IF INTERRUPT_MODE
;@ Don't do own int handler, call mames instead
;@ save everything back into DrZ80 context
stmia cpucontext,{z80pc-z80sp} ;@ save Z80 registers
stmfd sp!,{r3,r4,r5,lr} ;@ save rest of regs on stack
mov lr,pc
ldr pc,Interrupt_local
ldmfd sp!,{r3,r4,r5,lr} ;@ load regs from stack
;@ reload regs from DrZ80 context
ldmia cpucontext,{z80pc-z80sp} ;@ load Z80 registers
mov pc,lr ;@ return
ELSE
ldrb r0,[cpucontext,#z80irq]
tst r0,r0
moveq pc,lr
ldrb r0,[cpucontext,#z80if]
tst r0,#1
moveq pc,lr ;@ exit IF int disabled
stmfd sp!,{lr}
tst r0,#4 ;@ check halt
addne z80pc,z80pc,#1
;@ clear halt and int flags
eor r0,r0,r0
strb r0,[cpucontext,#z80if]
;@ now check int mode
ldrb r0,[cpucontext,#z80im]
and r0,r0,#3
ldr pc,[pc,r0,lsl #2]
DCD 0
DCD DoInterrupt_mode0
DCD DoInterrupt_mode1
DCD DoInterrupt_mode2
DCD DoInterrupt_mode1
DoInterrupt_mode0
;@ get 3 byte vector
ldr r2,[cpucontext, #z80irqvector]
and r1,r2,#0xFF0000
cmp r1,#0xCD0000 ;@ call
bne 1f
;@ ########
;@ # call
;@ ########
;@ save current pc on stack
ldr r0,[cpucontext,#z80pc_base]
sub r0,z80pc,r0
IF FAST_Z80SP
mov r1,r0, lsr #8
strb r1,[z80sp,#-1]!
strb r0,[z80sp,#-1]!
ELSE
sub z80sp,z80sp,#2
mov r1,z80sp
writemem16
ldr r2,[cpucontext, #z80irqvector]
ENDIF
;@ jump to vector
mov r2,r2,lsl #16
mov r0,r2,lsr #16
;@ rebase new pc
rebasepc
b DoInterrupt_end
1
cmp r1,#0xC30000 ;@ jump
bne DoInterrupt_mode1 ;@ rst
;@ #######
;@ # jump
;@ #######
;@ jump to vector
mov r2,r2,lsl #16
mov r0,r2,lsr #16
;@ rebase new pc
rebasepc
b DoInterrupt_end
DoInterrupt_mode1
ldr r0,[cpucontext,#z80pc_base]
sub r0,z80pc,r0
IF FAST_Z80SP
mov r1,r0, lsr #8
strb r1,[z80sp,#-1]!
strb r0,[z80sp,#-1]!
ELSE
sub z80sp,z80sp,#2
mov r1,z80sp
writemem16
ENDIF
mov r0,#0x38
rebasepc
b DoInterrupt_end
DoInterrupt_mode2
;@ push pc on stack
ldr r0,[cpucontext,#z80pc_base]
sub r0,z80pc,r0
IF FAST_Z80SP
mov r1,r0, lsr #8
strb r1,[z80sp,#-1]!
strb r0,[z80sp,#-1]!
ELSE
sub z80sp,z80sp,#2
mov r1,z80sp
writemem16
ENDIF
;@ get 1 byte vector address
ldrb r0,[cpucontext, #z80irqvector]
ldr r1,[cpucontext, #z80i]
orr r0,r0,r1,lsr #16
;@ read new pc from vector address
stmfd sp!,{r3,r12}
mov lr,pc
ldr pc,[cpucontext,#z80_read16]
;@ rebase new pc
IF UPDATE_CONTEXT
str z80pc,[cpucontext,#z80pc_pointer]
ENDIF
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
DoInterrupt_end
;@ interupt accepted so callback irq interface
ldr r0,[cpucontext, #z80irqcallback]
tst r0,r0
ldmeqfd sp!,{pc}
stmfd sp!,{r3,r12}
mov lr,pc
mov pc,r0 ;@ call callback function
ldmfd sp!,{r3,r12}
ldmfd sp!,{pc} ;@ return
ENDIF
DAATable
DCW 5
DCW 256
DCW 512
DCW 769
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -