summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/cpu/m6502/opsc02.h
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/cpu/m6502/opsc02.h')
-rw-r--r--trunk/src/emu/cpu/m6502/opsc02.h359
1 files changed, 359 insertions, 0 deletions
diff --git a/trunk/src/emu/cpu/m6502/opsc02.h b/trunk/src/emu/cpu/m6502/opsc02.h
new file mode 100644
index 00000000000..affd6dfd72a
--- /dev/null
+++ b/trunk/src/emu/cpu/m6502/opsc02.h
@@ -0,0 +1,359 @@
+/*****************************************************************************
+ *
+ * m6502ops.h
+ * Addressing mode and opcode macros for 6502,65c02,65sc02,6510,n2a03 CPUs
+ *
+ * Copyright Juergen Buchmueller, all rights reserved.
+ * 65sc02 core Copyright Peter Trauner, 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.
+ *
+ *****************************************************************************/
+
+
+/***************************************************************
+ ***************************************************************
+ * Macros to emulate the 65C02 opcodes
+ ***************************************************************
+ ***************************************************************/
+
+/* 65C02 *******************************************************
+ * EA = absolute address + X
+ * one additional read if page boundary is crossed
+ ***************************************************************/
+#define EA_ABX_C02_P \
+ EA_ABS; \
+ if ( EAL + X > 0xff ) { \
+ RDMEM( PCW - 1 ); \
+ } \
+ EAW += X;
+
+/* 65C02 *******************************************************
+ * EA = absolute address + X
+ ***************************************************************/
+#define EA_ABX_C02_NP \
+ EA_ABS; \
+ RDMEM( PCW - 1 ); \
+ EAW += X;
+
+/***************************************************************
+ * EA = absolute address + Y
+ * one additional read if page boundary is crossed
+ ***************************************************************/
+#define EA_ABY_C02_P \
+ EA_ABS; \
+ if ( EAL + Y > 0xff ) { \
+ RDMEM( PCW - 1 ); \
+ } \
+ EAW += Y;
+
+/* 65C02 *******************************************************
+ * EA = absolute address + Y
+ ***************************************************************/
+#define EA_ABY_C02_NP \
+ EA_ABS; \
+ RDMEM( PCW - 1 ); \
+ EAW += Y
+
+/* 65C02 *******************************************************
+ * EA = zero page indirect + Y (post indexed)
+ * subtract 1 cycle if page boundary is crossed
+ ***************************************************************/
+#define EA_IDY_C02_P \
+ ZPL = RDOPARG(); \
+ EAL = RDMEM(ZPD); \
+ ZPL++; \
+ EAH = RDMEM(ZPD); \
+ if (EAL + Y > 0xff) { \
+ RDMEM( PCW - 1 ); \
+ } \
+ EAW += Y;
+
+/* 65C02 *******************************************************
+ * EA = zero page indirect + Y
+ ***************************************************************/
+#define EA_IDY_C02_NP \
+ ZPL = RDOPARG(); \
+ EAL = RDMEM(ZPD); \
+ ZPL++; \
+ EAH = RDMEM(ZPD); \
+ RDMEM( PCW - 1 ); \
+ EAW += Y
+
+/* 65C02 *******************************************************
+ * EA = indirect (only used by JMP)
+ * correct overflow handling
+ ***************************************************************/
+#define EA_IND_C02 \
+ EA_ABS; \
+ tmp = RDMEM(EAD); \
+ RDMEM(PCW-1); \
+ EAD++; \
+ EAH = RDMEM(EAD); \
+ EAL = tmp
+
+/* 65C02 *******************************************************
+ * EA = indirect plus x (only used by 65c02 JMP)
+ ***************************************************************/
+#define EA_IAX \
+ EA_ABS; \
+ RDMEM( PCW - 1 ); \
+ if (EAL + X > 0xff) { \
+ RDMEM( PCW - 1 ); \
+ } \
+ EAW += X; \
+ tmp = RDMEM(EAD); \
+ EAD++; \
+ EAH = RDMEM(EAD); \
+ EAL = tmp
+
+/* read a value into tmp */
+/* Base number of cycles taken for each mode (including reading of opcode):
+ RD_ABX_C02_P 4/5
+ RD_ABX_C02_NP/WR_ABX_C02_NP 5
+ RD_ABY_C02_P 4/5
+ RD_IDY_C02_P 5/6
+ WR_IDY_C02_NP 6
+ */
+#define RD_ABX_C02_P EA_ABX_C02_P; tmp = RDMEM(EAD)
+#define RD_ABX_C02_NP EA_ABX_C02_NP; tmp = RDMEM(EAD)
+#define RD_ABX_C02_NP_DISCARD EA_ABX_C02_NP; RDMEM(EAD)
+#define RD_ABY_C02_P EA_ABY_C02_P; tmp = RDMEM(EAD)
+#define RD_IDY_C02_P EA_IDY_C02_P; tmp = RDMEM_ID(EAD); cpustate->icount -= 1
+
+#define WR_ABX_C02_NP EA_ABX_C02_NP; WRMEM(EAD, tmp)
+#define WR_ABY_C02_NP EA_ABY_C02_NP; WRMEM(EAD, tmp)
+#define WR_IDY_C02_NP EA_IDY_C02_NP; WRMEM_ID(EAD, tmp); cpustate->icount -= 1
+
+
+/* 65C02********************************************************
+ * BRA branch relative
+ * extra cycle if page boundary is crossed
+ ***************************************************************/
+#define BRA_C02(cond) \
+ tmp = RDOPARG(); \
+ if (cond) \
+ { \
+ RDMEM(PCW); \
+ EAW = PCW + (signed char)tmp; \
+ if ( EAH != PCH ) { \
+ RDMEM( PCW - 1 ); \
+ } \
+ PCD = EAD; \
+ }
+
+/* 65C02 ********************************************************
+ * ADC Add with carry
+ * different setting of flags in decimal mode
+ ***************************************************************/
+#define ADC_C02 \
+ if (P & F_D) \
+ { \
+ int c = (P & F_C); \
+ int lo = (A & 0x0f) + (tmp & 0x0f) + c; \
+ int hi = (A & 0xf0) + (tmp & 0xf0); \
+ P &= ~(F_V | F_C); \
+ if( lo > 0x09 ) \
+ { \
+ hi += 0x10; \
+ lo += 0x06; \
+ } \
+ if( ~(A^tmp) & (A^hi) & F_N ) \
+ P |= F_V; \
+ if( hi > 0x90 ) \
+ hi += 0x60; \
+ if( hi & 0xff00 ) \
+ P |= F_C; \
+ A = (lo & 0x0f) + (hi & 0xf0); \
+ RDMEM( PCW - 1 ); \
+ } \
+ else \
+ { \
+ int c = (P & F_C); \
+ int sum = A + tmp + c; \
+ P &= ~(F_V | F_C); \
+ if( ~(A^tmp) & (A^sum) & F_N ) \
+ P |= F_V; \
+ if( sum & 0xff00 ) \
+ P |= F_C; \
+ A = (UINT8) sum; \
+ } \
+ SET_NZ(A)
+
+/* 65C02 ********************************************************
+ * SBC Subtract with carry
+ * different setting of flags in decimal mode
+ ***************************************************************/
+#define SBC_C02 \
+ if (P & F_D) \
+ { \
+ int c = (P & F_C) ^ F_C; \
+ int sum = A - tmp - c; \
+ int lo = (A & 0x0f) - (tmp & 0x0f) - c; \
+ int hi = (A & 0xf0) - (tmp & 0xf0); \
+ P &= ~(F_V | F_C); \
+ if( (A^tmp) & (A^sum) & F_N ) \
+ P |= F_V; \
+ if( lo & 0xf0 ) \
+ lo -= 6; \
+ if( lo & 0x80 ) \
+ hi -= 0x10; \
+ if( hi & 0x0f00 ) \
+ hi -= 0x60; \
+ if( (sum & 0xff00) == 0 ) \
+ P |= F_C; \
+ A = (lo & 0x0f) + (hi & 0xf0); \
+ RDMEM( PCW - 1 ); \
+ } \
+ else \
+ { \
+ int c = (P & F_C) ^ F_C; \
+ int sum = A - tmp - c; \
+ P &= ~(F_V | F_C); \
+ if( (A^tmp) & (A^sum) & F_N ) \
+ P |= F_V; \
+ if( (sum & 0xff00) == 0 ) \
+ P |= F_C; \
+ A = (UINT8) sum; \
+ } \
+ SET_NZ(A)
+
+/* 65C02 *******************************************************
+ * BBR Branch if bit is reset
+ ***************************************************************/
+#define BBR(bit) \
+ BRA(!(tmp & (1<<bit)))
+
+/* 65C02 *******************************************************
+ * BBS Branch if bit is set
+ ***************************************************************/
+#define BBS(bit) \
+ BRA(tmp & (1<<bit))
+
+/* 65c02 ********************************************************
+ * BRK Break
+ * increment PC, push PC hi, PC lo, flags (with B bit set),
+ * set I flag, reset D flag and jump via IRQ vector
+ ***************************************************************/
+#define BRK_C02 \
+ RDOPARG(); \
+ PUSH(PCH); \
+ PUSH(PCL); \
+ PUSH(P | F_B); \
+ P = (P | F_I) & ~F_D; \
+ PCL = RDMEM(M6502_IRQ_VEC); \
+ PCH = RDMEM(M6502_IRQ_VEC+1);
+
+
+/* 65C02 *******************************************************
+ * DEA Decrement accumulator
+ ***************************************************************/
+#define DEA \
+ A = (UINT8)(A - 1); \
+ SET_NZ(A)
+
+/* 65C02 *******************************************************
+ * INA Increment accumulator
+ ***************************************************************/
+#define INA \
+ A = (UINT8)(A + 1); \
+ SET_NZ(A)
+
+/* 65C02 *******************************************************
+ * PHX Push index X
+ ***************************************************************/
+#define PHX \
+ PUSH(X)
+
+/* 65C02 *******************************************************
+ * PHY Push index Y
+ ***************************************************************/
+#define PHY \
+ PUSH(Y)
+
+/* 65C02 *******************************************************
+ * PLX Pull index X
+ ***************************************************************/
+#define PLX \
+ RDMEM(SPD); \
+ PULL(X); \
+ SET_NZ(X)
+
+/* 65C02 *******************************************************
+ * PLY Pull index Y
+ ***************************************************************/
+#define PLY \
+ RDMEM(SPD); \
+ PULL(Y); \
+ SET_NZ(Y)
+
+/* 65C02 *******************************************************
+ * RMB Reset memory bit
+ ***************************************************************/
+#define RMB(bit) \
+ tmp &= ~(1<<bit)
+
+/* 65C02 *******************************************************
+ * SMB Set memory bit
+ ***************************************************************/
+#define SMB(bit) \
+ tmp |= (1<<bit)
+
+/* 65C02 *******************************************************
+ * STZ Store zero
+ ***************************************************************/
+#define STZ \
+ tmp = 0
+
+/* 65C02 *******************************************************
+ * TRB Test and reset bits
+ ***************************************************************/
+#define TRB \
+ SET_Z(tmp&A); \
+ tmp &= ~A
+
+/* 65C02 *******************************************************
+ * TSB Test and set bits
+ ***************************************************************/
+#define TSB \
+ SET_Z(tmp&A); \
+ tmp |= A
+
+/* 6502 ********************************************************
+ * BIT Bit test Immediate, only Z affected
+ ***************************************************************/
+#undef BIT_IMM_C02
+#define BIT_IMM_C02 \
+ P &= ~(F_Z); \
+ if ((tmp & A) == 0) \
+ P |= F_Z
+
+
+/***************************************************************
+ ***************************************************************
+ * Macros to emulate the 65sc02 opcodes
+ ***************************************************************
+ ***************************************************************/
+
+
+/* 65sc02 ********************************************************
+ * BSR Branch to subroutine
+ ***************************************************************/
+#define BSR \
+ EAL = RDOPARG(); \
+ RDMEM(SPD); \
+ PUSH(PCH); \
+ PUSH(PCL); \
+ EAH = RDOPARG(); \
+ EAW = PCW + (INT16)(EAW-1); \
+ PCD = EAD;