📄 m6502ops.h
字号:
/*****************************************************************************
*
* m6502ops.h
* Addressing mode and opcode macros for 6502,65c02,6510 CPUs
*
* Copyright (c) 1998 Juergen Buchmueller, all rights reserved.
*
* - This source code is released as freeware for non-commercial purposes.
* - You are free to use and redistribute this code in modified or
* unmodified form, provided you list me in the credits.
* - If you modify this source code, you must add a notice to each modified
* source file that it has been changed. If you're a nice person, you
* will clearly mark each change too. :)
* - If you wish to use this for commercial purposes, please contact me at
* pullmoll@t-online.de
* - The author of this copywritten work reserves the right to change the
* terms of its usage and license at any time, including retroactively
* - This entire notice must remain in the source code.
*
*****************************************************************************/
/* 6502 flags */
#define _fC 0x01
#define _fZ 0x02
#define _fI 0x04
#define _fD 0x08
#define _fB 0x10
#define _fT 0x20
#define _fV 0x40
#define _fN 0x80
/* some shortcuts for improved readability */
#define A m6502.a
#define X m6502.x
#define Y m6502.y
#define P m6502.p
#define S m6502.sp.B.l
#define SPD m6502.sp.D
#if LAZY_FLAGS
#define NZ m6502.nz
#define SET_NZ(n) NZ = (((n) & _fN) << 8) | (n)
#define SET_Z(n) NZ = (NZ & 0x100) | (n)
#else
#define SET_NZ(n) \
P = (P & ~(_fN | _fZ)) | ((n) & _fN) | (((n) == 0) ? _fZ : 0)
#define SET_Z(n) \
P = (P & ~_fZ) | ((n) == 0) ? _fZ : 0)
#endif
#define EAL m6502.ea.B.l
#define EAH m6502.ea.B.h
#define EAW m6502.ea.W.l
#define EAD m6502.ea.D
#define ZPL m6502.zp.B.l
#define ZPH m6502.zp.B.h
#define ZPW m6502.zp.W.l
#define ZPD m6502.zp.D
#define PCL m6502.pc.B.l
#define PCH m6502.pc.B.h
#define PCW m6502.pc.W.l
#define PCD m6502.pc.D
#if FAST_MEMORY
extern MHELE *cur_mwhard;
extern MHELE *cur_mrhard;
extern byte *RAM;
#endif
/***************************************************************
* RDOP read an opcode
***************************************************************/
#define RDOP() cpu_readop(PCW++)
/***************************************************************
* RDOPARG read an opcode argument
***************************************************************/
#define RDOPARG() cpu_readop_arg(PCW++)
/***************************************************************
* RDMEM read memory
***************************************************************/
#if FAST_MEMORY
#define RDMEM(addr) \
((cur_mrhard[(addr) >> (ABITS2_16 + ABITS_MIN_16)]) ? \
cpu_readmem16(addr) : RAM[addr])
#else
#define RDMEM(addr) cpu_readmem16(addr)
#endif
/***************************************************************
* WRMEM write memory
***************************************************************/
#if FAST_MEMORY
#define WRMEM(addr,data) \
if (cur_mwhard[(addr) >> (ABITS2_16 + ABITS_MIN_16)]) \
cpu_writemem16(addr,data); \
else \
RAM[addr] = data
#else
#define WRMEM(addr,data) cpu_writemem16(addr,data)
#endif
/***************************************************************
* BRA branch relative
* extra cycle if page boundary is crossed
***************************************************************/
#define BRA(cond) \
if (cond) \
{ \
tmp = RDOPARG(); \
EAW = PCW + (signed char)tmp; \
M6502_ICount -= (PCH == EAH) ? 3 : 4; \
PCD = EAD; \
change_pc16(PCD); \
} \
else \
{ \
PCW++; \
M6502_ICount -= 2; \
}
/***************************************************************
*
* Helper macros to build the effective address
*
***************************************************************/
/***************************************************************
* EA = zero page address
***************************************************************/
#define EA_ZPG \
ZPL = RDOPARG(); \
EAD = ZPD
/***************************************************************
* EA = zero page address + X
***************************************************************/
#define EA_ZPX \
ZPL = RDOPARG() + X; \
EAD = ZPD
/***************************************************************
* EA = zero page address + Y
***************************************************************/
#define EA_ZPY \
ZPL = RDOPARG() + Y; \
EAD = ZPD
/***************************************************************
* EA = absolute address
***************************************************************/
#define EA_ABS \
EAL = RDOPARG(); \
EAH = RDOPARG()
/***************************************************************
* EA = absolute address + X
***************************************************************/
#define EA_ABX \
EA_ABS; \
EAW += X
/***************************************************************
* EA = absolute address + Y
***************************************************************/
#define EA_ABY \
EA_ABS; \
EAW += Y
/***************************************************************
* EA = zero page indirect (65c02 pre indexed w/o X)
***************************************************************/
#define EA_ZPI \
ZPL = RDOPARG(); \
EAL = RDMEM(ZPD); \
ZPL++; \
EAH = RDMEM(ZPD)
/***************************************************************
* EA = zero page + X indirect (pre indexed)
***************************************************************/
#define EA_IDX \
ZPL = RDOPARG() + X; \
EAL = RDMEM(ZPD); \
ZPL++; \
EAH = RDMEM(ZPD)
/***************************************************************
* EA = zero page indirect + Y (post indexed)
* subtract 1 cycle if page boundary is crossed
***************************************************************/
#define EA_IDY \
ZPL = RDOPARG(); \
EAL = RDMEM(ZPD); \
ZPL++; \
EAH = RDMEM(ZPD); \
if (EAL + Y > 0xff) \
M6502_ICount--; \
EAW += Y
/***************************************************************
* EA = indirect (only used by JMP)
***************************************************************/
#define EA_IND \
EA_ABS; \
tmp = RDMEM(EAD); \
EAL++; /* booby trap: stay in same page! ;-) */ \
EAH = RDMEM(EAD); \
EAL = tmp
/***************************************************************
* EA = indirect plus x (only used by 65c02 JMP)
***************************************************************/
#define EA_IAX \
EA_IND; \
if (EAL + X > 0xff) /* assumption; probably wrong ? */ \
M6502_ICount--; \
EAW += X
/* read a value into tmp */
#define RD_IMM tmp = RDOPARG()
#define RD_ACC tmp = A
#define RD_ZPG EA_ZPG; tmp = RDMEM(EAD)
#define RD_ZPX EA_ZPX; tmp = RDMEM(EAD)
#define RD_ZPY EA_ZPY; tmp = RDMEM(EAD)
#define RD_ABS EA_ABS; tmp = RDMEM(EAD)
#define RD_ABX EA_ABX; tmp = RDMEM(EAD)
#define RD_ABY EA_ABY; tmp = RDMEM(EAD)
#define RD_ZPI EA_ZPI; tmp = RDMEM(EAD)
#define RD_IDX EA_IDX; tmp = RDMEM(EAD)
#define RD_IDY EA_IDY; tmp = RDMEM(EAD)
/* write a value from tmp */
#define WR_ZPG EA_ZPG; WRMEM(EAD, tmp)
#define WR_ZPX EA_ZPX; WRMEM(EAD, tmp)
#define WR_ZPY EA_ZPY; WRMEM(EAD, tmp)
#define WR_ABS EA_ABS; WRMEM(EAD, tmp)
#define WR_ABX EA_ABX; WRMEM(EAD, tmp)
#define WR_ABY EA_ABY; WRMEM(EAD, tmp)
#define WR_ZPI EA_ZPI; WRMEM(EAD, tmp)
#define WR_IDX EA_IDX; WRMEM(EAD, tmp)
#define WR_IDY EA_IDY; WRMEM(EAD, tmp)
/* write back a value from tmp to the last EA */
#define WB_ACC A = (byte)tmp;
#define WB_EA WRMEM(EAD, tmp)
/***************************************************************
***************************************************************
* Macros to emulate the plain 6502 opcodes
***************************************************************
***************************************************************/
/***************************************************************
* compose the real flag register by
* including N and Z and set any
* SET and clear any CLR bits also
***************************************************************/
#if LAZY_FLAGS
#define COMPOSE_P \
P = (P & ~(_fN|_fZ)) | (NZ >> 8) | ((NZ&0xff) ? 0:_fZ)
#else
#define COMPOSE_P
#endif
/***************************************************************
* push a register onto the stack
***************************************************************/
#define PUSH(Rg) WRMEM(SPD, Rg); S--
/***************************************************************
* pull a register from the stack
***************************************************************/
#define PULL(Rg) S++; Rg = RDMEM(SPD)
/* 6502 ********************************************************
* ADC Add with carry
***************************************************************/
#define ADC \
if (P & _fD) \
{ \
int c = (P & _fC); \
int lo = (A & 0x0f) + (tmp & 0x0f) + c; \
int hi = (A & 0xf0) + (tmp & 0xf0); \
P &= ~(_fV | _fC); \
if (lo > 0x09) \
{ \
hi += 0x10; \
lo += 0x06; \
} \
if (~(A^tmp) & (A^hi) & _fN) \
P |= _fV; \
if (hi > 0x90) \
hi += 0x60; \
if (hi & 0xff00) \
P |= _fC; \
A = (lo & 0x0f) + (hi & 0xf0); \
} \
else \
{ \
int c = (P & _fC); \
int sum = A + tmp + c; \
P &= ~(_fV | _fC); \
if (~(A^tmp) & (A^sum) & _fN) \
P |= _fV; \
if (sum & 0xff00) \
P |= _fC; \
A = (byte) sum; \
} \
SET_NZ(A)
/* 6502 ********************************************************
* AND Logical and
***************************************************************/
#define AND \
A = (byte)(A & tmp); \
SET_NZ(A)
/* 6502 ********************************************************
* ASL Arithmetic shift left
***************************************************************/
#define ASL \
P = (P & ~_fC) | ((tmp >> 7) & _fC); \
tmp = (byte)(tmp << 1); \
SET_NZ(tmp)
/* 6502 ********************************************************
* BCC Branch if carry clear
***************************************************************/
#define BCC BRA(!(P & _fC))
/* 6502 ********************************************************
* BCS Branch if carry set
***************************************************************/
#define BCS BRA(P & _fC)
/* 6502 ********************************************************
* BEQ Branch if equal
***************************************************************/
#if LAZY_FLAGS
#define BEQ BRA(!(NZ & 0xff))
#else
#define BEQ BRA(P & _fZ)
#endif
/* 6502 ********************************************************
* BIT Bit test
***************************************************************/
#if LAZY_FLAGS
#define BIT \
P = (P & ~_fV) | (tmp & _fV); \
NZ = (tmp & _fN) << 8; \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -