📄 cpuaddr.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:
; 65c816 addressing mode macros
;
; Note: As of 0.372 (11-99), be very careful when modifying this code,
; and the CPU loops! The CPU loops set eax/ebx to 0, except al/bl, and
; esi to the address of the data at PB:PC (opcode + operands),
; and the new address mode emulation expects this!
;
; Final address in ebx, or eax when address is to be stored in PC!
; Helper macro for read-modify-write operations.
;insn, addr
%macro RMW 2
RMW_ %+ %2 %1
%endmacro
;helper macro for nonzero DL fixup/quirks
%macro Check_DL_Not_Zero 0
%ifdef S_8bit
%if S_8bit
test dl,dl
jz %%fixup
add R_Cycles,_5A22_FAST_CYCLE
jmp %%no_fixup
%%fixup:
mov bh,dh
%%no_fixup:
%else
add dl,255
sbb edx,edx
and edx,_5A22_FAST_CYCLE
add R_Cycles,edx
%endif
%endif
%endmacro
; Implied
%macro ADDR_Implied 0
inc R_PC
add R_Cycles,_5A22_FAST_CYCLE
%endmacro
; shift, rotate, increment, and decrement of registers
; RMW 8-bit and 16-bit
; M ASL-0A INC-1A ROL-2A DEC-3A LSR-4A ROR-6A
; X DEY-88 INY-C8 DEX-CA INX-E8
%macro RMW_Accumulator 1
ADDR_Implied
%if M_8bit
mov al,B_A
%else
mov eax,B_A
%endif
add R_Cycles,_5A22_FAST_CYCLE
%1
%if M_8bit
mov B_A,al
%else
mov B_A,ax
%endif
%endmacro
%macro RMW_Index_X 1
ADDR_Implied
%if X_8bit
mov al,B_X
%else
mov eax,B_X
%endif
add R_Cycles,_5A22_FAST_CYCLE
%1
%if X_8bit
mov B_X,al
%else
mov B_X,ax
%endif
%endmacro
%macro RMW_Index_Y 1
ADDR_Implied
%if X_8bit
mov al,B_Y
%else
mov eax,B_Y
%endif
add R_Cycles,_5A22_FAST_CYCLE
%1
%if X_8bit
mov B_Y,al
%else
mov B_Y,ax
%endif
%endmacro
; Immediate (read-only)
; Read 8-bit and 16-bit
; ORA-09 AND-29 EOR-49 ADC-69 BIT-89 LDY-A0 LDX-A2 LDA-A9
; CPY-C0 CMP-C9 CPX-E0 SBC-E9
; Read 8-bit
; REP-C2 SEP-E2
;
%macro ADDR_Immediate 0
%endmacro
%macro READ8_Immediate 0
GET_PBPC ebx
inc bx
GET_BYTE
add R_PC,byte 2
%endmacro
%macro READ16_Immediate 0-1 0
GET_PBPC ebx
inc bx
GET_WORD wrap
%ifnidni %1,JSR
%ifnidni %1,JMP
add R_PC,byte 3
%endif
%else
add R_PC,byte 2
add R_Cycles,_5A22_FAST_CYCLE
%endif
%endmacro
%macro READ24_Immediate 0-1 0
GET_PBPC ebx
inc bx
%ifnidni %1,JSR
GET_LONG wrap
%ifnidni %1,JMP
add R_PC,byte 4
%endif
%else
READ16_Immediate
push eax
mov al,B_PB
E0_PUSH_B
add R_Cycles,_5A22_FAST_CYCLE
GET_PBPC ebx
GET_BYTE
movzx ecx,al
shl ecx,16
pop eax
add ecx,eax
GET_PBPC eax
E0_PUSH_W
mov eax,ecx
Stack_Fixup
%endif
%endmacro
; Absolute
; Address = DB:a16
; Read 8-bit and 16-bit
; ORA-0D BIT-2C AND-2D EOR-4D ADC-6D LDY-AC LDA-AD LDX-AE
; CPY-CC CMP-CD CPX-EC SBC-ED
; Write 8-bit and 16-bit
; STZ-9C STY-8C STA-8D STX-8E
; RMW 8-bit and 16-bit
; TSB-0C ASL-0E TRB-1C ROL-2E LSR-4E ROR-6E DEC-CE INC-EE
;
; if present, argument specifies post-index
%macro ADDR_Absolute 0-2 0,0
mov eax,B_DB_Shifted ;implied bank
READ16_Immediate
%ifnidni %1,0 ;helper: index
%ifidni %2,0
%define %%wrapcheck X_8bit
%else
%define %%wrapcheck 0
%endif
%if %%wrapcheck ;time always taken
mov ebx,(1 << 24) - 1 ;clip for indexing
add eax,%1
and ebx,eax
add R_Cycles,%2
%else ;penalty for address wrap
mov ebx,(1 << 24) - 1 ;clip for indexing
mov edx,eax
add eax,%1
sub dh,ah
and ebx,eax
add dh,255
sbb edx,edx
and edx,_5A22_FAST_CYCLE ;address page wrap?
add R_Cycles,edx
%endif
%else
mov ebx,eax
%endif
%endmacro
%macro READ8_Absolute 0
ADDR_Absolute
GET_BYTE
%endmacro
%macro READ16_Absolute 0
ADDR_Absolute
GET_WORD
%endmacro
%macro WRITE8_Absolute 1
ADDR_Absolute
mov al,%1
SET_BYTE
%endmacro
%macro WRITE16_Absolute 1
ADDR_Absolute
mov eax,%1
SET_WORD
%endmacro
%macro RMW_Absolute 1
READ %+ M_size %+ _Absolute
add R_Cycles,_5A22_FAST_CYCLE
%1
%if M_8bit
SET_BYTE
%else
SET_WORD_HL
%endif
%endmacro
; Absolute Long (corrupts eax)
; Address = a24
; Read 8-bit and 16-bit
; ORA-0F AND-2F EOR-4F ADC-6F LDA-AF CMP-CF SBC-EF
; Write 8-bit and 16-bit
; STA-8F
;
; if present, argument specifies post-index
%macro ADDR_Absolute_Long 0-1 0
READ24_Immediate
%ifnidni %1,0
mov ebx,(1 << 24) - 1
add eax,%1 ;helper: index
and ebx,eax ;clip for indexing
%else
mov ebx,eax
%endif
%endmacro
%macro READ8_Absolute_Long 0
ADDR_Absolute_Long
GET_BYTE
%endmacro
%macro READ16_Absolute_Long 0
ADDR_Absolute_Long
GET_WORD
%endmacro
%macro WRITE8_Absolute_Long 1
ADDR_Absolute_Long
mov al,%1
SET_BYTE
%endmacro
%macro WRITE16_Absolute_Long 1
ADDR_Absolute_Long
mov eax,%1
SET_WORD
%endmacro
; Direct (corrupts eax)
; Read 8-bit and 16-bit
; ORA-05 BIT-24 AND-25 EOR-45 ADC-65 LDY-A4 LDA-A5 LDX-A6
; CPY-C4 CMP-C5 CPX-E4 SBC-E5
; Write 8-bit and 16-bit
; STZ-64 STY-84 STA-85 STX-86
; RMW 8-bit and 16-bit
; TSB-04 ASL-06 TRB-14 ROL-26 LSR-46 ROR-66 DEC-C6 INC-E6
;
; if present, argument specifies index
%macro ADDR_Direct 0-1 0
READ8_Immediate
%ifnidni %1,0
add eax,%1 ;helper: index
%endif
mov edx,B_D
mov ebx,(1 << 16) - 1
add eax,edx ;(D + byte (+ index, if present))
and ebx,eax ;bank 00
Check_DL_Not_Zero
%ifnidni %1,0
add R_Cycles,_5A22_FAST_CYCLE
%endif
%endmacro
%macro READ8_Direct 0
ADDR_Direct
GET_BYTE
%endmacro
%macro READ16_Direct 0
ADDR_Direct
%if S_8bit
GET_WORD wrap
%else
GET_WORD
%endif
%endmacro
%macro READ24_Direct 0
ADDR_Direct
%if S_8bit
GET_LONG wrap
%else
GET_LONG
%endif
%endmacro
%macro WRITE8_Direct 1
ADDR_Direct
mov al,%1
SET_BYTE
%endmacro
%macro WRITE16_Direct 1
ADDR_Direct
mov eax,%1
%if S_8bit
SET_WORD wrap
%else
SET_WORD
%endif
%endmacro
%macro RMW_Direct 1
READ %+ M_size %+ _Direct
add R_Cycles,_5A22_FAST_CYCLE
%1
%if M_8bit
SET_BYTE
%else
%if S_8bit
SET_WORD_HL wrap
%else
SET_WORD_HL
%endif
%endif
%endmacro
; if present, argument specifies post-index
%macro ADDR_Direct_Indirect_Base 0-2 0,0
mov eax,B_DB_Shifted ;implied bank
%if S_8bit
GET_WORD wrap
%else
GET_WORD
%endif
%ifnidni %1,0 ;helper: post-index
%ifidni %2,0
%define %%wrapcheck X_8bit
%else
%define %%wrapcheck 0
%endif
%if %%wrapcheck ;time always taken
mov ebx,(1 << 24) - 1 ;clip for indexing
add eax,%1
and ebx,eax
add R_Cycles,%2
%else ;penalty for address wrap
mov ebx,(1 << 24) - 1 ;clip for indexing
mov edx,eax
add eax,%1
sub dh,ah
and ebx,eax
add dh,255
sbb edx,edx
and edx,_5A22_FAST_CYCLE ;address page wrap?
add R_Cycles,edx
%endif
%else
mov ebx,eax
%endif
%undef %%wrapcheck
%endmacro
; Direct Indirect (corrupts eax)
; Read 8-bit and 16-bit
; ORA-12 AND-32 EOR-52 ADC-72 LDA-B2 CMP-D2 SBC-F2
; Write 8-bit and 16-bit
; STA-92
; Push address (doesn't use these macros)
; PEI-D4
;
; 2 bytes, 5-7 cycles
;
; 1 1 1 1 1 PBR,PC Op Code 1
; 2 1 1 0 1 PBR,PC+1 DO 1
; (if DL != 0)
; (2) 2a 1 1 0 0 PBR,PC+1 IO 1
; 3 1 1 1 0 0,D+DO AAL 1
; 1 1 1 1 0 0,D+DO+1 AAH 1
; 5 1 1 1 0 DBR,AA Data Low 1/0
; (if 16-bit data)
; (1) 5a 1 1 1 0 DBR,AA+1 Data Low 1/0
; if present, first argument = pre-index, second = post-index
%macro ADDR_Direct_Indirect 0-3 0,0,0
ADDR_Direct %1
ADDR_Direct_Indirect_Base %2,%3
%endmacro
%macro READ8_Direct_Indirect 0
ADDR_Direct_Indirect
GET_BYTE
%endmacro
%macro READ16_Direct_Indirect 0
ADDR_Direct_Indirect
GET_WORD
%endmacro
%macro WRITE8_Direct_Indirect 1
ADDR_Direct_Indirect
mov al,%1
SET_BYTE
%endmacro
%macro WRITE16_Direct_Indirect 1
ADDR_Direct_Indirect
mov eax,%1
SET_WORD
%endmacro
; Direct Indirect Indexed (corrupts eax)
; Read 8-bit and 16-bit
; ORA-11 AND-31 EOR-51 ADC-71 LDA-B1 CMP-D1 SBC-F1
; Write 8-bit and 16-bit
; STA-91
;
; 2 bytes, 5-8 clocks
; 1 1 1 1 1 PBR,PC Op Code 1
; 2 1 1 0 1 PBR,PC+1 DO 1
; (if DL != 0)
; (2) 2a 1 1 0 0 PBR,PC+1 IO 1
; 3 1 1 1 0 0,D+DO AAL 1
; 4 1 1 1 0 0,D+DO+1 AAH 1
; (if index across page boundary, write, or X=0)
; (4) 4a 1 1 0 0 DBR,AAH,AAL+YL IO 1
; 5 1 1 1 0 DBR,AA+Y Data Low 1/0
; (if 16-bit data)
; (1) 5a 1 1 1 1 DBR,AA+Y+1 Data High 1/0
%macro ADDR_Direct_Indirect_Indexed 0-1 0
ADDR_Direct_Indirect 0,B_Y,%1
%endmacro
%macro READ8_Direct_Indirect_Indexed 0
ADDR_Direct_Indirect_Indexed
GET_BYTE
%endmacro
%macro READ16_Direct_Indirect_Indexed 0
ADDR_Direct_Indirect_Indexed
GET_WORD
%endmacro
%macro WRITE8_Direct_Indirect_Indexed 1
ADDR_Direct_Indirect_Indexed _5A22_FAST_CYCLE
mov al,%1
SET_BYTE
%endmacro
%macro WRITE16_Direct_Indirect_Indexed 1
ADDR_Direct_Indirect_Indexed _5A22_FAST_CYCLE
mov eax,%1
SET_WORD
%endmacro
; Direct Indirect Long (corrupts eax)
; Read 8-bit and 16-bit
; ORA-07 AND-27 EOR-47 ADC-67 LDA-A7 CMP-C7 SBC-E7
; Write 8-bit and 16-bit
; STA-87
;
; 2 bytes, 6-8 cycles
;
; 1 1 1 1 1 PBR,PC Op Code 1
; 2 1 1 0 1 PBR,PC+1 DO 1
; (if DL != 0)
; (2) 2a 1 1 0 0 PBR,PC+1 IO 1
; 3 1 1 1 0 0,D+DO AAL 1
; 4 1 1 1 0 0,D+DO+1 AAH 1
; 5 1 1 1 0 0,D+DO+2 AAB 1
; 6 1 1 1 0 AAB,AA Data Low 1/0
; (if 16-bit data)
; (1) 6a 1 1 1 0 AAB,AA+1 Data High 1/0
; if present, argument specifies index
%macro ADDR_Direct_Indirect_Long 0-1 0
READ24_Direct
%ifnidni %1,0 ;helper: index
mov ebx,(1 << 24) - 1 ;clip for indexing
add eax,%1
and ebx,eax
%else
mov ebx,eax
%endif
%endmacro
%macro READ8_Direct_Indirect_Long 0
ADDR_Direct_Indirect_Long
GET_BYTE
%endmacro
%macro READ16_Direct_Indirect_Long 0
ADDR_Direct_Indirect_Long
GET_WORD
%endmacro
%macro WRITE8_Direct_Indirect_Long 1
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -