Branch tests and misc tweaks

This commit is contained in:
Aaron Culliney 2014-02-22 14:28:01 -08:00
parent d481d59851
commit 442915b9cb

View File

@ -22,7 +22,8 @@
#define fV V_Flag_6502 // o[V]erflow
#define fN N_Flag_6502 // [N]egative
#define TEST_LOC 0x1f00
#define TEST_LOC 0x1f82
#define TEST_LOC_LO 0x82
#define RW_NONE 0x0
#define RW_READ 0x1
@ -1080,7 +1081,6 @@ TEST test_ASL_abs_x(uint8_t regA, uint8_t val, uint8_t regX, uint8_t lobyte, uin
uint16_t addrs = lobyte | (hibyte<<8);
addrs = addrs + regX;
if ((uint8_t)((addrs>>8)&0xff) != (uint8_t)hibyte) {
fprintf(stderr, "CROSS PG BOUNDARY\n");
++cycle_count;
}
apple_ii_64k[0][addrs] = val;
@ -1112,6 +1112,417 @@ TEST test_ASL_abs_x(uint8_t regA, uint8_t val, uint8_t regX, uint8_t lobyte, uin
PASS();
}
// ----------------------------------------------------------------------------
// Branch instructions
TEST test_BCC(int8_t off, bool flag, uint16_t addrs) {
HEADER0();
cpu65_current.pc = addrs;
flags |= flag ? fC : 0;
uint8_t cycle_count = 2;
uint16_t newpc = 0xffff;
if (flag) {
newpc = addrs+2;
} else {
newpc = addrs+2+off;
++cycle_count;
if ((newpc&0xFF00) != (addrs&0xFF00)) {
++cycle_count;
}
}
apple_ii_64k[0][addrs+0] = 0x90;
apple_ii_64k[0][addrs+1] = off;
apple_ii_64k[0][addrs+2] = (uint8_t)random();
cpu65_current.a = 0xed;
cpu65_current.x = 0xde;
cpu65_current.y = 0x05;
cpu65_current.sp = 0x81;
cpu65_current.f = flags;
cpu65_run();
ASSERT(cpu65_current.pc == newpc);
ASSERT(cpu65_current.a == 0xed);
ASSERT(cpu65_current.x == 0xde);
ASSERT(cpu65_current.y == 0x05);
ASSERT(cpu65_current.sp == 0x81);
ASSERT(cpu65_current.f == flags);
ASSERT(cpu65_debug.ea == addrs+1);
ASSERT(cpu65_debug.d == 0xff);
ASSERT(cpu65_debug.rw == 0);
ASSERT(cpu65_debug.opcode == 0x90);
ASSERT(cpu65_debug.opcycles == cycle_count);
PASS();
}
TEST test_BCS(int8_t off, bool flag, uint16_t addrs) {
HEADER0();
cpu65_current.pc = addrs;
flags |= flag ? fC : 0;
uint8_t cycle_count = 2;
uint16_t newpc = 0xffff;
if (!flag) {
newpc = addrs+2;
} else {
newpc = addrs+2+off;
++cycle_count;
if ((newpc&0xFF00) != (addrs&0xFF00)) {
++cycle_count;
}
}
apple_ii_64k[0][addrs+0] = 0xB0;
apple_ii_64k[0][addrs+1] = off;
apple_ii_64k[0][addrs+2] = (uint8_t)random();
cpu65_current.a = 0xed;
cpu65_current.x = 0xde;
cpu65_current.y = 0x05;
cpu65_current.sp = 0x81;
cpu65_current.f = flags;
cpu65_run();
ASSERT(cpu65_current.pc == newpc);
ASSERT(cpu65_current.a == 0xed);
ASSERT(cpu65_current.x == 0xde);
ASSERT(cpu65_current.y == 0x05);
ASSERT(cpu65_current.sp == 0x81);
ASSERT(cpu65_current.f == flags);
ASSERT(cpu65_debug.ea == addrs+1);
ASSERT(cpu65_debug.d == 0xff);
ASSERT(cpu65_debug.rw == 0);
ASSERT(cpu65_debug.opcode == 0xB0);
ASSERT(cpu65_debug.opcycles == cycle_count);
PASS();
}
TEST test_BEQ(int8_t off, bool flag, uint16_t addrs) {
HEADER0();
cpu65_current.pc = addrs;
flags |= flag ? fZ : 0;
uint8_t cycle_count = 2;
uint16_t newpc = 0xffff;
if (!flag) {
newpc = addrs+2;
} else {
newpc = addrs+2+off;
++cycle_count;
if ((newpc&0xFF00) != (addrs&0xFF00)) {
++cycle_count;
}
}
apple_ii_64k[0][addrs+0] = 0xF0;
apple_ii_64k[0][addrs+1] = off;
apple_ii_64k[0][addrs+2] = (uint8_t)random();
cpu65_current.a = 0xed;
cpu65_current.x = 0xde;
cpu65_current.y = 0x05;
cpu65_current.sp = 0x81;
cpu65_current.f = flags;
cpu65_run();
ASSERT(cpu65_current.pc == newpc);
ASSERT(cpu65_current.a == 0xed);
ASSERT(cpu65_current.x == 0xde);
ASSERT(cpu65_current.y == 0x05);
ASSERT(cpu65_current.sp == 0x81);
ASSERT(cpu65_current.f == flags);
ASSERT(cpu65_debug.ea == addrs+1);
ASSERT(cpu65_debug.d == 0xff);
ASSERT(cpu65_debug.rw == 0);
ASSERT(cpu65_debug.opcode == 0xF0);
ASSERT(cpu65_debug.opcycles == cycle_count);
PASS();
}
TEST test_BNE(int8_t off, bool flag, uint16_t addrs) {
HEADER0();
cpu65_current.pc = addrs;
flags |= flag ? fZ : 0;
uint8_t cycle_count = 2;
uint16_t newpc = 0xffff;
if (flag) {
newpc = addrs+2;
} else {
newpc = addrs+2+off;
++cycle_count;
if ((newpc&0xFF00) != (addrs&0xFF00)) {
++cycle_count;
}
}
apple_ii_64k[0][addrs+0] = 0xD0;
apple_ii_64k[0][addrs+1] = off;
apple_ii_64k[0][addrs+2] = (uint8_t)random();
cpu65_current.a = 0xed;
cpu65_current.x = 0xde;
cpu65_current.y = 0x05;
cpu65_current.sp = 0x81;
cpu65_current.f = flags;
cpu65_run();
ASSERT(cpu65_current.pc == newpc);
ASSERT(cpu65_current.a == 0xed);
ASSERT(cpu65_current.x == 0xde);
ASSERT(cpu65_current.y == 0x05);
ASSERT(cpu65_current.sp == 0x81);
ASSERT(cpu65_current.f == flags);
ASSERT(cpu65_debug.ea == addrs+1);
ASSERT(cpu65_debug.d == 0xff);
ASSERT(cpu65_debug.rw == 0);
ASSERT(cpu65_debug.opcode == 0xD0);
ASSERT(cpu65_debug.opcycles == cycle_count);
PASS();
}
TEST test_BMI(int8_t off, bool flag, uint16_t addrs) {
HEADER0();
cpu65_current.pc = addrs;
flags |= flag ? fN : 0;
uint8_t cycle_count = 2;
uint16_t newpc = 0xffff;
if (!flag) {
newpc = addrs+2;
} else {
newpc = addrs+2+off;
++cycle_count;
if ((newpc&0xFF00) != (addrs&0xFF00)) {
++cycle_count;
}
}
apple_ii_64k[0][addrs+0] = 0x30;
apple_ii_64k[0][addrs+1] = off;
apple_ii_64k[0][addrs+2] = (uint8_t)random();
cpu65_current.a = 0xed;
cpu65_current.x = 0xde;
cpu65_current.y = 0x05;
cpu65_current.sp = 0x81;
cpu65_current.f = flags;
cpu65_run();
ASSERT(cpu65_current.pc == newpc);
ASSERT(cpu65_current.a == 0xed);
ASSERT(cpu65_current.x == 0xde);
ASSERT(cpu65_current.y == 0x05);
ASSERT(cpu65_current.sp == 0x81);
ASSERT(cpu65_current.f == flags);
ASSERT(cpu65_debug.ea == addrs+1);
ASSERT(cpu65_debug.d == 0xff);
ASSERT(cpu65_debug.rw == 0);
ASSERT(cpu65_debug.opcode == 0x30);
ASSERT(cpu65_debug.opcycles == cycle_count);
PASS();
}
TEST test_BPL(int8_t off, bool flag, uint16_t addrs) {
HEADER0();
cpu65_current.pc = addrs;
flags |= flag ? fN : 0;
uint8_t cycle_count = 2;
uint16_t newpc = 0xffff;
if (flag) {
newpc = addrs+2;
} else {
newpc = addrs+2+off;
++cycle_count;
if ((newpc&0xFF00) != (addrs&0xFF00)) {
++cycle_count;
}
}
apple_ii_64k[0][addrs+0] = 0x10;
apple_ii_64k[0][addrs+1] = off;
apple_ii_64k[0][addrs+2] = (uint8_t)random();
cpu65_current.a = 0xed;
cpu65_current.x = 0xde;
cpu65_current.y = 0x05;
cpu65_current.sp = 0x81;
cpu65_current.f = flags;
cpu65_run();
ASSERT(cpu65_current.pc == newpc);
ASSERT(cpu65_current.a == 0xed);
ASSERT(cpu65_current.x == 0xde);
ASSERT(cpu65_current.y == 0x05);
ASSERT(cpu65_current.sp == 0x81);
ASSERT(cpu65_current.f == flags);
ASSERT(cpu65_debug.ea == addrs+1);
ASSERT(cpu65_debug.d == 0xff);
ASSERT(cpu65_debug.rw == 0);
ASSERT(cpu65_debug.opcode == 0x10);
ASSERT(cpu65_debug.opcycles == cycle_count);
PASS();
}
TEST test_BRA(int8_t off, bool flag, uint16_t addrs) {
HEADER0();
cpu65_current.pc = addrs;
flags |= flag ? fN : 0;
uint8_t cycle_count = 3;
uint16_t newpc = addrs+2+off;
if ((newpc&0xFF00) != (addrs&0xFF00)) {
++cycle_count;
}
apple_ii_64k[0][addrs+0] = 0x80;
apple_ii_64k[0][addrs+1] = off;
apple_ii_64k[0][addrs+2] = (uint8_t)random();
cpu65_current.a = 0xed;
cpu65_current.x = 0xde;
cpu65_current.y = 0x05;
cpu65_current.sp = 0x81;
cpu65_current.f = flags;
cpu65_run();
ASSERT(cpu65_current.pc == newpc);
ASSERT(cpu65_current.a == 0xed);
ASSERT(cpu65_current.x == 0xde);
ASSERT(cpu65_current.y == 0x05);
ASSERT(cpu65_current.sp == 0x81);
ASSERT(cpu65_current.f == flags);
ASSERT(cpu65_debug.ea == addrs+1);
ASSERT(cpu65_debug.d == 0xff);
ASSERT(cpu65_debug.rw == 0);
ASSERT(cpu65_debug.opcode == 0x80);
ASSERT(cpu65_debug.opcycles == cycle_count);
PASS();
}
TEST test_BVC(int8_t off, bool flag, uint16_t addrs) {
HEADER0();
cpu65_current.pc = addrs;
flags |= flag ? fV : 0;
uint8_t cycle_count = 2;
uint16_t newpc = 0xffff;
if (flag) {
newpc = addrs+2;
} else {
newpc = addrs+2+off;
++cycle_count;
if ((newpc&0xFF00) != (addrs&0xFF00)) {
++cycle_count;
}
}
apple_ii_64k[0][addrs+0] = 0x50;
apple_ii_64k[0][addrs+1] = off;
apple_ii_64k[0][addrs+2] = (uint8_t)random();
cpu65_current.a = 0xed;
cpu65_current.x = 0xde;
cpu65_current.y = 0x05;
cpu65_current.sp = 0x81;
cpu65_current.f = flags;
cpu65_run();
ASSERT(cpu65_current.pc == newpc);
ASSERT(cpu65_current.a == 0xed);
ASSERT(cpu65_current.x == 0xde);
ASSERT(cpu65_current.y == 0x05);
ASSERT(cpu65_current.sp == 0x81);
ASSERT(cpu65_current.f == flags);
ASSERT(cpu65_debug.ea == addrs+1);
ASSERT(cpu65_debug.d == 0xff);
ASSERT(cpu65_debug.rw == 0);
ASSERT(cpu65_debug.opcode == 0x50);
ASSERT(cpu65_debug.opcycles == cycle_count);
PASS();
}
TEST test_BVS(int8_t off, bool flag, uint16_t addrs) {
HEADER0();
cpu65_current.pc = addrs;
flags |= flag ? fV : 0;
uint8_t cycle_count = 2;
uint16_t newpc = 0xffff;
if (!flag) {
newpc = addrs+2;
} else {
newpc = addrs+2+off;
++cycle_count;
if ((newpc&0xFF00) != (addrs&0xFF00)) {
++cycle_count;
}
}
apple_ii_64k[0][addrs+0] = 0x70;
apple_ii_64k[0][addrs+1] = off;
apple_ii_64k[0][addrs+2] = (uint8_t)random();
cpu65_current.a = 0xed;
cpu65_current.x = 0xde;
cpu65_current.y = 0x05;
cpu65_current.sp = 0x81;
cpu65_current.f = flags;
cpu65_run();
ASSERT(cpu65_current.pc == newpc);
ASSERT(cpu65_current.a == 0xed);
ASSERT(cpu65_current.x == 0xde);
ASSERT(cpu65_current.y == 0x05);
ASSERT(cpu65_current.sp == 0x81);
ASSERT(cpu65_current.f == flags);
ASSERT(cpu65_debug.ea == addrs+1);
ASSERT(cpu65_debug.d == 0xff);
ASSERT(cpu65_debug.rw == 0);
ASSERT(cpu65_debug.opcode == 0x70);
ASSERT(cpu65_debug.opcycles == cycle_count);
PASS();
}
// ----------------------------------------------------------------------------
// BRK operand (and IRQ handling)
@ -1119,7 +1530,7 @@ TEST test_BRK() {
testcpu_set_opcode1(0x00);
ASSERT(apple_ii_64k[0][0x1ff] != 0x1f);
ASSERT(apple_ii_64k[0][0x1fe] != 0x01);
ASSERT(apple_ii_64k[0][0x1fe] != TEST_LOC_LO+2);
cpu65_current.a = 0x02;
cpu65_current.x = 0x03;
@ -1135,7 +1546,7 @@ TEST test_BRK() {
ASSERT(cpu65_current.sp == 0xfc);
ASSERT(apple_ii_64k[0][0x1ff] == 0x1f);
ASSERT(apple_ii_64k[0][0x1fe] == 0x02);
ASSERT(apple_ii_64k[0][0x1fe] == TEST_LOC_LO+2);
ASSERT(apple_ii_64k[0][0x1fd] == cpu65_flags_encode[B_Flag|X_Flag]);
ASSERT(cpu65_debug.ea == 0xfffe);
@ -1149,7 +1560,7 @@ TEST test_BRK() {
TEST test_IRQ() {
// NOTE : not an opcode
SKIPm("unimplemented for now");
FAILm("unimplemented for now");
}
// ----------------------------------------------------------------------------
@ -1162,7 +1573,7 @@ TEST test_NOP() {
cpu65_current.x = 0x03;
cpu65_current.y = 0x04;
cpu65_current.sp = 0x80;
cpu65_current.f = 0x05;
cpu65_current.f = 0x55;
cpu65_run();
@ -1170,7 +1581,7 @@ TEST test_NOP() {
ASSERT(cpu65_current.a == 0x02);
ASSERT(cpu65_current.x == 0x03);
ASSERT(cpu65_current.y == 0x04);
ASSERT(cpu65_current.f == 0x05);
ASSERT(cpu65_current.f == 0x55);
ASSERT(cpu65_current.sp == 0x80);
ASSERT(cpu65_debug.ea == TEST_LOC);
@ -1682,6 +2093,38 @@ GREATEST_SUITE(test_suite_cpu) {
A2_REMOVE_TEST(func);
}
// ------------------------------------------------------------------------
// Branch tests :
// NOTE : these should be a comprehensive exercise of the branching logic
greatest_info.flags = GREATEST_FLAG_SILENT_SUCCESS;
A2_ADD_TEST(test_BCC);
A2_ADD_TEST(test_BCS);
A2_ADD_TEST(test_BEQ);
A2_ADD_TEST(test_BNE);
A2_ADD_TEST(test_BMI);
A2_ADD_TEST(test_BPL);
A2_ADD_TEST(test_BRA);
A2_ADD_TEST(test_BVC);
A2_ADD_TEST(test_BVS);
HASH_ITER(hh, test_funcs, func, tmp) {
fprintf(GREATEST_STDOUT, "\n%s (SILENCED OUTPUT) :\n", func->name);
// test comprehensive logic in immediate mode (since no addressing to test) ...
for (uint16_t addrs = 0x1f02; addrs < 0x2000; addrs+=0x80) {
for (uint8_t flag = 0x00; flag < 0x02; flag++) {
uint8_t off=0x00;
do {
A2_RUN_TESTp( func->func, off, flag, addrs);
} while (++off);
}
}
fprintf(GREATEST_STDOUT, "...OK\n");
A2_REMOVE_TEST(func);
}
greatest_info.flags = 0x0;
// ------------------------------------------------------------------------
// Immediate addressing mode tests :
// NOTE : these should be a comprehensive exercise of the instruction logic