mirror of
https://github.com/cc65/cc65.git
synced 2024-11-19 06:31:31 +00:00
Added decimal mode (untested): http://www.6502.org/tutorials/decimal_mode.html
git-svn-id: svn://svn.cc65.org/cc65/trunk@4327 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
ca5ada12ba
commit
8b7c9fdc4f
@ -124,11 +124,11 @@ static char BreakMsg[1024];
|
||||
#define PAGE_CROSS(addr,offs) ((((addr) & 0xFF) + offs) >= 0x100)
|
||||
|
||||
/* #imm */
|
||||
#define AC_OP_IMM(op) \
|
||||
Cycles = 2; \
|
||||
Regs.AC = Regs.AC op MemReadByte (Regs.PC+1); \
|
||||
TEST_ZF (Regs.AC); \
|
||||
TEST_SF (Regs.AC); \
|
||||
#define AC_OP_IMM(op) \
|
||||
Cycles = 2; \
|
||||
Regs.AC = Regs.AC op MemReadByte (Regs.PC+1); \
|
||||
TEST_ZF (Regs.AC); \
|
||||
TEST_SF (Regs.AC); \
|
||||
Regs.PC += 2
|
||||
|
||||
/* zp */
|
||||
@ -140,163 +140,196 @@ static char BreakMsg[1024];
|
||||
Regs.PC += 2
|
||||
|
||||
/* zp,x */
|
||||
#define AC_OP_ZPX(op) \
|
||||
unsigned char ZPAddr; \
|
||||
Cycles = 4; \
|
||||
ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; \
|
||||
Regs.AC = Regs.AC op MemReadByte (ZPAddr); \
|
||||
TEST_ZF (Regs.AC); \
|
||||
TEST_SF (Regs.AC); \
|
||||
#define AC_OP_ZPX(op) \
|
||||
unsigned char ZPAddr; \
|
||||
Cycles = 4; \
|
||||
ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; \
|
||||
Regs.AC = Regs.AC op MemReadByte (ZPAddr); \
|
||||
TEST_ZF (Regs.AC); \
|
||||
TEST_SF (Regs.AC); \
|
||||
Regs.PC += 2
|
||||
|
||||
/* zp,y */
|
||||
#define AC_OP_ZPY(op) \
|
||||
unsigned char ZPAddr; \
|
||||
Cycles = 4; \
|
||||
ZPAddr = MemReadByte (Regs.PC+1) + Regs.YR; \
|
||||
Regs.AC = Regs.AC op MemReadByte (ZPAddr); \
|
||||
TEST_ZF (Regs.AC); \
|
||||
TEST_SF (Regs.AC); \
|
||||
#define AC_OP_ZPY(op) \
|
||||
unsigned char ZPAddr; \
|
||||
Cycles = 4; \
|
||||
ZPAddr = MemReadByte (Regs.PC+1) + Regs.YR; \
|
||||
Regs.AC = Regs.AC op MemReadByte (ZPAddr); \
|
||||
TEST_ZF (Regs.AC); \
|
||||
TEST_SF (Regs.AC); \
|
||||
Regs.PC += 2
|
||||
|
||||
/* abs */
|
||||
#define AC_OP_ABS(op) \
|
||||
unsigned Addr; \
|
||||
Cycles = 4; \
|
||||
Addr = MemReadWord (Regs.PC+1); \
|
||||
Regs.AC = Regs.AC op MemReadByte (Addr); \
|
||||
TEST_ZF (Regs.AC); \
|
||||
TEST_SF (Regs.AC); \
|
||||
#define AC_OP_ABS(op) \
|
||||
unsigned Addr; \
|
||||
Cycles = 4; \
|
||||
Addr = MemReadWord (Regs.PC+1); \
|
||||
Regs.AC = Regs.AC op MemReadByte (Addr); \
|
||||
TEST_ZF (Regs.AC); \
|
||||
TEST_SF (Regs.AC); \
|
||||
Regs.PC += 3
|
||||
|
||||
/* abs,x */
|
||||
#define AC_OP_ABSX(op) \
|
||||
unsigned Addr; \
|
||||
Cycles = 4; \
|
||||
Addr = MemReadWord (Regs.PC+1); \
|
||||
if (PAGE_CROSS (Addr, Regs.XR)) { \
|
||||
++Cycles; \
|
||||
} \
|
||||
Regs.AC = Regs.AC op MemReadByte (Addr + Regs.XR); \
|
||||
TEST_ZF (Regs.AC); \
|
||||
TEST_SF (Regs.AC); \
|
||||
#define AC_OP_ABSX(op) \
|
||||
unsigned Addr; \
|
||||
Cycles = 4; \
|
||||
Addr = MemReadWord (Regs.PC+1); \
|
||||
if (PAGE_CROSS (Addr, Regs.XR)) { \
|
||||
++Cycles; \
|
||||
} \
|
||||
Regs.AC = Regs.AC op MemReadByte (Addr + Regs.XR); \
|
||||
TEST_ZF (Regs.AC); \
|
||||
TEST_SF (Regs.AC); \
|
||||
Regs.PC += 3
|
||||
|
||||
/* abs,y */
|
||||
#define AC_OP_ABSY(op) \
|
||||
unsigned Addr; \
|
||||
Cycles = 4; \
|
||||
Addr = MemReadWord (Regs.PC+1); \
|
||||
if (PAGE_CROSS (Addr, Regs.YR)) { \
|
||||
++Cycles; \
|
||||
} \
|
||||
Regs.AC = Regs.AC op MemReadByte (Addr + Regs.YR); \
|
||||
TEST_ZF (Regs.AC); \
|
||||
TEST_SF (Regs.AC); \
|
||||
#define AC_OP_ABSY(op) \
|
||||
unsigned Addr; \
|
||||
Cycles = 4; \
|
||||
Addr = MemReadWord (Regs.PC+1); \
|
||||
if (PAGE_CROSS (Addr, Regs.YR)) { \
|
||||
++Cycles; \
|
||||
} \
|
||||
Regs.AC = Regs.AC op MemReadByte (Addr + Regs.YR); \
|
||||
TEST_ZF (Regs.AC); \
|
||||
TEST_SF (Regs.AC); \
|
||||
Regs.PC += 3
|
||||
|
||||
/* (zp,x) */
|
||||
#define AC_OP_ZPXIND(op) \
|
||||
unsigned char ZPAddr; \
|
||||
unsigned Addr; \
|
||||
Cycles = 6; \
|
||||
ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; \
|
||||
Addr = MemReadZPWord (ZPAddr); \
|
||||
Regs.AC = Regs.AC op MemReadByte (Addr); \
|
||||
TEST_ZF (Regs.AC); \
|
||||
TEST_SF (Regs.AC); \
|
||||
#define AC_OP_ZPXIND(op) \
|
||||
unsigned char ZPAddr; \
|
||||
unsigned Addr; \
|
||||
Cycles = 6; \
|
||||
ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; \
|
||||
Addr = MemReadZPWord (ZPAddr); \
|
||||
Regs.AC = Regs.AC op MemReadByte (Addr); \
|
||||
TEST_ZF (Regs.AC); \
|
||||
TEST_SF (Regs.AC); \
|
||||
Regs.PC += 2
|
||||
|
||||
/* (zp),y */
|
||||
#define AC_OP_ZPINDY(op) \
|
||||
unsigned char ZPAddr; \
|
||||
unsigned Addr; \
|
||||
Cycles = 5; \
|
||||
ZPAddr = MemReadByte (Regs.PC+1); \
|
||||
Addr = MemReadZPWord (ZPAddr) + Regs.YR; \
|
||||
Regs.AC = Regs.AC op MemReadByte (Addr); \
|
||||
TEST_ZF (Regs.AC); \
|
||||
TEST_SF (Regs.AC); \
|
||||
#define AC_OP_ZPINDY(op) \
|
||||
unsigned char ZPAddr; \
|
||||
unsigned Addr; \
|
||||
Cycles = 5; \
|
||||
ZPAddr = MemReadByte (Regs.PC+1); \
|
||||
Addr = MemReadZPWord (ZPAddr) + Regs.YR; \
|
||||
Regs.AC = Regs.AC op MemReadByte (Addr); \
|
||||
TEST_ZF (Regs.AC); \
|
||||
TEST_SF (Regs.AC); \
|
||||
Regs.PC += 2
|
||||
|
||||
/* ADC */
|
||||
#define ADC(v) \
|
||||
if (GET_DF ()) { \
|
||||
Warning ("Decimal mode not available"); \
|
||||
} else { \
|
||||
unsigned old = Regs.AC; \
|
||||
unsigned rhs = (v & 0xFF); \
|
||||
Regs.AC += rhs + GET_CF (); \
|
||||
TEST_ZF (Regs.AC); \
|
||||
TEST_SF (Regs.AC); \
|
||||
TEST_CF (Regs.AC); \
|
||||
SET_OF (!((old ^ rhs) & 0x80) && \
|
||||
((old ^ Regs.AC) & 0x80)); \
|
||||
Regs.AC &= 0xFF; \
|
||||
}
|
||||
#define ADC(v) \
|
||||
do { \
|
||||
unsigned old = Regs.AC; \
|
||||
unsigned rhs = (v & 0xFF); \
|
||||
if (GET_DF ()) { \
|
||||
unsigned lo; \
|
||||
int res; \
|
||||
lo = (old & 0x0F) + (rhs & 0x0F) + GET_CF (); \
|
||||
if (lo >= 0x0A) { \
|
||||
lo = ((lo + 0x06) & 0x0F) + 0x10; \
|
||||
} \
|
||||
Regs.AC = (old & 0xF0) + (rhs & 0xF0) + lo; \
|
||||
res = (signed char)(old & 0xF0) + \
|
||||
(signed char)(rhs & 0xF0) + \
|
||||
(signed char)lo; \
|
||||
TEST_ZF (old + rhs + GET_CF ()); \
|
||||
TEST_SF (Regs.AC); \
|
||||
if (Regs.AC >= 0xA0) { \
|
||||
Regs.AC += 0x60; \
|
||||
} \
|
||||
TEST_CF (Regs.AC); \
|
||||
SET_OF ((res < -128) || (res > 127)); \
|
||||
} else { \
|
||||
Regs.AC += rhs + GET_CF (); \
|
||||
TEST_ZF (Regs.AC); \
|
||||
TEST_SF (Regs.AC); \
|
||||
TEST_CF (Regs.AC); \
|
||||
SET_OF (!((old ^ rhs) & 0x80) && \
|
||||
((old ^ Regs.AC) & 0x80)); \
|
||||
Regs.AC &= 0xFF; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* branches */
|
||||
#define BRANCH(cond) \
|
||||
Cycles = 2; \
|
||||
if (cond) { \
|
||||
signed char Offs; \
|
||||
unsigned char OldPCH; \
|
||||
++Cycles; \
|
||||
Offs = (signed char) MemReadByte (Regs.PC+1); \
|
||||
OldPCH = PCH; \
|
||||
Regs.PC += 2 + (int) Offs; \
|
||||
if (PCH != OldPCH) { \
|
||||
++Cycles; \
|
||||
} \
|
||||
} else { \
|
||||
Regs.PC += 2; \
|
||||
#define BRANCH(cond) \
|
||||
Cycles = 2; \
|
||||
if (cond) { \
|
||||
signed char Offs; \
|
||||
unsigned char OldPCH; \
|
||||
++Cycles; \
|
||||
Offs = (signed char) MemReadByte (Regs.PC+1); \
|
||||
OldPCH = PCH; \
|
||||
Regs.PC += 2 + (int) Offs; \
|
||||
if (PCH != OldPCH) { \
|
||||
++Cycles; \
|
||||
} \
|
||||
} else { \
|
||||
Regs.PC += 2; \
|
||||
}
|
||||
|
||||
/* compares */
|
||||
#define CMP(v1,v2) \
|
||||
{ \
|
||||
unsigned Result = v1 - v2; \
|
||||
TEST_ZF (Result & 0xFF); \
|
||||
TEST_SF (Result); \
|
||||
SET_CF (Result <= 0xFF); \
|
||||
}
|
||||
#define CMP(v1,v2) \
|
||||
do { \
|
||||
unsigned Result = v1 - v2; \
|
||||
TEST_ZF (Result & 0xFF); \
|
||||
TEST_SF (Result); \
|
||||
SET_CF (Result <= 0xFF); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* ROL */
|
||||
#define ROL(Val) \
|
||||
Val <<= 1; \
|
||||
if (GET_CF ()) { \
|
||||
Val |= 0x01; \
|
||||
} \
|
||||
TEST_ZF (Val); \
|
||||
TEST_SF (Val); \
|
||||
#define ROL(Val) \
|
||||
Val <<= 1; \
|
||||
if (GET_CF ()) { \
|
||||
Val |= 0x01; \
|
||||
} \
|
||||
TEST_ZF (Val); \
|
||||
TEST_SF (Val); \
|
||||
TEST_CF (Val)
|
||||
|
||||
/* ROR */
|
||||
#define ROR(Val) \
|
||||
if (GET_CF ()) { \
|
||||
Val |= 0x100; \
|
||||
} \
|
||||
SET_CF (Val & 0x01); \
|
||||
Val >>= 1; \
|
||||
TEST_ZF (Val); \
|
||||
#define ROR(Val) \
|
||||
if (GET_CF ()) { \
|
||||
Val |= 0x100; \
|
||||
} \
|
||||
SET_CF (Val & 0x01); \
|
||||
Val >>= 1; \
|
||||
TEST_ZF (Val); \
|
||||
TEST_SF (Val)
|
||||
|
||||
/* SBC */
|
||||
#define SBC(v) \
|
||||
if (GET_DF ()) { \
|
||||
Warning ("Decimal mode not available"); \
|
||||
} else { \
|
||||
unsigned old = Regs.AC; \
|
||||
unsigned rhs = (v & 0xFF); \
|
||||
Regs.AC -= rhs - (!GET_CF ()); \
|
||||
TEST_ZF (Regs.AC); \
|
||||
TEST_SF (Regs.AC); \
|
||||
SET_CF (Regs.AC <= 0xFF); \
|
||||
SET_OF (((old^rhs) & (old^Regs.AC) & 0x80)); \
|
||||
Regs.AC &= 0xFF; \
|
||||
}
|
||||
|
||||
#define SBC(v) \
|
||||
do { \
|
||||
unsigned old = Regs.AC; \
|
||||
unsigned rhs = (v & 0xFF); \
|
||||
if (GET_DF ()) { \
|
||||
unsigned lo; \
|
||||
int res; \
|
||||
lo = (old & 0x0F) - (rhs & 0x0F) + GET_CF () - 1; \
|
||||
if (lo & 0x80) { \
|
||||
lo = ((lo - 0x06) & 0x0F) - 0x10; \
|
||||
} \
|
||||
Regs.AC = (old & 0xF0) - (rhs & 0xF0) + lo; \
|
||||
if (Regs.AC & 0x80) { \
|
||||
Regs.AC -= 0x60; \
|
||||
} \
|
||||
res = Regs.AC - rhs + (!GET_CF ()); \
|
||||
TEST_ZF (res); \
|
||||
TEST_SF (res); \
|
||||
SET_CF (res <= 0xFF); \
|
||||
SET_OF (((old^rhs) & (old^res) & 0x80)); \
|
||||
} else { \
|
||||
Regs.AC -= rhs - (!GET_CF ()); \
|
||||
TEST_ZF (Regs.AC); \
|
||||
TEST_SF (Regs.AC); \
|
||||
SET_CF (Regs.AC <= 0xFF); \
|
||||
SET_OF (((old^rhs) & (old^Regs.AC) & 0x80)); \
|
||||
Regs.AC &= 0xFF; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
Loading…
Reference in New Issue
Block a user