CPU fixes - notably ADC/SBC in Decimal mode with invalid BCD values

This commit is contained in:
Jorj Bauer 2018-06-15 23:51:42 -04:00
parent fbb9c85468
commit aa45e49f40
1 changed files with 76 additions and 45 deletions

121
cpu.cpp
View File

@ -741,7 +741,7 @@ uint8_t Cpu::step()
break; break;
case O_TAX: case O_TAX:
x = a; x = a;
SETNZA; SETNZX;
break; break;
case O_BPL: case O_BPL:
if (!(flags & F_N)) { if (!(flags & F_N)) {
@ -977,64 +977,95 @@ uint8_t Cpu::step()
break; break;
case O_SBC: case O_SBC:
{ {
uint8_t memTemp = readmem(param) ^ 0xFF; uint8_t B = readmem(param) ^ 0xFF;
uint8_t Cin = (flags & F_C);
uint8_t Cout, Vout;
int16_t Aout;
int16_t c; if ((flags & F_D) == 0) {
uint8_t v; // Binary mode: same as ADC
if (flags & F_D) { Aout = a + B + Cin;
cyclesThisStep++; Vout = (a ^ Aout) & (B ^ Aout) & 0x80;
c = (a & 0x0F) + (memTemp & 0x0F) + (flags & F_C); Cout = (Aout >= 0x100) ? 1 : 0;
if (c < 0x10) a = Aout & 0xFF;
c = (c - 0x06) & 0x0f;
c += (a & 0xf0) + (memTemp & 0xf0);
v = (c >> 1) ^ c;
if (c < 0x100)
c = (c + 0xa0) & 0xff;
} else { } else {
c = a + memTemp + (flags & F_C); // Decimal mode
v = (c ^ a) & 0x80; cyclesThisStep++;
Aout = (a & 0x0F) + (B & 0x0F) + Cin;
if (Aout < 0x10) {
Aout = (Aout - 0x06) & 0x0F;
}
Aout = Aout + (a & 0xF0) + (B & 0xF0);
Vout = (a ^ Aout) & (B ^ Aout) & 0x80;
if (Aout < 0x100) {
Aout = (Aout + 0xa0) & 0xFF;
}
Cout = (Aout >= 0x100) ? 1 : 0;
B = readmem(param);
int8_t AL = (a & 0x0F) - (B & 0x0F) + (Cin - 1);
Aout = a - B + Cin - 1;
if (Aout < 0) {
Aout = Aout - 0x60;
}
if (AL < 0) {
Aout = Aout - 0x06;
}
a = Aout & 0xFF;
} }
if (((a ^ memTemp) & 0x80) != 0) { FLAG(F_C, Cout);
v = 0; FLAG(F_V, Vout);
}
FLAG(F_C, c > 0xFF);
FLAG(F_V, v);
a = c & 0xFF;
SETNZA; SETNZA;
} }
break; break;
case O_ADC: case O_ADC:
{ {
uint8_t memTemp = readmem(param); uint8_t B = readmem(param);
uint8_t Cin = (flags & F_C);
uint8_t Cout, Vout;
uint16_t Aout;
int16_t c; if ((flags & F_D) == 0x00) {
uint8_t v; // Simple binary mode
if (flags & F_D) { Aout = a + B + Cin;
cyclesThisStep++; Vout = (a ^ Aout) & (B ^ Aout) & 0x80;
c = (a & 0x0F) + (memTemp & 0x0F) + (flags & F_C); Cout = (Aout >= 0x100) ? 1 : 0;
if (c > 0x09) a = Aout & 0xFF;
c = (c - 0x0a) | 0x10;
c += (a & 0xf0) + (memTemp & 0xf0);
v = (c >> 1) ^ c;
if (c > 0x99)
c += 0x60;
} else { } else {
c = a + memTemp + (flags & F_C); // Decimal mode
v = (c ^ a) & 0x80; cyclesThisStep++;
Aout = (a & 0x0F) + (B & 0x0F) + Cin;
int tmpOverflow = 0;
if (Aout >= 0x0A) {
tmpOverflow = 0x10;
Aout = (Aout + 0x06) & 0x0F;
}
Aout = Aout | (a & 0xF0);
Aout = Aout + (B & 0xF0) + tmpOverflow;
Vout = 0;
if ( ((a ^ B) & 0x80) == 0) {
if (((a ^ Aout) & 0x80)) {
Vout = 1;
}
}
if (Aout >= 0xA0) {
Aout = Aout + 0x60;
Cout = 1;
} else {
Cout = 0;
}
a = Aout & 0xFF;
} }
if (((a ^ memTemp) & 0x80) != 0) { FLAG(F_C, Cout);
v = 0; FLAG(F_V, Vout);
}
FLAG(F_C, c > 0xFF);
FLAG(F_V, v);
a = c & 0xFF;
SETNZA; SETNZA;
} }
break; break;