⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpumacro.inc

📁 NES game Emulator in Linux.c and asm codes.
💻 INC
字号:
%if 0

SNEeSe, an Open Source Super NES emulator.


Copyright (c) 1998-2004 Charles Bilyue'.
Portions Copyright (c) 2003-2004 Daniel Horchner.

This is free software.  See 'LICENSE' for details.
You must read and accept the license prior to use.

%endif

; SNEeSe 65c816 CPU emulation core
; Originally written by Savoury SnaX (Not quite sure if I like AT&T)
; Maintained/rewritten by Charles Bilyue'
;
; Compile under NASM
;
; This file contains:
;  CPU opcode macros
;
; Examples of usage:
;  EM_LDA Direct = 8-bit LDA using "direct" address mode
;  BFC SNES_FLAG_C = Branch if carry flag clear (BCC)

;%1 = emulation mode vector, %2 = native mode vector
%macro SoftwareInterrupt 2
 READ8_Immediate
%if S_8bit == 0 ; native mode interrupt
 mov al,B_PB
 PUSH_B
%endif
 GET_PBPC eax
 PUSH_W
 SETUPFLAGS     ; Put flags into true 65c816 format
 PUSH_B

 xor eax,eax

%if S_8bit      ; emulation mode interrupt
 mov ebx,%1
%else           ; native mode interrupt
 mov ebx,%2
%endif

 GET_WORD
 mov R_PBPC,eax         ; PC = vector
 mov B_PB,byte 0        ; Setup bank

 STORE_FLAGS_I 1        ; Disable IRQs
 STORE_FLAGS_D 0        ; Disable decimal mode
%endmacro


;%1 = addr
%macro _ADC 1
%if M_8bit
 READ8_%1
 JUMP_FLAG SNES_FLAG_D,%%decimal_mode
 mov cl,B_C_flag
 mov bl,B_A
 add cl,255 ;MAKE_CARRY
 adc bl,al
 seto B_V_flag
 sbb al,al
 mov B_A,bl
 STORE_FLAGS_NZC bl,al
 OPCODE_EPILOG

ALIGNC
%%decimal_mode:
 mov cl,B_C_flag
 mov bl,al
 add cl,255 ;MAKE_CARRY
 mov al,B_A
 mov ecx,ebx
 mov edx,eax
 adc al,bl
 daa
 mov B_A,al
 sbb bl,bl
 STORE_FLAGS_NZC al,bl
;al = result, cl = argument, dl = old accumulator
 xor cl,dl ;accum ^ arg
 xor al,dl ;accum ^ result
 xor cl,-1 ;~(accum ^ arg)
 and al,0x80
 and al,cl ;(~((accum ^ arg)) & ((accum ^ result)) & 0x80)
 STORE_FLAGS_V al
%else
 READ16_%1
 JUMP_FLAG SNES_FLAG_D,%%decimal_mode
 mov cl,B_C_flag
 mov ebx,B_A
 add cl,255 ;MAKE_CARRY
 adc bx,ax
 seto B_V_flag
 sbb al,al
 STORE_FLAGS_N bh
 mov B_A,bx
 or bl,bh
 STORE_FLAGS_C al
 STORE_FLAGS_Z bl
 OPCODE_EPILOG

ALIGNC
%%decimal_mode:
 mov cl,B_C_flag
 mov ebx,eax
 add cl,255 ;MAKE_CARRY
 mov eax,B_A
 mov ecx,ebx
 mov edx,eax
 adc al,bl
 daa
 mov bl,al
 mov al,ah
 adc al,bh
 daa
 mov bh,al
 sbb al,al
 STORE_FLAGS_N bh
 mov B_A,bx
 or bl,bh
 STORE_FLAGS_C al
 STORE_FLAGS_Z bl
;ax = result, cx = argument, dx = old accumulator
 xor ch,dh ;accum ^ arg
 xor ah,dh ;accum ^ result
 xor ch,-1 ;~(accum ^ arg)
 and ah,0x80
 and ah,ch ;(~((accum ^ arg)) & ((accum ^ result)) & 0x80)
 STORE_FLAGS_V ah
%endif
%endmacro

;%1 = addr
%macro _AND 1
%if M_8bit
 READ8_%1
 mov bl,B_A
 and bl,al
 mov B_A,bl
 STORE_FLAGS_NZ bl
%else
 READ16_%1
 mov ebx,B_A
 and ebx,eax
 mov B_A,bx
 or bl,bh
 STORE_FLAGS_N bh
 STORE_FLAGS_Z bl
%endif
%endmacro

%macro _ASL 0
%if M_8bit
 add al,al
 sbb cl,cl
 STORE_FLAGS_NZC al,cl
%else
 add ax,ax
 sbb cl,cl
 mov dl,ah
 STORE_FLAGS_C cl
 or dl,al
 STORE_FLAGS_N ah
 STORE_FLAGS_Z dl
%endif
%endmacro

;eax = sign-extended branch offset
%macro short_branch 0
%if S_8bit
 mov edx,R_PBPC
 add R_PC,ax
 add R_Cycles,_5A22_FAST_CYCLE  ; branch taken
 xor edx,R_PBPC
 add dh,255
 sbb edx,edx
 and edx,_5A22_FAST_CYCLE   ;address page wrap?
 add R_Cycles,edx
%else
 add R_PC,ax
 add R_Cycles,_5A22_FAST_CYCLE  ; branch taken
%endif
%endmacro

;%1 = flag
%macro _BFC 1
 READ8_Immediate
 JUMP_FLAG %1,C_LABEL(CPU_RETURN)       ; flag set
 movsx eax,al                   ; sign extend for addition
 short_branch
%endmacro

;%1 = flag
%macro _BFS 1
 READ8_Immediate
 JUMP_NOT_FLAG %1,C_LABEL(CPU_RETURN)   ; flag clear
 movsx eax,al                   ; sign extend for addition
 short_branch
%endmacro

%macro _BRA 0
 READ8_Immediate
 movsx eax,al                   ; sign extend for addition
 short_branch
%endmacro

;%1 = addr
%macro _BIT 1
%if M_8bit
 READ8_%1
 mov cl,B_A
%ifnidni %1,Immediate
 STORE_FLAGS_N al
 and cl,al
 and al,0x40
 STORE_FLAGS_Z cl
 STORE_FLAGS_V al
%else   ; immediate affects only Z flag, others copy 2 MSBs to NV
 and cl,al
 STORE_FLAGS_Z cl
%endif
%else
 READ16_%1
 mov ecx,B_A
%ifnidni %1,Immediate
 STORE_FLAGS_N ah
 and ecx,eax
 and ah,0x40
 or cl,ch
 STORE_FLAGS_V ah
 STORE_FLAGS_Z cl
%else   ; immediate affects only Z flag, others copy 2 MSBs to NV
 and ecx,eax
 or cl,ch
 STORE_FLAGS_Z cl
%endif
%endif
%endmacro

;%1 = addr, %2 = reg, %3 = size
%macro V_CMP 3
%if %3 == 8
 READ8_%1
 mov cl,%2
 sub cl,al
 sbb al,al
 STORE_FLAGS_N cl
 xor al,0xFF
 STORE_FLAGS_Z cl
 STORE_FLAGS_C al
%else
 READ16_%1
 mov ecx,%2
 sub cx,ax
 sbb al,al
 STORE_FLAGS_N ch
 or cl,ch
 xor al,0xFF
 STORE_FLAGS_Z cl
 STORE_FLAGS_C al
%endif
%endmacro

;%1 = addr
%macro _CMP 1
 V_CMP %1,B_A,M_size
%endmacro

;%1 = addr
%macro _CPX 1
 V_CMP %1,B_X,X_size
%endmacro

;%1 = addr
%macro _CPY 1
 V_CMP %1,B_Y,X_size
%endmacro

;size
%macro _DEC 1
%if (%1) == 8
 dec al
 STORE_FLAGS_NZ al
%else
 dec eax
 mov cl,ah
 STORE_FLAGS_N ah
 or cl,al
 STORE_FLAGS_Z cl
