Updated CPU Module
This commit is contained in:
parent
7a668f2462
commit
b1ec2bd4e4
218
src/cpu.c
218
src/cpu.c
@ -12,14 +12,6 @@ extern uint8_t read6502(uint16_t address);
|
||||
extern void write6502(uint16_t address, uint8_t value);
|
||||
|
||||
//6502 defines
|
||||
#define UNDOCUMENTED //when this is defined, undocumented opcodes are handled.
|
||||
//otherwise, they're simply treated as NOPs.
|
||||
|
||||
//#define NES_CPU //when this is defined, the binary-coded decimal (BCD)
|
||||
//status flag is not honored by ADC and SBC. the 2A03
|
||||
//CPU in the Nintendo Entertainment System does not
|
||||
//support BCD operation.
|
||||
|
||||
#define FLAG_CARRY 0x01
|
||||
#define FLAG_ZERO 0x02
|
||||
#define FLAG_INTERRUPT 0x04
|
||||
@ -35,18 +27,18 @@ extern void write6502(uint16_t address, uint8_t value);
|
||||
|
||||
|
||||
//flag modifier macros
|
||||
#define setcarry() status |= FLAG_CARRY
|
||||
#define clearcarry() status &= (~FLAG_CARRY)
|
||||
#define setzero() status |= FLAG_ZERO
|
||||
#define clearzero() status &= (~FLAG_ZERO)
|
||||
#define setinterrupt() status |= FLAG_INTERRUPT
|
||||
#define clearinterrupt() status &= (~FLAG_INTERRUPT)
|
||||
#define setdecimal() status |= FLAG_DECIMAL
|
||||
#define cleardecimal() status &= (~FLAG_DECIMAL)
|
||||
#define setoverflow() status |= FLAG_OVERFLOW
|
||||
#define clearoverflow() status &= (~FLAG_OVERFLOW)
|
||||
#define setsign() status |= FLAG_SIGN
|
||||
#define clearsign() status &= (~FLAG_SIGN)
|
||||
#define setcarry() status |= FLAG_CARRY
|
||||
#define clearcarry() status &= (~FLAG_CARRY)
|
||||
#define setzero() status |= FLAG_ZERO
|
||||
#define clearzero() status &= (~FLAG_ZERO)
|
||||
#define setinterrupt() status |= FLAG_INTERRUPT
|
||||
#define clearinterrupt() status &= (~FLAG_INTERRUPT)
|
||||
#define setdecimal() status |= FLAG_DECIMAL
|
||||
#define cleardecimal() status &= (~FLAG_DECIMAL)
|
||||
#define setoverflow() status |= FLAG_OVERFLOW
|
||||
#define clearoverflow() status &= (~FLAG_OVERFLOW)
|
||||
#define setsign() status |= FLAG_SIGN
|
||||
#define clearsign() status &= (~FLAG_SIGN)
|
||||
|
||||
|
||||
//flag calculation macros
|
||||
@ -77,10 +69,17 @@ uint8_t sp, a, x, y, status = FLAG_CONSTANT;
|
||||
|
||||
|
||||
//helper variables
|
||||
uint64_t instructions = 0; //keep track of total instructions executed
|
||||
uint32_t clockticks6502 = 0, clockgoal6502 = 0;
|
||||
uint16_t oldpc, ea, reladdr, value, result;
|
||||
uint8_t opcode, oldstatus;
|
||||
uint32_t clockticks6502 = 0;
|
||||
uint32_t clockgoal6502 = 0;
|
||||
|
||||
uint16_t oldpc;
|
||||
uint16_t ea;
|
||||
uint16_t reladdr;
|
||||
uint16_t value;
|
||||
uint16_t result;
|
||||
|
||||
uint8_t opcode;
|
||||
uint8_t oldstatus;
|
||||
|
||||
//a few general functions used by various other functions
|
||||
void push16(uint16_t pushval) {
|
||||
@ -157,7 +156,7 @@ static void absx() { //absolute,X
|
||||
startpage = ea & 0xFF00;
|
||||
ea += (uint16_t)x;
|
||||
|
||||
if (startpage != (ea & 0xFF00)) { //one cycle penlty for page-crossing on some opcodes
|
||||
if (startpage != (ea & 0xFF00)) { //one cycle penalty for page-crossing on some opcodes
|
||||
penaltyaddr = 1;
|
||||
}
|
||||
|
||||
@ -206,12 +205,12 @@ static void indy() { // (indirect),Y
|
||||
|
||||
static uint16_t getvalue() {
|
||||
if (addrtable[opcode] == acc) return((uint16_t)a);
|
||||
else return((uint16_t)read6502(ea));
|
||||
else return((uint16_t)read6502(ea));
|
||||
}
|
||||
|
||||
static void putvalue(uint16_t saveval) {
|
||||
if (addrtable[opcode] == acc) a = (uint8_t)(saveval & 0x00FF);
|
||||
else write6502(ea, (saveval & 0x00FF));
|
||||
else write6502(ea, (saveval & 0x00FF));
|
||||
}
|
||||
|
||||
|
||||
@ -226,22 +225,6 @@ static void adc() {
|
||||
overflowcalc(result, a, value);
|
||||
signcalc(result);
|
||||
|
||||
#ifndef NES_CPU
|
||||
if (status & FLAG_DECIMAL) {
|
||||
clearcarry();
|
||||
|
||||
if ((a & 0x0F) > 0x09) {
|
||||
a += 0x06;
|
||||
}
|
||||
if ((a & 0xF0) > 0x90) {
|
||||
a += 0x60;
|
||||
setcarry();
|
||||
}
|
||||
|
||||
clockticks6502++;
|
||||
}
|
||||
#endif
|
||||
|
||||
saveaccum(result);
|
||||
}
|
||||
|
||||
@ -272,7 +255,7 @@ static void bcc() {
|
||||
oldpc = pc;
|
||||
pc += reladdr;
|
||||
if ((oldpc & 0xFF00) != (pc & 0xFF00)) clockticks6502 += 2; //check if jump crossed a page boundary
|
||||
else clockticks6502++;
|
||||
else clockticks6502++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -281,7 +264,7 @@ static void bcs() {
|
||||
oldpc = pc;
|
||||
pc += reladdr;
|
||||
if ((oldpc & 0xFF00) != (pc & 0xFF00)) clockticks6502 += 2; //check if jump crossed a page boundary
|
||||
else clockticks6502++;
|
||||
else clockticks6502++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -290,7 +273,7 @@ static void beq() {
|
||||
oldpc = pc;
|
||||
pc += reladdr;
|
||||
if ((oldpc & 0xFF00) != (pc & 0xFF00)) clockticks6502 += 2; //check if jump crossed a page boundary
|
||||
else clockticks6502++;
|
||||
else clockticks6502++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -307,7 +290,7 @@ static void bmi() {
|
||||
oldpc = pc;
|
||||
pc += reladdr;
|
||||
if ((oldpc & 0xFF00) != (pc & 0xFF00)) clockticks6502 += 2; //check if jump crossed a page boundary
|
||||
else clockticks6502++;
|
||||
else clockticks6502++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -316,7 +299,7 @@ static void bne() {
|
||||
oldpc = pc;
|
||||
pc += reladdr;
|
||||
if ((oldpc & 0xFF00) != (pc & 0xFF00)) clockticks6502 += 2; //check if jump crossed a page boundary
|
||||
else clockticks6502++;
|
||||
else clockticks6502++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -325,7 +308,7 @@ static void bpl() {
|
||||
oldpc = pc;
|
||||
pc += reladdr;
|
||||
if ((oldpc & 0xFF00) != (pc & 0xFF00)) clockticks6502 += 2; //check if jump crossed a page boundary
|
||||
else clockticks6502++;
|
||||
else clockticks6502++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -342,7 +325,7 @@ static void bvc() {
|
||||
oldpc = pc;
|
||||
pc += reladdr;
|
||||
if ((oldpc & 0xFF00) != (pc & 0xFF00)) clockticks6502 += 2; //check if jump crossed a page boundary
|
||||
else clockticks6502++;
|
||||
else clockticks6502++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -351,7 +334,7 @@ static void bvs() {
|
||||
oldpc = pc;
|
||||
pc += reladdr;
|
||||
if ((oldpc & 0xFF00) != (pc & 0xFF00)) clockticks6502 += 2; //check if jump crossed a page boundary
|
||||
else clockticks6502++;
|
||||
else clockticks6502++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -377,9 +360,9 @@ static void cmp() {
|
||||
result = (uint16_t)a - value;
|
||||
|
||||
if (a >= (uint8_t)(value & 0x00FF)) setcarry();
|
||||
else clearcarry();
|
||||
else clearcarry();
|
||||
if (a == (uint8_t)(value & 0x00FF)) setzero();
|
||||
else clearzero();
|
||||
else clearzero();
|
||||
signcalc(result);
|
||||
}
|
||||
|
||||
@ -388,9 +371,9 @@ static void cpx() {
|
||||
result = (uint16_t)x - value;
|
||||
|
||||
if (x >= (uint8_t)(value & 0x00FF)) setcarry();
|
||||
else clearcarry();
|
||||
else clearcarry();
|
||||
if (x == (uint8_t)(value & 0x00FF)) setzero();
|
||||
else clearzero();
|
||||
else clearzero();
|
||||
signcalc(result);
|
||||
}
|
||||
|
||||
@ -399,9 +382,9 @@ static void cpy() {
|
||||
result = (uint16_t)y - value;
|
||||
|
||||
if (y >= (uint8_t)(value & 0x00FF)) setcarry();
|
||||
else clearcarry();
|
||||
else clearcarry();
|
||||
if (y == (uint8_t)(value & 0x00FF)) setzero();
|
||||
else clearzero();
|
||||
else clearzero();
|
||||
signcalc(result);
|
||||
}
|
||||
|
||||
@ -505,7 +488,7 @@ static void lsr() {
|
||||
result = value >> 1;
|
||||
|
||||
if (value & 1) setcarry();
|
||||
else clearcarry();
|
||||
else clearcarry();
|
||||
zerocalc(result);
|
||||
signcalc(result);
|
||||
|
||||
@ -571,7 +554,8 @@ static void ror() {
|
||||
result = (value >> 1) | ((status & FLAG_CARRY) << 7);
|
||||
|
||||
if (value & 1) setcarry();
|
||||
else clearcarry();
|
||||
else clearcarry();
|
||||
|
||||
zerocalc(result);
|
||||
signcalc(result);
|
||||
|
||||
@ -599,23 +583,6 @@ static void sbc() {
|
||||
overflowcalc(result, a, value);
|
||||
signcalc(result);
|
||||
|
||||
#ifndef NES_CPU
|
||||
if (status & FLAG_DECIMAL) {
|
||||
clearcarry();
|
||||
|
||||
a -= 0x66;
|
||||
if ((a & 0x0F) > 0x09) {
|
||||
a += 0x06;
|
||||
}
|
||||
if ((a & 0xF0) > 0x90) {
|
||||
a += 0x60;
|
||||
setcarry();
|
||||
}
|
||||
|
||||
clockticks6502++;
|
||||
}
|
||||
#endif
|
||||
|
||||
saveaccum(result);
|
||||
}
|
||||
|
||||
@ -682,67 +649,6 @@ static void tya() {
|
||||
signcalc(a);
|
||||
}
|
||||
|
||||
//undocumented instructions
|
||||
#ifdef UNDOCUMENTED
|
||||
static void lax() {
|
||||
lda();
|
||||
ldx();
|
||||
}
|
||||
|
||||
static void sax() {
|
||||
sta();
|
||||
stx();
|
||||
putvalue(a & x);
|
||||
if (penaltyop && penaltyaddr) clockticks6502--;
|
||||
}
|
||||
|
||||
static void dcp() {
|
||||
dec();
|
||||
cmp();
|
||||
if (penaltyop && penaltyaddr) clockticks6502--;
|
||||
}
|
||||
|
||||
static void isb() {
|
||||
inc();
|
||||
sbc();
|
||||
if (penaltyop && penaltyaddr) clockticks6502--;
|
||||
}
|
||||
|
||||
static void slo() {
|
||||
asl();
|
||||
ora();
|
||||
if (penaltyop && penaltyaddr) clockticks6502--;
|
||||
}
|
||||
|
||||
static void rla() {
|
||||
rol();
|
||||
and();
|
||||
if (penaltyop && penaltyaddr) clockticks6502--;
|
||||
}
|
||||
|
||||
static void sre() {
|
||||
lsr();
|
||||
eor();
|
||||
if (penaltyop && penaltyaddr) clockticks6502--;
|
||||
}
|
||||
|
||||
static void rra() {
|
||||
ror();
|
||||
adc();
|
||||
if (penaltyop && penaltyaddr) clockticks6502--;
|
||||
}
|
||||
#else
|
||||
#define lax nop
|
||||
#define sax nop
|
||||
#define dcp nop
|
||||
#define isb nop
|
||||
#define slo nop
|
||||
#define rla nop
|
||||
#define sre nop
|
||||
#define rra nop
|
||||
#endif
|
||||
|
||||
|
||||
static void (*addrtable[256])() = {
|
||||
/* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | */
|
||||
/* 0 */ imp, indx, imp, indx, zp, zp, zp, zp, imp, imm, acc, imm, abso, abso, abso, abso, /* 0 */
|
||||
@ -765,22 +671,22 @@ static void (*addrtable[256])() = {
|
||||
|
||||
static void (*optable[256])() = {
|
||||
/* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | */
|
||||
/* 0 */ brk, ora, nop, slo, nop, ora, asl, slo, php, ora, asl, nop, nop, ora, asl, slo, /* 0 */
|
||||
/* 1 */ bpl, ora, nop, slo, nop, ora, asl, slo, clc, ora, nop, slo, nop, ora, asl, slo, /* 1 */
|
||||
/* 2 */ jsr, and, nop, rla, bit, and, rol, rla, plp, and, rol, nop, bit, and, rol, rla, /* 2 */
|
||||
/* 3 */ bmi, and, nop, rla, nop, and, rol, rla, sec, and, nop, rla, nop, and, rol, rla, /* 3 */
|
||||
/* 4 */ rti, eor, nop, sre, nop, eor, lsr, sre, pha, eor, lsr, nop, jmp, eor, lsr, sre, /* 4 */
|
||||
/* 5 */ bvc, eor, nop, sre, nop, eor, lsr, sre, cli, eor, nop, sre, nop, eor, lsr, sre, /* 5 */
|
||||
/* 6 */ rts, adc, nop, rra, nop, adc, ror, rra, pla, adc, ror, nop, jmp, adc, ror, rra, /* 6 */
|
||||
/* 7 */ bvs, adc, nop, rra, nop, adc, ror, rra, sei, adc, nop, rra, nop, adc, ror, rra, /* 7 */
|
||||
/* 8 */ nop, sta, nop, sax, sty, sta, stx, sax, dey, nop, txa, nop, sty, sta, stx, sax, /* 8 */
|
||||
/* 9 */ bcc, sta, nop, nop, sty, sta, stx, sax, tya, sta, txs, nop, nop, sta, nop, nop, /* 9 */
|
||||
/* A */ ldy, lda, ldx, lax, ldy, lda, ldx, lax, tay, lda, tax, nop, ldy, lda, ldx, lax, /* A */
|
||||
/* B */ bcs, lda, nop, lax, ldy, lda, ldx, lax, clv, lda, tsx, lax, ldy, lda, ldx, lax, /* B */
|
||||
/* C */ cpy, cmp, nop, dcp, cpy, cmp, dec, dcp, iny, cmp, dex, nop, cpy, cmp, dec, dcp, /* C */
|
||||
/* D */ bne, cmp, nop, dcp, nop, cmp, dec, dcp, cld, cmp, nop, dcp, nop, cmp, dec, dcp, /* D */
|
||||
/* E */ cpx, sbc, nop, isb, cpx, sbc, inc, isb, inx, sbc, nop, sbc, cpx, sbc, inc, isb, /* E */
|
||||
/* F */ beq, sbc, nop, isb, nop, sbc, inc, isb, sed, sbc, nop, isb, nop, sbc, inc, isb /* F */
|
||||
/* 0 */ brk, ora, nop, nop, nop, ora, asl, nop, php, ora, asl, nop, nop, ora, asl, nop, /* 0 */
|
||||
/* 1 */ bpl, ora, nop, nop, nop, ora, asl, nop, clc, ora, nop, nop, nop, ora, asl, nop, /* 1 */
|
||||
/* 2 */ jsr, and, nop, nop, bit, and, rol, nop, plp, and, rol, nop, bit, and, rol, nop, /* 2 */
|
||||
/* 3 */ bmi, and, nop, nop, nop, and, rol, nop, sec, and, nop, nop, nop, and, rol, nop, /* 3 */
|
||||
/* 4 */ rti, eor, nop, nop, nop, eor, lsr, nop, pha, eor, lsr, nop, jmp, eor, lsr, nop, /* 4 */
|
||||
/* 5 */ bvc, eor, nop, nop, nop, eor, lsr, nop, cli, eor, nop, nop, nop, eor, lsr, nop, /* 5 */
|
||||
/* 6 */ rts, adc, nop, nop, nop, adc, ror, nop, pla, adc, ror, nop, jmp, adc, ror, nop, /* 6 */
|
||||
/* 7 */ bvs, adc, nop, nop, nop, adc, ror, nop, sei, adc, nop, nop, nop, adc, ror, nop, /* 7 */
|
||||
/* 8 */ nop, sta, nop, nop, sty, sta, stx, nop, dey, nop, txa, nop, sty, sta, stx, nop, /* 8 */
|
||||
/* 9 */ bcc, sta, nop, nop, sty, sta, stx, nop, tya, sta, txs, nop, nop, sta, nop, nop, /* 9 */
|
||||
/* A */ ldy, lda, ldx, nop, ldy, lda, ldx, nop, tay, lda, tax, nop, ldy, lda, ldx, nop, /* A */
|
||||
/* B */ bcs, lda, nop, nop, ldy, lda, ldx, nop, clv, lda, tsx, nop, ldy, lda, ldx, nop, /* B */
|
||||
/* C */ cpy, cmp, nop, nop, cpy, cmp, dec, nop, iny, cmp, dex, nop, cpy, cmp, dec, nop, /* C */
|
||||
/* D */ bne, cmp, nop, nop, nop, cmp, dec, nop, cld, cmp, nop, nop, nop, cmp, dec, nop, /* D */
|
||||
/* E */ cpx, sbc, nop, nop, cpx, sbc, inc, nop, inx, sbc, nop, sbc, cpx, sbc, inc, nop, /* E */
|
||||
/* F */ beq, sbc, nop, nop, nop, sbc, inc, nop, sed, sbc, nop, nop, nop, sbc, inc, nop /* F */
|
||||
};
|
||||
|
||||
static const uint32_t ticktable[256] = {
|
||||
@ -835,8 +741,6 @@ void exec6502(uint32_t tickcount) {
|
||||
clockticks6502 += ticktable[opcode];
|
||||
if (penaltyop && penaltyaddr) clockticks6502++;
|
||||
|
||||
instructions++;
|
||||
|
||||
if (callexternal) (*loopexternal)();
|
||||
}
|
||||
|
||||
@ -854,8 +758,6 @@ void step6502() {
|
||||
if (penaltyop && penaltyaddr) clockticks6502++;
|
||||
clockgoal6502 = clockticks6502;
|
||||
|
||||
instructions++;
|
||||
|
||||
if (callexternal) (*loopexternal)();
|
||||
}
|
||||
|
||||
@ -864,4 +766,4 @@ void hookexternal(void *funcptr) {
|
||||
loopexternal = funcptr;
|
||||
callexternal = 1;
|
||||
} else callexternal = 0;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user