#define ADC(rvalue) cpu_65c02_adc(self, (rvalue))
#define AND(rvalue) cpu_65c02_and(self, (rvalue))
#define ASL(lvalue) cpu_65c02_asl(self, (lvalue))
+#define BBR0(rvalue, lvalue) cpu_65c02_bbr(self, (rvalue) & 1, (lvalue))
+#define BBR1(rvalue, lvalue) cpu_65c02_bbr(self, (rvalue) & 2, (lvalue))
+#define BBR2(rvalue, lvalue) cpu_65c02_bbr(self, (rvalue) & 4, (lvalue))
+#define BBR3(rvalue, lvalue) cpu_65c02_bbr(self, (rvalue) & 8, (lvalue))
+#define BBR4(rvalue, lvalue) cpu_65c02_bbr(self, (rvalue) & 0x10, (lvalue))
+#define BBR5(rvalue, lvalue) cpu_65c02_bbr(self, (rvalue) & 0x20, (lvalue))
+#define BBR6(rvalue, lvalue) cpu_65c02_bbr(self, (rvalue) & 0x40, (lvalue))
+#define BBR7(rvalue, lvalue) cpu_65c02_bbr(self, (rvalue) & 0x80, (lvalue))
+#define BBS0(rvalue, lvalue) cpu_65c02_bbs(self, (rvalue) & 1, (lvalue))
+#define BBS1(rvalue, lvalue) cpu_65c02_bbs(self, (rvalue) & 2, (lvalue))
+#define BBS2(rvalue, lvalue) cpu_65c02_bbs(self, (rvalue) & 4, (lvalue))
+#define BBS3(rvalue, lvalue) cpu_65c02_bbs(self, (rvalue) & 8, (lvalue))
+#define BBS4(rvalue, lvalue) cpu_65c02_bbs(self, (rvalue) & 0x10, (lvalue))
+#define BBS5(rvalue, lvalue) cpu_65c02_bbs(self, (rvalue) & 0x20, (lvalue))
+#define BBS6(rvalue, lvalue) cpu_65c02_bbs(self, (rvalue) & 0x40, (lvalue))
+#define BBS7(rvalue, lvalue) cpu_65c02_bbs(self, (rvalue) & 0x80, (lvalue))
#define BCC(lvalue) cpu_65c02_bc(self, FLAG_C, (lvalue))
#define BCS(lvalue) cpu_65c02_bs(self, FLAG_C, (lvalue))
#define BEQ(lvalue) cpu_65c02_bs(self, FLAG_Z, (lvalue))
#define BIT(rvalue) cpu_65c02_bit(self, (rvalue))
+// BIT_IMM() is the same as BIT() but only affects the Z flag
+#define BIT_IMM(rvalue) cpu_65c02_bit_imm(self, (rvalue))
#define BMI(lvalue) cpu_65c02_bs(self, FLAG_N, (lvalue))
#define BNE(lvalue) cpu_65c02_bc(self, FLAG_Z, (lvalue))
#define BPL(lvalue) cpu_65c02_bc(self, FLAG_N, (lvalue))
#define DEX() cpu_65c02_dec(self, EA_X)
#define DEY() cpu_65c02_dec(self, EA_Y)
#define EOR(rvalue) cpu_65c02_eor(self, (rvalue))
-#define ILL() cpu_65c02_ill(self)
+// the illegal opcodes ILLmn() perform as m-byte, n-cycle nops
+#define ILL11() cpu_65c02_ill11(self)
+#define ILL22() cpu_65c02_ill22(self)
+#define ILL23() cpu_65c02_ill23(self)
+#define ILL24() cpu_65c02_ill24(self)
+#define ILL34() cpu_65c02_ill34(self)
+#define ILL38() cpu_65c02_ill38(self)
#define INC(lvalue) cpu_65c02_inc(self, (lvalue))
#define INX() cpu_65c02_inc(self, EA_X)
#define INY() cpu_65c02_inc(self, EA_Y)
#define SMB6(lvalue) cpu_65c02_smb(self, 0x40, (lvalue))
#define SMB7(lvalue) cpu_65c02_smb(self, 0x80, (lvalue))
#define STA(lvalue) cpu_65c02_st(self, A, (lvalue))
+#define STP() cpu_65c02_stp(self)
#define STX(lvalue) cpu_65c02_st(self, X, (lvalue))
#define STY(lvalue) cpu_65c02_st(self, Y, (lvalue))
#define STZ(lvalue) cpu_65c02_st(self, 0, (lvalue))
(result & FLAG_N);
}
+INLINE void cpu_65c02_bbr(struct cpu_65c02 *self, int rvalue, int lvalue) {
+ if (rvalue == 0)
+ PC = lvalue;
+}
+
+INLINE void cpu_65c02_bbs(struct cpu_65c02 *self, int rvalue, int lvalue) {
+ if (rvalue)
+ PC = lvalue;
+}
+
INLINE void cpu_65c02_bc(struct cpu_65c02 *self, int flag, int lvalue) {
if ((P & flag) == 0)
PC = lvalue;
(rvalue & (FLAG_V | FLAG_N));
}
+INLINE void cpu_65c02_bit_imm(struct cpu_65c02 *self, int rvalue) {
+ int result = A & rvalue;
+ P =
+ (P & ~FLAG_Z) |
+ ((result == 0) << 1); // Z
+}
+
INLINE void cpu_65c02_brk(struct cpu_65c02 *self) {
++self->cycles; // operand is ignored
PHW((PC + 1) & 0xffff);
(result & FLAG_N);
}
-INLINE void cpu_65c02_ill(struct cpu_65c02 *self) {
- abort();
+INLINE void cpu_65c02_ill11(struct cpu_65c02 *self) {
+}
+
+INLINE void cpu_65c02_ill22(struct cpu_65c02 *self) {
+ ++self->cycles;
+ PC = (PC + 1) & 0xffff;
+}
+
+INLINE void cpu_65c02_ill23(struct cpu_65c02 *self) {
+ self->cycles += 2;
+ PC = (PC + 1) & 0xffff;
+}
+
+INLINE void cpu_65c02_ill24(struct cpu_65c02 *self) {
+ self->cycles += 3;
+ PC = (PC + 1) & 0xffff;
+}
+
+INLINE void cpu_65c02_ill34(struct cpu_65c02 *self) {
+ self->cycles += 3;
+ PC = (PC + 2) & 0xffff;
+}
+
+INLINE void cpu_65c02_ill38(struct cpu_65c02 *self) {
+ self->cycles += 7;
+ PC = (PC + 2) & 0xffff;
}
INLINE void cpu_65c02_inc(struct cpu_65c02 *self, int lvalue) {
P = PLB() | 0x30;
}
-INLINE void cpu_65c02_rmb(struct cpu_65c02 *self, int n, int lvalue) {
- abort();
+INLINE void cpu_65c02_rmb(struct cpu_65c02 *self, int rvalue, int lvalue) {
+ int result = RB(lvalue) & ~rvalue;
+ ++self->cycles;
+ WB(lvalue, result);
}
INLINE void cpu_65c02_rol(struct cpu_65c02 *self, int lvalue) {
P |= flag;
}
-INLINE void cpu_65c02_smb(struct cpu_65c02 *self, int n, int lvalue) {
- abort();
+INLINE void cpu_65c02_smb(struct cpu_65c02 *self, int rvalue, int lvalue) {
+ int result = RB(lvalue) | rvalue;
+ ++self->cycles;
+ WB(lvalue, result);
}
INLINE void cpu_65c02_st(struct cpu_65c02 *self, int rvalue, int lvalue) {
WB(lvalue, rvalue);
}
-INLINE void cpu_65c02_trb(struct cpu_65c02 *self, int lvalue) {
+INLINE void cpu_65c02_stp(struct cpu_65c02 *self) {
abort();
}
+INLINE void cpu_65c02_trb(struct cpu_65c02 *self, int lvalue) {
+ int result = RB(lvalue);
+ ++self->cycles;
+ WB(lvalue, result & ~A);
+ result &= A;
+ P =
+ (P & ~FLAG_Z) |
+ ((result == 0) << 1); // Z
+}
+
INLINE void cpu_65c02_tsb(struct cpu_65c02 *self, int lvalue) {
- abort();
+ int result = RB(lvalue);
+ ++self->cycles;
+ WB(lvalue, result | A);
+ result &= A;
+ P =
+ (P & ~FLAG_Z) |
+ ((result == 0) << 1); // Z
}
INLINE void cpu_65c02_wai(struct cpu_65c02 *self) {
ORA(ZPG_IDX_IND(X));
break;
case 0x02:
- ILL();
+ ILL22();
break;
case 0x03:
- ILL();
+ ILL11();
break;
case 0x04:
TSB(EA_ZPG());
ASL(EA_A);
break;
case 0x0b:
- ILL();
+ ILL11();
break;
case 0x0c:
TSB(EA_ABS());
ASL(EA_ABS());
break;
case 0x0f:
- ILL();
+ {
+ int rvalue = ZPG();
+ BBR0(rvalue, EA_REL());
+ }
break;
case 0x10:
BPL(EA_REL());
ORA(ZPG_IND());
break;
case 0x13:
- ILL();
+ ILL11();
break;
case 0x14:
TRB(EA_ZPG());
INC(EA_A);
break;
case 0x1b:
- ILL();
+ ILL11();
break;
case 0x1c:
TRB(EA_ABS());
ASL(EA_ABS_IDX(X));
break;
case 0x1f:
- ILL();
+ {
+ int rvalue = ZPG();
+ BBR1(rvalue, EA_REL());
+ }
break;
case 0x20:
JSR(EA_ABS());
AND(ZPG_IDX_IND(X));
break;
case 0x22:
- ILL();
+ ILL22();
break;
case 0x23:
- ILL();
+ ILL11();
break;
case 0x24:
BIT(ZPG());
ROL(EA_A);
break;
case 0x2b:
- ILL();
+ ILL11();
break;
case 0x2c:
BIT(ABS());
ROL(EA_ABS());
break;
case 0x2f:
- ILL();
+ {
+ int rvalue = ZPG();
+ BBR2(rvalue, EA_REL());
+ }
break;
case 0x30:
BMI(EA_REL());
AND(ZPG_IND());
break;
case 0x33:
- ILL();
+ ILL11();
break;
case 0x34:
BIT(ZPG_IDX(X));
DEC(EA_A);
break;
case 0x3b:
- ILL();
+ ILL11();
break;
case 0x3c:
BIT(ABS_IDX(X));
ROL(EA_ABS_IDX(X));
break;
case 0x3f:
- ILL();
+ {
+ int rvalue = ZPG();
+ BBR3(rvalue, EA_REL());
+ }
break;
case 0x40:
RTI();
EOR(ZPG_IDX_IND(X));
break;
case 0x42:
- ILL();
+ ILL22();
break;
case 0x43:
- ILL();
+ ILL11();
break;
case 0x44:
- ILL();
+ ILL23();
break;
case 0x45:
EOR(ZPG());
LSR(EA_A);
break;
case 0x4b:
- ILL();
+ ILL11();
break;
case 0x4c:
JMP(EA_ABS());
LSR(EA_ABS());
break;
case 0x4f:
- ILL();
+ {
+ int rvalue = ZPG();
+ BBR4(rvalue, EA_REL());
+ }
break;
case 0x50:
BVC(EA_REL());
EOR(ZPG_IND());
break;
case 0x53:
- ILL();
+ ILL11();
break;
case 0x54:
- ILL();
+ ILL24();
break;
case 0x55:
EOR(ZPG_IDX(X));
PHY();
break;
case 0x5b:
- ILL();
+ ILL11();
break;
case 0x5c:
- ILL();
+ ILL38();
break;
case 0x5d:
EOR(ABS_IDX(X));
LSR(EA_ABS_IDX(X));
break;
case 0x5f:
- ILL();
+ {
+ int rvalue = ZPG();
+ BBR5(rvalue, EA_REL());
+ }
break;
case 0x60:
RTS();
ADC(ZPG_IDX_IND(X));
break;
case 0x62:
- ILL();
+ ILL22();
break;
case 0x63:
- ILL();
+ ILL11();
break;
case 0x64:
STZ(EA_ZPG());
ROR(EA_A);
break;
case 0x6b:
- ILL();
+ ILL11();
break;
case 0x6c:
JMP(EA_ABS_IND());
ROR(EA_ABS());
break;
case 0x6f:
- ILL();
+ {
+ int rvalue = ZPG();
+ BBR6(rvalue, EA_REL());
+ }
break;
case 0x70:
BVS(EA_REL());
ADC(ZPG_IND());
break;
case 0x73:
- ILL();
+ ILL11();
break;
case 0x74:
STZ(EA_ZPG_IDX(X));
PLY();
break;
case 0x7b:
- ILL();
+ ILL11();
break;
case 0x7c:
JMP(EA_ABS_IDX_IND(X));
ROR(EA_ABS_IDX(X));
break;
case 0x7f:
- ILL();
+ {
+ int rvalue = ZPG();
+ BBR7(rvalue, EA_REL());
+ }
break;
case 0x80:
BRA(EA_REL());
STA(EA_ZPG_IDX_IND(X));
break;
case 0x82:
- ILL();
+ ILL22();
break;
case 0x83:
- ILL();
+ ILL11();
break;
case 0x84:
STY(EA_ZPG());
DEY();
break;
case 0x89:
- BIT(IMM());
+ BIT_IMM(IMM());
break;
case 0x8a:
TXA();
break;
case 0x8b:
- ILL();
+ ILL11();
break;
case 0x8c:
STY(EA_ABS());
STX(EA_ABS());
break;
case 0x8f:
- ILL();
+ {
+ int rvalue = ZPG();
+ BBS0(rvalue, EA_REL());
+ }
break;
case 0x90:
BCC(EA_REL());
STA(EA_ZPG_IND());
break;
case 0x93:
- ILL();
+ ILL11();
break;
case 0x94:
STY(EA_ZPG_IDX(X));
TXS();
break;
case 0x9b:
- ILL();
+ ILL11();
break;
case 0x9c:
STZ(EA_ABS());
STZ(EA_ABS_IDX(X));
break;
case 0x9f:
- ILL();
+ {
+ int rvalue = ZPG();
+ BBS1(rvalue, EA_REL());
+ }
break;
case 0xa0:
LDY(IMM());
LDX(IMM());
break;
case 0xa3:
- ILL();
+ ILL11();
break;
case 0xa4:
LDY(ZPG());
TAX();
break;
case 0xab:
- ILL();
+ ILL11();
break;
case 0xac:
LDY(ABS());
LDX(ABS());
break;
case 0xaf:
- ILL();
+ {
+ int rvalue = ZPG();
+ BBS2(rvalue, EA_REL());
+ }
break;
case 0xb0:
BCS(EA_REL());
LDA(ZPG_IND());
break;
case 0xb3:
- ILL();
+ ILL11();
break;
case 0xb4:
LDY(ZPG_IDX(X));
TSX();
break;
case 0xbb:
- ILL();
+ ILL11();
break;
case 0xbc:
LDY(ABS_IDX(X));
LDX(ABS_IDX(Y));
break;
case 0xbf:
- ILL();
+ {
+ int rvalue = ZPG();
+ BBS3(rvalue, EA_REL());
+ }
break;
case 0xc0:
CPY(IMM());
CMP(ZPG_IDX_IND(X));
break;
case 0xc2:
- ILL();
+ ILL22();
break;
case 0xc3:
- ILL();
+ ILL11();
break;
case 0xc4:
CPY(ZPG());
DEC(EA_ABS());
break;
case 0xcf:
- ILL();
+ {
+ int rvalue = ZPG();
+ BBS4(rvalue, EA_REL());
+ }
break;
case 0xd0:
BNE(EA_REL());
CMP(ZPG_IND());
break;
case 0xd3:
- ILL();
+ ILL11();
break;
case 0xd4:
- ILL();
+ ILL24();
break;
case 0xd5:
CMP(ZPG_IDX(X));
PHX();
break;
case 0xdb:
- ILL();
+ ILL11();
break;
case 0xdc:
- ILL();
+ ILL34();
break;
case 0xdd:
CMP(ABS_IDX(X));
DEC(EA_ABS_IDX(X));
break;
case 0xdf:
- ILL();
+ {
+ int rvalue = ZPG();
+ BBS5(rvalue, EA_REL());
+ }
break;
case 0xe0:
CPX(IMM());
SBC(ZPG_IDX_IND(X));
break;
case 0xe2:
- ILL();
+ ILL22();
break;
case 0xe3:
- ILL();
+ ILL11();
break;
case 0xe4:
CPX(ZPG());
NOP();
break;
case 0xeb:
- ILL();
+ ILL11();
break;
case 0xec:
CPX(ABS());
INC(EA_ABS());
break;
case 0xef:
- ILL();
+ {
+ int rvalue = ZPG();
+ BBS6(rvalue, EA_REL());
+ }
break;
case 0xf0:
BEQ(EA_REL());
SBC(ZPG_IND());
break;
case 0xf3:
- ILL();
+ ILL11();
break;
case 0xf4:
- ILL();
+ ILL24();
break;
case 0xf5:
SBC(ZPG_IDX(X));
PLX();
break;
case 0xfb:
- ILL();
+ ILL11();
break;
case 0xfc:
- ILL();
+ ILL34();
break;
case 0xfd:
SBC(ABS_IDX(X));
INC(EA_ABS_IDX(X));
break;
case 0xff:
- ILL();
+ {
+ int rvalue = ZPG();
+ BBS7(rvalue, EA_REL());
+ }
break;
}
}