%endif
%endmacro

%define _DEC_M _DEC M_size
%define _DEC_X _DEC X_size

;%1 = addr
%macro _EOR 1
%if M_8bit
 READ8_%1
 mov bl,B_A
 xor bl,al
 mov B_A,bl
 STORE_FLAGS_NZ bl
%else
 READ16_%1
 mov ebx,B_A
 xor ebx,eax
 mov B_A,bx
 or bl,bh
 STORE_FLAGS_N bh
 STORE_FLAGS_Z bl
%endif
%endmacro

;size
%macro _INC 1
%if (%1) == 8
 inc al
 STORE_FLAGS_NZ al
%else
 inc eax
 mov cl,ah
 STORE_FLAGS_N ah
 or cl,al
 STORE_FLAGS_Z cl
%endif
%endmacro

%define _INC_M _INC M_size
%define _INC_X _INC X_size

;%1 = addr, %2 = reg, %3 = size
%macro V_LDx 3
%if %3 == 8
 READ8_%1
 mov %2,al
 STORE_FLAGS_NZ al
%else
 READ16_%1
 mov %2,ax
 or al,ah
 STORE_FLAGS_N ah
 STORE_FLAGS_Z al
%endif
%endmacro

;%1 = addr
%macro _LDA 1
 V_LDx %1,B_A,M_size
%endmacro

;%1 = addr
%macro _LDX 1
 V_LDx %1,B_X,X_size
%endmacro

;%1 = addr
%macro _LDY 1
 V_LDx %1,B_Y,X_size
%endmacro

%macro _LSR 0
%if M_8bit
 shr al,1
 sbb cl,cl
 STORE_FLAGS_NZC al,cl
%else
 shr ax,1
 sbb cl,cl
 mov dl,ah
 STORE_FLAGS_C cl
 or dl,al
 STORE_FLAGS_N ah
 STORE_FLAGS_Z dl
%endif
%endmacro

;%1 = direction (0 = MVP, backward, 1 = MVN, forward)
%macro _MVX 1
 push ebx           ; Cycles per instruction iteration
.again:
 READ16_Immediate
 mov B_DB,al            ; Dest bank
 movzx ebx,ah           ; Src bank
 mov eax,B_X        ; Source address
 shl ebx,16
 add ebx,eax
%ifidni %1,MVN
 inc eax            ; MVN, Forward copy
%elifidni %1,MVP
 dec eax            ; MVP, Backward copy
%else
%error Invalid instruction ID for ALL_MVX
%endif
%if X_8bit
 mov B_X,al
%else
 mov B_X,ax
%endif
 GET_BYTE
 mov ebx,B_DB_Shifted
 add ebx,B_Y        ; Dest address
 SET_BYTE
 add R_Cycles,_5A22_FAST_CYCLE * 2
 mov eax,B_A
%ifidni %1,MVN
 inc ebx            ; MVN, Forward copy
%elifidni %1,MVP
 dec ebx            ; MVP, Backward copy
%else
%error Invalid instruction ID for ALL_MVX
%endif
 sub eax,byte 1
%if X_8bit
 mov B_Y,bl
%else
 mov B_Y,bx
%endif
 jc  .done
 sub R_PC,byte 3
 test R_Cycles,R_Cycles
 jge .event
 mov B_A,ax
 GET_PBPC ebx
 GET_BYTE
 jmp .again
ALIGNC
.done:
.event:
 mov B_A,ax
 pop edx
 OPCODE_EPILOG
%endmacro

;%1 = addr
%macro _ORA 1
%if M_8bit
 READ8_%1
 mov bl,B_A
 or bl,al
 mov B_A,bl
 STORE_FLAGS_NZ bl
%else
 READ16_%1
 mov ebx,B_A
 or ebx,eax
 mov B_A,bx
 or bl,bh
 STORE_FLAGS_N bh
 STORE_FLAGS_Z bl
%endif
%endmacro

%macro _ROL 0
%if M_8bit
 mov cl,B_C_flag
 add cl,255 ;MAKE_CARRY
 adc al,al
 sbb cl,cl
 STORE_FLAGS_NZC al,cl
