+#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include "cpu_65c02.h"
#define INLINE __attribute__((always_inline))
// convenient byte register access
-#define A (self->regs.b[CPU_65C02_REG_A])
-#define X (self->regs.b[CPU_65C02_REG_X])
-#define Y (self->regs.b[CPU_65C02_REG_Y])
-#define P (self->regs.b[CPU_65C02_REG_P])
-#define S (self->regs.b[CPU_65C02_REG_S])
+#define A (self->regs.byte.a)
+#define X (self->regs.byte.x)
+#define Y (self->regs.byte.y)
+#define P (self->regs.byte.p)
+#define S (self->regs.byte.s)
// convenient word register access
-#define SP (self->regs.w[CPU_65C02_REG_SP >> 1])
-#define PC (self->regs.w[CPU_65C02_REG_PC >> 1])
+#define SP (self->regs.word.sp)
+#define PC (self->regs.word.pc)
// convenient flags bit access
#define FLAG_C (1 << CPU_65C02_REG_P_BIT_C)
void (*write_byte)(int addr, int data)
) {
memset(self, 0, sizeof(struct cpu_65c02));
- self->regs.w[CPU_65C02_REG_PC >> 1] = pc;
- self->regs.b[CPU_65C02_REG_P] = 0x30;
- self->regs.w[CPU_65C02_REG_SP >> 1] = 0x1ff;
+ self->regs.byte.p = 0x30; // unused bits are hard coded to 1
+ self->regs.word.sp = 0x1ff; // unused byte is hard coded to 01
+ self->regs.word.pc = pc;
self->read_byte = read_byte;
self->write_byte = write_byte;
}
// memory (or internal register memory) access
INLINE int cpu_65c02_rb(struct cpu_65c02 *self, int addr) {
if (addr < 0)
- return self->regs.b[CPU_65C02_N_REGS + addr];
+ return self->regs.mem[CPU_65C02_N_REGS + addr];
self->cycles += 1;
return self->read_byte(addr & 0xffff);
}
INLINE void cpu_65c02_wb(struct cpu_65c02 *self, int addr, int data) {
self->cycles += 1;
if (addr < 0)
- self->regs.b[CPU_65C02_N_REGS + addr] = data;
+ self->regs.mem[CPU_65C02_N_REGS + addr] = data;
else
self->write_byte(addr, data);
}
// instruction execute
INLINE void cpu_65c02_adc(struct cpu_65c02 *self, int rvalue) {
int result0, result1, result2;
- if (P & FLAG_D) {
- result0 = (A & 0xf) + (rvalue & 0xf) + (P & FLAG_C);
+ if (self->regs.bit.df) {
+ result0 = (A & 0xf) + (rvalue & 0xf) + self->regs.bit.cf;
if (result0 >= 0xa)
- result0 += 6;
+ result0 = (result0 + 6) & 0x1f;
result0 += (A & 0x70) + (rvalue & 0x70);
result1 = (A & 0x80) + (rvalue & 0x80) + result0;
result2 = result1;
if (result2 >= 0xa0)
- result2 += 0x60;
+ result2 = (result2 + 0x60) & 0x1ff;
}
else {
- result0 = (A & 0x7f) + (rvalue & 0x7f) + (P & FLAG_C);
+ result0 = (A & 0x7f) + (rvalue & 0x7f) + self->regs.bit.cf;
result1 = (A & 0x80) + (rvalue & 0x80) + result0;
result2 = result1;
}
A = result2 & 0xff;
- P =
- (P & ~(FLAG_C | FLAG_Z | FLAG_V | FLAG_N)) |
- ((result2 >> 8) & FLAG_C) | // C
- (((result2 & 0xff) == 0) << 1) | // Z
- (((result0 >> 1) ^ (result1 >> 2)) & FLAG_V) |
- (result2 & FLAG_N);
+ self->regs.bit.cf = result2 >> 8;
+ self->regs.bit.zf = (result2 & 0xff) == 0;
+ self->regs.bit.vf = ((result0 >> 7) ^ (result1 >> 8)) & 1;
+ self->regs.bit.nf = (result2 >> 7) & 1;
}
INLINE void cpu_65c02_and(struct cpu_65c02 *self, int rvalue) {
int result = A & rvalue;
A = result;
- P =
- (P & ~(FLAG_Z | FLAG_N)) |
- ((result == 0) << 1) | // Z
- (result & FLAG_N);
+ self->regs.bit.zf = result == 0;
+ self->regs.bit.nf = (result >> 7) & 1;
}
INLINE void cpu_65c02_asl(struct cpu_65c02 *self, int lvalue) {
int result = RB(lvalue) << 1;
++self->cycles;
WB(lvalue, result & 0xff);
- P =
- (P & ~(FLAG_C | FLAG_Z | FLAG_N)) |
- (result >> 8) | // C
- (((result & 0xff) == 0) << 1) | // Z
- (result & FLAG_N);
+ self->regs.bit.cf = result >> 8;
+ self->regs.bit.zf = (result & 0xff) == 0;
+ self->regs.bit.nf = (result >> 7) & 1;
}
INLINE void cpu_65c02_bbr(struct cpu_65c02 *self, int rvalue, int lvalue) {
INLINE void cpu_65c02_bit(struct cpu_65c02 *self, int rvalue) {
int result = A & rvalue;
- P =
- (P & ~(FLAG_Z | FLAG_V | FLAG_N)) |
- ((result == 0) << 1) | // Z
- (rvalue & (FLAG_V | FLAG_N));
+ self->regs.bit.zf = result == 0;
+ self->regs.bit.vf = (rvalue >> 6) & 1;
+ self->regs.bit.nf = (rvalue >> 7) & 1;
}
INLINE void cpu_65c02_bit_imm(struct cpu_65c02 *self, int rvalue) {
int result = A & rvalue;
- P =
- (P & ~FLAG_Z) |
- ((result == 0) << 1); // Z
+ self->regs.bit.zf = result == 0;
}
INLINE void cpu_65c02_brk(struct cpu_65c02 *self) {
PHW((PC + 1) & 0xffff);
PHB(P); // already has break flag set
PC = RW(IRQ_VECTOR);
- P = (P & ~FLAG_D) | FLAG_I;
+ self->regs.bit._if = true;
+ self->regs.bit.df = false;
}
INLINE void cpu_65c02_cl(struct cpu_65c02 *self, int flag) {
INLINE void cpu_65c02_cmp(struct cpu_65c02 *self, int rvalue0, int rvalue1) {
rvalue1 ^= 0xff;
int result = rvalue0 + rvalue1 + 1;
- P =
- (P & ~(FLAG_C | FLAG_Z | FLAG_N)) |
- (result >> 8) | // C
- (((result & 0xff) == 0) << 1) | // Z
- (result & FLAG_N);
+ self->regs.bit.cf = result >> 8;
+ self->regs.bit.zf = (result & 0xff) == 0;
+ self->regs.bit.nf = (result >> 7) & 1;
}
INLINE void cpu_65c02_dec(struct cpu_65c02 *self, int lvalue) {
int result = (RB(lvalue) - 1) & 0xff;
++self->cycles;
WB(lvalue, result);
- P =
- (P & ~(FLAG_Z | FLAG_N)) |
- ((result == 0) << 1) | // Z
- (result & FLAG_N);
+ self->regs.bit.zf = result == 0;
+ self->regs.bit.nf = (result >> 7) & 1;
}
INLINE void cpu_65c02_eor(struct cpu_65c02 *self, int rvalue) {
int result = A ^ rvalue;
A = result;
- P =
- (P & ~(FLAG_Z | FLAG_N)) |
- ((result == 0) << 1) | // Z
- (result & FLAG_N);
+ self->regs.bit.zf = result == 0;
+ self->regs.bit.nf = (result >> 7) & 1;
}
INLINE void cpu_65c02_ill11(struct cpu_65c02 *self) {
int result = (RB(lvalue) + 1) & 0xff;
++self->cycles;
WB(lvalue, result);
- P =
- (P & ~(FLAG_Z | FLAG_N)) |
- ((result == 0) << 1) | // Z
- (result & FLAG_N);
+ self->regs.bit.zf = result == 0;
+ self->regs.bit.nf = (result >> 7) & 1;
}
INLINE void cpu_65c02_jmp(struct cpu_65c02 *self, int lvalue) {
INLINE void cpu_65c02_ld(struct cpu_65c02 *self, int lvalue, int rvalue) {
WB(lvalue, rvalue);
- P =
- (P & ~(FLAG_Z | FLAG_N)) |
- ((rvalue == 0) << 1) | // Z
- (rvalue & FLAG_N);
+ self->regs.bit.zf = rvalue == 0;
+ self->regs.bit.nf = (rvalue >> 7) & 1;
}
INLINE void cpu_65c02_lsr(struct cpu_65c02 *self, int lvalue) {
int result = RB(lvalue);
++self->cycles;
WB(lvalue, result >> 1);
- P =
- (P & ~(FLAG_C | FLAG_Z | FLAG_N)) |
- (result & FLAG_C) |
- (((result & 0xfe) == 0) << 1); // Z
+ self->regs.bit.cf = result & 1;
+ self->regs.bit.zf = (result & 0xfe) == 0;
+ self->regs.bit.nf = false;
}
INLINE void cpu_65c02_nop(struct cpu_65c02 *self) {
INLINE void cpu_65c02_ora(struct cpu_65c02 *self, int rvalue) {
int result = A | rvalue;
A = result;
- P =
- (P & ~(FLAG_Z | FLAG_N)) |
- ((result == 0) << 1) | // Z
- (result & FLAG_N);
+ self->regs.bit.zf = result == 0;
+ self->regs.bit.nf = (result >> 7) & 1;
}
INLINE void cpu_65c02_ph(struct cpu_65c02 *self, int rvalue) {
INLINE void cpu_65c02_pl(struct cpu_65c02 *self, int lvalue) {
int result = PLB();
WB(lvalue, result);
- P =
- (P & ~(FLAG_Z | FLAG_N)) |
- ((result == 0) << 1) | // Z
- (result & FLAG_N);
+ self->regs.bit.zf = result == 0;
+ self->regs.bit.nf = (result >> 7) & 1;
}
INLINE void cpu_65c02_plp(struct cpu_65c02 *self) {
}
INLINE void cpu_65c02_rol(struct cpu_65c02 *self, int lvalue) {
- int result = (RB(lvalue) << 1) | (P & FLAG_C);
+ int result = (RB(lvalue) << 1) | self->regs.bit.cf;
++self->cycles;
WB(lvalue, result & 0xff);
- P =
- (P & ~(FLAG_C | FLAG_Z | FLAG_N)) |
- (result >> 8) | // C
- (((result & 0xff) == 0) << 1) | // Z
- (result & FLAG_N);
+ self->regs.bit.cf = result >> 8;
+ self->regs.bit.zf = (result & 0xff) == 0;
+ self->regs.bit.nf = (result >> 7) & 1;
}
INLINE void cpu_65c02_ror(struct cpu_65c02 *self, int lvalue) {
- int result = RB(lvalue) | ((P & FLAG_C) << 8);
+ int result = RB(lvalue) | (self->regs.bit.cf << 8);
++self->cycles;
WB(lvalue, result >> 1);
- P =
- (P & ~(FLAG_C | FLAG_Z | FLAG_N)) |
- (result & FLAG_C) |
- (((result & 0x1fe) == 0) << 1) | // Z
- ((result >> 1) & FLAG_N);
+ self->regs.bit.cf = result & 1;
+ self->regs.bit.zf = (result & 0x1fe) == 0;
+ self->regs.bit.nf = (result >> 8) & 1;
}
INLINE void cpu_65c02_rti(struct cpu_65c02 *self) {
INLINE void cpu_65c02_sbc(struct cpu_65c02 *self, int rvalue) {
rvalue ^= 0xff;
int result0, result1, result2;
- if (P & FLAG_D) {
- result0 = (A & 0xf) + (rvalue & 0xf) + (P & FLAG_C);
+ if (self->regs.bit.df) {
+ result0 = (A & 0xf) + (rvalue & 0xf) + self->regs.bit.cf;
if (result0 < 0x10)
- result0 -= 6;
+ result0 = (result0 - 6) & 0x1f;
result0 += (A & 0x70) + (rvalue & 0x70);
result1 = (A & 0x80) + (rvalue & 0x80) + result0;
result2 = result1;
if (result2 < 0x100)
- result2 -= 0x60;
+ result2 = (result2 - 0x60) & 0x1ff;
}
else {
- result0 = (A & 0x7f) + (rvalue & 0x7f) + (P & FLAG_C);
+ result0 = (A & 0x7f) + (rvalue & 0x7f) + self->regs.bit.cf;
result1 = (A & 0x80) + (rvalue & 0x80) + result0;
result2 = result1;
}
A = result2 & 0xff;
- P =
- (P & ~(FLAG_C | FLAG_Z | FLAG_V | FLAG_N)) |
- ((result2 >> 8) & FLAG_C) | // C
- (((result2 & 0xff) == 0) << 1) | // Z
- (((result0 >> 1) ^ (result1 >> 2)) & FLAG_V) |
- (result2 & FLAG_N);
+ self->regs.bit.cf = result2 >> 8;
+ self->regs.bit.zf = (result2 & 0xff) == 0;
+ self->regs.bit.vf = ((result0 >> 7) ^ (result1 >> 8)) & 1;
+ self->regs.bit.nf = (result2 >> 7) & 1;
}
INLINE void cpu_65c02_se(struct cpu_65c02 *self, int flag) {
++self->cycles;
WB(lvalue, result & ~A);
result &= A;
- P =
- (P & ~FLAG_Z) |
- ((result == 0) << 1); // Z
+ self->regs.bit.zf = result == 0;
}
INLINE void cpu_65c02_tsb(struct cpu_65c02 *self, int lvalue) {
++self->cycles;
WB(lvalue, result | A);
result &= A;
- P =
- (P & ~FLAG_Z) |
- ((result == 0) << 1); // Z
+ self->regs.bit.zf = result == 0;
}
INLINE void cpu_65c02_wai(struct cpu_65c02 *self) {