From 8b7c9fdc4ffd5cedb8848afe87d409f7d40d2cb1 Mon Sep 17 00:00:00 2001 From: uz Date: Sun, 4 Oct 2009 18:52:10 +0000 Subject: [PATCH] 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 --- src/sim65/cpucore.c | 287 ++++++++++++++++++++++++-------------------- 1 file changed, 160 insertions(+), 127 deletions(-) diff --git a/src/sim65/cpucore.c b/src/sim65/cpucore.c index b46b97eab..aa3a69070 100644 --- a/src/sim65/cpucore.c +++ b/src/sim65/cpucore.c @@ -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) /*****************************************************************************/