%else
 mov cl,B_C_flag
 add cl,255 ;MAKE_CARRY
 adc ax,ax
 sbb cl,cl
 mov dl,ah
 STORE_FLAGS_C cl
 or dl,al
 STORE_FLAGS_N ah
 STORE_FLAGS_Z dl
%endif
%endmacro

%macro _ROR 0
%if M_8bit
 mov cl,B_C_flag
 add cl,255 ;MAKE_CARRY
 rcr al,1
 sbb cl,cl
 STORE_FLAGS_NZC al,cl
%else
 mov cl,B_C_flag
 add cl,255 ;MAKE_CARRY
 rcr ax,1
 sbb cl,cl
 mov dl,ah
 STORE_FLAGS_C cl
 or dl,al
 STORE_FLAGS_N ah
 STORE_FLAGS_Z dl
%endif
%endmacro

;%1 = addr
%macro _SBC 1
%if M_8bit
 READ8_%1
 JUMP_FLAG SNES_FLAG_D,%%decimal_mode
 mov cl,B_C_flag
 mov bl,B_A
 cmp cl,1   ;MAKE_NOT_CARRY
 sbb bl,al
 seto B_V_flag
 sbb al,al
 mov B_A,bl
 xor al,0xFF
 STORE_FLAGS_NZC bl,al
 OPCODE_EPILOG

ALIGNC
%%decimal_mode:
 mov cl,B_C_flag
 mov bl,al
 cmp cl,1   ;MAKE_NOT_CARRY
 mov al,B_A
 mov ecx,ebx
 mov edx,eax
 sbb al,bl
 das
 mov B_A,al
 sbb bl,bl
 STORE_FLAGS_N al
 xor bl,0xFF
 STORE_FLAGS_Z al
 STORE_FLAGS_C bl
;al = result, cl = argument, dl = old accumulator
 xor cl,dl ;accum ^ arg
 xor al,dl ;accum ^ result
 and cl,0x80
 and al,cl ;(((accum ^ arg)) & ((accum ^ result)) & 0x80)
 STORE_FLAGS_V al
%else
 READ16_%1
 JUMP_FLAG SNES_FLAG_D,%%decimal_mode
 mov cl,B_C_flag
 mov ebx,B_A
 cmp cl,1   ;MAKE_NOT_CARRY
 sbb bx,ax
 seto B_V_flag
 sbb al,al
 mov B_A,bx
 xor al,0xFF
 STORE_FLAGS_N bh
 or bl,bh
 STORE_FLAGS_C al
 STORE_FLAGS_Z bl
 OPCODE_EPILOG

ALIGNC
%%decimal_mode:
 mov cl,B_C_flag
 mov ebx,eax
 cmp cl,1   ;MAKE_NOT_CARRY
 mov eax,B_A
 mov ecx,ebx
 mov edx,eax
 sbb al,bl
 das
 mov bl,al
 mov al,ah
 sbb al,bh
 das
 mov bh,al
 sbb al,al
 STORE_FLAGS_N bh
 xor al,0xFF
 mov B_A,bx
 or bl,bh
 STORE_FLAGS_C al
 STORE_FLAGS_Z bl
;ax = result, cx = argument, dx = old accumulator
 xor ch,dh ;accum ^ arg
 xor ah,dh ;accum ^ result
 and ch,0x80
 and ah,ch ;(((accum ^ arg)) & ((accum ^ result)) & 0x80)
 STORE_FLAGS_V ah
%endif
%endmacro

;%1 = addr, %2 = reg, %3 = size
%macro V_STx 3
%if %3 == 8
 WRITE8_%1 %2
%else
 WRITE16_%1 %2
%endif
%endmacro

;%1 = addr
%macro _STA 1
 V_STx %1,B_A,M_size
%endmacro

;%1 = addr
%macro _STX 1
 V_STx %1,B_X,X_size
%endmacro

;%1 = addr
%macro _STY 1
 V_STx %1,B_Y,X_size
