-/* Set flags */
-#define SET_CF() (SR |= CF)
-#define SET_ZF() (SR |= ZF)
-#define SET_IF() (SR |= IF)
-#define SET_DF() (SR |= DF)
-#define SET_BF() (SR |= BF)
-#define SET_OF() (SR |= OF)
-#define SET_SF() (SR |= SF)
-
-/* Reset flags */
-#define CLR_CF() (SR &= ~CF)
-#define CLR_ZF() (SR &= ~ZF)
-#define CLR_IF() (SR &= ~IF)
-#define CLR_DF() (SR &= ~DF)
-#define CLR_BF() (SR &= ~BF)
-#define CLR_OF() (SR &= ~OF)
-#define CLR_SF() (SR &= ~SF)
-
-/* Test for the flags */
-#define CF_IS_SET() (SR & CF)
-#define ZF_IS_SET() (SR & ZF)
-#define IF_IS_SET() (SR & IF)
-#define DF_IS_SET() (SR & DF)
-#define BF_IS_SET() (SR & BF)
-#define OF_IS_SET() (SR & OF)
-#define SF_IS_SET() (SR & SF)
-
-/* Set the flags according to a given value */
-#define TEST_ZF(v) do { if ((v) == 0) { SET_ZF(); } else { CLR_ZF(); } } while (0)
-#define TEST_SF(v) do { if ((v) & 0x80) { SET_SF(); } else { CLR_SF(); } } while (0)
-#define TEST_CF(v) do { if (v) { SET_CF (); } else { CLR_CF (); } } while (0)
+/* Return the flags as a boolean value */
+#define GET_CF() ((SR & CF) != 0)
+#define GET_ZF() ((SR & ZF) != 0)
+#define GET_IF() ((SR & IF) != 0)
+#define GET_DF() ((SR & DF) != 0)
+#define GET_BF() ((SR & BF) != 0)
+#define GET_OF() ((SR & OF) != 0)
+#define GET_SF() ((SR & SF) != 0)
+
+/* Set the flags. The parameter is a boolean flag that says if the flag should be
+ * set or reset.
+ */
+#define SET_CF(f) do { if (f) { SR |= CF; } else { SR &= ~CF; } } while (0)
+#define SET_ZF(f) do { if (f) { SR |= ZF; } else { SR &= ~ZF; } } while (0)
+#define SET_IF(f) do { if (f) { SR |= IF; } else { SR &= ~IF; } } while (0)
+#define SET_DF(f) do { if (f) { SR |= DF; } else { SR &= ~DF; } } while (0)
+#define SET_BF(f) do { if (f) { SR |= BF; } else { SR &= ~BF; } } while (0)
+#define SET_OF(f) do { if (f) { SR |= OF; } else { SR &= ~OF; } } while (0)
+#define SET_SF(f) do { if (f) { SR |= SF; } else { SR &= ~SF; } } while (0)
+
+/* Special test and set macros. The meaning of the parameter depends on the
+ * actual flag that should be set or reset.
+ */
+#define TEST_ZF(v) SET_ZF (((v) & 0xFF) == 0)
+#define TEST_SF(v) SET_SF (((v) & 0x80) != 0)
+#define TEST_CF(v) SET_CF (((v) & 0xFF00) != 0)
/* Program counter halves */
#define PCL (PC & 0xFF)
unsigned Result = v1 - v2; \
TEST_ZF (Result & 0xFF); \
TEST_SF (Result); \
- TEST_CF (Result <= 0xFF); \
+ SET_CF (Result <= 0xFF); \
}
{
Cycles = 7;
PC += 2;
- SET_BF ();
+ SET_BF (1);
PUSH (PCH);
PUSH (PCL);
PUSH (SR);
- SET_IF ();
+ SET_IF (1);
PC = ReadMemW (0xFFFE);
}
static void OPC_6502_06 (void)
/* Opcode $06: ASL zp */
{
- NotImplemented ();
+ unsigned char ZPAddr;
+ unsigned Val;
+ Cycles = 5;
+ ZPAddr = ReadMem (PC+1);
+ Val = ReadMem (ZPAddr) << 1;
+ WriteMem (ZPAddr, (unsigned char) Val);
+ TEST_ZF (Val & 0xFF);
+ TEST_SF (Val);
+ SET_CF (Val & 0x100);
+ PC += 2;
}
static void OPC_6502_0A (void)
/* Opcode $0A: ASL a */
{
- NotImplemented ();
+ unsigned Val;
+ Cycles = 2;
+ Val = AC << 1;
+ AC = (unsigned char) Val;
+ TEST_ZF (Val & 0xFF);
+ TEST_SF (Val);
+ SET_CF (Val & 0x100);
+ PC += 1;
}
static void OPC_6502_0E (void)
/* Opcode $0E: ALS abs */
{
- NotImplemented ();
+ unsigned Addr;
+ unsigned Val;
+ Cycles = 6;
+ Addr = ReadMemW (PC+1);
+ Val = ReadMem (Addr) << 1;
+ WriteMem (Addr, (unsigned char) Val);
+ TEST_ZF (Val & 0xFF);
+ TEST_SF (Val);
+ SET_CF (Val & 0x100);
+ PC += 3;
}
static void OPC_6502_10 (void)
/* Opcode $10: BPL */
{
- BRANCH (!SF_IS_SET ());
+ BRANCH (!GET_SF ());
}
static void OPC_6502_16 (void)
/* Opcode $16: ASL zp,x */
{
- NotImplemented ();
+ unsigned char ZPAddr;
+ unsigned Val;
+ Cycles = 6;
+ ZPAddr = ReadMem (PC+1) + XR;
+ Val = ReadMem (ZPAddr) << 1;
+ WriteMem (ZPAddr, (unsigned char) Val);
+ TEST_ZF (Val & 0xFF);
+ TEST_SF (Val);
+ SET_CF (Val & 0x100);
+ PC += 2;
}
/* Opcode $18: CLC */
{
Cycles = 2;
- CLR_CF ();
+ SET_CF (0);
PC += 1;
}
static void OPC_6502_1E (void)
/* Opcode $1E: ASL abs,x */
{
- NotImplemented ();
+ unsigned Addr;
+ unsigned Val;
+ Cycles = 7;
+ Addr = ReadMemW (PC+1) + XR;
+ Val = ReadMem (Addr) << 1;
+ WriteMem (Addr, (unsigned char) Val);
+ TEST_ZF (Val & 0xFF);
+ TEST_SF (Val);
+ SET_CF (Val & 0x100);
+ PC += 3;
}
static void OPC_6502_20 (void)
/* Opcode $20: JSR */
{
- NotImplemented ();
+ unsigned Addr;
+ Cycles = 6;
+ Addr = ReadMemW (PC+1);
+ PC += 2;
+ PUSH (PCH);
+ PUSH (PCL);
+ PC = Addr;
}
static void OPC_6502_24 (void)
/* Opcode $24: BIT zp */
{
- NotImplemented ();
+ unsigned char ZPAddr;
+ unsigned char Val;
+ Cycles = 3;
+ ZPAddr = ReadMem (PC+1);
+ Val = ReadMem (ZPAddr);
+ SET_SF (Val & 0x80);
+ SET_OF (Val & 0x40);
+ SET_ZF ((Val & AC) == 0);
+ PC += 2;
}
static void OPC_6502_26 (void)
/* Opcode $26: ROL zp */
{
- NotImplemented ();
+ unsigned char ZPAddr;
+ unsigned Val;
+ Cycles = 5;
+ ZPAddr = ReadMem (PC+1);
+ Val = ReadMem (ZPAddr) << 1;
+ if (GET_CF ()) {
+ Val |= 0x01;
+ }
+ AC = (unsigned char) Val;
+ TEST_ZF (AC);
+ TEST_SF (AC);
+ TEST_CF (Val);
+ PC += 2;
}
static void OPC_6502_2A (void)
/* Opcode $2A: ROL a */
{
- NotImplemented ();
+ unsigned Val;
+ Cycles = 2;
+ Val = AC << 1;
+ if (GET_CF ()) {
+ Val |= 0x01;
+ }
+ AC = (unsigned char) Val;
+ TEST_ZF (AC);
+ TEST_SF (AC);
+ TEST_CF (Val);
+ PC += 1;
}
static void OPC_6502_2C (void)
/* Opcode $2C: BIT abs */
{
- NotImplemented ();
+ unsigned Addr;
+ unsigned char Val;
+ Cycles = 4;
+ Addr = ReadMem (PC+1);
+ Val = ReadMem (Addr);
+ SET_SF (Val & 0x80);
+ SET_OF (Val & 0x40);
+ SET_ZF ((Val & AC) == 0);
+ PC += 3;
}
static void OPC_6502_2E (void)
/* Opcode $2E: ROL abs */
{
- NotImplemented ();
+ unsigned Addr;
+ unsigned Val;
+ Cycles = 6;
+ Addr = ReadMemW (PC+1);
+ Val = ReadMem (Addr) << 1;
+ if (GET_CF ()) {
+ Val |= 0x01;
+ }
+ AC = (unsigned char) Val;
+ TEST_ZF (AC);
+ TEST_SF (AC);
+ TEST_CF (Val);
+ PC += 3;
}
static void OPC_6502_30 (void)
/* Opcode $30: BMI */
{
- BRANCH (SF_IS_SET ());
+ BRANCH (GET_SF ());
}
static void OPC_6502_36 (void)
/* Opcode $36: ROL zp,x */
{
- NotImplemented ();
+ unsigned char ZPAddr;
+ unsigned Val;
+ Cycles = 6;
+ ZPAddr = ReadMem (PC+1) + XR;
+ Val = ReadMem (ZPAddr) << 1;
+ if (GET_CF ()) {
+ Val |= 0x01;
+ }
+ AC = (unsigned char) Val;
+ TEST_ZF (AC);
+ TEST_SF (AC);
+ TEST_CF (Val);
+ PC += 2;
}
/* Opcode $38: SEC */
{
Cycles = 2;
- SET_CF ();
+ SET_CF (1);
PC += 1;
}
static void OPC_6502_3E (void)
/* Opcode $3E: ROL abs,x */
{
- NotImplemented ();
+ unsigned Addr;
+ unsigned Val;
+ Cycles = 7;
+ Addr = ReadMemW (PC+1) + XR;
+ Val = ReadMem (Addr) << 1;
+ if (GET_CF ()) {
+ Val |= 0x01;
+ }
+ AC = (unsigned char) Val;
+ TEST_ZF (AC);
+ TEST_SF (AC);
+ TEST_CF (Val);
+ PC += 2;
}
static void OPC_6502_46 (void)
/* Opcode $46: LSR zp */
{
- NotImplemented ();
+ unsigned char ZPAddr;
+ unsigned char Val;
+ Cycles = 5;
+ ZPAddr = ReadMem (PC+1);
+ Val = ReadMem (ZPAddr);
+ SET_CF (Val & 0x01);
+ Val >>= 1;
+ WriteMem (ZPAddr, Val);
+ TEST_ZF (Val);
+ TEST_SF (Val);
+ PC += 2;
}
static void OPC_6502_4A (void)
/* Opcode $4A: LSR a */
{
- NotImplemented ();
+ Cycles = 2;
+ SET_CF (AC & 0x01);
+ AC >>= 1;
+ TEST_ZF (AC);
+ TEST_SF (AC);
+ PC += 1;
}
static void OPC_6502_4E (void)
/* Opcode $4E: LSR abs */
{
- NotImplemented ();
+ unsigned Addr;
+ unsigned char Val;
+ Cycles = 6;
+ Addr = ReadMemW (PC+1);
+ Val = ReadMem (Addr);
+ SET_CF (Val & 0x01);
+ Val >>= 1;
+ WriteMem (Addr, Val);
+ TEST_ZF (Val);
+ TEST_SF (Val);
+ PC += 3;
}
static void OPC_6502_50 (void)
/* Opcode $50: BVC */
{
- BRANCH (!OF_IS_SET());
+ BRANCH (!GET_OF ());
}
static void OPC_6502_56 (void)
/* Opcode $56: LSR zp,x */
{
- NotImplemented ();
+ unsigned char ZPAddr;
+ unsigned char Val;
+ Cycles = 6;
+ ZPAddr = ReadMem (PC+1) + XR;
+ Val = ReadMem (ZPAddr);
+ SET_CF (Val & 0x01);
+ Val >>= 1;
+ WriteMem (ZPAddr, Val);
+ TEST_ZF (Val);
+ TEST_SF (Val);
+ PC += 2;
}
/* Opcode $58: CLI */
{
Cycles = 2;
- CLR_IF ();
+ SET_IF (0);
PC += 1;
}
static void OPC_6502_5E (void)
/* Opcode $5E: LSR abs,x */
{
- NotImplemented ();
+ unsigned Addr;
+ unsigned char Val;
+ Cycles = 7;
+ Addr = ReadMemW (PC+1) + XR;
+ Val = ReadMem (Addr);
+ SET_CF (Val & 0x01);
+ Val >>= 1;
+ WriteMem (Addr, Val);
+ TEST_ZF (Val);
+ TEST_SF (Val);
+ PC += 3;
}
static void OPC_6502_70 (void)
/* Opcode $70: BVS */
{
- BRANCH (OF_IS_SET ());
+ BRANCH (GET_OF ());
}
/* Opcode $78: SEI */
{
Cycles = 2;
- SET_IF ();
+ SET_IF (1);
PC += 1;
}
static void OPC_6502_90 (void)
/* Opcode $90: BCC */
{
- BRANCH (!CF_IS_SET ());
+ BRANCH (!GET_CF ());
}
static void OPC_6502_B0 (void)
/* Opcode $B0: BCS */
{
- BRANCH (CF_IS_SET ());
+ BRANCH (GET_CF ());
}
/* Opcode $B8: CLV */
{
Cycles = 2;
- CLR_OF ();
+ SET_OF (0);
PC += 1;
}
static void OPC_6502_D0 (void)
/* Opcode $D0: BNE */
{
- BRANCH (!ZF_IS_SET ());
+ BRANCH (!GET_ZF ());
}
static void OPC_6502_D8 (void)
/* Opcode $D8: CLD */
{
- CLR_DF ();
+ Cycles = 2;
+ SET_DF (0);
+ PC += 1;
}
static void OPC_6502_E1 (void)
-/* Opcode $E1 */
+/* Opcode $E1: SBC (zp,x) */
{
+ NotImplemented ();
}
static void OPC_6502_E5 (void)
-/* Opcode $E5 */
+/* Opcode $E5: SBC zp */
{
+ NotImplemented ();
}
static void OPC_6502_E9 (void)
-/* Opcode $E9 */
+/* Opcode $E9: SBC #imm */
{
+ NotImplemented ();
}
static void OPC_6502_ED (void)
-/* Opcode $ED */
+/* Opcode $ED: SBC abs */
{
+ NotImplemented ();
}
static void OPC_6502_F0 (void)
/* Opcode $F0: BEQ */
{
- BRANCH (ZF_IS_SET ());
+ BRANCH (GET_ZF ());
}
static void OPC_6502_F1 (void)
-/* Opcode $F1 */
+/* Opcode $F1: SBC (zp),y */
{
+ NotImplemented ();
}
static void OPC_6502_F5 (void)
-/* Opcode $F5 */
+/* Opcode $F5: SBC zp,x */
{
+ NotImplemented ();
}
static void OPC_6502_F8 (void)
/* Opcode $F8: SED */
{
- SET_DF ();
+ SET_DF (1);
}
static void OPC_6502_F9 (void)
-/* Opcode $F9 */
+/* Opcode $F9: SBC abs,y */
{
+ NotImplemented ();
}
static void OPC_6502_FD (void)
-/* Opcode $FD */
+/* Opcode $FD: SBC abs,x */
{
+ NotImplemented ();
}
/* Execute it */
OPCTable[B] ();
+
+ /* Count cycles */
+ TotalCycles += Cycles;
}
}