|
|
|
@@ -136,11 +136,11 @@ static inline e6502_Address adr_reg_y (e6502_Core* core) { |
|
|
|
} |
|
|
|
|
|
|
|
static inline e6502_Address adr_reg_s (e6502_Core* core) { |
|
|
|
return &core->registers.S; |
|
|
|
return &core->registers.P; |
|
|
|
} |
|
|
|
|
|
|
|
static inline e6502_Address adr_reg_sp (e6502_Core* core) { |
|
|
|
return &core->registers.SP; |
|
|
|
return &core->registers.S; |
|
|
|
} |
|
|
|
|
|
|
|
// Instructions |
|
|
|
@@ -151,53 +151,53 @@ static inline void nop(e6502_Core*, e6502_Address) { |
|
|
|
|
|
|
|
static inline void brk(e6502_Core *core, e6502_Address) { |
|
|
|
e6502_push16(core, core->registers.PC + 1); |
|
|
|
e6502_push8(core, core->registers.S | |
|
|
|
e6502_push8(core, core->registers.P | |
|
|
|
e6502_Status_1 | |
|
|
|
e6502_Status_B); |
|
|
|
core->registers.S |= e6502_Status_I; |
|
|
|
core->registers.P |= e6502_Status_I; |
|
|
|
core->registers.PC = e6502_r16(core, e6502_IRQ_Vec); |
|
|
|
} |
|
|
|
|
|
|
|
static inline void rti(e6502_Core *core, e6502_Address) { |
|
|
|
core->registers.S = e6502_pop8(core) & ~(e6502_Status_B); |
|
|
|
core->registers.P = e6502_pop8(core) & ~(e6502_Status_B); |
|
|
|
core->registers.PC = e6502_pop16(core); |
|
|
|
} |
|
|
|
|
|
|
|
static inline void ora(e6502_Core *core, e6502_Address adr) { |
|
|
|
core->registers.A |= e6502_adr_r8(core, adr); |
|
|
|
core->registers.S &= ~(e6502_Status_Z | e6502_Status_N); |
|
|
|
core->registers.S |= (core->registers.A & e6502_Status_N); |
|
|
|
if (!core->registers.A) core->registers.S |= e6502_Status_Z; |
|
|
|
core->registers.P &= ~(e6502_Status_Z | e6502_Status_N); |
|
|
|
core->registers.P |= (core->registers.A & e6502_Status_N); |
|
|
|
if (!core->registers.A) core->registers.P |= e6502_Status_Z; |
|
|
|
} |
|
|
|
|
|
|
|
static inline void eor(e6502_Core *core, e6502_Address adr) { |
|
|
|
core->registers.A ^= e6502_adr_r8(core, adr); |
|
|
|
core->registers.S &= ~(e6502_Status_Z | e6502_Status_N); |
|
|
|
core->registers.S |= (core->registers.A & e6502_Status_N); |
|
|
|
if (!core->registers.A) core->registers.S |= e6502_Status_Z; |
|
|
|
core->registers.P &= ~(e6502_Status_Z | e6502_Status_N); |
|
|
|
core->registers.P |= (core->registers.A & e6502_Status_N); |
|
|
|
if (!core->registers.A) core->registers.P |= e6502_Status_Z; |
|
|
|
} |
|
|
|
|
|
|
|
static inline void asl(e6502_Core *core, e6502_Address adr) { |
|
|
|
uint8_t val = e6502_adr_r8(core, adr); |
|
|
|
core->registers.S &= ~(e6502_Status_C | |
|
|
|
core->registers.P &= ~(e6502_Status_C | |
|
|
|
e6502_Status_Z | |
|
|
|
e6502_Status_N); |
|
|
|
if (val & 0x80) core->registers.S |= e6502_Status_C; |
|
|
|
if (val & 0x80) core->registers.P |= e6502_Status_C; |
|
|
|
val <<= 1; |
|
|
|
core->registers.S |= (val & e6502_Status_N); |
|
|
|
if (!val) core->registers.S |= e6502_Status_Z; |
|
|
|
core->registers.P |= (val & e6502_Status_N); |
|
|
|
if (!val) core->registers.P |= e6502_Status_Z; |
|
|
|
e6502_adr_w8(core, adr, val); |
|
|
|
} |
|
|
|
|
|
|
|
static inline void lsr(e6502_Core *core, e6502_Address adr) { |
|
|
|
uint8_t val = e6502_adr_r8(core, adr); |
|
|
|
core->registers.S &= ~(e6502_Status_C | |
|
|
|
core->registers.P &= ~(e6502_Status_C | |
|
|
|
e6502_Status_Z | |
|
|
|
e6502_Status_N); |
|
|
|
core->registers.S |= (val & e6502_Status_C); |
|
|
|
core->registers.P |= (val & e6502_Status_C); |
|
|
|
val >>= 1; |
|
|
|
core->registers.S |= (val & e6502_Status_N); |
|
|
|
if (!val) core->registers.S |= e6502_Status_Z; |
|
|
|
core->registers.P |= (val & e6502_Status_N); |
|
|
|
if (!val) core->registers.P |= e6502_Status_Z; |
|
|
|
e6502_adr_w8(core, adr, val); |
|
|
|
} |
|
|
|
|
|
|
|
@@ -205,13 +205,13 @@ static inline void rol(e6502_Core *core, e6502_Address adr) { |
|
|
|
uint8_t val = e6502_adr_r8(core, adr); |
|
|
|
uint8_t new_c = (val & 0x80) ? e6502_Status_C : 0; |
|
|
|
val <<= 1; |
|
|
|
val |= (core->registers.S & e6502_Status_C); |
|
|
|
core->registers.S &= ~(e6502_Status_C | |
|
|
|
val |= (core->registers.P & e6502_Status_C); |
|
|
|
core->registers.P &= ~(e6502_Status_C | |
|
|
|
e6502_Status_Z | |
|
|
|
e6502_Status_N); |
|
|
|
core->registers.S |= new_c; |
|
|
|
if (!val) core->registers.S |= e6502_Status_Z; |
|
|
|
core->registers.S |= (val & e6502_Status_N); |
|
|
|
core->registers.P |= new_c; |
|
|
|
if (!val) core->registers.P |= e6502_Status_Z; |
|
|
|
core->registers.P |= (val & e6502_Status_N); |
|
|
|
e6502_adr_w8(core, adr, val); |
|
|
|
} |
|
|
|
|
|
|
|
@@ -219,13 +219,13 @@ static inline void ror(e6502_Core *core, e6502_Address adr) { |
|
|
|
uint8_t val = e6502_adr_r8(core, adr); |
|
|
|
uint8_t new_c = (val & e6502_Status_C); |
|
|
|
val >>= 1; |
|
|
|
if (core->registers.S & e6502_Status_C) val |= e6502_Status_N; |
|
|
|
core->registers.S &= ~(e6502_Status_C | |
|
|
|
if (core->registers.P & e6502_Status_C) val |= e6502_Status_N; |
|
|
|
core->registers.P &= ~(e6502_Status_C | |
|
|
|
e6502_Status_Z | |
|
|
|
e6502_Status_N); |
|
|
|
core->registers.S |= new_c; |
|
|
|
if (!val) core->registers.S |= e6502_Status_Z; |
|
|
|
core->registers.S |= (val & e6502_Status_N); |
|
|
|
core->registers.P |= new_c; |
|
|
|
if (!val) core->registers.P |= e6502_Status_Z; |
|
|
|
core->registers.P |= (val & e6502_Status_N); |
|
|
|
e6502_adr_w8(core, adr, val); |
|
|
|
} |
|
|
|
|
|
|
|
@@ -234,20 +234,20 @@ static inline void pha(e6502_Core *core, e6502_Address adr) { |
|
|
|
} |
|
|
|
|
|
|
|
static inline void php(e6502_Core *core, e6502_Address adr) { |
|
|
|
e6502_push8(core, core->registers.S | |
|
|
|
e6502_push8(core, core->registers.P | |
|
|
|
e6502_Status_1 | |
|
|
|
e6502_Status_B); |
|
|
|
} |
|
|
|
|
|
|
|
static inline void pla(e6502_Core *core, e6502_Address adr) { |
|
|
|
core->registers.A = e6502_pop8(core); |
|
|
|
core->registers.S &= ~(e6502_Status_Z | e6502_Status_N); |
|
|
|
if (!core->registers.A) core->registers.S |= e6502_Status_Z; |
|
|
|
core->registers.S |= (core->registers.A & e6502_Status_N); |
|
|
|
core->registers.P &= ~(e6502_Status_Z | e6502_Status_N); |
|
|
|
if (!core->registers.A) core->registers.P |= e6502_Status_Z; |
|
|
|
core->registers.P |= (core->registers.A & e6502_Status_N); |
|
|
|
} |
|
|
|
|
|
|
|
static inline void plp(e6502_Core *core, e6502_Address adr) { |
|
|
|
core->registers.S = (e6502_pop8(core) | |
|
|
|
core->registers.P = (e6502_pop8(core) | |
|
|
|
e6502_Status_1 | |
|
|
|
e6502_Status_B); |
|
|
|
} |
|
|
|
@@ -261,79 +261,79 @@ static inline void b(e6502_Core *core, e6502_Address adr) { |
|
|
|
} |
|
|
|
|
|
|
|
static inline void bpl(e6502_Core *core, e6502_Address adr) { |
|
|
|
if (!(core->registers.S & e6502_Status_N)) { |
|
|
|
if (!(core->registers.P & e6502_Status_N)) { |
|
|
|
b(core, adr); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static inline void bmi(e6502_Core *core, e6502_Address adr) { |
|
|
|
if (core->registers.S & e6502_Status_N) { |
|
|
|
if (core->registers.P & e6502_Status_N) { |
|
|
|
b(core, adr); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static inline void bcc(e6502_Core *core, e6502_Address adr) { |
|
|
|
if (!(core->registers.S & e6502_Status_C)) { |
|
|
|
if (!(core->registers.P & e6502_Status_C)) { |
|
|
|
b(core, adr); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static inline void bcs(e6502_Core *core, e6502_Address adr) { |
|
|
|
if (core->registers.S & e6502_Status_C) { |
|
|
|
if (core->registers.P & e6502_Status_C) { |
|
|
|
b(core, adr); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static inline void bvc(e6502_Core *core, e6502_Address adr) { |
|
|
|
if (!(core->registers.S & e6502_Status_V)) { |
|
|
|
if (!(core->registers.P & e6502_Status_V)) { |
|
|
|
b(core, adr); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static inline void bvs(e6502_Core *core, e6502_Address adr) { |
|
|
|
if (core->registers.S & e6502_Status_V) { |
|
|
|
if (core->registers.P & e6502_Status_V) { |
|
|
|
b(core, adr); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static inline void bne(e6502_Core *core, e6502_Address adr) { |
|
|
|
if (!(core->registers.S & e6502_Status_Z)) { |
|
|
|
if (!(core->registers.P & e6502_Status_Z)) { |
|
|
|
b(core, adr); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static inline void beq(e6502_Core *core, e6502_Address adr) { |
|
|
|
if (core->registers.S & e6502_Status_Z) { |
|
|
|
if (core->registers.P & e6502_Status_Z) { |
|
|
|
b(core, adr); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static inline void clc(e6502_Core *core, e6502_Address) { |
|
|
|
core->registers.S &= ~e6502_Status_C; |
|
|
|
core->registers.P &= ~e6502_Status_C; |
|
|
|
} |
|
|
|
|
|
|
|
static inline void cli(e6502_Core *core, e6502_Address) { |
|
|
|
core->registers.S &= ~e6502_Status_I; |
|
|
|
core->registers.P &= ~e6502_Status_I; |
|
|
|
} |
|
|
|
|
|
|
|
static inline void cld(e6502_Core *core, e6502_Address) { |
|
|
|
core->registers.S &= ~e6502_Status_D; |
|
|
|
core->registers.P &= ~e6502_Status_D; |
|
|
|
} |
|
|
|
|
|
|
|
static inline void clv(e6502_Core *core, e6502_Address) { |
|
|
|
core->registers.S &= ~e6502_Status_V; |
|
|
|
core->registers.P &= ~e6502_Status_V; |
|
|
|
} |
|
|
|
|
|
|
|
static inline void sec(e6502_Core *core, e6502_Address) { |
|
|
|
core->registers.S |= e6502_Status_C; |
|
|
|
core->registers.P |= e6502_Status_C; |
|
|
|
} |
|
|
|
|
|
|
|
static inline void sei(e6502_Core *core, e6502_Address) { |
|
|
|
core->registers.S |= e6502_Status_I; |
|
|
|
core->registers.P |= e6502_Status_I; |
|
|
|
} |
|
|
|
|
|
|
|
static inline void sed(e6502_Core *core, e6502_Address) { |
|
|
|
core->registers.S |= e6502_Status_D; |
|
|
|
core->registers.P |= e6502_Status_D; |
|
|
|
} |
|
|
|
|
|
|
|
static inline void jsr(e6502_Core *core, e6502_Address adr) { |
|
|
|
@@ -351,13 +351,13 @@ static inline void jmp(e6502_Core *core, e6502_Address adr) { |
|
|
|
|
|
|
|
static inline void bit(e6502_Core *core, e6502_Address adr) { |
|
|
|
uint8_t val = e6502_adr_r8(core, adr); |
|
|
|
core->registers.S &= ~(e6502_Status_Z | |
|
|
|
core->registers.P &= ~(e6502_Status_Z | |
|
|
|
e6502_Status_V | |
|
|
|
e6502_Status_N); |
|
|
|
core->registers.S |= (val & (e6502_Status_V | |
|
|
|
core->registers.P |= (val & (e6502_Status_V | |
|
|
|
e6502_Status_N)); |
|
|
|
if (!(val & core->registers.A)) { |
|
|
|
core->registers.S |= e6502_Status_Z; |
|
|
|
core->registers.P |= e6502_Status_Z; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@@ -366,12 +366,12 @@ static inline void cmp(e6502_Core *core, |
|
|
|
uint8_t minuend) { |
|
|
|
uint8_t val = e6502_adr_r8(core, adr); |
|
|
|
uint8_t diff = minuend - val; |
|
|
|
core->registers.S &= ~(e6502_Status_C | |
|
|
|
core->registers.P &= ~(e6502_Status_C | |
|
|
|
e6502_Status_Z | |
|
|
|
e6502_Status_N); |
|
|
|
if (minuend >= val) core->registers.S |= e6502_Status_C; |
|
|
|
if (diff == 0) core->registers.S |= e6502_Status_Z; |
|
|
|
core->registers.S |= (diff & e6502_Status_N); |
|
|
|
if (minuend >= val) core->registers.P |= e6502_Status_C; |
|
|
|
if (diff == 0) core->registers.P |= e6502_Status_Z; |
|
|
|
core->registers.P |= (diff & e6502_Status_N); |
|
|
|
} |
|
|
|
|
|
|
|
static inline void cpa(e6502_Core *core, e6502_Address adr) { |
|
|
|
@@ -388,25 +388,25 @@ static inline void cpy(e6502_Core *core, e6502_Address adr) { |
|
|
|
|
|
|
|
static inline void and(e6502_Core *core, e6502_Address adr) { |
|
|
|
core->registers.A &= e6502_adr_r8(core, adr); |
|
|
|
core->registers.S &= ~(e6502_Status_Z | e6502_Status_N); |
|
|
|
core->registers.S |= (core->registers.A & e6502_Status_N); |
|
|
|
if (!core->registers.A) core->registers.S |= e6502_Status_Z; |
|
|
|
core->registers.P &= ~(e6502_Status_Z | e6502_Status_N); |
|
|
|
core->registers.P |= (core->registers.A & e6502_Status_N); |
|
|
|
if (!core->registers.A) core->registers.P |= e6502_Status_Z; |
|
|
|
} |
|
|
|
|
|
|
|
static inline void adc(e6502_Core *core, e6502_Address adr) { |
|
|
|
uint8_t addend = e6502_adr_r8(core, adr); |
|
|
|
uint32_t sum = core->registers.A + |
|
|
|
addend + |
|
|
|
(core->registers.S & e6502_Status_C); |
|
|
|
core->registers.S &= ~(e6502_Status_C | e6502_Status_Z | |
|
|
|
(core->registers.P & e6502_Status_C); |
|
|
|
core->registers.P &= ~(e6502_Status_C | e6502_Status_Z | |
|
|
|
e6502_Status_V | e6502_Status_N); |
|
|
|
if (sum > 0xFF) core->registers.S |= e6502_Status_C; |
|
|
|
if (!(uint8_t)sum) core->registers.S |= e6502_Status_Z; |
|
|
|
if (sum > 0xFF) core->registers.P |= e6502_Status_C; |
|
|
|
if (!(uint8_t)sum) core->registers.P |= e6502_Status_Z; |
|
|
|
if ( (addend & 0x80) == (core->registers.A & 0x80) && |
|
|
|
(sum & 0x80) != (addend & 0x80)) { |
|
|
|
core->registers.S |= e6502_Status_V; |
|
|
|
core->registers.P |= e6502_Status_V; |
|
|
|
} |
|
|
|
core->registers.S |= (sum & e6502_Status_N); |
|
|
|
core->registers.P |= (sum & e6502_Status_N); |
|
|
|
core->registers.A = sum; |
|
|
|
} |
|
|
|
|
|
|
|
@@ -414,32 +414,32 @@ static inline void sbc(e6502_Core *core, e6502_Address adr) { |
|
|
|
uint8_t addend = e6502_adr_r8(core, adr); |
|
|
|
uint32_t sum = core->registers.A - |
|
|
|
addend - |
|
|
|
(1 - (core->registers.S & e6502_Status_C)); |
|
|
|
core->registers.S &= ~(e6502_Status_C | e6502_Status_Z | |
|
|
|
(1 - (core->registers.P & e6502_Status_C)); |
|
|
|
core->registers.P &= ~(e6502_Status_C | e6502_Status_Z | |
|
|
|
e6502_Status_V | e6502_Status_N); |
|
|
|
if (sum < 0x100) core->registers.S |= e6502_Status_C; |
|
|
|
if (!(uint8_t)sum) core->registers.S |= e6502_Status_Z; |
|
|
|
if (sum < 0x100) core->registers.P |= e6502_Status_C; |
|
|
|
if (!(uint8_t)sum) core->registers.P |= e6502_Status_Z; |
|
|
|
if ( (sum & 0x80) != (core->registers.A & 0x80) && |
|
|
|
(addend & 0x80) != (core->registers.A & 0x80)) { |
|
|
|
core->registers.S |= e6502_Status_V; |
|
|
|
core->registers.P |= e6502_Status_V; |
|
|
|
} |
|
|
|
core->registers.S |= (sum & e6502_Status_N); |
|
|
|
core->registers.P |= (sum & e6502_Status_N); |
|
|
|
core->registers.A = sum; |
|
|
|
} |
|
|
|
|
|
|
|
static inline void inc(e6502_Core *core, e6502_Address adr) { |
|
|
|
uint8_t val = e6502_adr_r8(core, adr) + 1; |
|
|
|
core->registers.S &= ~(e6502_Status_Z | e6502_Status_N); |
|
|
|
core->registers.S |= (val & e6502_Status_N); |
|
|
|
if (!val) core->registers.S |= e6502_Status_Z; |
|
|
|
core->registers.P &= ~(e6502_Status_Z | e6502_Status_N); |
|
|
|
core->registers.P |= (val & e6502_Status_N); |
|
|
|
if (!val) core->registers.P |= e6502_Status_Z; |
|
|
|
e6502_adr_w8(core, adr, val); |
|
|
|
} |
|
|
|
|
|
|
|
static inline void dec(e6502_Core *core, e6502_Address adr) { |
|
|
|
uint8_t val = e6502_adr_r8(core, adr) - 1; |
|
|
|
core->registers.S &= ~(e6502_Status_Z | e6502_Status_N); |
|
|
|
core->registers.S |= (val & e6502_Status_N); |
|
|
|
if (!val) core->registers.S |= e6502_Status_Z; |
|
|
|
core->registers.P &= ~(e6502_Status_Z | e6502_Status_N); |
|
|
|
core->registers.P |= (val & e6502_Status_N); |
|
|
|
if (!val) core->registers.P |= e6502_Status_Z; |
|
|
|
e6502_adr_w8(core, adr, val); |
|
|
|
} |
|
|
|
|
|
|
|
@@ -458,9 +458,9 @@ static inline void sty(e6502_Core *core, e6502_Address adr) { |
|
|
|
static inline void t(e6502_Core *core, |
|
|
|
e6502_Address adr, |
|
|
|
uint8_t reg) { |
|
|
|
core->registers.S &= ~(e6502_Status_Z | e6502_Status_N); |
|
|
|
core->registers.S |= (reg & e6502_Status_N); |
|
|
|
if (!reg) core->registers.S |= e6502_Status_Z; |
|
|
|
core->registers.P &= ~(e6502_Status_Z | e6502_Status_N); |
|
|
|
core->registers.P |= (reg & e6502_Status_N); |
|
|
|
if (!reg) core->registers.P |= e6502_Status_Z; |
|
|
|
e6502_adr_w8(core, adr, reg); |
|
|
|
} |
|
|
|
|
|
|
|
@@ -469,7 +469,7 @@ static inline void ta(e6502_Core *core, e6502_Address adr) { |
|
|
|
} |
|
|
|
|
|
|
|
static inline void txs(e6502_Core *core, e6502_Address adr) { |
|
|
|
core->registers.SP = core->registers.X; |
|
|
|
core->registers.S = core->registers.X; |
|
|
|
} |
|
|
|
|
|
|
|
static inline void txa(e6502_Core *core, e6502_Address adr) { |
|
|
|
@@ -481,7 +481,7 @@ static inline void ty(e6502_Core *core, e6502_Address adr) { |
|
|
|
} |
|
|
|
|
|
|
|
static inline void ts(e6502_Core *core, e6502_Address adr) { |
|
|
|
t(core, adr, core->registers.SP); |
|
|
|
t(core, adr, core->registers.S); |
|
|
|
} |
|
|
|
|
|
|
|
static inline void lda(e6502_Core *core, e6502_Address adr) { |
|
|
|
@@ -779,9 +779,9 @@ int e6502_dump_instr(e6502_Core* core, e6502_Mem_Addr addr, |
|
|
|
|
|
|
|
int e6502_dump_regs(e6502_Core* core, FILE* file) { |
|
|
|
fprintf(file, "S:%02x A:%02x X:%02x Y:%02x P:%02x\n", |
|
|
|
core->registers.SP, core->registers.A, |
|
|
|
core->registers.S, core->registers.A, |
|
|
|
core->registers.X, core->registers.Y, |
|
|
|
core->registers.S); |
|
|
|
core->registers.P); |
|
|
|
} |
|
|
|
*/ |
|
|
|
|
|
|
|
@@ -837,6 +837,6 @@ int e6502_run(e6502_Core* core, |
|
|
|
|
|
|
|
int e6502_reset(e6502_Core* core) { |
|
|
|
core->registers.PC = e6502_r16(core, e6502_Reset_Vec); |
|
|
|
core->registers.SP -= 3; |
|
|
|
core->registers.S |= (e6502_Status_B | e6502_Status_1); |
|
|
|
core->registers.S -= 3; |
|
|
|
core->registers.P |= (e6502_Status_B | e6502_Status_1); |
|
|
|
} |