%endmacro

;%1 = addr
%macro _STZ 1
 V_STx %1,0,M_size
%endmacro

; TRB set flag Z on A & Memory Operand not A & !Memory Operand!
%macro _TRB 0
%if M_8bit
 mov cl,B_A
 mov ah,cl
 xor cl,-1
 and ah,al      ; Z set for: mem & A
 STORE_FLAGS_Z ah
 and al,cl      ; mem &= ~A
%else
 mov ecx,B_A
 test ecx,eax
 setnz B_Z_flag ; Z set for: mem & A
 xor ecx,-1
 and eax,ecx    ; mem &= ~A
%endif
%endmacro

; TSB set flag Z on A & Memory Operand not A | Memory Operand!
%macro _TSB 0
%if M_8bit
 mov cl,B_A
 mov ah,cl
 and cl,al      ; Z set for: mem & A
 STORE_FLAGS_Z cl
 or al,ah       ; mem |= A
%else
 mov ecx,B_A
 test ecx,eax
 setnz B_Z_flag ; Z set for: mem & A
 or eax,ecx     ; mem |= A
%endif
%endmacro

;%1 = value
%macro _PUSH8 1
 ADDR_Implied
 mov al,%1
 PUSH_B
%endmacro

;%1 = value, %2 = new
%macro _PUSH16 1-2 0
 ADDR_Implied
 mov eax,%1
 PUSH_W %2
%endmacro

;%1 = register
%macro _PULL8 1
 ADDR_Implied
 add R_Cycles,_5A22_FAST_CYCLE
 PULL_B
 mov %1,al
 STORE_FLAGS_NZ al
%endmacro

;%1 = register, %2 = new
%macro _PULL16 1-2 0
 ADDR_Implied
 add R_Cycles,_5A22_FAST_CYCLE
 PULL_W %2
 STORE_FLAGS_N ah
 mov %1,eax
 or al,ah
 STORE_FLAGS_Z al
%endmacro


;register, size
%macro _PUSH_reg 2
%if (%2) == 8
 _PUSH8 %1
%else
 _PUSH16 %1
%endif
%endmacro

%define _PHA _PUSH_reg B_A, M_size
%define _PHX _PUSH_reg B_X, X_size
%define _PHY _PUSH_reg B_Y, X_size
%define _PHB _PUSH_reg B_DB, 8
%define _PHK _PUSH_reg B_PB, 8
%define _PHD _PUSH16 B_D,New


;register, size
%macro _PULL_reg 2
%if (%2) == 8
 _PULL8 %1
%else
 _PULL16 %1
%endif
%endmacro

%define _PLA _PULL_reg B_A, M_size
%define _PLX _PULL_reg B_X, X_size
%define _PLY _PULL_reg B_Y, X_size
%define _PLB _PULL_reg B_DB, 8
%define _PLD _PULL16 B_D,New


;src
%macro _TxS 1
 ADDR_Implied
 mov eax,%1
%if S_8bit
 mov B_S,al
%else
 mov B_S,eax
%endif
%endmacro

;src,dest,size
%macro _Txx 3
 ADDR_Implied
 mov eax,%1
%if (%3) == 8
 mov %2,al
 STORE_FLAGS_NZ al
%else
 mov %2,eax
 or al,ah
 STORE_FLAGS_N ah
 STORE_FLAGS_Z al
%endif
%endmacro

;src
%macro _TxA 1
 _Txx %1,B_A,M_size
%endmacro

;src
%macro _TxX 1
 _Txx %1,B_X,X_size
%endmacro

;src
%macro _TxY 1
 _Txx %1,B_Y,X_size
%endmacro

;src
%macro _TxC 1
 _Txx %1,B_A,16
%endmacro

;src
%macro _TCD 0
 _Txx B_A,B_D,16
%endmacro

;flag
%macro _CLx 1   ;clear flag
 ADDR_Implied
 STORE_FLAGS_%1 0
%endmacro

;flag
%macro _SEx 1   ;set flag
 ADDR_Implied
 STORE_FLAGS_%1 1
%endmacro

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -